Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy...
authorLinus Torvalds <torvalds@woody.osdl.org>
Tue, 12 Dec 2006 15:45:48 +0000 (07:45 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Tue, 12 Dec 2006 15:45:48 +0000 (07:45 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6:
  JFS: Fix conflicting superblock flags

3221 files changed:
CREDITS
Documentation/ABI/testing/debugfs-pktcdvd [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class-pktcdvd [new file with mode: 0644]
Documentation/CodingStyle
Documentation/DMA-API.txt
Documentation/DocBook/Makefile
Documentation/DocBook/kernel-api.tmpl
Documentation/IPMI.txt
Documentation/SubmitChecklist
Documentation/accounting/getdelays.c
Documentation/block/as-iosched.txt
Documentation/cdrom/packet-writing.txt
Documentation/devices.txt
Documentation/dvb/cards.txt
Documentation/fault-injection/failcmd.sh [new file with mode: 0644]
Documentation/fault-injection/failmodule.sh [new file with mode: 0644]
Documentation/fault-injection/fault-injection.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/Locking
Documentation/filesystems/fuse.txt
Documentation/filesystems/sysv-fs.txt
Documentation/i386/boot.txt
Documentation/ioctl-number.txt
Documentation/ioctl/ioctl-decoding.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/networking/00-INDEX
Documentation/networking/dccp.txt
Documentation/networking/generic_netlink.txt [new file with mode: 0644]
Documentation/power/s2ram.txt [new file with mode: 0644]
Documentation/power/swsusp-and-swap-files.txt [new file with mode: 0644]
Documentation/power/swsusp.txt
Documentation/power/userland-swsusp.txt
Documentation/s390/driver-model.txt
Documentation/spi/pxa2xx
Documentation/stable_api_nonsense.txt
Documentation/sysctl/kernel.txt
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/cafe_ccic [new file with mode: 0644]
Documentation/video4linux/zr36120.txt [deleted file]
Documentation/x86_64/boot-options.txt
MAINTAINERS
Makefile
README
REPORTING-BUGS
arch/alpha/Kconfig
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/mm/fault.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/common/gic.c
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/common/sharpsl_pm.c
arch/arm/common/vic.c
arch/arm/configs/at91rm9200dk_defconfig
arch/arm/configs/at91rm9200ek_defconfig
arch/arm/configs/at91sam9260ek_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9261ek_defconfig [new file with mode: 0644]
arch/arm/configs/badge4_defconfig
arch/arm/configs/carmeva_defconfig
arch/arm/configs/cerfcube_defconfig
arch/arm/configs/collie_defconfig
arch/arm/configs/corgi_defconfig
arch/arm/configs/csb337_defconfig
arch/arm/configs/csb637_defconfig
arch/arm/configs/ep93xx_defconfig
arch/arm/configs/h7202_defconfig
arch/arm/configs/hackkit_defconfig
arch/arm/configs/integrator_defconfig
arch/arm/configs/iop13xx_defconfig [new file with mode: 0644]
arch/arm/configs/iop32x_defconfig
arch/arm/configs/iop33x_defconfig
arch/arm/configs/ixp2000_defconfig
arch/arm/configs/ixp23xx_defconfig
arch/arm/configs/ixp4xx_defconfig
arch/arm/configs/jornada720_defconfig
arch/arm/configs/kb9202_defconfig
arch/arm/configs/lpd270_defconfig
arch/arm/configs/lpd7a400_defconfig
arch/arm/configs/lpd7a404_defconfig
arch/arm/configs/lubbock_defconfig
arch/arm/configs/mainstone_defconfig
arch/arm/configs/mx1ads_defconfig
arch/arm/configs/neponset_defconfig
arch/arm/configs/netwinder_defconfig
arch/arm/configs/netx_defconfig
arch/arm/configs/onearm_defconfig
arch/arm/configs/pleb_defconfig
arch/arm/configs/pnx4008_defconfig
arch/arm/configs/pxa255-idp_defconfig
arch/arm/configs/realview-smp_defconfig
arch/arm/configs/realview_defconfig
arch/arm/configs/rpc_defconfig
arch/arm/configs/s3c2410_defconfig
arch/arm/configs/shark_defconfig
arch/arm/configs/simpad_defconfig
arch/arm/configs/spitz_defconfig
arch/arm/configs/versatile_defconfig
arch/arm/kernel/Makefile
arch/arm/kernel/apm.c
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/ecard.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/irq.c
arch/arm/kernel/iwmmxt-notifier.c [deleted file]
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/traps.c
arch/arm/kernel/xscale-cp0.c [new file with mode: 0644]
arch/arm/mach-aaec2000/core.c
arch/arm/mach-at91rm9200/Kconfig
arch/arm/mach-at91rm9200/Makefile
arch/arm/mach-at91rm9200/at91rm9200.c
arch/arm/mach-at91rm9200/at91rm9200_devices.c [moved from arch/arm/mach-at91rm9200/devices.c with 83% similarity]
arch/arm/mach-at91rm9200/at91rm9200_time.c
arch/arm/mach-at91rm9200/at91sam9260.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91sam9260_devices.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91sam9261.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91sam9261_devices.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91sam926x_time.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-carmeva.c
arch/arm/mach-at91rm9200/board-csb337.c
arch/arm/mach-at91rm9200/board-dk.c
arch/arm/mach-at91rm9200/board-eb9200.c
arch/arm/mach-at91rm9200/board-ek.c
arch/arm/mach-at91rm9200/board-kb9202.c
arch/arm/mach-at91rm9200/board-sam9260ek.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-sam9261ek.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/clock.c
arch/arm/mach-at91rm9200/clock.h
arch/arm/mach-at91rm9200/generic.h
arch/arm/mach-at91rm9200/gpio.c
arch/arm/mach-at91rm9200/irq.c
arch/arm/mach-at91rm9200/pm.c
arch/arm/mach-clps711x/irq.c
arch/arm/mach-clps7500/core.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/Makefile
arch/arm/mach-ep93xx/adssphere.c [new file with mode: 0644]
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb9302a.c [new file with mode: 0644]
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/isa-irq.c
arch/arm/mach-h720x/common.c
arch/arm/mach-h720x/cpu-h7202.c
arch/arm/mach-imx/generic.c
arch/arm/mach-imx/irq.c
arch/arm/mach-imx/time.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-integrator/platsmp.c
arch/arm/mach-iop13xx/Kconfig [new file with mode: 0644]
arch/arm/mach-iop13xx/Makefile [new file with mode: 0644]
arch/arm/mach-iop13xx/Makefile.boot [new file with mode: 0644]
arch/arm/mach-iop13xx/io.c [new file with mode: 0644]
arch/arm/mach-iop13xx/iq81340mc.c [new file with mode: 0644]
arch/arm/mach-iop13xx/iq81340sc.c [new file with mode: 0644]
arch/arm/mach-iop13xx/irq.c [new file with mode: 0644]
arch/arm/mach-iop13xx/pci.c [new file with mode: 0644]
arch/arm/mach-iop13xx/setup.c [new file with mode: 0644]
arch/arm/mach-iop13xx/time.c [new file with mode: 0644]
arch/arm/mach-iop32x/irq.c
arch/arm/mach-iop33x/irq.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/ixdp2x00.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp2000/pci.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-l7200/core.c
arch/arm/mach-lh7a40x/arch-kev7a400.c
arch/arm/mach-lh7a40x/arch-lpd7a40x.c
arch/arm/mach-lh7a40x/irq-kev7a400.c
arch/arm/mach-lh7a40x/irq-lh7a400.c
arch/arm/mach-lh7a40x/irq-lh7a404.c
arch/arm/mach-lh7a40x/irq-lpd7a40x.c
arch/arm/mach-netx/generic.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/fpga.c
arch/arm/mach-omap1/irq.c
arch/arm/mach-omap1/leds-osk.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-pnx4008/irq.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/akita-ioexp.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/time.c
arch/arm/mach-rpc/irq.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/irq.h
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-osiris.c
arch/arm/mach-s3c2410/mach-rx3715.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/pm-h1940.S [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410-pm.c
arch/arm/mach-s3c2410/s3c2412-irq.c
arch/arm/mach-s3c2410/s3c2440-irq.c
arch/arm/mach-s3c2410/s3c244x-irq.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/irq.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/time.c
arch/arm/mach-shark/irq.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/versatile_pb.c
arch/arm/mm/Kconfig
arch/arm/mm/fault.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm6_7.S
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-arm740.S
arch/arm/mm/proc-arm7tdmi.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-arm9tdmi.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-omap/gpio.c
arch/arm/tools/mach-types
arch/arm26/Kconfig
arch/arm26/kernel/ecard.c
arch/arm26/mm/fault.c
arch/arm26/mm/memc.c
arch/avr32/Kconfig
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/kernel/avr32_ksyms.c
arch/avr32/kernel/kprobes.c
arch/avr32/kernel/process.c
arch/avr32/kernel/setup.c
arch/avr32/kernel/signal.c
arch/avr32/lib/delay.c
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/intc.c
arch/avr32/mach-at32ap/pio.c
arch/avr32/mach-at32ap/sm.c [deleted file]
arch/avr32/mm/dma-coherent.c
arch/cris/Kconfig
arch/cris/arch-v32/drivers/sync_serial.c
arch/cris/mm/fault.c
arch/frv/Kconfig
arch/frv/kernel/futex.c
arch/frv/kernel/pm.c
arch/frv/kernel/setup.c
arch/frv/kernel/signal.c
arch/frv/mm/elf-fdpic.c
arch/frv/mm/fault.c
arch/frv/mm/pgalloc.c
arch/h8300/Kconfig
arch/h8300/kernel/setup.c
arch/h8300/kernel/signal.c
arch/h8300/kernel/vmlinux.lds.S
arch/i386/Kconfig
arch/i386/Kconfig.cpu
arch/i386/Kconfig.debug
arch/i386/Makefile
arch/i386/Makefile.cpu
arch/i386/boot/compressed/Makefile
arch/i386/boot/compressed/head.S
arch/i386/boot/compressed/misc.c
arch/i386/boot/compressed/relocs.c [new file with mode: 0644]
arch/i386/boot/compressed/vmlinux.lds [new file with mode: 0644]
arch/i386/boot/compressed/vmlinux.scr
arch/i386/boot/setup.S
arch/i386/defconfig
arch/i386/kernel/Makefile
arch/i386/kernel/acpi/cstate.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/alternative.c
arch/i386/kernel/apic.c
arch/i386/kernel/apm.c
arch/i386/kernel/asm-offsets.c
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/common.c
arch/i386/kernel/cpu/intel.c
arch/i386/kernel/cpu/intel_cacheinfo.c
arch/i386/kernel/cpu/mcheck/non-fatal.c
arch/i386/kernel/cpu/mcheck/therm_throt.c
arch/i386/kernel/cpu/mtrr/Makefile
arch/i386/kernel/cpu/mtrr/amd.c
arch/i386/kernel/cpu/mtrr/centaur.c
arch/i386/kernel/cpu/mtrr/cyrix.c
arch/i386/kernel/cpu/mtrr/generic.c
arch/i386/kernel/cpu/mtrr/if.c
arch/i386/kernel/cpu/mtrr/main.c
arch/i386/kernel/cpu/mtrr/mtrr.h
arch/i386/kernel/cpu/proc.c
arch/i386/kernel/cpuid.c
arch/i386/kernel/crash.c
arch/i386/kernel/e820.c [new file with mode: 0644]
arch/i386/kernel/efi.c
arch/i386/kernel/entry.S
arch/i386/kernel/head.S
arch/i386/kernel/hpet.c
arch/i386/kernel/i8259.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/kprobes.c
arch/i386/kernel/ldt.c
arch/i386/kernel/mca.c
arch/i386/kernel/microcode.c
arch/i386/kernel/module.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/msr.c
arch/i386/kernel/nmi.c
arch/i386/kernel/paravirt.c [new file with mode: 0644]
arch/i386/kernel/pci-dma.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/quirks.c
arch/i386/kernel/reboot.c
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/sysenter.c
arch/i386/kernel/time.c
arch/i386/kernel/time_hpet.c
arch/i386/kernel/topology.c
arch/i386/kernel/traps.c
arch/i386/kernel/tsc.c
arch/i386/kernel/vm86.c
arch/i386/kernel/vmlinux.lds.S
arch/i386/mach-generic/probe.c
arch/i386/mach-visws/setup.c
arch/i386/mach-voyager/voyager_cat.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/math-emu/fpu_emu.h
arch/i386/math-emu/fpu_entry.c
arch/i386/math-emu/fpu_system.h
arch/i386/math-emu/load_store.c
arch/i386/math-emu/reg_ld_str.c
arch/i386/mm/boot_ioremap.c
arch/i386/mm/discontig.c
arch/i386/mm/fault.c
arch/i386/mm/highmem.c
arch/i386/mm/hugetlbpage.c
arch/i386/mm/init.c
arch/i386/mm/pageattr.c
arch/i386/mm/pgtable.c
arch/i386/pci/early.c
arch/i386/pci/irq.c
arch/i386/pci/pcbios.c
arch/i386/power/Makefile
arch/i386/power/cpu.c
arch/i386/power/suspend.c [new file with mode: 0644]
arch/i386/power/swsusp.S
arch/ia64/Kconfig
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/simserial.c
arch/ia64/ia32/binfmt_elf32.c
arch/ia64/ia32/ia32_support.c
arch/ia64/ia32/ia32priv.h
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/Makefile
arch/ia64/kernel/cpufreq/acpi-cpufreq.c
arch/ia64/kernel/crash.c [new file with mode: 0644]
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/machine_kexec.c [new file with mode: 0644]
arch/ia64/kernel/mca.c
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/perfmon_montecito.h
arch/ia64/kernel/relocate_kernel.S [new file with mode: 0644]
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/topology.c
arch/ia64/lib/ip_fast_csum.S
arch/ia64/mm/hugetlbpage.c
arch/ia64/mm/init.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/sn/kernel/setup.c
arch/m32r/Kconfig
arch/m32r/boot/compressed/m32r_sio.c
arch/m32r/kernel/entry.S
arch/m32r/kernel/io_opsput.c
arch/m32r/kernel/setup.c
arch/m32r/kernel/setup_opsput.c
arch/m32r/kernel/signal.c
arch/m32r/mm/discontig.c
arch/m32r/mm/fault.c
arch/m68k/Kconfig
arch/m68k/amiga/chipram.c
arch/m68k/atari/hades-pci.c
arch/m68k/atari/stdma.c
arch/m68k/kernel/sun3-head.S
arch/m68k/kernel/vmlinux-sun3.lds
arch/m68k/mm/fault.c
arch/m68k/mm/memory.c
arch/m68k/mm/sun3mmu.c
arch/m68knommu/Kconfig
arch/m68knommu/kernel/vmlinux.lds.S
arch/m68knommu/platform/5307/timers.c
arch/m68knommu/platform/68360/config.c
arch/mips/Kconfig
arch/mips/Makefile
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/jaguar-atx_defconfig
arch/mips/configs/jazz_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-stb810_defconfig [new file with mode: 0644]
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/dec/ecc-berr.c
arch/mips/dec/ioasic-irq.c
arch/mips/dec/kn01-berr.c
arch/mips/dec/kn02-irq.c
arch/mips/defconfig
arch/mips/emma2rh/common/irq_emma2rh.c
arch/mips/emma2rh/markeins/irq_markeins.c
arch/mips/jazz/irq.c
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/head.S
arch/mips/kernel/i8259.c
arch/mips/kernel/irixelf.c
arch/mips/kernel/irq-mv6434x.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/kspd.c
arch/mips/kernel/reset.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/sysirix.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kernel/vpe.c
arch/mips/lasat/interrupt.c
arch/mips/lasat/sysctl.c
arch/mips/lib/csum_partial.S
arch/mips/lib/csum_partial_copy.c
arch/mips/mips-boards/malta/Makefile
arch/mips/mips-boards/malta/malta_setup.c
arch/mips/mm/cache.c
arch/mips/mm/dma-coherent.c
arch/mips/mm/dma-ip27.c
arch/mips/mm/dma-ip32.c
arch/mips/mm/dma-noncoherent.c
arch/mips/mm/highmem.c
arch/mips/mm/init.c
arch/mips/mm/ioremap.c
arch/mips/momentum/ocelot_c/cpci-irq.c
arch/mips/momentum/ocelot_c/uart-irq.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-pnx8550.c
arch/mips/philips/pnx8550/common/int.c
arch/mips/philips/pnx8550/common/prom.c
arch/mips/philips/pnx8550/jbs/irqmap.c
arch/mips/philips/pnx8550/stb810/Makefile [new file with mode: 0644]
arch/mips/philips/pnx8550/stb810/board_setup.c [new file with mode: 0644]
arch/mips/philips/pnx8550/stb810/irqmap.c [new file with mode: 0644]
arch/mips/philips/pnx8550/stb810/prom_init.c [new file with mode: 0644]
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/tx4927/common/tx4927_irq.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
arch/mips/tx4938/common/irq.c
arch/mips/tx4938/toshiba_rbtx4938/irq.c
arch/mips/vr41xx/common/icu.c
arch/mips/vr41xx/nec-cmbvr4133/irq.c
arch/parisc/Kconfig
arch/parisc/hpux/sys_hpux.c
arch/parisc/kernel/binfmt_elf32.c
arch/parisc/mm/fault.c
arch/parisc/mm/ioremap.c
arch/powerpc/Kconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/module_32.c
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/of_device.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/proc_ppc64.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/52xx/lite5200.c
arch/powerpc/platforms/cell/cbe_thermal.c
arch/powerpc/platforms/cell/pmu.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/syscalls.c
arch/powerpc/platforms/embedded6xx/ls_uart.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/powermac/backlight.c
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/platforms/pseries/hotplug-cpu.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/hvCall_inst.c
arch/powerpc/platforms/pseries/scanlog.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/dcr.S [deleted file]
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/rom.c
arch/powerpc/xmon/xmon.c
arch/ppc/8260_io/fcc_enet.c
arch/ppc/8xx_io/cs4218_tdm.c
arch/ppc/8xx_io/fec.c
arch/ppc/Kconfig
arch/ppc/kernel/pci.c
arch/ppc/kernel/traps.c
arch/ppc/kernel/vmlinux.lds.S
arch/s390/Kconfig
arch/s390/appldata/appldata_base.c
arch/s390/defconfig
arch/s390/hypfs/inode.c
arch/s390/kernel/binfmt_elf32.c
arch/s390/kernel/debug.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/setup.c
arch/s390/lib/uaccess_pt.c
arch/s390/lib/uaccess_std.c
arch/s390/mm/Makefile
arch/s390/mm/extmem.c
arch/s390/mm/init.c
arch/s390/mm/ioremap.c
arch/s390/mm/vmem.c [new file with mode: 0644]
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/renesas/r7780rp/Makefile
arch/sh/boards/renesas/r7780rp/irq.c
arch/sh/boards/renesas/r7780rp/psw.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/setup.c
arch/sh/boards/se/7206/Makefile [new file with mode: 0644]
arch/sh/boards/se/7206/io.c [new file with mode: 0644]
arch/sh/boards/se/7206/irq.c [new file with mode: 0644]
arch/sh/boards/se/7206/led.c [new file with mode: 0644]
arch/sh/boards/se/7206/setup.c [new file with mode: 0644]
arch/sh/boards/se/7619/Makefile [new file with mode: 0644]
arch/sh/boards/se/7619/io.c [new file with mode: 0644]
arch/sh/boards/se/7619/setup.c [new file with mode: 0644]
arch/sh/boards/titan/setup.c
arch/sh/boot/compressed/misc.c
arch/sh/configs/r7780rp_defconfig
arch/sh/configs/se7206_defconfig [new file with mode: 0644]
arch/sh/drivers/Kconfig [new file with mode: 0644]
arch/sh/drivers/Makefile
arch/sh/drivers/dma/Makefile
arch/sh/drivers/dma/dma-api.c
arch/sh/drivers/dma/dma-sh.c
arch/sh/drivers/dma/dma-sysfs.c
arch/sh/drivers/pci/ops-titan.c
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/push-switch.c [new file with mode: 0644]
arch/sh/kernel/Makefile
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/imask.c
arch/sh/kernel/cpu/irq/intc2.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/sh2/Makefile
arch/sh/kernel/cpu/sh2/clock-sh7619.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2/entry.S [new file with mode: 0644]
arch/sh/kernel/cpu/sh2/ex.S [new file with mode: 0644]
arch/sh/kernel/cpu/sh2/probe.c
arch/sh/kernel/cpu/sh2/setup-sh7619.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/Makefile [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/clock-sh7206.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/probe.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/setup-sh7206.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/clock-sh7709.c
arch/sh/kernel/cpu/sh3/entry.S [moved from arch/sh/kernel/entry.S with 58% similarity]
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4/clock-sh7780.c
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7780.c
arch/sh/kernel/cpu/sh4/sq.c
arch/sh/kernel/early_printk.c
arch/sh/kernel/entry-common.S [new file with mode: 0644]
arch/sh/kernel/head.S
arch/sh/kernel/irq.c
arch/sh/kernel/process.c
arch/sh/kernel/relocate_kernel.S
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/stacktrace.c [new file with mode: 0644]
arch/sh/kernel/sys_sh.c
arch/sh/kernel/time.c
arch/sh/kernel/timers/Makefile
arch/sh/kernel/timers/timer-cmt.c [new file with mode: 0644]
arch/sh/kernel/timers/timer-mtu2.c [new file with mode: 0644]
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/timers/timer.c
arch/sh/kernel/traps.c
arch/sh/kernel/vsyscall/vsyscall.c
arch/sh/mm/Kconfig
arch/sh/mm/cache-sh2.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/clear_page.S
arch/sh/mm/copy_page.S
arch/sh/mm/fault.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh/mm/ioremap.c
arch/sh/mm/pg-dma.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pmb.c
arch/sh/oprofile/op_model_sh7750.c
arch/sh/tools/mach-types
arch/sh64/Kconfig
arch/sh64/kernel/setup.c
arch/sh64/kernel/signal.c
arch/sh64/mm/fault.c
arch/sh64/mm/hugetlbpage.c
arch/sh64/mm/ioremap.c
arch/sparc/Kconfig
arch/sparc/kernel/ioport.c
arch/sparc/kernel/of_device.c
arch/sparc/kernel/ptrace.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/kernel/sys_sunos.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/mm/highmem.c
arch/sparc/mm/io-unit.c
arch/sparc64/Kconfig
arch/sparc64/Kconfig.debug
arch/sparc64/defconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/binfmt_aout32.c
arch/sparc64/kernel/binfmt_elf32.c
arch/sparc64/kernel/chmc.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/head.S
arch/sparc64/kernel/isa.c
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/stacktrace.c [new file with mode: 0644]
arch/sparc64/kernel/sun4v_ivec.S
arch/sparc64/kernel/sys_sunos32.c
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/unaligned.c
arch/sparc64/kernel/visemul.c
arch/sparc64/kernel/vmlinux.lds.S
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/mm/init.c
arch/sparc64/mm/tsb.c
arch/sparc64/mm/ultra.S
arch/sparc64/solaris/fs.c
arch/sparc64/solaris/ioctl.c
arch/sparc64/solaris/misc.c
arch/sparc64/solaris/socksys.c
arch/sparc64/solaris/timod.c
arch/um/Kconfig
arch/um/drivers/chan_kern.c
arch/um/drivers/daemon_kern.c
arch/um/drivers/line.c
arch/um/drivers/mcast_kern.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/port_kern.c
arch/um/drivers/slip_kern.c
arch/um/drivers/slirp_kern.c
arch/um/include/chan_kern.h
arch/um/include/line.h
arch/um/include/sysdep-i386/ptrace.h
arch/um/include/sysdep-i386/stub.h
arch/um/include/sysdep-x86_64/ptrace.h
arch/um/kernel/exec.c
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/sys-i386/Makefile
arch/um/sys-i386/bug.c [new file with mode: 0644]
arch/um/sys-i386/ldt.c
arch/um/sys-i386/ptrace_user.c
arch/um/sys-i386/user-offsets.c
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/bug.c [new file with mode: 0644]
arch/v850/Kconfig
arch/v850/kernel/vmlinux.lds.S
arch/x86_64/Kconfig
arch/x86_64/Makefile
arch/x86_64/defconfig
arch/x86_64/ia32/ia32_aout.c
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/ia32/ia32_signal.c
arch/x86_64/ia32/syscall32.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/crash.c
arch/x86_64/kernel/early-quirks.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/genapic.c
arch/x86_64/kernel/head64.c
arch/x86_64/kernel/i387.c
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/irq.c
arch/x86_64/kernel/kprobes.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mce_amd.c
arch/x86_64/kernel/module.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/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsyscall.c
arch/x86_64/lib/csum-partial.c
arch/x86_64/lib/delay.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/pageattr.c
arch/xtensa/Kconfig
arch/xtensa/Makefile
arch/xtensa/boot/boot-elf/bootstrap.S
arch/xtensa/boot/boot-redboot/bootstrap.S
arch/xtensa/configs/iss_defconfig
arch/xtensa/kernel/align.S
arch/xtensa/kernel/asm-offsets.c
arch/xtensa/kernel/coprocessor.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/head.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/pci-dma.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/syscall.c [new file with mode: 0644]
arch/xtensa/kernel/syscalls.c [deleted file]
arch/xtensa/kernel/syscalls.h [deleted file]
arch/xtensa/kernel/time.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/lib/checksum.S
arch/xtensa/lib/memcopy.S
arch/xtensa/lib/memset.S
arch/xtensa/lib/strncpy_user.S
arch/xtensa/lib/strnlen_user.S
arch/xtensa/lib/usercopy.S
arch/xtensa/mm/fault.c
arch/xtensa/mm/init.c
arch/xtensa/mm/misc.S
arch/xtensa/mm/tlb.c
arch/xtensa/platform-iss/console.c
arch/xtensa/platform-iss/network.c
block/as-iosched.c
block/blktrace.c
block/cfq-iosched.c
block/genhd.c
block/ioctl.c
block/ll_rw_blk.c
block/scsi_ioctl.c
crypto/Kconfig
crypto/Makefile
crypto/api.c
crypto/cryptomgr.c
crypto/digest.c
crypto/gf128mul.c [new file with mode: 0644]
crypto/lrw.c [new file with mode: 0644]
crypto/sha512.c
crypto/tcrypt.c
crypto/tcrypt.h
crypto/xcbc.c [new file with mode: 0644]
drivers/Kconfig
drivers/Makefile
drivers/acpi/osl.c
drivers/amba/bus.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/ata/sata_promise.c
drivers/atm/.gitignore
drivers/atm/Kconfig
drivers/atm/Makefile
drivers/atm/ambassador.c
drivers/atm/he.c
drivers/atm/idt77252.c
drivers/base/core.c
drivers/base/cpu.c
drivers/base/dmapool.c
drivers/base/memory.c
drivers/base/topology.c
drivers/block/DAC960.c
drivers/block/Kconfig
drivers/block/acsi_slm.c
drivers/block/aoe/aoe.h
drivers/block/aoe/aoeblk.c
drivers/block/aoe/aoecmd.c
drivers/block/aoe/aoedev.c
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/paride/aten.c
drivers/block/paride/bpck.c
drivers/block/paride/bpck6.c
drivers/block/paride/comm.c
drivers/block/paride/dstr.c
drivers/block/paride/epat.c
drivers/block/paride/epia.c
drivers/block/paride/fit2.c
drivers/block/paride/fit3.c
drivers/block/paride/friq.c
drivers/block/paride/frpw.c
drivers/block/paride/jumbo [deleted file]
drivers/block/paride/kbic.c
drivers/block/paride/ktti.c
drivers/block/paride/on20.c
drivers/block/paride/on26.c
drivers/block/paride/paride.c
drivers/block/paride/paride.h
drivers/block/paride/pcd.c
drivers/block/paride/pd.c
drivers/block/paride/pf.c
drivers/block/paride/pg.c
drivers/block/paride/pseudo.h
drivers/block/paride/pt.c
drivers/block/pktcdvd.c
drivers/block/sx8.c
drivers/block/ub.c
drivers/bluetooth/bcm203x.c
drivers/bluetooth/hci_bcsp.c
drivers/cdrom/optcd.c
drivers/cdrom/sbpcd.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/agp/amd64-agp.c
drivers/char/amiserial.c
drivers/char/cs5535_gpio.c
drivers/char/cyclades.c
drivers/char/decserial.c
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_bufs.c
drivers/char/drm/drm_core.h
drivers/char/drm/drm_drawable.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_ioc32.c
drivers/char/drm/drm_irq.c
drivers/char/drm/drm_lock.c
drivers/char/drm/drm_sman.c
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_vm.c
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drm.h
drivers/char/drm/i915_drv.c
drivers/char/drm/i915_drv.h
drivers/char/drm/i915_ioc32.c
drivers/char/drm/i915_irq.c
drivers/char/drm/mga_ioc32.c
drivers/char/drm/r128_ioc32.c
drivers/char/drm/radeon_ioc32.c
drivers/char/drm/via_dmablit.c
drivers/char/dsp56k.c
drivers/char/dtlk.c
drivers/char/epca.c
drivers/char/esp.c
drivers/char/generic_serial.c
drivers/char/genrtc.c
drivers/char/hvc_console.c
drivers/char/hvcs.c
drivers/char/hvsi.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/Makefile
drivers/char/ip2/i2cmd.h
drivers/char/ip2/i2lib.c
drivers/char/ip2/ip2main.c
drivers/char/ipmi/ipmi_bt_sm.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_kcs_sm.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_smic_sm.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/keyboard.c
drivers/char/lp.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/mmtimer.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/mxser_new.c [new file with mode: 0644]
drivers/char/mxser_new.h [new file with mode: 0644]
drivers/char/n_r3964.c
drivers/char/n_tty.c
drivers/char/nsc_gpio.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/ppdev.c
drivers/char/pty.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/rio/rio_linux.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/ser_a2232.c
drivers/char/serial167.c
drivers/char/sonypi.c
drivers/char/specialix.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/char/sx.h
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/sysrq.c
drivers/char/tb0219.c
drivers/char/tipar.c
drivers/char/toshiba.c
drivers/char/tpm/tpm.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vc_screen.c
drivers/char/viotape.c
drivers/char/vme_scc.c
drivers/char/vr41xx_giu.c
drivers/char/vt.c
drivers/char/watchdog/at91rm9200_wdt.c
drivers/char/watchdog/pcwd_usb.c
drivers/clocksource/acpi_pm.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/geode-aes.c [new file with mode: 0644]
drivers/crypto/geode-aes.h [new file with mode: 0644]
drivers/dma/ioatdma.c
drivers/edac/edac_mc.c
drivers/hid/Kconfig [new file with mode: 0644]
drivers/hid/Makefile [new file with mode: 0644]
drivers/hid/hid-core.c [new file with mode: 0644]
drivers/hid/hid-input.c [moved from drivers/usb/input/hid-input.c with 88% similarity]
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/chips/ds1374.c
drivers/i2c/chips/m41t00.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/ide-cd.c
drivers/ide/ide-probe.c
drivers/ide/ide.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/piix.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/via82cxxx.c
drivers/ide/setup-pci.c
drivers/ieee1394/Kconfig
drivers/ieee1394/Makefile
drivers/ieee1394/csr.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/pcilynx.c
drivers/ieee1394/raw1394-private.h
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_mem.c
drivers/infiniband/hw/amso1100/c2_vq.c
drivers/infiniband/hw/ehca/ehca_av.c
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_mrmw.c
drivers/infiniband/hw/ehca/ehca_pd.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_user_pages.c
drivers/infiniband/hw/mthca/mthca_av.c
drivers/infiniband/hw/mthca/mthca_catas.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_srq.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/Makefile
drivers/input/ff-core.c
drivers/input/ff-memless.c
drivers/input/gameport/gameport.c
drivers/input/gameport/lightning.c
drivers/input/input.c
drivers/input/joystick/adi.c
drivers/input/joystick/amijoy.c
drivers/input/joystick/analog.c
drivers/input/joystick/cobra.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip_mp.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/interact.c
drivers/input/joystick/magellan.c
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceorb.c
drivers/input/joystick/stinger.c
drivers/input/joystick/twidjoy.c
drivers/input/joystick/warrior.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/aaed2000_kbd.c [new file with mode: 0644]
drivers/input/keyboard/amikbd.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/locomokbd.c
drivers/input/keyboard/maple_keyb.c [deleted file]
drivers/input/keyboard/newtonkbd.c
drivers/input/keyboard/spitzkbd.c
drivers/input/keyboard/stowaway.c
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/xtkbd.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/mouse/amimouse.c
drivers/input/mouse/hil_ptr.c
drivers/input/mouse/inport.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/logibm.c
drivers/input/mouse/logips2pp.c
drivers/input/mouse/pc110pad.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/rpcmouse.c
drivers/input/mouse/sermouse.c
drivers/input/mouse/trackpoint.c
drivers/input/mouse/vsxxxaa.c
drivers/input/mousedev.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/serio/libps2.c
drivers/input/serio/serio.c
drivers/input/serio/serio_raw.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/corgi_ts.c
drivers/input/touchscreen/elo.c
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/h3600_ts_input.c
drivers/input/touchscreen/hp680_ts_input.c
drivers/input/touchscreen/mk712.c
drivers/input/touchscreen/mtouch.c
drivers/input/touchscreen/penmount.c
drivers/input/touchscreen/touchright.c
drivers/input/touchscreen/touchwin.c
drivers/input/touchscreen/ucb1400_ts.c [new file with mode: 0644]
drivers/isdn/act2000/capi.c
drivers/isdn/act2000/capi.h
drivers/isdn/act2000/module.c
drivers/isdn/capi/capi.c
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/Kconfig
drivers/isdn/gigaset/asyncdata.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/gigaset.h
drivers/isdn/gigaset/interface.c
drivers/isdn/gigaset/isocdata.c
drivers/isdn/gigaset/usb-gigaset.c
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hardware/avm/b1.c
drivers/isdn/hardware/avm/t1isa.c
drivers/isdn/hardware/eicon/debug.c
drivers/isdn/hardware/eicon/di.c
drivers/isdn/hardware/eicon/divasmain.c
drivers/isdn/hardware/eicon/io.c
drivers/isdn/hardware/eicon/istream.c
drivers/isdn/hardware/eicon/platform.h
drivers/isdn/hisax/Kconfig
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/fsm.c
drivers/isdn/hisax/hfc4s8s_l1.c
drivers/isdn/hisax/hfc_2bds0.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/hisax/hisax.h
drivers/isdn/hisax/hisax_fcpcipnp.c
drivers/isdn/hisax/hisax_isac.c
drivers/isdn/hisax/icc.c
drivers/isdn/hisax/isac.c
drivers/isdn/hisax/isar.c
drivers/isdn/hisax/isdnhdlc.c
drivers/isdn/hisax/isdnhdlc.h
drivers/isdn/hisax/isdnl1.c
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/st5481_b.c
drivers/isdn/hisax/st5481_d.c
drivers/isdn/hisax/st5481_init.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/hisax/w6692.c
drivers/isdn/hysdn/boardergo.c
drivers/isdn/hysdn/hycapi.c
drivers/isdn/hysdn/hysdn_boot.c
drivers/isdn/hysdn/hysdn_init.c
drivers/isdn/hysdn/hysdn_net.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/isdn/i4l/isdn_bsdcomp.c
drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_net.c
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/i4l/isdn_v110.c
drivers/isdn/icn/icn.c
drivers/isdn/isdnloop/isdnloop.c
drivers/isdn/pcbit/drv.c
drivers/isdn/pcbit/layer2.c
drivers/isdn/pcbit/pcbit.h
drivers/isdn/sc/init.c
drivers/kvm/Kconfig [new file with mode: 0644]
drivers/kvm/Makefile [new file with mode: 0644]
drivers/kvm/kvm.h [new file with mode: 0644]
drivers/kvm/kvm_main.c [new file with mode: 0644]
drivers/kvm/kvm_svm.h [new file with mode: 0644]
drivers/kvm/kvm_vmx.h [new file with mode: 0644]
drivers/kvm/mmu.c [new file with mode: 0644]
drivers/kvm/paging_tmpl.h [new file with mode: 0644]
drivers/kvm/segment_descriptor.h [new file with mode: 0644]
drivers/kvm/svm.c [new file with mode: 0644]
drivers/kvm/svm.h [new file with mode: 0644]
drivers/kvm/vmx.c [new file with mode: 0644]
drivers/kvm/vmx.h [new file with mode: 0644]
drivers/kvm/x86_emulate.c [new file with mode: 0644]
drivers/kvm/x86_emulate.h [new file with mode: 0644]
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-wrap.c [new file with mode: 0644]
drivers/macintosh/Kconfig
drivers/macintosh/adb.c
drivers/macintosh/adbhid.c
drivers/macintosh/apm_emu.c
drivers/macintosh/mac_hid.c
drivers/macintosh/rack-meter.c
drivers/macintosh/smu.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/via-pmu.c
drivers/macintosh/windfarm_core.c
drivers/md/Kconfig
drivers/md/bitmap.c
drivers/md/dm-bio-list.h
drivers/md/dm-crypt.c
drivers/md/dm-emc.c
drivers/md/dm-hw-handler.h
drivers/md/dm-io.c
drivers/md/dm-ioctl.c
drivers/md/dm-linear.c
drivers/md/dm-log.c
drivers/md/dm-log.h
drivers/md/dm-mpath.c
drivers/md/dm-mpath.h
drivers/md/dm-path-selector.h
drivers/md/dm-raid1.c
drivers/md/dm-round-robin.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-zero.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/kcopyd.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_i2c.c
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/gp8psk.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/ttusb2.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/ttusb2.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/usb-urb.c
drivers/media/dvb/dvb-usb/vp702x.c
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dib7000m.c [new file with mode: 0644]
drivers/media/dvb/frontends/dib7000m.h [new file with mode: 0644]
drivers/media/dvb/frontends/dib7000p.c [new file with mode: 0644]
drivers/media/dvb/frontends/dib7000p.h [new file with mode: 0644]
drivers/media/dvb/frontends/dibx000_common.h
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/lg_h06xf.h [deleted file]
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgdt330x_priv.h
drivers/media/dvb/frontends/lgh06xf.c [new file with mode: 0644]
drivers/media/dvb/frontends/lgh06xf.h [new file with mode: 0644]
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda826x.c
drivers/media/dvb/frontends/tua6100.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/radio/Kconfig
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/cafe_ccic-regs.h [new file with mode: 0644]
drivers/media/video/cafe_ccic.c [new file with mode: 0644]
drivers/media/video/compat_ioctl32.c
drivers/media/video/cpia_pp.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/msp3400-driver.c
drivers/media/video/mxb.c
drivers/media/video/ov7670.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-context.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/saa6588.c
drivers/media/video/saa7115.c
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/stv680.c
drivers/media/video/tda9887.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-types.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/usbvideo/quickcam_messenger.c
drivers/media/video/usbvision/Kconfig [new file with mode: 0644]
drivers/media/video/usbvision/Makefile [new file with mode: 0644]
drivers/media/video/usbvision/usbvision-cards.c [new file with mode: 0644]
drivers/media/video/usbvision/usbvision-core.c [new file with mode: 0644]
drivers/media/video/usbvision/usbvision-i2c.c [new file with mode: 0644]
drivers/media/video/usbvision/usbvision-video.c [new file with mode: 0644]
drivers/media/video/usbvision/usbvision.h [new file with mode: 0644]
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf-dvb.c
drivers/media/video/videodev.c
drivers/media/video/vivi.c
drivers/media/video/zoran_procfs.c
drivers/media/video/zr36120.c [deleted file]
drivers/media/video/zr36120.h [deleted file]
drivers/media/video/zr36120_i2c.c [deleted file]
drivers/media/video/zr36120_mem.c [deleted file]
drivers/media/video/zr36120_mem.h [deleted file]
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/message/i2o/bus-osm.c
drivers/message/i2o/device.c
drivers/message/i2o/driver.c
drivers/message/i2o/exec-osm.c
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_block.h
drivers/message/i2o/i2o_config.c
drivers/message/i2o/i2o_proc.c
drivers/message/i2o/i2o_scsi.c
drivers/message/i2o/pci.c
drivers/mfd/ucb1x00-ts.c
drivers/misc/tifm_7xx1.c
drivers/misc/tifm_core.c
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/at91_mci.c
drivers/mmc/au1xmmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc.h
drivers/mmc/mmc_queue.c
drivers/mmc/mmc_sysfs.c
drivers/mmc/pxamci.c
drivers/mmc/sdhci.c
drivers/mmc/tifm_sd.c
drivers/mtd/devices/m25p80.c
drivers/net/3c501.c
drivers/net/3c503.c
drivers/net/3c505.c
drivers/net/3c507.c
drivers/net/3c523.c
drivers/net/3c527.c
drivers/net/7990.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/ac3200.c
drivers/net/apne.c
drivers/net/appletalk/cops.c
drivers/net/arm/at91_ether.c
drivers/net/arm/at91_ether.h
drivers/net/arm/ether1.c
drivers/net/arm/ether3.c
drivers/net/at1700.c
drivers/net/atarilance.c
drivers/net/bnx2.c
drivers/net/bonding/bond_main.c
drivers/net/cassini.c
drivers/net/chelsio/common.h
drivers/net/chelsio/cphy.h
drivers/net/chelsio/cxgb2.c
drivers/net/chelsio/my3126.c
drivers/net/chelsio/sge.c
drivers/net/chelsio/sge.h
drivers/net/cs89x0.c
drivers/net/de600.c
drivers/net/declance.c
drivers/net/e100.c
drivers/net/e1000/e1000_main.c
drivers/net/e2100.c
drivers/net/eepro.c
drivers/net/eexpress.c
drivers/net/ehea/ehea_main.c
drivers/net/es3210.c
drivers/net/eth16i.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/hp-plus.c
drivers/net/hp.c
drivers/net/hplance.c
drivers/net/irda/irtty-sir.c
drivers/net/irda/mcs7780.c
drivers/net/irda/pxaficp_ir.c
drivers/net/irda/sir-dev.h
drivers/net/irda/sir_dev.c
drivers/net/irda/stir4200.c
drivers/net/iseries_veth.c
drivers/net/ixgb/ixgb_main.c
drivers/net/lance.c
drivers/net/lasi_82596.c
drivers/net/lne390.c
drivers/net/macb.c
drivers/net/macb.h
drivers/net/mv643xx_eth.c
drivers/net/mvme147.c
drivers/net/myri10ge/myri10ge.c
drivers/net/myri10ge/myri10ge_mcp.h
drivers/net/myri10ge/myri10ge_mcp_gen_header.h
drivers/net/ne.c
drivers/net/ne2.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_hw.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_ioctl.h
drivers/net/netxen/netxen_nic_isr.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_niu.c
drivers/net/netxen/netxen_nic_phan_reg.h
drivers/net/ni52.c
drivers/net/ni65.c
drivers/net/ns83820.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/phy/phy.c
drivers/net/plip.c
drivers/net/qla3xxx.c
drivers/net/qla3xxx.h
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/seeq8005.c
drivers/net/sis190.c
drivers/net/sk98lin/skgesirq.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/sky2.c
drivers/net/sky2.h
drivers/net/smc-ultra.c
drivers/net/smc-ultra32.c
drivers/net/smc9194.c
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/net/spider_net.c
drivers/net/sun3lance.c
drivers/net/sungem.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tlan.c
drivers/net/tlan.h
drivers/net/tokenring/smctr.c
drivers/net/tulip/21142.c
drivers/net/tulip/timer.c
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/ucc_geth.c
drivers/net/via-velocity.c
drivers/net/wan/Kconfig
drivers/net/wan/cosa.c
drivers/net/wan/pc300_tty.c
drivers/net/wd.c
drivers/net/wireless/airo.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/hostap/hostap.h
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_download.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_info.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2100.h
drivers/net/wireless/ipw2200.c
drivers/net/wireless/ipw2200.h
drivers/net/wireless/orinoco.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.h
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_eth.h
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/strip.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/oprofile/buffer_sync.c
drivers/oprofile/cpu_buffer.c
drivers/oprofile/cpu_buffer.h
drivers/parport/Kconfig
drivers/parport/parport_pc.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/msi.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pcmcia/at91_cf.c
drivers/pcmcia/cs.c
drivers/pcmcia/ds.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pnp/card.c
drivers/pnp/interface.c
drivers/pnp/isapnp/proc.c
drivers/pnp/pnpbios/core.c
drivers/ps3/Makefile
drivers/ps3/vuart.c [new file with mode: 0644]
drivers/ps3/vuart.h [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-at91rm9200.c [moved from drivers/rtc/rtc-at91.c with 100% similarity]
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-lib.c
drivers/rtc/rtc-omap.c [new file with mode: 0644]
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-x1205.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/char/ctrlchar.c
drivers/s390/char/fs3270.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/tape.h
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_core.c
drivers/s390/char/tty3270.c
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/crypto/ap_bus.c
drivers/s390/net/lcs.c
drivers/s390/net/qeth_main.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_fsf.c
drivers/sbus/char/bpp.c
drivers/sbus/char/cpwatchdog.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/openprom.c
drivers/sbus/char/vfc_dev.c
drivers/scsi/53c700.c
drivers/scsi/53c700.h
drivers/scsi/Kconfig
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/aha152x.c
drivers/scsi/aic94xx/aic94xx.h
drivers/scsi/aic94xx/aic94xx_hwi.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ide-scsi.c
drivers/scsi/imm.c
drivers/scsi/ipr.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/libsas/sas_event.c
drivers/scsi/libsas/sas_init.c
drivers/scsi/libsas/sas_internal.h
drivers/scsi/libsas/sas_phy.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/oktagon_esp.c
drivers/scsi/ppa.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sd.c
drivers/scsi/st.c
drivers/scsi/sun3_NCR5380.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi.h
drivers/scsi/sun3_scsi_vme.c
drivers/serial/21285.c
drivers/serial/68328serial.c
drivers/serial/68360serial.c
drivers/serial/8250.c
drivers/serial/8250_exar_st16c554.c [new file with mode: 0644]
drivers/serial/8250_pnp.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/amba-pl010.c
drivers/serial/amba-pl011.c
drivers/serial/atmel_serial.c
drivers/serial/atmel_serial.h
drivers/serial/clps711x.c
drivers/serial/crisv10.c
drivers/serial/crisv10.h
drivers/serial/dz.c
drivers/serial/dz.h
drivers/serial/icom.c
drivers/serial/imx.c
drivers/serial/ioc3_serial.c
drivers/serial/ioc4_serial.c
drivers/serial/ip22zilog.c
drivers/serial/jsm/jsm_tty.c
drivers/serial/m32r_sio.c
drivers/serial/mcfserial.c
drivers/serial/mpc52xx_uart.c
drivers/serial/mpsc.c
drivers/serial/mux.c
drivers/serial/netx-serial.c
drivers/serial/pmac_zilog.c
drivers/serial/pmac_zilog.h
drivers/serial/pxa.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_core.c
drivers/serial/serial_lh7a40x.c
drivers/serial/serial_txx9.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/sn_console.c
drivers/serial/sunhv.c
drivers/serial/sunsab.c
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/serial/uartlite.c [new file with mode: 0644]
drivers/serial/v850e_uart.c
drivers/serial/vr41xx_siu.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi.c
drivers/spi/spi_bitbang.c
drivers/spi/spi_butterfly.c
drivers/tc/zs.c
drivers/telephony/ixj.c
drivers/usb/Kconfig
drivers/usb/atm/cxacru.c
drivers/usb/atm/speedtch.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/buffer.c
drivers/usb/core/hub.c
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/usb.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/hc_crisv10.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-q.c
drivers/usb/input/Kconfig
drivers/usb/input/Makefile
drivers/usb/input/acecad.c
drivers/usb/input/aiptek.c
drivers/usb/input/appletouch.c
drivers/usb/input/ati_remote.c
drivers/usb/input/hid-core.c
drivers/usb/input/hid-ff.c
drivers/usb/input/hid-lgff.c
drivers/usb/input/hid-pidff.c
drivers/usb/input/hid-tmff.c
drivers/usb/input/hid-zpff.c
drivers/usb/input/hiddev.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/usbhid.h [new file with mode: 0644]
drivers/usb/input/usbkbd.c
drivers/usb/input/usbmouse.c
drivers/usb/input/usbtouchscreen.c
drivers/usb/input/xpad.c
drivers/usb/input/yealink.c
drivers/usb/misc/appledisplay.c
drivers/usb/misc/ftdi-elan.c
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usbtest.c
drivers/usb/mon/mon_text.c
drivers/usb/net/catc.c
drivers/usb/net/kaweth.c
drivers/usb/net/net1080.c
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.h
drivers/usb/net/rndis_host.c
drivers/usb/net/rtl8150.c
drivers/usb/net/usbnet.c
drivers/usb/serial/aircable.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/console.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/transport.c
drivers/usb/storage/usb.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/S3triofb.c
drivers/video/amifb.c
drivers/video/arcfb.c
drivers/video/atafb.c
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb.h
drivers/video/aty/atyfb_base.c
drivers/video/aty/mach64_ct.c
drivers/video/aty/radeon_monitor.c
drivers/video/au1100fb.h
drivers/video/backlight/backlight.c
drivers/video/backlight/corgi_bl.c
drivers/video/backlight/hp680_bl.c
drivers/video/backlight/lcd.c
drivers/video/backlight/locomolcd.c
drivers/video/cfbimgblt.c
drivers/video/cirrusfb.c
drivers/video/console/fbcon.c
drivers/video/console/softcursor.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/cyberfb.c
drivers/video/epson1355fb.c
drivers/video/fbcmap.c
drivers/video/fbcvt.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/ffb.c
drivers/video/fm2fb.c
drivers/video/geode/Kconfig
drivers/video/geode/display_gx.c
drivers/video/geode/display_gx.h
drivers/video/geode/gxfb_core.c
drivers/video/geode/video_gx.c
drivers/video/geode/video_gx.h
drivers/video/gxt4500.c [new file with mode: 0644]
drivers/video/hpfb.c
drivers/video/i810/i810-i2c.c
drivers/video/igafb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/macfb.c
drivers/video/mbx/mbxdebugfs.c
drivers/video/mbx/mbxfb.c
drivers/video/mbx/reg_bits.h
drivers/video/mbx/regs.h
drivers/video/modedb.c
drivers/video/neofb.c
drivers/video/nvidia/nv_accel.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nv_local.h
drivers/video/nvidia/nv_of.c
drivers/video/nvidia/nv_proto.h
drivers/video/offb.c
drivers/video/platinumfb.c
drivers/video/pmagb-b-fb.c
drivers/video/pvr2fb.c
drivers/video/pxafb.c
drivers/video/retz3fb.c
drivers/video/riva/fbdev.c
drivers/video/riva/riva_hw.c
drivers/video/riva/riva_hw.h
drivers/video/s3c2410fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/sis/init301.c
drivers/video/stifb.c
drivers/video/tgafb.c
drivers/video/tridentfb.c
drivers/video/vesafb.c
drivers/video/vga16fb.c
drivers/video/virgefb.c
drivers/w1/Makefile
drivers/w1/slaves/Makefile
drivers/w1/slaves/w1_ds2433.c
drivers/w1/w1.c
drivers/zorro/proc.c
fs/9p/mux.c
fs/9p/vfs_addr.c
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/Makefile
fs/adfs/dir.c
fs/adfs/super.c
fs/affs/amigaffs.c
fs/affs/bitmap.c
fs/affs/dir.c
fs/affs/super.c
fs/afs/dir.c
fs/afs/kafsasyncd.c
fs/afs/kafstimod.c
fs/afs/mntpt.c
fs/afs/server.c
fs/afs/super.c
fs/aio.c
fs/autofs/inode.c
fs/autofs/root.c
fs/autofs4/autofs_i.h
fs/autofs4/inode.c
fs/autofs4/root.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/bfs/inode.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/binfmt_misc.c
fs/bio.c
fs/block_dev.c
fs/buffer.c
fs/cifs/CHANGES
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifspdu.h
fs/cifs/connect.c
fs/cifs/fcntl.c
fs/cifs/file.c
fs/cifs/misc.c
fs/cifs/readdir.c
fs/cifs/transport.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c
fs/compat.c
fs/compat_ioctl.c
fs/configfs/configfs_internal.h
fs/configfs/dir.c
fs/configfs/file.c
fs/configfs/mount.c
fs/cramfs/inode.c
fs/dcache.c
fs/dcookies.c
fs/direct-io.c
fs/dlm/Kconfig
fs/dlm/Makefile
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/lowcomms-sctp.c [moved from fs/dlm/lowcomms.c with 87% similarity]
fs/dlm/lowcomms-tcp.c [new file with mode: 0644]
fs/dlm/lowcomms.h
fs/dlm/main.c
fs/dlm/member.c
fs/dlm/memory.c
fs/dlm/rcom.c
fs/dlm/recover.c
fs/dlm/recoverd.c
fs/dlm/requestqueue.c
fs/dlm/requestqueue.h
fs/dnotify.c
fs/dquot.c
fs/ecryptfs/crypto.c
fs/ecryptfs/dentry.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/ecryptfs/super.c
fs/efs/dir.c
fs/efs/super.c
fs/eventpoll.c
fs/exec.c
fs/ext2/dir.c
fs/ext2/ioctl.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/ext3/Makefile
fs/ext3/balloc.c
fs/ext3/dir.c
fs/ext3/ext3_jbd.c [new file with mode: 0644]
fs/ext3/file.c
fs/ext3/inode.c
fs/ext3/ioctl.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext3/xattr.c
fs/ext4/Makefile
fs/ext4/balloc.c
fs/ext4/dir.c
fs/ext4/ext4_jbd2.c [new file with mode: 0644]
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/fcntl.c
fs/file.c
fs/file_table.c
fs/freevxfs/vxfs_inode.c
fs/freevxfs/vxfs_lookup.c
fs/fuse/control.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/Kconfig
fs/gfs2/acl.c
fs/gfs2/acl.h
fs/gfs2/bmap.c
fs/gfs2/daemon.c
fs/gfs2/dir.c
fs/gfs2/dir.h
fs/gfs2/eaops.c
fs/gfs2/eattr.c
fs/gfs2/eattr.h
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/lops.c
fs/gfs2/lops.h
fs/gfs2/main.c
fs/gfs2/meta_io.c
fs/gfs2/meta_io.h
fs/gfs2/ondisk.c
fs/gfs2/ops_address.c
fs/gfs2/ops_dentry.c
fs/gfs2/ops_export.c
fs/gfs2/ops_export.h
fs/gfs2/ops_file.c
fs/gfs2/ops_file.h
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
fs/gfs2/ops_super.c
fs/gfs2/ops_vm.c
fs/gfs2/quota.c
fs/gfs2/recovery.c
fs/gfs2/recovery.h
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/super.h
fs/gfs2/sys.c
fs/gfs2/util.c
fs/gfs2/util.h
fs/hfs/dir.c
fs/hfs/inode.c
fs/hfs/super.c
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/dir.c
fs/hpfs/dnode.c
fs/hpfs/ea.c
fs/hpfs/file.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/map.c
fs/hpfs/super.c
fs/hppfs/hppfs_kern.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/inotify_user.c
fs/ioctl.c
fs/isofs/compress.c
fs/isofs/dir.c
fs/isofs/inode.c
fs/jbd/journal.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/revoke.c
fs/jbd2/transaction.c
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jffs/jffs_fm.c
fs/jffs2/background.c
fs/jffs2/dir.c
fs/jffs2/malloc.c
fs/jffs2/super.c
fs/jfs/jfs_dtree.c
fs/jfs/jfs_logmgr.c
fs/jfs/jfs_metapage.c
fs/jfs/jfs_txnmgr.c
fs/jfs/super.c
fs/libfs.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/locks.c
fs/mbcache.c
fs/minix/dir.c
fs/minix/inode.c
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/mmap.c
fs/ncpfs/sock.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/getroot.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4renewd.c
fs/nfs/pagelist.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/symlink.c
fs/nfs/write.c
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3acl.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
fs/nls/nls_cp936.c
fs/ntfs/attrib.c
fs/ntfs/dir.c
fs/ntfs/file.c
fs/ntfs/index.c
fs/ntfs/inode.c
fs/ntfs/unistr.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/quorum.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/cluster/tcp_internal.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/userdlm.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/ocfs2/inode.h
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/ocfs2.h
fs/ocfs2/super.c
fs/ocfs2/uptodate.c
fs/open.c
fs/openpromfs/inode.c
fs/partitions/Kconfig
fs/partitions/amiga.c
fs/partitions/atari.c
fs/partitions/check.c
fs/partitions/ibm.c
fs/pipe.c
fs/pnode.c
fs/pnode.h
fs/proc/Makefile
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/kcore.c
fs/proc/nommu.c
fs/proc/proc_misc.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/qnx4/dir.c
fs/qnx4/inode.c
fs/ramfs/file-nommu.c
fs/read_write.c
fs/readdir.c
fs/reiserfs/bitmap.c
fs/reiserfs/dir.c
fs/reiserfs/file.c
fs/reiserfs/fix_node.c
fs/reiserfs/inode.c
fs/reiserfs/ioctl.c
fs/reiserfs/journal.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/reiserfs/tail_conversion.c
fs/reiserfs/xattr.c
fs/romfs/inode.c
fs/select.c
fs/seq_file.c
fs/smbfs/cache.c
fs/smbfs/dir.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/request.c
fs/smbfs/sock.c
fs/splice.c
fs/stack.c [new file with mode: 0644]
fs/stat.c
fs/super.c
fs/sync.c
fs/sysfs/bin.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/mount.c
fs/sysfs/sysfs.h
fs/sysv/CHANGES [deleted file]
fs/sysv/ChangeLog [deleted file]
fs/sysv/INTRO [deleted file]
fs/sysv/dir.c
fs/sysv/inode.c
fs/udf/dir.c
fs/udf/file.c
fs/udf/super.c
fs/ufs/dir.c
fs/ufs/super.c
fs/ufs/util.h
fs/xattr.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_ioctl32.c
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/xfs_dfrag.c
include/acpi/platform/aclinux.h
include/asm-alpha/dma-mapping.h
include/asm-alpha/termbits.h
include/asm-alpha/unistd.h
include/asm-arm/arch-aaec2000/memory.h
include/asm-arm/arch-at91rm9200/at91_aic.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_dbgu.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_ecc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_lcdc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_mci.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_mci.h with 85% similarity]
include/asm-arm/arch-at91rm9200/at91_pdc.h [moved from include/asm-avr32/arch-at32ap/at91rm9200_pdc.h with 92% similarity]
include/asm-arm/arch-at91rm9200/at91_pio.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_pit.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_pmc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_rstc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_rtc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_rtt.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_shdwc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_spi.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_spi.h with 95% similarity]
include/asm-arm/arch-at91rm9200/at91_ssc.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h with 86% similarity]
include/asm-arm/arch-at91rm9200/at91_st.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91_tc.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_tc.h with 98% similarity]
include/asm-arm/arch-at91rm9200/at91_twi.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_twi.h with 90% similarity]
include/asm-arm/arch-at91rm9200/at91_wdt.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200.h
include/asm-arm/arch-at91rm9200/at91rm9200_mc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200_sys.h [deleted file]
include/asm-arm/arch-at91rm9200/at91rm9200_udp.h [deleted file]
include/asm-arm/arch-at91rm9200/at91sam9260.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91sam9261.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91sam926x_mc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/board.h
include/asm-arm/arch-at91rm9200/cpu.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/debug-macro.S
include/asm-arm/arch-at91rm9200/entry-macro.S
include/asm-arm/arch-at91rm9200/hardware.h
include/asm-arm/arch-at91rm9200/irqs.h
include/asm-arm/arch-at91rm9200/system.h
include/asm-arm/arch-at91rm9200/timex.h
include/asm-arm/arch-at91rm9200/uncompress.h
include/asm-arm/arch-at91rm9200/vmalloc.h
include/asm-arm/arch-clps711x/memory.h
include/asm-arm/arch-imx/timex.h
include/asm-arm/arch-iop13xx/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop13xx/dma.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop13xx/hardware.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/io.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/iop13xx.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/iq81340.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/irqs.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/memory.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/pci.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/system.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/timex.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-iop13xx/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/nslu2.h
include/asm-arm/arch-ixp4xx/udc.h [new file with mode: 0644]
include/asm-arm/arch-l7200/io.h
include/asm-arm/arch-lh7a40x/memory.h
include/asm-arm/arch-omap/irda.h
include/asm-arm/arch-pxa/memory.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/pxa2xx_spi.h
include/asm-arm/arch-s3c2410/fb.h
include/asm-arm/arch-s3c2410/h1940.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/system.h
include/asm-arm/arch-sa1100/jornada720.h [deleted file]
include/asm-arm/arch-sa1100/memory.h
include/asm-arm/bug.h
include/asm-arm/cnt32_to_63.h [new file with mode: 0644]
include/asm-arm/div64.h
include/asm-arm/dma-mapping.h
include/asm-arm/elf.h
include/asm-arm/io.h
include/asm-arm/mach/irq.h
include/asm-arm/memory.h
include/asm-arm/pgtable-nommu.h
include/asm-arm/pgtable.h
include/asm-arm/processor.h
include/asm-arm/procinfo.h
include/asm-arm/setup.h
include/asm-arm/termbits.h
include/asm-arm/thread_info.h
include/asm-arm/unistd.h
include/asm-arm26/pgalloc.h
include/asm-arm26/setup.h
include/asm-arm26/termbits.h
include/asm-arm26/unistd.h
include/asm-avr32/arch-at32ap/at32ap7000.h [new file with mode: 0644]
include/asm-avr32/arch-at32ap/at91_pdc.h [moved from include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h with 92% similarity]
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/arch-at32ap/portmux.h
include/asm-avr32/dma-mapping.h
include/asm-avr32/setup.h
include/asm-avr32/termbits.h
include/asm-cris/arch-v10/bitops.h
include/asm-cris/dma-mapping.h
include/asm-cris/semaphore-helper.h
include/asm-cris/termbits.h
include/asm-frv/bitops.h
include/asm-frv/dma-mapping.h
include/asm-frv/highmem.h
include/asm-frv/param.h
include/asm-frv/setup.h
include/asm-frv/termbits.h
include/asm-frv/unistd.h
include/asm-generic/Kbuild
include/asm-generic/Kbuild.asm
include/asm-generic/atomic.h
include/asm-generic/bug.h
include/asm-generic/dma-mapping.h
include/asm-generic/futex.h
include/asm-generic/page.h
include/asm-generic/termios.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/delay.h
include/asm-h8300/mmu_context.h
include/asm-h8300/pci.h
include/asm-h8300/termbits.h
include/asm-h8300/tlbflush.h
include/asm-h8300/unistd.h
include/asm-i386/Kbuild
include/asm-i386/alternative.h
include/asm-i386/apic.h
include/asm-i386/atomic.h
include/asm-i386/boot.h
include/asm-i386/bug.h
include/asm-i386/bugs.h
include/asm-i386/cpu.h
include/asm-i386/cpufeature.h
include/asm-i386/current.h
include/asm-i386/delay.h
include/asm-i386/desc.h
include/asm-i386/dma-mapping.h
include/asm-i386/e820.h
include/asm-i386/elf.h
include/asm-i386/futex.h
include/asm-i386/genapic.h
include/asm-i386/i387.h
include/asm-i386/ide.h
include/asm-i386/io.h
include/asm-i386/irq.h
include/asm-i386/irq_regs.h
include/asm-i386/irqflags.h
include/asm-i386/mach-default/setup_arch.h
include/asm-i386/math_emu.h
include/asm-i386/mmu_context.h
include/asm-i386/mmzone.h
include/asm-i386/module.h
include/asm-i386/mpspec_def.h
include/asm-i386/msr.h
include/asm-i386/nmi.h
include/asm-i386/page.h
include/asm-i386/param.h
include/asm-i386/paravirt.h [new file with mode: 0644]
include/asm-i386/pda.h [new file with mode: 0644]
include/asm-i386/percpu.h
include/asm-i386/pgtable-2level.h
include/asm-i386/pgtable-3level.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/ptrace.h
include/asm-i386/rwsem.h
include/asm-i386/segment.h
include/asm-i386/setup.h
include/asm-i386/smp.h
include/asm-i386/spinlock.h
include/asm-i386/spinlock_types.h
include/asm-i386/suspend.h
include/asm-i386/system.h
include/asm-i386/termbits.h
include/asm-i386/thread_info.h
include/asm-i386/time.h [new file with mode: 0644]
include/asm-i386/tlbflush.h
include/asm-i386/topology.h
include/asm-i386/unistd.h
include/asm-i386/unwind.h
include/asm-i386/vm86.h
include/asm-ia64/Kbuild
include/asm-ia64/checksum.h
include/asm-ia64/dma-mapping.h
include/asm-ia64/futex.h
include/asm-ia64/kexec.h [new file with mode: 0644]
include/asm-ia64/machvec.h
include/asm-ia64/machvec_sn2.h
include/asm-ia64/meminit.h
include/asm-ia64/page.h
include/asm-ia64/pal.h
include/asm-ia64/pgalloc.h
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/termbits.h
include/asm-ia64/topology.h
include/asm-m32r/ide.h
include/asm-m32r/m32102.h
include/asm-m32r/ptrace.h
include/asm-m32r/setup.h
include/asm-m32r/sigcontext.h
include/asm-m32r/termbits.h
include/asm-m32r/unistd.h
include/asm-m68k/dma-mapping.h
include/asm-m68k/setup.h
include/asm-m68k/sun3-head.h
include/asm-m68k/sun3ints.h
include/asm-m68k/termbits.h
include/asm-m68k/unistd.h
include/asm-m68knommu/irq.h
include/asm-m68knommu/rtc.h [new file with mode: 0644]
include/asm-m68knommu/setup.h
include/asm-m68knommu/ucontext.h
include/asm-m68knommu/unistd.h
include/asm-mips/bootinfo.h
include/asm-mips/compat.h
include/asm-mips/dma-mapping.h
include/asm-mips/futex.h
include/asm-mips/highmem.h
include/asm-mips/i8259.h
include/asm-mips/mach-ip27/irq.h
include/asm-mips/mach-ip27/topology.h
include/asm-mips/mach-rm/cpu-feature-overrides.h [moved from include/asm-mips/mach-rm200/cpu-feature-overrides.h with 100% similarity]
include/asm-mips/mach-rm/mc146818rtc.h [moved from include/asm-mips/mach-rm200/mc146818rtc.h with 100% similarity]
include/asm-mips/mach-rm/timex.h [moved from include/asm-mips/mach-rm200/timex.h with 100% similarity]
include/asm-mips/pci.h
include/asm-mips/pgtable-32.h
include/asm-mips/pgtable-64.h
include/asm-mips/ptrace.h
include/asm-mips/setup.h
include/asm-mips/sn/arch.h
include/asm-mips/sn/klconfig.h
include/asm-mips/system.h
include/asm-mips/termbits.h
include/asm-mips/unistd.h
include/asm-mips/war.h
include/asm-parisc/dma-mapping.h
include/asm-parisc/futex.h
include/asm-parisc/termbits.h
include/asm-powerpc/Kbuild
include/asm-powerpc/bitops.h
include/asm-powerpc/bug.h
include/asm-powerpc/cputable.h
include/asm-powerpc/dcr-native.h
include/asm-powerpc/dcr.h
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/elf.h
include/asm-powerpc/futex.h
include/asm-powerpc/hw_irq.h
include/asm-powerpc/module.h
include/asm-powerpc/page_32.h
include/asm-powerpc/pci-bridge.h
include/asm-powerpc/pci.h
include/asm-powerpc/pgalloc.h
include/asm-powerpc/reg.h
include/asm-powerpc/rtas.h
include/asm-powerpc/setup.h
include/asm-powerpc/termbits.h
include/asm-powerpc/topology.h
include/asm-powerpc/unistd.h
include/asm-ppc/highmem.h
include/asm-ppc/pci-bridge.h
include/asm-ppc/pci.h
include/asm-ppc/reg_booke.h
include/asm-s390/dasd.h
include/asm-s390/page.h
include/asm-s390/pgalloc.h
include/asm-s390/pgtable.h
include/asm-s390/setup.h
include/asm-s390/termbits.h
include/asm-s390/unistd.h
include/asm-sh/atomic.h
include/asm-sh/bugs.h
include/asm-sh/clock.h
include/asm-sh/cpu-sh2/cache.h
include/asm-sh/cpu-sh2/freq.h [new file with mode: 0644]
include/asm-sh/cpu-sh2/mmu_context.h [new file with mode: 0644]
include/asm-sh/cpu-sh2/timer.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/addrspace.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/cache.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/cacheflush.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/dma.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/freq.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/mmu_context.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/timer.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/ubc.h [new file with mode: 0644]
include/asm-sh/cpu-sh2a/watchdog.h [new file with mode: 0644]
include/asm-sh/dma-mapping.h
include/asm-sh/dma.h
include/asm-sh/elf.h
include/asm-sh/entry-macros.S [new file with mode: 0644]
include/asm-sh/irq-sh73180.h [deleted file]
include/asm-sh/irq-sh7343.h [deleted file]
include/asm-sh/irq-sh7780.h [deleted file]
include/asm-sh/irq.h
include/asm-sh/irqflags.h [new file with mode: 0644]
include/asm-sh/mmu_context.h
include/asm-sh/page.h
include/asm-sh/pgalloc.h
include/asm-sh/pgtable-2level.h [deleted file]
include/asm-sh/pgtable.h
include/asm-sh/processor.h
include/asm-sh/push-switch.h [new file with mode: 0644]
include/asm-sh/rwsem.h
include/asm-sh/se7206.h [new file with mode: 0644]
include/asm-sh/setup.h
include/asm-sh/system.h
include/asm-sh/termbits.h
include/asm-sh/thread_info.h
include/asm-sh/timer.h
include/asm-sh/titan.h
include/asm-sh/unistd.h
include/asm-sh64/dma-mapping.h
include/asm-sh64/setup.h
include/asm-sh64/unistd.h
include/asm-sparc/termbits.h
include/asm-sparc/unistd.h
include/asm-sparc64/dma-mapping.h
include/asm-sparc64/dma.h
include/asm-sparc64/futex.h
include/asm-sparc64/irqflags.h [new file with mode: 0644]
include/asm-sparc64/kprobes.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/rwsem.h
include/asm-sparc64/system.h
include/asm-sparc64/termbits.h
include/asm-sparc64/ttable.h
include/asm-sparc64/unistd.h
include/asm-um/bug.h
include/asm-um/dma-mapping.h
include/asm-v850/irq.h
include/asm-v850/termbits.h
include/asm-v850/unistd.h
include/asm-x86_64/Kbuild
include/asm-x86_64/alternative.h
include/asm-x86_64/atomic.h
include/asm-x86_64/bug.h
include/asm-x86_64/calgary.h
include/asm-x86_64/cpufeature.h
include/asm-x86_64/delay.h
include/asm-x86_64/desc.h
include/asm-x86_64/desc_defs.h [new file with mode: 0644]
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/futex.h
include/asm-x86_64/genapic.h
include/asm-x86_64/ioctls.h
include/asm-x86_64/msr.h
include/asm-x86_64/nmi.h
include/asm-x86_64/pci-direct.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor.h
include/asm-x86_64/proto.h
include/asm-x86_64/rio.h [new file with mode: 0644]
include/asm-x86_64/smp.h
include/asm-x86_64/spinlock.h
include/asm-x86_64/spinlock_types.h
include/asm-x86_64/stacktrace.h
include/asm-x86_64/termbits.h
include/asm-x86_64/termios.h
include/asm-x86_64/topology.h
include/asm-x86_64/unistd.h
include/asm-x86_64/unwind.h
include/asm-x86_64/vsyscall.h
include/asm-xtensa/asmmacro.h [new file with mode: 0644]
include/asm-xtensa/bug.h
include/asm-xtensa/byteorder.h
include/asm-xtensa/cache.h
include/asm-xtensa/cacheasm.h [new file with mode: 0644]
include/asm-xtensa/cacheflush.h
include/asm-xtensa/checksum.h
include/asm-xtensa/coprocessor.h
include/asm-xtensa/dma-mapping.h
include/asm-xtensa/dma.h
include/asm-xtensa/elf.h
include/asm-xtensa/fcntl.h
include/asm-xtensa/fixmap.h [deleted file]
include/asm-xtensa/io.h
include/asm-xtensa/irq.h
include/asm-xtensa/irq_regs.h [new file with mode: 0644]
include/asm-xtensa/mmu_context.h
include/asm-xtensa/page.h
include/asm-xtensa/param.h
include/asm-xtensa/pgtable.h
include/asm-xtensa/platform-iss/hardware.h
include/asm-xtensa/platform-iss/simcall.h [new file with mode: 0644]
include/asm-xtensa/posix_types.h
include/asm-xtensa/processor.h
include/asm-xtensa/ptrace.h
include/asm-xtensa/regs.h [new file with mode: 0644]
include/asm-xtensa/sembuf.h
include/asm-xtensa/shmbuf.h
include/asm-xtensa/stat.h
include/asm-xtensa/syscall.h [new file with mode: 0644]
include/asm-xtensa/system.h
include/asm-xtensa/timex.h
include/asm-xtensa/tlbflush.h
include/asm-xtensa/unistd.h
include/asm-xtensa/variant-fsf/core.h [new file with mode: 0644]
include/asm-xtensa/variant-fsf/tie.h [new file with mode: 0644]
include/asm-xtensa/xtensa/cacheasm.h [deleted file]
include/asm-xtensa/xtensa/cacheattrasm.h [deleted file]
include/asm-xtensa/xtensa/config-linux_be/core.h [deleted file]
include/asm-xtensa/xtensa/config-linux_be/defs.h [deleted file]
include/asm-xtensa/xtensa/config-linux_be/specreg.h [deleted file]
include/asm-xtensa/xtensa/config-linux_be/system.h [deleted file]
include/asm-xtensa/xtensa/config-linux_be/tie.h [deleted file]
include/asm-xtensa/xtensa/coreasm.h [deleted file]
include/asm-xtensa/xtensa/corebits.h [deleted file]
include/asm-xtensa/xtensa/hal.h [deleted file]
include/asm-xtensa/xtensa/simcall.h [deleted file]
include/asm-xtensa/xtensa/xt2000-uart.h [deleted file]
include/asm-xtensa/xtensa/xt2000.h [deleted file]
include/asm-xtensa/xtensa/xtboard.h [deleted file]
include/crypto/b128ops.h [new file with mode: 0644]
include/crypto/gf128mul.h [new file with mode: 0644]
include/linux/Kbuild
include/linux/aio.h
include/linux/audit.h
include/linux/bitrev.h [new file with mode: 0644]
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/bottom_half.h [new file with mode: 0644]
include/linux/bug.h [new file with mode: 0644]
include/linux/carta_random32.h [deleted file]
include/linux/cciss_ioctl.h
include/linux/cdev.h
include/linux/clocksource.h
include/linux/connector.h
include/linux/cpu.h
include/linux/cpuset.h
include/linux/crc32.h
include/linux/crypto.h
include/linux/dccp.h
include/linux/debug_locks.h
include/linux/delayacct.h
include/linux/device-mapper.h
include/linux/device.h
include/linux/dm-ioctl.h
include/linux/efi.h
include/linux/elf.h
include/linux/ext3_jbd.h
include/linux/ext4_jbd2.h
include/linux/fault-inject.h [new file with mode: 0644]
include/linux/fb.h
include/linux/file.h
include/linux/freezer.h [new file with mode: 0644]
include/linux/fs.h
include/linux/fs_stack.h [new file with mode: 0644]
include/linux/fs_struct.h
include/linux/fsl_devices.h
include/linux/fsnotify.h
include/linux/fuse.h
include/linux/futex.h
include/linux/generic_serial.h
include/linux/genetlink.h
include/linux/genhd.h
include/linux/gfp.h
include/linux/gfs2_ondisk.h
include/linux/hid-debug.h [moved from drivers/usb/input/hid-debug.h with 100% similarity]
include/linux/hid.h [moved from drivers/usb/input/hid.h with 86% similarity]
include/linux/highmem.h
include/linux/hugetlb.h
include/linux/i2c-id.h
include/linux/i2c-pxa.h
include/linux/i2o.h
include/linux/ide.h
include/linux/if_addr.h
include/linux/if_link.h
include/linux/init.h
include/linux/init_task.h
include/linux/input.h
include/linux/interrupt.h
include/linux/ipmi.h
include/linux/ipmi_msgdefs.h
include/linux/ipmi_smi.h
include/linux/isdn.h
include/linux/istallion.h
include/linux/jbd.h
include/linux/jbd2.h
include/linux/kbd_kern.h
include/linux/kernel.h
include/linux/kexec.h
include/linux/kprobes.h
include/linux/ktime.h
include/linux/kvm.h [new file with mode: 0644]
include/linux/libata.h
include/linux/lockd/lockd.h
include/linux/lockdep.h
include/linux/log2.h [new file with mode: 0644]
include/linux/mm.h
include/linux/mmc/host.h
include/linux/mmzone.h
include/linux/mnt_namespace.h [new file with mode: 0644]
include/linux/module.h
include/linux/moduleparam.h
include/linux/mount.h
include/linux/msg.h
include/linux/mutex.h
include/linux/namei.h
include/linux/namespace.h [deleted file]
include/linux/nbd.h
include/linux/ncp_fs_sb.h
include/linux/netdevice.h
include/linux/netfilter/nf_conntrack_pptp.h
include/linux/netpoll.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/nmi.h
include/linux/nsproxy.h
include/linux/pci_ids.h
include/linux/pfkeyv2.h
include/linux/pid.h
include/linux/pid_namespace.h [new file with mode: 0644]
include/linux/pktcdvd.h
include/linux/profile.h
include/linux/pspace.h [deleted file]
include/linux/quotaops.h
include/linux/radix-tree.h
include/linux/raid/raid5.h
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs_sb.h
include/linux/relay.h
include/linux/rmap.h
include/linux/rtc.h
include/linux/rtmutex.h
include/linux/rtnetlink.h
include/linux/rwsem-spinlock.h
include/linux/sched.h
include/linux/screen_info.h
include/linux/seq_file.h
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/serio.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/smp.h
include/linux/spinlock.h
include/linux/stallion.h
include/linux/start_kernel.h [new file with mode: 0644]
include/linux/sunrpc/auth_gss.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/gss_krb5.h
include/linux/sunrpc/gss_spkm3.h
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xprt.h
include/linux/suspend.h
include/linux/swap.h
include/linux/sysctl.h
include/linux/task_io_accounting.h [new file with mode: 0644]
include/linux/task_io_accounting_ops.h [new file with mode: 0644]
include/linux/taskstats.h
include/linux/taskstats_kern.h
include/linux/tfrc.h
include/linux/timer.h
include/linux/topology.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/tty_ldisc.h
include/linux/uaccess.h
include/linux/usb.h
include/linux/usb/serial.h
include/linux/videodev2.h
include/linux/workqueue.h
include/linux/xfrm.h
include/media/ir-common.h
include/media/saa7146.h
include/media/tuner-types.h
include/media/tuner.h
include/media/tveeprom.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/net/ax25.h
include/net/dst.h
include/net/ieee80211softmac.h
include/net/inet_hashtables.h
include/net/inet_timewait_sock.h
include/net/ip.h
include/net/irda/ircomm_tty.h
include/net/irda/irlan_filter.h
include/net/neighbour.h
include/net/netfilter/nf_conntrack_expect.h
include/net/request_sock.h
include/net/sctp/sctp.h
include/net/sctp/structs.h
include/net/sock.h
include/net/timewait_sock.h
include/net/xfrm.h
include/scsi/libsas.h
include/scsi/scsi_transport_fc.h
include/scsi/scsi_transport_iscsi.h
include/sound/ac97_codec.h
include/sound/ak4114.h
include/video/mbxfb.h
include/video/pm3fb.h
init/Kconfig
init/Makefile
init/do_mounts_initrd.c
init/initramfs.c
init/main.c
init/version.c
ipc/compat.c
ipc/mqueue.c
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
kernel/Kconfig.hz
kernel/acct.c
kernel/audit.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/configs.c
kernel/cpu.c
kernel/cpuset.c
kernel/delayacct.c
kernel/dma.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/irq/handle.c
kernel/irq/proc.c
kernel/kallsyms.c
kernel/kexec.c
kernel/kmod.c
kernel/kprobes.c
kernel/kthread.c
kernel/lockdep.c
kernel/lockdep_internals.h
kernel/lockdep_proc.c
kernel/module.c
kernel/mutex-debug.c
kernel/mutex.c
kernel/nsproxy.c
kernel/pid.c
kernel/posix-timers.c
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
kernel/power/poweroff.c
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/swap.c
kernel/power/swsusp.c
kernel/power/user.c
kernel/printk.c
kernel/profile.c
kernel/rcupdate.c
kernel/rcutorture.c
kernel/relay.c
kernel/resource.c
kernel/rtmutex-tester.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/sys.c
kernel/sysctl.c
kernel/taskstats.c
kernel/time/clocksource.c
kernel/timer.c
kernel/tsacct.c
kernel/unwind.c
kernel/user.c
kernel/workqueue.c
lib/Kconfig
lib/Kconfig.debug
lib/Makefile
lib/bitrev.c [new file with mode: 0644]
lib/bug.c [new file with mode: 0644]
lib/cmdline.c
lib/crc32.c
lib/fault-inject.c [new file with mode: 0644]
lib/idr.c
lib/kobject.c
lib/list_debug.c
lib/locking-selftest.c
lib/radix-tree.c
lib/spinlock_debug.c
mm/allocpercpu.c
mm/bootmem.c
mm/fadvise.c
mm/filemap.c
mm/filemap_xip.c
mm/fremap.c
mm/hugetlb.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mmap.c
mm/mmzone.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_io.c
mm/pdflush.c
mm/readahead.c
mm/shmem.c
mm/slab.c
mm/sparse.c
mm/swap.c
mm/swapfile.c
mm/thrash.c
mm/tiny-shmem.c
mm/truncate.c
mm/vmscan.c
mm/vmstat.c
net/atm/lec.c
net/atm/lec.h
net/atm/proc.c
net/ax25/ax25_addr.c
net/bluetooth/hci_sysfs.c
net/bluetooth/rfcomm/tty.c
net/bridge/br_fdb.c
net/bridge/br_if.c
net/bridge/br_netfilter.c
net/bridge/br_private.h
net/core/dev.c
net/core/dst.c
net/core/flow.c
net/core/link_watch.c
net/core/neighbour.c
net/core/netpoll.c
net/core/skbuff.c
net/core/sock.c
net/core/wireless.c
net/dccp/ackvec.c
net/dccp/ccid.c
net/dccp/ccid.h
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/ccids/lib/loss_interval.c
net/dccp/ccids/lib/loss_interval.h
net/dccp/ccids/lib/packet_history.c
net/dccp/ccids/lib/packet_history.h
net/dccp/ccids/lib/tfrc.h
net/dccp/ccids/lib/tfrc_equation.c
net/dccp/dccp.h
net/dccp/feat.c
net/dccp/input.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/minisocks.c
net/dccp/options.c
net/dccp/output.c
net/dccp/proto.c
net/dccp/timer.c
net/decnet/dn_dev.c
net/decnet/dn_table.c
net/decnet/sysctl_net_decnet.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_auth.c
net/ieee80211/softmac/ieee80211softmac_event.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ieee80211/softmac/ieee80211softmac_scan.c
net/ieee80211/softmac/ieee80211softmac_wx.c
net/ipv4/devinet.c
net/ipv4/fib_hash.c
net/ipv4/fib_trie.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/inetpeer.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/ipvs/ip_vs_conn.c
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_sync.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_recent.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_output.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/raw.c
net/ipv6/xfrm6_tunnel.c
net/irda/ircomm/ircomm_tty.c
net/irda/ircomm/ircomm_tty_ioctl.c
net/irda/irttp.c
net/key/af_key.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/xt_hashlimit.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/rxrpc/krxiod.c
net/rxrpc/krxsecd.c
net/rxrpc/krxtimod.c
net/sched/cls_fw.c
net/sched/sch_cbq.c
net/sched/sch_htb.c
net/sctp/associola.c
net/sctp/endpointola.c
net/sctp/inqueue.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/auth_gss/gss_spkm3_token.c
net/sunrpc/auth_gss/gss_spkm3_unseal.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/pmap_clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/socklib.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcauth.c
net/sunrpc/svcsock.c
net/sunrpc/sysctl.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
net/tipc/handler.c
net/unix/garbage.c
net/wanrouter/wanmain.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/Kbuild.include
scripts/kallsyms.c
scripts/kconfig/qconf.cc
scripts/kernel-doc
scripts/mod/modpost.c
scripts/ver_linux
security/keys/key.c
security/keys/keyring.c
security/keys/process_keys.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/selinuxfs.c
security/selinux/ss/avtab.c
sound/aoa/aoa-gpio.h
sound/aoa/core/snd-aoa-gpio-feature.c
sound/aoa/core/snd-aoa-gpio-pmf.c
sound/arm/sa11xx-uda1341.c
sound/core/info.c
sound/core/pcm_native.c
sound/i2c/other/ak4114.c
sound/oss/Kconfig
sound/oss/btaudio.c
sound/oss/dmasound/dmasound_core.c
sound/oss/emu10k1/audio.c
sound/oss/emu10k1/cardwi.c
sound/oss/emu10k1/cardwi.h
sound/oss/emu10k1/passthrough.c
sound/oss/msnd_pinnacle.c
sound/oss/soundcard.c
sound/oss/via82cxxx_audio.c
sound/pci/ac97/ac97_codec.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_local.h
sound/ppc/tumbler.c
sound/sound_firmware.c
sound/usb/usx2y/usX2Yhwdep.c

diff --git a/CREDITS b/CREDITS
index d088008..8218e79 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1808,6 +1808,14 @@ S: Kruislaan 419
 S: 1098 VA Amsterdam 
 S: The Netherlands
 
+N: Jiri Kosina
+E: jikos@jikos.cz
+E: jkosina@suse.cz
+D: Generic HID layer - original code split, fixes
+D: Various ACPI fixes, keeping correct battery state through suspend
+D: various lockdep annotations, autofs and other random bugfixes
+S: Prague, Czech Republic
+
 N: Gene Kozin
 E: 74604.152@compuserve.com
 W: http://www.sangoma.com
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
new file mode 100644 (file)
index 0000000..03dbd88
--- /dev/null
@@ -0,0 +1,20 @@
+What:           /debug/pktcdvd/pktcdvd[0-7]
+Date:           Oct. 2006
+KernelVersion:  2.6.19
+Contact:        Thomas Maier <balagi@justmail.de>
+Description:
+
+debugfs interface
+-----------------
+
+The pktcdvd module (packet writing driver) creates
+these files in debugfs:
+
+/debug/pktcdvd/pktcdvd[0-7]/
+    info            (0444) Lots of human readable driver
+                           statistics and infos. Multiple lines!
+
+Example:
+-------
+
+cat /debug/pktcdvd/pktcdvd0/info
diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd
new file mode 100644 (file)
index 0000000..c4c55ed
--- /dev/null
@@ -0,0 +1,72 @@
+What:           /sys/class/pktcdvd/
+Date:           Oct. 2006
+KernelVersion:  2.6.19
+Contact:        Thomas Maier <balagi@justmail.de>
+Description:
+
+sysfs interface
+---------------
+
+The pktcdvd module (packet writing driver) creates
+these files in the sysfs:
+(<devid> is in format  major:minor )
+
+/sys/class/pktcdvd/
+    add            (0200)  Write a block device id (major:minor)
+                           to create a new pktcdvd device and map
+                           it to the block device.
+
+    remove         (0200)  Write the pktcdvd device id (major:minor)
+                           to it to remove the pktcdvd device.
+
+    device_map     (0444)  Shows the device mapping in format:
+                             pktcdvd[0-7] <pktdevid> <blkdevid>
+
+/sys/class/pktcdvd/pktcdvd[0-7]/
+    dev                   (0444) Device id
+    uevent                (0200) To send an uevent.
+
+/sys/class/pktcdvd/pktcdvd[0-7]/stat/
+    packets_started       (0444) Number of started packets.
+    packets_finished      (0444) Number of finished packets.
+
+    kb_written            (0444) kBytes written.
+    kb_read               (0444) kBytes read.
+    kb_read_gather        (0444) kBytes read to fill write packets.
+
+    reset                 (0200) Write any value to it to reset
+                                 pktcdvd device statistic values, like
+                                 bytes read/written.
+
+/sys/class/pktcdvd/pktcdvd[0-7]/write_queue/
+    size                  (0444) Contains the size of the bio write
+                                 queue.
+
+    congestion_off        (0644) If bio write queue size is below
+                                 this mark, accept new bio requests
+                                 from the block layer.
+
+    congestion_on         (0644) If bio write queue size is higher
+                                 as this mark, do no longer accept
+                                 bio write requests from the block
+                                 layer and wait till the pktcdvd
+                                 device has processed enough bio's
+                                 so that bio write queue size is
+                                 below congestion off mark.
+                                 A value of <= 0 disables congestion
+                                 control.
+
+
+Example:
+--------
+To use the pktcdvd sysfs interface directly, you can do:
+
+# create a new pktcdvd device mapped to /dev/hdc
+echo "22:0" >/sys/class/pktcdvd/add
+cat /sys/class/pktcdvd/device_map
+# assuming device pktcdvd0 was created, look at stat's
+cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
+# print the device id of the mapped block device
+fgrep pktcdvd0 /sys/class/pktcdvd/device_map
+# remove device, using pktcdvd0 device id   253:0
+echo "253:0" >/sys/class/pktcdvd/remove
index 29c1896..0ad6dcb 100644 (file)
@@ -35,12 +35,37 @@ In short, 8-char indents make things easier to read, and have the added
 benefit of warning you when you're nesting your functions too deep.
 Heed that warning.
 
+The preferred way to ease multiple indentation levels in a switch statement is
+to align the "switch" and its subordinate "case" labels in the same column
+instead of "double-indenting" the "case" labels.  E.g.:
+
+       switch (suffix) {
+       case 'G':
+       case 'g':
+               mem <<= 30;
+               break;
+       case 'M':
+       case 'm':
+               mem <<= 20;
+               break;
+       case 'K':
+       case 'k':
+               mem <<= 10;
+               /* fall through */
+       default:
+               break;
+       }
+
+
 Don't put multiple statements on a single line unless you have
 something to hide:
 
        if (condition) do_this;
          do_something_everytime;
 
+Don't put multiple assignments on a single line either.  Kernel coding style
+is super simple.  Avoid tricky expressions.
+
 Outside of comments, documentation and except in Kconfig, spaces are never
 used for indentation, and the above example is deliberately broken.
 
@@ -69,7 +94,7 @@ void fun(int a, int b, int c)
                next_statement;
 }
 
-               Chapter 3: Placing Braces
+               Chapter 3: Placing Braces and Spaces
 
 The other issue that always comes up in C styling is the placement of
 braces.  Unlike the indent size, there are few technical reasons to
@@ -81,6 +106,20 @@ brace last on the line, and put the closing brace first, thusly:
                we do y
        }
 
+This applies to all non-function statement blocks (if, switch, for,
+while, do).  E.g.:
+
+       switch (action) {
+       case KOBJ_ADD:
+               return "add";
+       case KOBJ_REMOVE:
+               return "remove";
+       case KOBJ_CHANGE:
+               return "change";
+       default:
+               return NULL;
+       }
+
 However, there is one special case, namely functions: they have the
 opening brace at the beginning of the next line, thus:
 
@@ -121,6 +160,49 @@ supply of new-lines on your screen is not a renewable resource (think
 25-line terminal screens here), you have more empty lines to put
 comments on.
 
+               3.1:  Spaces
+
+Linux kernel style for use of spaces depends (mostly) on
+function-versus-keyword usage.  Use a space after (most) keywords.  The
+notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
+somewhat like functions (and are usually used with parentheses in Linux,
+although they are not required in the language, as in: "sizeof info" after
+"struct fileinfo info;" is declared).
+
+So use a space after these keywords:
+       if, switch, case, for, do, while
+but not with sizeof, typeof, alignof, or __attribute__.  E.g.,
+       s = sizeof(struct file);
+
+Do not add spaces around (inside) parenthesized expressions.  This example is
+*bad*:
+
+       s = sizeof( struct file );
+
+When declaring pointer data or a function that returns a pointer type, the
+preferred use of '*' is adjacent to the data name or function name and not
+adjacent to the type name.  Examples:
+
+       char *linux_banner;
+       unsigned long long memparse(char *ptr, char **retptr);
+       char *match_strdup(substring_t *s);
+
+Use one space around (on each side of) most binary and ternary operators,
+such as any of these:
+
+       =  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+but no space after unary operators:
+       &  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+no space before the postfix increment & decrement unary operators:
+       ++  --
+
+no space after the prefix increment & decrement unary operators:
+       ++  --
+
+and no space around the '.' and "->" structure member operators.
+
 
                Chapter 4: Naming
 
@@ -152,7 +234,7 @@ variable that is used to hold a temporary value.
 
 If you are afraid to mix up your local variable names, you have another
 problem, which is called the function-growth-hormone-imbalance syndrome.
-See next chapter.
+See chapter 6 (Functions).
 
 
                Chapter 5: Typedefs
@@ -258,6 +340,20 @@ generally easily keep track of about 7 different things, anything more
 and it gets confused.  You know you're brilliant, but maybe you'd like
 to understand what you did 2 weeks from now.
 
+In source files, separate functions with one blank line.  If the function is
+exported, the EXPORT* macro for it should follow immediately after the closing
+function brace line.  E.g.:
+
+int system_is_up(void)
+{
+       return system_state == SYSTEM_RUNNING;
+}
+EXPORT_SYMBOL(system_is_up);
+
+In function prototypes, include parameter names with their data types.
+Although this is not required by the C language, it is preferred in Linux
+because it is a simple way to add valuable information for the reader.
+
 
                Chapter 7: Centralized exiting of functions
 
@@ -306,16 +402,36 @@ time to explain badly written code.
 Generally, you want your comments to tell WHAT your code does, not HOW.
 Also, try to avoid putting comments inside a function body: if the
 function is so complex that you need to separately comment parts of it,
-you should probably go back to chapter 5 for a while.  You can make
+you should probably go back to chapter 6 for a while.  You can make
 small comments to note or warn about something particularly clever (or
 ugly), but try to avoid excess.  Instead, put the comments at the head
 of the function, telling people what it does, and possibly WHY it does
 it.
 
-When commenting the kernel API functions, please use the kerneldoc format.
+When commenting the kernel API functions, please use the kernel-doc format.
 See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
 for details.
 
+Linux style for comments is the C89 "/* ... */" style.
+Don't use C99-style "// ..." comments.
+
+The preferred style for long (multi-line) comments is:
+
+       /*
+        * This is the preferred style for multi-line
+        * comments in the Linux kernel source code.
+        * Please use it consistently.
+        *
+        * Description:  A column of asterisks on the left side,
+        * with beginning and ending almost-blank lines.
+        */
+
+It's also important to comment data, whether they are basic types or derived
+types.  To this end, use just one data declaration per line (no commas for
+multiple data declarations).  This leaves you room for a small comment on each
+item, explaining its use.
+
+
                Chapter 9: You've made a mess of it
 
 That's OK, we all do.  You've probably been told by your long-time Unix
@@ -591,4 +707,4 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
 
 --
-Last updated on 30 April 2006.
+Last updated on 2006-December-06.
index 0543162..805db4b 100644 (file)
@@ -77,7 +77,7 @@ To get this part of the dma_ API, you must #include <linux/dmapool.h>
 Many drivers need lots of small dma-coherent memory regions for DMA
 descriptors or I/O buffers.  Rather than allocating in units of a page
 or more using dma_alloc_coherent(), you can use DMA pools.  These work
-much like a kmem_cache_t, except that they use the dma-coherent allocator
+much like a struct kmem_cache, except that they use the dma-coherent allocator
 not __get_free_pages().  Also, they understand common hardware constraints
 for alignment, like queue heads needing to be aligned on N byte boundaries.
 
@@ -94,7 +94,7 @@ The pool create() routines initialize a pool of dma-coherent buffers
 for use with a given device.  It must be called in a context which
 can sleep.
 
-The "name" is for diagnostics (like a kmem_cache_t name); dev and size
+The "name" is for diagnostics (like a struct kmem_cache name); dev and size
 are like what you'd pass to dma_alloc_coherent().  The device's hardware
 alignment requirement for this type of data is "align" (which is expressed
 in bytes, and must be a power of two).  If your device has no boundary
@@ -431,10 +431,10 @@ be identical to those passed in (and returned by
 dma_alloc_noncoherent()).
 
 int
-dma_is_consistent(dma_addr_t dma_handle)
+dma_is_consistent(struct device *dev, dma_addr_t dma_handle)
 
-returns true if the memory pointed to by the dma_handle is actually
-consistent.
+returns true if the device dev is performing consistent DMA on the memory
+area pointed to by the dma_handle.
 
 int
 dma_get_cache_alignment(void)
@@ -459,7 +459,7 @@ anything like this.  You must also be extra careful about accessing
 memory you intend to sync partially.
 
 void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 
 Do a partial sync of memory that was allocated by
index db9499a..36526a1 100644 (file)
@@ -190,9 +190,13 @@ quiet_cmd_fig2png = FIG2PNG $@
 ###
 # Help targets as used by the top-level makefile
 dochelp:
-       @echo  '  Linux kernel internal documentation in different formats:'
-       @echo  '  xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)'
-       @echo  '  htmldocs (HTML), mandocs (man pages, use installmandocs to install)'
+       @echo  ' Linux kernel internal documentation in different formats:'
+       @echo  '  htmldocs        - HTML'
+       @echo  '  installmandocs  - install man pages generated by mandocs'
+       @echo  '  mandocs         - man pages'
+       @echo  '  pdfdocs         - PDF'
+       @echo  '  psdocs          - Postscript'
+       @echo  '  xmldocs         - XML DocBook'
 
 ###
 # Temporary files left by various tools
index a166675..3fa0c4b 100644 (file)
@@ -418,9 +418,35 @@ X!Edrivers/pnp/system.c
 !Idrivers/parport/daisy.c
   </chapter>
 
-  <chapter id="viddev">
-     <title>Video4Linux</title>
-!Edrivers/media/video/videodev.c
+  <chapter id="message_devices">
+       <title>Message-based devices</title>
+     <sect1><title>Fusion message devices</title>
+!Edrivers/message/fusion/mptbase.c
+!Idrivers/message/fusion/mptbase.c
+!Edrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptctl.c
+!Idrivers/message/fusion/mptspi.c
+!Idrivers/message/fusion/mptfc.c
+!Idrivers/message/fusion/mptlan.c
+     </sect1>
+     <sect1><title>I2O message devices</title>
+!Iinclude/linux/i2o.h
+!Idrivers/message/i2o/core.h
+!Edrivers/message/i2o/iop.c
+!Idrivers/message/i2o/iop.c
+!Idrivers/message/i2o/config-osm.c
+!Edrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/bus-osm.c
+!Edrivers/message/i2o/device.c
+!Idrivers/message/i2o/device.c
+!Idrivers/message/i2o/driver.c
+!Idrivers/message/i2o/pci.c
+!Idrivers/message/i2o/i2o_block.c
+!Idrivers/message/i2o/i2o_scsi.c
+!Idrivers/message/i2o/i2o_proc.c
+     </sect1>
   </chapter>
 
   <chapter id="snddev">
@@ -533,4 +559,12 @@ X!Idrivers/video/console/fonts.c
 -->
      </sect1>
   </chapter>
+
+  <chapter id="input_subsystem">
+     <title>Input Subsystem</title>
+!Iinclude/linux/input.h
+!Edrivers/input/input.c
+!Edrivers/input/ff-core.c
+!Edrivers/input/ff-memless.c
+  </chapter>
 </book>
index 0e3924e..24dc3fc 100644 (file)
@@ -365,6 +365,7 @@ You can change this at module load time (for a module) with:
        regshifts=<shift1>,<shift2>,...
        slave_addrs=<addr1>,<addr2>,...
        force_kipmid=<enable1>,<enable2>,...
+       unload_when_empty=[0|1]
 
 Each of these except si_trydefaults is a list, the first item for the
 first interface, second item for the second interface, etc.
@@ -416,6 +417,11 @@ by the driver, but systems with broken interrupts might need an enable,
 or users that don't want the daemon (don't need the performance, don't
 want the CPU hit) can disable it.
 
+If unload_when_empty is set to 1, the driver will be unloaded if it
+doesn't find any interfaces or all the interfaces fail to work.  The
+default is one.  Setting to 0 is useful with the hotmod, but is
+obviously only useful for modules.
+
 When compiled into the kernel, the parameters can be specified on the
 kernel command line as:
 
@@ -441,6 +447,25 @@ have high-res timers enabled in the kernel and you don't have
 interrupts enabled, the driver will run VERY slowly.  Don't blame me,
 these interfaces suck.
 
+The driver supports a hot add and remove of interfaces.  This way,
+interfaces can be added or removed after the kernel is up and running.
+This is done using /sys/modules/ipmi_si/hotmod, which is a write-only
+parameter.  You write a string to this interface.  The string has the
+format:
+   <op1>[:op2[:op3...]]
+The "op"s are:
+   add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]
+You can specify more than one interface on the line.  The "opt"s are:
+   rsp=<regspacing>
+   rsi=<regsize>
+   rsh=<regshift>
+   irq=<irq>
+   ipmb=<ipmb slave addr>
+and these have the same meanings as discussed above.  Note that you
+can also use this on the kernel command line for a more compact format
+for specifying an interface.  Note that when removing an interface,
+only the first three parameters (si type, address type, and address)
+are used for the comparison.  Any options are ignored for removing.
 
 The SMBus Driver
 ----------------
@@ -502,7 +527,10 @@ used to control it:
 
   modprobe ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
       preaction=<preaction type> preop=<preop type> start_now=x
-      nowayout=x
+      nowayout=x ifnum_to_use=n
+
+ifnum_to_use specifies which interface the watchdog timer should use.
+The default is -1, which means to pick the first one registered.
 
 The timeout is the number of seconds to the action, and the pretimeout
 is the amount of seconds before the reset that the pre-timeout panic will
@@ -624,5 +652,9 @@ command line.  The parameter is also available via the proc filesystem
 in /proc/sys/dev/ipmi/poweroff_powercycle.  Note that if the system
 does not support power cycling, it will always do the power off.
 
+The "ifnum_to_use" parameter specifies which interface the poweroff
+code should use.  The default is -1, which means to pick the first one
+registered.
+
 Note that if you have ACPI enabled, the system will prefer using ACPI to
 power off.
index 7ac61f6..2270efa 100644 (file)
@@ -66,3 +66,9 @@ kernel patches.
     See Documentation/ABI/README for more information.
 
 20: Check that it all passes `make headers_check'.
+
+21: Has been checked with injection of at least slab and page-allocation
+    fauilures.  See Documentation/fault-injection/.
+
+    If the new code is substantial, addition of subsystem-specific fault
+    injection might be appropriate.
index bf2b0e2..e9126e7 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) Balbir Singh, IBM Corp. 2006
  * Copyright (c) Jay Lan, SGI. 2006
  *
+ * Compile with
+ *     gcc -I/usr/src/linux/include getdelays.c -o getdelays
  */
 
 #include <stdio.h>
 #define NLA_DATA(na)           ((void *)((char*)(na) + NLA_HDRLEN))
 #define NLA_PAYLOAD(len)       (len - NLA_HDRLEN)
 
-#define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0)
-int done = 0;
-int rcvbufsz=0;
-
-    char name[100];
-int dbg=0, print_delays=0;
+#define err(code, fmt, arg...)                 \
+       do {                                    \
+               fprintf(stderr, fmt, ##arg);    \
+               exit(code);                     \
+       } while (0)
+
+int done;
+int rcvbufsz;
+char name[100];
+int dbg;
+int print_delays;
+int print_io_accounting;
 __u64 stime, utime;
+
 #define PRINTF(fmt, arg...) {                  \
            if (dbg) {                          \
                printf(fmt, ##arg);             \
@@ -78,8 +87,9 @@ static int create_nl_socket(int protocol)
        if (rcvbufsz)
                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
                                &rcvbufsz, sizeof(rcvbufsz)) < 0) {
-                       printf("Unable to set socket rcv buf size to %d\n",
-                              rcvbufsz);
+                       fprintf(stderr, "Unable to set socket rcv buf size "
+                                       "to %d\n",
+                               rcvbufsz);
                        return -1;
                }
 
@@ -186,6 +196,15 @@ void print_delayacct(struct taskstats *t)
               "count", "delay total", t->swapin_count, t->swapin_delay_total);
 }
 
+void print_ioacct(struct taskstats *t)
+{
+       printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
+               t->ac_comm,
+               (unsigned long long)t->read_bytes,
+               (unsigned long long)t->write_bytes,
+               (unsigned long long)t->cancelled_write_bytes);
+}
+
 int main(int argc, char *argv[])
 {
        int c, rc, rep_len, aggr_len, len2, cmd_type;
@@ -208,7 +227,7 @@ int main(int argc, char *argv[])
        struct msgtemplate msg;
 
        while (1) {
-               c = getopt(argc, argv, "dw:r:m:t:p:v:l");
+               c = getopt(argc, argv, "diw:r:m:t:p:v:l");
                if (c < 0)
                        break;
 
@@ -217,6 +236,10 @@ int main(int argc, char *argv[])
                        printf("print delayacct stats ON\n");
                        print_delays = 1;
                        break;
+               case 'i':
+                       printf("printing IO accounting\n");
+                       print_io_accounting = 1;
+                       break;
                case 'w':
                        strncpy(logfile, optarg, MAX_FILENAME);
                        printf("write to file %s\n", logfile);
@@ -238,14 +261,12 @@ int main(int argc, char *argv[])
                        if (!tid)
                                err(1, "Invalid tgid\n");
                        cmd_type = TASKSTATS_CMD_ATTR_TGID;
-                       print_delays = 1;
                        break;
                case 'p':
                        tid = atoi(optarg);
                        if (!tid)
                                err(1, "Invalid pid\n");
                        cmd_type = TASKSTATS_CMD_ATTR_PID;
-                       print_delays = 1;
                        break;
                case 'v':
                        printf("debug on\n");
@@ -277,7 +298,7 @@ int main(int argc, char *argv[])
        mypid = getpid();
        id = get_family_id(nl_sd);
        if (!id) {
-               printf("Error getting family id, errno %d", errno);
+               fprintf(stderr, "Error getting family id, errno %d\n", errno);
                goto err;
        }
        PRINTF("family id %d\n", id);
@@ -288,7 +309,7 @@ int main(int argc, char *argv[])
                              &cpumask, strlen(cpumask) + 1);
                PRINTF("Sent register cpumask, retval %d\n", rc);
                if (rc < 0) {
-                       printf("error sending register cpumask\n");
+                       fprintf(stderr, "error sending register cpumask\n");
                        goto err;
                }
        }
@@ -298,7 +319,7 @@ int main(int argc, char *argv[])
                              cmd_type, &tid, sizeof(__u32));
                PRINTF("Sent pid/tgid, retval %d\n", rc);
                if (rc < 0) {
-                       printf("error sending tid/tgid cmd\n");
+                       fprintf(stderr, "error sending tid/tgid cmd\n");
                        goto done;
                }
        }
@@ -310,13 +331,15 @@ int main(int argc, char *argv[])
                PRINTF("received %d bytes\n", rep_len);
 
                if (rep_len < 0) {
-                       printf("nonfatal reply error: errno %d\n", errno);
+                       fprintf(stderr, "nonfatal reply error: errno %d\n",
+                               errno);
                        continue;
                }
                if (msg.n.nlmsg_type == NLMSG_ERROR ||
                    !NLMSG_OK((&msg.n), rep_len)) {
                        struct nlmsgerr *err = NLMSG_DATA(&msg);
-                       printf("fatal reply error,  errno %d\n", err->error);
+                       fprintf(stderr, "fatal reply error,  errno %d\n",
+                               err->error);
                        goto done;
                }
 
@@ -356,6 +379,8 @@ int main(int argc, char *argv[])
                                                count++;
                                                if (print_delays)
                                                        print_delayacct((struct taskstats *) NLA_DATA(na));
+                                               if (print_io_accounting)
+                                                       print_ioacct((struct taskstats *) NLA_DATA(na));
                                                if (fd) {
                                                        if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
                                                                err(1,"write error\n");
@@ -365,7 +390,9 @@ int main(int argc, char *argv[])
                                                        goto done;
                                                break;
                                        default:
-                                               printf("Unknown nested nla_type %d\n", na->nla_type);
+                                               fprintf(stderr, "Unknown nested"
+                                                       " nla_type %d\n",
+                                                       na->nla_type);
                                                break;
                                        }
                                        len2 += NLA_ALIGN(na->nla_len);
@@ -374,7 +401,8 @@ int main(int argc, char *argv[])
                                break;
 
                        default:
-                               printf("Unknown nla_type %d\n", na->nla_type);
+                               fprintf(stderr, "Unknown nla_type %d\n",
+                                       na->nla_type);
                                break;
                        }
                        na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
index e2a66f8..a598fe1 100644 (file)
@@ -24,8 +24,10 @@ very similar behavior to the deadline IO scheduler.
 Selecting IO schedulers
 -----------------------
 To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop' and 'as' (the default) are also available. IO schedulers are assigned
-globally at boot time only presently.
+'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
+assigned globally at boot time only presently. It's also possible to change
+the IO scheduler for a determined device on the fly, as described in
+Documentation/block/switching-sched.txt.
 
 
 Anticipatory IO scheduler Policies
index 3d44c56..7715d22 100644 (file)
@@ -90,6 +90,41 @@ Notes
   to create an ext2 filesystem on the disc.
 
 
+Using the pktcdvd sysfs interface
+---------------------------------
+
+Since Linux 2.6.19, the pktcdvd module has a sysfs interface
+and can be controlled by it. For example the "pktcdvd" tool uses
+this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
+
+"pktcdvd" works similar to "pktsetup", e.g.:
+
+       # pktcdvd -a dev_name /dev/hdc
+       # mkudffs /dev/pktcdvd/dev_name
+       # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram
+       # cp files /dvdram
+       # umount /dvdram
+       # pktcdvd -r dev_name
+
+
+For a description of the sysfs interface look into the file:
+
+  Documentation/ABI/testing/sysfs-block-pktcdvd
+
+
+Using the pktcdvd debugfs interface
+-----------------------------------
+
+To read pktcdvd device infos in human readable form, do:
+
+       # cat /debug/pktcdvd/pktcdvd[0-7]/info
+
+For a description of the debugfs interface look into the file:
+
+  Documentation/ABI/testing/debugfs-pktcdvd
+
+
+
 Links
 -----
 
index 70690f1..8de132a 100644 (file)
@@ -3,7 +3,7 @@
 
             Maintained by Torben Mathiasen <device@lanana.org>
 
-                     Last revised: 15 May 2006
+                     Last revised: 29 November 2006
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -94,6 +94,7 @@ Your cooperation is appreciated.
                  9 = /dev/urandom      Faster, less secure random number gen.
                 10 = /dev/aio          Asynchronous I/O notification interface
                 11 = /dev/kmsg         Writes to this come out as printk's
+
   1 block      RAM disk
                  0 = /dev/ram0         First RAM disk
                  1 = /dev/ram1         Second RAM disk
@@ -122,7 +123,7 @@ Your cooperation is appreciated.
                devices are on major 128 and above and use the PTY
                master multiplex (/dev/ptmx) to acquire a PTY on
                demand.
-  
+
   2 block      Floppy disks
                  0 = /dev/fd0          Controller 0, drive 0, autodetect
                  1 = /dev/fd1          Controller 0, drive 1, autodetect
@@ -257,7 +258,7 @@ Your cooperation is appreciated.
                129 = /dev/vcsa1        tty1 text/attribute contents
                    ...
                191 = /dev/vcsa63       tty63 text/attribute contents
-       
+
                NOTE: These devices permit both read and write access.
 
   7 block      Loopback devices
@@ -411,7 +412,7 @@ Your cooperation is appreciated.
                207 = /dev/video/em8300_sp      EM8300 DVD decoder subpicture
                208 = /dev/compaq/cpqphpc       Compaq PCI Hot Plug Controller
                209 = /dev/compaq/cpqrid        Compaq Remote Insight Driver
-               210 = /dev/impi/bt      IMPI coprocessor block transfer 
+               210 = /dev/impi/bt      IMPI coprocessor block transfer
                211 = /dev/impi/smic    IMPI coprocessor stream interface
                212 = /dev/watchdogs/0  First watchdog device
                213 = /dev/watchdogs/1  Second watchdog device
@@ -506,6 +507,7 @@ Your cooperation is appreciated.
                 33 = /dev/patmgr1      Sequencer patch manager
                 34 = /dev/midi02       Third MIDI port
                 50 = /dev/midi03       Fourth MIDI port
+
  14 block      BIOS harddrive callback support {2.6}
                  0 = /dev/dos_hda      First BIOS harddrive whole disk
                 64 = /dev/dos_hdb      Second BIOS harddrive whole disk
@@ -527,6 +529,7 @@ Your cooperation is appreciated.
 
  16 char       Non-SCSI scanners
                  0 = /dev/gs4500       Genius 4500 handheld scanner
+
  16 block      GoldStar CD-ROM
                  0 = /dev/gscd         GoldStar CD-ROM
 
@@ -548,6 +551,7 @@ Your cooperation is appreciated.
                  0 = /dev/ttyC0        First Cyclades port
                    ...
                 31 = /dev/ttyC31       32nd Cyclades port
+
  19 block      "Double" compressed disk
                  0 = /dev/double0      First compressed disk
                    ...
@@ -563,6 +567,7 @@ Your cooperation is appreciated.
                  0 = /dev/cub0         Callout device for ttyC0
                    ...
                 31 = /dev/cub31        Callout device for ttyC31
+
  20 block      Hitachi CD-ROM (under development)
                  0 = /dev/hitcd        Hitachi CD-ROM
 
@@ -582,7 +587,7 @@ Your cooperation is appreciated.
 
                This device is used on the ARM-based Acorn RiscPC.
                Partitions are handled the same way as for IDE disks
-               (see major number 3). 
+               (see major number 3).
 
  22 char       Digiboard serial card
                  0 = /dev/ttyD0        First Digiboard port
@@ -591,7 +596,7 @@ Your cooperation is appreciated.
  22 block      Second IDE hard disk/CD-ROM interface
                  0 = /dev/hdc          Master: whole disk (or CD-ROM)
                 64 = /dev/hdd          Slave: whole disk (or CD-ROM)
-               
+
                Partitions are handled the same way as for the first
                interface (see major number 3).
 
@@ -639,6 +644,7 @@ Your cooperation is appreciated.
 
  26 char       Quanta WinVision frame grabber {2.6}
                  0 = /dev/wvisfgrab    Quanta WinVision frame grabber
+
  26 block      Second Matsushita (Panasonic/SoundBlaster) CD-ROM
                  0 = /dev/sbpcd4       Panasonic CD-ROM controller 1 unit 0
                  1 = /dev/sbpcd5       Panasonic CD-ROM controller 1 unit 1
@@ -670,6 +676,7 @@ Your cooperation is appreciated.
                 37 = /dev/nrawqft1     Unit 1, no rewind-on-close, no file marks
                 38 = /dev/nrawqft2     Unit 2, no rewind-on-close, no file marks
                 39 = /dev/nrawqft3     Unit 3, no rewind-on-close, no file marks
+
  27 block      Third Matsushita (Panasonic/SoundBlaster) CD-ROM
                  0 = /dev/sbpcd8       Panasonic CD-ROM controller 2 unit 0
                  1 = /dev/sbpcd9       Panasonic CD-ROM controller 2 unit 1
@@ -681,6 +688,7 @@ Your cooperation is appreciated.
                  1 = /dev/staliomem1   Second Stallion card I/O memory
                  2 = /dev/staliomem2   Third Stallion card I/O memory
                  3 = /dev/staliomem3   Fourth Stallion card I/O memory
+
  28 char       Atari SLM ACSI laser printer (68k/Atari)
                  0 = /dev/slm0         First SLM laser printer
                  1 = /dev/slm1         Second SLM laser printer
@@ -690,6 +698,7 @@ Your cooperation is appreciated.
                  1 = /dev/sbpcd13      Panasonic CD-ROM controller 3 unit 1
                  2 = /dev/sbpcd14      Panasonic CD-ROM controller 3 unit 2
                  3 = /dev/sbpcd15      Panasonic CD-ROM controller 3 unit 3
+
  28 block      ACSI disk (68k/Atari)
                  0 = /dev/ada          First ACSI disk whole disk
                 16 = /dev/adb          Second ACSI disk whole disk
@@ -750,6 +759,7 @@ Your cooperation is appreciated.
  31 char       MPU-401 MIDI
                  0 = /dev/mpu401data   MPU-401 data port
                  1 = /dev/mpu401stat   MPU-401 status port
+
  31 block      ROM/flash memory card
                  0 = /dev/rom0         First ROM card (rw)
                      ...
@@ -801,7 +811,7 @@ Your cooperation is appreciated.
  34 block      Fourth IDE hard disk/CD-ROM interface
                  0 = /dev/hdg          Master: whole disk (or CD-ROM)
                 64 = /dev/hdh          Slave: whole disk (or CD-ROM)
-               
+
                Partitions are handled the same way as for the first
                interface (see major number 3).
 
@@ -818,6 +828,7 @@ Your cooperation is appreciated.
                129 = /dev/smpte1       Second MIDI port, SMPTE timed
                130 = /dev/smpte2       Third MIDI port, SMPTE timed
                131 = /dev/smpte3       Fourth MIDI port, SMPTE timed
+
  35 block      Slow memory ramdisk
                  0 = /dev/slram        Slow memory ramdisk
 
@@ -828,6 +839,7 @@ Your cooperation is appreciated.
                 16 = /dev/tap0         First Ethertap device
                    ...
                 31 = /dev/tap15        16th Ethertap device
+
  36 block      MCA ESDI hard disk
                  0 = /dev/eda          First ESDI disk whole disk
                 64 = /dev/edb          Second ESDI disk whole disk
@@ -882,6 +894,7 @@ Your cooperation is appreciated.
 
  40 char       Matrox Meteor frame grabber {2.6}
                  0 = /dev/mmetfgrab    Matrox Meteor frame grabber
+
  40 block      Syquest EZ135 parallel port removable drive
                  0 = /dev/eza          Parallel EZ135 drive, whole disk
 
@@ -893,6 +906,7 @@ Your cooperation is appreciated.
 
  41 char       Yet Another Micro Monitor
                  0 = /dev/yamm         Yet Another Micro Monitor
+
  41 block      MicroSolutions BackPack parallel port CD-ROM
                  0 = /dev/bpcd         BackPack CD-ROM
 
@@ -901,6 +915,7 @@ Your cooperation is appreciated.
                the parallel port ATAPI CD-ROM driver at major number 46.
 
  42 char       Demo/sample use
+
  42 block      Demo/sample use
 
                This number is intended for use in sample code, as
@@ -918,6 +933,7 @@ Your cooperation is appreciated.
                  0 = /dev/ttyI0        First virtual modem
                    ...
                 63 = /dev/ttyI63       64th virtual modem
+
  43 block      Network block devices
                  0 = /dev/nb0          First network block device
                  1 = /dev/nb1          Second network block device
@@ -934,12 +950,13 @@ Your cooperation is appreciated.
                  0 = /dev/cui0         Callout device for ttyI0
                    ...
                 63 = /dev/cui63        Callout device for ttyI63
+
  44 block      Flash Translation Layer (FTL) filesystems
                  0 = /dev/ftla         FTL on first Memory Technology Device
                 16 = /dev/ftlb         FTL on second Memory Technology Device
                 32 = /dev/ftlc         FTL on third Memory Technology Device
                    ...
-               240 = /dev/ftlp         FTL on 16th Memory Technology Device 
+               240 = /dev/ftlp         FTL on 16th Memory Technology Device
 
                Partitions are handled in the same way as for IDE
                disks (see major number 3) except that the partition
@@ -958,6 +975,7 @@ Your cooperation is appreciated.
                191 = /dev/ippp63       64th SyncPPP device
 
                255 = /dev/isdninfo     ISDN monitor interface
+
  45 block      Parallel port IDE disk devices
                  0 = /dev/pda          First parallel port IDE disk
                 16 = /dev/pdb          Second parallel port IDE disk
@@ -1044,6 +1062,7 @@ Your cooperation is appreciated.
                  1 = /dev/dcbri1       Second DataComm card
                  2 = /dev/dcbri2       Third DataComm card
                  3 = /dev/dcbri3       Fourth DataComm card
+
  52 block      Mylex DAC960 PCI RAID controller; fifth controller
                  0 = /dev/rd/c4d0      First disk, whole disk
                  8 = /dev/rd/c4d1      Second disk, whole disk
@@ -1093,6 +1112,7 @@ Your cooperation is appreciated.
 
  55 char       DSP56001 digital signal processor
                  0 = /dev/dsp56k       First DSP56001
+
  55 block      Mylex DAC960 PCI RAID controller; eighth controller
                  0 = /dev/rd/c7d0      First disk, whole disk
                  8 = /dev/rd/c7d1      Second disk, whole disk
@@ -1130,6 +1150,7 @@ Your cooperation is appreciated.
                  0 = /dev/cup0         Callout device for ttyP0
                  1 = /dev/cup1         Callout device for ttyP1
                    ...
+
  58 block      Reserved for logical volume manager
 
  59 char       sf firewall package
@@ -1149,6 +1170,7 @@ Your cooperation is appreciated.
                NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc
 
  60-63 char    LOCAL/EXPERIMENTAL USE
+
  60-63 block   LOCAL/EXPERIMENTAL USE
                Allocated for local/experimental use.  For devices not
                assigned official numbers, these ranges should be
@@ -1434,7 +1456,6 @@ Your cooperation is appreciated.
                DAC960 (see major number 48) except that the limit on
                partitions is 15.
 
-
  78 char       PAM Software's multimodem boards
                  0 = /dev/ttyM0        First PAM modem
                  1 = /dev/ttyM1        Second PAM modem
@@ -1450,7 +1471,6 @@ Your cooperation is appreciated.
                DAC960 (see major number 48) except that the limit on
                partitions is 15.
 
-
  79 char       PAM Software's multimodem boards - alternate devices
                  0 = /dev/cum0         Callout device for ttyM0
                  1 = /dev/cum1         Callout device for ttyM1
@@ -1466,7 +1486,6 @@ Your cooperation is appreciated.
                DAC960 (see major number 48) except that the limit on
                partitions is 15.
 
-
  80 char       Photometrics AT200 CCD camera
                  0 = /dev/at200        Photometrics AT200 CCD camera
 
@@ -1679,7 +1698,7 @@ Your cooperation is appreciated.
                  1 = /dev/dcxx1        Second capture card
                    ...
 
- 94 block IBM S/390 DASD block storage
+ 94 block      IBM S/390 DASD block storage
                  0 = /dev/dasda First DASD device, major
                  1 = /dev/dasda1 First DASD device, block 1
                  2 = /dev/dasda2 First DASD device, block 2
@@ -1695,7 +1714,7 @@ Your cooperation is appreciated.
                  1 = /dev/ipnat        NAT control device/log file
                  2 = /dev/ipstate      State information log file
                  3 = /dev/ipauth       Authentication control device/log file
-                   ...         
+                   ...
 
  96 char       Parallel port ATAPI tape devices
                  0 = /dev/pt0          First parallel port ATAPI tape
@@ -1705,7 +1724,7 @@ Your cooperation is appreciated.
                129 = /dev/npt1         Second p.p. ATAPI tape, no rewind
                    ...
 
- 96 block Inverse NAND Flash Translation Layer
+ 96 block      Inverse NAND Flash Translation Layer
                  0 = /dev/inftla First INFTL layer
                 16 = /dev/inftlb Second INFTL layer
                    ...
@@ -1937,7 +1956,6 @@ Your cooperation is appreciated.
                    ...
 
 113 block      IBM iSeries virtual CD-ROM
-
                  0 = /dev/iseries/vcda First virtual CD-ROM
                  1 = /dev/iseries/vcdb Second virtual CD-ROM
                    ...
@@ -2059,11 +2077,12 @@ Your cooperation is appreciated.
                    ...
 
 119 char       VMware virtual network control
-                 0 = /dev/vnet0        1st virtual network
-                 1 = /dev/vnet1        2nd virtual network
+                 0 = /dev/vmnet0       1st virtual network
+                 1 = /dev/vmnet1       2nd virtual network
                    ...
 
 120-127 char   LOCAL/EXPERIMENTAL USE
+
 120-127 block  LOCAL/EXPERIMENTAL USE
                Allocated for local/experimental use.  For devices not
                assigned official numbers, these ranges should be
@@ -2075,7 +2094,6 @@ Your cooperation is appreciated.
                nodes; instead they should be accessed through the
                /dev/ptmx cloning interface.
 
-
 128 block       SCSI disk devices (128-143)
                   0 = /dev/sddy         129th SCSI disk whole disk
                  16 = /dev/sddz         130th SCSI disk whole disk
@@ -2087,7 +2105,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 129 block       SCSI disk devices (144-159)
                   0 = /dev/sdeo         145th SCSI disk whole disk
                  16 = /dev/sdep         146th SCSI disk whole disk
@@ -2123,7 +2140,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 132 block       SCSI disk devices (192-207)
                   0 = /dev/sdgk         193rd SCSI disk whole disk
                  16 = /dev/sdgl         194th SCSI disk whole disk
@@ -2135,7 +2151,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 133 block       SCSI disk devices (208-223)
                   0 = /dev/sdha         209th SCSI disk whole disk
                  16 = /dev/sdhb         210th SCSI disk whole disk
@@ -2147,7 +2162,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 134 block       SCSI disk devices (224-239)
                   0 = /dev/sdhq         225th SCSI disk whole disk
                  16 = /dev/sdhr         226th SCSI disk whole disk
@@ -2159,7 +2173,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 135 block       SCSI disk devices (240-255)
                   0 = /dev/sdig         241st SCSI disk whole disk
                  16 = /dev/sdih         242nd SCSI disk whole disk
@@ -2171,7 +2184,6 @@ Your cooperation is appreciated.
                disks (see major number 3) except that the limit on
                partitions is 15.
 
-
 136-143 char   Unix98 PTY slaves
                  0 = /dev/pts/0        First Unix98 pseudo-TTY
                  1 = /dev/pts/1        Second Unix98 pesudo-TTY
@@ -2384,6 +2396,7 @@ Your cooperation is appreciated.
                    ...
 
 159 char       RESERVED
+
 159 block      RESERVED
 
 160 char       General Purpose Instrument Bus (GPIB)
@@ -2427,7 +2440,7 @@ Your cooperation is appreciated.
 
                Partitions are handled in the same way as for IDE
                disks (see major number 3) except that the limit on
-               partitions is 31. 
+               partitions is 31.
 
 162 char       Raw block device interface
                  0 = /dev/rawctl       Raw I/O control device
@@ -2483,7 +2496,6 @@ Your cooperation is appreciated.
 
 171 char       Reserved for IEEE 1394 (Firewire)
 
-
 172 char       Moxa Intellio serial card
                  0 = /dev/ttyMX0       First Moxa port
                  1 = /dev/ttyMX1       Second Moxa port
@@ -2543,9 +2555,6 @@ 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
@@ -2558,7 +2567,7 @@ Your cooperation is appreciated.
                132 = /dev/usb/idmouse  ID Mouse (fingerprint scanner) device
                133 = /dev/usb/sisusbvga1       First SiSUSB VGA device
                    ...
-               140 = /dev/usb/sisusbvga8       Eigth SISUSB VGA device
+               140 = /dev/usb/sisusbvga8       Eighth SISUSB VGA device
                144 = /dev/usb/lcd      USB LCD device
                160 = /dev/usb/legousbtower0    1st USB Legotower device
                    ...
@@ -2571,7 +2580,7 @@ Your cooperation is appreciated.
                  0 = /dev/uba          First USB block device
                  8 = /dev/ubb          Second USB block device
                 16 = /dev/ubc          Third USB block device
-                   ...
+                   ...
 
 181 char       Conrad Electronic parallel port radio clocks
                  0 = /dev/pcfclock0    First Conrad radio clock
@@ -2657,7 +2666,7 @@ Your cooperation is appreciated.
                 32 = /dev/mvideo/status2       Third device
                    ...
                    ...
-               240 = /dev/mvideo/status15      16th device 
+               240 = /dev/mvideo/status15      16th device
                    ...
 
 195 char       Nvidia graphics devices
@@ -2795,6 +2804,10 @@ Your cooperation is appreciated.
                    ...
                 185 = /dev/ttyNX15             Hilscher netX serial port 15
                 186 = /dev/ttyJ0               JTAG1 DCC protocol based serial port emulation
+                187 = /dev/ttyUL0              Xilinx uartlite - port 0
+                   ...
+                190 = /dev/ttyUL3              Xilinx uartlite - port 3
+                191 = /dev/xvc0                Xen virtual console - port 0
 
 205 char       Low-density serial ports (alternate device)
                  0 = /dev/culu0                Callout device for ttyLU0
@@ -2832,7 +2845,6 @@ Your cooperation is appreciated.
                 82 = /dev/cuvr0                Callout device for ttyVR0
                 83 = /dev/cuvr1                Callout device for ttyVR1
 
-
 206 char       OnStream SC-x0 tape devices
                  0 = /dev/osst0                First OnStream SCSI tape, mode 0
                  1 = /dev/osst1                Second OnStream SCSI tape, mode 0
@@ -2922,7 +2934,6 @@ Your cooperation is appreciated.
                    ...
 
 212 char       LinuxTV.org DVB driver subsystem
-
                  0 = /dev/dvb/adapter0/video0    first video decoder of first card
                  1 = /dev/dvb/adapter0/audio0    first audio decoder of first card
                  2 = /dev/dvb/adapter0/sec0      (obsolete/unused)
@@ -3008,9 +3019,9 @@ Your cooperation is appreciated.
                  2 = /dev/3270/tub2            Second 3270 terminal
                    ...
 
-229 char       IBM iSeries virtual console
-                 0 = /dev/iseries/vtty0        First console port
-                 1 = /dev/iseries/vtty1        Second console port
+229 char       IBM iSeries/pSeries virtual console
+                 0 = /dev/hvc0                 First console port
+                 1 = /dev/hvc1                 Second console port
                    ...
 
 230 char       IBM iSeries virtual tape
@@ -3083,12 +3094,14 @@ Your cooperation is appreciated.
 234-239                UNASSIGNED
 
 240-254 char   LOCAL/EXPERIMENTAL USE
+
 240-254 block  LOCAL/EXPERIMENTAL USE
                Allocated for local/experimental use.  For devices not
                assigned official numbers, these ranges should be
                used in order to avoid conflicting with future assignments.
 
 255 char       RESERVED
+
 255 block      RESERVED
 
                This major is reserved to assist the expansion to a
@@ -3115,7 +3128,20 @@ Your cooperation is appreciated.
 257 char       Phoenix Technologies Cryptographic Services Driver
                  0 = /dev/ptlsec       Crypto Services Driver
 
-
+257 block      SSFDC Flash Translation Layer filesystem
+                 0 = /dev/ssfdca       First SSFDC layer
+                 8 = /dev/ssfdcb       Second SSFDC layer
+                16 = /dev/ssfdcc       Third SSFDC layer
+                24 = /dev/ssfdcd       4th SSFDC layer
+                32 = /dev/ssfdce       5th SSFDC layer
+                40 = /dev/ssfdcf       6th SSFDC layer
+                48 = /dev/ssfdcg       7th SSFDC layer
+                56 = /dev/ssfdch       8th SSFDC layer
+
+258 block      ROM/Flash read-only translation layer
+                 0 = /dev/blockrom0    First ROM card's translation layer interface
+                 1 = /dev/blockrom1    Second ROM card's translation layer interface
+                 ...
 
  ****  ADDITIONAL /dev DIRECTORY ENTRIES
 
index ca58e33..cc09187 100644 (file)
@@ -22,10 +22,10 @@ o Frontends drivers:
    - ves1x93           : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993)
    - cx24110           : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL)
    - grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
-   - mt312             : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
+   - mt312             : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3
    - stv0299           : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
                          LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
-                         Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB
+                         Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6
   DVB-C:
    - ves1820           : various (ves1820 demodulator, sp5659c or spXXXX PLL)
    - at76c651          : Atmel AT76c651(B) with DAT7021 PLL
diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh
new file mode 100644 (file)
index 0000000..63177ab
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo 1 > /proc/self/make-it-fail
+exec $*
diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh
new file mode 100644 (file)
index 0000000..474a8b9
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+#
+# Usage: failmodule <failname> <modulename> [stacktrace-depth]
+#
+#      <failname>: "failslab", "fail_alloc_page", or "fail_make_request"
+#
+#      <modulename>: module name that you want to inject faults.
+#
+#      [stacktrace-depth]: the maximum number of stacktrace walking allowed
+#
+
+STACKTRACE_DEPTH=5
+if [ $# -gt 2 ]; then
+       STACKTRACE_DEPTH=$3
+fi
+
+if [ ! -d /debug/$1 ]; then
+       echo "Fault-injection $1 does not exist" >&2
+       exit 1
+fi
+if [ ! -d /sys/module/$2 ]; then
+       echo "Module $2 does not exist" >&2
+       exit 1
+fi
+
+# Disable any fault injection
+echo 0 > /debug/$1/stacktrace-depth
+
+echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start
+echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end
+echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
new file mode 100644 (file)
index 0000000..b7ca560
--- /dev/null
@@ -0,0 +1,225 @@
+Fault injection capabilities infrastructure
+===========================================
+
+See also drivers/md/faulty.c and "every_nth" module option for scsi_debug.
+
+
+Available fault injection capabilities
+--------------------------------------
+
+o failslab
+
+  injects slab allocation failures. (kmalloc(), kmem_cache_alloc(), ...)
+
+o fail_page_alloc
+
+  injects page allocation failures. (alloc_pages(), get_free_pages(), ...)
+
+o fail_make_request
+
+  injects disk IO errors on devices permitted by setting
+  /sys/block/<device>/make-it-fail or
+  /sys/block/<device>/<partition>/make-it-fail. (generic_make_request())
+
+Configure fault-injection capabilities behavior
+-----------------------------------------------
+
+o debugfs entries
+
+fault-inject-debugfs kernel module provides some debugfs entries for runtime
+configuration of fault-injection capabilities.
+
+- /debug/fail*/probability:
+
+       likelihood of failure injection, in percent.
+       Format: <percent>
+
+       Note that one-failure-per-hundred is a very high error rate
+       for some testcases.  Consider setting probability=100 and configure
+       /debug/fail*/interval for such testcases.
+
+- /debug/fail*/interval:
+
+       specifies the interval between failures, for calls to
+       should_fail() that pass all the other tests.
+
+       Note that if you enable this, by setting interval>1, you will
+       probably want to set probability=100.
+
+- /debug/fail*/times:
+
+       specifies how many times failures may happen at most.
+       A value of -1 means "no limit".
+
+- /debug/fail*/space:
+
+       specifies an initial resource "budget", decremented by "size"
+       on each call to should_fail(,size).  Failure injection is
+       suppressed until "space" reaches zero.
+
+- /debug/fail*/verbose
+
+       Format: { 0 | 1 | 2 }
+       specifies the verbosity of the messages when failure is
+       injected.  '0' means no messages; '1' will print only a single
+       log line per failure; '2' will print a call trace too -- useful
+       to debug the problems revealed by fault injection.
+
+- /debug/fail*/task-filter:
+
+       Format: { 'Y' | 'N' }
+       A value of 'N' disables filtering by process (default).
+       Any positive value limits failures to only processes indicated by
+       /proc/<pid>/make-it-fail==1.
+
+- /debug/fail*/require-start:
+- /debug/fail*/require-end:
+- /debug/fail*/reject-start:
+- /debug/fail*/reject-end:
+
+       specifies the range of virtual addresses tested during
+       stacktrace walking.  Failure is injected only if some caller
+       in the walked stacktrace lies within the required range, and
+       none lies within the rejected range.
+       Default required range is [0,ULONG_MAX) (whole of virtual address space).
+       Default rejected range is [0,0).
+
+- /debug/fail*/stacktrace-depth:
+
+       specifies the maximum stacktrace depth walked during search
+       for a caller within [require-start,require-end) OR
+       [reject-start,reject-end).
+
+- /debug/fail_page_alloc/ignore-gfp-highmem:
+
+       Format: { 'Y' | 'N' }
+       default is 'N', setting it to 'Y' won't inject failures into
+       highmem/user allocations.
+
+- /debug/failslab/ignore-gfp-wait:
+- /debug/fail_page_alloc/ignore-gfp-wait:
+
+       Format: { 'Y' | 'N' }
+       default is 'N', setting it to 'Y' will inject failures
+       only into non-sleep allocations (GFP_ATOMIC allocations).
+
+o Boot option
+
+In order to inject faults while debugfs is not available (early boot time),
+use the boot option:
+
+       failslab=
+       fail_page_alloc=
+       fail_make_request=<interval>,<probability>,<space>,<times>
+
+How to add new fault injection capability
+-----------------------------------------
+
+o #include <linux/fault-inject.h>
+
+o define the fault attributes
+
+  DECLARE_FAULT_INJECTION(name);
+
+  Please see the definition of struct fault_attr in fault-inject.h
+  for details.
+
+o provide a way to configure fault attributes
+
+- boot option
+
+  If you need to enable the fault injection capability from boot time, you can
+  provide boot option to configure it. There is a helper function for it:
+
+       setup_fault_attr(attr, str);
+
+- debugfs entries
+
+  failslab, fail_page_alloc, and fail_make_request use this way.
+  Helper functions:
+
+       init_fault_attr_entries(entries, attr, name);
+       void cleanup_fault_attr_entries(entries);
+
+- module parameters
+
+  If the scope of the fault injection capability is limited to a
+  single kernel module, it is better to provide module parameters to
+  configure the fault attributes.
+
+o add a hook to insert failures
+
+  Upon should_fail() returning true, client code should inject a failure.
+
+       should_fail(attr, size);
+
+Application Examples
+--------------------
+
+o inject slab allocation failures into module init/cleanup code
+
+------------------------------------------------------------------------------
+#!/bin/bash
+
+FAILCMD=Documentation/fault-injection/failcmd.sh
+BLACKLIST="root_plug evbug"
+
+FAILNAME=failslab
+echo Y > /debug/$FAILNAME/task-filter
+echo 10 > /debug/$FAILNAME/probability
+echo 100 > /debug/$FAILNAME/interval
+echo -1 > /debug/$FAILNAME/times
+echo 2 > /debug/$FAILNAME/verbose
+echo 1 > /debug/$FAILNAME/ignore-gfp-wait
+
+blacklist()
+{
+       echo $BLACKLIST | grep $1 > /dev/null 2>&1
+}
+
+oops()
+{
+       dmesg | grep BUG > /dev/null 2>&1
+}
+
+find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; |
+       while read i
+       do
+               oops && exit 1
+
+               if ! blacklist $i
+               then
+                       echo inserting $i...
+                       bash $FAILCMD modprobe $i
+               fi
+       done
+
+lsmod | awk '{ if ($3 == 0) { print $1 } }' |
+       while read i
+       do
+               oops && exit 1
+
+               if ! blacklist $i
+               then
+                       echo removing $i...
+                       bash $FAILCMD modprobe -r $i
+               fi
+       done
+
+------------------------------------------------------------------------------
+
+o inject slab allocation failures only for a specific module
+
+------------------------------------------------------------------------------
+#!/bin/bash
+
+FAILMOD=Documentation/fault-injection/failmodule.sh
+
+echo injecting errors into the module $1...
+
+modprobe $1
+bash $FAILMOD failslab $1 10
+echo 25 > /debug/failslab/probability
+
+------------------------------------------------------------------------------
+
index 226ecf2..46f2a55 100644 (file)
@@ -30,11 +30,39 @@ Who:        Adrian Bunk <bunk@stusta.de>
 ---------------------------
 
 What:  raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When:  November 2006
-Why:   Deprecated in favour of the new ioctl-based rawiso interface, which is
-       more efficient.  You should really be using libraw1394 for raw1394
-       access anyway.
-Who:   Jody McIntyre <scjody@modernduck.com>
+When:  June 2007
+Why:   Deprecated in favour of the more efficient and robust rawiso interface.
+       Affected are applications which use the deprecated part of libraw1394
+       (raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
+       raw1394_stop_iso_rcv) or bypass libraw1394.
+Who:   Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+---------------------------
+
+What:  dv1394 driver (CONFIG_IEEE1394_DV1394)
+When:  June 2007
+Why:   Replaced by raw1394 + userspace libraries, notably libiec61883.  This
+       shift of application support has been indicated on www.linux1394.org
+       and developers' mailinglists for quite some time.  Major applications
+       have been converted, with the exception of ffmpeg and hence xine.
+       Piped output of dvgrab2 is a partial equivalent to dv1394.
+Who:   Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+---------------------------
+
+What:  ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API)
+When:  January 2007
+Why:   There are no projects known to use these exported symbols, except
+       dfg1394 (uses one symbol whose functionality is core-internal now).
+Who:   Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+---------------------------
+
+What:  ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB)
+When:  January 2007
+Files: drivers/ieee1394/: oui.db, oui2c.sh
+Why:   big size, little value
+Who:   Stefan Richter <stefanr@s5r6.in-berlin.de>
 
 ---------------------------
 
index eb1a6ca..790ef6f 100644 (file)
@@ -124,7 +124,7 @@ sync_fs:            no      no      read
 write_super_lockfs:    ?
 unlockfs:              ?
 statfs:                        no      no      no
-remount_fs:            no      yes     maybe           (see below)
+remount_fs:            yes     yes     maybe           (see below)
 clear_inode:           no
 umount_begin:          yes     no      no
 show_options:          no                              (vfsmount->sem)
index 3d74477..345392c 100644 (file)
@@ -51,6 +51,22 @@ homepage:
 
   http://fuse.sourceforge.net/
 
+Filesystem type
+~~~~~~~~~~~~~~~
+
+The filesystem type given to mount(2) can be one of the following:
+
+'fuse'
+
+  This is the usual way to mount a FUSE filesystem.  The first
+  argument of the mount system call may contain an arbitrary string,
+  which is not interpreted by the kernel.
+
+'fuseblk'
+
+  The filesystem is block device based.  The first argument of the
+  mount system call is interpreted as the name of the device.
+
 Mount options
 ~~~~~~~~~~~~~
 
@@ -94,6 +110,11 @@ Mount options
   The default is infinite.  Note that the size of read requests is
   limited anyway to 32 pages (which is 128kbyte on i386).
 
+'blksize=N'
+
+  Set the block size for the filesystem.  The default is 512.  This
+  option is only valid for 'fuseblk' type mounts.
+
 Control filesystem
 ~~~~~~~~~~~~~~~~~~
 
index d817224..253b50d 100644 (file)
@@ -1,11 +1,8 @@
-This is the implementation of the SystemV/Coherent filesystem for Linux.
 It implements all of
   - Xenix FS,
   - SystemV/386 FS,
   - Coherent FS.
 
-This is version beta 4.
-
 To install:
 * Answer the 'System V and Coherent filesystem support' question with 'y'
   when configuring the kernel.
@@ -28,11 +25,173 @@ Bugs in the present implementation:
   for this FS on hard disk yet.
 
 
-Please report any bugs and suggestions to
-  Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>
-  Pascal Haible <haible@izfm.uni-stuttgart.de>
-  Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
+These filesystems are rather similar. Here is a comparison with Minix FS:
+
+* Linux fdisk reports on partitions
+  - Minix FS     0x81 Linux/Minix
+  - Xenix FS     ??
+  - SystemV FS   ??
+  - Coherent FS  0x08 AIX bootable
+
+* Size of a block or zone (data allocation unit on disk)
+  - Minix FS     1024
+  - Xenix FS     1024 (also 512 ??)
+  - SystemV FS   1024 (also 512 and 2048)
+  - Coherent FS   512
+
+* General layout: all have one boot block, one super block and
+  separate areas for inodes and for directories/data.
+  On SystemV Release 2 FS (e.g. Microport) the first track is reserved and
+  all the block numbers (including the super block) are offset by one track.
+
+* Byte ordering of "short" (16 bit entities) on disk:
+  - Minix FS     little endian  0 1
+  - Xenix FS     little endian  0 1
+  - SystemV FS   little endian  0 1
+  - Coherent FS  little endian  0 1
+  Of course, this affects only the file system, not the data of files on it!
+
+* Byte ordering of "long" (32 bit entities) on disk:
+  - Minix FS     little endian  0 1 2 3
+  - Xenix FS     little endian  0 1 2 3
+  - SystemV FS   little endian  0 1 2 3
+  - Coherent FS  PDP-11         2 3 0 1
+  Of course, this affects only the file system, not the data of files on it!
+
+* Inode on disk: "short", 0 means non-existent, the root dir ino is:
+  - Minix FS                            1
+  - Xenix FS, SystemV FS, Coherent FS   2
+
+* Maximum number of hard links to a file:
+  - Minix FS     250
+  - Xenix FS     ??
+  - SystemV FS   ??
+  - Coherent FS  >=10000
+
+* Free inode management:
+  - Minix FS                             a bitmap
+  - Xenix FS, SystemV FS, Coherent FS
+      There is a cache of a certain number of free inodes in the super-block.
+      When it is exhausted, new free inodes are found using a linear search.
+
+* Free block management:
+  - Minix FS                             a bitmap
+  - Xenix FS, SystemV FS, Coherent FS
+      Free blocks are organized in a "free list". Maybe a misleading term,
+      since it is not true that every free block contains a pointer to
+      the next free block. Rather, the free blocks are organized in chunks
+      of limited size, and every now and then a free block contains pointers
+      to the free blocks pertaining to the next chunk; the first of these
+      contains pointers and so on. The list terminates with a "block number"
+      0 on Xenix FS and SystemV FS, with a block zeroed out on Coherent FS.
+
+* Super-block location:
+  - Minix FS     block 1 = bytes 1024..2047
+  - Xenix FS     block 1 = bytes 1024..2047
+  - SystemV FS   bytes 512..1023
+  - Coherent FS  block 1 = bytes 512..1023
+
+* Super-block layout:
+  - Minix FS
+                    unsigned short s_ninodes;
+                    unsigned short s_nzones;
+                    unsigned short s_imap_blocks;
+                    unsigned short s_zmap_blocks;
+                    unsigned short s_firstdatazone;
+                    unsigned short s_log_zone_size;
+                    unsigned long s_max_size;
+                    unsigned short s_magic;
+  - Xenix FS, SystemV FS, Coherent FS
+                    unsigned short s_firstdatazone;
+                    unsigned long  s_nzones;
+                    unsigned short s_fzone_count;
+                    unsigned long  s_fzones[NICFREE];
+                    unsigned short s_finode_count;
+                    unsigned short s_finodes[NICINOD];
+                    char           s_flock;
+                    char           s_ilock;
+                    char           s_modified;
+                    char           s_rdonly;
+                    unsigned long  s_time;
+                    short          s_dinfo[4]; -- SystemV FS only
+                    unsigned long  s_free_zones;
+                    unsigned short s_free_inodes;
+                    short          s_dinfo[4]; -- Xenix FS only
+                    unsigned short s_interleave_m,s_interleave_n; -- Coherent FS only
+                    char           s_fname[6];
+                    char           s_fpack[6];
+    then they differ considerably:
+        Xenix FS
+                    char           s_clean;
+                    char           s_fill[371];
+                    long           s_magic;
+                    long           s_type;
+        SystemV FS
+                    long           s_fill[12 or 14];
+                    long           s_state;
+                    long           s_magic;
+                    long           s_type;
+        Coherent FS
+                    unsigned long  s_unique;
+    Note that Coherent FS has no magic.
+
+* Inode layout:
+  - Minix FS
+                    unsigned short i_mode;
+                    unsigned short i_uid;
+                    unsigned long  i_size;
+                    unsigned long  i_time;
+                    unsigned char  i_gid;
+                    unsigned char  i_nlinks;
+                    unsigned short i_zone[7+1+1];
+  - Xenix FS, SystemV FS, Coherent FS
+                    unsigned short i_mode;
+                    unsigned short i_nlink;
+                    unsigned short i_uid;
+                    unsigned short i_gid;
+                    unsigned long  i_size;
+                    unsigned char  i_zone[3*(10+1+1+1)];
+                    unsigned long  i_atime;
+                    unsigned long  i_mtime;
+                    unsigned long  i_ctime;
+
+* Regular file data blocks are organized as
+  - Minix FS
+               7 direct blocks
+               1 indirect block (pointers to blocks)
+               1 double-indirect block (pointer to pointers to blocks)
+  - Xenix FS, SystemV FS, Coherent FS
+              10 direct blocks
+               1 indirect block (pointers to blocks)
+               1 double-indirect block (pointer to pointers to blocks)
+               1 triple-indirect block (pointer to pointers to pointers to blocks)
+
+* Inode size, inodes per block
+  - Minix FS        32   32
+  - Xenix FS        64   16
+  - SystemV FS      64   16
+  - Coherent FS     64    8
+
+* Directory entry on disk
+  - Minix FS
+                    unsigned short inode;
+                    char name[14/30];
+  - Xenix FS, SystemV FS, Coherent FS
+                    unsigned short inode;
+                    char name[14];
+
+* Dir entry size, dir entries per block
+  - Minix FS     16/32    64/32
+  - Xenix FS     16       64
+  - SystemV FS   16       64
+  - Coherent FS  16       32
+
+* How to implement symbolic links such that the host fsck doesn't scream:
+  - Minix FS     normal
+  - Xenix FS     kludge: as regular files with  chmod 1000
+  - SystemV FS   ??
+  - Coherent FS  kludge: as regular files with  chmod 1000
 
-Bruno Haible
-<haible@ma2s2.mathematik.uni-karlsruhe.de>
 
+Notation: We often speak of a "block" but mean a zone (the allocation unit)
+and not the disk driver's notion of "block".
index c51314b..9575de3 100644 (file)
@@ -2,7 +2,7 @@
                     ----------------------------
 
                    H. Peter Anvin <hpa@zytor.com>
-                       Last update 2005-09-02
+                       Last update 2006-11-17
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -35,6 +35,8 @@ Protocol 2.03:        (Kernel 2.4.18-pre1) Explicitly makes the highest possible
                initrd address available to the bootloader.
 
 Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
+Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
+               Introduce relocatable_kernel and kernel_alignment fields.
 
 
 **** MEMORY LAYOUT
@@ -129,6 +131,8 @@ Offset      Proto   Name            Meaning
 0226/2 N/A     pad1            Unused
 0228/4 2.02+   cmd_line_ptr    32-bit pointer to the kernel command line
 022C/4 2.03+   initrd_addr_max Highest legal initrd address
+0230/4 2.05+   kernel_alignment Physical addr alignment required for kernel
+0234/1 2.05+   relocatable_kernel Whether kernel is relocatable or not
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
index edc04d7..5a8bd5b 100644 (file)
@@ -191,3 +191,5 @@ Code        Seq#    Include File            Comments
                                        <mailto:aherrman@de.ibm.com>
 0xF3   00-3F   video/sisfb.h           sisfb (in development)
                                        <mailto:thomas@winischhofer.net>
+0xF4   00-1F   video/mbxfb.h           mbxfb
+                                       <mailto:raph@8d.com>
diff --git a/Documentation/ioctl/ioctl-decoding.txt b/Documentation/ioctl/ioctl-decoding.txt
new file mode 100644 (file)
index 0000000..bfdf7f3
--- /dev/null
@@ -0,0 +1,24 @@
+To decode a hex IOCTL code:
+
+Most architecures use this generic format, but check
+include/ARCH/ioctl.h for specifics, e.g. powerpc
+uses 3 bits to encode read/write and 13 bits for size.
+
+ bits    meaning
+ 31-30 00 - no parameters: uses _IO macro
+       10 - read: _IOR
+       01 - write: _IOW
+       11 - read/write: _IOWR
+
+ 29-16 size of arguments
+
+ 15-8  ascii character supposedly
+       unique to each driver
+
+ 7-0   function #
+
+
+ So for example 0x82187201 is a read with arg length of 0x218,
+character 'r' function 1. Grepping the source reveals this is:
+
+#define VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
index 2e1898e..d8323b8 100644 (file)
@@ -548,6 +548,13 @@ and is between 256 and 4096 characters. It is defined in the file
        eurwdt=         [HW,WDT] Eurotech CPU-1220/1410 onboard watchdog.
                        Format: <io>[,<irq>]
 
+       failslab=
+       fail_page_alloc=
+       fail_make_request=[KNL]
+                       General fault injection mechanism.
+                       Format: <interval>,<probability>,<space>,<times>
+                       See also /Documentation/fault-injection/.
+
        fd_mcs=         [HW,SCSI]
                        See header of drivers/scsi/fd_mcs.c.
 
@@ -599,8 +606,6 @@ and is between 256 and 4096 characters. It is defined in the file
 
        hugepages=      [HW,IA-32,IA-64] Maximal number of HugeTLB pages.
 
-       noirqbalance    [IA-32,SMP,KNL] Disable kernel irq balancing
-
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
                             keyboard and cannot control its state
@@ -650,6 +655,10 @@ and is between 256 and 4096 characters. It is defined in the file
        idle=           [HW]
                        Format: idle=poll or idle=halt
 
+       ignore_loglevel [KNL]
+                       Ignore loglevel setting - this will print /all/
+                       kernel messages to the console. Useful for debugging.
+
        ihash_entries=  [KNL]
                        Set number of hash buckets for inode cache.
 
@@ -714,7 +723,12 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: <RDP>,<reset>,<pci_scan>,<verbosity>
 
        isolcpus=       [KNL,SMP] Isolate CPUs from the general scheduler.
-                       Format: <cpu number>,...,<cpu number>
+                       Format:
+                       <cpu number>,...,<cpu number>
+                       or
+                       <cpu number>-<cpu number>  (must be a positive range in ascending order)
+                       or a mixture
+                       <cpu number>,...,<cpu number>-<cpu number>
                        This option can be used to specify one or more CPUs
                        to isolate from the general SMP balancing and scheduling
                        algorithms. The only way to move a process onto or off
@@ -1012,6 +1026,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        emulation library even if a 387 maths coprocessor
                        is present.
 
+       noaliencache    [MM, NUMA] Disables the allcoation of alien caches in
+                       the slab allocator.  Saves per-node memory, but will
+                       impact performance on real NUMA hardware.
+
        noalign         [KNL,ARM]
 
        noapic          [SMP,APIC] Tells the kernel to not make use of any
@@ -1052,9 +1070,14 @@ and is between 256 and 4096 characters. It is defined in the file
                        in certain environments such as networked servers or
                        real-time systems.
 
+       noirqbalance    [IA-32,SMP,KNL] Disable kernel irq balancing
+
        noirqdebug      [IA-32] Disables the code which attempts to detect and
                        disable unhandled interrupt sources.
 
+       no_timer_check  [IA-32,X86_64,APIC] Disables the code which tests for
+                       broken timer IRQ sources.
+
        noisapnp        [ISAPNP] Disables ISA PnP code.
 
        noinitrd        [RAM] Tells the kernel not to load any configured
@@ -1285,6 +1308,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        Param: "schedule" - profile schedule points.
                        Param: <number> - step/bucket size as a power of 2 for
                                statistical time based profiling.
+                       Param: "sleep" - profile D-state sleeping (millisecs)
 
        processor.max_cstate=   [HW,ACPI]
                        Limit processor to maximum C-state
@@ -1366,6 +1390,12 @@ and is between 256 and 4096 characters. It is defined in the file
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
+       resume_offset=  [SWSUSP]
+                       Specify the offset from the beginning of the partition
+                       given by "resume=" at which the swap header is located,
+                       in <PAGE_SIZE> units (needed only for swap files).
+                       See  Documentation/power/swsusp-and-swap-files.txt
+
        rhash_entries=  [KNL,NET]
                        Set number of hash buckets for route cache
 
@@ -1732,6 +1762,9 @@ and is between 256 and 4096 characters. It is defined in the file
        norandmaps      Don't use address space randomization
                        Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
 
+       unwind_debug=N  N > 0 will enable dwarf2 unwinder debugging
+                       This is useful to get more information why
+                       you got a "dwarf2 unwinder stuck"
 
 ______________________________________________________________________
 
index b1181ce..e06b6e3 100644 (file)
@@ -58,6 +58,8 @@ fore200e.txt
        - FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
        - info on using Frame Relay/Data Link Connection Identifier (DLCI).
+generic_netlink.txt
+       - info on Generic Netlink
 ip-sysctl.txt
        - /proc/sys/net/ipv4/* variables
 ip_dynaddr.txt
index dda1588..387482e 100644 (file)
@@ -19,7 +19,8 @@ for real time and multimedia traffic.
 
 It has a base protocol and pluggable congestion control IDs (CCIDs).
 
-It is at experimental RFC status and the homepage for DCCP as a protocol is at:
+It is at proposed standard RFC status and the homepage for DCCP as a protocol
+is at:
        http://www.read.cs.ucla.edu/dccp/
 
 Missing features
@@ -34,9 +35,6 @@ The known bugs are at:
 Socket options
 ==============
 
-DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for
-calculations.
-
 DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
 service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
 the socket will fall back to 0 (which means that no meaningful service code
diff --git a/Documentation/networking/generic_netlink.txt b/Documentation/networking/generic_netlink.txt
new file mode 100644 (file)
index 0000000..d4f8b8b
--- /dev/null
@@ -0,0 +1,3 @@
+A wiki document on how to use Generic Netlink can be found here:
+
+ * http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
diff --git a/Documentation/power/s2ram.txt b/Documentation/power/s2ram.txt
new file mode 100644 (file)
index 0000000..b05f512
--- /dev/null
@@ -0,0 +1,56 @@
+                       How to get s2ram working
+                       ~~~~~~~~~~~~~~~~~~~~~~~~
+                       2006 Linus Torvalds
+                       2006 Pavel Machek
+
+1) Check suspend.sf.net, program s2ram there has long whitelist of
+   "known ok" machines, along with tricks to use on each one.
+
+2) If that does not help, try reading tricks.txt and
+   video.txt. Perhaps problem is as simple as broken module, and
+   simple module unload can fix it.
+
+3) You can use Linus' TRACE_RESUME infrastructure, described below.
+
+                     Using TRACE_RESUME
+                     ~~~~~~~~~~~~~~~~~~
+
+I've been working at making the machines I have able to STR, and almost
+always it's a driver that is buggy. Thank God for the suspend/resume
+debugging - the thing that Chuck tried to disable. That's often the _only_
+way to debug these things, and it's actually pretty powerful (but
+time-consuming - having to insert TRACE_RESUME() markers into the device
+driver that doesn't resume and recompile and reboot).
+
+Anyway, the way to debug this for people who are interested (have a
+machine that doesn't boot) is:
+
+ - enable PM_DEBUG, and PM_TRACE
+
+ - use a script like this:
+
+       #!/bin/sh
+       sync
+       echo 1 > /sys/power/pm_trace
+       echo mem > /sys/power/state
+
+   to suspend
+
+ - if it doesn't come back up (which is usually the problem), reboot by
+   holding the power button down, and look at the dmesg output for things
+   like
+
+       Magic number: 4:156:725
+       hash matches drivers/base/power/resume.c:28
+       hash matches device 0000:01:00.0
+
+   which means that the last trace event was just before trying to resume
+   device 0000:01:00.0. Then figure out what driver is controlling that
+   device (lspci and /sys/devices/pci* is your friend), and see if you can
+   fix it, disable it, or trace into its resume function.
+
+For example, the above happens to be the VGA device on my EVO, which I
+used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out
+that "radeonfb" simply cannot resume that device - it tries to set the
+PLL's, and it just _hangs_. Using the regular VGA console and letting X
+resume it instead works fine.
diff --git a/Documentation/power/swsusp-and-swap-files.txt b/Documentation/power/swsusp-and-swap-files.txt
new file mode 100644 (file)
index 0000000..06f911a
--- /dev/null
@@ -0,0 +1,60 @@
+Using swap files with software suspend (swsusp)
+       (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+
+The Linux kernel handles swap files almost in the same way as it handles swap
+partitions and there are only two differences between these two types of swap
+areas:
+(1) swap files need not be contiguous,
+(2) the header of a swap file is not in the first block of the partition that
+holds it.  From the swsusp's point of view (1) is not a problem, because it is
+already taken care of by the swap-handling code, but (2) has to be taken into
+consideration.
+
+In principle the location of a swap file's header may be determined with the
+help of appropriate filesystem driver.  Unfortunately, however, it requires the
+filesystem holding the swap file to be mounted, and if this filesystem is
+journaled, it cannot be mounted during resume from disk.  For this reason to
+identify a swap file swsusp uses the name of the partition that holds the file
+and the offset from the beginning of the partition at which the swap file's
+header is located.  For convenience, this offset is expressed in <PAGE_SIZE>
+units.
+
+In order to use a swap file with swsusp, you need to:
+
+1) Create the swap file and make it active, eg.
+
+# dd if=/dev/zero of=<swap_file_path> bs=1024 count=<swap_file_size_in_k>
+# mkswap <swap_file_path>
+# swapon <swap_file_path>
+
+2) Use an application that will bmap the swap file with the help of the
+FIBMAP ioctl and determine the location of the file's swap header, as the
+offset, in <PAGE_SIZE> units, from the beginning of the partition which
+holds the swap file.
+
+3) Add the following parameters to the kernel command line:
+
+resume=<swap_file_partition> resume_offset=<swap_file_offset>
+
+where <swap_file_partition> is the partition on which the swap file is located
+and <swap_file_offset> is the offset of the swap header determined by the
+application in 2) (of course, this step may be carried out automatically
+by the same application that determies the swap file's header offset using the
+FIBMAP ioctl)
+
+OR
+
+Use a userland suspend application that will set the partition and offset
+with the help of the SNAPSHOT_SET_SWAP_AREA ioctl described in
+Documentation/power/userland-swsusp.txt (this is the only method to suspend
+to a swap file allowing the resume to be initiated from an initrd or initramfs
+image).
+
+Now, swsusp will use the swap file in the same way in which it would use a swap
+partition.  In particular, the swap file has to be active (ie. be present in
+/proc/swaps) so that it can be used for suspending.
+
+Note that if the swap file used for suspending is deleted and recreated,
+the location of its header need not be the same as before.  Thus every time
+this happens the value of the "resume_offset=" kernel command line parameter
+has to be updated.
index e635e6f..0761ff6 100644 (file)
@@ -297,20 +297,12 @@ system is shut down or suspended. Additionally use the encrypted
 suspend image to prevent sensitive data from being stolen after
 resume.
 
-Q: Why can't we suspend to a swap file?
+Q: Can I suspend to a swap file?
 
-A: Because accessing swap file needs the filesystem mounted, and
-filesystem might do something wrong (like replaying the journal)
-during mount.
-
-There are few ways to get that fixed:
-
-1) Probably could be solved by modifying every filesystem to support
-some kind of "really read-only!" option. Patches welcome.
-
-2) suspend2 gets around that by storing absolute positions in on-disk
-image (and blocksize), with resume parameter pointing directly to
-suspend header.
+A: Generally, yes, you can.  However, it requires you to use the "resume=" and
+"resume_offset=" kernel command line parameters, so the resume from a swap file
+cannot be initiated from an initrd or initramfs image.  See
+swsusp-and-swap-files.txt for details.
 
 Q: Is there a maximum system RAM size that is supported by swsusp?
 
index 64755e9..000556c 100644 (file)
@@ -9,9 +9,8 @@ done it already.
 Now, to use the userland interface for software suspend you need special
 utilities that will read/write the system memory snapshot from/to the
 kernel.  Such utilities are available, for example, from
-<http://www.sisk.pl/kernel/utilities/suspend>.  You may want to have
-a look at them if you are going to develop your own suspend/resume
-utilities.
+<http://suspend.sourceforge.net>.  You may want to have a look at them if you
+are going to develop your own suspend/resume utilities.
 
 The interface consists of a character device providing the open(),
 release(), read(), and write() operations as well as several ioctl()
@@ -21,9 +20,9 @@ be read from /sys/class/misc/snapshot/dev.
 
 The device can be open either for reading or for writing.  If open for
 reading, it is considered to be in the suspend mode.  Otherwise it is
-assumed to be in the resume mode.  The device cannot be open for reading
-and writing.  It is also impossible to have the device open more than once
-at a time.
+assumed to be in the resume mode.  The device cannot be open for simultaneous
+reading and writing.  It is also impossible to have the device open more than
+once at a time.
 
 The ioctl() commands recognized by the device are:
 
@@ -69,9 +68,46 @@ SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated with
 SNAPSHOT_SET_SWAP_FILE - set the resume partition (the last ioctl() argument
        should specify the device's major and minor numbers in the old
        two-byte format, as returned by the stat() function in the .st_rdev
-       member of the stat structure); it is recommended to always use this
-       call, because the code to set the resume partition could be removed from
-       future kernels
+       member of the stat structure)
+
+SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in <PAGE_SIZE>
+       units) from the beginning of the partition at which the swap header is
+       located (the last ioctl() argument should point to a struct
+       resume_swap_area, as defined in kernel/power/power.h, containing the
+       resume device specification, as for the SNAPSHOT_SET_SWAP_FILE ioctl(),
+       and the offset); for swap partitions the offset is always 0, but it is
+       different to zero for swap files (please see
+       Documentation/swsusp-and-swap-files.txt for details).
+       The SNAPSHOT_SET_SWAP_AREA ioctl() is considered as a replacement for
+       SNAPSHOT_SET_SWAP_FILE which is regarded as obsolete.   It is
+       recommended to always use this call, because the code to set the resume
+       partition may be removed from future kernels
+
+SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to
+       immediately enter the suspend-to-RAM state, so this call must always
+       be preceded by the SNAPSHOT_FREEZE call and it is also necessary
+       to use the SNAPSHOT_UNFREEZE call after the system wakes up.  This call
+       is needed to implement the suspend-to-both mechanism in which the
+       suspend image is first created, as though the system had been suspended
+       to disk, and then the system is suspended to RAM (this makes it possible
+       to resume the system from RAM if there's enough battery power or restore
+       its state on the basis of the saved suspend image otherwise)
+
+SNAPSHOT_PMOPS - enable the usage of the pmops->prepare, pmops->enter and
+       pmops->finish methods (the in-kernel swsusp knows these as the "platform
+       method") which are needed on many machines to (among others) speed up
+       the resume by letting the BIOS skip some steps or to let the system
+       recognise the correct state of the hardware after the resume (in
+       particular on many machines this ensures that unplugged AC
+       adapters get correctly detected and that kacpid does not run wild after
+       the resume).  The last ioctl() argument can take one of the three
+       values, defined in kernel/power/power.h:
+       PMOPS_PREPARE - make the kernel carry out the
+               pm_ops->prepare(PM_SUSPEND_DISK) operation
+       PMOPS_ENTER - make the kernel power off the system by calling
+               pm_ops->enter(PM_SUSPEND_DISK)
+       PMOPS_FINISH - make the kernel carry out the
+               pm_ops->finish(PM_SUSPEND_DISK) operation
 
 The device's read() operation can be used to transfer the snapshot image from
 the kernel.  It has the following limitations:
@@ -91,10 +127,12 @@ unfreeze user space processes frozen by SNAPSHOT_UNFREEZE if they are
 still frozen when the device is being closed).
 
 Currently it is assumed that the userland utilities reading/writing the
-snapshot image from/to the kernel will use a swap partition, called the resume
-partition, as storage space.  However, this is not really required, as they
-can use, for example, a special (blank) suspend partition or a file on a partition
-that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and mounted afterwards.
+snapshot image from/to the kernel will use a swap parition, called the resume
+partition, or a swap file as storage space (if a swap file is used, the resume
+partition is the partition that holds this file).  However, this is not really
+required, as they can use, for example, a special (blank) suspend partition or
+a file on a partition that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and
+mounted afterwards.
 
 These utilities SHOULD NOT make any assumptions regarding the ordering of
 data within the snapshot image, except for the image header that MAY be
index 77bf450..e938c44 100644 (file)
@@ -18,11 +18,18 @@ devices/
           - 0.0.0002/
           - 0.1.0000/0.1.1234/
           ...
+          - defunct/
 
 In this example, device 0815 is accessed via subchannel 0 in subchannel set 0,
 device 4711 via subchannel 1 in subchannel set 0, and subchannel 2 is a non-I/O
 subchannel. Device 1234 is accessed via subchannel 0 in subchannel set 1.
 
+The subchannel named 'defunct' does not represent any real subchannel on the
+system; it is a pseudo subchannel where disconnnected ccw devices are moved to
+if they are displaced by another ccw device becoming operational on their
+former subchannel. The ccw devices will be moved again to a proper subchannel
+if they become operational again on that subchannel.
+
 You should address a ccw device via its bus id (e.g. 0.0.4711); the device can
 be found under bus/ccw/devices/.
 
index a1e0ee2..f9717fe 100644 (file)
@@ -102,7 +102,7 @@ struct pxa2xx_spi_chip {
        u8 tx_threshold;
        u8 rx_threshold;
        u8 dma_burst_size;
-       u32 timeout_microsecs;
+       u32 timeout;
        u8 enable_loopback;
        void (*cs_control)(u32 command);
 };
@@ -121,7 +121,7 @@ the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
 to determine the correct value. An SSP configured for byte-wide transfers would
 use a value of 8.
 
-The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle
+The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle
 trailing bytes in the SSP receiver fifo.  The correct value for this field is
 dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
 slave device.  Please note that the PXA2xx SSP 1 does not support trailing byte
@@ -162,18 +162,18 @@ static void cs8405a_cs_control(u32 command)
 }
 
 static struct pxa2xx_spi_chip cs8415a_chip_info = {
-       .tx_threshold = 12, /* SSP hardward FIFO threshold */
-       .rx_threshold = 4, /* SSP hardward FIFO threshold */
+       .tx_threshold = 8, /* SSP hardward FIFO threshold */
+       .rx_threshold = 8, /* SSP hardward FIFO threshold */
        .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
-       .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+       .timeout = 235, /* See Intel documentation */
        .cs_control = cs8415a_cs_control, /* Use external chip select */
 };
 
 static struct pxa2xx_spi_chip cs8405a_chip_info = {
-       .tx_threshold = 12, /* SSP hardward FIFO threshold */
-       .rx_threshold = 4, /* SSP hardward FIFO threshold */
+       .tx_threshold = 8, /* SSP hardward FIFO threshold */
+       .rx_threshold = 8, /* SSP hardward FIFO threshold */
        .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
-       .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+       .timeout = 235, /* See Intel documentation */
        .cs_control = cs8405a_cs_control, /* Use external chip select */
 };
 
index f39c9d7..a2afca3 100644 (file)
@@ -62,9 +62,6 @@ consider the following facts about the Linux kernel:
       - different structures can contain different fields
       - Some functions may not be implemented at all, (i.e. some locks
        compile away to nothing for non-SMP builds.)
-      - Parameter passing of variables from function to function can be
-       done in different ways (the CONFIG_REGPARM option controls
-       this.)
       - Memory within the kernel can be aligned in different ways,
        depending on the build options.
   - Linux runs on a wide range of different processor architectures.
index 0bc7f1e..5922e84 100644 (file)
@@ -27,6 +27,7 @@ show up in /proc/sys/kernel:
 - hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
+- kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/kmod.txt
 - msgmax
@@ -170,6 +171,13 @@ This flag controls the L2 cache of G3 processor boards. If
 
 ==============================================================
 
+kstack_depth_to_print: (X86 only)
+
+Controls the number of words to print when dumping the raw
+kernel stack.
+
+==============================================================
+
 osrelease, ostype & version:
 
 # cat osrelease
index 8755b3e..62e32b4 100644 (file)
@@ -43,7 +43,7 @@
  42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1,12ab:2300]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
- 45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
+ 45 -> KWorld HardwareMpegTV XPert                         [17de:0840,1421:0305]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
  47 -> pcHDTV HD5500 HDTV                                  [7063:5500]
  48 -> Kworld MCE 200 Deluxe                               [17de:0841]
index 53ce6a3..f6201cc 100644 (file)
@@ -76,7 +76,7 @@
  75 -> AVerMedia AVerTVHD MCE A180              [1461:1044]
  76 -> SKNet MonsterTV Mobile                   [1131:4ee9]
  77 -> Pinnacle PCTV 40i/50i/110i (saa7133)     [11bd:002e]
- 78 -> ASUSTeK P7131 Dual                       [1043:4862]
+ 78 -> ASUSTeK P7131 Dual                       [1043:4862,1043:4876]
  79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
  80 -> ASUS Digimatrix TV                       [1043:0210]
  81 -> Philips Tiger reference design           [1131:2018]
@@ -99,3 +99,8 @@
  98 -> Proteus Pro 2309                         [0919:2003]
  99 -> AVerMedia TV Hybrid A16AR                [1461:2c00]
 100 -> Asus Europa2 OEM                         [1043:4860]
+101 -> Pinnacle PCTV 310i                       [11bd:002f]
+102 -> Avermedia AVerTV Studio 507              [1461:9715]
+103 -> Compro Videomate DVB-T200A
+104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid     [0070:6701]
+105 -> Terratec Cinergy HT PCMCIA               [153b:1172]
diff --git a/Documentation/video4linux/cafe_ccic b/Documentation/video4linux/cafe_ccic
new file mode 100644 (file)
index 0000000..8882102
--- /dev/null
@@ -0,0 +1,54 @@
+"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera
+controller.  This is the controller found in first-generation OLPC systems,
+and this driver was written with support from the OLPC project.
+
+Current status: the core driver works.  It can generate data in YUV422,
+RGB565, and RGB444 formats.  (Anybody looking at the code will see RGB32 as
+well, but that is a debugging aid which will be removed shortly).  VGA and
+QVGA modes work; CIF is there but the colors remain funky.  Only the OV7670
+sensor is known to work with this controller at this time.
+
+To try it out: either of these commands will work:
+
+     mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound
+     mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound
+
+The "xawtv" utility also works; gqcam does not, for unknown reasons.
+
+There are a few load-time options, most of which can be changed after
+loading via sysfs as well:
+
+ - alloc_bufs_at_load:  Normally, the driver will not allocate any DMA
+   buffers until the time comes to transfer data.  If this option is set,
+   then worst-case-sized buffers will be allocated at module load time.
+   This option nails down the memory for the life of the module, but
+   perhaps decreases the chances of an allocation failure later on.
+
+ - dma_buf_size: The size of DMA buffers to allocate.  Note that this
+   option is only consulted for load-time allocation; when buffers are
+   allocated at run time, they will be sized appropriately for the current
+   camera settings.
+
+ - n_dma_bufs: The controller can cycle through either two or three DMA
+   buffers.  Normally, the driver tries to use three buffers; on faster
+   systems, however, it will work well with only two.
+
+ - min_buffers: The minimum number of streaming I/O buffers that the driver
+   will consent to work with.  Default is one, but, on slower systems,
+   better behavior with mplayer can be achieved by setting to a higher
+   value (like six).
+
+ - max_buffers: The maximum number of streaming I/O buffers; default is
+   ten.  That number was carefully picked out of a hat and should not be
+   assumed to actually mean much of anything.
+
+ - flip: If this boolean parameter is set, the sensor will be instructed to
+   invert the video image.  Whether it makes sense is determined by how
+   your particular camera is mounted.
+
+Work is ongoing with this driver, stay tuned.
+
+jon
+
+Jonathan Corbet
+corbet@lwn.net
diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt
deleted file mode 100644 (file)
index 1a1c2d0..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-Driver for Trust Computer Products Framegrabber, version 0.6.1
------- --- ----- -------- -------- ------------  ------- - - -
-
-- ZORAN ------------------------------------------------------
- Author: Pauline Middelink <middelin@polyware.nl>
-   Date: 18 September 1999
-Version: 0.6.1
-
-- Description ------------------------------------------------
-
-Video4Linux compatible driver for an unknown brand framegrabber
-(Sold in the Netherlands by TRUST Computer Products) and various
-other zoran zr36120 based framegrabbers.
-
-The card contains a ZR36120 Multimedia PCI Interface and a Philips
-SAA7110 Onechip Frontend videodecoder. There is also an DSP of
-which I have forgotten the number, since i will never get that thing
-to work without specs from the vendor itself.
-
-The SAA711x are capable of processing 6 different video inputs,
-CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or
-SECAM and delivering a YUV datastream.  On my card the input
-'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2.
-
-I have some reports of other cards working with the mentioned
-chip sets. For a list of other working cards please have a look
-at the cards named in the tvcards struct in the beginning of
-zr36120.c
-
-After some testing, I discovered that the carddesigner messed up
-on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
-which (s)he connected reversely. So we have to clock on the SDA
-and r/w data on the SCL pin. Life is fun... Each cardtype now has
-a bit which signifies if you have a card with the same deficiency.
-
-Oh, for the completeness of this story I must mention that my
-card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
-GIRQ0 as some other cards have. This is also incorporated in
-the driver be clearing/setting the 'useirq1' bit in the tvcard
-description.
-
-Another problems of continuous capturing data with a Zoran chip
-is something nasty inside the chip. It effectively halves the
-fps we ought to get... Here is the scenario: capturing frames
-to memory is done in the so-called snapshot mode. In this mode
-the Zoran stops after capturing a frame worth of data and wait
-till the application set GRAB bit to indicate readiness for the
-next frame. After detecting a set bit, the chip neatly waits
-till the start of a frame, captures it and it goes back to off.
-Smart ppl will notice the problem here. Its the waiting on the
-_next_ frame each time we set the GRAB bit... Oh well, 12,5 fps
-is still plenty fast for me.
--- update 28/7/1999 --
-Don't believe a word I just said... Proof is the output
-of `streamer -t 300 -r 25 -f avi15 -o /dev/null`
-       ++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
-       +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+-
-       syncer: done
-       writer: done
-(note the /dev/null is prudent here, my system is not able to
- grab /and/ write 25 fps to a file... gifts welcome :) )
-The technical reasoning follows: The zoran completed the last
-frame, the VSYNC goes low, and GRAB is cleared. The interrupt
-routine starts to work since its VSYNC driven, and again
-activates the GRAB bit. A few ms later the VSYNC (re-)rises and
-the zoran starts to work on a new and freshly broadcasted frame....
-
-For pointers I used the specs of both chips. Below are the URLs:
-  http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf
-  http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf
-Some alternatives for the Philips SAA 7110 datasheet are:
-  http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml
-  http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part
-
-The documentation has very little on absolute numbers or timings
-needed for the various modes/resolutions, but there are other
-programs you can borrow those from.
-
------- Install --------------------------------------------
-Read the file called TODO.  Note its long list of limitations.
-
-Build a kernel with VIDEO4LINUX enabled. Activate the
-BT848 driver; we need this because we have need for the
-other modules (i2c and videodev) it enables.
-
-To install this software, extract it into a suitable directory.
-Examine the makefile and change anything you don't like.  Type "make".
-
-After making the modules check if you have the much needed
-/dev/video devices. If not, execute the following 4 lines:
-       mknod /dev/video c 81 0
-       mknod /dev/video1 c 81 1
-       mknod /dev/video2 c 81 2
-       mknod /dev/video3 c 81 3
-       mknod /dev/video4 c 81 4
-
-After making/checking the devices do:
-       modprobe i2c
-       modprobe videodev
-       modprobe saa7110        (optional)
-       modprobe saa7111        (optional)
-       modprobe tuner          (optional)
-       insmod zoran cardtype=<n>
-
-<n> is the cardtype of the card you have. The cardnumber can
-be found in the source of zr36120. Look for tvcards. If your
-card is not there, please try if any other card gives some
-response, and mail me if you got a working tvcard addition.
-
-PS. <TVCard editors behold!)
-    Don't forget to set video_input to the number of inputs
-    you defined in the video_mux part of the tvcard definition.
-    It's a common error to add a channel but not incrementing
-    video_input and getting angry with me/v4l/linux/linus :(
-
-You are now ready to test the framegrabber with your favorite
-video4linux compatible tool
-
------- Application ----------------------------------------
-
-This device works with all Video4Linux compatible applications,
-given the limitations in the TODO file.
-
------- API ------------------------------------------------
-
-This uses the V4L interface as of kernel release 2.1.116, and in
-fact has not been tested on any lower version.  There are a couple
-of minor differences due to the fact that the amount of data returned
-with each frame varies, and no doubt there are discrepancies due to my
-misunderstanding of the API.  I intend to convert this driver to the
-new V4L2 API when it has stabilized more.
-
------- Current state --------------------------------------
-
-The driver is capable of overlaying a video image in screen, and
-even capable of grabbing frames. It uses the BIGPHYSAREA patch
-to allocate lots of large memory blocks when tis patch is
-found in the kernel, but it doesn't need it.
-The consequence is that, when loading the driver as a module,
-the module may tell you it's out of memory, but 'free' says
-otherwise. The reason is simple; the modules wants its memory
-contiguous, not fragmented, and after a long uptime there
-probably isn't a fragment of memory large enough...
-
-The driver uses a double buffering scheme, which should really
-be an n-way buffer, depending on the size of allocated framebuffer
-and the requested grab-size/format.
-This current version also fixes a dead-lock situation during irq
-time, which really, really froze my system... :)
-
-Good luck.
-  Pauline
index f3c57f4..dbdcaf6 100644 (file)
@@ -52,10 +52,6 @@ APICs
                 apicmaintimer. Useful when your PIT timer is totally
                 broken.
 
-   disable_8254_timer / enable_8254_timer
-                Enable interrupt 0 timer routing over the 8254 in addition to over
-                the IO-APIC. The kernel tries to set a sensible default.
-
 Early Console
 
    syntax: earlyprintk=vga
@@ -183,7 +179,7 @@ PCI
 IOMMU
 
  iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge][,noaperture]
+         [,forcesac][,fullflush][,nomerge][,noaperture][,calgary]
    size  set size of iommu (in bytes)
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
@@ -204,6 +200,7 @@ IOMMU
            buffering.
    nodac    Forbid DMA >4GB
    panic    Always panic when IOMMU overflows
+   calgary  Use the Calgary IOMMU if it is available
 
   swiotlb=pages[,force]
 
index 5dff268..b202493 100644 (file)
@@ -348,6 +348,13 @@ P: Ian Molton
 M:     spyro@f2s.com
 S:     Maintained
 
+ARM/ATMEL AT91RM9200 ARM ARCHITECTURE
+P:      Andrew Victor
+M:      andrew@sanpeople.com
+L:      linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:      http://maxim.org.za/at91_26.html
+S:      Maintained
+
 ARM/CORGI MACHINE SUPPORT
 P:     Richard Purdie
 M:     rpurdie@rpsys.net
@@ -677,7 +684,7 @@ S:  Supported
 CIRRUS LOGIC GENERIC FBDEV DRIVER
 P:     Jeff Garzik
 M:     jgarzik@pobox.com
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Odd Fixes
 
 CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
@@ -784,7 +791,7 @@ S:  Maintained
 CYBLAFB FRAMEBUFFER DRIVER
 P:     Knut Petersen
 M:     Knut_Petersen@t-online.de
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 CYCLADES 2X SYNC CARD DRIVER
@@ -1091,13 +1098,19 @@ M:      miku@iki.fi
 S:     Maintained
 
 EXT2 FILE SYSTEM
-L:     ext2-devel@lists.sourceforge.net
+L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
 EXT3 FILE SYSTEM
 P:     Stephen Tweedie, Andrew Morton
 M:     sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
-L:     ext2-devel@lists.sourceforge.net
+L:     linux-ext4@vger.kernel.org
+S:     Maintained
+
+EXT4 FILE SYSTEM
+P:     Stephen Tweedie, Andrew Morton
+M:     sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
 F71805F HARDWARE MONITORING DRIVER
@@ -1115,7 +1128,7 @@ S:        Supported
 FRAMEBUFFER LAYER
 P:     Antonino Daplas
 M:     adaplas@pol.net
-L:     linux-fbdev-devel@lists.sourceforge.net 
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 W:     http://linux-fbdev.sourceforge.net/
 S:     Maintained
 
@@ -1214,7 +1227,8 @@ HARDWARE MONITORING
 P:     Jean Delvare
 M:     khali@linux-fr.org
 L:     lm-sensors@lm-sensors.org
-W:     http://www.lm-sensors.nu/
+W:     http://www.lm-sensors.org/
+T:     quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-hwmon/
 S:     Maintained
 
 HARDWARE RANDOM NUMBER GENERATOR CORE
@@ -1340,8 +1354,7 @@ I2C SUBSYSTEM
 P:     Jean Delvare
 M:     khali@linux-fr.org
 L:     i2c@lm-sensors.org
-W:     http://www.lm-sensors.nu/
-T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+T:     quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
 S:     Maintained
 
 I2O
@@ -1466,7 +1479,7 @@ S:        Maintained
 IMS TWINTURBO FRAMEBUFFER DRIVER
 P:     Paul Mundt
 M:     lethal@chaoticdreams.org
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 INFINIBAND SUBSYSTEM
@@ -1499,13 +1512,13 @@ S:      Maintained
 INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
 P:     Sylvain Meyer
 M:     sylvain.meyer@worldonline.fr
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 INTEL 810/815 FRAMEBUFFER DRIVER
 P:     Antonino Daplas
 M:     adaplas@pol.net
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
@@ -1673,7 +1686,7 @@ S:        Supported
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 P:     Stephen Tweedie, Andrew Morton
 M:     sct@redhat.com, akpm@osdl.org
-L:     ext2-devel@lists.sourceforge.net
+L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
 K8TEMP HARDWARE MONITORING DRIVER
@@ -1951,7 +1964,7 @@ S:        Odd Fixes for 2.4; Maintained for 2.6.
 MATROX FRAMEBUFFER DRIVER
 P:     Petr Vandrovec
 M:     vandrove@vc.cvut.cz
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 MEGARAID SCSI DRIVERS
@@ -2012,6 +2025,12 @@ M:       rubini@ipvvis.unipv.it
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0)
+P:     Jiri Slaby
+M:     jirislaby@gmail.com
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+
 MSI LAPTOP SUPPORT
 P:     Lennart Poettering
 M:     mzxreary@0pointer.de
@@ -2037,6 +2056,12 @@ P:       Andrew Veliath
 M:     andrewtv@usa.net
 S:     Maintained
 
+MULTITECH MULTIPORT CARD (ISICOM)
+P:     Jiri Slaby
+M:     jirislaby@gmail.com
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+
 NATSEMI ETHERNET DRIVER (DP8381x)
 P:     Tim Hockin
 M:     thockin@hockin.org
@@ -2197,7 +2222,7 @@ S:        Maintained
 NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
 P:     Antonino Daplas
 M:     adaplas@pol.net
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 OPENCORES I2C BUS DRIVER
@@ -2481,13 +2506,13 @@ S:      Maintained
 RADEON FRAMEBUFFER DISPLAY DRIVER
 P:     Benjamin Herrenschmidt
 M:     benh@kernel.crashing.org
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
 P:     Paul Mackerras
 M:     paulus@samba.org
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
@@ -2529,7 +2554,7 @@ S:        Maintained
 REAL TIME CLOCK (RTC) SUBSYSTEM
 P:     Alessandro Zummo
 M:     a.zummo@towertech.it
-L:     linux-kernel@vger.kernel.org
+L:     rtc-linux@googlegroups.com
 S:     Maintained
 
 REISERFS FILE SYSTEM
@@ -2557,7 +2582,7 @@ S:        Orphan
 S3 SAVAGE FRAMEBUFFER DRIVER
 P:     Antonino Daplas
 M:     adaplas@pol.net
-L:     linux-fbdev-devel@lists.sourceforge.net
+L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 S390
@@ -2913,7 +2938,6 @@ S:        Maintained
 SUN3/3X
 P:     Sam Creasey
 M:     sammy@sammy.net
-L:     sun3-list@redhat.com
 W:     http://sammy.net/sun3/
 S:     Maintained
 
@@ -3454,6 +3478,12 @@ W:       http://oss.sgi.com/projects/xfs
 T:     git git://oss.sgi.com:8090/xfs/xfs-2.6
 S:     Supported
 
+XILINX UARTLITE SERIAL DRIVER
+P:     Peter Korsgaard
+M:     jacmet@sunsite.dk
+L:     linux-serial@vger.kernel.org
+S:     Maintained
+
 X86 3-LEVEL PAGING (PAE) SUPPORT
 P:     Ingo Molnar
 M:     mingo@redhat.com
index aef9625..73e825b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,8 +10,11 @@ NAME=Avast! A bilge rat!
 # Comments in this file are targeted only to the developer, do not
 # expect to learn how to build the kernel reading this file.
 
-# Do not print "Entering directory ..."
-MAKEFLAGS += --no-print-directory
+# Do not:
+# o  use make's built-in rules and variables
+#    (this increases performance and avoid hard-to-debug behavour);
+# o  print "Entering directory ...";
+MAKEFLAGS += -rR --no-print-directory
 
 # We are using a recursive build, so we need to do a little thinking
 # to get the ordering right.
@@ -271,12 +274,8 @@ export quiet Q KBUILD_VERBOSE
 # Look for make include files relative to root of kernel src
 MAKEFLAGS += --include-dir=$(srctree)
 
-# We need some generic definitions
-include  $(srctree)/scripts/Kbuild.include
-
-# Do not use make's built-in rules and variables
-# This increases performance and avoid hard-to-debug behavour
-MAKEFLAGS += -rR
+# We need some generic definitions.
+include $(srctree)/scripts/Kbuild.include
 
 # Make variables (CC, etc...)
 
@@ -1484,6 +1483,8 @@ endif     # skip-makefile
 PHONY += FORCE
 FORCE:
 
+# Cancel implicit rules on top Makefile, `-rR' will apply to sub-makes.
+Makefile: ;
 
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable se we can use it in if_changed and friends.
diff --git a/README b/README
index 3e26472..c055615 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-       Linux kernel release 2.6.xx <http://kernel.org>
+       Linux kernel release 2.6.xx <http://kernel.org/>
 
 These are the release notes for Linux version 2.6.  Read them carefully,
 as they tell you what this is all about, explain how to install the
@@ -22,15 +22,17 @@ ON WHAT HARDWARE DOES IT RUN?
 
   Although originally developed first for 32-bit x86-based PCs (386 or higher),
   today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
-  UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH,
+  UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
   IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
-  and Renesas M32R architectures.
+  Cris, Xtensa, AVR32 and Renesas M32R architectures.
 
   Linux is easily portable to most general-purpose 32- or 64-bit architectures
   as long as they have a paged memory management unit (PMMU) and a port of the
   GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
   also been ported to a number of architectures without a PMMU, although
   functionality is then obviously somewhat limited.
+  Linux has also been ported to itself. You can now run the kernel as a
+  userspace application - this is called UserMode Linux (UML).
 
 DOCUMENTATION:
 
@@ -113,6 +115,7 @@ INSTALLING the kernel:
    version 2.6.12.2 and want to jump to 2.6.12.3, you must first
    reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
    the 2.6.12.3 patch.
+   You can read more on this in Documentation/applying-patches.txt
 
  - Make sure you have no stale .o files and dependencies lying around:
 
@@ -161,6 +164,7 @@ CONFIGURING the kernel:
    only ask you for the answers to new questions.
 
  - Alternate configuration commands are:
+       "make config"      Plain text interface.
        "make menuconfig"  Text based color menus, radiolists & dialogs.
        "make xconfig"     X windows (Qt) based configuration tool.
        "make gconfig"     X windows (Gtk) based configuration tool.
@@ -303,8 +307,9 @@ IF SOMETHING GOES WRONG:
 
  - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
    as is, otherwise you will have to use the "ksymoops" program to make
-   sense of the dump.  This utility can be downloaded from
-   ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops.
+   sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
+   This utility can be downloaded from
+   ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
    Alternately you can do the dump lookup by hand:
 
  - In debugging dumps like the above, it helps enormously if you can
@@ -336,7 +341,7 @@ IF SOMETHING GOES WRONG:
 
    If you for some reason cannot do the above (you have a pre-compiled
    kernel image or similar), telling me as much about your setup as
-   possible will help. 
+   possible will help.  Please read the REPORTING-BUGS document for details.
 
  - Alternately, you can use gdb on a running kernel. (read-only; i.e. you
    cannot change values or set break points.) To do this, first compile the
index f9da827..ac02e42 100644 (file)
@@ -40,7 +40,9 @@ summary from [1.]>" for easy identification by the developers.
 [1.] One line summary of the problem:
 [2.] Full description of the problem/report:
 [3.] Keywords (i.e., modules, networking, kernel):
-[4.] Kernel version (from /proc/version):
+[4.] Kernel information
+[4.1.] Kernel version (from /proc/version):
+[4.2.] Kernel .config file:
 [5.] Most recent kernel version which did not have the bug:
 [6.] Output of Oops.. message (if applicable) with symbolic information
      resolved (see Documentation/oops-tracing.txt)
index 7e55ea6..84caf50 100644 (file)
@@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index ad61736..be133f1 100644 (file)
@@ -277,7 +277,7 @@ osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bu
        retval = -EBADF;
        file = fget(fd);
        if (file) {
-               retval = do_osf_statfs(file->f_dentry, buffer, bufsiz);
+               retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz);
                fput(file);
        }
        return retval;
@@ -979,7 +979,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
        long timeout;
        int ret = -EINVAL;
        struct fdtable *fdt;
-       int max_fdset;
+       int max_fds;
 
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) {
@@ -1003,9 +1003,9 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 
        rcu_read_lock();
        fdt = files_fdtable(current->files);
-       max_fdset = fdt->max_fdset;
+       max_fds = fdt->max_fds;
        rcu_read_unlock();
-       if (n < 0 || n > max_fdset)
+       if (n < 0 || n > max_fds)
                goto out_nofds;
 
        /*
index ffb7d54..3c10b9a 100644 (file)
@@ -516,10 +516,11 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
                if (bus == 0 && dfn == 0) {
                        hose = pci_isa_hose;
                } else {
-                       dev = pci_find_slot(bus, dfn);
+                       dev = pci_get_bus_and_slot(bus, dfn);
                        if (!dev)
                                return -ENODEV;
                        hose = dev->sysdata;
+                       pci_dev_put(dev);
                }
        }
 
index b8b817f..910b43c 100644 (file)
@@ -183,11 +183,15 @@ miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
        if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
                u8 irq=0;
-
-               if(pci_read_config_byte(pci_find_slot(dev->bus->number, dev->devfn & ~(7)), 0x40,&irq)!=PCIBIOS_SUCCESSFUL)
+               struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7);
+               if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) {
+                       pci_dev_put(pdev);
                        return -1;
-               else    
+               }
+               else    {
+                       pci_dev_put(pdev);
                        return irq;
+               }
        }
 
        return COMMON_TABLE_LOOKUP;
index 93744ba..e7594a7 100644 (file)
@@ -200,7 +200,7 @@ nautilus_init_pci(void)
        bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
        hose->bus = bus;
 
-       irongate = pci_find_slot(0, 0);
+       irongate = pci_get_bus_and_slot(0, 0);
        bus->self = irongate;
        bus->resource[1] = &irongate_mem;
 
index 8871529..8aa9db8 100644 (file)
@@ -108,7 +108,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
 
        /* If we're in an interrupt context, or have no user context,
           we must not take the fault.  */
-       if (!mm || in_interrupt())
+       if (!mm || in_atomic())
                goto no_context;
 
 #ifdef CONFIG_ALPHA_LARGE_VMALLOC
index ce00c57..aa1d400 100644 (file)
@@ -74,6 +74,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -223,6 +231,12 @@ config ARCH_IOP33X
        help
          Support for Intel's IOP33X (XScale) family of processors.
 
+config ARCH_IOP13XX
+       bool "IOP13xx-based"
+       select PCI
+       help
+         Support for Intel's IOP13XX (XScale) family of processors.
+
 config ARCH_IXP4XX
        bool "IXP4xx-based"
        depends on MMU
@@ -331,6 +345,8 @@ source "arch/arm/mach-iop32x/Kconfig"
 
 source "arch/arm/mach-iop33x/Kconfig"
 
+source "arch/arm/mach-iop13xx/Kconfig"
+
 source "arch/arm/mach-ixp4xx/Kconfig"
 
 source "arch/arm/mach-ixp2000/Kconfig"
@@ -374,6 +390,14 @@ config PLAT_IOP
 
 source arch/arm/mm/Kconfig
 
+config IWMMXT
+       bool "Enable iWMMXt support"
+       depends CPU_XSCALE || CPU_XSC3
+       default y if PXA27x
+       help
+         Enable support for iWMMXt context switching at run time if
+         running on a CPU that supports it.
+
 #  bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
 config XSCALE_PMU
        bool
@@ -583,7 +607,7 @@ config LEDS
                   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
                   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
                   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
-                  ARCH_AT91RM9200 || MACH_TRIZEPS4
+                  ARCH_AT91 || MACH_TRIZEPS4
        help
          If you say Y here, the LEDs on your machine will be used
          to provide useful information about your current system status.
index d22f38b..40c5eb1 100644 (file)
@@ -32,10 +32,6 @@ config DEBUG_USER
              8 - SIGSEGV faults
             16 - SIGBUS faults
 
-config DEBUG_WAITQ
-       bool "Wait queue debugging"
-       depends on DEBUG_KERNEL
-
 config DEBUG_ERRORS
        bool "Verbose kernel error messages"
        depends on DEBUG_KERNEL
index 6f4f8bf..000f110 100644 (file)
@@ -15,6 +15,8 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
 OBJCOPYFLAGS   :=-O binary -R .note -R .comment -S
 GZFLAGS                :=-9
 #CFLAGS                +=-pipe
+# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
+CFLAGS         +=$(call cc-option,-marm,)
 
 # Do not use arch/arm/defconfig - it's always outdated.
 # Select a platform tht is kept up-to-date
@@ -108,6 +110,7 @@ endif
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
  machine-$(CONFIG_ARCH_IOP32X)    := iop32x
  machine-$(CONFIG_ARCH_IOP33X)    := iop33x
+ machine-$(CONFIG_ARCH_IOP13XX)           := iop13xx
  machine-$(CONFIG_ARCH_IXP4XX)    := ixp4xx
  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
index f3e020f..09b9d1b 100644 (file)
@@ -160,7 +160,7 @@ void __init gic_dist_init(void __iomem *base)
         */
        for (i = 29; i < max_irq; i++) {
                set_irq_chip(i, &gic_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
index 80a72c7..cfe6f46 100644 (file)
@@ -163,11 +163,11 @@ static struct locomo_dev_info locomo_devices[] = {
 #define        LOCOMO_IRQ_LT_START     (IRQ_LOCOMO_LT)
 #define        LOCOMO_IRQ_SPI_START    (IRQ_LOCOMO_SPI_RFR)
 
-static void locomo_handler(unsigned int irq, struct irqdesc *desc)
+static void locomo_handler(unsigned int irq, struct irq_desc *desc)
 {
        int req, i;
-       struct irqdesc *d;
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       struct irq_desc *d;
+       void __iomem *mapbase = get_irq_chip_data(irq);
 
        /* Acknowledge the parent IRQ */
        desc->chip->ack(irq);
@@ -194,7 +194,7 @@ static void locomo_ack_irq(unsigned int irq)
 
 static void locomo_mask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_ICR);
        r &= ~(0x0010 << (irq - LOCOMO_IRQ_START));
@@ -203,7 +203,7 @@ static void locomo_mask_irq(unsigned int irq)
 
 static void locomo_unmask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_ICR);
        r |= (0x0010 << (irq - LOCOMO_IRQ_START));
@@ -217,10 +217,10 @@ static struct irq_chip locomo_chip = {
        .unmask = locomo_unmask_irq,
 };
 
-static void locomo_key_handler(unsigned int irq, struct irqdesc *desc)
+static void locomo_key_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct irqdesc *d;
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       struct irq_desc *d;
+       void __iomem *mapbase = get_irq_chip_data(irq);
 
        if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
                d = irq_desc + LOCOMO_IRQ_KEY_START;
@@ -230,7 +230,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc)
 
 static void locomo_key_ack_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
        r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
@@ -239,7 +239,7 @@ static void locomo_key_ack_irq(unsigned int irq)
 
 static void locomo_key_mask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
        r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
@@ -248,7 +248,7 @@ static void locomo_key_mask_irq(unsigned int irq)
 
 static void locomo_key_unmask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
        r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
@@ -262,11 +262,11 @@ static struct irq_chip locomo_key_chip = {
        .unmask = locomo_key_unmask_irq,
 };
 
-static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc)
+static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc)
 {
        int req, i;
-       struct irqdesc *d;
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       struct irq_desc *d;
+       void __iomem *mapbase = get_irq_chip_data(irq);
 
        req =   locomo_readl(mapbase + LOCOMO_GIR) &
                locomo_readl(mapbase + LOCOMO_GPD) &
@@ -285,7 +285,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc)
 
 static void locomo_gpio_ack_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_GWE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
@@ -302,7 +302,7 @@ static void locomo_gpio_ack_irq(unsigned int irq)
 
 static void locomo_gpio_mask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_GIE);
        r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
@@ -311,7 +311,7 @@ static void locomo_gpio_mask_irq(unsigned int irq)
 
 static void locomo_gpio_unmask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_GIE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
@@ -325,10 +325,10 @@ static struct irq_chip locomo_gpio_chip = {
        .unmask = locomo_gpio_unmask_irq,
 };
 
-static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc)
+static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct irqdesc *d;
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       struct irq_desc *d;
+       void __iomem *mapbase = get_irq_chip_data(irq);
 
        if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
                d = irq_desc + LOCOMO_IRQ_LT_START;
@@ -338,7 +338,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc)
 
 static void locomo_lt_ack_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_LTINT);
        r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START));
@@ -347,7 +347,7 @@ static void locomo_lt_ack_irq(unsigned int irq)
 
 static void locomo_lt_mask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_LTINT);
        r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START));
@@ -356,7 +356,7 @@ static void locomo_lt_mask_irq(unsigned int irq)
 
 static void locomo_lt_unmask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_LTINT);
        r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START));
@@ -370,11 +370,11 @@ static struct irq_chip locomo_lt_chip = {
        .unmask = locomo_lt_unmask_irq,
 };
 
-static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc)
+static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc)
 {
        int req, i;
-       struct irqdesc *d;
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       struct irq_desc *d;
+       void __iomem *mapbase = get_irq_chip_data(irq);
 
        req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
        if (req) {
@@ -391,7 +391,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc)
 
 static void locomo_spi_ack_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
@@ -408,7 +408,7 @@ static void locomo_spi_ack_irq(unsigned int irq)
 
 static void locomo_spi_mask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
        r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
@@ -417,7 +417,7 @@ static void locomo_spi_mask_irq(unsigned int irq)
 
 static void locomo_spi_unmask_irq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned int r;
        r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
@@ -440,55 +440,55 @@ static void locomo_setup_irq(struct locomo *lchip)
         * Install handler for IRQ_LOCOMO_HW.
         */
        set_irq_type(lchip->irq, IRQT_FALLING);
-       set_irq_chipdata(lchip->irq, irqbase);
+       set_irq_chip_data(lchip->irq, irqbase);
        set_irq_chained_handler(lchip->irq, locomo_handler);
 
        /* Install handlers for IRQ_LOCOMO_*_BASE */
        set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip);
-       set_irq_chipdata(IRQ_LOCOMO_KEY_BASE, irqbase);
+       set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase);
        set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler);
        set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE);
 
        set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);
-       set_irq_chipdata(IRQ_LOCOMO_GPIO_BASE, irqbase);
+       set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase);
        set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);
        set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE);
 
        set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);
-       set_irq_chipdata(IRQ_LOCOMO_LT_BASE, irqbase);
+       set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase);
        set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);
        set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE);
 
        set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);
-       set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase);
+       set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase);
        set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);
        set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE);
 
        /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
        set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);
-       set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase);
-       set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ);
+       set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase);
+       set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq);
        set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);
 
        /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
        for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {
                set_irq_chip(irq, &locomo_gpio_chip);
-               set_irq_chipdata(irq, irqbase);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_chip_data(irq, irqbase);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
        set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);
-       set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase);
-       set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ);
+       set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase);
+       set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq);
        set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);
 
        /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
        for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) {
                set_irq_chip(irq, &locomo_spi_chip);
-               set_irq_chipdata(irq, irqbase);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_chip_data(irq, irqbase);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index d5f7201..fe3f059 100644 (file)
@@ -147,7 +147,7 @@ void __init sa1111_adjust_zones(int node, unsigned long *size, unsigned long *ho
  * will call us again if there are more interrupts to process.
  */
 static void
-sa1111_irq_handler(unsigned int irq, struct irqdesc *desc)
+sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int stat0, stat1, i;
        void __iomem *base = get_irq_data(irq);
@@ -187,7 +187,7 @@ static void sa1111_ack_irq(unsigned int irq)
 
 static void sa1111_mask_lowirq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ie0;
 
        ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -197,7 +197,7 @@ static void sa1111_mask_lowirq(unsigned int irq)
 
 static void sa1111_unmask_lowirq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ie0;
 
        ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -215,7 +215,7 @@ static void sa1111_unmask_lowirq(unsigned int irq)
 static int sa1111_retrigger_lowirq(unsigned int irq)
 {
        unsigned int mask = SA1111_IRQMASK_LO(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip0;
        int i;
 
@@ -236,7 +236,7 @@ static int sa1111_retrigger_lowirq(unsigned int irq)
 static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
 {
        unsigned int mask = SA1111_IRQMASK_LO(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip0;
 
        if (flags == IRQT_PROBE)
@@ -259,7 +259,7 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
 static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
 {
        unsigned int mask = SA1111_IRQMASK_LO(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long we0;
 
        we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
@@ -284,7 +284,7 @@ static struct irq_chip sa1111_low_chip = {
 
 static void sa1111_mask_highirq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ie1;
 
        ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -294,7 +294,7 @@ static void sa1111_mask_highirq(unsigned int irq)
 
 static void sa1111_unmask_highirq(unsigned int irq)
 {
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ie1;
 
        ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -312,7 +312,7 @@ static void sa1111_unmask_highirq(unsigned int irq)
 static int sa1111_retrigger_highirq(unsigned int irq)
 {
        unsigned int mask = SA1111_IRQMASK_HI(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip1;
        int i;
 
@@ -333,7 +333,7 @@ static int sa1111_retrigger_highirq(unsigned int irq)
 static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
 {
        unsigned int mask = SA1111_IRQMASK_HI(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip1;
 
        if (flags == IRQT_PROBE)
@@ -356,7 +356,7 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
 static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
 {
        unsigned int mask = SA1111_IRQMASK_HI(irq);
-       void __iomem *mapbase = get_irq_chipdata(irq);
+       void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long we1;
 
        we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
@@ -410,15 +410,15 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
 
        for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
                set_irq_chip(irq, &sa1111_low_chip);
-               set_irq_chipdata(irq, irqbase);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_chip_data(irq, irqbase);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
                set_irq_chip(irq, &sa1111_high_chip);
-               set_irq_chipdata(irq, irqbase);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_chip_data(irq, irqbase);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index 605dedf..b359974 100644 (file)
@@ -60,16 +60,16 @@ static int sharpsl_ac_check(void);
 static int sharpsl_fatal_check(void);
 static int sharpsl_average_value(int ad);
 static void sharpsl_average_clear(void);
-static void sharpsl_charge_toggle(void *private_);
-static void sharpsl_battery_thread(void *private_);
+static void sharpsl_charge_toggle(struct work_struct *private_);
+static void sharpsl_battery_thread(struct work_struct *private_);
 
 
 /*
  * Variables
  */
 struct sharpsl_pm_status sharpsl_pm;
-DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL);
-DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL);
+DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
+DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
 DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
 
 
@@ -116,7 +116,7 @@ void sharpsl_battery_kick(void)
 EXPORT_SYMBOL(sharpsl_battery_kick);
 
 
-static void sharpsl_battery_thread(void *private_)
+static void sharpsl_battery_thread(struct work_struct *private_)
 {
        int voltage, percent, apm_status, i = 0;
 
@@ -128,7 +128,7 @@ static void sharpsl_battery_thread(void *private_)
        /* Corgi cannot confirm when battery fully charged so periodically kick! */
        if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
                        && time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
-               schedule_work(&toggle_charger);
+               schedule_delayed_work(&toggle_charger, 0);
 
        while(1) {
                voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
@@ -212,7 +212,7 @@ static void sharpsl_charge_off(void)
        sharpsl_pm_led(SHARPSL_LED_OFF);
        sharpsl_pm.charge_mode = CHRG_OFF;
 
-       schedule_work(&sharpsl_bat);
+       schedule_delayed_work(&sharpsl_bat, 0);
 }
 
 static void sharpsl_charge_error(void)
@@ -222,7 +222,7 @@ static void sharpsl_charge_error(void)
        sharpsl_pm.charge_mode = CHRG_ERROR;
 }
 
-static void sharpsl_charge_toggle(void *private_)
+static void sharpsl_charge_toggle(struct work_struct *private_)
 {
        dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
 
@@ -254,7 +254,7 @@ static void sharpsl_ac_timer(unsigned long data)
        else if (sharpsl_pm.charge_mode == CHRG_ON)
                sharpsl_charge_off();
 
-       schedule_work(&sharpsl_bat);
+       schedule_delayed_work(&sharpsl_bat, 0);
 }
 
 
@@ -279,10 +279,10 @@ static void sharpsl_chrg_full_timer(unsigned long data)
                        sharpsl_charge_off();
        } else if (sharpsl_pm.full_count < 2) {
                dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
-               schedule_work(&toggle_charger);
+               schedule_delayed_work(&toggle_charger, 0);
        } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
                dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
-               schedule_work(&toggle_charger);
+               schedule_delayed_work(&toggle_charger, 0);
        } else {
                sharpsl_charge_off();
                sharpsl_pm.charge_mode = CHRG_DONE;
index 43d2781..c026fa2 100644 (file)
 
 static void vic_mask_irq(unsigned int irq)
 {
-       void __iomem *base = get_irq_chipdata(irq);
+       void __iomem *base = get_irq_chip_data(irq);
        irq &= 31;
        writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
 }
 
 static void vic_unmask_irq(unsigned int irq)
 {
-       void __iomem *base = get_irq_chipdata(irq);
+       void __iomem *base = get_irq_chip_data(irq);
        irq &= 31;
        writel(1 << irq, base + VIC_INT_ENABLE);
 }
@@ -88,10 +88,10 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
                unsigned int irq = irq_start + i;
 
                set_irq_chip(irq, &vic_chip);
-               set_irq_chipdata(irq, base);
+               set_irq_chip_data(irq, base);
 
                if (vic_sources & (1 << i)) {
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
        }
index b430414..e10d003 100644 (file)
@@ -357,9 +357,9 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x10000000
-CONFIG_MTD_PHYSMAP_LEN=0x200000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
 # CONFIG_MTD_PLATRAM is not set
@@ -585,7 +585,9 @@ CONFIG_AT91RM9200_WATCHDOG=y
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_AT91_RTC=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -979,7 +981,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index d96fc83..834dddb 100644 (file)
@@ -348,9 +348,9 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x10000000
-CONFIG_MTD_PHYSMAP_LEN=0x800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
 # CONFIG_MTD_PLATRAM is not set
@@ -566,7 +566,9 @@ CONFIG_AT91RM9200_WATCHDOG=y
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_AT91_RTC=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -968,7 +970,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
new file mode 100644 (file)
index 0000000..7904920
--- /dev/null
@@ -0,0 +1,950 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19-rc6
+# Fri Nov 17 18:42:21 2006
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_AT91SAM9260=y
+# CONFIG_ARCH_AT91SAM9261 is not set
+
+#
+# AT91SAM9260 Board Type
+#
+CONFIG_MACH_AT91SAM9260EK=y
+
+#
+# AT91 Board Options
+#
+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_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_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# 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 is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS 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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
new file mode 100644 (file)
index 0000000..784ad7c
--- /dev/null
@@ -0,0 +1,1106 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19-rc6
+# Fri Nov 17 18:00:38 2006
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+CONFIG_ARCH_AT91SAM9261=y
+
+#
+# AT91SAM9261 Board Type
+#
+CONFIG_MACH_AT91SAM9261EK=y
+
+#
+# AT91 Board Options
+#
+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_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_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR 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
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_AT91=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91=m
+# CONFIG_MMC_TIFM_SD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_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
+# 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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
index cfe6bd8..821865f 100644 (file)
@@ -1216,7 +1216,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index d24ae87..d392833 100644 (file)
@@ -474,7 +474,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_AT91_RTC is not set
+# CONFIG_AT91RM9200_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
index 09b7acd..ee130b5 100644 (file)
@@ -851,7 +851,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index a375891..970c8c7 100644 (file)
@@ -934,7 +934,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index c41c04f..e8980a9 100644 (file)
@@ -1513,7 +1513,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 20e6825..2cadd51 100644 (file)
@@ -1113,7 +1113,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index df8595a..94908c1 100644 (file)
@@ -623,7 +623,7 @@ CONFIG_AT91RM9200_WATCHDOG=y
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-# CONFIG_AT91_RTC is not set
+# CONFIG_AT91RM9200_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -1062,7 +1062,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 3b4802a..f8a66b7 100644 (file)
@@ -125,6 +125,7 @@ CONFIG_CRUNCH=y
 #
 # EP93xx Platforms
 #
+CONFIG_MACH_ADSSPHERE=y
 CONFIG_MACH_EDB9302=y
 CONFIG_MACH_EDB9312=y
 CONFIG_MACH_EDB9315=y
@@ -1134,7 +1135,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_WAITQ=y
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 9d62ed1..0e739af 100644 (file)
@@ -702,7 +702,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_LL is not set
 
index a45b575..1c8fb89 100644 (file)
@@ -740,7 +740,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_WAITQ=y
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 692ab57..3ce96e6 100644 (file)
@@ -835,7 +835,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig
new file mode 100644 (file)
index 0000000..f6e4619
--- /dev/null
@@ -0,0 +1,1134 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Fri Dec  1 10:51:01 2006
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=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=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE 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_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+CONFIG_ARCH_IOP13XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# IOP13XX Implementation Options
+#
+
+#
+# IOP13XX Platform Support
+#
+CONFIG_MACH_IQ81340SC=y
+CONFIG_MACH_IQ81340MC=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=bootp root=nfs console=ttyS0,115200 nfsroot=,tcp,v3,wsize=8192,rsize=8192"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# 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
+# CONFIG_SSFDC 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=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY 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_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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=0xfa000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_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=2
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# 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=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=y
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
+CONFIG_MD_RAID456=y
+# CONFIG_MD_RAID5_RESHAPE is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+# 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_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
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# 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_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO 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
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# 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
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM 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=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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_IOP3XX=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 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 is not set
+# 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_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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# 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 is not set
+# 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_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D 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_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=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
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS 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 is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_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_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS 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=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL 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=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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# 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 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_ENABLE_MUST_CHECK=y
+# 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_BUGVERBOSE=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
index 0d67f66..b275c53 100644 (file)
@@ -1204,7 +1204,6 @@ CONFIG_FRAME_POINTER=y
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 2a8fc15..848e3ac 100644 (file)
@@ -1051,7 +1051,6 @@ CONFIG_FRAME_POINTER=y
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 27b3e31..bbd2dcf 100644 (file)
@@ -1026,7 +1026,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 7b18997..06deefa 100644 (file)
@@ -1305,7 +1305,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index fac7c3b..fabf74c 100644 (file)
@@ -1243,7 +1243,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 80a6fd9..0c55628 100644 (file)
@@ -889,7 +889,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index b4cd4b4..c16537d 100644 (file)
@@ -437,7 +437,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_AT91_RTC is not set
+# CONFIG_AT91RM9200_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -753,7 +753,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 4b29e09..e146189 100644 (file)
@@ -949,7 +949,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index bf9cf9c..f8ac29d 100644 (file)
@@ -850,7 +850,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index 3a57be3..46a0f7f 100644 (file)
@@ -1100,7 +1100,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index 81daadc..e544bfb 100644 (file)
@@ -772,7 +772,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index b112bd7..cc8c95b 100644 (file)
@@ -766,7 +766,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index d16f6cd..577d7e1 100644 (file)
@@ -691,7 +691,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index df8168e..e86794a 100644 (file)
@@ -1115,7 +1115,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 2cae1ea..c1a63a3 100644 (file)
@@ -994,7 +994,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_LL is not set
 
index 61115a7..57f32f3 100644 (file)
@@ -872,7 +872,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index 9b9f215..0498ebd 100644 (file)
@@ -1045,7 +1045,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 24e8bdd..a6b47ea 100644 (file)
@@ -721,7 +721,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_LL is not set
 
index a4989f4..b5e11aa 100644 (file)
@@ -1604,7 +1604,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_LL is not set
 
index b71d31a..46e5089 100644 (file)
@@ -768,7 +768,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index ffd905f..fc39ba1 100644 (file)
@@ -967,7 +967,6 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 3f1ec4e..accbf52 100644 (file)
@@ -759,7 +759,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_LL is not set
 
index b498afd..bc09126 100644 (file)
@@ -910,7 +910,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index c015239..3b31a33 100644 (file)
@@ -1319,7 +1319,6 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index c48d170..9b6561d 100644 (file)
@@ -965,7 +965,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_LL is not set
 
index 140056a..03f783e 100644 (file)
@@ -934,7 +934,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index bd03238..aa7a011 100644 (file)
@@ -1406,7 +1406,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index f7bf6ef..48dca69 100644 (file)
@@ -972,7 +972,6 @@ CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
index 1320a0e..ab06a86 100644 (file)
@@ -24,7 +24,9 @@ obj-$(CONFIG_OABI_COMPAT)     += sys_oabi-compat.o
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o           := -Wa,-mcpu=ep9312
 
-obj-$(CONFIG_IWMMXT)           += iwmmxt.o iwmmxt-notifier.o
+obj-$(CONFIG_CPU_XSCALE)       += xscale-cp0.o
+obj-$(CONFIG_CPU_XSC3)         += xscale-cp0.o
+obj-$(CONFIG_IWMMXT)           += iwmmxt.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
index ecf4f94..a11fb9a 100644 (file)
@@ -12,7 +12,6 @@
  */
 #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>
@@ -26,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 #include <asm/apm.h> /* apm_power_info */
 #include <asm/system.h>
@@ -71,7 +71,8 @@ struct apm_user {
 #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 */
+#define SUSPEND_WAIT   4               /* waiting for suspend */
+#define SUSPEND_DONE   5               /* suspend completed */
 
        struct apm_queue        queue;
 };
@@ -101,6 +102,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
 static DEFINE_SPINLOCK(kapmd_queue_lock);
 static struct apm_queue kapmd_queue;
 
+static DEFINE_MUTEX(state_lock);
 
 static const char driver_version[] = "1.13";   /* no spaces */
 
@@ -148,38 +150,60 @@ static void queue_add_event(struct apm_queue *q, apm_event_t event)
        q->events[q->event_head] = event;
 }
 
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+static void queue_event(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;
+       struct apm_user *as;
 
-                       as->suspend_state = SUSPEND_PENDING;
-                       suspends_pending++;
-                       break;
-               }
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               if (as->reader)
+                       queue_add_event(&as->queue, event);
        }
-       queue_add_event(&as->queue, event);
+       up_read(&user_list_lock);
+       wake_up_interruptible(&apm_waitqueue);
 }
 
-static void queue_event(apm_event_t event, struct apm_user *sender)
+/*
+ * queue_suspend_event - queue an APM suspend event.
+ *
+ * Check that we're in a state where we can suspend.  If not,
+ * return -EBUSY.  Otherwise, queue an event to all "writer"
+ * users.  If there are no "writer" users, return '1' to
+ * indicate that we can immediately suspend.
+ */
+static int queue_suspend_event(apm_event_t event, struct apm_user *sender)
 {
        struct apm_user *as;
+       int ret = 1;
 
+       mutex_lock(&state_lock);
        down_read(&user_list_lock);
+
+       /*
+        * If a thread is still processing, we can't suspend, so reject
+        * the request.
+        */
        list_for_each_entry(as, &apm_user_list, list) {
-               if (as != sender && as->reader)
-                       queue_event_one_user(as, event);
+               if (as != sender && as->reader && as->writer && as->suser &&
+                   as->suspend_state != SUSPEND_NONE) {
+                       ret = -EBUSY;
+                       goto out;
+               }
        }
+
+       list_for_each_entry(as, &apm_user_list, list) {
+               if (as != sender && as->reader && as->writer && as->suser) {
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       queue_add_event(&as->queue, event);
+                       ret = 0;
+               }
+       }
+ out:
        up_read(&user_list_lock);
+       mutex_unlock(&state_lock);
        wake_up_interruptible(&apm_waitqueue);
+       return ret;
 }
 
 static void apm_suspend(void)
@@ -191,17 +215,22 @@ static void apm_suspend(void)
         * 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);
+       queue_event(APM_NORMAL_RESUME);
 
        /*
         * Finally, wake up anyone who is sleeping on the suspend.
         */
+       mutex_lock(&state_lock);
        down_read(&user_list_lock);
        list_for_each_entry(as, &apm_user_list, list) {
-               as->suspend_result = err;
-               as->suspend_state = SUSPEND_DONE;
+               if (as->suspend_state == SUSPEND_WAIT ||
+                   as->suspend_state == SUSPEND_ACKED) {
+                       as->suspend_result = err;
+                       as->suspend_state = SUSPEND_DONE;
+               }
        }
        up_read(&user_list_lock);
+       mutex_unlock(&state_lock);
 
        wake_up(&apm_suspend_waitqueue);
 }
@@ -227,8 +256,11 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t
                if (copy_to_user(buf, &event, sizeof(event)))
                        break;
 
-               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+               mutex_lock(&state_lock);
+               if (as->suspend_state == SUSPEND_PENDING &&
+                   (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND))
                        as->suspend_state = SUSPEND_READ;
+               mutex_unlock(&state_lock);
 
                buf += sizeof(event);
                i -= sizeof(event);
@@ -270,9 +302,13 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 
        switch (cmd) {
        case APM_IOC_SUSPEND:
+               mutex_lock(&state_lock);
+
                as->suspend_result = -EINTR;
 
                if (as->suspend_state == SUSPEND_READ) {
+                       int pending;
+
                        /*
                         * If we read a suspend command from /dev/apm_bios,
                         * then the corresponding APM_IOC_SUSPEND ioctl is
@@ -280,47 +316,73 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
                         */
                        as->suspend_state = SUSPEND_ACKED;
                        suspends_pending--;
+                       pending = suspends_pending == 0;
+                       mutex_unlock(&state_lock);
+
+                       /*
+                        * If there are no further acknowledges required,
+                        * suspend the system.
+                        */
+                       if (pending)
+                               apm_suspend();
+
+                       /*
+                        * Wait for the suspend/resume to complete.  If there
+                        * are pending acknowledges, we wait here for them.
+                        *
+                        * Note: 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;
+
+                       wait_event(apm_suspend_waitqueue,
+                                  as->suspend_state == SUSPEND_DONE);
                } else {
+                       as->suspend_state = SUSPEND_WAIT;
+                       mutex_unlock(&state_lock);
+
                        /*
                         * 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();
+                       err = queue_suspend_event(APM_USER_SUSPEND, as);
+                       if (err < 0) {
+                               /*
+                                * Avoid taking the lock here - this
+                                * should be fine.
+                                */
+                               as->suspend_state = SUSPEND_NONE;
+                               break;
+                       }
+
+                       if (err > 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;
+                       /*
+                        * Wait for the suspend/resume to complete.  If there
+                        * are pending acknowledges, we wait here for them.
+                        *
+                        * Note: 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;
+
+               mutex_lock(&state_lock);
                err = as->suspend_result;
                as->suspend_state = SUSPEND_NONE;
+               mutex_unlock(&state_lock);
                break;
        }
 
@@ -330,6 +392,8 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 static int apm_release(struct inode * inode, struct file * filp)
 {
        struct apm_user *as = filp->private_data;
+       int pending = 0;
+
        filp->private_data = NULL;
 
        down_write(&user_list_lock);
@@ -342,11 +406,14 @@ static int apm_release(struct inode * inode, struct file * filp)
         * need to balance suspends_pending, which means the
         * possibility of sleeping.
         */
+       mutex_lock(&state_lock);
        if (as->suspend_state != SUSPEND_NONE) {
                suspends_pending -= 1;
-               if (suspends_pending == 0)
-                       apm_suspend();
+               pending = suspends_pending == 0;
        }
+       mutex_unlock(&state_lock);
+       if (pending)
+               apm_suspend();
 
        kfree(as);
        return 0;
@@ -470,6 +537,7 @@ static int kapmd(void *arg)
 {
        do {
                apm_event_t event;
+               int ret;
 
                wait_event_interruptible(kapmd_wait,
                                !queue_empty(&kapmd_queue) || kthread_should_stop());
@@ -489,13 +557,20 @@ static int kapmd(void *arg)
 
                case APM_LOW_BATTERY:
                case APM_POWER_STATUS_CHANGE:
-                       queue_event(event, NULL);
+                       queue_event(event);
                        break;
 
                case APM_USER_SUSPEND:
                case APM_SYS_SUSPEND:
-                       queue_event(event, NULL);
-                       if (suspends_pending == 0)
+                       ret = queue_suspend_event(event, NULL);
+                       if (ret < 0) {
+                               /*
+                                * We were busy.  Try again in 50ms.
+                                */
+                               queue_add_event(&kapmd_queue, event);
+                               msleep(50);
+                       }
+                       if (ret > 0)
                                apm_suspend();
                        break;
 
index cc2d58d..3c078e3 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/mach/arch.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
+#include <asm/procinfo.h>
 
 /*
  * Make sure that the compiler and target are compatible.
index b27513a..a786f76 100644 (file)
@@ -529,7 +529,7 @@ static void ecard_dump_irq_state(void)
        }
 }
 
-static void ecard_check_lockup(struct irqdesc *desc)
+static void ecard_check_lockup(struct irq_desc *desc)
 {
        static unsigned long last;
        static int lockup;
@@ -567,7 +567,7 @@ static void ecard_check_lockup(struct irqdesc *desc)
 }
 
 static void
-ecard_irq_handler(unsigned int irq, struct irqdesc *desc)
+ecard_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        ecard_t *ec;
        int called = 0;
@@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc)
                        pending = ecard_default_ops.irqpending(ec);
 
                if (pending) {
-                       struct irqdesc *d = irq_desc + ec->irq;
+                       struct irq_desc *d = irq_desc + ec->irq;
                        desc_handle_irq(ec->irq, d);
                        called ++;
                }
@@ -609,7 +609,7 @@ static unsigned char first_set[] =
 };
 
 static void
-ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc)
+ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc)
 {
        const unsigned int statusmask = 15;
        unsigned int status;
@@ -1022,7 +1022,7 @@ ecard_probe(int slot, card_type_t type)
        if (slot < 8) {
                ec->irq = 32 + slot;
                set_irq_chip(ec->irq, &ecard_chip);
-               set_irq_handler(ec->irq, do_level_IRQ);
+               set_irq_handler(ec->irq, handle_level_irq);
                set_irq_flags(ec->irq, IRQF_VALID);
        }
 
index bd623b7..2db42b1 100644 (file)
@@ -589,10 +589,6 @@ ENTRY(__switch_to)
        strex   r5, r4, [ip]                    @ Clear exclusive monitor
 #endif
 #endif
-#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
-       mra     r4, r5, acc0
-       stmia   ip, {r4, r5}
-#endif
 #if defined(CONFIG_HAS_TLS_REG)
        mcr     p15, 0, r3, c13, c0, 3          @ set TLS register
 #elif !defined(CONFIG_TLS_REG_EMUL)
@@ -601,11 +597,6 @@ ENTRY(__switch_to)
 #endif
 #ifdef CONFIG_MMU
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
-#endif
-#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
-       add     r4, r2, #TI_CPU_DOMAIN + 40     @ cpu_context_save->extra
-       ldmib   r4, {r4, r5}
-       mar     acc0, r4, r5
 #endif
        mov     r5, r0
        add     r4, r2, #TI_CPU_SAVE
index f359a18..0119c0d 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/assembler.h>
 #include <asm/mach-types.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
index ebc3e74..bda0748 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/assembler.h>
 #include <asm/domain.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/memory.h>
index 2c4ff1c..ec01f08 100644 (file)
@@ -112,7 +112,7 @@ static struct irq_desc bad_irq_desc = {
 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
-       struct irqdesc *desc = irq_desc + irq;
+       struct irq_desc *desc = irq_desc + irq;
 
        /*
         * Some hardware gives randomly wrong interrupts.  Rather
@@ -134,7 +134,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 
 void set_irq_flags(unsigned int irq, unsigned int iflags)
 {
-       struct irqdesc *desc;
+       struct irq_desc *desc;
        unsigned long flags;
 
        if (irq >= NR_IRQS) {
@@ -171,7 +171,7 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
+static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
 {
        pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu);
 
@@ -190,7 +190,7 @@ void migrate_irqs(void)
        unsigned int i, cpu = smp_processor_id();
 
        for (i = 0; i < NR_IRQS; i++) {
-               struct irqdesc *desc = irq_desc + i;
+               struct irq_desc *desc = irq_desc + i;
 
                if (desc->cpu == cpu) {
                        unsigned int newcpu = any_online_cpu(desc->affinity);
diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c
deleted file mode 100644 (file)
index 0d1a1db..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  linux/arch/arm/kernel/iwmmxt-notifier.c
- *
- *  XScale iWMMXt (Concan) context switching and handling
- *
- *  Initial code:
- *  Copyright (c) 2003, Intel Corporation
- *
- *  Full lazy switching support, optimizations and more, by Nicolas Pitre
- *  Copyright (c) 2003-2004, MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <asm/thread_notify.h>
-#include <asm/io.h>
-
-static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
-{
-       struct thread_info *thread = t;
-
-       switch (cmd) {
-       case THREAD_NOTIFY_FLUSH:
-               /*
-                * flush_thread() zeroes thread->fpstate, so no need
-                * to do anything here.
-                *
-                * FALLTHROUGH: Ensure we don't try to overwrite our newly
-                * initialised state information on the first fault.
-                */
-
-       case THREAD_NOTIFY_RELEASE:
-               iwmmxt_task_release(thread);
-               break;
-
-       case THREAD_NOTIFY_SWITCH:
-               iwmmxt_task_switch(thread);
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block iwmmxt_notifier_block = {
-       .notifier_call  = iwmmxt_do,
-};
-
-static int __init iwmmxt_init(void)
-{
-       thread_register_notifier(&iwmmxt_notifier_block);
-
-       return 0;
-}
-
-late_initcall(iwmmxt_init);
index bf35c17..a9e8f7e 100644 (file)
@@ -280,67 +280,6 @@ void show_fpregs(struct user_fp *regs)
                (unsigned long)regs->fpcr);
 }
 
-/*
- * Task structure and kernel stack allocation.
- */
-struct thread_info_list {
-       unsigned long *head;
-       unsigned int nr;
-};
-
-static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 };
-
-#define EXTRA_TASK_STRUCT      4
-
-struct thread_info *alloc_thread_info(struct task_struct *task)
-{
-       struct thread_info *thread = NULL;
-
-       if (EXTRA_TASK_STRUCT) {
-               struct thread_info_list *th = &get_cpu_var(thread_info_list);
-               unsigned long *p = th->head;
-
-               if (p) {
-                       th->head = (unsigned long *)p[0];
-                       th->nr -= 1;
-               }
-               put_cpu_var(thread_info_list);
-
-               thread = (struct thread_info *)p;
-       }
-
-       if (!thread)
-               thread = (struct thread_info *)
-                          __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-       /*
-        * The stack must be cleared if you want SYSRQ-T to
-        * give sensible stack usage information
-        */
-       if (thread)
-               memzero(thread, THREAD_SIZE);
-#endif
-       return thread;
-}
-
-void free_thread_info(struct thread_info *thread)
-{
-       if (EXTRA_TASK_STRUCT) {
-               struct thread_info_list *th = &get_cpu_var(thread_info_list);
-               if (th->nr < EXTRA_TASK_STRUCT) {
-                       unsigned long *p = (unsigned long *)thread;
-                       p[0] = (unsigned long)th->head;
-                       th->head = p;
-                       th->nr += 1;
-                       put_cpu_var(thread_info_list);
-                       return;
-               }
-               put_cpu_var(thread_info_list);
-       }
-       free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
-}
-
 /*
  * Free current thread data structures etc..
  */
index 29efc9f..238dd9b 100644 (file)
@@ -357,9 +357,6 @@ static void __init setup_processor(void)
 #ifndef CONFIG_VFP
        elf_hwcap &= ~HWCAP_VFP;
 #endif
-#ifndef CONFIG_IWMMXT
-       elf_hwcap &= ~HWCAP_IWMMXT;
-#endif
 
        cpu_proc_init();
 }
@@ -441,16 +438,19 @@ __early_param("initrd=", early_initrd);
 
 static void __init arm_add_memory(unsigned long start, unsigned long size)
 {
+       struct membank *bank;
+
        /*
         * Ensure that start/size are aligned to a page boundary.
         * Size is appropriately rounded down, start is rounded up.
         */
        size -= start & ~PAGE_MASK;
 
-       meminfo.bank[meminfo.nr_banks].start = PAGE_ALIGN(start);
-       meminfo.bank[meminfo.nr_banks].size  = size & PAGE_MASK;
-       meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
-       meminfo.nr_banks += 1;
+       bank = &meminfo.bank[meminfo.nr_banks++];
+
+       bank->start = PAGE_ALIGN(start);
+       bank->size  = size & PAGE_MASK;
+       bank->node  = PHYS_TO_NID(start);
 }
 
 /*
index 48cf7ff..3843d3b 100644 (file)
@@ -11,7 +11,9 @@
 #include <linux/signal.h>
 #include <linux/ptrace.h>
 #include <linux/personality.h>
+#include <linux/freezer.h>
 
+#include <asm/elf.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
index bede380..042a129 100644 (file)
@@ -631,12 +631,9 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
        notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
-void __attribute__((noreturn)) __bug(const char *file, int line, void *data)
+void __attribute__((noreturn)) __bug(const char *file, int line)
 {
-       printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
-       if (data)
-               printk(" - extra data = %p", data);
-       printk("\n");
+       printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
        *(int *)0 = 0;
 
        /* Avoid "noreturn function does return" */
diff --git a/arch/arm/kernel/xscale-cp0.c b/arch/arm/kernel/xscale-cp0.c
new file mode 100644 (file)
index 0000000..180000b
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * linux/arch/arm/kernel/xscale-cp0.c
+ *
+ * XScale DSP and iWMMXt coprocessor context switching and handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/thread_notify.h>
+#include <asm/io.h>
+
+static inline void dsp_save_state(u32 *state)
+{
+       __asm__ __volatile__ (
+               "mrrc   p0, 0, %0, %1, c0\n"
+               : "=r" (state[0]), "=r" (state[1]));
+}
+
+static inline void dsp_load_state(u32 *state)
+{
+       __asm__ __volatile__ (
+               "mcrr   p0, 0, %0, %1, c0\n"
+               : : "r" (state[0]), "r" (state[1]));
+}
+
+static int dsp_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = t;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               thread->cpu_context.extra[0] = 0;
+               thread->cpu_context.extra[1] = 0;
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               dsp_save_state(current_thread_info()->cpu_context.extra);
+               dsp_load_state(thread->cpu_context.extra);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block dsp_notifier_block = {
+       .notifier_call  = dsp_do,
+};
+
+
+#ifdef CONFIG_IWMMXT
+static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = t;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               /*
+                * flush_thread() zeroes thread->fpstate, so no need
+                * to do anything here.
+                *
+                * FALLTHROUGH: Ensure we don't try to overwrite our newly
+                * initialised state information on the first fault.
+                */
+
+       case THREAD_NOTIFY_RELEASE:
+               iwmmxt_task_release(thread);
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               iwmmxt_task_switch(thread);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block iwmmxt_notifier_block = {
+       .notifier_call  = iwmmxt_do,
+};
+#endif
+
+
+static u32 __init xscale_cp_access_read(void)
+{
+       u32 value;
+
+       __asm__ __volatile__ (
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               : "=r" (value));
+
+       return value;
+}
+
+static void __init xscale_cp_access_write(u32 value)
+{
+       u32 temp;
+
+       __asm__ __volatile__ (
+               "mcr    p15, 0, %1, c15, c1, 0\n\t"
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "mov    %0, %0\n\t"
+               "sub    pc, pc, #4\n\t"
+               : "=r" (temp) : "r" (value));
+}
+
+/*
+ * Detect whether we have a MAC coprocessor (40 bit register) or an
+ * iWMMXt coprocessor (64 bit registers) by loading 00000100:00000000
+ * into a coprocessor register and reading it back, and checking
+ * whether the upper word survived intact.
+ */
+static int __init cpu_has_iwmmxt(void)
+{
+       u32 lo;
+       u32 hi;
+
+       /*
+        * This sequence is interpreted by the DSP coprocessor as:
+        *      mar     acc0, %2, %3
+        *      mra     %0, %1, acc0
+        *
+        * And by the iWMMXt coprocessor as:
+        *      tmcrr   wR0, %2, %3
+        *      tmrrc   %0, %1, wR0
+        */
+       __asm__ __volatile__ (
+               "mcrr   p0, 0, %2, %3, c0\n"
+               "mrrc   p0, 0, %0, %1, c0\n"
+               : "=r" (lo), "=r" (hi)
+               : "r" (0), "r" (0x100));
+
+       return !!hi;
+}
+
+
+/*
+ * If we detect that the CPU has iWMMXt (and CONFIG_IWMMXT=y), we
+ * disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
+ * switch code handle iWMMXt context switching.  If on the other
+ * hand the CPU has a DSP coprocessor, we keep access to CP0 enabled
+ * all the time, and save/restore acc0 on context switch in non-lazy
+ * fashion.
+ */
+static int __init xscale_cp0_init(void)
+{
+       u32 cp_access;
+
+       cp_access = xscale_cp_access_read() & ~3;
+       xscale_cp_access_write(cp_access | 1);
+
+       if (cpu_has_iwmmxt()) {
+#ifndef CONFIG_IWMMXT
+               printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor "
+                       "detected, but kernel support is missing.\n");
+#else
+               printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n");
+               elf_hwcap |= HWCAP_IWMMXT;
+               thread_register_notifier(&iwmmxt_notifier_block);
+#endif
+       } else {
+               printk(KERN_INFO "XScale DSP coprocessor detected.\n");
+               thread_register_notifier(&dsp_notifier_block);
+               cp_access |= 1;
+       }
+
+       xscale_cp_access_write(cp_access);
+
+       return 0;
+}
+
+late_initcall(xscale_cp0_init);
index fe3d297..a950160 100644 (file)
@@ -82,7 +82,7 @@ static void aaec2000_int_unmask(unsigned int irq)
        IRQ_INTENS |= (1 << irq);
 }
 
-static struct irqchip aaec2000_irq_chip = {
+static struct irq_chip aaec2000_irq_chip = {
        .ack    = aaec2000_int_ack,
        .mask   = aaec2000_int_mask,
        .unmask = aaec2000_int_unmask,
@@ -93,7 +93,7 @@ void __init aaec2000_init_irq(void)
        unsigned int i;
 
        for (i = 0; i < NR_IRQS; i++) {
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_chip(i, &aaec2000_irq_chip);
                set_irq_flags(i, IRQF_VALID);
        }
index 2f85e86..9f11db8 100644 (file)
@@ -2,7 +2,8 @@ if ARCH_AT91
 
 menu "Atmel AT91 System-on-Chip"
 
-comment "Atmel AT91 Processors"
+choice
+       prompt "Atmel AT91 Processor"
 
 config ARCH_AT91RM9200
        bool "AT91RM9200"
@@ -13,6 +14,8 @@ config ARCH_AT91SAM9260
 config ARCH_AT91SAM9261
        bool "AT91SAM9261"
 
+endchoice
+
 # ----------------------------------------------------------
 
 if ARCH_AT91RM9200
@@ -33,7 +36,6 @@ config ARCH_AT91RM9200DK
          Select this if you are using Atmel's AT91RM9200-DK Development board.
          (Discontinued)
 
-
 config MACH_AT91RM9200EK
        bool "Atmel AT91RM9200-EK Evaluation Kit"
        depends on ARCH_AT91RM9200
@@ -90,6 +92,13 @@ if ARCH_AT91SAM9260
 
 comment "AT91SAM9260 Board Type"
 
+config MACH_AT91SAM9260EK
+       bool "Atmel AT91SAM9260-EK Evaluation Kit"
+       depends on ARCH_AT91SAM9260
+       help
+         Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit.
+         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+
 endif
 
 # ----------------------------------------------------------
@@ -98,8 +107,31 @@ if ARCH_AT91SAM9261
 
 comment "AT91SAM9261 Board Type"
 
+config MACH_AT91SAM9261EK
+       bool "Atmel AT91SAM9261-EK Evaluation Kit"
+       depends on ARCH_AT91SAM9261
+       help
+         Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
+         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
+
 endif
 
+# ----------------------------------------------------------
+
+comment "AT91 Board Options"
+
+config MTD_AT91_DATAFLASH_CARD
+       bool "Enable DataFlash Card support"
+       depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK)
+       help
+         Enable support for the DataFlash card.
+
+config MTD_NAND_AT91_BUSWIDTH_16
+       bool "Enable 16-bit data bus interface to NAND flash"
+       depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK)
+       help
+         On AT91SAM926x boards both types of NAND flash can be present
+         (8 and 16 bit data bus width).
 
 # ----------------------------------------------------------
 
index c174805..cf77700 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y          := clock.o irq.o gpio.o devices.o
+obj-y          := clock.o irq.o gpio.o
 obj-m          :=
 obj-n          :=
 obj-           :=
@@ -10,11 +10,11 @@ obj-                :=
 obj-$(CONFIG_PM)               += pm.o
 
 # CPU-specific support
-obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200.o at91rm9200_time.o
-obj-$(CONFIG_ARCH_AT91SAM9260) +=
-obj-$(CONFIG_ARCH_AT91SAM9261) +=
+obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
 
-# AT91RM9200 Board-specific support
+# AT91RM9200 board-specific support
 obj-$(CONFIG_MACH_ONEARM)      += board-1arm.o
 obj-$(CONFIG_ARCH_AT91RM9200DK)        += board-dk.o
 obj-$(CONFIG_MACH_AT91RM9200EK)        += board-ek.o
@@ -26,8 +26,10 @@ obj-$(CONFIG_MACH_ATEB9200)  += board-eb9200.o
 obj-$(CONFIG_MACH_KAFA)                += board-kafa.o
 
 # AT91SAM9260 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
 
 # AT91SAM9261 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
 
 # LEDs support
 led-$(CONFIG_ARCH_AT91RM9200DK)        += leds.o
index dcf6136..a92e9a4 100644 (file)
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_st.h>
 
-#include <asm/hardware.h>
 #include "generic.h"
 #include "clock.h"
 
@@ -25,33 +27,13 @@ static struct map_desc at91rm9200_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(AT91_BASE_SYS),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_SPI,
-               .pfn            = __phys_to_pfn(AT91RM9200_BASE_SPI),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_EMAC,
                .pfn            = __phys_to_pfn(AT91RM9200_BASE_EMAC),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = AT91_VA_BASE_TWI,
-               .pfn            = __phys_to_pfn(AT91RM9200_BASE_TWI),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_MCI,
-               .pfn            = __phys_to_pfn(AT91RM9200_BASE_MCI),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_UDP,
-               .pfn            = __phys_to_pfn(AT91RM9200_BASE_UDP),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_SRAM_VIRT_BASE,
+               .virtual        = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE,
                .pfn            = __phys_to_pfn(AT91RM9200_SRAM_BASE),
                .length         = AT91RM9200_SRAM_SIZE,
                .type           = MT_DEVICE,
@@ -222,6 +204,16 @@ static struct at91_gpio_bank at91rm9200_gpio[] = {
        }
 };
 
+static void at91rm9200_reset(void)
+{
+       /*
+        * Perform a hardware reset with the use of the Watchdog timer.
+        */
+       at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+
 /* --------------------------------------------------------------------
  *  AT91RM9200 processor initialization
  * -------------------------------------------------------------------- */
@@ -230,6 +222,12 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks
        /* Map peripherals */
        iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 
+       at91_arch_reset = at91rm9200_reset;
+       at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
+                       | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
+                       | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
+                       | (1 << AT91RM9200_ID_IRQ6);
+
        /* Init clock subsystem */
        at91_clock_init(main_clock);
 
similarity index 83%
rename from arch/arm/mach-at91rm9200/devices.c
rename to arch/arm/mach-at91rm9200/at91rm9200_devices.c
index 0598243..4641b99 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91rm9200/devices.c
+ * arch/arm/mach-at91rm9200/at91rm9200_devices.c
  *
  *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
  *  Copyright (C) 2005 David Brownell
 
 #include <linux/platform_device.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91rm9200_mc.h>
 
 #include "generic.h"
 
@@ -33,7 +34,7 @@
 static u64 ohci_dmamask = 0xffffffffUL;
 static struct at91_usbh_data usbh_data;
 
-static struct resource at91_usbh_resources[] = {
+static struct resource usbh_resources[] = {
        [0] = {
                .start  = AT91RM9200_UHP_BASE,
                .end    = AT91RM9200_UHP_BASE + SZ_1M - 1,
@@ -54,8 +55,8 @@ static struct platform_device at91rm9200_usbh_device = {
                                .coherent_dma_mask      = 0xffffffff,
                                .platform_data          = &usbh_data,
        },
-       .resource       = at91_usbh_resources,
-       .num_resources  = ARRAY_SIZE(at91_usbh_resources),
+       .resource       = usbh_resources,
+       .num_resources  = ARRAY_SIZE(usbh_resources),
 };
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -78,7 +79,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
 #ifdef CONFIG_USB_GADGET_AT91
 static struct at91_udc_data udc_data;
 
-static struct resource at91_udc_resources[] = {
+static struct resource udc_resources[] = {
        [0] = {
                .start  = AT91RM9200_BASE_UDP,
                .end    = AT91RM9200_BASE_UDP + SZ_16K - 1,
@@ -97,8 +98,8 @@ static struct platform_device at91rm9200_udc_device = {
        .dev            = {
                                .platform_data          = &udc_data,
        },
-       .resource       = at91_udc_resources,
-       .num_resources  = ARRAY_SIZE(at91_udc_resources),
+       .resource       = udc_resources,
+       .num_resources  = ARRAY_SIZE(udc_resources),
 };
 
 void __init at91_add_device_udc(struct at91_udc_data *data)
@@ -129,7 +130,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
 static u64 eth_dmamask = 0xffffffffUL;
 static struct at91_eth_data eth_data;
 
-static struct resource at91_eth_resources[] = {
+static struct resource eth_resources[] = {
        [0] = {
                .start  = AT91_VA_BASE_EMAC,
                .end    = AT91_VA_BASE_EMAC + SZ_16K - 1,
@@ -150,8 +151,8 @@ static struct platform_device at91rm9200_eth_device = {
                                .coherent_dma_mask      = 0xffffffff,
                                .platform_data          = &eth_data,
        },
-       .resource       = at91_eth_resources,
-       .num_resources  = ARRAY_SIZE(at91_eth_resources),
+       .resource       = eth_resources,
+       .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
 void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -202,11 +203,13 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
 #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
 static struct at91_cf_data cf_data;
 
-static struct resource at91_cf_resources[] = {
+#define CF_BASE                AT91_CHIPSELECT_4
+
+static struct resource cf_resources[] = {
        [0] = {
-               .start  = AT91_CF_BASE,
+               .start  = CF_BASE,
                /* ties up CS4, CS5 and CS6 */
-               .end    = AT91_CF_BASE + (0x30000000 - 1),
+               .end    = CF_BASE + (0x30000000 - 1),
                .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
        },
 };
@@ -217,15 +220,38 @@ static struct platform_device at91rm9200_cf_device = {
        .dev            = {
                                .platform_data          = &cf_data,
        },
-       .resource       = at91_cf_resources,
-       .num_resources  = ARRAY_SIZE(at91_cf_resources),
+       .resource       = cf_resources,
+       .num_resources  = ARRAY_SIZE(cf_resources),
 };
 
 void __init at91_add_device_cf(struct at91_cf_data *data)
 {
+       unsigned int csa;
+
        if (!data)
                return;
 
+       data->chipselect = 4;           /* can only use EBI ChipSelect 4 */
+
+       /* CF takes over CS4, CS5, CS6 */
+       csa = at91_sys_read(AT91_EBI_CSA);
+       at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+       /*
+        * Static memory controller timing adjustments.
+        * REVISIT:  these timings are in terms of MCK cycles, so
+        * when MCK changes (cpufreq etc) so must these values...
+        */
+       at91_sys_write(AT91_SMC_CSR(4),
+                                 AT91_SMC_ACSS_STD
+                               | AT91_SMC_DBW_16
+                               | AT91_SMC_BAT
+                               | AT91_SMC_WSEN
+                               | AT91_SMC_NWS_(32)     /* wait states */
+                               | AT91_SMC_RWSETUP_(6)  /* setup time */
+                               | AT91_SMC_RWHOLD_(4)   /* hold time */
+       );
+
        /* input/irq */
        if (data->irq_pin) {
                at91_set_gpio_input(data->irq_pin, 1);
@@ -245,6 +271,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
        at91_set_A_periph(AT91_PIN_PC11, 0);    /* NCS5/CFCE1 */
        at91_set_A_periph(AT91_PIN_PC12, 0);    /* NCS6/CFCE2 */
 
+       /* nWAIT is _not_ a default setting */
+       at91_set_A_periph(AT91_PIN_PC6, 1);     /*  nWAIT */
+
        cf_data = *data;
        platform_device_register(&at91rm9200_cf_device);
 }
@@ -257,11 +286,11 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE)
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
 static u64 mmc_dmamask = 0xffffffffUL;
 static struct at91_mmc_data mmc_data;
 
-static struct resource at91_mmc_resources[] = {
+static struct resource mmc_resources[] = {
        [0] = {
                .start  = AT91RM9200_BASE_MCI,
                .end    = AT91RM9200_BASE_MCI + SZ_16K - 1,
@@ -282,8 +311,8 @@ static struct platform_device at91rm9200_mmc_device = {
                                .coherent_dma_mask      = 0xffffffff,
                                .platform_data          = &mmc_data,
        },
-       .resource       = at91_mmc_resources,
-       .num_resources  = ARRAY_SIZE(at91_mmc_resources),
+       .resource       = mmc_resources,
+       .num_resources  = ARRAY_SIZE(mmc_resources),
 };
 
 void __init at91_add_device_mmc(struct at91_mmc_data *data)
@@ -298,31 +327,33 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
        }
        if (data->wp_pin)
                at91_set_gpio_input(data->wp_pin, 1);
+       if (data->vcc_pin)
+               at91_set_gpio_output(data->vcc_pin, 0);
 
        /* CLK */
        at91_set_A_periph(AT91_PIN_PA27, 0);
 
-       if (data->is_b) {
+       if (data->slot_b) {
                /* CMD */
-               at91_set_B_periph(AT91_PIN_PA8, 0);
+               at91_set_B_periph(AT91_PIN_PA8, 1);
 
                /* DAT0, maybe DAT1..DAT3 */
-               at91_set_B_periph(AT91_PIN_PA9, 0);
+               at91_set_B_periph(AT91_PIN_PA9, 1);
                if (data->wire4) {
-                       at91_set_B_periph(AT91_PIN_PA10, 0);
-                       at91_set_B_periph(AT91_PIN_PA11, 0);
-                       at91_set_B_periph(AT91_PIN_PA12, 0);
+                       at91_set_B_periph(AT91_PIN_PA10, 1);
+                       at91_set_B_periph(AT91_PIN_PA11, 1);
+                       at91_set_B_periph(AT91_PIN_PA12, 1);
                }
        } else {
                /* CMD */
-               at91_set_A_periph(AT91_PIN_PA28, 0);
+               at91_set_A_periph(AT91_PIN_PA28, 1);
 
                /* DAT0, maybe DAT1..DAT3 */
-               at91_set_A_periph(AT91_PIN_PA29, 0);
+               at91_set_A_periph(AT91_PIN_PA29, 1);
                if (data->wire4) {
-                       at91_set_B_periph(AT91_PIN_PB3, 0);
-                       at91_set_B_periph(AT91_PIN_PB4, 0);
-                       at91_set_B_periph(AT91_PIN_PB5, 0);
+                       at91_set_B_periph(AT91_PIN_PB3, 1);
+                       at91_set_B_periph(AT91_PIN_PB4, 1);
+                       at91_set_B_periph(AT91_PIN_PB5, 1);
                }
        }
 
@@ -341,29 +372,45 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
 static struct at91_nand_data nand_data;
 
-static struct resource at91_nand_resources[] = {
+#define NAND_BASE      AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
        {
-               .start  = AT91_SMARTMEDIA_BASE,
-               .end    = AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+               .start  = NAND_BASE,
+               .end    = NAND_BASE + SZ_8M - 1,
                .flags  = IORESOURCE_MEM,
        }
 };
 
-static struct platform_device at91_nand_device = {
+static struct platform_device at91rm9200_nand_device = {
        .name           = "at91_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
        },
-       .resource       = at91_nand_resources,
-       .num_resources  = ARRAY_SIZE(at91_nand_resources),
+       .resource       = nand_resources,
+       .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
 void __init at91_add_device_nand(struct at91_nand_data *data)
 {
+       unsigned int csa;
+
        if (!data)
                return;
 
+       /* enable the address range of CS3 */
+       csa = at91_sys_read(AT91_EBI_CSA);
+       at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
+
+       /* set the bus interface characteristics */
+       at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
+               | AT91_SMC_NWS_(5)
+               | AT91_SMC_TDF_(1)
+               | AT91_SMC_RWSETUP_(0)  /* tDS Data Set up Time 30 - ns */
+               | AT91_SMC_RWHOLD_(1)   /* tDH Data Hold Time 20 - ns */
+       );
+
        /* enable pin */
        if (data->enable_pin)
                at91_set_gpio_output(data->enable_pin, 1);
@@ -380,7 +427,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        at91_set_A_periph(AT91_PIN_PC3, 0);             /* SMWE */
 
        nand_data = *data;
-       platform_device_register(&at91_nand_device);
+       platform_device_register(&at91rm9200_nand_device);
 }
 #else
 void __init at91_add_device_nand(struct at91_nand_data *data) {}
@@ -392,10 +439,25 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+       [0] = {
+               .start  = AT91RM9200_BASE_TWI,
+               .end    = AT91RM9200_BASE_TWI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91RM9200_ID_TWI,
+               .end    = AT91RM9200_ID_TWI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct platform_device at91rm9200_twi_device = {
        .name           = "at91_i2c",
        .id             = -1,
-       .num_resources  = 0,
+       .resource       = twi_resources,
+       .num_resources  = ARRAY_SIZE(twi_resources),
 };
 
 void __init at91_add_device_i2c(void)
@@ -421,7 +483,7 @@ void __init at91_add_device_i2c(void) {}
 #if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
 static u64 spi_dmamask = 0xffffffffUL;
 
-static struct resource at91_spi_resources[] = {
+static struct resource spi_resources[] = {
        [0] = {
                .start  = AT91RM9200_BASE_SPI,
                .end    = AT91RM9200_BASE_SPI + SZ_16K - 1,
@@ -438,14 +500,14 @@ static struct platform_device at91rm9200_spi_device = {
        .name           = "at91_spi",
        .id             = 0,
        .dev            = {
-               .dma_mask               = &spi_dmamask,
-               .coherent_dma_mask      = 0xffffffff,
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
        },
-       .resource       = at91_spi_resources,
-       .num_resources  = ARRAY_SIZE(at91_spi_resources),
+       .resource       = spi_resources,
+       .num_resources  = ARRAY_SIZE(spi_resources),
 };
 
-static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
 
 void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
 {
@@ -461,7 +523,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                if (devices[i].controller_data)
                        cs_pin = (unsigned long) devices[i].controller_data;
                else
-                       cs_pin = at91_spi_standard_cs[devices[i].chip_select];
+                       cs_pin = spi_standard_cs[devices[i].chip_select];
 
 #ifdef CONFIG_SPI_AT91_MANUAL_CS
                at91_set_gpio_output(cs_pin, 1);
@@ -474,7 +536,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
        }
 
        spi_register_board_info(devices, nr_devices);
-       at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi");
+       at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi");
        platform_device_register(&at91rm9200_spi_device);
 }
 #else
@@ -486,7 +548,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
  *  RTC
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE)
+#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
 static struct platform_device at91rm9200_rtc_device = {
        .name           = "at91_rtc",
        .id             = -1,
@@ -506,7 +568,7 @@ static void __init at91_add_device_rtc(void) {}
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
 static struct platform_device at91rm9200_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index 07c9cea..b999e19 100644 (file)
@@ -30,6 +30,8 @@
 #include <asm/io.h>
 #include <asm/mach/time.h>
 
+#include <asm/arch/at91_st.h>
+
 static unsigned long last_crtr;
 
 /*
@@ -99,6 +101,9 @@ void at91rm9200_timer_reset(void)
        /* Set Period Interval timer */
        at91_sys_write(AT91_ST_PIMR, LATCH);
 
+       /* Clear any pending interrupts */
+       (void) at91_sys_read(AT91_ST_SR);
+
        /* Enable Period Interval Timer interrupt */
        at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
 }
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c
new file mode 100644 (file)
index 0000000..203f073
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * arch/arm/mach-at91rm9200/at91sam9260.c
+ *
+ *  Copyright (C) 2006 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91_pmc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9260_io_desc[] __initdata = {
+       {
+               .virtual        = AT91_VA_BASE_SYS,
+               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
+               .pfn            = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
+               .length         = AT91SAM9260_SRAM0_SIZE,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
+               .pfn            = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
+               .length         = AT91SAM9260_SRAM1_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+       .name           = "pioA_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_PIOA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+       .name           = "pioB_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_PIOB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+       .name           = "pioC_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_PIOC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk adc_clk = {
+       .name           = "adc_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_ADC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+       .name           = "usart0_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+       .name           = "usart1_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+       .name           = "usart2_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+       .name           = "mci_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_MCI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+       .name           = "udc_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_UDP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+       .name           = "twi_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_TWI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+       .name           = "spi0_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_SPI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+       .name           = "spi1_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_SPI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+       .name           = "ohci_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_UHP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ether_clk = {
+       .name           = "ether_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_EMAC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+       .name           = "isi_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_ISI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+       .name           = "usart3_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US3,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart4_clk = {
+       .name           = "usart4_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US4,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart5_clk = {
+       .name           = "usart5_clk",
+       .pmc_mask       = 1 << AT91SAM9260_ID_US5,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+       &pioA_clk,
+       &pioB_clk,
+       &pioC_clk,
+       &adc_clk,
+       &usart0_clk,
+       &usart1_clk,
+       &usart2_clk,
+       &mmc_clk,
+       &udc_clk,
+       &twi_clk,
+       &spi0_clk,
+       &spi1_clk,
+       // ssc
+       // tc0 .. tc2
+       &ohci_clk,
+       &ether_clk,
+       &isi_clk,
+       &usart3_clk,
+       &usart4_clk,
+       &usart5_clk,
+       // tc3 .. tc5
+       // irq0 .. irq2
+};
+
+/*
+ * The two programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+       .name           = "pck0",
+       .pmc_mask       = AT91_PMC_PCK0,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 0,
+};
+static struct clk pck1 = {
+       .name           = "pck1",
+       .pmc_mask       = AT91_PMC_PCK1,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 1,
+};
+
+static void __init at91sam9260_register_clocks(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+               clk_register(periph_clocks[i]);
+
+       clk_register(&pck0);
+       clk_register(&pck1);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9260_gpio[] = {
+       {
+               .id             = AT91SAM9260_ID_PIOA,
+               .offset         = AT91_PIOA,
+               .clock          = &pioA_clk,
+       }, {
+               .id             = AT91SAM9260_ID_PIOB,
+               .offset         = AT91_PIOB,
+               .clock          = &pioB_clk,
+       }, {
+               .id             = AT91SAM9260_ID_PIOC,
+               .offset         = AT91_PIOC,
+               .clock          = &pioC_clk,
+       }
+};
+
+static void at91sam9260_reset(void)
+{
+#warning "Implement CPU reset"
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9260 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9260_initialize(unsigned long main_clock)
+{
+       /* Map peripherals */
+       iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
+
+       at91_arch_reset = at91sam9260_reset;
+       at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+                       | (1 << AT91SAM9260_ID_IRQ2);
+
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at91sam9260_register_clocks();
+
+       /* Register GPIO subsystem */
+       at91_gpio_init(at91sam9260_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
+       7,      /* Advanced Interrupt Controller */
+       7,      /* System Peripherals */
+       0,      /* Parallel IO Controller A */
+       0,      /* Parallel IO Controller B */
+       0,      /* Parallel IO Controller C */
+       0,      /* Analog-to-Digital Converter */
+       6,      /* USART 0 */
+       6,      /* USART 1 */
+       6,      /* USART 2 */
+       0,      /* Multimedia Card Interface */
+       4,      /* USB Device Port */
+       0,      /* Two-Wire Interface */
+       6,      /* Serial Peripheral Interface 0 */
+       6,      /* Serial Peripheral Interface 1 */
+       5,      /* Serial Synchronous Controller */
+       0,
+       0,
+       0,      /* Timer Counter 0 */
+       0,      /* Timer Counter 1 */
+       0,      /* Timer Counter 2 */
+       3,      /* USB Host port */
+       3,      /* Ethernet */
+       0,      /* Image Sensor Interface */
+       6,      /* USART 3 */
+       6,      /* USART 4 */
+       6,      /* USART 5 */
+       0,      /* Timer Counter 3 */
+       0,      /* Timer Counter 4 */
+       0,      /* Timer Counter 5 */
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+};
+
+void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+       if (!priority)
+               priority = at91sam9260_default_irq_priority;
+
+       /* Initialize the AIC interrupt controller */
+       at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c
new file mode 100644 (file)
index 0000000..a6c596d
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ * arch/arm/mach-at91rm9200/at91sam9260_devices.c
+ *
+ *  Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16  0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_UHP_BASE,
+               .end    = AT91SAM9260_UHP_BASE + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_UHP,
+               .end    = AT91SAM9260_ID_UHP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91_usbh_device = {
+       .name           = "at91_ohci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &ohci_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &usbh_data,
+       },
+       .resource       = usbh_resources,
+       .num_resources  = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+       if (!data)
+               return;
+
+       usbh_data = *data;
+       platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_UDP,
+               .end    = AT91SAM9260_BASE_UDP + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_UDP,
+               .end    = AT91SAM9260_ID_UDP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91_udc_device = {
+       .name           = "at91_udc",
+       .id             = -1,
+       .dev            = {
+                               .platform_data          = &udc_data,
+       },
+       .resource       = udc_resources,
+       .num_resources  = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->vbus_pin) {
+               at91_set_gpio_input(data->vbus_pin, 0);
+               at91_set_deglitch(data->vbus_pin, 1);
+       }
+
+       /* Pullup pin is handled internally by USB device peripheral */
+
+       udc_data = *data;
+       platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct eth_platform_data eth_data;
+
+static struct resource eth_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_EMAC,
+               .end    = AT91SAM9260_BASE_EMAC + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_EMAC,
+               .end    = AT91SAM9260_ID_EMAC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9260_eth_device = {
+       .name           = "macb",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &eth_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &eth_data,
+       },
+       .resource       = eth_resources,
+       .num_resources  = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct eth_platform_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->phy_irq_pin) {
+               at91_set_gpio_input(data->phy_irq_pin, 0);
+               at91_set_deglitch(data->phy_irq_pin, 1);
+       }
+
+       /* Pins used for MII and RMII */
+       at91_set_A_periph(AT91_PIN_PA19, 0);    /* ETXCK_EREFCK */
+       at91_set_A_periph(AT91_PIN_PA17, 0);    /* ERXDV */
+       at91_set_A_periph(AT91_PIN_PA14, 0);    /* ERX0 */
+       at91_set_A_periph(AT91_PIN_PA15, 0);    /* ERX1 */
+       at91_set_A_periph(AT91_PIN_PA18, 0);    /* ERXER */
+       at91_set_A_periph(AT91_PIN_PA16, 0);    /* ETXEN */
+       at91_set_A_periph(AT91_PIN_PA12, 0);    /* ETX0 */
+       at91_set_A_periph(AT91_PIN_PA13, 0);    /* ETX1 */
+       at91_set_A_periph(AT91_PIN_PA21, 0);    /* EMDIO */
+       at91_set_A_periph(AT91_PIN_PA20, 0);    /* EMDC */
+
+       if (!data->is_rmii) {
+               at91_set_B_periph(AT91_PIN_PA28, 0);    /* ECRS */
+               at91_set_B_periph(AT91_PIN_PA29, 0);    /* ECOL */
+               at91_set_B_periph(AT91_PIN_PA25, 0);    /* ERX2 */
+               at91_set_B_periph(AT91_PIN_PA26, 0);    /* ERX3 */
+               at91_set_B_periph(AT91_PIN_PA27, 0);    /* ERXCK */
+               at91_set_B_periph(AT91_PIN_PA23, 0);    /* ETX2 */
+               at91_set_B_periph(AT91_PIN_PA24, 0);    /* ETX3 */
+               at91_set_B_periph(AT91_PIN_PA22, 0);    /* ETXER */
+       }
+
+       eth_data = *data;
+       platform_device_register(&at91sam9260_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct eth_platform_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_MCI,
+               .end    = AT91SAM9260_BASE_MCI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_MCI,
+               .end    = AT91SAM9260_ID_MCI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9260_mmc_device = {
+       .name           = "at91_mci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &mmc_data,
+       },
+       .resource       = mmc_resources,
+       .num_resources  = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(struct at91_mmc_data *data)
+{
+       if (!data)
+               return;
+
+       /* input/irq */
+       if (data->det_pin) {
+               at91_set_gpio_input(data->det_pin, 1);
+               at91_set_deglitch(data->det_pin, 1);
+       }
+       if (data->wp_pin)
+               at91_set_gpio_input(data->wp_pin, 1);
+       if (data->vcc_pin)
+               at91_set_gpio_output(data->vcc_pin, 0);
+
+       /* CLK */
+       at91_set_A_periph(AT91_PIN_PA8, 0);
+
+       if (data->slot_b) {
+               /* CMD */
+               at91_set_B_periph(AT91_PIN_PA1, 1);
+
+               /* DAT0, maybe DAT1..DAT3 */
+               at91_set_B_periph(AT91_PIN_PA0, 1);
+               if (data->wire4) {
+                       at91_set_B_periph(AT91_PIN_PA5, 1);
+                       at91_set_B_periph(AT91_PIN_PA4, 1);
+                       at91_set_B_periph(AT91_PIN_PA3, 1);
+               }
+       } else {
+               /* CMD */
+               at91_set_A_periph(AT91_PIN_PA7, 1);
+
+               /* DAT0, maybe DAT1..DAT3 */
+               at91_set_A_periph(AT91_PIN_PA6, 1);
+               if (data->wire4) {
+                       at91_set_A_periph(AT91_PIN_PA9, 1);
+                       at91_set_A_periph(AT91_PIN_PA10, 1);
+                       at91_set_A_periph(AT91_PIN_PA11, 1);
+               }
+       }
+
+       mmc_data = *data;
+       platform_device_register(&at91sam9260_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE      AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+       {
+               .start  = NAND_BASE,
+               .end    = NAND_BASE + SZ_8M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device at91sam9260_nand_device = {
+       .name           = "at91_nand",
+       .id             = -1,
+       .dev            = {
+                               .platform_data  = &nand_data,
+       },
+       .resource       = nand_resources,
+       .num_resources  = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+       unsigned long csa, mode;
+
+       if (!data)
+               return;
+
+       csa = at91_sys_read(AT91_MATRIX_EBICSA);
+       at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+       /* set the bus interface characteristics */
+       at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+                       | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+       at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+                       | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+       at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+       if (data->bus_width_16)
+               mode = AT91_SMC_DBW_16;
+       else
+               mode = AT91_SMC_DBW_8;
+       at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+       /* enable pin */
+       if (data->enable_pin)
+               at91_set_gpio_output(data->enable_pin, 1);
+
+       /* ready/busy pin */
+       if (data->rdy_pin)
+               at91_set_gpio_input(data->rdy_pin, 1);
+
+       /* card detect pin */
+       if (data->det_pin)
+               at91_set_gpio_input(data->det_pin, 1);
+
+       nand_data = *data;
+       platform_device_register(&at91sam9260_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_TWI,
+               .end    = AT91SAM9260_BASE_TWI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_TWI,
+               .end    = AT91SAM9260_ID_TWI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9260_twi_device = {
+       .name           = "at91_i2c",
+       .id             = -1,
+       .resource       = twi_resources,
+       .num_resources  = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+       /* pins used for TWI interface */
+       at91_set_A_periph(AT91_PIN_PA23, 0);            /* TWD */
+       at91_set_multi_drive(AT91_PIN_PA23, 1);
+
+       at91_set_A_periph(AT91_PIN_PA24, 0);            /* TWCK */
+       at91_set_multi_drive(AT91_PIN_PA24, 1);
+
+       platform_device_register(&at91sam9260_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_SPI0,
+               .end    = AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_SPI0,
+               .end    = AT91SAM9260_ID_SPI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9260_spi0_device = {
+       .name           = "atmel_spi",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi0_resources,
+       .num_resources  = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
+
+static struct resource spi1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_SPI1,
+               .end    = AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_SPI1,
+               .end    = AT91SAM9260_ID_SPI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9260_spi1_device = {
+       .name           = "atmel_spi",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi1_resources,
+       .num_resources  = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+       int i;
+       unsigned long cs_pin;
+       short enable_spi0 = 0;
+       short enable_spi1 = 0;
+
+       /* Choose SPI chip-selects */
+       for (i = 0; i < nr_devices; i++) {
+               if (devices[i].controller_data)
+                       cs_pin = (unsigned long) devices[i].controller_data;
+               else if (devices[i].bus_num == 0)
+                       cs_pin = spi0_standard_cs[devices[i].chip_select];
+               else
+                       cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+               if (devices[i].bus_num == 0)
+                       enable_spi0 = 1;
+               else
+                       enable_spi1 = 1;
+
+               /* enable chip-select pin */
+               at91_set_gpio_output(cs_pin, 1);
+
+               /* pass chip-select pin to driver */
+               devices[i].controller_data = (void *) cs_pin;
+       }
+
+       spi_register_board_info(devices, nr_devices);
+
+       /* Configure SPI bus(es) */
+       if (enable_spi0) {
+               at91_set_A_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
+               at91_set_A_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
+               at91_set_A_periph(AT91_PIN_PA2, 0);     /* SPI1_SPCK */
+
+               at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk");
+               platform_device_register(&at91sam9260_spi0_device);
+       }
+       if (enable_spi1) {
+               at91_set_A_periph(AT91_PIN_PB0, 0);     /* SPI1_MISO */
+               at91_set_A_periph(AT91_PIN_PB1, 0);     /* SPI1_MOSI */
+               at91_set_A_periph(AT91_PIN_PB2, 0);     /* SPI1_SPCK */
+
+               at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk");
+               platform_device_register(&at91sam9260_spi1_device);
+       }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+       at91_leds_cpu   = cpu_led;
+       at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+       [0] = {
+               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
+               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91_ID_SYS,
+               .end    = AT91_ID_SYS,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data dbgu_data = {
+       .use_dma_tx     = 0,
+       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
+       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9260_dbgu_device = {
+       .name           = "atmel_usart",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &dbgu_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = dbgu_resources,
+       .num_resources  = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB14, 0);            /* DRXD */
+       at91_set_A_periph(AT91_PIN_PB15, 1);            /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US0,
+               .end    = AT91SAM9260_BASE_US0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US0,
+               .end    = AT91SAM9260_ID_US0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart0_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart0_device = {
+       .name           = "atmel_usart",
+       .id             = 1,
+       .dev            = {
+                               .platform_data  = &uart0_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart0_resources,
+       .num_resources  = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB4, 1);             /* TXD0 */
+       at91_set_A_periph(AT91_PIN_PB5, 0);             /* RXD0 */
+       at91_set_A_periph(AT91_PIN_PB26, 0);            /* RTS0 */
+       at91_set_A_periph(AT91_PIN_PB27, 0);            /* CTS0 */
+       at91_set_A_periph(AT91_PIN_PB24, 0);            /* DTR0 */
+       at91_set_A_periph(AT91_PIN_PB22, 0);            /* DSR0 */
+       at91_set_A_periph(AT91_PIN_PB23, 0);            /* DCD0 */
+       at91_set_A_periph(AT91_PIN_PB25, 0);            /* RI0 */
+}
+
+static struct resource uart1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US1,
+               .end    = AT91SAM9260_BASE_US1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US1,
+               .end    = AT91SAM9260_ID_US1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart1_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart1_device = {
+       .name           = "atmel_usart",
+       .id             = 2,
+       .dev            = {
+                               .platform_data  = &uart1_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart1_resources,
+       .num_resources  = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB6, 1);             /* TXD1 */
+       at91_set_A_periph(AT91_PIN_PB7, 0);             /* RXD1 */
+       at91_set_A_periph(AT91_PIN_PB28, 0);            /* RTS1 */
+       at91_set_A_periph(AT91_PIN_PB29, 0);            /* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US2,
+               .end    = AT91SAM9260_BASE_US2 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US2,
+               .end    = AT91SAM9260_ID_US2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart2_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart2_device = {
+       .name           = "atmel_usart",
+       .id             = 3,
+       .dev            = {
+                               .platform_data  = &uart2_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart2_resources,
+       .num_resources  = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB8, 1);             /* TXD2 */
+       at91_set_A_periph(AT91_PIN_PB9, 0);             /* RXD2 */
+}
+
+static struct resource uart3_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US3,
+               .end    = AT91SAM9260_BASE_US3 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US3,
+               .end    = AT91SAM9260_ID_US3,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart3_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart3_device = {
+       .name           = "atmel_usart",
+       .id             = 4,
+       .dev            = {
+                               .platform_data  = &uart3_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart3_resources,
+       .num_resources  = ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB10, 1);            /* TXD3 */
+       at91_set_A_periph(AT91_PIN_PB11, 0);            /* RXD3 */
+}
+
+static struct resource uart4_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US4,
+               .end    = AT91SAM9260_BASE_US4 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US4,
+               .end    = AT91SAM9260_ID_US4,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart4_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart4_device = {
+       .name           = "atmel_usart",
+       .id             = 5,
+       .dev            = {
+                               .platform_data  = &uart4_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart4_resources,
+       .num_resources  = ARRAY_SIZE(uart4_resources),
+};
+
+static inline void configure_usart4_pins(void)
+{
+       at91_set_B_periph(AT91_PIN_PA31, 1);            /* TXD4 */
+       at91_set_B_periph(AT91_PIN_PA30, 0);            /* RXD4 */
+}
+
+static struct resource uart5_resources[] = {
+       [0] = {
+               .start  = AT91SAM9260_BASE_US5,
+               .end    = AT91SAM9260_BASE_US5 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9260_ID_US5,
+               .end    = AT91SAM9260_ID_US5,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart5_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9260_uart5_device = {
+       .name           = "atmel_usart",
+       .id             = 6,
+       .dev            = {
+                               .platform_data  = &uart5_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart5_resources,
+       .num_resources  = ARRAY_SIZE(uart5_resources),
+};
+
+static inline void configure_usart5_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PB12, 1);            /* TXD5 */
+       at91_set_A_periph(AT91_PIN_PB13, 0);            /* RXD5 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];    /* the UARTs to use */
+struct platform_device *atmel_default_console_device;  /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+       int i;
+
+       /* Fill in list of supported UARTs */
+       for (i = 0; i < config->nr_tty; i++) {
+               switch (config->tty_map[i]) {
+                       case 0:
+                               configure_usart0_pins();
+                               at91_uarts[i] = &at91sam9260_uart0_device;
+                               at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
+                               break;
+                       case 1:
+                               configure_usart1_pins();
+                               at91_uarts[i] = &at91sam9260_uart1_device;
+                               at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
+                               break;
+                       case 2:
+                               configure_usart2_pins();
+                               at91_uarts[i] = &at91sam9260_uart2_device;
+                               at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
+                               break;
+                       case 3:
+                               configure_usart3_pins();
+                               at91_uarts[i] = &at91sam9260_uart3_device;
+                               at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
+                               break;
+                       case 4:
+                               configure_usart4_pins();
+                               at91_uarts[i] = &at91sam9260_uart4_device;
+                               at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
+                               break;
+                       case 5:
+                               configure_usart5_pins();
+                               at91_uarts[i] = &at91sam9260_uart5_device;
+                               at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
+                               break;
+                       case 6:
+                               configure_dbgu_pins();
+                               at91_uarts[i] = &at91sam9260_dbgu_device;
+                               at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
+                               break;
+                       default:
+                               continue;
+               }
+               at91_uarts[i]->id = i;          /* update ID number to mapped ID */
+       }
+
+       /* Set serial console device */
+       if (config->console_tty < ATMEL_MAX_UART)
+               atmel_default_console_device = at91_uarts[config->console_tty];
+       if (!atmel_default_console_device)
+               printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+       int i;
+
+       for (i = 0; i < ATMEL_MAX_UART; i++) {
+               if (at91_uarts[i])
+                       platform_device_register(at91_uarts[i]);
+       }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+       return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c
new file mode 100644 (file)
index 0000000..5a82f35
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * arch/arm/mach-at91rm9200/at91sam9261.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91_pmc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9261_io_desc[] __initdata = {
+       {
+               .virtual        = AT91_VA_BASE_SYS,
+               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
+               .pfn            = __phys_to_pfn(AT91SAM9261_SRAM_BASE),
+               .length         = AT91SAM9261_SRAM_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+       .name           = "pioA_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_PIOA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+       .name           = "pioB_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_PIOB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+       .name           = "pioC_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_PIOC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+       .name           = "usart0_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_US0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+       .name           = "usart1_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_US1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+       .name           = "usart2_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_US2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+       .name           = "mci_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_MCI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+       .name           = "udc_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_UDP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+       .name           = "twi_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_TWI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+       .name           = "spi0_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_SPI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+       .name           = "spi1_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_SPI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+       .name           = "ohci_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_UHP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+       .name           = "lcdc_clk",
+       .pmc_mask       = 1 << AT91SAM9261_ID_LCDC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+       &pioA_clk,
+       &pioB_clk,
+       &pioC_clk,
+       &usart0_clk,
+       &usart1_clk,
+       &usart2_clk,
+       &mmc_clk,
+       &udc_clk,
+       &twi_clk,
+       &spi0_clk,
+       &spi1_clk,
+       // ssc 0 .. ssc2
+       // tc0 .. tc2
+       &ohci_clk,
+       &lcdc_clk,
+       // irq0 .. irq2
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+       .name           = "pck0",
+       .pmc_mask       = AT91_PMC_PCK0,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 0,
+};
+static struct clk pck1 = {
+       .name           = "pck1",
+       .pmc_mask       = AT91_PMC_PCK1,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 1,
+};
+static struct clk pck2 = {
+       .name           = "pck2",
+       .pmc_mask       = AT91_PMC_PCK2,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 2,
+};
+static struct clk pck3 = {
+       .name           = "pck3",
+       .pmc_mask       = AT91_PMC_PCK3,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 3,
+};
+
+/* HClocks */
+static struct clk hck0 = {
+       .name           = "hck0",
+       .pmc_mask       = AT91_PMC_HCK0,
+       .type           = CLK_TYPE_SYSTEM,
+       .id             = 0,
+};
+static struct clk hck1 = {
+       .name           = "hck1",
+       .pmc_mask       = AT91_PMC_HCK1,
+       .type           = CLK_TYPE_SYSTEM,
+       .id             = 1,
+};
+
+static void __init at91sam9261_register_clocks(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+               clk_register(periph_clocks[i]);
+
+       clk_register(&pck0);
+       clk_register(&pck1);
+       clk_register(&pck2);
+       clk_register(&pck3);
+
+       clk_register(&hck0);
+       clk_register(&hck1);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9261_gpio[] = {
+       {
+               .id             = AT91SAM9261_ID_PIOA,
+               .offset         = AT91_PIOA,
+               .clock          = &pioA_clk,
+       }, {
+               .id             = AT91SAM9261_ID_PIOB,
+               .offset         = AT91_PIOB,
+               .clock          = &pioB_clk,
+       }, {
+               .id             = AT91SAM9261_ID_PIOC,
+               .offset         = AT91_PIOC,
+               .clock          = &pioC_clk,
+       }
+};
+
+static void at91sam9261_reset(void)
+{
+#warning "Implement CPU reset"
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9261 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9261_initialize(unsigned long main_clock)
+{
+       /* Map peripherals */
+       iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
+
+       at91_arch_reset = at91sam9261_reset;
+       at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
+                       | (1 << AT91SAM9261_ID_IRQ2);
+
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at91sam9261_register_clocks();
+
+       /* Register GPIO subsystem */
+       at91_gpio_init(at91sam9261_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
+       7,      /* Advanced Interrupt Controller */
+       7,      /* System Peripherals */
+       0,      /* Parallel IO Controller A */
+       0,      /* Parallel IO Controller B */
+       0,      /* Parallel IO Controller C */
+       0,
+       6,      /* USART 0 */
+       6,      /* USART 1 */
+       6,      /* USART 2 */
+       0,      /* Multimedia Card Interface */
+       4,      /* USB Device Port */
+       0,      /* Two-Wire Interface */
+       6,      /* Serial Peripheral Interface 0 */
+       6,      /* Serial Peripheral Interface 1 */
+       5,      /* Serial Synchronous Controller 0 */
+       5,      /* Serial Synchronous Controller 1 */
+       5,      /* Serial Synchronous Controller 2 */
+       0,      /* Timer Counter 0 */
+       0,      /* Timer Counter 1 */
+       0,      /* Timer Counter 2 */
+       3,      /* USB Host port */
+       3,      /* LCD Controller */
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+};
+
+void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+       if (!priority)
+               priority = at91sam9261_default_irq_priority;
+
+       /* Initialize the AIC interrupt controller */
+       at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91rm9200/at91sam9261_devices.c
new file mode 100644 (file)
index 0000000..ed1d790
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ * arch/arm/mach-at91rm9200/at91sam9261_devices.c
+ *
+ *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *  Copyright (C) 2005 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 option) any later version.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91sam9261_matrix.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16  0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_UHP_BASE,
+               .end    = AT91SAM9261_UHP_BASE + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_UHP,
+               .end    = AT91SAM9261_ID_UHP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_usbh_device = {
+       .name           = "at91_ohci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &ohci_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &usbh_data,
+       },
+       .resource       = usbh_resources,
+       .num_resources  = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+       if (!data)
+               return;
+
+       usbh_data = *data;
+       platform_device_register(&at91sam9261_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_UDP,
+               .end    = AT91SAM9261_BASE_UDP + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_UDP,
+               .end    = AT91SAM9261_ID_UDP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_udc_device = {
+       .name           = "at91_udc",
+       .id             = -1,
+       .dev            = {
+                               .platform_data          = &udc_data,
+       },
+       .resource       = udc_resources,
+       .num_resources  = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+       unsigned long x;
+
+       if (!data)
+               return;
+
+       if (data->vbus_pin) {
+               at91_set_gpio_input(data->vbus_pin, 0);
+               at91_set_deglitch(data->vbus_pin, 1);
+       }
+
+       /* Pullup pin is handled internally */
+       x = at91_sys_read(AT91_MATRIX_USBPUCR);
+       at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON);
+
+       udc_data = *data;
+       platform_device_register(&at91sam9261_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_MCI,
+               .end    = AT91SAM9261_BASE_MCI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_MCI,
+               .end    = AT91SAM9261_ID_MCI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_mmc_device = {
+       .name           = "at91_mci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &mmc_data,
+       },
+       .resource       = mmc_resources,
+       .num_resources  = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(struct at91_mmc_data *data)
+{
+       if (!data)
+               return;
+
+       /* input/irq */
+       if (data->det_pin) {
+               at91_set_gpio_input(data->det_pin, 1);
+               at91_set_deglitch(data->det_pin, 1);
+       }
+       if (data->wp_pin)
+               at91_set_gpio_input(data->wp_pin, 1);
+       if (data->vcc_pin)
+               at91_set_gpio_output(data->vcc_pin, 0);
+
+       /* CLK */
+       at91_set_B_periph(AT91_PIN_PA2, 0);
+
+       /* CMD */
+       at91_set_B_periph(AT91_PIN_PA1, 1);
+
+       /* DAT0, maybe DAT1..DAT3 */
+       at91_set_B_periph(AT91_PIN_PA0, 1);
+       if (data->wire4) {
+               at91_set_B_periph(AT91_PIN_PA4, 1);
+               at91_set_B_periph(AT91_PIN_PA5, 1);
+               at91_set_B_periph(AT91_PIN_PA6, 1);
+       }
+
+       mmc_data = *data;
+       platform_device_register(&at91sam9261_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE      AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+       {
+               .start  = NAND_BASE,
+               .end    = NAND_BASE + SZ_256M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device at91_nand_device = {
+       .name           = "at91_nand",
+       .id             = -1,
+       .dev            = {
+                               .platform_data  = &nand_data,
+       },
+       .resource       = nand_resources,
+       .num_resources  = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+       unsigned long csa, mode;
+
+       if (!data)
+               return;
+
+       csa = at91_sys_read(AT91_MATRIX_EBICSA);
+       at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+       /* set the bus interface characteristics */
+       at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+                       | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+       at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+                       | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+       at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+       if (data->bus_width_16)
+               mode = AT91_SMC_DBW_16;
+       else
+               mode = AT91_SMC_DBW_8;
+       at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+       /* enable pin */
+       if (data->enable_pin)
+               at91_set_gpio_output(data->enable_pin, 1);
+
+       /* ready/busy pin */
+       if (data->rdy_pin)
+               at91_set_gpio_input(data->rdy_pin, 1);
+
+       /* card detect pin */
+       if (data->det_pin)
+               at91_set_gpio_input(data->det_pin, 1);
+
+       at91_set_A_periph(AT91_PIN_PC0, 0);             /* NANDOE */
+       at91_set_A_periph(AT91_PIN_PC1, 0);             /* NANDWE */
+
+       nand_data = *data;
+       platform_device_register(&at91_nand_device);
+}
+
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_TWI,
+               .end    = AT91SAM9261_BASE_TWI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_TWI,
+               .end    = AT91SAM9261_ID_TWI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_twi_device = {
+       .name           = "at91_i2c",
+       .id             = -1,
+       .resource       = twi_resources,
+       .num_resources  = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+       /* pins used for TWI interface */
+       at91_set_A_periph(AT91_PIN_PA7, 0);             /* TWD */
+       at91_set_multi_drive(AT91_PIN_PA7, 1);
+
+       at91_set_A_periph(AT91_PIN_PA8, 0);             /* TWCK */
+       at91_set_multi_drive(AT91_PIN_PA8, 1);
+
+       platform_device_register(&at91sam9261_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_SPI0,
+               .end    = AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_SPI0,
+               .end    = AT91SAM9261_ID_SPI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_spi0_device = {
+       .name           = "atmel_spi",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi0_resources,
+       .num_resources  = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+static struct resource spi1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_SPI1,
+               .end    = AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_SPI1,
+               .end    = AT91SAM9261_ID_SPI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9261_spi1_device = {
+       .name           = "atmel_spi",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &spi_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+       },
+       .resource       = spi1_resources,
+       .num_resources  = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+       int i;
+       unsigned long cs_pin;
+       short enable_spi0 = 0;
+       short enable_spi1 = 0;
+
+       /* Choose SPI chip-selects */
+       for (i = 0; i < nr_devices; i++) {
+               if (devices[i].controller_data)
+                       cs_pin = (unsigned long) devices[i].controller_data;
+               else if (devices[i].bus_num == 0)
+                       cs_pin = spi0_standard_cs[devices[i].chip_select];
+               else
+                       cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+               if (devices[i].bus_num == 0)
+                       enable_spi0 = 1;
+               else
+                       enable_spi1 = 1;
+
+               /* enable chip-select pin */
+               at91_set_gpio_output(cs_pin, 1);
+
+               /* pass chip-select pin to driver */
+               devices[i].controller_data = (void *) cs_pin;
+       }
+
+       spi_register_board_info(devices, nr_devices);
+
+       /* Configure SPI bus(es) */
+       if (enable_spi0) {
+               at91_set_A_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
+               at91_set_A_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
+               at91_set_A_periph(AT91_PIN_PA2, 0);     /* SPI0_SPCK */
+
+               at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk");
+               platform_device_register(&at91sam9261_spi0_device);
+       }
+       if (enable_spi1) {
+               at91_set_A_periph(AT91_PIN_PB30, 0);    /* SPI1_MISO */
+               at91_set_A_periph(AT91_PIN_PB31, 0);    /* SPI1_MOSI */
+               at91_set_A_periph(AT91_PIN_PB29, 0);    /* SPI1_SPCK */
+
+               at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk");
+               platform_device_register(&at91sam9261_spi1_device);
+       }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LCD Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
+static u64 lcdc_dmamask = 0xffffffffUL;
+static struct at91fb_info lcdc_data;
+
+static struct resource lcdc_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_LCDC_BASE,
+               .end    = AT91SAM9261_LCDC_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_LCDC,
+               .end    = AT91SAM9261_ID_LCDC,
+               .flags  = IORESOURCE_IRQ,
+       },
+#if defined(CONFIG_FB_INTSRAM)
+       [2] = {
+               .start  = AT91SAM9261_SRAM_BASE,
+               .end    = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device at91_lcdc_device = {
+       .name           = "at91-fb",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &lcdc_dmamask,
+                               .coherent_dma_mask      = 0xffffffff,
+                               .platform_data          = &lcdc_data,
+       },
+       .resource       = lcdc_resources,
+       .num_resources  = ARRAY_SIZE(lcdc_resources),
+};
+
+void __init at91_add_device_lcdc(struct at91fb_info *data)
+{
+       if (!data) {
+               return;
+       }
+
+       at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
+       at91_set_A_periph(AT91_PIN_PB2, 0);     /* LCDDOTCK */
+       at91_set_A_periph(AT91_PIN_PB3, 0);     /* LCDDEN */
+       at91_set_A_periph(AT91_PIN_PB4, 0);     /* LCDCC */
+       at91_set_A_periph(AT91_PIN_PB7, 0);     /* LCDD2 */
+       at91_set_A_periph(AT91_PIN_PB8, 0);     /* LCDD3 */
+       at91_set_A_periph(AT91_PIN_PB9, 0);     /* LCDD4 */
+       at91_set_A_periph(AT91_PIN_PB10, 0);    /* LCDD5 */
+       at91_set_A_periph(AT91_PIN_PB11, 0);    /* LCDD6 */
+       at91_set_A_periph(AT91_PIN_PB12, 0);    /* LCDD7 */
+       at91_set_A_periph(AT91_PIN_PB15, 0);    /* LCDD10 */
+       at91_set_A_periph(AT91_PIN_PB16, 0);    /* LCDD11 */
+       at91_set_A_periph(AT91_PIN_PB17, 0);    /* LCDD12 */
+       at91_set_A_periph(AT91_PIN_PB18, 0);    /* LCDD13 */
+       at91_set_A_periph(AT91_PIN_PB19, 0);    /* LCDD14 */
+       at91_set_A_periph(AT91_PIN_PB20, 0);    /* LCDD15 */
+       at91_set_B_periph(AT91_PIN_PB23, 0);    /* LCDD18 */
+       at91_set_B_periph(AT91_PIN_PB24, 0);    /* LCDD19 */
+       at91_set_B_periph(AT91_PIN_PB25, 0);    /* LCDD20 */
+       at91_set_B_periph(AT91_PIN_PB26, 0);    /* LCDD21 */
+       at91_set_B_periph(AT91_PIN_PB27, 0);    /* LCDD22 */
+       at91_set_B_periph(AT91_PIN_PB28, 0);    /* LCDD23 */
+
+       lcdc_data = *data;
+       platform_device_register(&at91_lcdc_device);
+}
+#else
+void __init at91_add_device_lcdc(struct at91fb_info *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+       at91_leds_cpu   = cpu_led;
+       at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+       [0] = {
+               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
+               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91_ID_SYS,
+               .end    = AT91_ID_SYS,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data dbgu_data = {
+       .use_dma_tx     = 0,
+       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
+       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9261_dbgu_device = {
+       .name           = "atmel_usart",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &dbgu_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = dbgu_resources,
+       .num_resources  = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PA9, 0);             /* DRXD */
+       at91_set_A_periph(AT91_PIN_PA10, 1);            /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_US0,
+               .end    = AT91SAM9261_BASE_US0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_US0,
+               .end    = AT91SAM9261_ID_US0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart0_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9261_uart0_device = {
+       .name           = "atmel_usart",
+       .id             = 1,
+       .dev            = {
+                               .platform_data  = &uart0_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart0_resources,
+       .num_resources  = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PC8, 1);             /* TXD0 */
+       at91_set_A_periph(AT91_PIN_PC9, 0);             /* RXD0 */
+       at91_set_A_periph(AT91_PIN_PC10, 0);            /* RTS0 */
+       at91_set_A_periph(AT91_PIN_PC11, 0);            /* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_US1,
+               .end    = AT91SAM9261_BASE_US1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_US1,
+               .end    = AT91SAM9261_ID_US1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart1_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9261_uart1_device = {
+       .name           = "atmel_usart",
+       .id             = 2,
+       .dev            = {
+                               .platform_data  = &uart1_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart1_resources,
+       .num_resources  = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PC12, 1);            /* TXD1 */
+       at91_set_A_periph(AT91_PIN_PC13, 0);            /* RXD1 */
+}
+
+static struct resource uart2_resources[] = {
+       [0] = {
+               .start  = AT91SAM9261_BASE_US2,
+               .end    = AT91SAM9261_BASE_US2 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9261_ID_US2,
+               .end    = AT91SAM9261_ID_US2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct atmel_uart_data uart2_data = {
+       .use_dma_tx     = 1,
+       .use_dma_rx     = 1,
+};
+
+static struct platform_device at91sam9261_uart2_device = {
+       .name           = "atmel_usart",
+       .id             = 3,
+       .dev            = {
+                               .platform_data  = &uart2_data,
+                               .coherent_dma_mask = 0xffffffff,
+       },
+       .resource       = uart2_resources,
+       .num_resources  = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+       at91_set_A_periph(AT91_PIN_PC15, 0);            /* RXD2 */
+       at91_set_A_periph(AT91_PIN_PC14, 1);            /* TXD2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];    /* the UARTs to use */
+struct platform_device *atmel_default_console_device;  /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+       int i;
+
+       /* Fill in list of supported UARTs */
+       for (i = 0; i < config->nr_tty; i++) {
+               switch (config->tty_map[i]) {
+                       case 0:
+                               configure_usart0_pins();
+                               at91_uarts[i] = &at91sam9261_uart0_device;
+                               at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
+                               break;
+                       case 1:
+                               configure_usart1_pins();
+                               at91_uarts[i] = &at91sam9261_uart1_device;
+                               at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
+                               break;
+                       case 2:
+                               configure_usart2_pins();
+                               at91_uarts[i] = &at91sam9261_uart2_device;
+                               at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
+                               break;
+                       case 3:
+                               configure_dbgu_pins();
+                               at91_uarts[i] = &at91sam9261_dbgu_device;
+                               at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
+                               break;
+                       default:
+                               continue;
+               }
+               at91_uarts[i]->id = i;          /* update ID number to mapped ID */
+       }
+
+       /* Set serial console device */
+       if (config->console_tty < ATMEL_MAX_UART)
+               atmel_default_console_device = at91_uarts[config->console_tty];
+       if (!atmel_default_console_device)
+               printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+       int i;
+
+       for (i = 0; i < ATMEL_MAX_UART; i++) {
+               if (at91_uarts[i])
+                       platform_device_register(at91_uarts[i]);
+       }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+       return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91rm9200/at91sam926x_time.c
new file mode 100644 (file)
index 0000000..99df5f6
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c
+ *
+ * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+ * Revision     2005 M. Nicolas Diremdjian, ATMEL Rousset, France
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/at91_pit.h>
+
+
+#define PIT_CPIV(x)    ((x) & AT91_PIT_CPIV)
+#define PIT_PICNT(x)   (((x) & AT91_PIT_PICNT) >> 20)
+
+/*
+ * Returns number of microseconds since last timer interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ *  'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91sam926x_gettimeoffset(void)
+{
+       unsigned long elapsed;
+       unsigned long t = at91_sys_read(AT91_PIT_PIIR);
+
+       elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);         /* hardware clock cycles */
+
+       return (unsigned long)(elapsed * 1000000) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+{
+       volatile long nr_ticks;
+
+       if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) {       /* This is a shared interrupt */
+               write_seqlock(&xtime_lock);
+
+               /* Get number to ticks performed before interrupt and clear PIT interrupt */
+               nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+               do {
+                       timer_tick();
+                       nr_ticks--;
+               } while (nr_ticks);
+
+               write_sequnlock(&xtime_lock);
+               return IRQ_HANDLED;
+       } else
+               return IRQ_NONE;                /* not handled */
+}
+
+static struct irqaction at91sam926x_timer_irq = {
+       .name           = "at91_tick",
+       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+       .handler        = at91sam926x_timer_interrupt
+};
+
+void at91sam926x_timer_reset(void)
+{
+       /* Disable timer */
+       at91_sys_write(AT91_PIT_MR, 0);
+
+       /* Clear any pending interrupts */
+       (void) at91_sys_read(AT91_PIT_PIVR);
+
+       /* Set Period Interval timer and enable its interrupt */
+       at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91sam926x_timer_init(void)
+{
+       /* Initialize and enable the timer */
+       at91sam926x_timer_reset();
+
+       /* Make IRQs happen for the system timer. */
+       setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
+}
+
+#ifdef CONFIG_PM
+static void at91sam926x_timer_suspend(void)
+{
+       /* Disable timer */
+       at91_sys_write(AT91_PIT_MR, 0);
+}
+#else
+#define at91sam926x_timer_suspend      NULL
+#endif
+
+struct sys_timer at91sam926x_timer = {
+       .init           = at91sam926x_timer_init,
+       .offset         = at91sam926x_gettimeoffset,
+       .suspend        = at91sam926x_timer_suspend,
+       .resume         = at91sam926x_timer_reset,
+};
+
index 9820874..654f037 100644 (file)
@@ -65,7 +65,6 @@ static void __init carmeva_init_irq(void)
        at91rm9200_init_interrupts(NULL);
 }
 
-
 static struct at91_eth_data __initdata carmeva_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -89,8 +88,33 @@ static struct at91_udc_data __initdata carmeva_udc_data = {
 // };
 
 static struct at91_mmc_data __initdata carmeva_mmc_data = {
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
+       .det_pin        = AT91_PIN_PB10,
+       .wp_pin         = AT91_PIN_PC14,
+};
+
+static struct spi_board_info carmeva_spi_devices[] = {
+       { /* DataFlash chip */
+               .modalias = "mtd_dataflash",
+               .chip_select  = 0,
+               .max_speed_hz = 10 * 1000 * 1000,
+       },
+       { /* User accessable spi - cs1 (250KHz) */
+               .modalias = "spi-cs1",
+               .chip_select  = 1,
+               .max_speed_hz = 250 *  1000,
+       },
+       { /* User accessable spi - cs2 (1MHz) */
+               .modalias = "spi-cs2",
+               .chip_select  = 2,
+               .max_speed_hz = 1 * 1000 *  1000,
+       },
+       { /* User accessable spi - cs3 (10MHz) */
+               .modalias = "spi-cs3",
+               .chip_select  = 3,
+               .max_speed_hz = 10 * 1000 *  1000,
+       },
 };
 
 static void __init carmeva_board_init(void)
@@ -105,10 +129,10 @@ static void __init carmeva_board_init(void)
        at91_add_device_udc(&carmeva_udc_data);
        /* I2C */
        at91_add_device_i2c();
+       /* SPI */
+       at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
        /* Compact Flash */
 //     at91_add_device_cf(&carmeva_cf_data);
-       /* SPI */
-//     at91_add_device_spi(NULL, 0);
        /* MMC */
        at91_add_device_mmc(&carmeva_mmc_data);
 }
index 8eeae49..b8bb805 100644 (file)
@@ -99,7 +99,7 @@ static struct at91_cf_data __initdata csb337_cf_data = {
 
 static struct at91_mmc_data __initdata csb337_mmc_data = {
        .det_pin        = AT91_PIN_PD5,
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
        .wp_pin         = AT91_PIN_PD6,
 };
index c699f39..7522bf9 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -39,6 +40,7 @@
 
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
 
 #include "generic.h"
 
@@ -93,7 +95,7 @@ static struct at91_cf_data __initdata dk_cf_data = {
 };
 
 static struct at91_mmc_data __initdata dk_mmc_data = {
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
 };
 
@@ -145,6 +147,30 @@ static struct at91_nand_data __initdata dk_nand_data = {
        .partition_info = nand_partitions,
 };
 
+#define DK_FLASH_BASE  AT91_CHIPSELECT_0
+#define DK_FLASH_SIZE  0x200000
+
+static struct physmap_flash_data dk_flash_data = {
+       .width  = 2,
+};
+
+static struct resource dk_flash_resource = {
+       .start          = DK_FLASH_BASE,
+       .end            = DK_FLASH_BASE + DK_FLASH_SIZE - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device dk_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &dk_flash_data,
+                       },
+       .resource       = &dk_flash_resource,
+       .num_resources  = 1,
+};
+
+
 static void __init dk_board_init(void)
 {
        /* Serial */
@@ -172,6 +198,8 @@ static void __init dk_board_init(void)
 #endif
        /* NAND */
        at91_add_device_nand(&dk_nand_data);
+       /* NOR Flash */
+       platform_device_register(&dk_flash);
        /* VGA */
 //     dk_add_device_video();
 }
index 65e867b..80b72cf 100644 (file)
@@ -87,7 +87,7 @@ static struct at91_cf_data __initdata eb9200_cf_data = {
 };
 
 static struct at91_mmc_data __initdata eb9200_mmc_data = {
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
 };
 
index 830eb79..c4fdb41 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -39,6 +40,7 @@
 
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
 
 #include "generic.h"
 
@@ -87,7 +89,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
 
 static struct at91_mmc_data __initdata ek_mmc_data = {
        .det_pin        = AT91_PIN_PB27,
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
        .wp_pin         = AT91_PIN_PA17,
 };
@@ -107,6 +109,30 @@ static struct spi_board_info ek_spi_devices[] = {
 #endif
 };
 
+#define EK_FLASH_BASE  AT91_CHIPSELECT_0
+#define EK_FLASH_SIZE  0x200000
+
+static struct physmap_flash_data ek_flash_data = {
+       .width  = 2,
+};
+
+static struct resource ek_flash_resource = {
+       .start          = EK_FLASH_BASE,
+       .end            = EK_FLASH_BASE + EK_FLASH_SIZE - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device ek_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &ek_flash_data,
+                       },
+       .resource       = &ek_flash_resource,
+       .num_resources  = 1,
+};
+
+
 static void __init ek_board_init(void)
 {
        /* Serial */
@@ -130,6 +156,8 @@ static void __init ek_board_init(void)
        at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
        at91_add_device_mmc(&ek_mmc_data);
 #endif
+       /* NOR Flash */
+       platform_device_register(&ek_flash);
        /* VGA */
 //     ek_add_device_video();
 }
index 35a954a..759d819 100644 (file)
@@ -84,7 +84,7 @@ static struct at91_udc_data __initdata kb9202_udc_data = {
 
 static struct at91_mmc_data __initdata kb9202_mmc_data = {
        .det_pin        = AT91_PIN_PB2,
-       .is_b           = 0,
+       .slot_b         = 0,
        .wire4          = 1,
 };
 
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c
new file mode 100644 (file)
index 0000000..ffca9bd
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 5 = USART0 .. USART5
+ *    6      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 3,
+       .tty_map        = { 6, 0, 1, -1, -1, -1, -1 }   /* ttyS0, ..., ttyS6 */
+};
+
+static void __init ek_map_io(void)
+{
+       /* Initialize processor: 18.432 MHz crystal */
+       at91sam9260_initialize(18432000);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+       at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+       .ports          = 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+       .vbus_pin       = AT91_PIN_PC5,
+       .pullup_pin     = 0,            /* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+       {       /* DataFlash chip */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 1,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+       {       /* DataFlash card */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 0,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#endif
+#endif
+#if defined(CONFIG_SND_AT73C213)
+       {       /* AT73C213 DAC */
+               .modalias       = "snd_at73c213",
+               .chip_select    = 0,
+               .max_speed_hz   = 10 * 1000 * 1000,
+               .bus_num        = 1,
+       },
+#endif
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct __initdata eth_platform_data ek_macb_data = {
+       .is_rmii        = 1,
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+       {
+               .name   = "Partition 1",
+               .offset = 0,
+               .size   = 256 * 1024,
+       },
+       {
+               .name   = "Partition 2",
+               .offset = 256 * 1024,
+               .size   = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(ek_nand_partition);
+       return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+       .ale            = 21,
+       .cle            = 22,
+//     .det_pin        = ... not connected
+       .rdy_pin        = AT91_PIN_PC13,
+       .enable_pin     = AT91_PIN_PC14,
+       .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+       .bus_width_16   = 1,
+#else
+       .bus_width_16   = 0,
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+       .slot_b         = 1,
+       .wire4          = 1,
+//     .det_pin        = ... not connected
+//     .wp_pin         = ... not connected
+//     .vcc_pin        = ... not connected
+};
+
+static void __init ek_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* USB Host */
+       at91_add_device_usbh(&ek_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&ek_udc_data);
+       /* SPI */
+       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+       /* NAND */
+       at91_add_device_nand(&ek_nand_data);
+       /* Ethernet */
+       at91_add_device_eth(&ek_macb_data);
+       /* MMC */
+       at91_add_device_mmc(&ek_mmc_data);
+}
+
+MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
+       /* Maintainer: Atmel */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = ek_map_io,
+       .init_irq       = ek_init_irq,
+       .init_machine   = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91rm9200/board-sam9261ek.c
new file mode 100644 (file)
index 0000000..30b490d
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/dm9000.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 2 = USART0 .. USART2
+ *    3      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 1,
+       .tty_map        = { 3, -1, -1, -1 }             /* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+       /* Initialize processor: 18.432 MHz crystal */
+       at91sam9261_initialize(18432000);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+       at91sam9261_init_interrupts(NULL);
+}
+
+
+/*
+ * DM9000 ethernet device
+ */
+#if defined(CONFIG_DM9000)
+static struct resource at91sam9261_dm9000_resource[] = {
+       [0] = {
+               .start  = AT91_CHIPSELECT_2,
+               .end    = AT91_CHIPSELECT_2 + 3,
+               .flags  = IORESOURCE_MEM
+       },
+       [1] = {
+               .start  = AT91_CHIPSELECT_2 + 0x44,
+               .end    = AT91_CHIPSELECT_2 + 0xFF,
+               .flags  = IORESOURCE_MEM
+       },
+       [2] = {
+               .start  = AT91_PIN_PC11,
+               .end    = AT91_PIN_PC11,
+               .flags  = IORESOURCE_IRQ
+       }
+};
+
+static struct dm9000_plat_data dm9000_platdata = {
+       .flags          = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device at91sam9261_dm9000_device = {
+       .name           = "dm9000",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(at91sam9261_dm9000_resource),
+       .resource       = at91sam9261_dm9000_resource,
+       .dev            = {
+               .platform_data  = &dm9000_platdata,
+       }
+};
+
+static void __init ek_add_device_dm9000(void)
+{
+       /*
+        * Configure Chip-Select 2 on SMC for the DM9000.
+        * Note: These timings were calculated for MASTER_CLOCK = 100000000
+        *  according to the DM9000 timings.
+        */
+       at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0));
+       at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8));
+       at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16));
+       at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1));
+
+       /* Configure Reset signal as output */
+       at91_set_gpio_output(AT91_PIN_PC10, 0);
+
+       /* Configure Interrupt pin as input, no pull-up */
+       at91_set_gpio_input(AT91_PIN_PC11, 0);
+
+       platform_device_register(&at91sam9261_dm9000_device);
+}
+#else
+static void __init ek_add_device_dm9000(void) {}
+#endif /* CONFIG_DM9000 */
+
+
+/*
+ * USB Host Port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+       .ports          = 2,
+};
+
+
+/*
+ * USB Device Port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+       .vbus_pin       = AT91_PIN_PB29,
+       .pullup_pin     = 0,            /* pull-up driven by UDC */
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+       .wire4          = 1,
+//     .det_pin        = ... not connected
+//     .wp_pin         = ... not connected
+//     .vcc_pin        = ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+       {
+               .name   = "Partition 1",
+               .offset = 0,
+               .size   = 256 * 1024,
+       },
+       {
+               .name   = "Partition 2",
+               .offset = 256 * 1024 ,
+               .size   = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(ek_nand_partition);
+       return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+       .ale            = 22,
+       .cle            = 21,
+//     .det_pin        = ... not connected
+       .rdy_pin        = AT91_PIN_PC15,
+       .enable_pin     = AT91_PIN_PC14,
+       .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+       .bus_width_16   = 1,
+#else
+       .bus_width_16   = 0,
+#endif
+};
+
+/*
+ * SPI devices
+ */
+static struct spi_board_info ek_spi_devices[] = {
+       {       /* DataFlash chip */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 0,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+       {       /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
+               .modalias       = "mtd_dataflash",
+               .chip_select    = 3,
+               .max_speed_hz   = 15 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#elif defined(CONFIG_SND_AT73C213)
+       {       /* AT73C213 DAC */
+               .modalias       = "snd_at73c213",
+               .chip_select    = 3,
+               .max_speed_hz   = 10 * 1000 * 1000,
+               .bus_num        = 0,
+       },
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* USB Host */
+       at91_add_device_usbh(&ek_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&ek_udc_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* NAND */
+       at91_add_device_nand(&ek_nand_data);
+       /* DM9000 ethernet */
+       ek_add_device_dm9000();
+
+       /* spi0 and mmc/sd share the same PIO pins */
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+       /* SPI */
+       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+#else
+       /* MMC */
+       at91_add_device_mmc(&ek_mmc_data);
+#endif
+}
+
+MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
+       /* Maintainer: Atmel */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = ek_map_io,
+       .init_irq       = ek_init_irq,
+       .init_machine   = ek_board_init,
+MACHINE_END
index a43b061..4dee21f 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/mach-types.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/cpu.h>
 
 #include "clock.h"
 
@@ -41,6 +43,7 @@
 #define clk_is_primary(x)      ((x)->type & CLK_TYPE_PRIMARY)
 #define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
 #define clk_is_peripheral(x)   ((x)->type & CLK_TYPE_PERIPHERAL)
+#define clk_is_sys(x)          ((x)->type & CLK_TYPE_SYSTEM)
 
 
 static LIST_HEAD(clocks);
@@ -114,13 +117,11 @@ static void pmc_sys_mode(struct clk *clk, int is_on)
 static struct clk udpck = {
        .name           = "udpck",
        .parent         = &pllb,
-       .pmc_mask       = AT91_PMC_UDP,
        .mode           = pmc_sys_mode,
 };
 static struct clk uhpck = {
        .name           = "uhpck",
        .parent         = &pllb,
-       .pmc_mask       = AT91_PMC_UHP,
        .mode           = pmc_sys_mode,
 };
 
@@ -434,6 +435,12 @@ int __init clk_register(struct clk *clk)
                clk->mode = pmc_periph_mode;
                list_add_tail(&clk->node, &clocks);
        }
+       else if (clk_is_sys(clk)) {
+               clk->parent = &mck;
+               clk->mode = pmc_sys_mode;
+
+               list_add_tail(&clk->node, &clocks);
+       }
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
        else if (clk_is_programmable(clk)) {
                clk->mode = pmc_sys_mode;
@@ -586,9 +593,21 @@ int __init at91_clock_init(unsigned long main_clock)
         */
        at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
        pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-       at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP);
+       if (cpu_is_at91rm9200()) {
+               uhpck.pmc_mask = AT91RM9200_PMC_UHP;
+               udpck.pmc_mask = AT91RM9200_PMC_UDP;
+               at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP);
+               at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+       } else if (cpu_is_at91sam9260()) {
+               uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+               udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+               at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP);
+       } else if (cpu_is_at91sam9261()) {
+               uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0);
+               udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+               at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP);
+       }
        at91_sys_write(AT91_CKGR_PLLBR, 0);
-       at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP);
 
        udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
        uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
index 0592e66..b5c7a2e 100644 (file)
@@ -10,6 +10,7 @@
 #define CLK_TYPE_PLL           0x2
 #define CLK_TYPE_PROGRAMMABLE  0x4
 #define CLK_TYPE_PERIPHERAL    0x8
+#define CLK_TYPE_SYSTEM                0x10
 
 
 struct clk {
index 694e411..8c4d5a7 100644 (file)
 
  /* Processors */
 extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
+extern void __init at91sam9260_initialize(unsigned long main_clock);
+extern void __init at91sam9261_initialize(unsigned long main_clock);
 
  /* Interrupts */
 extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
 
  /* Timer */
 struct sys_timer;
 extern struct sys_timer at91rm9200_timer;
+extern struct sys_timer at91sam926x_timer;
 
  /* Clocks */
 extern int __init at91_clock_init(unsigned long main_clock);
@@ -39,3 +44,6 @@ struct at91_gpio_bank {
 };
 extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
 extern void __init at91_gpio_irq_setup(void);
+
+extern void (*at91_arch_reset)(void);
+extern int at91_extern_irq;
index 7467d64..3f18850 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/at91_pmc.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
@@ -332,10 +334,10 @@ static struct irq_chip gpio_irqchip = {
        .set_wake       = gpio_irq_set_wake,
 };
 
-static void gpio_irq_handler(unsigned irq, struct irqdesc *desc)
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
        unsigned        pin;
-       struct irqdesc  *gpio;
+       struct irq_desc *gpio;
        void __iomem    *pio;
        u32             isr;
 
@@ -396,7 +398,7 @@ void __init at91_gpio_irq_setup(void)
                __raw_writel(~0, controller + PIO_IDR);
 
                set_irq_data(id, (void *) pin);
-               set_irq_chipdata(id, controller);
+               set_irq_chip_data(id, controller);
 
                for (i = 0; i < 32; i++, pin++) {
                        /*
@@ -404,7 +406,7 @@ void __init at91_gpio_irq_setup(void)
                         * shorter, and the AIC handles interupts sanely.
                         */
                        set_irq_chip(pin, &gpio_irqchip);
-                       set_irq_handler(pin, do_simple_IRQ);
+                       set_irq_handler(pin, handle_simple_irq);
                        set_irq_flags(pin, IRQF_VALID);
                }
 
index 3e48811..2148daa 100644 (file)
@@ -47,6 +47,10 @@ static void at91_aic_unmask_irq(unsigned int irq)
        at91_sys_write(AT91_AIC_IECR, 1 << irq);
 }
 
+unsigned int at91_extern_irq;
+
+#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
+
 static int at91_aic_set_type(unsigned irq, unsigned type)
 {
        unsigned int smr, srctype;
@@ -59,14 +63,16 @@ static int at91_aic_set_type(unsigned irq, unsigned type)
                srctype = AT91_AIC_SRCTYPE_RISING;
                break;
        case IRQT_LOW:
-               if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))  /* only supported on external interrupts */
+               if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))         /* only supported on external interrupts */
+                       srctype = AT91_AIC_SRCTYPE_LOW;
+               else
                        return -EINVAL;
-               srctype = AT91_AIC_SRCTYPE_LOW;
                break;
        case IRQT_FALLING:
-               if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))  /* only supported on external interrupts */
+               if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))         /* only supported on external interrupts */
+                       srctype = AT91_AIC_SRCTYPE_FALLING;
+               else
                        return -EINVAL;
-               srctype = AT91_AIC_SRCTYPE_FALLING;
                break;
        default:
                return -EINVAL;
@@ -139,7 +145,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
                at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
 
                set_irq_chip(i, &at91_aic_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 
                /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
index 32c95d8..67aa557 100644 (file)
 #include <asm/mach/irq.h>
 #include <asm/mach-types.h>
 
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91rm9200_mc.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
 
 #include "generic.h"
 
@@ -68,9 +71,15 @@ static int at91_pm_verify_clocks(void)
        scsr = at91_sys_read(AT91_PMC_SCSR);
 
        /* USB must not be using PLLB */
-       if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) {
-               pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
-               return 0;
+       if (cpu_is_at91rm9200()) {
+               if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
+                       pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+                       return 0;
+               }
+       } else if (cpu_is_at91sam9260()) {
+#warning "Check SAM9260 USB clocks"
+       } else if (cpu_is_at91sam9261()) {
+#warning "Check SAM9261 USB clocks"
        }
 
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
@@ -112,7 +121,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 static void (*slow_clock)(void);
 
 
-
 static int at91_pm_enter(suspend_state_t state)
 {
        at91_gpio_suspend();
@@ -123,13 +131,7 @@ static int at91_pm_enter(suspend_state_t state)
                        (at91_sys_read(AT91_PMC_PCSR)
                                        | (1 << AT91_ID_FIQ)
                                        | (1 << AT91_ID_SYS)
-                                       | (1 << AT91RM9200_ID_IRQ0)
-                                       | (1 << AT91RM9200_ID_IRQ1)
-                                       | (1 << AT91RM9200_ID_IRQ2)
-                                       | (1 << AT91RM9200_ID_IRQ3)
-                                       | (1 << AT91RM9200_ID_IRQ4)
-                                       | (1 << AT91RM9200_ID_IRQ5)
-                                       | (1 << AT91RM9200_ID_IRQ6))
+                                       | (at91_extern_irq))
                                & at91_sys_read(AT91_AIC_IMR),
                        state);
 
index 7ee926e..ca10296 100644 (file)
@@ -63,7 +63,7 @@ static void int1_unmask(unsigned int irq)
        clps_writel(intmr1, INTMR1);
 }
 
-static struct irqchip int1_chip = {
+static struct irq_chip int1_chip = {
        .ack    = int1_ack,
        .mask   = int1_mask,
        .unmask = int1_unmask,
@@ -100,7 +100,7 @@ static void int2_unmask(unsigned int irq)
        clps_writel(intmr2, INTMR2);
 }
 
-static struct irqchip int2_chip = {
+static struct irq_chip int2_chip = {
        .ack    = int2_ack,
        .mask   = int2_mask,
        .unmask = int2_unmask,
@@ -112,12 +112,12 @@ void __init clps711x_init_irq(void)
 
        for (i = 0; i < NR_IRQS; i++) {
                if (INT1_IRQS & (1 << i)) {
-                       set_irq_handler(i, do_level_IRQ);
+                       set_irq_handler(i, handle_level_irq);
                        set_irq_chip(i, &int1_chip);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }
                if (INT2_IRQS & (1 << i)) {
-                       set_irq_handler(i, do_level_IRQ);
+                       set_irq_handler(i, handle_level_irq);
                        set_irq_chip(i, &int2_chip);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }                       
index fb10cf2..231b900 100644 (file)
@@ -57,7 +57,7 @@ static void cl7500_unmask_irq_a(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKA);
 }
 
-static struct irqchip clps7500_a_chip = {
+static struct irq_chip clps7500_a_chip = {
        .ack    = cl7500_ack_irq_a,
        .mask   = cl7500_mask_irq_a,
        .unmask = cl7500_unmask_irq_a,
@@ -81,7 +81,7 @@ static void cl7500_unmask_irq_b(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKB);
 }
 
-static struct irqchip clps7500_b_chip = {
+static struct irq_chip clps7500_b_chip = {
        .ack    = cl7500_mask_irq_b,
        .mask   = cl7500_mask_irq_b,
        .unmask = cl7500_unmask_irq_b,
@@ -105,7 +105,7 @@ static void cl7500_unmask_irq_c(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKC);
 }
 
-static struct irqchip clps7500_c_chip = {
+static struct irq_chip clps7500_c_chip = {
        .ack    = cl7500_mask_irq_c,
        .mask   = cl7500_mask_irq_c,
        .unmask = cl7500_unmask_irq_c,
@@ -129,7 +129,7 @@ static void cl7500_unmask_irq_d(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKD);
 }
 
-static struct irqchip clps7500_d_chip = {
+static struct irq_chip clps7500_d_chip = {
        .ack    = cl7500_mask_irq_d,
        .mask   = cl7500_mask_irq_d,
        .unmask = cl7500_unmask_irq_d,
@@ -153,7 +153,7 @@ static void cl7500_unmask_irq_dma(unsigned int irq)
        iomd_writeb(val | mask, IOMD_DMAMASK);
 }
 
-static struct irqchip clps7500_dma_chip = {
+static struct irq_chip clps7500_dma_chip = {
        .ack    = cl7500_mask_irq_dma,
        .mask   = cl7500_mask_irq_dma,
        .unmask = cl7500_unmask_irq_dma,
@@ -177,7 +177,7 @@ static void cl7500_unmask_irq_fiq(unsigned int irq)
        iomd_writeb(val | mask, IOMD_FIQMASK);
 }
 
-static struct irqchip clps7500_fiq_chip = {
+static struct irq_chip clps7500_fiq_chip = {
        .ack    = cl7500_mask_irq_fiq,
        .mask   = cl7500_mask_irq_fiq,
        .unmask = cl7500_unmask_irq_fiq,
@@ -187,7 +187,7 @@ static void cl7500_no_action(unsigned int irq)
 {
 }
 
-static struct irqchip clps7500_no_chip = {
+static struct irq_chip clps7500_no_chip = {
        .ack    = cl7500_no_action,
        .mask   = cl7500_no_action,
        .unmask = cl7500_no_action,
@@ -214,43 +214,43 @@ static void __init clps7500_init_irq(void)
                switch (irq) {
                case 0 ... 7:
                        set_irq_chip(irq, &clps7500_a_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 8 ... 15:
                        set_irq_chip(irq, &clps7500_b_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 16 ... 22:
                        set_irq_chip(irq, &clps7500_dma_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 24 ... 31:
                        set_irq_chip(irq, &clps7500_c_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 40 ... 47:
                        set_irq_chip(irq, &clps7500_d_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 48 ... 55:
                        set_irq_chip(irq, &clps7500_no_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 64 ... 72:
                        set_irq_chip(irq, &clps7500_fiq_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
                }
index 90103ab..8459431 100644 (file)
@@ -45,7 +45,7 @@ static void ebsa110_unmask_irq(unsigned int irq)
        __raw_writeb(1 << irq, IRQ_MSET);
 }
 
-static struct irqchip ebsa110_irq_chip = {
+static struct irq_chip ebsa110_irq_chip = {
        .ack    = ebsa110_mask_irq,
        .mask   = ebsa110_mask_irq,
        .unmask = ebsa110_unmask_irq,
@@ -67,7 +67,7 @@ static void __init ebsa110_init_irq(void)
 
        for (irq = 0; irq < NR_IRQS; irq++) {
                set_irq_chip(irq, &ebsa110_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index e346b03..af7904b 100644 (file)
@@ -9,12 +9,24 @@ config CRUNCH
 
 comment "EP93xx Platforms"
 
+config MACH_ADSSPHERE
+       bool "Support ADS Sphere"
+       help
+         Say 'Y' here if you want your kernel to support the ADS
+         Sphere board.
+
 config MACH_EDB9302
        bool "Support Cirrus Logic EDB9302"
        help
          Say 'Y' here if you want your kernel to support the Cirrus
          Logic EDB9302 Evaluation Board.
 
+config MACH_EDB9302A
+       bool "Support Cirrus Logic EDB9302A"
+       help
+         Say 'Y' here if you want your kernel to support the Cirrus
+         Logic EDB9302A Evaluation Board.
+
 config MACH_EDB9312
        bool "Support Cirrus Logic EDB9312"
        help
index c2eb18b..b06641d 100644 (file)
@@ -6,7 +6,9 @@ obj-m                   :=
 obj-n                  :=
 obj-                   :=
 
+obj-$(CONFIG_MACH_ADSSPHERE)   += adssphere.o
 obj-$(CONFIG_MACH_EDB9302)     += edb9302.o
+obj-$(CONFIG_MACH_EDB9302A)    += edb9302a.o
 obj-$(CONFIG_MACH_EDB9312)     += edb9312.o
 obj-$(CONFIG_MACH_EDB9315)     += edb9315.o
 obj-$(CONFIG_MACH_EDB9315A)    += edb9315a.o
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
new file mode 100644 (file)
index 0000000..ac5d581
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * arch/arm/mach-ep93xx/adssphere.c
+ * ADS Sphere support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data adssphere_flash_data = {
+       .width          = 4,
+};
+
+static struct resource adssphere_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x61ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device adssphere_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &adssphere_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &adssphere_flash_resource,
+};
+
+static struct ep93xx_eth_data adssphere_eth_data = {
+       .phy_id         = 1,
+};
+
+static struct resource adssphere_eth_resource[] = {
+       {
+               .start  = EP93XX_ETHERNET_PHYS_BASE,
+               .end    = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_EP93XX_ETHERNET,
+               .end    = IRQ_EP93XX_ETHERNET,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device adssphere_eth_device = {
+       .name           = "ep93xx-eth",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &adssphere_eth_data,
+       },
+       .num_resources  = 2,
+       .resource       = adssphere_eth_resource,
+};
+
+static void __init adssphere_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&adssphere_flash);
+
+       memcpy(adssphere_eth_data.dev_addr,
+               (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+       platform_device_register(&adssphere_eth_device);
+}
+
+MACHINE_START(ADSSPHERE, "ADS Sphere board")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = adssphere_init_machine,
+MACHINE_END
index e3fd1ab..d649b39 100644 (file)
@@ -245,7 +245,7 @@ EXPORT_SYMBOL(gpio_line_set);
  * EP93xx IRQ handling
  *************************************************************************/
 static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
-               struct irqdesc *desc)
+               struct irq_desc *desc)
 {
        unsigned char status;
        int i;
@@ -335,7 +335,7 @@ static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
        return 0;
 }
 
-static struct irqchip ep93xx_gpio_ab_irq_chip = {
+static struct irq_chip ep93xx_gpio_ab_irq_chip = {
        .ack            = ep93xx_gpio_ab_irq_mask_ack,
        .mask           = ep93xx_gpio_ab_irq_mask,
        .unmask         = ep93xx_gpio_ab_irq_unmask,
@@ -352,7 +352,7 @@ void __init ep93xx_init_irq(void)
 
        for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) {
                set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
        set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
diff --git a/arch/arm/mach-ep93xx/edb9302a.c b/arch/arm/mach-ep93xx/edb9302a.c
new file mode 100644 (file)
index 0000000..62e064b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * arch/arm/mach-ep93xx/edb9302a.c
+ * Cirrus Logic EDB9302A support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9302a_flash_data = {
+       .width          = 2,
+};
+
+static struct resource edb9302a_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x60ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9302a_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &edb9302a_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &edb9302a_flash_resource,
+};
+
+static struct ep93xx_eth_data edb9302a_eth_data = {
+       .phy_id                 = 1,
+};
+
+static struct resource edb9302a_eth_resource[] = {
+       {
+               .start  = EP93XX_ETHERNET_PHYS_BASE,
+               .end    = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_EP93XX_ETHERNET,
+               .end    = IRQ_EP93XX_ETHERNET,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device edb9302a_eth_device = {
+       .name           = "ep93xx-eth",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &edb9302a_eth_data,
+       },
+       .num_resources  = 2,
+       .resource       = edb9302a_eth_resource,
+};
+
+static void __init edb9302a_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&edb9302a_flash);
+
+       memcpy(edb9302a_eth_data.dev_addr,
+               (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+       platform_device_register(&edb9302a_eth_device);
+}
+
+MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0xc0000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = edb9302a_init_machine,
+MACHINE_END
index af900f4..ef29fc3 100644 (file)
@@ -78,7 +78,7 @@ static void fb_unmask_irq(unsigned int irq)
        *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
 }
 
-static struct irqchip fb_chip = {
+static struct irq_chip fb_chip = {
        .ack    = fb_mask_irq,
        .mask   = fb_mask_irq,
        .unmask = fb_unmask_irq,
@@ -96,7 +96,7 @@ static void __init __fb_init_irq(void)
 
        for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
                set_irq_chip(irq, &fb_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 }
index 888dedd..79443ff 100644 (file)
@@ -49,7 +49,7 @@ static void isa_unmask_pic_lo_irq(unsigned int irq)
        outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
 }
 
-static struct irqchip isa_lo_chip = {
+static struct irq_chip isa_lo_chip = {
        .ack    = isa_ack_pic_lo_irq,
        .mask   = isa_mask_pic_lo_irq,
        .unmask = isa_unmask_pic_lo_irq,
@@ -78,14 +78,14 @@ static void isa_unmask_pic_hi_irq(unsigned int irq)
        outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
 }
 
-static struct irqchip isa_hi_chip = {
+static struct irq_chip isa_hi_chip = {
        .ack    = isa_ack_pic_hi_irq,
        .mask   = isa_mask_pic_hi_irq,
        .unmask = isa_unmask_pic_hi_irq,
 };
 
 static void
-isa_irq_handler(unsigned int irq, struct irqdesc *desc)
+isa_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
 
@@ -150,13 +150,13 @@ void __init isa_init_irq(unsigned int host_irq)
        if (host_irq != (unsigned int)-1) {
                for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
                        set_irq_chip(irq, &isa_lo_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
 
                for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
                        set_irq_chip(irq, &isa_hi_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
 
index 4719229..7f31816 100644 (file)
@@ -101,7 +101,7 @@ static void inline unmask_gpio_irq(u32 irq)
 
 static void
 h720x_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irqdesc *desc)
+                 struct irq_desc *desc)
 {
        IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
        desc = irq_desc + irq;
@@ -117,7 +117,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq,
 }
 
 static void
-h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h720x_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -128,7 +128,7 @@ h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h720x_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
        mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT);
@@ -138,7 +138,7 @@ h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h720x_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -149,7 +149,7 @@ h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h720x_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -161,7 +161,7 @@ h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 
 #ifdef CONFIG_CPU_H7202
 static void
-h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h720x_gpioe_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -172,13 +172,13 @@ h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 #endif
 
-static struct irqchip h720x_global_chip = {
+static struct irq_chip h720x_global_chip = {
        .ack = mask_global_irq,
        .mask = mask_global_irq,
        .unmask = unmask_global_irq,
 };
 
-static struct irqchip h720x_gpio_chip = {
+static struct irq_chip h720x_gpio_chip = {
        .ack = ack_gpio_irq,
        .mask = mask_gpio_irq,
        .unmask = unmask_gpio_irq,
@@ -203,14 +203,14 @@ void __init h720x_init_irq (void)
        /* Initialize global IRQ's, fast path */
        for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
                set_irq_chip(irq, &h720x_global_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /* Initialize multiplexed IRQ's, slow path */
        for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
                set_irq_chip(irq, &h720x_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
        set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
@@ -221,7 +221,7 @@ void __init h720x_init_irq (void)
 #ifdef CONFIG_CPU_H7202
        for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
                set_irq_chip(irq, &h720x_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
        set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
index 06fecae..703870f 100644 (file)
@@ -106,7 +106,7 @@ static struct platform_device *devices[] __initdata = {
  * we have to handle all timer interrupts in one place.
  */
 static void
-h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -162,7 +162,7 @@ static void inline unmask_timerx_irq (u32 irq)
        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
 }
 
-static struct irqchip h7202_timerx_chip = {
+static struct irq_chip h7202_timerx_chip = {
        .ack = mask_timerx_irq,
        .mask = mask_timerx_irq,
        .unmask = unmask_timerx_irq,
@@ -202,7 +202,7 @@ void __init h7202_init_irq (void)
                          irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
                mask_timerx_irq(irq);
                set_irq_chip(irq, &h7202_timerx_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID );
        }
        set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
index 12ea58a..b5aa49d 100644 (file)
@@ -104,6 +104,9 @@ EXPORT_SYMBOL(imx_gpio_mode);
  */
 static unsigned int imx_decode_pll(unsigned int pll)
 {
+       unsigned long long ll;
+       unsigned long quot;
+
        u32 mfi = (pll >> 10) & 0xf;
        u32 mfn = pll & 0x3ff;
        u32 mfd = (pll >> 16) & 0x3ff;
@@ -112,7 +115,11 @@ static unsigned int imx_decode_pll(unsigned int pll)
 
        mfi = mfi <= 5 ? 5 : mfi;
 
-       return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
+       ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
+       quot = (pd+1) * (1<<16);
+       ll += quot / 2;
+       do_div(ll, quot);
+       return (unsigned int) ll;
 }
 
 unsigned int imx_get_system_clk(void)
index 368b13b..0791b56 100644 (file)
@@ -146,7 +146,7 @@ imx_gpio_unmask_irq(unsigned int irq)
 
 static void
 imx_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irqdesc *desc)
+                 struct irq_desc *desc)
 {
        desc = irq_desc + irq;
        while (mask) {
@@ -161,7 +161,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
 }
 
 static void
-imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -171,7 +171,7 @@ imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -181,7 +181,7 @@ imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -191,7 +191,7 @@ imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 }
 
 static void
-imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
@@ -230,13 +230,13 @@ imx_init_irq(void)
 
        for (irq = 0; irq < IMX_IRQS; irq++) {
                set_irq_chip(irq, &imx_internal_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
        for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
                set_irq_chip(irq, &imx_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
index 8ae4a2c..40039b2 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/time.h>
+#include <linux/clocksource.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
 /* Use timer 1 as system timer */
 #define TIMER_BASE IMX_TIM1_BASE
 
-/*
- * Returns number of us since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long imx_gettimeoffset(void)
-{
-       unsigned long ticks;
-
-       /*
-        * Get the current number of ticks.  Note that there is a race
-        * condition between us reading the timer and checking for
-        * an interrupt.  We get around this by ensuring that the
-        * counter has not reloaded between our two reads.
-        */
-       ticks = IMX_TCN(TIMER_BASE);
-
-       /*
-        * Interrupt pending?  If so, we've reloaded once already.
-        */
-       if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
-               ticks += LATCH;
-
-       /*
-        * Convert the ticks to usecs
-        */
-       return (1000000 / CLK32) * ticks;
-}
+static unsigned long evt_diff;
 
 /*
  * IRQ handler for the timer
@@ -58,14 +33,23 @@ static unsigned long imx_gettimeoffset(void)
 static irqreturn_t
 imx_timer_interrupt(int irq, void *dev_id)
 {
-       write_seqlock(&xtime_lock);
+       uint32_t tstat;
 
        /* clear the interrupt */
-       if (IMX_TSTAT(TIMER_BASE))
-               IMX_TSTAT(TIMER_BASE) = 0;
+       tstat = IMX_TSTAT(TIMER_BASE);
+       IMX_TSTAT(TIMER_BASE) = 0;
+
+       if (tstat & TSTAT_COMP) {
+               do {
+
+                       write_seqlock(&xtime_lock);
+                       timer_tick();
+                       write_sequnlock(&xtime_lock);
+                       IMX_TCMP(TIMER_BASE) += evt_diff;
 
-       timer_tick();
-       write_sequnlock(&xtime_lock);
+               } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
+                                       - IMX_TCN(TIMER_BASE)) < 0));
+       }
 
        return IRQ_HANDLED;
 }
@@ -77,9 +61,9 @@ static struct irqaction imx_timer_irq = {
 };
 
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer hardware into expected mode and state.
  */
-static void __init imx_timer_init(void)
+static void __init imx_timer_hardware_init(void)
 {
        /*
         * Initialise to a known state (all timers off, and timing reset)
@@ -87,7 +71,38 @@ static void __init imx_timer_init(void)
        IMX_TCTL(TIMER_BASE) = 0;
        IMX_TPRER(TIMER_BASE) = 0;
        IMX_TCMP(TIMER_BASE) = LATCH - 1;
-       IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN;
+
+       IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
+       evt_diff = LATCH;
+}
+
+cycle_t imx_get_cycles(void)
+{
+       return IMX_TCN(TIMER_BASE);
+}
+
+static struct clocksource clocksource_imx = {
+       .name           = "imx_timer1",
+       .rating         = 200,
+       .read           = imx_get_cycles,
+       .mask           = 0xFFFFFFFF,
+       .shift          = 20,
+       .is_continuous  = 1,
+};
+
+static int __init imx_clocksource_init(void)
+{
+       clocksource_imx.mult =
+               clocksource_hz2mult(imx_get_perclk1(), clocksource_imx.shift);
+       clocksource_register(&clocksource_imx);
+
+       return 0;
+}
+
+static void __init imx_timer_init(void)
+{
+       imx_timer_hardware_init();
+       imx_clocksource_init();
 
        /*
         * Make irqs happen for the system timer
@@ -97,5 +112,4 @@ static void __init imx_timer_init(void)
 
 struct sys_timer imx_timer = {
        .init           = imx_timer_init,
-       .offset         = imx_gettimeoffset,
 };
index 191c57a..7228075 100644 (file)
@@ -183,7 +183,7 @@ static void __init ap_init_irq(void)
        for (i = 0; i < NR_IRQS; i++) {
                if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
                        set_irq_chip(i, &sc_chip);
-                       set_irq_handler(i, do_level_IRQ);
+                       set_irq_handler(i, handle_level_irq);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }
        }
index 771b65b..913f64b 100644 (file)
@@ -202,7 +202,7 @@ static struct irq_chip sic_chip = {
 };
 
 static void
-sic_handle_irq(unsigned int irq, struct irqdesc *desc)
+sic_handle_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
 
@@ -238,7 +238,7 @@ static void __init intcp_init_irq(void)
                if (i == 29)
                        break;
                set_irq_chip(i, &pic_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
@@ -247,7 +247,7 @@ static void __init intcp_init_irq(void)
 
        for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) {
                set_irq_chip(i, &cic_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
@@ -256,7 +256,7 @@ static void __init intcp_init_irq(void)
 
        for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
                set_irq_chip(i, &sic_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
index 1bc8534..613b841 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <asm/delay.h>
 #include <asm/mmu_context.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/smp.h>
 
diff --git a/arch/arm/mach-iop13xx/Kconfig b/arch/arm/mach-iop13xx/Kconfig
new file mode 100644 (file)
index 0000000..40c2d68
--- /dev/null
@@ -0,0 +1,20 @@
+if ARCH_IOP13XX
+
+menu "IOP13XX Implementation Options"
+
+comment "IOP13XX Platform Support"
+
+config MACH_IQ81340SC
+       bool "Enable IQ81340SC Hardware Support"
+       help
+         Say Y here if you want to support running on the Intel IQ81340SC
+         evaluation kit.
+
+config MACH_IQ81340MC
+       bool "Enable IQ81340MC Hardware Support"
+       help
+         Say Y here if you want to support running on the Intel IQ81340MC
+         evaluation kit.
+
+endmenu
+endif
diff --git a/arch/arm/mach-iop13xx/Makefile b/arch/arm/mach-iop13xx/Makefile
new file mode 100644 (file)
index 0000000..c3d6c08
--- /dev/null
@@ -0,0 +1,12 @@
+obj-y                  :=
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+obj-$(CONFIG_ARCH_IOP13XX) += setup.o
+obj-$(CONFIG_ARCH_IOP13XX) += irq.o
+obj-$(CONFIG_ARCH_IOP13XX) += time.o
+obj-$(CONFIG_ARCH_IOP13XX) += pci.o
+obj-$(CONFIG_ARCH_IOP13XX) += io.o
+obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
+obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
diff --git a/arch/arm/mach-iop13xx/Makefile.boot b/arch/arm/mach-iop13xx/Makefile.boot
new file mode 100644 (file)
index 0000000..0b0e19f
--- /dev/null
@@ -0,0 +1,3 @@
+   zreladdr-y   := 0x00008000
+params_phys-y  := 0x00000100
+initrd_phys-y  := 0x00800000
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c
new file mode 100644 (file)
index 0000000..fbf9f88
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * iop13xx custom ioremap implementation
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags)
+{
+       void __iomem * retval;
+
+       switch (cookie) {
+       case IOP13XX_PCIX_LOWER_MEM_RA ... IOP13XX_PCIX_UPPER_MEM_RA:
+               if (unlikely(!iop13xx_atux_mem_base))
+                       retval = NULL;
+               else
+                       retval = (void *)(iop13xx_atux_mem_base +
+                                (cookie - IOP13XX_PCIX_LOWER_MEM_RA));
+               break;
+       case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA:
+               if (unlikely(!iop13xx_atue_mem_base))
+                       retval = NULL;
+               else
+                       retval = (void *)(iop13xx_atue_mem_base +
+                                (cookie - IOP13XX_PCIE_LOWER_MEM_RA));
+               break;
+       case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
+               retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA +
+                                 (cookie - IOP13XX_PBI_LOWER_MEM_RA),
+                                 size, flags);
+               break;
+       case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
+               retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
+               break;
+       case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA:
+               retval = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(cookie);
+               break;
+       case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA:
+               retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
+               break;
+       default:
+               retval = __ioremap(cookie, size, flags);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(__iop13xx_ioremap);
+
+void __iop13xx_iounmap(void __iomem *addr)
+{
+       extern void __iounmap(volatile void __iomem *addr);
+
+       if (iop13xx_atue_mem_base)
+               if (addr >= (void __iomem *) iop13xx_atue_mem_base &&
+                   addr < (void __iomem *) (iop13xx_atue_mem_base +
+                                            iop13xx_atue_mem_size))
+                   goto skip;
+
+       if (iop13xx_atux_mem_base)
+               if (addr >= (void __iomem *) iop13xx_atux_mem_base &&
+                   addr < (void __iomem *) (iop13xx_atux_mem_base +
+                                            iop13xx_atux_mem_size))
+                   goto skip;
+
+       switch ((u32) addr) {
+       case IOP13XX_PCIE_LOWER_IO_VA ... IOP13XX_PCIE_UPPER_IO_VA:
+       case IOP13XX_PCIX_LOWER_IO_VA ... IOP13XX_PCIX_UPPER_IO_VA:
+       case IOP13XX_PMMR_VIRT_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_VA:
+               goto skip;
+       }
+       __iounmap(addr);
+
+skip:
+       return;
+}
+EXPORT_SYMBOL(__iop13xx_iounmap);
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
new file mode 100644 (file)
index 0000000..ee59578
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * iq81340mc board support
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/pci.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/pci.h>
+#include <asm/mach/time.h>
+
+extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
+
+static int __init
+iq81340mc_pcix_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+       switch (idsel) {
+       case 1:
+               switch (pin) {
+               case 1: return ATUX_INTB;
+               case 2: return ATUX_INTC;
+               case 3: return ATUX_INTD;
+               case 4: return ATUX_INTA;
+               default: return -1;
+               }
+       case 2:
+               switch (pin) {
+               case 1: return ATUX_INTC;
+               case 2: return ATUX_INTD;
+               case 3: return ATUX_INTC;
+               case 4: return ATUX_INTD;
+               default: return -1;
+               }
+       default: return -1;
+       }
+}
+
+static struct hw_pci iq81340mc_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 0,
+       .setup          = iop13xx_pci_setup,
+       .map_irq        = iq81340mc_pcix_map_irq,
+       .scan           = iop13xx_scan_bus,
+       .preinit        = iop13xx_pci_init,
+};
+
+static int __init iq81340mc_pci_init(void)
+{
+       iop13xx_atu_select(&iq81340mc_pci);
+       pci_common_init(&iq81340mc_pci);
+       iop13xx_map_pci_memory();
+
+       return 0;
+}
+
+static void __init iq81340mc_init(void)
+{
+       iop13xx_platform_init();
+       iq81340mc_pci_init();
+}
+
+static void __init iq81340mc_timer_init(void)
+{
+       iop13xx_init_time(400000000);
+}
+
+static struct sys_timer iq81340mc_timer = {
+       .init       = iq81340mc_timer_init,
+       .offset     = iop13xx_gettimeoffset,
+};
+
+MACHINE_START(IQ81340MC, "Intel IQ81340MC")
+       /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
+       .phys_io        = PHYS_IO,
+       .io_pg_offst    = IO_PG_OFFSET,
+       .map_io         = iop13xx_map_io,
+       .init_irq       = iop13xx_init_irq,
+       .timer          = &iq81340mc_timer,
+       .boot_params    = BOOT_PARAM_OFFSET,
+       .init_machine   = iq81340mc_init,
+MACHINE_END
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
new file mode 100644 (file)
index 0000000..6677e14
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * iq81340sc board support
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/pci.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/pci.h>
+#include <asm/mach/time.h>
+
+extern int init_atu;
+
+static int __init
+iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+       WARN_ON(idsel < 1 || idsel > 2);
+
+       switch (idsel) {
+       case 1:
+               switch (pin) {
+               case 1: return ATUX_INTB;
+               case 2: return ATUX_INTC;
+               case 3: return ATUX_INTD;
+               case 4: return ATUX_INTA;
+               default: return -1;
+               }
+       case 2:
+               switch (pin) {
+               case 1: return ATUX_INTC;
+               case 2: return ATUX_INTC;
+               case 3: return ATUX_INTC;
+               case 4: return ATUX_INTC;
+               default: return -1;
+               }
+       default: return -1;
+       }
+}
+
+static struct hw_pci iq81340sc_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 0,
+       .setup          = iop13xx_pci_setup,
+       .scan           = iop13xx_scan_bus,
+       .map_irq        = iq81340sc_atux_map_irq,
+       .preinit        = iop13xx_pci_init
+};
+
+static int __init iq81340sc_pci_init(void)
+{
+       iop13xx_atu_select(&iq81340sc_pci);
+       pci_common_init(&iq81340sc_pci);
+       iop13xx_map_pci_memory();
+
+       return 0;
+}
+
+static void __init iq81340sc_init(void)
+{
+       iop13xx_platform_init();
+       iq81340sc_pci_init();
+}
+
+static void __init iq81340sc_timer_init(void)
+{
+       iop13xx_init_time(400000000);
+}
+
+static struct sys_timer iq81340sc_timer = {
+       .init       = iq81340sc_timer_init,
+       .offset     = iop13xx_gettimeoffset,
+};
+
+MACHINE_START(IQ81340SC, "Intel IQ81340SC")
+       /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
+       .phys_io        = PHYS_IO,
+       .io_pg_offst    = IO_PG_OFFSET,
+       .map_io         = iop13xx_map_io,
+       .init_irq       = iop13xx_init_irq,
+       .timer          = &iq81340sc_timer,
+       .boot_params    = BOOT_PARAM_OFFSET,
+       .init_machine   = iq81340sc_init,
+MACHINE_END
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
new file mode 100644 (file)
index 0000000..c4d9c8c
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * iop13xx IRQ handling / support functions
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/sysctl.h>
+#include <asm/uaccess.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/irqs.h>
+
+/* INTCTL0 CP6 R0 Page 4
+ */
+static inline u32 read_intctl_0(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val));
+       return val;
+}
+static inline void write_intctl_0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val));
+}
+
+/* INTCTL1 CP6 R1 Page 4
+ */
+static inline u32 read_intctl_1(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val));
+       return val;
+}
+static inline void write_intctl_1(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val));
+}
+
+/* INTCTL2 CP6 R2 Page 4
+ */
+static inline u32 read_intctl_2(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val));
+       return val;
+}
+static inline void write_intctl_2(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val));
+}
+
+/* INTCTL3 CP6 R3 Page 4
+ */
+static inline u32 read_intctl_3(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val));
+       return val;
+}
+static inline void write_intctl_3(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val));
+}
+
+/* INTSTR0 CP6 R0 Page 5
+ */
+static inline u32 read_intstr_0(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c0, c5, 0":"=r" (val));
+       return val;
+}
+static inline void write_intstr_0(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val));
+}
+
+/* INTSTR1 CP6 R1 Page 5
+ */
+static inline u32 read_intstr_1(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c1, c5, 0":"=r" (val));
+       return val;
+}
+static void write_intstr_1(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val));
+}
+
+/* INTSTR2 CP6 R2 Page 5
+ */
+static inline u32 read_intstr_2(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c5, 0":"=r" (val));
+       return val;
+}
+static void write_intstr_2(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val));
+}
+
+/* INTSTR3 CP6 R3 Page 5
+ */
+static inline u32 read_intstr_3(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c5, 0":"=r" (val));
+       return val;
+}
+static void write_intstr_3(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val));
+}
+
+/* INTBASE CP6 R0 Page 2
+ */
+static inline u32 read_intbase(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c0, c2, 0":"=r" (val));
+       return val;
+}
+static void write_intbase(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val));
+}
+
+/* INTSIZE CP6 R2 Page 2
+ */
+static inline u32 read_intsize(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c2, 0":"=r" (val));
+       return val;
+}
+static void write_intsize(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val));
+}
+
+/* 0 = Interrupt Masked and 1 = Interrupt not masked */
+static void
+iop13xx_irq_mask0 (unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_0(read_intctl_0() & ~(1 << (irq - 0)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_mask1 (unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_1(read_intctl_1() & ~(1 << (irq - 32)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_mask2 (unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_2(read_intctl_2() & ~(1 << (irq - 64)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_mask3 (unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_3(read_intctl_3() & ~(1 << (irq - 96)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_unmask0(unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_0(read_intctl_0() | (1 << (irq - 0)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_unmask1(unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_1(read_intctl_1() | (1 << (irq - 32)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_unmask2(unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_2(read_intctl_2() | (1 << (irq - 64)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static void
+iop13xx_irq_unmask3(unsigned int irq)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+       write_intctl_3(read_intctl_3() | (1 << (irq - 96)));
+       iop13xx_cp6_restore(cp_flags);
+}
+
+static struct irqchip iop13xx_irqchip0 = {
+       .ack    = iop13xx_irq_mask0,
+       .mask   = iop13xx_irq_mask0,
+       .unmask = iop13xx_irq_unmask0,
+};
+
+static struct irqchip iop13xx_irqchip1 = {
+       .ack    = iop13xx_irq_mask1,
+       .mask   = iop13xx_irq_mask1,
+       .unmask = iop13xx_irq_unmask1,
+};
+
+static struct irqchip iop13xx_irqchip2 = {
+       .ack    = iop13xx_irq_mask2,
+       .mask   = iop13xx_irq_mask2,
+       .unmask = iop13xx_irq_unmask2,
+};
+
+static struct irqchip iop13xx_irqchip3 = {
+       .ack    = iop13xx_irq_mask3,
+       .mask   = iop13xx_irq_mask3,
+       .unmask = iop13xx_irq_unmask3,
+};
+
+void __init iop13xx_init_irq(void)
+{
+       unsigned int i;
+
+       u32 cp_flags = iop13xx_cp6_save();
+
+       /* disable all interrupts */
+       write_intctl_0(0);
+       write_intctl_1(0);
+       write_intctl_2(0);
+       write_intctl_3(0);
+
+       /* treat all as IRQ */
+       write_intstr_0(0);
+       write_intstr_1(0);
+       write_intstr_2(0);
+       write_intstr_3(0);
+
+       /* initialize the interrupt vector generator */
+       write_intbase(INTBASE);
+       write_intsize(INTSIZE_4);
+
+       for(i = 0; i < NR_IOP13XX_IRQS; i++) {
+               if (i < 32)
+                       set_irq_chip(i, &iop13xx_irqchip0);
+               else if (i < 64)
+                       set_irq_chip(i, &iop13xx_irqchip1);
+               else if (i < 96)
+                       set_irq_chip(i, &iop13xx_irqchip2);
+               else
+                       set_irq_chip(i, &iop13xx_irqchip3);
+
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+
+       iop13xx_cp6_restore(cp_flags);
+}
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
new file mode 100644 (file)
index 0000000..89ec70e
--- /dev/null
@@ -0,0 +1,1113 @@
+/*
+ * iop13xx PCI support
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach/pci.h>
+#include <asm/arch/pci.h>
+
+#define IOP13XX_PCI_DEBUG 0
+#define PRINTK(x...) ((void)(IOP13XX_PCI_DEBUG && printk(x)))
+
+u32 iop13xx_atux_pmmr_offset; /* This offset can change based on strapping */
+u32 iop13xx_atue_pmmr_offset; /* This offset can change based on strapping */
+static struct pci_bus *pci_bus_atux = 0;
+static struct pci_bus *pci_bus_atue = 0;
+u32 iop13xx_atue_mem_base;
+u32 iop13xx_atux_mem_base;
+size_t iop13xx_atue_mem_size;
+size_t iop13xx_atux_mem_size;
+unsigned long iop13xx_pcibios_min_io = 0;
+unsigned long iop13xx_pcibios_min_mem = 0;
+
+EXPORT_SYMBOL(iop13xx_atue_mem_base);
+EXPORT_SYMBOL(iop13xx_atux_mem_base);
+EXPORT_SYMBOL(iop13xx_atue_mem_size);
+EXPORT_SYMBOL(iop13xx_atux_mem_size);
+
+int init_atu = 0; /* Flag to select which ATU(s) to initialize / disable */
+static unsigned long atux_trhfa_timeout = 0; /* Trhfa = RST# high to first
+                                                access */
+
+/* Scan the initialized busses and ioremap the requested memory range
+ */
+void iop13xx_map_pci_memory(void)
+{
+       int atu;
+       struct pci_bus *bus;
+       struct pci_dev *dev;
+       resource_size_t end = 0;
+
+       for (atu = 0; atu < 2; atu++) {
+               bus = atu ? pci_bus_atue : pci_bus_atux;
+               if (bus) {
+                       list_for_each_entry(dev, &bus->devices, bus_list) {
+                               int i;
+                               int max = 7;
+
+                               if (dev->subordinate)
+                                       max = DEVICE_COUNT_RESOURCE;
+
+                               for (i = 0; i < max; i++) {
+                                       struct resource *res = &dev->resource[i];
+                                       if (res->flags & IORESOURCE_MEM)
+                                               end = max(res->end, end);
+                               }
+                       }
+
+                       switch(atu) {
+                       case 0:
+                               iop13xx_atux_mem_size =
+                                       (end - IOP13XX_PCIX_LOWER_MEM_RA) + 1;
+
+                               /* 16MB align the request */
+                               if (iop13xx_atux_mem_size & (SZ_16M - 1)) {
+                                       iop13xx_atux_mem_size &= ~(SZ_16M - 1);
+                                       iop13xx_atux_mem_size += SZ_16M;
+                               }
+
+                               if (end) {
+                                       iop13xx_atux_mem_base =
+                                       (u32) __ioremap_pfn(
+                                       __phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA)
+                                       , 0, iop13xx_atux_mem_size, 0);
+                                       if (!iop13xx_atux_mem_base) {
+                                               printk("%s: atux allocation "
+                                                      "failed\n", __FUNCTION__);
+                                               BUG();
+                                       }
+                               } else
+                                       iop13xx_atux_mem_size = 0;
+                               PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n",
+                               __FUNCTION__, atu, iop13xx_atux_mem_size,
+                               iop13xx_atux_mem_base);
+                               break;
+                       case 1:
+                               iop13xx_atue_mem_size =
+                                       (end - IOP13XX_PCIE_LOWER_MEM_RA) + 1;
+
+                               /* 16MB align the request */
+                               if (iop13xx_atue_mem_size & (SZ_16M - 1)) {
+                                       iop13xx_atue_mem_size &= ~(SZ_16M - 1);
+                                       iop13xx_atue_mem_size += SZ_16M;
+                               }
+
+                               if (end) {
+                                       iop13xx_atue_mem_base =
+                                       (u32) __ioremap_pfn(
+                                       __phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA)
+                                       , 0, iop13xx_atue_mem_size, 0);
+                                       if (!iop13xx_atue_mem_base) {
+                                               printk("%s: atue allocation "
+                                                      "failed\n", __FUNCTION__);
+                                               BUG();
+                                       }
+                               } else
+                                       iop13xx_atue_mem_size = 0;
+                               PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n",
+                               __FUNCTION__, atu, iop13xx_atue_mem_size,
+                               iop13xx_atue_mem_base);
+                               break;
+                       }
+
+                       printk("%s: Initialized (%uM @ resource/virtual: %08lx/%08x)\n",
+                       atu ? "ATUE" : "ATUX",
+                       (atu ? iop13xx_atue_mem_size : iop13xx_atux_mem_size) /
+                       SZ_1M,
+                       atu ? IOP13XX_PCIE_LOWER_MEM_RA :
+                       IOP13XX_PCIX_LOWER_MEM_RA,
+                       atu ? iop13xx_atue_mem_base :
+                       iop13xx_atux_mem_base);
+                       end = 0;
+               }
+
+       }
+}
+
+static inline int iop13xx_atu_function(int atu)
+{
+       int func = 0;
+       /* the function number depends on the value of the
+        * IOP13XX_INTERFACE_SEL_PCIX reset strap
+        * see C-Spec section 3.17
+        */
+       switch(atu) {
+       case IOP13XX_INIT_ATU_ATUX:
+               if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
+                       func = 5;
+               else
+                       func = 0;
+               break;
+       case IOP13XX_INIT_ATU_ATUE:
+               if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
+                       func = 0;
+               else
+                       func = 5;
+               break;
+       default:
+               BUG();
+       }
+
+       return func;
+}
+
+/* iop13xx_atux_cfg_address - format a configuration address for atux
+ * @bus: Target bus to access
+ * @devfn: Combined device number and function number
+ * @where: Desired register's address offset
+ *
+ * Convert the parameters to a configuration address formatted
+ * according the PCI-X 2.0 specification
+ */
+static u32 iop13xx_atux_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+       struct pci_sys_data *sys = bus->sysdata;
+       u32 addr;
+
+       if (sys->busnr == bus->number)
+               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
+       else
+               addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
+
+       addr |= PCI_FUNC(devfn) << 8 | ((where & 0xff) & ~3);
+       addr |= ((where & 0xf00) >> 8) << 24; /* upper register number */
+
+       return addr;
+}
+
+/* iop13xx_atue_cfg_address - format a configuration address for atue
+ * @bus: Target bus to access
+ * @devfn: Combined device number and function number
+ * @where: Desired register's address offset
+ *
+ * Convert the parameters to an address usable by the ATUE_OCCAR
+ */
+static u32 iop13xx_atue_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+       struct pci_sys_data *sys = bus->sysdata;
+       u32 addr;
+
+       PRINTK("iop13xx_atue_cfg_address: bus: %d dev: %d func: %d",
+               bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+       addr = ((u32) bus->number)     << IOP13XX_ATUE_OCCAR_BUS_NUM |
+                  ((u32) PCI_SLOT(devfn)) << IOP13XX_ATUE_OCCAR_DEV_NUM |
+                  ((u32) PCI_FUNC(devfn)) << IOP13XX_ATUE_OCCAR_FUNC_NUM |
+                  (where & ~0x3);
+
+       if (sys->busnr != bus->number)
+               addr |= 1; /* type 1 access */
+
+       return addr;
+}
+
+/* This routine checks the status of the last configuration cycle.  If an error
+ * was detected it returns >0, else it returns a 0.  The errors being checked
+ * are parity, master abort, target abort (master and target).  These types of
+ * errors occure during a config cycle where there is no device, like during
+ * the discovery stage.
+ */
+static int iop13xx_atux_pci_status(int clear)
+{
+       unsigned int status;
+       int err = 0;
+
+       /*
+        * Check the status registers.
+        */
+       status = __raw_readw(IOP13XX_ATUX_ATUSR);
+       if (status & IOP_PCI_STATUS_ERROR)
+       {
+               PRINTK("\t\t\tPCI error: ATUSR %#08x", status);
+               if(clear)
+                       __raw_writew(status & IOP_PCI_STATUS_ERROR,
+                               IOP13XX_ATUX_ATUSR);
+               err = 1;
+       }
+       status = __raw_readl(IOP13XX_ATUX_ATUISR);
+       if (status & IOP13XX_ATUX_ATUISR_ERROR)
+       {
+               PRINTK("\t\t\tPCI error interrupt:  ATUISR %#08x", status);
+               if(clear)
+                       __raw_writel(status & IOP13XX_ATUX_ATUISR_ERROR,
+                               IOP13XX_ATUX_ATUISR);
+               err = 1;
+       }
+       return err;
+}
+
+/* Simply write the address register and read the configuration
+ * data.  Note that the data dependency on %0 encourages an abort
+ * to be detected before we return.
+ */
+static inline u32 iop13xx_atux_read(unsigned long addr)
+{
+       u32 val;
+
+       __asm__ __volatile__(
+               "str    %1, [%2]\n\t"
+               "ldr    %0, [%3]\n\t"
+               "mov    %0, %0\n\t"
+               : "=r" (val)
+               : "r" (addr), "r" (IOP13XX_ATUX_OCCAR), "r" (IOP13XX_ATUX_OCCDR));
+
+       return val;
+}
+
+/* The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop13xx_atux_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 *value)
+{
+       unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where);
+       u32 val = iop13xx_atux_read(addr) >> ((where & 3) * 8);
+
+       if (iop13xx_atux_pci_status(1) || is_atux_occdr_error()) {
+               __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3,
+                       IOP13XX_XBG_BECSR);
+               val = 0xffffffff;
+       }
+
+       *value = val;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop13xx_atux_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 value)
+{
+       unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where);
+       u32 val;
+
+       if (size != 4) {
+               val = iop13xx_atux_read(addr);
+               if (!iop13xx_atux_pci_status(1) == 0)
+                       return PCIBIOS_SUCCESSFUL;
+
+               where = (where & 3) * 8;
+
+               if (size == 1)
+                       val &= ~(0xff << where);
+               else
+                       val &= ~(0xffff << where);
+
+               __raw_writel(val | value << where, IOP13XX_ATUX_OCCDR);
+       } else {
+               __raw_writel(addr, IOP13XX_ATUX_OCCAR);
+               __raw_writel(value, IOP13XX_ATUX_OCCDR);
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop13xx_atux_ops = {
+       .read   = iop13xx_atux_read_config,
+       .write  = iop13xx_atux_write_config,
+};
+
+/* This routine checks the status of the last configuration cycle.  If an error
+ * was detected it returns >0, else it returns a 0.  The errors being checked
+ * are parity, master abort, target abort (master and target).  These types of
+ * errors occure during a config cycle where there is no device, like during
+ * the discovery stage.
+ */
+static int iop13xx_atue_pci_status(int clear)
+{
+       unsigned int status;
+       int err = 0;
+
+       /*
+        * Check the status registers.
+        */
+
+       /* standard pci status register */
+       status = __raw_readw(IOP13XX_ATUE_ATUSR);
+       if (status & IOP_PCI_STATUS_ERROR) {
+               PRINTK("\t\t\tPCI error: ATUSR %#08x", status);
+               if(clear)
+                       __raw_writew(status & IOP_PCI_STATUS_ERROR,
+                               IOP13XX_ATUE_ATUSR);
+               err++;
+       }
+
+       /* check the normal status bits in the ATUISR */
+       status = __raw_readl(IOP13XX_ATUE_ATUISR);
+       if (status & IOP13XX_ATUE_ATUISR_ERROR) {
+               PRINTK("\t\t\tPCI error: ATUISR %#08x", status);
+               if (clear)
+                       __raw_writew(status & IOP13XX_ATUE_ATUISR_ERROR,
+                               IOP13XX_ATUE_ATUISR);
+               err++;
+
+               /* check the PCI-E status if the ATUISR reports an interface error */
+               if (status & IOP13XX_ATUE_STAT_PCI_IFACE_ERR) {
+                       /* get the unmasked errors */
+                       status = __raw_readl(IOP13XX_ATUE_PIE_STS) &
+                                       ~(__raw_readl(IOP13XX_ATUE_PIE_MSK));
+
+                       if (status) {
+                               PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x",
+                                       __raw_readl(IOP13XX_ATUE_PIE_STS));
+                               err++;
+                       } else {
+                               PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x",
+                                       __raw_readl(IOP13XX_ATUE_PIE_STS));
+                               PRINTK("\t\t\tPCI-E error: ATUE_PIE_MSK %#08x",
+                                       __raw_readl(IOP13XX_ATUE_PIE_MSK));
+                               BUG();
+                       }
+
+                       if(clear)
+                               __raw_writel(status, IOP13XX_ATUE_PIE_STS);
+               }
+       }
+
+       return err;
+}
+
+static inline int __init
+iop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+       WARN_ON(idsel != 0);
+
+       switch (pin) {
+       case 1: return ATUE_INTA;
+       case 2: return ATUE_INTB;
+       case 3: return ATUE_INTC;
+       case 4: return ATUE_INTD;
+       default: return -1;
+       }
+}
+
+static inline u32 iop13xx_atue_read(unsigned long addr)
+{
+       u32 val;
+
+       __raw_writel(addr, IOP13XX_ATUE_OCCAR);
+       val = __raw_readl(IOP13XX_ATUE_OCCDR);
+
+       rmb();
+
+       return val;
+}
+
+/* The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop13xx_atue_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 *value)
+{
+       u32 val;
+       unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where);
+
+       /* Hide device numbers > 0 on the local PCI-E bus (Type 0 access) */
+       if (!PCI_SLOT(devfn) || (addr & 1)) {
+               val = iop13xx_atue_read(addr) >> ((where & 3) * 8);
+               if( iop13xx_atue_pci_status(1) || is_atue_occdr_error() ) {
+                       __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3,
+                               IOP13XX_XBG_BECSR);
+                       val = 0xffffffff;
+               }
+
+               PRINTK("addr=%#0lx, val=%#010x", addr, val);
+       } else
+               val = 0xffffffff;
+
+       *value = val;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop13xx_atue_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 value)
+{
+       unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where);
+       u32 val;
+
+       if (size != 4) {
+               val = iop13xx_atue_read(addr);
+               if (!iop13xx_atue_pci_status(1) == 0)
+                       return PCIBIOS_SUCCESSFUL;
+
+               where = (where & 3) * 8;
+
+               if (size == 1)
+                       val &= ~(0xff << where);
+               else
+                       val &= ~(0xffff << where);
+
+               __raw_writel(val | value << where, IOP13XX_ATUE_OCCDR);
+       } else {
+               __raw_writel(addr, IOP13XX_ATUE_OCCAR);
+               __raw_writel(value, IOP13XX_ATUE_OCCDR);
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop13xx_atue_ops = {
+       .read   = iop13xx_atue_read_config,
+       .write  = iop13xx_atue_write_config,
+};
+
+/* When a PCI device does not exist during config cycles, the XScale gets a
+ * bus error instead of returning 0xffffffff.  We can't rely on the ATU status
+ * bits to tell us that it was indeed a configuration cycle that caused this
+ * error especially in the case when the ATUE link is down.  Instead we rely
+ * on data from the south XSI bridge to validate the abort
+ */
+int
+iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+       PRINTK("Data abort: address = 0x%08lx "
+                   "fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx",
+               addr, fsr, regs->ARM_pc, regs->ARM_lr);
+
+       PRINTK("IOP13XX_XBG_BECSR: %#10x", __raw_readl(IOP13XX_XBG_BECSR));
+       PRINTK("IOP13XX_XBG_BERAR: %#10x", __raw_readl(IOP13XX_XBG_BERAR));
+       PRINTK("IOP13XX_XBG_BERUAR: %#10x", __raw_readl(IOP13XX_XBG_BERUAR));
+
+       /*  If it was an imprecise abort, then we need to correct the
+        *  return address to be _after_ the instruction.
+        */
+       if (fsr & (1 << 10))
+               regs->ARM_pc += 4;
+
+       if (is_atue_occdr_error() || is_atux_occdr_error())
+               return 0;
+       else
+               return 1;
+}
+
+/* Scan an IOP13XX PCI bus.  nr selects which ATU we use.
+ */
+struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
+{
+       int which_atu;
+       struct pci_bus *bus = NULL;
+
+       switch (init_atu) {
+       case IOP13XX_INIT_ATU_ATUX:
+               which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX;
+               break;
+       case IOP13XX_INIT_ATU_ATUE:
+               which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE;
+               break;
+       case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE):
+               which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX;
+               break;
+       default:
+               which_atu = 0;
+       }
+
+       if (!which_atu) {
+               BUG();
+               return NULL;
+       }
+
+       switch (which_atu) {
+       case IOP13XX_INIT_ATU_ATUX:
+               if (time_after_eq(jiffies + msecs_to_jiffies(1000),
+                                 atux_trhfa_timeout))  /* ensure not wrap */
+                       while(time_before(jiffies, atux_trhfa_timeout))
+                               udelay(100);
+
+               bus = pci_bus_atux = pci_scan_bus(sys->busnr,
+                                                 &iop13xx_atux_ops,
+                                                 sys);
+               break;
+       case IOP13XX_INIT_ATU_ATUE:
+               bus = pci_bus_atue = pci_scan_bus(sys->busnr,
+                                                 &iop13xx_atue_ops,
+                                                 sys);
+               break;
+       }
+
+       return bus;
+}
+
+/* This function is called from iop13xx_pci_init() after assigning valid
+ * values to iop13xx_atue_pmmr_offset.  This is the location for common
+ * setup of ATUE for all IOP13XX implementations.
+ */
+void __init iop13xx_atue_setup(void)
+{
+       int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUE);
+       u32 reg_val;
+
+       /* BAR 1 (1:1 mapping with Physical RAM) */
+       /* Set limit and enable */
+       __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1,
+                       IOP13XX_ATUE_IALR1);
+       __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1);
+
+       /* Set base at the top of the reserved address space */
+       __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 |
+                       PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUE_IABAR1);
+
+       /* 1:1 mapping with physical ram
+        * (leave big endian byte swap disabled)
+        */
+        __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1);
+        __raw_writel(PHYS_OFFSET, IOP13XX_ATUE_IATVR1);
+
+       /* Outbound window 1 (PCIX/PCIE memory window) */
+       /* 32 bit Address Space */
+       __raw_writel(0x0, IOP13XX_ATUE_OUMWTVR1);
+       /* PA[35:32] */
+       __raw_writel(IOP13XX_ATUE_OUMBAR_ENABLE |
+                       (IOP13XX_PCIE_MEM_PHYS_OFFSET >> 32),
+                       IOP13XX_ATUE_OUMBAR1);
+
+       /* Setup the I/O Bar
+        * A[35-16] in 31-12
+        */
+       __raw_writel(((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000),
+               IOP13XX_ATUE_OIOBAR);
+       __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR);
+
+       /* clear startup errors */
+       iop13xx_atue_pci_status(1);
+
+       /* OIOBAR function number
+        */
+       reg_val = __raw_readl(IOP13XX_ATUE_OIOBAR);
+       reg_val &= ~0x7;
+       reg_val |= func;
+       __raw_writel(reg_val, IOP13XX_ATUE_OIOBAR);
+
+       /* OUMBAR function numbers
+        */
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0);
+
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1);
+
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2);
+
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3);
+
+       /* Enable inbound and outbound cycles
+        */
+       reg_val = __raw_readw(IOP13XX_ATUE_ATUCMD);
+       reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+                       PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       __raw_writew(reg_val, IOP13XX_ATUE_ATUCMD);
+
+       reg_val = __raw_readl(IOP13XX_ATUE_ATUCR);
+       reg_val |= IOP13XX_ATUE_ATUCR_OUT_EN |
+                       IOP13XX_ATUE_ATUCR_IVM;
+       __raw_writel(reg_val, IOP13XX_ATUE_ATUCR);
+}
+
+void __init iop13xx_atue_disable(void)
+{
+       u32 reg_val;
+
+       __raw_writew(0x0, IOP13XX_ATUE_ATUCMD);
+       __raw_writel(IOP13XX_ATUE_ATUCR_IVM, IOP13XX_ATUE_ATUCR);
+
+       /* wait for cycles to quiesce */
+       while (__raw_readl(IOP13XX_ATUE_PCSR) & (IOP13XX_ATUE_PCSR_OUT_Q_BUSY |
+                                            IOP13XX_ATUE_PCSR_IN_Q_BUSY |
+                                            IOP13XX_ATUE_PCSR_LLRB_BUSY))
+               cpu_relax();
+
+       /* BAR 0 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUE_IAUBAR0);
+       __raw_writel(0x0, IOP13XX_ATUE_IABAR0);
+       __raw_writel(0x0, IOP13XX_ATUE_IAUTVR0);
+       __raw_writel(0x0, IOP13XX_ATUE_IATVR0);
+       __raw_writel(0x0, IOP13XX_ATUE_IALR0);
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0);
+       reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0);
+
+       /* BAR 1 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1);
+       __raw_writel(0x0, IOP13XX_ATUE_IABAR1);
+       __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1);
+       __raw_writel(0x0, IOP13XX_ATUE_IATVR1);
+       __raw_writel(0x0, IOP13XX_ATUE_IALR1);
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1);
+       reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1);
+
+       /* BAR 2 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUE_IAUBAR2);
+       __raw_writel(0x0, IOP13XX_ATUE_IABAR2);
+       __raw_writel(0x0, IOP13XX_ATUE_IAUTVR2);
+       __raw_writel(0x0, IOP13XX_ATUE_IATVR2);
+       __raw_writel(0x0, IOP13XX_ATUE_IALR2);
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2);
+       reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2);
+
+       /* BAR 3 ( Disabled ) */
+       reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3);
+       reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3);
+
+       /* Setup the I/O Bar
+        * A[35-16] in 31-12
+        */
+       __raw_writel((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000,
+                       IOP13XX_ATUE_OIOBAR);
+       __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR);
+}
+
+/* This function is called from iop13xx_pci_init() after assigning valid
+ * values to iop13xx_atux_pmmr_offset.  This is the location for common
+ * setup of ATUX for all IOP13XX implementations.
+ */
+void __init iop13xx_atux_setup(void)
+{
+       u32 reg_val;
+       int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX);
+
+       /* Take PCI-X bus out of reset if bootloader hasn't already.
+        * According to spec, we should wait for 2^25 PCI clocks to meet
+        * the PCI timing parameter Trhfa (RST# high to first access).
+        * This is rarely necessary and often ignored.
+        */
+       reg_val = __raw_readl(IOP13XX_ATUX_PCSR);
+       if (reg_val & IOP13XX_ATUX_PCSR_P_RSTOUT) {
+               int msec = (reg_val >> IOP13XX_ATUX_PCSR_FREQ_OFFSET) & 0x7;
+               msec = 1000 / (8-msec); /* bits 100=133MHz, 111=>33MHz */
+               __raw_writel(reg_val & ~IOP13XX_ATUX_PCSR_P_RSTOUT,
+                               IOP13XX_ATUX_PCSR);
+               atux_trhfa_timeout = jiffies + msecs_to_jiffies(msec);
+       }
+       else
+               atux_trhfa_timeout = jiffies;
+
+       /* BAR 1 (1:1 mapping with Physical RAM) */
+       /* Set limit and enable */
+       __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1,
+                       IOP13XX_ATUX_IALR1);
+       __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1);
+
+       /* Set base at the top of the reserved address space */
+       __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 |
+                       PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUX_IABAR1);
+
+       /* 1:1 mapping with physical ram
+        * (leave big endian byte swap disabled)
+        */
+       __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1);
+       __raw_writel(PHYS_OFFSET, IOP13XX_ATUX_IATVR1);
+
+       /* Outbound window 1 (PCIX/PCIE memory window) */
+       /* 32 bit Address Space */
+       __raw_writel(0x0, IOP13XX_ATUX_OUMWTVR1);
+       /* PA[35:32] */
+       __raw_writel(IOP13XX_ATUX_OUMBAR_ENABLE |
+                       IOP13XX_PCIX_MEM_PHYS_OFFSET >> 32,
+                       IOP13XX_ATUX_OUMBAR1);
+
+       /* Setup the I/O Bar
+        * A[35-16] in 31-12
+        */
+       __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000,
+               IOP13XX_ATUX_OIOBAR);
+       __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR);
+
+       /* clear startup errors */
+       iop13xx_atux_pci_status(1);
+
+       /* OIOBAR function number
+        */
+       reg_val = __raw_readl(IOP13XX_ATUX_OIOBAR);
+       reg_val &= ~0x7;
+       reg_val |= func;
+       __raw_writel(reg_val, IOP13XX_ATUX_OIOBAR);
+
+       /* OUMBAR function numbers
+        */
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0);
+
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1);
+
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2);
+
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3);
+       reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK <<
+                       IOP13XX_ATU_OUMBAR_FUNC_NUM);
+       reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3);
+
+       /* Enable inbound and outbound cycles
+        */
+       reg_val = __raw_readw(IOP13XX_ATUX_ATUCMD);
+       reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+                       PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       __raw_writew(reg_val, IOP13XX_ATUX_ATUCMD);
+
+       reg_val = __raw_readl(IOP13XX_ATUX_ATUCR);
+       reg_val |= IOP13XX_ATUX_ATUCR_OUT_EN;
+       __raw_writel(reg_val, IOP13XX_ATUX_ATUCR);
+}
+
+void __init iop13xx_atux_disable(void)
+{
+       u32 reg_val;
+
+       __raw_writew(0x0, IOP13XX_ATUX_ATUCMD);
+       __raw_writel(0x0, IOP13XX_ATUX_ATUCR);
+
+       /* wait for cycles to quiesce */
+       while (__raw_readl(IOP13XX_ATUX_PCSR) & (IOP13XX_ATUX_PCSR_OUT_Q_BUSY |
+                                    IOP13XX_ATUX_PCSR_IN_Q_BUSY))
+               cpu_relax();
+
+       /* BAR 0 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUX_IAUBAR0);
+       __raw_writel(0x0, IOP13XX_ATUX_IABAR0);
+       __raw_writel(0x0, IOP13XX_ATUX_IAUTVR0);
+       __raw_writel(0x0, IOP13XX_ATUX_IATVR0);
+       __raw_writel(0x0, IOP13XX_ATUX_IALR0);
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0);
+       reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0);
+
+       /* BAR 1 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1);
+       __raw_writel(0x0, IOP13XX_ATUX_IABAR1);
+       __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1);
+       __raw_writel(0x0, IOP13XX_ATUX_IATVR1);
+       __raw_writel(0x0, IOP13XX_ATUX_IALR1);
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1);
+       reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1);
+
+       /* BAR 2 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUX_IAUBAR2);
+       __raw_writel(0x0, IOP13XX_ATUX_IABAR2);
+       __raw_writel(0x0, IOP13XX_ATUX_IAUTVR2);
+       __raw_writel(0x0, IOP13XX_ATUX_IATVR2);
+       __raw_writel(0x0, IOP13XX_ATUX_IALR2);
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2);
+       reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2);
+
+       /* BAR 3 ( Disabled ) */
+       __raw_writel(0x0, IOP13XX_ATUX_IAUBAR3);
+       __raw_writel(0x0, IOP13XX_ATUX_IABAR3);
+       __raw_writel(0x0, IOP13XX_ATUX_IAUTVR3);
+       __raw_writel(0x0, IOP13XX_ATUX_IATVR3);
+       __raw_writel(0x0, IOP13XX_ATUX_IALR3);
+       reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3);
+       reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE;
+       __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3);
+
+       /* Setup the I/O Bar
+       * A[35-16] in 31-12
+       */
+       __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000,
+                       IOP13XX_ATUX_OIOBAR);
+       __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR);
+}
+
+void __init iop13xx_set_atu_mmr_bases(void)
+{
+       /* Based on ESSR0, determine the ATU X/E offsets */
+       switch(__raw_readl(IOP13XX_ESSR0) &
+               (IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX)) {
+       /* both asserted */
+       case 0:
+               iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET;
+               iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
+               break;
+       /* IOP13XX_CONTROLLER_ONLY = deasserted
+        * IOP13XX_INTERFACE_SEL_PCIX = asserted
+        */
+       case IOP13XX_CONTROLLER_ONLY:
+               iop13xx_atux_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET;
+               iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
+               break;
+       /* IOP13XX_CONTROLLER_ONLY = asserted
+        * IOP13XX_INTERFACE_SEL_PCIX = deasserted
+        */
+       case IOP13XX_INTERFACE_SEL_PCIX:
+               iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET;
+               iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
+               break;
+       /* both deasserted */
+       case IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX:
+               iop13xx_atux_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET;
+               iop13xx_atue_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET;
+               break;
+       default:
+               BUG();
+       }
+}
+
+void __init iop13xx_atu_select(struct hw_pci *plat_pci)
+{
+       int i;
+
+       /* set system defaults
+        * note: if "iop13xx_init_atu=" is specified this autodetect
+        * sequence will be bypassed
+        */
+       if (init_atu == IOP13XX_INIT_ATU_DEFAULT) {
+               /* check for single/dual interface */
+               if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) {
+                       /* ATUE must be present check the device id
+                        * to see if ATUX is present.
+                        */
+                       init_atu |= IOP13XX_INIT_ATU_ATUE;
+                       switch (__raw_readw(IOP13XX_ATUE_DID) & 0xf0) {
+                       case 0x70:
+                       case 0x80:
+                       case 0xc0:
+                               init_atu |= IOP13XX_INIT_ATU_ATUX;
+                               break;
+                       }
+               } else {
+                       /* ATUX must be present check the device id
+                        * to see if ATUE is present.
+                        */
+                       init_atu |= IOP13XX_INIT_ATU_ATUX;
+                       switch (__raw_readw(IOP13XX_ATUX_DID) & 0xf0) {
+                       case 0x70:
+                       case 0x80:
+                       case 0xc0:
+                               init_atu |= IOP13XX_INIT_ATU_ATUE;
+                               break;
+                       }
+               }
+
+               /* check central resource and root complex capability */
+               if (init_atu & IOP13XX_INIT_ATU_ATUX)
+                       if (!(__raw_readl(IOP13XX_ATUX_PCSR) &
+                               IOP13XX_ATUX_PCSR_CENTRAL_RES))
+                               init_atu &= ~IOP13XX_INIT_ATU_ATUX;
+
+               if (init_atu & IOP13XX_INIT_ATU_ATUE)
+                       if (__raw_readl(IOP13XX_ATUE_PCSR) &
+                               IOP13XX_ATUE_PCSR_END_POINT)
+                               init_atu &= ~IOP13XX_INIT_ATU_ATUE;
+       }
+
+       for (i = 0; i < 2; i++) {
+               if((init_atu & (1 << i)) == (1 << i))
+                       plat_pci->nr_controllers++;
+       }
+}
+
+void __init iop13xx_pci_init(void)
+{
+       /* clear pre-existing south bridge errors */
+       __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
+
+       /* Setup the Min Address for PCI memory... */
+       iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
+
+       /* if Linux is given control of an ATU
+        * clear out its prior configuration,
+        * otherwise do not touch the registers
+        */
+       if (init_atu & IOP13XX_INIT_ATU_ATUE) {
+               iop13xx_atue_disable();
+               iop13xx_atue_setup();
+       }
+
+       if (init_atu & IOP13XX_INIT_ATU_ATUX) {
+               iop13xx_atux_disable();
+               iop13xx_atux_setup();
+       }
+
+       hook_fault_code(16+6, iop13xx_pci_abort, SIGBUS,
+                       "imprecise external abort");
+}
+
+/* intialize the pci memory space.  handle any combination of
+ * atue and atux enabled/disabled
+ */
+int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       struct resource *res;
+       int which_atu;
+       u32 pcixsr, pcsr;
+
+       if (nr > 1)
+               return 0;
+
+       res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+       if (!res)
+               panic("PCI: unable to alloc resources");
+
+       memset(res, 0, sizeof(struct resource) * 2);
+
+       /* 'nr' assumptions:
+        * ATUX is always 0
+        * ATUE is 1 when ATUX is also enabled
+        * ATUE is 0 when ATUX is disabled
+        */
+       switch(init_atu) {
+       case IOP13XX_INIT_ATU_ATUX:
+               which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX;
+               break;
+       case IOP13XX_INIT_ATU_ATUE:
+               which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE;
+               break;
+       case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE):
+               which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX;
+               break;
+       default:
+               which_atu = 0;
+       }
+
+       if (!which_atu)
+               return 0;
+
+       switch(which_atu) {
+       case IOP13XX_INIT_ATU_ATUX:
+               pcixsr = __raw_readl(IOP13XX_ATUX_PCIXSR);
+               pcixsr &= ~0xffff;
+               pcixsr |= sys->busnr << IOP13XX_ATUX_PCIXSR_BUS_NUM |
+                         0 << IOP13XX_ATUX_PCIXSR_DEV_NUM |
+                         iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX)
+                                 << IOP13XX_ATUX_PCIXSR_FUNC_NUM;
+               __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
+
+               res[0].start = IOP13XX_PCIX_LOWER_IO_PA;
+               res[0].end   = IOP13XX_PCIX_UPPER_IO_PA;
+               res[0].name  = "IQ81340 ATUX PCI I/O Space";
+               res[0].flags = IORESOURCE_IO;
+
+               res[1].start = IOP13XX_PCIX_LOWER_MEM_RA;
+               res[1].end   = IOP13XX_PCIX_UPPER_MEM_RA;
+               res[1].name  = "IQ81340 ATUX PCI Memory Space";
+               res[1].flags = IORESOURCE_MEM;
+               sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
+               sys->io_offset = IOP13XX_PCIX_IO_OFFSET;
+               break;
+       case IOP13XX_INIT_ATU_ATUE:
+               /* Note: the function number field in the PCSR is ro */
+               pcsr = __raw_readl(IOP13XX_ATUE_PCSR);
+               pcsr &= ~(0xfff8 << 16);
+               pcsr |= sys->busnr << IOP13XX_ATUE_PCSR_BUS_NUM |
+                               0 << IOP13XX_ATUE_PCSR_DEV_NUM;
+
+               __raw_writel(pcsr, IOP13XX_ATUE_PCSR);
+
+               res[0].start = IOP13XX_PCIE_LOWER_IO_PA;
+               res[0].end   = IOP13XX_PCIE_UPPER_IO_PA;
+               res[0].name  = "IQ81340 ATUE PCI I/O Space";
+               res[0].flags = IORESOURCE_IO;
+
+               res[1].start = IOP13XX_PCIE_LOWER_MEM_RA;
+               res[1].end   = IOP13XX_PCIE_UPPER_MEM_RA;
+               res[1].name  = "IQ81340 ATUE PCI Memory Space";
+               res[1].flags = IORESOURCE_MEM;
+               sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
+               sys->io_offset = IOP13XX_PCIE_IO_OFFSET;
+               sys->map_irq = iop13xx_pcie_map_irq;
+               break;
+       default:
+               return 0;
+       }
+
+       request_resource(&ioport_resource, &res[0]);
+       request_resource(&iomem_resource, &res[1]);
+
+       sys->resource[0] = &res[0];
+       sys->resource[1] = &res[1];
+       sys->resource[2] = NULL;
+
+       return 1;
+}
+
+u16 iop13xx_dev_id(void)
+{
+       if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
+               return __raw_readw(IOP13XX_ATUE_DID);
+       else
+               return __raw_readw(IOP13XX_ATUX_DID);
+}
+
+static int __init iop13xx_init_atu_setup(char *str)
+{
+        init_atu = IOP13XX_INIT_ATU_NONE;
+        if (str) {
+                while (*str != '\0') {
+                        switch (*str) {
+                        case 'x':
+                        case 'X':
+                                init_atu |= IOP13XX_INIT_ATU_ATUX;
+                                init_atu &= ~IOP13XX_INIT_ATU_NONE;
+                                break;
+                        case 'e':
+                        case 'E':
+                                init_atu |= IOP13XX_INIT_ATU_ATUE;
+                                init_atu &= ~IOP13XX_INIT_ATU_NONE;
+                                break;
+                        case ',':
+                        case '=':
+                                break;
+                        default:
+                                PRINTK("\"iop13xx_init_atu\" malformed at "
+                                            "character: \'%c\'", *str);
+                                *(str + 1) = '\0';
+                                init_atu = IOP13XX_INIT_ATU_DEFAULT;
+                        }
+                        str++;
+                }
+        }
+        return 1;
+}
+
+__setup("iop13xx_init_atu", iop13xx_init_atu_setup);
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
new file mode 100644 (file)
index 0000000..3756d2c
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * iop13xx platform Initialization
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/serial_8250.h>
+#ifdef CONFIG_MTD_PHYSMAP
+#include <linux/mtd/physmap.h>
+#endif
+#include <asm/mach/map.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#define IOP13XX_UART_XTAL 33334000
+#define IOP13XX_SETUP_DEBUG 0
+#define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x)))
+
+/* Standard IO mapping for all IOP13XX based systems
+ */
+static struct map_desc iop13xx_std_desc[] __initdata = {
+       {    /* mem mapped registers */
+               .virtual = IOP13XX_PMMR_VIRT_MEM_BASE,
+               .pfn     = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE),
+               .length  = IOP13XX_PMMR_SIZE,
+               .type    = MT_DEVICE,
+       }, { /* PCIE IO space */
+               .virtual = IOP13XX_PCIE_LOWER_IO_VA,
+               .pfn     = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA),
+               .length  = IOP13XX_PCIX_IO_WINDOW_SIZE,
+               .type    = MT_DEVICE,
+       }, { /* PCIX IO space */
+               .virtual = IOP13XX_PCIX_LOWER_IO_VA,
+               .pfn     = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA),
+               .length  = IOP13XX_PCIX_IO_WINDOW_SIZE,
+               .type    = MT_DEVICE,
+       },
+};
+
+static struct resource iop13xx_uart0_resources[] = {
+       [0] = {
+               .start = IOP13XX_UART0_PHYS,
+               .end = IOP13XX_UART0_PHYS + 0x3f,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_UART0,
+               .end = IRQ_IOP13XX_UART0,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_uart1_resources[] = {
+       [0] = {
+               .start = IOP13XX_UART1_PHYS,
+               .end = IOP13XX_UART1_PHYS + 0x3f,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_UART1,
+               .end = IRQ_IOP13XX_UART1,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct plat_serial8250_port iop13xx_uart0_data[] = {
+       {
+       .membase     = (char*)(IOP13XX_UART0_VIRT),
+       .mapbase     = (IOP13XX_UART0_PHYS),
+       .irq         = IRQ_IOP13XX_UART0,
+       .uartclk     = IOP13XX_UART_XTAL,
+       .regshift    = 2,
+       .iotype      = UPIO_MEM,
+       .flags       = UPF_SKIP_TEST,
+       },
+       {  },
+};
+
+static struct plat_serial8250_port iop13xx_uart1_data[] = {
+       {
+       .membase     = (char*)(IOP13XX_UART1_VIRT),
+       .mapbase     = (IOP13XX_UART1_PHYS),
+       .irq         = IRQ_IOP13XX_UART1,
+       .uartclk     = IOP13XX_UART_XTAL,
+       .regshift    = 2,
+       .iotype      = UPIO_MEM,
+       .flags       = UPF_SKIP_TEST,
+       },
+       {  },
+};
+
+/* The ids are fixed up later in iop13xx_platform_init */
+static struct platform_device iop13xx_uart0 = {
+       .name = "serial8250",
+       .id = 0,
+       .dev.platform_data = iop13xx_uart0_data,
+       .num_resources = 2,
+       .resource = iop13xx_uart0_resources,
+};
+
+static struct platform_device iop13xx_uart1 = {
+       .name = "serial8250",
+       .id = 0,
+       .dev.platform_data = iop13xx_uart1_data,
+       .num_resources = 2,
+       .resource = iop13xx_uart1_resources
+};
+
+static struct resource iop13xx_i2c_0_resources[] = {
+       [0] = {
+               .start = IOP13XX_I2C0_PHYS,
+               .end = IOP13XX_I2C0_PHYS + 0x18,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_I2C_0,
+               .end = IRQ_IOP13XX_I2C_0,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_i2c_1_resources[] = {
+       [0] = {
+               .start = IOP13XX_I2C1_PHYS,
+               .end = IOP13XX_I2C1_PHYS + 0x18,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_I2C_1,
+               .end = IRQ_IOP13XX_I2C_1,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+static struct resource iop13xx_i2c_2_resources[] = {
+       [0] = {
+               .start = IOP13XX_I2C2_PHYS,
+               .end = IOP13XX_I2C2_PHYS + 0x18,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IOP13XX_I2C_2,
+               .end = IRQ_IOP13XX_I2C_2,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+/* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so
+ * we just use the same device name.
+ */
+
+/* The ids are fixed up later in iop13xx_platform_init */
+static struct platform_device iop13xx_i2c_0_controller = {
+       .name = "IOP3xx-I2C",
+       .id = 0,
+       .num_resources = 2,
+       .resource = iop13xx_i2c_0_resources
+};
+
+static struct platform_device iop13xx_i2c_1_controller = {
+       .name = "IOP3xx-I2C",
+       .id = 0,
+       .num_resources = 2,
+       .resource = iop13xx_i2c_1_resources
+};
+
+static struct platform_device iop13xx_i2c_2_controller = {
+       .name = "IOP3xx-I2C",
+       .id = 0,
+       .num_resources = 2,
+       .resource = iop13xx_i2c_2_resources
+};
+
+#ifdef CONFIG_MTD_PHYSMAP
+/* PBI Flash Device
+ */
+static struct physmap_flash_data iq8134x_flash_data = {
+       .width = 2,
+};
+
+static struct resource iq8134x_flash_resource = {
+       .start = IQ81340_FLASHBASE,
+       .end   = 0,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device iq8134x_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = { .platform_data  = &iq8134x_flash_data, },
+       .num_resources  = 1,
+       .resource       = &iq8134x_flash_resource,
+};
+
+static unsigned long iq8134x_probe_flash_size(void)
+{
+       uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE);
+       int i;
+       char query[3];
+       unsigned long size = 0;
+       int width = iq8134x_flash_data.width;
+
+       if (flash_addr) {
+               /* send CFI 'query' command */
+               writew(0x98, flash_addr);
+
+               /* check for CFI compliance */
+               for (i = 0; i < 3 * width; i += width)
+                       query[i / width] = readb(flash_addr + (0x10 * width) + i);
+
+               /* read the size */
+               if (memcmp(query, "QRY", 3) == 0)
+                       size = 1 << readb(flash_addr + (0x27 * width));
+
+               /* send CFI 'read array' command */
+               writew(0xff, flash_addr);
+
+               iounmap(flash_addr);
+       }
+
+       return size;
+}
+#endif
+
+void __init iop13xx_map_io(void)
+{
+       /* Initialize the Static Page Table maps */
+       iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
+}
+
+static int init_uart = 0;
+static int init_i2c = 0;
+
+void __init iop13xx_platform_init(void)
+{
+       int i;
+       u32 uart_idx, i2c_idx, plat_idx;
+       struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
+
+       /* set the bases so we can read the device id */
+       iop13xx_set_atu_mmr_bases();
+
+       memset(iop13xx_devices, 0, sizeof(iop13xx_devices));
+
+       if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
+               switch (iop13xx_dev_id()) {
+               /* enable both uarts on iop341 and iop342 */
+               case 0x3380:
+               case 0x3384:
+               case 0x3388:
+               case 0x338c:
+               case 0x3382:
+               case 0x3386:
+               case 0x338a:
+               case 0x338e:
+                       init_uart |= IOP13XX_INIT_UART_0;
+                       init_uart |= IOP13XX_INIT_UART_1;
+                       break;
+               /* only enable uart 1 */
+               default:
+                       init_uart |= IOP13XX_INIT_UART_1;
+               }
+       }
+
+       if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) {
+               switch (iop13xx_dev_id()) {
+               /* enable all i2c units on iop341 and iop342 */
+               case 0x3380:
+               case 0x3384:
+               case 0x3388:
+               case 0x338c:
+               case 0x3382:
+               case 0x3386:
+               case 0x338a:
+               case 0x338e:
+                       init_i2c |= IOP13XX_INIT_I2C_0;
+                       init_i2c |= IOP13XX_INIT_I2C_1;
+                       init_i2c |= IOP13XX_INIT_I2C_2;
+                       break;
+               /* only enable i2c 1 and 2 */
+               default:
+                       init_i2c |= IOP13XX_INIT_I2C_1;
+                       init_i2c |= IOP13XX_INIT_I2C_2;
+               }
+       }
+
+       plat_idx = 0;
+       uart_idx = 0;
+       i2c_idx = 0;
+
+       /* uart 1 (if enabled) is ttyS0 */
+       if (init_uart & IOP13XX_INIT_UART_1) {
+               PRINTK("Adding uart1 to platform device list\n");
+               iop13xx_uart1.id = uart_idx++;
+               iop13xx_devices[plat_idx++] = &iop13xx_uart1;
+       }
+       if (init_uart & IOP13XX_INIT_UART_0) {
+               PRINTK("Adding uart0 to platform device list\n");
+               iop13xx_uart0.id = uart_idx++;
+               iop13xx_devices[plat_idx++] = &iop13xx_uart0;
+       }
+
+       for(i = 0; i < IQ81340_NUM_I2C; i++) {
+               if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG)
+                       printk("Adding i2c%d to platform device list\n", i);
+               switch(init_i2c & (1 << i)) {
+               case IOP13XX_INIT_I2C_0:
+                       iop13xx_i2c_0_controller.id = i2c_idx++;
+                       iop13xx_devices[plat_idx++] =
+                               &iop13xx_i2c_0_controller;
+                       break;
+               case IOP13XX_INIT_I2C_1:
+                       iop13xx_i2c_1_controller.id = i2c_idx++;
+                       iop13xx_devices[plat_idx++] =
+                               &iop13xx_i2c_1_controller;
+                       break;
+               case IOP13XX_INIT_I2C_2:
+                       iop13xx_i2c_2_controller.id = i2c_idx++;
+                       iop13xx_devices[plat_idx++] =
+                               &iop13xx_i2c_2_controller;
+                       break;
+               }
+       }
+
+#ifdef CONFIG_MTD_PHYSMAP
+       iq8134x_flash_resource.end = iq8134x_flash_resource.start +
+                               iq8134x_probe_flash_size();
+       if (iq8134x_flash_resource.end > iq8134x_flash_resource.start)
+               iop13xx_devices[plat_idx++] = &iq8134x_flash;
+       else
+               printk(KERN_ERR "%s: Failed to probe flash size\n", __FUNCTION__);
+#endif
+
+       platform_add_devices(iop13xx_devices, plat_idx);
+}
+
+static int __init iop13xx_init_uart_setup(char *str)
+{
+       if (str) {
+               while (*str != '\0') {
+                       switch(*str) {
+                       case '0':
+                               init_uart |= IOP13XX_INIT_UART_0;
+                               break;
+                       case '1':
+                               init_uart |= IOP13XX_INIT_UART_1;
+                               break;
+                       case ',':
+                       case '=':
+                               break;
+                       default:
+                               PRINTK("\"iop13xx_init_uart\" malformed"
+                                           " at character: \'%c\'", *str);
+                               *(str + 1) = '\0';
+                               init_uart = IOP13XX_INIT_UART_DEFAULT;
+                       }
+                       str++;
+               }
+       }
+       return 1;
+}
+
+static int __init iop13xx_init_i2c_setup(char *str)
+{
+       if (str) {
+               while (*str != '\0') {
+                       switch(*str) {
+                       case '0':
+                               init_i2c |= IOP13XX_INIT_I2C_0;
+                               break;
+                       case '1':
+                               init_i2c |= IOP13XX_INIT_I2C_1;
+                               break;
+                       case '2':
+                               init_i2c |= IOP13XX_INIT_I2C_2;
+                               break;
+                       case ',':
+                       case '=':
+                               break;
+                       default:
+                               PRINTK("\"iop13xx_init_i2c\" malformed"
+                                           " at character: \'%c\'", *str);
+                               *(str + 1) = '\0';
+                               init_i2c = IOP13XX_INIT_I2C_DEFAULT;
+                       }
+                       str++;
+               }
+       }
+       return 1;
+}
+
+__setup("iop13xx_init_uart", iop13xx_init_uart_setup);
+__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
diff --git a/arch/arm/mach-iop13xx/time.c b/arch/arm/mach-iop13xx/time.c
new file mode 100644 (file)
index 0000000..8b21365
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * arch/arm/mach-iop13xx/time.c
+ *
+ * Timer code for IOP13xx (copied from IOP32x/IOP33x implementation)
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2002-2003 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+static unsigned long ticks_per_jiffy;
+static unsigned long ticks_per_usec;
+static unsigned long next_jiffy_time;
+
+static inline u32 read_tcr1(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
+       return val;
+}
+
+unsigned long iop13xx_gettimeoffset(void)
+{
+       unsigned long offset;
+       u32 cp_flags;
+
+       cp_flags = iop13xx_cp6_save();
+       offset = next_jiffy_time - read_tcr1();
+       iop13xx_cp6_restore(cp_flags);
+
+       return offset / ticks_per_usec;
+}
+
+static irqreturn_t
+iop13xx_timer_interrupt(int irq, void *dev_id)
+{
+       u32 cp_flags = iop13xx_cp6_save();
+
+       write_seqlock(&xtime_lock);
+
+       asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (1));
+
+       while ((signed long)(next_jiffy_time - read_tcr1())
+                                                       >= ticks_per_jiffy) {
+               timer_tick();
+               next_jiffy_time -= ticks_per_jiffy;
+       }
+
+       write_sequnlock(&xtime_lock);
+
+       iop13xx_cp6_restore(cp_flags);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction iop13xx_timer_irq = {
+       .name           = "IOP13XX Timer Tick",
+       .handler        = iop13xx_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+};
+
+void __init iop13xx_init_time(unsigned long tick_rate)
+{
+       u32 timer_ctl;
+       u32 cp_flags;
+
+       ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+       ticks_per_usec = tick_rate / 1000000;
+       next_jiffy_time = 0xffffffff;
+
+       timer_ctl = IOP13XX_TMR_EN | IOP13XX_TMR_PRIVILEGED |
+                       IOP13XX_TMR_RELOAD | IOP13XX_TMR_RATIO_1_1;
+
+       /*
+        * We use timer 0 for our timer interrupt, and timer 1 as
+        * monotonic counter for tracking missed jiffies.
+        */
+       cp_flags = iop13xx_cp6_save();
+       asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (ticks_per_jiffy - 1));
+       asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (timer_ctl));
+       asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (0xffffffff));
+       asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (timer_ctl));
+       iop13xx_cp6_restore(cp_flags);
+
+       setup_irq(IRQ_IOP13XX_TIMER0, &iop13xx_timer_irq);
+}
index 69d6302..3ec1cd5 100644 (file)
@@ -70,7 +70,7 @@ void __init iop32x_init_irq(void)
 
        for (i = 0; i < NR_IRQS; i++) {
                set_irq_chip(i, &ext_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 }
index 63304b3..00b37f3 100644 (file)
@@ -121,7 +121,7 @@ void __init iop33x_init_irq(void)
 
        for (i = 0; i < NR_IRQS; i++) {
                set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 }
index 22c98e9..27b7480 100644 (file)
@@ -308,7 +308,7 @@ EXPORT_SYMBOL(gpio_line_config);
 /*************************************************************************
  * IRQ handling IXP2000
  *************************************************************************/
-static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc)
 {                               
        int i;
        unsigned long status = *IXP2000_GPIO_INST;
@@ -373,7 +373,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
        ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
 }
 
-static struct irqchip ixp2000_GPIO_irq_chip = {
+static struct irq_chip ixp2000_GPIO_irq_chip = {
        .ack            = ixp2000_GPIO_irq_mask_ack,
        .mask           = ixp2000_GPIO_irq_mask,
        .unmask         = ixp2000_GPIO_irq_unmask,
@@ -401,7 +401,7 @@ static void ixp2000_pci_irq_unmask(unsigned int irq)
 /*
  * Error interrupts. These are used extensively by the microengine drivers
  */
-static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        int i;
        unsigned long status = *IXP2000_IRQ_ERR_STATUS;
@@ -426,13 +426,13 @@ static void ixp2000_err_irq_unmask(unsigned int irq)
                        (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
 }
 
-static struct irqchip ixp2000_err_irq_chip = {
+static struct irq_chip ixp2000_err_irq_chip = {
        .ack    = ixp2000_err_irq_mask,
        .mask   = ixp2000_err_irq_mask,
        .unmask = ixp2000_err_irq_unmask
 };
 
-static struct irqchip ixp2000_pci_irq_chip = {
+static struct irq_chip ixp2000_pci_irq_chip = {
        .ack    = ixp2000_pci_irq_mask,
        .mask   = ixp2000_pci_irq_mask,
        .unmask = ixp2000_pci_irq_unmask
@@ -448,7 +448,7 @@ static void ixp2000_irq_unmask(unsigned int irq)
        ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));
 }
 
-static struct irqchip ixp2000_irq_chip = {
+static struct irq_chip ixp2000_irq_chip = {
        .ack    = ixp2000_irq_mask,
        .mask   = ixp2000_irq_mask,
        .unmask = ixp2000_irq_unmask
@@ -484,7 +484,7 @@ void __init ixp2000_init_irq(void)
        for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
                if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
                        set_irq_chip(irq, &ixp2000_irq_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                } else set_irq_flags(irq, 0);
        }
@@ -493,7 +493,7 @@ void __init ixp2000_init_irq(void)
                if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
                                IXP2000_VALID_ERR_IRQ_MASK) {
                        set_irq_chip(irq, &ixp2000_err_irq_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                }
                else
@@ -503,7 +503,7 @@ void __init ixp2000_init_irq(void)
 
        for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
                set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
        set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
@@ -516,7 +516,7 @@ void __init ixp2000_init_irq(void)
        ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
        for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
                set_irq_chip(irq, &ixp2000_pci_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 }
index aa26550..52b368b 100644 (file)
@@ -106,7 +106,7 @@ static void ixdp2x00_irq_unmask(unsigned int irq)
                ixp2000_release_slowport(&old_cfg);
 }
 
-static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
         volatile u32 ex_interrupt = 0;
        static struct slowport_cfg old_cfg;
@@ -129,7 +129,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc)
 
        for(i = 0; i < board_irq_count; i++) {
                if(ex_interrupt & (1 << i))  {
-                       struct irqdesc *cpld_desc;
+                       struct irq_desc *cpld_desc;
                        int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
                        cpld_desc = irq_desc + cpld_irq;
                        desc_handle_irq(cpld_irq, cpld_desc);
@@ -139,7 +139,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc)
        desc->chip->unmask(irq);
 }
 
-static struct irqchip ixdp2x00_cpld_irq_chip = {
+static struct irq_chip ixdp2x00_cpld_irq_chip = {
        .ack    = ixdp2x00_irq_mask,
        .mask   = ixdp2x00_irq_mask,
        .unmask = ixdp2x00_irq_unmask
@@ -162,7 +162,7 @@ void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long
 
        for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
                set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
index 9ccae9e..3084a5f 100644 (file)
@@ -63,7 +63,7 @@ static void ixdp2x01_irq_unmask(unsigned int irq)
 
 static u32 valid_irq_mask;
 
-static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        u32 ex_interrupt;
        int i;
@@ -79,7 +79,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc)
 
        for (i = 0; i < IXP2000_BOARD_IRQS; i++) {
                if (ex_interrupt & (1 << i)) {
-                       struct irqdesc *cpld_desc;
+                       struct irq_desc *cpld_desc;
                        int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
                        cpld_desc = irq_desc + cpld_irq;
                        desc_handle_irq(cpld_irq, cpld_desc);
@@ -89,7 +89,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc)
        desc->chip->unmask(irq);
 }
 
-static struct irqchip ixdp2x01_irq_chip = {
+static struct irq_chip ixdp2x01_irq_chip = {
        .mask   = ixdp2x01_irq_mask,
        .ack    = ixdp2x01_irq_mask,
        .unmask = ixdp2x01_irq_unmask
@@ -119,7 +119,7 @@ void __init ixdp2x01_init_irq(void)
        for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
                if (irq & valid_irq_mask) {
                        set_irq_chip(irq, &ixdp2x01_irq_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                } else {
                        set_irq_flags(irq, 0);
index d4bf1e1..5a09a90 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <asm/mach/pci.h>
 
-static int pci_master_aborts = 0;
+static volatile int pci_master_aborts = 0;
 
 static int clear_master_aborts(void);
 
index a704a18..ce6ad63 100644 (file)
@@ -224,14 +224,14 @@ static void ixp23xx_irq_edge_unmask(unsigned int irq)
        *intr_reg |= (1 << (irq % 32));
 }
 
-static struct irqchip ixp23xx_irq_level_chip = {
+static struct irq_chip ixp23xx_irq_level_chip = {
        .ack            = ixp23xx_irq_mask,
        .mask           = ixp23xx_irq_mask,
        .unmask         = ixp23xx_irq_level_unmask,
        .set_type       = ixp23xx_irq_set_type
 };
 
-static struct irqchip ixp23xx_irq_edge_chip = {
+static struct irq_chip ixp23xx_irq_edge_chip = {
        .ack            = ixp23xx_irq_ack,
        .mask           = ixp23xx_irq_mask,
        .unmask         = ixp23xx_irq_edge_unmask,
@@ -251,11 +251,11 @@ static void ixp23xx_pci_irq_unmask(unsigned int irq)
 /*
  * TODO: Should this just be done at ASM level?
  */
-static void pci_handler(unsigned int irq, struct irqdesc *desc)
+static void pci_handler(unsigned int irq, struct irq_desc *desc)
 {
        u32 pci_interrupt;
        unsigned int irqno;
-       struct irqdesc *int_desc;
+       struct irq_desc *int_desc;
 
        pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
 
@@ -276,7 +276,7 @@ static void pci_handler(unsigned int irq, struct irqdesc *desc)
        desc->chip->unmask(irq);
 }
 
-static struct irqchip ixp23xx_pci_irq_chip = {
+static struct irq_chip ixp23xx_pci_irq_chip = {
        .ack    = ixp23xx_pci_irq_mask,
        .mask   = ixp23xx_pci_irq_mask,
        .unmask = ixp23xx_pci_irq_unmask
@@ -287,11 +287,11 @@ static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
        switch (type) {
        case IXP23XX_IRQ_LEVEL:
                set_irq_chip(irq, &ixp23xx_irq_level_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                break;
        case IXP23XX_IRQ_EDGE:
                set_irq_chip(irq, &ixp23xx_irq_edge_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                break;
        }
        set_irq_flags(irq, IRQF_VALID);
@@ -322,7 +322,7 @@ void __init ixp23xx_init_irq(void)
 
        for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
                set_irq_chip(irq, &ixp23xx_pci_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
index b6ab0e8..7a86a25 100644 (file)
@@ -60,7 +60,7 @@ static void ixdp2351_inta_unmask(unsigned int irq)
        *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
 }
 
-static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc)
+static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc)
 {
        u16 ex_interrupt =
                *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
@@ -70,7 +70,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc)
 
        for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
                if (ex_interrupt & (1 << i)) {
-                       struct irqdesc *cpld_desc;
+                       struct irq_desc *cpld_desc;
                        int cpld_irq =
                                IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
                        cpld_desc = irq_desc + cpld_irq;
@@ -81,7 +81,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc)
        desc->chip->unmask(irq);
 }
 
-static struct irqchip ixdp2351_inta_chip = {
+static struct irq_chip ixdp2351_inta_chip = {
        .ack    = ixdp2351_inta_mask,
        .mask   = ixdp2351_inta_mask,
        .unmask = ixdp2351_inta_unmask
@@ -97,7 +97,7 @@ static void ixdp2351_intb_unmask(unsigned int irq)
        *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
 }
 
-static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc)
+static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc)
 {
        u16 ex_interrupt =
                *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
@@ -107,7 +107,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc)
 
        for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
                if (ex_interrupt & (1 << i)) {
-                       struct irqdesc *cpld_desc;
+                       struct irq_desc *cpld_desc;
                        int cpld_irq =
                                IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
                        cpld_desc = irq_desc + cpld_irq;
@@ -118,7 +118,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc)
        desc->chip->unmask(irq);
 }
 
-static struct irqchip ixdp2351_intb_chip = {
+static struct irq_chip ixdp2351_intb_chip = {
        .ack    = ixdp2351_intb_mask,
        .mask   = ixdp2351_intb_mask,
        .unmask = ixdp2351_intb_unmask
@@ -142,7 +142,7 @@ void ixdp2351_init_irq(void)
             irq++) {
                if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
                        set_irq_flags(irq, IRQF_VALID);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_chip(irq, &ixdp2351_inta_chip);
                }
        }
@@ -153,7 +153,7 @@ void ixdp2351_init_irq(void)
             irq++) {
                if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
                        set_irq_flags(irq, IRQF_VALID);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_chip(irq, &ixdp2351_intb_chip);
                }
        }
index 3b34fa3..ac7d43d 100644 (file)
@@ -36,7 +36,7 @@
 
 extern int (*external_fault) (unsigned long, struct pt_regs *);
 
-static int pci_master_aborts = 0;
+static volatile int pci_master_aborts = 0;
 
 #ifdef DEBUG
 #define DBG(x...)      printk(x)
index fbe288a..2ec9a9e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/timex.h>
 #include <linux/clocksource.h>
 
+#include <asm/arch/udc.h>
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -39,6 +40,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+static int __init ixp4xx_clocksource_init(void);
+
 /*************************************************************************
  * IXP4xx chipset I/O mapping
  *************************************************************************/
@@ -195,7 +198,7 @@ static void ixp4xx_irq_unmask(unsigned int irq)
                *IXP4XX_ICMR |= (1 << irq);
 }
 
-static struct irqchip ixp4xx_irq_chip = {
+static struct irq_chip ixp4xx_irq_chip = {
        .name           = "IXP4xx",
        .ack            = ixp4xx_irq_ack,
        .mask           = ixp4xx_irq_mask,
@@ -224,7 +227,7 @@ void __init ixp4xx_init_irq(void)
         /* Default to all level triggered */
        for(i = 0; i < NR_IRQS; i++) {
                set_irq_chip(i, &ixp4xx_irq_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 }
@@ -280,12 +283,52 @@ static void __init ixp4xx_timer_init(void)
 
        /* Connect the interrupt handler and enable the interrupt */
        setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
+
+       ixp4xx_clocksource_init();
 }
 
 struct sys_timer ixp4xx_timer = {
        .init           = ixp4xx_timer_init,
 };
 
+static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
+
+void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
+{
+       memcpy(&ixp4xx_udc_info, info, sizeof *info);
+}
+
+static struct resource ixp4xx_udc_resources[] = {
+       [0] = {
+               .start  = 0xc800b000,
+               .end    = 0xc800bfff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_IXP4XX_USB,
+               .end    = IRQ_IXP4XX_USB,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+/*
+ * USB device controller. The IXP4xx uses the same controller as PXA2XX,
+ * so we just use the same device.
+ */
+static struct platform_device ixp4xx_udc_device = {
+       .name           = "pxa2xx-udc",
+       .id             = -1,
+       .num_resources  = 2,
+       .resource       = ixp4xx_udc_resources,
+       .dev            = {
+               .platform_data = &ixp4xx_udc_info,
+       },
+};
+
+static struct platform_device *ixp4xx_devices[] __initdata = {
+       &ixp4xx_udc_device,
+};
+
 static struct resource ixp46x_i2c_resources[] = {
        [0] = {
                .start  = 0xc8011000,
@@ -321,6 +364,8 @@ void __init ixp4xx_sys_init(void)
 {
        ixp4xx_exp_bus_size = SZ_16M;
 
+       platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
+
        if (cpu_is_ixp46x()) {
                int region;
 
@@ -363,5 +408,3 @@ static int __init ixp4xx_clocksource_init(void)
 
        return 0;
 }
-
-device_initcall(ixp4xx_clocksource_init);
index b7af564..561a0fe 100644 (file)
@@ -55,7 +55,7 @@ static void l7200_unmask_irq(unsigned int irq)
        IRQ_ENABLE = 1 << irq;
 }
 
-static struct irqchip l7200_irq_chip = {
+static struct irq_chip l7200_irq_chip = {
        .ack            = l7200_mask_irq,
        .mask           = l7200_mask_irq,
        .unmask         = l7200_unmask_irq
@@ -71,7 +71,7 @@ static void __init l7200_init_irq(void)
        for (irq = 0; irq < NR_IRQS; irq++) {
                set_irq_chip(irq, &l7200_irq_chip);
                set_irq_flags(irq, IRQF_VALID);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
        }
 
        init_FIQ();
index 15fbcc9..6d26661 100644 (file)
@@ -71,7 +71,7 @@ static struct irq_chip kev7a400_cpld_chip = {
 };
 
 
-static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc)
+static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
        u32 mask = CPLD_LATCHED_INTS;
        irq = IRQ_KEV7A400_CPLD;
@@ -88,7 +88,7 @@ void __init lh7a40x_init_board_irq (void)
        for (irq = IRQ_KEV7A400_CPLD;
             irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) {
                set_irq_chip (irq, &kev7a400_cpld_chip);
-               set_irq_handler (irq, do_edge_IRQ);
+               set_irq_handler (irq, handle_edge_irq);
                set_irq_flags (irq, IRQF_VALID);
        }
        set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
index 8441e0a..fe64946 100644 (file)
@@ -207,7 +207,7 @@ static struct irq_chip lpd7a40x_cpld_chip = {
        .unmask = lh7a40x_unmask_cpld_irq,
 };
 
-static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc)
+static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
        unsigned int mask = CPLD_INTERRUPTS;
 
@@ -279,7 +279,7 @@ void __init lh7a40x_init_board_irq (void)
        for (irq = IRQ_BOARD_START;
             irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
                set_irq_chip (irq, &lpd7a40x_cpld_chip);
-               set_irq_handler (irq, do_level_IRQ);
+               set_irq_handler (irq, handle_level_irq);
                set_irq_flags (irq, IRQF_VALID);
        }
 
index 6460713..c7433b3 100644 (file)
@@ -51,7 +51,7 @@ irq_chip lh7a400_cpld_chip = {
 };
 
 static void
-lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc)
+lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
        u32 mask = CPLD_LATCHED_INTS;
        irq = IRQ_KEV_7A400_CPLD;
@@ -71,7 +71,7 @@ lh7a400_init_board_irq (void)
        for (irq = IRQ_KEV7A400_CPLD;
             irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) {
                set_irq_chip (irq, &lh7a400_cpld_chip);
-               set_irq_handler (irq, do_edge_IRQ);
+               set_irq_handler (irq, handle_edge_irq);
                set_irq_flags (irq, IRQF_VALID);
        }
        set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
index 091b2dc..0b938e8 100644 (file)
@@ -74,11 +74,11 @@ void __init lh7a400_init_irq (void)
                case IRQ_GPIO6INTR:
                case IRQ_GPIO7INTR:
                        set_irq_chip (irq, &lh7a400_gpio_chip);
-                       set_irq_handler (irq, do_level_IRQ); /* OK default */
+                       set_irq_handler (irq, handle_level_irq); /* OK default */
                        break;
                default:
                        set_irq_chip (irq, &lh7a400_internal_chip);
-                       set_irq_handler (irq, do_level_IRQ);
+                       set_irq_handler (irq, handle_level_irq);
                }
                set_irq_flags (irq, IRQF_VALID);
        }
index 7059b98..5760f8c 100644 (file)
@@ -161,13 +161,13 @@ void __init lh7a404_init_irq (void)
                        set_irq_chip (irq, irq < 32
                                      ? &lh7a404_gpio_vic1_chip
                                      : &lh7a404_gpio_vic2_chip);
-                       set_irq_handler (irq, do_level_IRQ); /* OK default */
+                       set_irq_handler (irq, handle_level_irq); /* OK default */
                        break;
                default:
                        set_irq_chip (irq, irq < 32
                                      ? &lh7a404_vic1_chip
                                      : &lh7a404_vic2_chip);
-                       set_irq_handler (irq, do_level_IRQ);
+                       set_irq_handler (irq, handle_level_irq);
                }
                set_irq_flags (irq, IRQF_VALID);
        }
index b203768..15b9577 100644 (file)
@@ -57,7 +57,7 @@ static struct irq_chip lh7a40x_cpld_chip = {
        .unmask = lh7a40x_unmask_cpld_irq,
 };
 
-static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc)
+static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
        unsigned int mask = CPLD_INTERRUPTS;
 
@@ -118,7 +118,7 @@ void __init lh7a40x_init_board_irq (void)
        for (irq = IRQ_BOARD_START;
             irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
                set_irq_chip (irq, &lh7a40x_cpld_chip);
-               set_irq_handler (irq, do_edge_IRQ);
+               set_irq_handler (irq, handle_edge_irq);
                set_irq_flags (irq, IRQF_VALID);
        }
 
index edbbbdc..b9ca8f9 100644 (file)
@@ -69,7 +69,7 @@ static struct platform_device *devices[] __initdata = {
 #endif
 
 static void
-netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
+netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 {
        unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
        unsigned int stat;
@@ -160,7 +160,7 @@ netx_hif_unmask_irq(unsigned int _irq)
        DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
 }
 
-static struct irqchip netx_hif_chip = {
+static struct irq_chip netx_hif_chip = {
        .ack = netx_hif_ack_irq,
        .mask = netx_hif_mask_irq,
        .unmask = netx_hif_unmask_irq,
@@ -175,7 +175,7 @@ void __init netx_init_irq(void)
 
        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
                set_irq_chip(irq, &netx_hif_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
index f225a08..9d2346f 100644 (file)
@@ -323,7 +323,8 @@ static int h3_transceiver_mode(struct device *dev, int mode)
 
        cancel_delayed_work(&irda_config->gpio_expa);
        PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
-       schedule_work(&irda_config->gpio_expa);
+#error this is not permitted - mode is an argument variable
+       schedule_delayed_work(&irda_config->gpio_expa, 0);
 
        return 0;
 }
index dbc555d..cbe909b 100644 (file)
@@ -74,7 +74,7 @@ static struct omap_kp_platform_data nokia770_kp_data = {
        .rows           = 8,
        .cols           = 8,
        .keymap         = nokia770_keymap,
-       .keymapsize     = ARRAY_SIZE(nokia770_keymap)
+       .keymapsize     = ARRAY_SIZE(nokia770_keymap),
        .delay          = 4,
 };
 
@@ -191,7 +191,7 @@ static void nokia770_audio_pwr_up(void)
                printk("HP connected\n");
 }
 
-static void codec_delayed_power_down(void *arg)
+static void codec_delayed_power_down(struct work_struct *work)
 {
        down(&audio_pwr_sem);
        if (audio_pwr_state == -1)
@@ -200,7 +200,7 @@ static void codec_delayed_power_down(void *arg)
        up(&audio_pwr_sem);
 }
 
-static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+static DECLARE_DELAYED_WORK(codec_power_down_work, codec_delayed_power_down);
 
 static void nokia770_audio_pwr_down(void)
 {
index a611c3b..6dcd10a 100644 (file)
@@ -55,7 +55,7 @@ static inline void omap_init_irda(void) {}
 
 /*-------------------------------------------------------------------------*/
 
-#if    defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC)
+#if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
 
 #define        OMAP_RTC_BASE           0xfffb4800
 
index 8e40208..30e1881 100644 (file)
@@ -84,9 +84,9 @@ static void fpga_mask_ack_irq(unsigned int irq)
        fpga_ack_irq(irq);
 }
 
-void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc)
+void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct irqdesc *d;
+       struct irq_desc *d;
        u32 stat;
        int fpga_irq;
 
@@ -168,7 +168,7 @@ void omap1510_fpga_init_irq(void)
                        set_irq_chip(i, &omap_fpga_irq);
                }
 
-               set_irq_handler(i, do_edge_IRQ);
+               set_irq_handler(i, handle_edge_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 
index 3ea140b..6383a12 100644 (file)
@@ -229,7 +229,7 @@ void __init omap_init_irq(void)
                        omap_irq_set_cfg(j, 0, 0, irq_trigger);
 
                        set_irq_chip(j, &omap_irq_chip);
-                       set_irq_handler(j, do_level_IRQ);
+                       set_irq_handler(j, handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
        }
index 3b29e59..0cbf1b0 100644 (file)
@@ -35,7 +35,7 @@ static u8 hw_led_state;
 
 static u8 tps_leds_change;
 
-static void tps_work(void *unused)
+static void tps_work(struct work_struct *unused)
 {
        for (;;) {
                u8      leds;
@@ -61,7 +61,7 @@ static void tps_work(void *unused)
        }
 }
 
-static DECLARE_WORK(work, tps_work, NULL);
+static DECLARE_WORK(work, tps_work);
 
 #ifdef CONFIG_OMAP_OSK_MISTRAL
 
index 26a95a6..3b1ad1d 100644 (file)
@@ -206,7 +206,8 @@ static int h4_transceiver_mode(struct device *dev, int mode)
 
        cancel_delayed_work(&irda_config->gpio_expa);
        PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
-       schedule_work(&irda_config->gpio_expa);
+#error this is not permitted - mode is an argument variable
+       schedule_delayed_work(&irda_config->gpio_expa, 0);
 
        return 0;
 }
index 1187009..a39d306 100644 (file)
@@ -130,7 +130,7 @@ void __init omap_init_irq(void)
 
        for (i = 0; i < nr_irqs; i++) {
                set_irq_chip(i, &omap_irq_chip);
-               set_irq_handler(i, do_level_IRQ);
+               set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
 }
index 3a4bcf3..968d0b0 100644 (file)
@@ -59,22 +59,22 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
        case IRQT_RISING:
                __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /*rising edge */
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                break;
        case IRQT_FALLING:
                __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*falling edge */
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                break;
        case IRQT_LOW:
                __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*low level */
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                break;
        case IRQT_HIGH:
                __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /* high level */
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                break;
 
        /* IRQT_BOTHEDGE is not supported */
@@ -85,7 +85,7 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
        return 0;
 }
 
-static struct irqchip pnx4008_irq_chip = {
+static struct irq_chip pnx4008_irq_chip = {
        .ack = pnx4008_mask_ack_irq,
        .mask = pnx4008_mask_irq,
        .unmask = pnx4008_unmask_irq,
index 03d07ca..9e3d0bd 100644 (file)
@@ -13,12 +13,10 @@ config ARCH_LUBBOCK
 config MACH_LOGICPD_PXA270
        bool "LogicPD PXA270 Card Engine Development Platform"
        select PXA27x
-       select IWMMXT
 
 config MACH_MAINSTONE
        bool "Intel HCDDBBVA0 Development Platform"
        select PXA27x
-       select IWMMXT
 
 config ARCH_PXA_IDP
        bool "Accelent Xscale IDP"
@@ -53,7 +51,6 @@ config PXA_SHARPSL_25x
 config PXA_SHARPSL_27x
        bool "Sharp PXA270 models (SL-Cxx00)"
        select PXA27x
-       select IWMMXT
 
 endchoice
 
@@ -129,11 +126,6 @@ config PXA27x
        help
          Select code specific to PXA27x variants
 
-config IWMMXT
-       bool
-       help
-         Enable support for iWMMXt
-
 config PXA_SHARP_C7xx
        bool
        select PXA_SSP
index 1b39874..12d2fe0 100644 (file)
@@ -36,11 +36,11 @@ I2C_CLIENT_INSMOD;
 
 static int max7310_write(struct i2c_client *client, int address, int data);
 static struct i2c_client max7310_template;
-static void akita_ioexp_work(void *private_);
+static void akita_ioexp_work(struct work_struct *private_);
 
 static struct device *akita_ioexp_device;
 static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT;
-DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL);
+DECLARE_WORK(akita_ioexp, akita_ioexp_work);
 
 
 /*
@@ -158,7 +158,7 @@ void akita_reset_ioexp(struct device *dev, unsigned char bit)
 EXPORT_SYMBOL(akita_set_ioexp);
 EXPORT_SYMBOL(akita_reset_ioexp);
 
-static void akita_ioexp_work(void *private_)
+static void akita_ioexp_work(struct work_struct *private_)
 {
        if (akita_ioexp_device)
                max7310_set_ouputs(akita_ioexp_device, ioexp_output_value);
index 45fb2c3..6ae6058 100644 (file)
 #include <linux/pm.h>
 #include <linux/string.h>
 
+#include <linux/sched.h>
+#include <asm/cnt32_to_63.h>
+#include <asm/div64.h>
+
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 
 #include "generic.h"
 
+/*
+ * This is the PXA2xx sched_clock implementation. This has a resolution
+ * of at least 308ns and a maximum value that depends on the value of
+ * CLOCK_TICK_RATE.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ */
+unsigned long long sched_clock(void)
+{
+       unsigned long long v = cnt32_to_63(OSCR);
+       /* Note: top bit ov v needs cleared unless multiplier is even. */
+
+#if    CLOCK_TICK_RATE == 3686400
+       /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
+       /* The <<1 is used to get rid of tick.hi top bit */
+       v *= 78125<<1;
+       do_div(v, 288<<1);
+#elif  CLOCK_TICK_RATE == 3250000
+       /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
+       v *= 4000;
+       do_div(v, 13);
+#elif  CLOCK_TICK_RATE == 3249600
+       /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
+       v *= 625000;
+       do_div(v, 2031);
+#else
+#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
+       /*
+        * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
+        * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
+        * years range which is nice, but with higher computation cost.
+        */
+       {
+               union {
+                       unsigned long long val;
+                       struct { unsigned long lo, hi; };
+               } x;
+               unsigned long long y;
+
+               x.val = v;
+               x.hi &= 0x7fffffff;
+               y = (unsigned long long)x.lo * NSEC_PER_SEC;
+               x.lo = y;
+               y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
+               x.hi = do_div(y, CLOCK_TICK_RATE);
+               do_div(x.val, CLOCK_TICK_RATE);
+               x.hi += y;
+               v = x.val;
+       }
+#endif
+
+       return v;
+}
+
 /*
  * Handy function to set GPIO alternate functions
  */
index ab1a160..f815678 100644 (file)
@@ -143,7 +143,7 @@ static struct irq_chip pxa_low_gpio_chip = {
  * Demux handler for GPIO>=2 edge detect interrupts
  */
 
-static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc)
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int mask;
        int loop;
@@ -286,27 +286,27 @@ void __init pxa_init_irq(void)
 
        for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
                set_irq_chip(irq, &pxa_internal_chip_low);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
 #if PXA_INTERNAL_IRQS > 32
        for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
                set_irq_chip(irq, &pxa_internal_chip_high);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 #endif
 
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
                set_irq_chip(irq, &pxa_low_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
                set_irq_chip(irq, &pxa_muxed_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index 5749f6b..8e27a64 100644 (file)
@@ -75,7 +75,7 @@ static struct irq_chip lpd270_irq_chip = {
        .unmask         = lpd270_unmask_irq,
 };
 
-static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long pending;
 
@@ -105,7 +105,7 @@ static void __init lpd270_init_irq(void)
        /* setup extra LogicPD PXA270 irqs */
        for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
                set_irq_chip(irq, &lpd270_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
        set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
index 142c33c..055de7f 100644 (file)
@@ -85,7 +85,7 @@ static struct irq_chip lubbock_irq_chip = {
        .unmask         = lubbock_unmask_irq,
 };
 
-static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
        do {
@@ -108,7 +108,7 @@ static void __init lubbock_init_irq(void)
        /* setup extra lubbock irqs */
        for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
                set_irq_chip(irq, &lubbock_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index 49c34d9..56d94d8 100644 (file)
@@ -71,7 +71,7 @@ static struct irq_chip mainstone_irq_chip = {
        .unmask         = mainstone_unmask_irq,
 };
 
-static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
        do {
@@ -94,7 +94,7 @@ static void __init mainstone_init_irq(void)
        /* setup extra Mainstone irqs */
        for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
                set_irq_chip(irq, &mainstone_irq_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
                else
index 2112c41..b4d8276 100644 (file)
@@ -83,7 +83,8 @@ int pxa_pm_enter(suspend_state_t state)
 
 #ifdef CONFIG_IWMMXT
        /* force any iWMMXt context to ram **/
-       iwmmxt_task_disable(NULL);
+       if (elf_hwcap & HWCAP_IWMMXT)
+               iwmmxt_task_disable(NULL);
 #endif
 
        /* preserve current time */
index 3ac268f..b914668 100644 (file)
@@ -124,6 +124,7 @@ static struct irqaction pxa_timer_irq = {
 static void __init pxa_timer_init(void)
 {
        struct timespec tv;
+       unsigned long flags;
 
        set_rtc = pxa_set_rtc;
 
@@ -132,12 +133,12 @@ static void __init pxa_timer_init(void)
        do_settimeofday(&tv);
 
        OIER = 0;               /* disable any timer interrupts */
-       OSCR = LATCH*2;         /* push OSCR out of the way */
-       OSMR0 = LATCH;          /* set initial match */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &pxa_timer_irq);
+       local_irq_save(flags);
        OIER = OIER_E0;         /* enable match on timer 0 to cause interrupts */
-       OSCR = 0;               /* initialize free-running timer */
+       OSMR0 = OSCR + LATCH;   /* set initial match */
+       local_irq_restore(flags);
 }
 
 #ifdef CONFIG_NO_IDLE_HZ
index 56b2716..7a02962 100644 (file)
@@ -34,7 +34,7 @@ static void iomd_unmask_irq_a(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKA);
 }
 
-static struct irqchip iomd_a_chip = {
+static struct irq_chip iomd_a_chip = {
        .ack    = iomd_ack_irq_a,
        .mask   = iomd_mask_irq_a,
        .unmask = iomd_unmask_irq_a,
@@ -58,7 +58,7 @@ static void iomd_unmask_irq_b(unsigned int irq)
        iomd_writeb(val | mask, IOMD_IRQMASKB);
 }
 
-static struct irqchip iomd_b_chip = {
+static struct irq_chip iomd_b_chip = {
        .ack    = iomd_mask_irq_b,
        .mask   = iomd_mask_irq_b,
        .unmask = iomd_unmask_irq_b,
@@ -82,7 +82,7 @@ static void iomd_unmask_irq_dma(unsigned int irq)
        iomd_writeb(val | mask, IOMD_DMAMASK);
 }
 
-static struct irqchip iomd_dma_chip = {
+static struct irq_chip iomd_dma_chip = {
        .ack    = iomd_mask_irq_dma,
        .mask   = iomd_mask_irq_dma,
        .unmask = iomd_unmask_irq_dma,
@@ -106,7 +106,7 @@ static void iomd_unmask_irq_fiq(unsigned int irq)
        iomd_writeb(val | mask, IOMD_FIQMASK);
 }
 
-static struct irqchip iomd_fiq_chip = {
+static struct irq_chip iomd_fiq_chip = {
        .ack    = iomd_mask_irq_fiq,
        .mask   = iomd_mask_irq_fiq,
        .unmask = iomd_unmask_irq_fiq,
@@ -134,19 +134,19 @@ void __init rpc_init_irq(void)
                switch (irq) {
                case 0 ... 7:
                        set_irq_chip(irq, &iomd_a_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 8 ... 15:
                        set_irq_chip(irq, &iomd_b_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
                case 16 ... 21:
                        set_irq_chip(irq, &iomd_dma_chip);
-                       set_irq_handler(irq, do_level_IRQ);
+                       set_irq_handler(irq, handle_level_irq);
                        set_irq_flags(irq, flags);
                        break;
 
index 9aa26b9..9f46bf3 100644 (file)
@@ -41,9 +41,16 @@ config BAST_PC104_IRQ
          Say Y here to enable the PC104 IRQ routing on the
          Simtec BAST (EB2410ITX)
 
+config PM_H1940
+       bool
+       depends on PM
+       help
+         Internal node for H1940 and related PM
+
 config ARCH_H1940
        bool "IPAQ H1940"
        select CPU_S3C2410
+       select PM_H1940
        help
          Say Y here if you are using the HP IPAQ H1940
 
@@ -115,6 +122,7 @@ config MACH_VR1000
 config MACH_RX3715
        bool "HP iPAQ rx3715"
        select CPU_S3C2440
+       select PM_H1940
        help
          Say Y here if you are using the HP iPAQ rx3715.
 
index d660133..27663e2 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o
 
 obj-$(CONFIG_PM)               += pm.o sleep.o
 obj-$(CONFIG_PM_SIMTEC)                += pm-simtec.o
+obj-$(CONFIG_PM_H1940)         += pm-h1940.o
 
 # S3C2412 support
 obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o
index 23d5bee..379efe7 100644 (file)
@@ -88,7 +88,7 @@ bast_pc104_mask(unsigned int irqno)
 static void
 bast_pc104_maskack(unsigned int irqno)
 {
-       struct irqdesc *desc = irq_desc + IRQ_ISA;
+       struct irq_desc *desc = irq_desc + IRQ_ISA;
 
        bast_pc104_mask(irqno);
        desc->chip->ack(IRQ_ISA);
@@ -104,7 +104,7 @@ bast_pc104_unmask(unsigned int irqno)
        __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
 }
 
-static struct irqchip  bast_pc104_chip = {
+static struct irq_chip  bast_pc104_chip = {
        .mask        = bast_pc104_mask,
        .unmask      = bast_pc104_unmask,
        .ack         = bast_pc104_maskack
@@ -112,7 +112,7 @@ static struct irqchip  bast_pc104_chip = {
 
 static void
 bast_irq_pc104_demux(unsigned int irq,
-                    struct irqdesc *desc)
+                    struct irq_desc *desc)
 {
        unsigned int stat;
        unsigned int irqno;
@@ -157,7 +157,7 @@ static __init int bast_irq_init(void)
                        unsigned int irqno = bast_pc104_irqs[i];
 
                        set_irq_chip(irqno, &bast_pc104_chip);
-                       set_irq_handler(irqno, do_level_IRQ);
+                       set_irq_handler(irqno, handle_level_irq);
                        set_irq_flags(irqno, IRQF_VALID);
                }
        }
index 3d211dc..01abb0a 100644 (file)
@@ -40,7 +40,7 @@
 
 /* io map for dma */
 static void __iomem *dma_base;
-static kmem_cache_t *dma_kmem;
+static struct kmem_cache *dma_kmem;
 
 struct s3c24xx_dma_selection dma_sel;
 
@@ -1271,7 +1271,7 @@ struct sysdev_class dma_sysclass = {
 
 /* kmem cache implementation */
 
-static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
+static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
 {
        memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
index 683b349..3c0ed78 100644 (file)
@@ -180,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno)
        __raw_writel(mask, S3C2410_INTMSK);
 }
 
-struct irqchip s3c_irq_level_chip = {
+struct irq_chip s3c_irq_level_chip = {
        .name           = "s3c-level",
        .ack            = s3c_irq_maskack,
        .mask           = s3c_irq_mask,
@@ -188,7 +188,7 @@ struct irqchip s3c_irq_level_chip = {
        .set_wake       = s3c_irq_wake
 };
 
-static struct irqchip s3c_irq_chip = {
+static struct irq_chip s3c_irq_chip = {
        .name           = "s3c",
        .ack            = s3c_irq_ack,
        .mask           = s3c_irq_mask,
@@ -206,18 +206,6 @@ s3c_irqext_mask(unsigned int irqno)
        mask = __raw_readl(S3C24XX_EINTMASK);
        mask |= ( 1UL << irqno);
        __raw_writel(mask, S3C24XX_EINTMASK);
-
-       if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
-               /* check to see if all need masking */
-
-               if ((mask & (0xf << 4)) == (0xf << 4)) {
-                       /* all masked, mask the parent */
-                       s3c_irq_mask(IRQ_EINT4t7);
-               }
-       } else {
-               /* todo: the same check as above for the rest of the irq regs...*/
-
-       }
 }
 
 static void
@@ -229,7 +217,6 @@ s3c_irqext_ack(unsigned int irqno)
 
        bit = 1UL << (irqno - EXTINT_OFF);
 
-
        mask = __raw_readl(S3C24XX_EINTMASK);
 
        __raw_writel(bit, S3C24XX_EINTPEND);
@@ -258,8 +245,6 @@ s3c_irqext_unmask(unsigned int irqno)
        mask = __raw_readl(S3C24XX_EINTMASK);
        mask &= ~( 1UL << irqno);
        __raw_writel(mask, S3C24XX_EINTMASK);
-
-       s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
 int
@@ -344,7 +329,7 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
        return 0;
 }
 
-static struct irqchip s3c_irqext_chip = {
+static struct irq_chip s3c_irqext_chip = {
        .name           = "s3c-ext",
        .mask           = s3c_irqext_mask,
        .unmask         = s3c_irqext_unmask,
@@ -353,7 +338,7 @@ static struct irqchip s3c_irqext_chip = {
        .set_wake       = s3c_irqext_wake
 };
 
-static struct irqchip s3c_irq_eint0t4 = {
+static struct irq_chip s3c_irq_eint0t4 = {
        .name           = "s3c-ext0",
        .ack            = s3c_irq_ack,
        .mask           = s3c_irq_mask,
@@ -390,7 +375,7 @@ s3c_irq_uart0_ack(unsigned int irqno)
        s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
 }
 
-static struct irqchip s3c_irq_uart0 = {
+static struct irq_chip s3c_irq_uart0 = {
        .name           = "s3c-uart0",
        .mask           = s3c_irq_uart0_mask,
        .unmask         = s3c_irq_uart0_unmask,
@@ -417,7 +402,7 @@ s3c_irq_uart1_ack(unsigned int irqno)
        s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
 }
 
-static struct irqchip s3c_irq_uart1 = {
+static struct irq_chip s3c_irq_uart1 = {
        .name           = "s3c-uart1",
        .mask           = s3c_irq_uart1_mask,
        .unmask         = s3c_irq_uart1_unmask,
@@ -444,7 +429,7 @@ s3c_irq_uart2_ack(unsigned int irqno)
        s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
 }
 
-static struct irqchip s3c_irq_uart2 = {
+static struct irq_chip s3c_irq_uart2 = {
        .name           = "s3c-uart2",
        .mask           = s3c_irq_uart2_mask,
        .unmask         = s3c_irq_uart2_unmask,
@@ -471,7 +456,7 @@ s3c_irq_adc_ack(unsigned int irqno)
        s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
 }
 
-static struct irqchip s3c_irq_adc = {
+static struct irq_chip s3c_irq_adc = {
        .name           = "s3c-adc",
        .mask           = s3c_irq_adc_mask,
        .unmask         = s3c_irq_adc_unmask,
@@ -480,11 +465,11 @@ static struct irqchip s3c_irq_adc = {
 
 /* irq demux for adc */
 static void s3c_irq_demux_adc(unsigned int irq,
-                             struct irqdesc *desc)
+                             struct irq_desc *desc)
 {
        unsigned int subsrc, submsk;
        unsigned int offset = 9;
-       struct irqdesc *mydesc;
+       struct irq_desc *mydesc;
 
        /* read the current pending interrupts, and the mask
         * for what it is available */
@@ -512,7 +497,7 @@ static void s3c_irq_demux_uart(unsigned int start)
 {
        unsigned int subsrc, submsk;
        unsigned int offset = start - IRQ_S3CUART_RX0;
-       struct irqdesc *desc;
+       struct irq_desc *desc;
 
        /* read the current pending interrupts, and the mask
         * for what it is available */
@@ -549,7 +534,7 @@ static void s3c_irq_demux_uart(unsigned int start)
 
 static void
 s3c_irq_demux_uart0(unsigned int irq,
-                   struct irqdesc *desc)
+                   struct irq_desc *desc)
 {
        irq = irq;
        s3c_irq_demux_uart(IRQ_S3CUART_RX0);
@@ -557,7 +542,7 @@ s3c_irq_demux_uart0(unsigned int irq,
 
 static void
 s3c_irq_demux_uart1(unsigned int irq,
-                   struct irqdesc *desc)
+                   struct irq_desc *desc)
 {
        irq = irq;
        s3c_irq_demux_uart(IRQ_S3CUART_RX1);
@@ -565,7 +550,7 @@ s3c_irq_demux_uart1(unsigned int irq,
 
 static void
 s3c_irq_demux_uart2(unsigned int irq,
-                   struct irqdesc *desc)
+                   struct irq_desc *desc)
 {
        irq = irq;
        s3c_irq_demux_uart(IRQ_S3CUART_RX2);
@@ -573,7 +558,7 @@ s3c_irq_demux_uart2(unsigned int irq,
 
 static void
 s3c_irq_demux_extint8(unsigned int irq,
-                     struct irqdesc *desc)
+                     struct irq_desc *desc)
 {
        unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
        unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
@@ -595,7 +580,7 @@ s3c_irq_demux_extint8(unsigned int irq,
 
 static void
 s3c_irq_demux_extint4t7(unsigned int irq,
-                       struct irqdesc *desc)
+                       struct irq_desc *desc)
 {
        unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
        unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
@@ -738,7 +723,7 @@ void __init s3c24xx_init_irq(void)
                case IRQ_UART2:
                case IRQ_ADCPARENT:
                        set_irq_chip(irqno, &s3c_irq_level_chip);
-                       set_irq_handler(irqno, do_level_IRQ);
+                       set_irq_handler(irqno, handle_level_irq);
                        break;
 
                case IRQ_RESERVED6:
@@ -749,7 +734,7 @@ void __init s3c24xx_init_irq(void)
                default:
                        //irqdbf("registering irq %d (s3c irq)\n", irqno);
                        set_irq_chip(irqno, &s3c_irq_chip);
-                       set_irq_handler(irqno, do_edge_IRQ);
+                       set_irq_handler(irqno, handle_edge_irq);
                        set_irq_flags(irqno, IRQF_VALID);
                }
        }
@@ -769,14 +754,14 @@ void __init s3c24xx_init_irq(void)
        for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
                irqdbf("registering irq %d (ext int)\n", irqno);
                set_irq_chip(irqno, &s3c_irq_eint0t4);
-               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_handler(irqno, handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
                irqdbf("registering irq %d (extended s3c irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irqext_chip);
-               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_handler(irqno, handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
@@ -787,28 +772,28 @@ void __init s3c24xx_init_irq(void)
        for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
                irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irq_uart0);
-               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
                irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irq_uart1);
-               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
                irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irq_uart2);
-               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
        for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
                irqdbf("registering irq %d (s3c adc irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irq_adc);
-               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_handler(irqno, handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 842a9f4..3686a00 100644 (file)
@@ -17,7 +17,7 @@
 
 #define EXTINT_OFF (IRQ_EINT4 - 4)
 
-extern struct irqchip s3c_irq_level_chip;
+extern struct irq_chip s3c_irq_level_chip;
 
 static inline void
 s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
index 8c895c0..f5b9809 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-lcd.h>
 
+#include <asm/arch/h1940.h>
 #include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
 
@@ -41,6 +42,7 @@
 #include "clock.h"
 #include "devs.h"
 #include "cpu.h"
+#include "pm.h"
 
 static struct map_desc h1940_iodesc[] __initdata = {
        [0] = {
@@ -164,12 +166,16 @@ static void __init h1940_map_io(void)
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
        s3c24xx_set_board(&h1940_board);
+
+       /* setup PM */
+
+       memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
+       s3c2410_pm_init();
 }
 
 static void __init h1940_init_irq(void)
 {
        s3c24xx_init_irq();
-
 }
 
 static void __init h1940_init(void)
index e193ba6..a4ab144 100644 (file)
@@ -114,6 +114,15 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
                .clocks      = osiris_serial_clocks,
                .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
        },
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+               .clocks      = osiris_serial_clocks,
+               .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+       }
 };
 
 /* NAND Flash on Osiris board */
index 23d7c05..ecbcdf7 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-lcd.h>
 
+#include <asm/arch/h1940.h>
 #include <asm/arch/nand.h>
 #include <asm/arch/fb.h>
 
@@ -224,7 +225,9 @@ static void __init rx3715_init_irq(void)
 
 static void __init rx3715_init_machine(void)
 {
+       memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
        s3c2410_pm_init();
+
        s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
 }
 
index a0d7692..e2eda39 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
 
 #include "clock.h"
 #include "devs.h"
@@ -313,6 +314,50 @@ static struct platform_device vr1000_dm9k1 = {
        }
 };
 
+/* LEDS */
+
+static struct s3c24xx_led_platdata vr1000_led1_pdata = {
+       .name           = "led1",
+       .gpio           = S3C2410_GPB0,
+       .def_trigger    = "",
+};
+
+static struct s3c24xx_led_platdata vr1000_led2_pdata = {
+       .name           = "led2",
+       .gpio           = S3C2410_GPB1,
+       .def_trigger    = "",
+};
+
+static struct s3c24xx_led_platdata vr1000_led3_pdata = {
+       .name           = "led3",
+       .gpio           = S3C2410_GPB2,
+       .def_trigger    = "",
+};
+
+static struct platform_device vr1000_led1 = {
+       .name           = "s3c24xx_led",
+       .id             = 1,
+       .dev            = {
+               .platform_data  = &vr1000_led1_pdata,
+       },
+};
+
+static struct platform_device vr1000_led2 = {
+       .name           = "s3c24xx_led",
+       .id             = 2,
+       .dev            = {
+               .platform_data  = &vr1000_led2_pdata,
+       },
+};
+
+static struct platform_device vr1000_led3 = {
+       .name           = "s3c24xx_led",
+       .id             = 1,
+       .dev            = {
+               .platform_data  = &vr1000_led3_pdata,
+       },
+};
+
 /* devices for this board */
 
 static struct platform_device *vr1000_devices[] __initdata = {
@@ -325,7 +370,10 @@ static struct platform_device *vr1000_devices[] __initdata = {
        &serial_device,
        &vr1000_nor,
        &vr1000_dm9k0,
-       &vr1000_dm9k1
+       &vr1000_dm9k1,
+       &vr1000_led1,
+       &vr1000_led2,
+       &vr1000_led3,
 };
 
 static struct clk *vr1000_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/pm-h1940.S b/arch/arm/mach-s3c2410/pm-h1940.S
new file mode 100644 (file)
index 0000000..7d66de7
--- /dev/null
@@ -0,0 +1,33 @@
+/* linux/arch/arm/mach-s3c2410/pm-h1940.S
+ *
+ * Copyright (c) 2006 Ben Dooks <ben-linux@fluff.org>
+ *
+ * H1940 Suspend to RAM
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+
+       .text
+       .global h1940_pm_return
+
+h1940_pm_return:
+       mov     r0, #S3C2410_PA_GPIO
+       ldr     pc, [ r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO ]
index e51d766..77c6814 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/h1940.h>
 
 #include "cpu.h"
 #include "pm.h"
@@ -52,6 +53,35 @@ static void s3c2410_pm_prepare(void)
        DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
        DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
+       if (machine_is_h1940()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
+
+               /* generate check for the bootloader to check on resume */
+
+               for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+                       calc += __raw_readl(base+ptr);
+
+               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
+       }
+
+       /* the RX3715 uses similar code and the same H1940 and the
+        * same offsets for resume and checksum pointers */
+
+       if (machine_is_rx3715()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
+
+               /* generate check for the bootloader to check on resume */
+
+               for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+                       calc += __raw_readl(base+ptr);
+
+               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
+       }
+
        if ( machine_is_aml_m5900() )
                s3c2410_gpio_setpin(S3C2410_GPF2, 1);
 
index 7f74154..ffcc30b 100644 (file)
@@ -98,7 +98,7 @@ s3c2412_irq_unmask(unsigned int irqno)
        __raw_writel(mask & ~bitval, S3C2410_INTMSK);
 }
 
-static struct irqchip s3c2412_irq_eint0t4 = {
+static struct irq_chip s3c2412_irq_eint0t4 = {
        .ack       = s3c2412_irq_ack,
        .mask      = s3c2412_irq_mask,
        .unmask    = s3c2412_irq_unmask,
@@ -112,7 +112,7 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
 
        for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
                set_irq_chip(irqno, &s3c2412_irq_eint0t4);
-               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_handler(irqno, handle_edge_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 39db075..1ba19b2 100644 (file)
 /* WDT/AC97 */
 
 static void s3c_irq_demux_wdtac97(unsigned int irq,
-                                 struct irqdesc *desc)
+                                 struct irq_desc *desc)
 {
        unsigned int subsrc, submsk;
-       struct irqdesc *mydesc;
+       struct irq_desc *mydesc;
 
        /* read the current pending interrupts, and the mask
         * for what it is available */
@@ -90,7 +90,7 @@ s3c_irq_wdtac97_ack(unsigned int irqno)
        s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
 }
 
-static struct irqchip s3c_irq_wdtac97 = {
+static struct irq_chip s3c_irq_wdtac97 = {
        .mask       = s3c_irq_wdtac97_mask,
        .unmask     = s3c_irq_wdtac97_unmask,
        .ack        = s3c_irq_wdtac97_ack,
@@ -105,12 +105,12 @@ static int s3c2440_irq_add(struct sys_device *sysdev)
        /* add new chained handler for wdt, ac7 */
 
        set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_WDT, do_level_IRQ);
+       set_irq_handler(IRQ_WDT, handle_level_irq);
        set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
 
        for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
                set_irq_chip(irqno, &s3c_irq_wdtac97);
-               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 146f210..ede9463 100644 (file)
 /* camera irq */
 
 static void s3c_irq_demux_cam(unsigned int irq,
-                             struct irqdesc *desc)
+                             struct irq_desc *desc)
 {
        unsigned int subsrc, submsk;
-       struct irqdesc *mydesc;
+       struct irq_desc *mydesc;
 
        /* read the current pending interrupts, and the mask
         * for what it is available */
@@ -89,7 +89,7 @@ s3c_irq_cam_ack(unsigned int irqno)
        s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
 }
 
-static struct irqchip s3c_irq_cam = {
+static struct irq_chip s3c_irq_cam = {
        .mask       = s3c_irq_cam_mask,
        .unmask     = s3c_irq_cam_unmask,
        .ack        = s3c_irq_cam_ack,
@@ -100,18 +100,18 @@ static int s3c244x_irq_add(struct sys_device *sysdev)
        unsigned int irqno;
 
        set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_NFCON, do_level_IRQ);
+       set_irq_handler(IRQ_NFCON, handle_level_irq);
        set_irq_flags(IRQ_NFCON, IRQF_VALID);
 
        /* add chained handler for camera */
 
        set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_CAM, do_level_IRQ);
+       set_irq_handler(IRQ_CAM, handle_level_irq);
        set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
 
        for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
                set_irq_chip(irqno, &s3c_irq_cam);
-               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_handler(irqno, handle_level_irq);
                set_irq_flags(irqno, IRQF_VALID);
        }
 
index 4575f31..e510295 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/div64.h>
+#include <asm/cnt32_to_63.h>
 #include <asm/hardware.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -118,15 +119,21 @@ EXPORT_SYMBOL(cpufreq_get);
 
 /*
  * This is the SA11x0 sched_clock implementation.  This has
- * a resolution of 271ns, and a maximum value of 1165s.
+ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ *
  *  ( * 1E9 / 3686400 => * 78125 / 288)
  */
 unsigned long long sched_clock(void)
 {
-       unsigned long long v;
+       unsigned long long v = cnt32_to_63(OSCR);
 
-       v = (unsigned long long)OSCR * 78125;
-       do_div(v, 288);
+       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
+       v *= 78125<<1;
+       do_div(v, 288<<1);
 
        return v;
 }
index fa6dc71..b034ad6 100644 (file)
@@ -702,7 +702,7 @@ static u32 gpio_irq_mask[] = {
        GPIO2_SD_CON_SLT,
 };
 
-static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc)
+static void h3800_IRQ_demux(unsigned int irq, struct irq_desc *desc)
 {
        int i;
 
@@ -719,14 +719,14 @@ static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc)
                if (0) printk("%s KPIO 0x%08X\n", __FUNCTION__, irq);
                for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
                        if (irq & kpio_irq_mask[j])
-                               do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j);
+                               handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j);
 
                /* GPIO2 */
                irq = H3800_ASIC2_GPIINTFLAG;
                if (0) printk("%s GPIO 0x%08X\n", __FUNCTION__, irq);
                for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
                        if (irq & gpio_irq_mask[j])
-                               do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j);
+                               handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j);
        }
 
        if (i >= MAX_ASIC_ISR_LOOPS)
index f4c6322..5642aec 100644 (file)
@@ -110,7 +110,7 @@ static struct irq_chip sa1100_low_gpio_chip = {
  * and call the handler.
  */
 static void
-sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc)
+sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int mask;
 
@@ -327,19 +327,19 @@ void __init sa1100_init_irq(void)
 
        for (irq = 0; irq <= 10; irq++) {
                set_irq_chip(irq, &sa1100_low_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        for (irq = 12; irq <= 31; irq++) {
                set_irq_chip(irq, &sa1100_normal_chip);
-               set_irq_handler(irq, do_level_IRQ);
+               set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
        }
 
        for (irq = 32; irq <= 48; irq++) {
                set_irq_chip(irq, &sa1100_high_gpio_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index 354d5e9..075d4d1 100644 (file)
  * is rather unfortunate.
  */
 static void
-neponset_irq_handler(unsigned int irq, struct irqdesc *desc)
+neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int irr;
 
        while (1) {
-               struct irqdesc *d;
+               struct irq_desc *d;
 
                /*
                 * Acknowledge the parent IRQ.
@@ -168,9 +168,9 @@ static int neponset_probe(struct platform_device *dev)
         * Setup other Neponset IRQs.  SA1111 will be done by the
         * generic SA1111 code.
         */
-       set_irq_handler(IRQ_NEPONSET_SMC9196, do_simple_IRQ);
+       set_irq_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
        set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
-       set_irq_handler(IRQ_NEPONSET_USAR, do_simple_IRQ);
+       set_irq_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
        set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
 
        /*
index 4284bd6..29c89f9 100644 (file)
@@ -118,6 +118,7 @@ static struct irqaction sa1100_timer_irq = {
 static void __init sa1100_timer_init(void)
 {
        struct timespec tv;
+       unsigned long flags;
 
        set_rtc = sa1100_set_rtc;
 
@@ -126,12 +127,12 @@ static void __init sa1100_timer_init(void)
        do_settimeofday(&tv);
 
        OIER = 0;               /* disable any timer interrupts */
-       OSCR = LATCH*2;         /* push OSCR out of the way */
-       OSMR0 = LATCH;          /* set initial match */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &sa1100_timer_irq);
+       local_irq_save(flags);
        OIER = OIER_E0;         /* enable match on timer 0 to cause interrupts */
-       OSCR = 0;               /* initialize free-running timer */
+       OSMR0 = OSCR + LATCH;   /* set initial match */
+       local_irq_restore(flags);
 }
 
 #ifdef CONFIG_NO_IDLE_HZ
index 297ecf1..00a6c14 100644 (file)
@@ -82,7 +82,7 @@ void __init shark_init_irq(void)
 
        for (irq = 0; irq < NR_IRQS; irq++) {
                set_irq_chip(irq, &fb_chip);
-               set_irq_handler(irq, do_edge_IRQ);
+               set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
index 3b85761..5719694 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 
+#include <asm/cnt32_to_63.h>
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -77,7 +78,7 @@ static struct irq_chip sic_chip = {
 };
 
 static void
-sic_handle_irq(unsigned int irq, struct irqdesc *desc)
+sic_handle_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
 
@@ -123,7 +124,7 @@ void __init versatile_init_irq(void)
        for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
                if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
                        set_irq_chip(i, &sic_chip);
-                       set_irq_handler(i, do_level_IRQ);
+                       set_irq_handler(i, handle_level_irq);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }
        }
@@ -228,14 +229,19 @@ void __init versatile_map_io(void)
 
 /*
  * This is the Versatile sched_clock implementation.  This has
- * a resolution of 41.7ns, and a maximum value of about 179s.
+ * a resolution of 41.7ns, and a maximum value of about 35583 days.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 89 seconds between successive
+ * calls to this function.
  */
 unsigned long long sched_clock(void)
 {
-       unsigned long long v;
+       unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER));
 
-       v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125;
-       do_div(v, 3);
+       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
+       v *= 125<<1;
+       do_div(v, 3<<1);
 
        return v;
 }
index 503725b..be439bb 100644 (file)
@@ -81,22 +81,18 @@ static struct amba_device *amba_devs[] __initdata = {
        &mmc1_device,
 };
 
-static int __init versatile_pb_init(void)
+static void __init versatile_pb_init(void)
 {
        int i;
 
-       if (machine_is_versatile_pb()) {
-               for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-                       struct amba_device *d = amba_devs[i];
-                       amba_device_register(d, &iomem_resource);
-               }
-       }
+       versatile_init();
 
-       return 0;
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               amba_device_register(d, &iomem_resource);
+       }
 }
 
-arch_initcall(versatile_pb_init);
-
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
        .phys_io        = 0x101f1000,
@@ -105,5 +101,5 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
        .map_io         = versatile_map_io,
        .init_irq       = versatile_init_irq,
        .timer          = &versatile_timer,
-       .init_machine   = versatile_init,
+       .init_machine   = versatile_pb_init,
 MACHINE_END
index b09a19f..aade2f7 100644 (file)
@@ -333,7 +333,7 @@ config CPU_XSCALE
 # XScale Core Version 3
 config CPU_XSC3
        bool
-       depends on ARCH_IXP23XX
+       depends on ARCH_IXP23XX || ARCH_IOP13XX
        default y
        select CPU_32v5
        select CPU_ABRT_EV5T
@@ -580,7 +580,7 @@ config CPU_CACHE_ROUND_ROBIN
 
 config CPU_BPREDICT_DISABLE
        bool "Disable branch prediction"
-       depends on CPU_ARM1020 || CPU_V6
+       depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3
        help
          Say Y here to disable branch prediction.  If unsure, say N.
 
index 5e658a8..9fd6d2e 100644 (file)
@@ -230,7 +230,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        /*
index bb2bc9a..a44e309 100644 (file)
@@ -1,4 +1,7 @@
 /* the upper-most page table pointer */
+
+#ifdef CONFIG_MMU
+
 extern pmd_t *top_pmd;
 
 #define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
@@ -13,6 +16,8 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
        return pmd_off(pgd_offset_k(virt), virt);
 }
 
+#endif
+
 struct map_desc;
 struct meminfo;
 struct pglist_data;
index f866bf6..b7f194a 100644 (file)
@@ -265,7 +265,7 @@ static void __init build_mem_type_table(void)
        if (arch_is_coherent()) {
                if (cpu_is_xsc3()) {
                        mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-                       mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+                       mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
                }
        }
 
@@ -619,6 +619,13 @@ void __init reserve_node_zero(pg_data_t *pgdat)
        if (machine_is_p720t())
                res_size = 0x00014000;
 
+       /* H1940 and RX3715 need to reserve this for suspend */
+
+       if (machine_is_h1940() || machine_is_rx3715()) {
+               reserve_bootmem_node(pgdat, 0x30003000, 0x1000);
+               reserve_bootmem_node(pgdat, 0x30081000, 0x1000);
+       }
+
 #ifdef CONFIG_SA1111
        /*
         * Because of the SA1111 DMA bug, we want to preserve our
index d0e6642..05818fc 100644 (file)
@@ -6,10 +6,12 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/bootmem.h>
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 #include <asm/page.h>
+#include <asm/mach/arch.h>
 
 #include "mm.h"
 
@@ -76,7 +78,7 @@ void __iomem *__ioremap(unsigned long phys_addr, size_t size,
 }
 EXPORT_SYMBOL(__ioremap);
 
-void __iounmap(void __iomem *addr)
+void __iounmap(volatile void __iomem *addr)
 {
 }
 EXPORT_SYMBOL(__iounmap);
index 1d8316f..289b8e6 100644 (file)
@@ -29,9 +29,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 #include "proc-macros.S"
index 89b1d6d..bed9db6 100644 (file)
@@ -29,9 +29,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 #include "proc-macros.S"
index a089528..d2a7c1b 100644 (file)
@@ -18,9 +18,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 #include "proc-macros.S"
index d6d84d9..3247ce5 100644 (file)
@@ -18,9 +18,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 #include "proc-macros.S"
index 0432e48..ce4f9ee 100644 (file)
@@ -15,9 +15,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 ENTRY(cpu_arm6_dcache_clean_area)
index c2f0705..c04c194 100644 (file)
@@ -36,9 +36,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 #include "proc-macros.S"
index 4071381..7069f49 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
        .text
index 22d7e31..d091c25 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
        .text
index 4adb46b..65cbb28 100644 (file)
@@ -28,9 +28,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include "proc-macros.S"
index 571f082..52761b7 100644 (file)
@@ -29,9 +29,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include "proc-macros.S"
index 8d9a9f9..5b74339 100644 (file)
@@ -52,9 +52,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include "proc-macros.S"
index 44a7a65..8628ed2 100644 (file)
@@ -28,9 +28,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include "proc-macros.S"
index 2397f4b..786c593 100644 (file)
@@ -11,9 +11,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 /* ARM940T has a 4KB DCache comprising 256 lines of 4 words */
index e186175..a60c142 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
 /*
index 918ebf6..4848eea 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-#include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
        .text
index c878064..cd7d865 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
-#include <asm/procinfo.h>
+#include <asm/elf.h>
 #include <asm/hardware.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
index b23b66a..b776653 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
-#include <asm/procinfo.h>
+#include <asm/elf.h>
 #include <asm/hardware.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
index 6f72549..b440c8a 100644 (file)
@@ -13,8 +13,8 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
+#include <asm/elf.h>
 #include <asm/hardware/arm_scu.h>
-#include <asm/procinfo.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 
index 4ace2d8..1ef564d 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/procinfo.h>
+#include <asm/elf.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
  */
 #define L2_CACHE_ENABLE        1
 
-/*
- * Enable the Branch Target Buffer (can cause crashes, see erratum #42.)
- */
-#define BTB_ENABLE     0
-
 /*
  * This macro is used to wait for a CP15 write and is needed
  * when we have to ensure that the last operation to the co-pro
@@ -371,8 +366,10 @@ ENTRY(cpu_xsc3_switch_mm)
 ENTRY(cpu_xsc3_set_pte)
        str     r1, [r0], #-2048                @ linux version
 
-       bic     r2, r1, #0xdf0                  @ Keep C, B, coherency bits
+       bic     r2, r1, #0xff0                  @ Keep C, B bits
        orr     r2, r2, #PTE_TYPE_EXT           @ extended page
+       tst     r1, #L_PTE_SHARED               @ Shared?
+       orrne   r2, r2, #0x200
 
        eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
 
@@ -432,9 +429,7 @@ __xsc3_setup:
        mrc     p15, 0, r0, c1, c0, 0           @ get control register
        bic     r0, r0, r5                      @ .... .... .... ..A.
        orr     r0, r0, r6                      @ .... .... .... .C.M
-#if BTB_ENABLE
        orr     r0, r0, #0x00000800             @ ..VI Z..S .... ....
-#endif
 #if L2_CACHE_ENABLE
        orr     r0, r0, #0x04000000             @ L2 enable
 #endif
index 2749c1f..cc1004b 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/procinfo.h>
+#include <asm/elf.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/page.h>
@@ -491,12 +491,7 @@ __xscale_setup:
        mcr     p15, 0, ip, c7, c7, 0           @ invalidate I, D caches & BTB
        mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
        mcr     p15, 0, ip, c8, c7, 0           @ invalidate I, D TLBs
-#ifdef CONFIG_IWMMXT
-       mov     r0, #0                          @ initially disallow access to CP0/CP1
-#else
-       mov     r0, #1                          @ Allow access to CP0
-#endif
-       orr     r0, r0, #1 << 6                 @ cp6 for IOP3xx and Bulverde
+       mov     r0, #1 << 6                     @ cp6 for IOP3xx and Bulverde
        orr     r0, r0, #1 << 13                @ Its undefined whether this
        mcr     p15, 0, r0, c15, c1, 0          @ affects USR or SVC modes
 
@@ -909,7 +904,7 @@ __pxa270_proc_info:
        b       __xscale_setup
        .long   cpu_arch_name
        .long   cpu_elf_name
-       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_IWMMXT
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
        .long   cpu_pxa270_name
        .long   xscale_processor_functions
        .long   v4wbi_tlb_fns
index 8162eed..4f2fd55 100644 (file)
@@ -410,7 +410,7 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
                trigger & __IRQT_RISEDGE);
        MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
                trigger & __IRQT_FALEDGE);
-       /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
+       /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level
         * triggering requested. */
 }
 
@@ -783,7 +783,7 @@ void omap_free_gpio(int gpio)
  * line's interrupt handler has been run, we may miss some nested
  * interrupts.
  */
-static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc)
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        void __iomem *isr_reg = NULL;
        u32 isr;
@@ -853,7 +853,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc)
 
                gpio_irq = bank->virtual_irq_start;
                for (; isr != 0; isr >>= 1, gpio_irq++) {
-                       struct irqdesc *d;
+                       struct irq_desc *d;
                        int irq_mask;
                        if (!(isr & 1))
                                continue;
@@ -1092,7 +1092,7 @@ static int __init _omap_gpio_init(void)
                                set_irq_chip(j, &mpuio_irq_chip);
                        else
                                set_irq_chip(j, &gpio_irq_chip);
-                       set_irq_handler(j, do_simple_IRQ);
+                       set_irq_handler(j, handle_simple_irq);
                        set_irq_flags(j, IRQF_VALID);
                }
                set_irq_chained_handler(bank->irq, gpio_irq_handler);
index 579c69a..8bcb838 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Oct 16 21:13:36 2006
+# Last update: Thu Dec 7 17:19:20 2006
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -79,7 +79,7 @@ psionw                        ARCH_PSIONW             PSIONW                  60
 aln                    SA1100_ALN              ALN                     61
 epxa                   ARCH_CAMELOT            CAMELOT                 62
 gds2200                        SA1100_GDS2200          GDS2200                 63
-psion_series7          SA1100_PSION_SERIES7    PSION_SERIES7           64
+netbook                        SA1100_PSION_SERIES7    PSION_SERIES7           64
 xfile                  SA1100_XFILE            XFILE                   65
 accelent_ep9312                ARCH_ACCELENT_EP9312    ACCELENT_EP9312         66
 ic200                  ARCH_IC200              IC200                   67
@@ -810,9 +810,9 @@ sb3010                      MACH_SB3010             SB3010                  795
 rm9200                 MACH_RM9200             RM9200                  796
 dma03                  MACH_DMA03              DMA03                   797
 road_s101              MACH_ROAD_S101          ROAD_S101               798
-iq_nextgen_a           MACH_IQ_NEXTGEN_A       IQ_NEXTGEN_A            799
+iq81340sc              MACH_IQ81340SC          IQ81340SC               799
 iq_nextgen_b           MACH_IQ_NEXTGEN_B       IQ_NEXTGEN_B            800
-iq_nextgen_c           MACH_IQ_NEXTGEN_C       IQ_NEXTGEN_C            801
+iq81340mc              MACH_IQ81340MC          IQ81340MC               801
 iq_nextgen_d           MACH_IQ_NEXTGEN_D       IQ_NEXTGEN_D            802
 iq_nextgen_e           MACH_IQ_NEXTGEN_E       IQ_NEXTGEN_E            803
 mallow_at91            MACH_MALLOW_AT91        MALLOW_AT91             804
@@ -1165,9 +1165,57 @@ pnx4010                  MACH_PNX4010            PNX4010                 1151
 oxnas                  MACH_OXNAS              OXNAS                   1152
 fiori                  MACH_FIORI              FIORI                   1153
 ml1200                 MACH_ML1200             ML1200                  1154
-cactus                 MACH_CACTUS             CACTUS                  1155
+pecos                  MACH_PECOS              PECOS                   1155
 nb2xxx                 MACH_NB2XXX             NB2XXX                  1156
 hw6900                 MACH_HW6900             HW6900                  1157
 cdcs_quoll             MACH_CDCS_QUOLL         CDCS_QUOLL              1158
 quicksilver            MACH_QUICKSILVER        QUICKSILVER             1159
 uplat926               MACH_UPLAT926           UPLAT926                1160
+dep2410_dep2410                MACH_DEP2410_THOMAS     DEP2410_THOMAS          1161
+dtk2410                        MACH_DTK2410            DTK2410                 1162
+chili                  MACH_CHILI              CHILI                   1163
+demeter                        MACH_DEMETER            DEMETER                 1164
+dionysus               MACH_DIONYSUS           DIONYSUS                1165
+as352x                 MACH_AS352X             AS352X                  1166
+service                        MACH_SERVICE            SERVICE                 1167
+cs_e9301               MACH_CS_E9301           CS_E9301                1168
+micro9m                        MACH_MICRO9M            MICRO9M                 1169
+ia_mospck              MACH_IA_MOSPCK          IA_MOSPCK               1170
+ql201b                 MACH_QL201B             QL201B                  1171
+bbm                    MACH_BBM                BBM                     1174
+exxx                   MACH_EXXX               EXXX                    1175
+wma11b                 MACH_WMA11B             WMA11B                  1176
+pelco_atlas            MACH_PELCO_ATLAS        PELCO_ATLAS             1177
+g500                   MACH_G500               G500                    1178
+bug                    MACH_BUG                BUG                     1179
+mx33ads                        MACH_MX33ADS            MX33ADS                 1180
+chub                   MACH_CHUB               CHUB                    1181
+gta01                  MACH_GTA01              GTA01                   1182
+w90n740                        MACH_W90N740            W90N740                 1183
+medallion_sa2410       MACH_MEDALLION_SA2410   MEDALLION_SA2410        1184
+ia_cpu_9200_2          MACH_IA_CPU_9200_2      IA_CPU_9200_2           1185
+dimmrm9200             MACH_DIMMRM9200         DIMMRM9200              1186
+pm9261                 MACH_PM9261             PM9261                  1187
+mx21                   MACH_MX21               MX21                    1188
+ml7304                 MACH_ML7304             ML7304                  1189
+ucp250                 MACH_UCP250             UCP250                  1190
+intboard               MACH_INTBOARD           INTBOARD                1191
+gulfstream             MACH_GULFSTREAM         GULFSTREAM              1192
+labquest               MACH_LABQUEST           LABQUEST                1193
+vcmx313                        MACH_VCMX313            VCMX313                 1194
+urg200                 MACH_URG200             URG200                  1195
+cpux255lcdnet          MACH_CPUX255LCDNET      CPUX255LCDNET           1196
+netdcu9                        MACH_NETDCU9            NETDCU9                 1197
+netdcu10               MACH_NETDCU10           NETDCU10                1198
+dspg_dga               MACH_DSPG_DGA           DSPG_DGA                1199
+dspg_dvw               MACH_DSPG_DVW           DSPG_DVW                1200
+solos                  MACH_SOLOS              SOLOS                   1201
+at91sam9263ek          MACH_AT91SAM9263EK      AT91SAM9263EK           1202
+osstbox                        MACH_OSSTBOX            OSSTBOX                 1203
+kbat9261               MACH_KBAT9261           KBAT9261                1204
+ct1100                 MACH_CT1100             CT1100                  1205
+akcppxa                        MACH_AKCPPXA            AKCPPXA                 1206
+zevio_1020             MACH_ZEVIO_1020         ZEVIO_1020              1207
+hitrack                        MACH_HITRACK            HITRACK                 1208
+syme1                  MACH_SYME1              SYME1                   1209
+syhl1                  MACH_SYHL1              SYHL1                   1210
index c14fe91..74eba8b 100644 (file)
@@ -41,6 +41,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_HWEIGHT
        bool
        default y
index 047d0a4..43dd41b 100644 (file)
@@ -620,12 +620,10 @@ ecard_probe(int slot, card_type_t type)
        struct ex_ecid cid;
        int i, rc = -ENOMEM;
 
-       ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
+       ec = kzalloc(sizeof(ecard_t), GFP_KERNEL);
        if (!ec)
                goto nomem;
 
-       memset(ec, 0, sizeof(ecard_t));
-
        ec->slot_no     = slot;
        ec->type        = type;
        ec->irq         = NO_IRQ;
index a1f6d8a..93c0cee 100644 (file)
@@ -215,7 +215,7 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        down_read(&mm->mmap_sem);
index 34def63..f290158 100644 (file)
@@ -24,7 +24,7 @@
 
 #define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
 
-kmem_cache_t *pte_cache, *pgd_cache;
+struct kmem_cache *pte_cache, *pgd_cache;
 int page_nr;
 
 /*
@@ -162,12 +162,12 @@ void __init create_memmap_holes(struct meminfo *mi)
 {
 }
 
-static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
+static void pte_cache_ctor(void *pte, struct kmem_cache *cache, unsigned long flags)
 {
        memzero(pte, sizeof(pte_t) * PTRS_PER_PTE);
 }
 
-static void pgd_cache_ctor(void *pgd, kmem_cache_t *cache, unsigned long flags)
+static void pgd_cache_ctor(void *pgd, struct kmem_cache *cache, unsigned long flags)
 {
        memzero(pgd + MEMC_TABLE_SIZE, USER_PTRS_PER_PGD * sizeof(pgd_t));
 }
index 5f1694e..bb059a4 100644 (file)
@@ -45,6 +45,14 @@ config GENERIC_TIME
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_BUST_SPINLOCK
        bool
 
index cced73c..32b361f 100644 (file)
@@ -7,20 +7,83 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
 
+#include <asm/io.h>
+#include <asm/setup.h>
 #include <asm/arch/board.h>
 #include <asm/arch/init.h>
 
-struct eth_platform_data __initdata eth0_data = {
-       .valid          = 1,
-       .mii_phy_addr   = 0x10,
-       .is_rmii        = 0,
-       .hw_addr        = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+struct eth_addr {
+       u8 addr[6];
 };
 
+static struct eth_addr __initdata hw_addr[2];
+
+static struct eth_platform_data __initdata eth_data[2];
 extern struct lcdc_platform_data atstk1000_fb0_data;
 
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+       int i;
+
+       i = tag->u.ethernet.mac_index;
+       if (i < ARRAY_SIZE(hw_addr))
+               memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+                      sizeof(hw_addr[i].addr));
+
+       return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+static void __init set_hw_addr(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       const u8 *addr;
+       void __iomem *regs;
+       struct clk *pclk;
+
+       if (!res)
+               return;
+       if (pdev->id >= ARRAY_SIZE(hw_addr))
+               return;
+
+       addr = hw_addr[pdev->id].addr;
+       if (!is_valid_ether_addr(addr))
+               return;
+
+       /*
+        * Since this is board-specific code, we'll cheat and use the
+        * physical address directly as we happen to know that it's
+        * the same as the virtual address.
+        */
+       regs = (void __iomem __force *)res->start;
+       pclk = clk_get(&pdev->dev, "pclk");
+       if (!pclk)
+               return;
+
+       clk_enable(pclk);
+       __raw_writel((addr[3] << 24) | (addr[2] << 16)
+                    | (addr[1] << 8) | addr[0], regs + 0x98);
+       __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
+       clk_disable(pclk);
+       clk_put(pclk);
+}
+
 void __init setup_board(void)
 {
        at32_map_usart(1, 0);   /* /dev/ttyS0 */
@@ -38,7 +101,8 @@ static int __init atstk1002_init(void)
        at32_add_device_usart(1);
        at32_add_device_usart(2);
 
-       at32_add_device_eth(0, &eth0_data);
+       set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+
        at32_add_device_spi(0);
        at32_add_device_lcdc(0, &atstk1000_fb0_data);
 
index 372e3f8..7c4c761 100644 (file)
@@ -7,12 +7,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
 
 #include <asm/checksum.h>
 #include <asm/uaccess.h>
-#include <asm/delay.h>
 
 /*
  * GCC functions
index ca41fc1..d0abbca 100644 (file)
@@ -154,6 +154,7 @@ ss_probe:
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
index 317dc50..0b43259 100644 (file)
@@ -38,6 +38,13 @@ void cpu_idle(void)
 
 void machine_halt(void)
 {
+       /*
+        * Enter Stop mode. The 32 kHz oscillator will keep running so
+        * the RTC will keep the time properly and the system will
+        * boot quickly.
+        */
+       asm volatile("sleep 3\n\t"
+                    "sub pc, -2");
 }
 
 void machine_power_off(void)
index ea2d1ff..a342116 100644 (file)
@@ -229,30 +229,6 @@ static int __init parse_tag_rsvd_mem(struct tag *tag)
 }
 __tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
 
-static int __init parse_tag_ethernet(struct tag *tag)
-{
-#if 0
-       const struct platform_device *pdev;
-
-       /*
-        * We really need a bus type that supports "classes"...this
-        * will do for now (until we must handle other kinds of
-        * ethernet controllers)
-        */
-       pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
-       if (pdev && pdev->dev.platform_data) {
-               struct eth_platform_data *data = pdev->dev.platform_data;
-
-               data->valid = 1;
-               data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
-               memcpy(data->hw_addr, tag->u.ethernet.hw_address,
-                      sizeof(data->hw_addr));
-       }
-#endif
-       return 0;
-}
-__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
-
 /*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
index 3309665..0ec1485 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
index 462c830..b3bc0b5 100644 (file)
@@ -12,9 +12,9 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/param.h>
 #include <linux/types.h>
 
-#include <asm/delay.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
index 7ff6ad8..48f4ef3 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 
+#include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
 #include <asm/arch/sm.h>
@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = {         \
        .num_resources  = ARRAY_SIZE(_name##_id##_resource),    \
 }
 
+#define select_peripheral(pin, periph, flags)                  \
+       at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
+
 #define DEV_CLK(_name, devname, bus, _index)                   \
 static struct clk devname##_##_name = {                                \
        .name           = #_name,                               \
@@ -67,18 +71,6 @@ static struct clk devname##_##_name = {                              \
        .index          = _index,                               \
 }
 
-enum {
-       PIOA,
-       PIOB,
-       PIOC,
-       PIOD,
-};
-
-enum {
-       FUNC_A,
-       FUNC_B,
-};
-
 unsigned long at32ap7000_osc_rates[3] = {
        [0] = 32768,
        /* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
 
 static inline void configure_usart0_pins(void)
 {
-       portmux_set_func(PIOA,  8, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOA,  9, FUNC_B);     /* TXD  */
+       select_peripheral(PA(8),  PERIPH_B, 0); /* RXD  */
+       select_peripheral(PA(9),  PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart1_pins(void)
 {
-       portmux_set_func(PIOA, 17, FUNC_A);     /* RXD  */
-       portmux_set_func(PIOA, 18, FUNC_A);     /* TXD  */
+       select_peripheral(PA(17), PERIPH_A, 0); /* RXD  */
+       select_peripheral(PA(18), PERIPH_A, 0); /* TXD  */
 }
 
 static inline void configure_usart2_pins(void)
 {
-       portmux_set_func(PIOB, 26, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 27, FUNC_B);     /* TXD  */
+       select_peripheral(PB(26), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(27), PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart3_pins(void)
 {
-       portmux_set_func(PIOB, 18, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 17, FUNC_B);     /* TXD  */
+       select_peripheral(PB(18), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(17), PERIPH_B, 0); /* TXD  */
 }
 
 static struct platform_device *at32_usarts[4];
@@ -654,6 +646,15 @@ DEFINE_DEV_DATA(macb, 0);
 DEV_CLK(hclk, macb0, hsb, 8);
 DEV_CLK(pclk, macb0, pbb, 6);
 
+static struct eth_platform_data macb1_data;
+static struct resource macb1_resource[] = {
+       PBMEM(0xfff01c00),
+       IRQ(26),
+};
+DEFINE_DEV_DATA(macb, 1);
+DEV_CLK(hclk, macb1, hsb, 9);
+DEV_CLK(pclk, macb1, pbb, 7);
+
 struct platform_device *__init
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
 {
@@ -663,27 +664,54 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
        case 0:
                pdev = &macb0_device;
 
-               portmux_set_func(PIOC,  3, FUNC_A);     /* TXD0 */
-               portmux_set_func(PIOC,  4, FUNC_A);     /* TXD1 */
-               portmux_set_func(PIOC,  7, FUNC_A);     /* TXEN */
-               portmux_set_func(PIOC,  8, FUNC_A);     /* TXCK */
-               portmux_set_func(PIOC,  9, FUNC_A);     /* RXD0 */
-               portmux_set_func(PIOC, 10, FUNC_A);     /* RXD1 */
-               portmux_set_func(PIOC, 13, FUNC_A);     /* RXER */
-               portmux_set_func(PIOC, 15, FUNC_A);     /* RXDV */
-               portmux_set_func(PIOC, 16, FUNC_A);     /* MDC  */
-               portmux_set_func(PIOC, 17, FUNC_A);     /* MDIO */
+               select_peripheral(PC(3),  PERIPH_A, 0); /* TXD0 */
+               select_peripheral(PC(4),  PERIPH_A, 0); /* TXD1 */
+               select_peripheral(PC(7),  PERIPH_A, 0); /* TXEN */
+               select_peripheral(PC(8),  PERIPH_A, 0); /* TXCK */
+               select_peripheral(PC(9),  PERIPH_A, 0); /* RXD0 */
+               select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
+               select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
+               select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
+               select_peripheral(PC(16), PERIPH_A, 0); /* MDC  */
+               select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
+
+               if (!data->is_rmii) {
+                       select_peripheral(PC(0),  PERIPH_A, 0); /* COL  */
+                       select_peripheral(PC(1),  PERIPH_A, 0); /* CRS  */
+                       select_peripheral(PC(2),  PERIPH_A, 0); /* TXER */
+                       select_peripheral(PC(5),  PERIPH_A, 0); /* TXD2 */
+                       select_peripheral(PC(6),  PERIPH_A, 0); /* TXD3 */
+                       select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
+                       select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
+                       select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
+                       select_peripheral(PC(18), PERIPH_A, 0); /* SPD  */
+               }
+               break;
+
+       case 1:
+               pdev = &macb1_device;
+
+               select_peripheral(PD(13), PERIPH_B, 0);         /* TXD0 */
+               select_peripheral(PD(14), PERIPH_B, 0);         /* TXD1 */
+               select_peripheral(PD(11), PERIPH_B, 0);         /* TXEN */
+               select_peripheral(PD(12), PERIPH_B, 0);         /* TXCK */
+               select_peripheral(PD(10), PERIPH_B, 0);         /* RXD0 */
+               select_peripheral(PD(6),  PERIPH_B, 0);         /* RXD1 */
+               select_peripheral(PD(5),  PERIPH_B, 0);         /* RXER */
+               select_peripheral(PD(4),  PERIPH_B, 0);         /* RXDV */
+               select_peripheral(PD(3),  PERIPH_B, 0);         /* MDC  */
+               select_peripheral(PD(2),  PERIPH_B, 0);         /* MDIO */
 
                if (!data->is_rmii) {
-                       portmux_set_func(PIOC,  0, FUNC_A);     /* COL  */
-                       portmux_set_func(PIOC,  1, FUNC_A);     /* CRS  */
-                       portmux_set_func(PIOC,  2, FUNC_A);     /* TXER */
-                       portmux_set_func(PIOC,  5, FUNC_A);     /* TXD2 */
-                       portmux_set_func(PIOC,  6, FUNC_A);     /* TXD3 */
-                       portmux_set_func(PIOC, 11, FUNC_A);     /* RXD2 */
-                       portmux_set_func(PIOC, 12, FUNC_A);     /* RXD3 */
-                       portmux_set_func(PIOC, 14, FUNC_A);     /* RXCK */
-                       portmux_set_func(PIOC, 18, FUNC_A);     /* SPD  */
+                       select_peripheral(PC(19), PERIPH_B, 0); /* COL  */
+                       select_peripheral(PC(23), PERIPH_B, 0); /* CRS  */
+                       select_peripheral(PC(26), PERIPH_B, 0); /* TXER */
+                       select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */
+                       select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */
+                       select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */
+                       select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */
+                       select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */
+                       select_peripheral(PD(15), PERIPH_B, 0); /* SPD  */
                }
                break;
 
@@ -714,12 +742,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
        switch (id) {
        case 0:
                pdev = &spi0_device;
-               portmux_set_func(PIOA,  0, FUNC_A);     /* MISO  */
-               portmux_set_func(PIOA,  1, FUNC_A);     /* MOSI  */
-               portmux_set_func(PIOA,  2, FUNC_A);     /* SCK   */
-               portmux_set_func(PIOA,  3, FUNC_A);     /* NPCS0 */
-               portmux_set_func(PIOA,  4, FUNC_A);     /* NPCS1 */
-               portmux_set_func(PIOA,  5, FUNC_A);     /* NPCS2 */
+               select_peripheral(PA(0),  PERIPH_A, 0); /* MISO  */
+               select_peripheral(PA(1),  PERIPH_A, 0); /* MOSI  */
+               select_peripheral(PA(2),  PERIPH_A, 0); /* SCK   */
+               select_peripheral(PA(3),  PERIPH_A, 0); /* NPCS0 */
+               select_peripheral(PA(4),  PERIPH_A, 0); /* NPCS1 */
+               select_peripheral(PA(5),  PERIPH_A, 0); /* NPCS2 */
                break;
 
        default:
@@ -762,37 +790,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
        switch (id) {
        case 0:
                pdev = &lcdc0_device;
-               portmux_set_func(PIOC, 19, FUNC_A);     /* CC     */
-               portmux_set_func(PIOC, 20, FUNC_A);     /* HSYNC  */
-               portmux_set_func(PIOC, 21, FUNC_A);     /* PCLK   */
-               portmux_set_func(PIOC, 22, FUNC_A);     /* VSYNC  */
-               portmux_set_func(PIOC, 23, FUNC_A);     /* DVAL   */
-               portmux_set_func(PIOC, 24, FUNC_A);     /* MODE   */
-               portmux_set_func(PIOC, 25, FUNC_A);     /* PWR    */
-               portmux_set_func(PIOC, 26, FUNC_A);     /* DATA0  */
-               portmux_set_func(PIOC, 27, FUNC_A);     /* DATA1  */
-               portmux_set_func(PIOC, 28, FUNC_A);     /* DATA2  */
-               portmux_set_func(PIOC, 29, FUNC_A);     /* DATA3  */
-               portmux_set_func(PIOC, 30, FUNC_A);     /* DATA4  */
-               portmux_set_func(PIOC, 31, FUNC_A);     /* DATA5  */
-               portmux_set_func(PIOD,  0, FUNC_A);     /* DATA6  */
-               portmux_set_func(PIOD,  1, FUNC_A);     /* DATA7  */
-               portmux_set_func(PIOD,  2, FUNC_A);     /* DATA8  */
-               portmux_set_func(PIOD,  3, FUNC_A);     /* DATA9  */
-               portmux_set_func(PIOD,  4, FUNC_A);     /* DATA10 */
-               portmux_set_func(PIOD,  5, FUNC_A);     /* DATA11 */
-               portmux_set_func(PIOD,  6, FUNC_A);     /* DATA12 */
-               portmux_set_func(PIOD,  7, FUNC_A);     /* DATA13 */
-               portmux_set_func(PIOD,  8, FUNC_A);     /* DATA14 */
-               portmux_set_func(PIOD,  9, FUNC_A);     /* DATA15 */
-               portmux_set_func(PIOD, 10, FUNC_A);     /* DATA16 */
-               portmux_set_func(PIOD, 11, FUNC_A);     /* DATA17 */
-               portmux_set_func(PIOD, 12, FUNC_A);     /* DATA18 */
-               portmux_set_func(PIOD, 13, FUNC_A);     /* DATA19 */
-               portmux_set_func(PIOD, 14, FUNC_A);     /* DATA20 */
-               portmux_set_func(PIOD, 15, FUNC_A);     /* DATA21 */
-               portmux_set_func(PIOD, 16, FUNC_A);     /* DATA22 */
-               portmux_set_func(PIOD, 17, FUNC_A);     /* DATA23 */
+               select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
+               select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+               select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+               select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+               select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
+               select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
+               select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+               select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
+               select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
+               select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
+               select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
+               select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
+               select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+               select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+               select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+               select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
+               select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
+               select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
+               select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
+               select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
+               select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+               select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+               select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+               select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+               select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+               select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+               select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+               select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+               select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+               select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+               select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
 
                clk_set_parent(&lcdc0_pixclk, &pll0);
                clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
@@ -838,6 +866,8 @@ struct clk *at32_clock_list[] = {
        &atmel_usart3_usart,
        &macb0_hclk,
        &macb0_pclk,
+       &macb1_hclk,
+       &macb1_pclk,
        &spi0_mck,
        &lcdc0_hclk,
        &lcdc0_pixclk,
index 4dff1f9..b59272e 100644 (file)
@@ -49,12 +49,25 @@ static void eim_unmask_irq(unsigned int irq)
 static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
 {
        struct at32_sm *sm = get_irq_chip_data(irq);
+       struct irq_desc *desc;
        unsigned int i = irq - sm->eim_first_irq;
        u32 mode, edge, level;
        unsigned long flags;
        int ret = 0;
 
-       flow_type &= IRQ_TYPE_SENSE_MASK;
+       if (flow_type == IRQ_TYPE_NONE)
+               flow_type = IRQ_TYPE_LEVEL_LOW;
+
+       desc = &irq_desc[irq];
+       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+
+       if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
+               desc->status |= IRQ_LEVEL;
+               set_irq_handler(irq, handle_level_irq);
+       } else {
+               set_irq_handler(irq, handle_edge_irq);
+       }
 
        spin_lock_irqsave(&sm->lock, flags);
 
@@ -148,10 +161,15 @@ static int __init eim_init(void)
        pattern = sm_readl(sm, EIM_MODE);
        nr_irqs = fls(pattern);
 
+       /* Trigger on falling edge unless overridden by driver */
+       sm_writel(sm, EIM_MODE, 0UL);
+       sm_writel(sm, EIM_EDGE, 0UL);
+
        sm->eim_chip = &eim_chip;
 
        for (i = 0; i < nr_irqs; i++) {
-               set_irq_chip(sm->eim_first_irq + i, &eim_chip);
+               set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
+                                        handle_edge_irq);
                set_irq_chip_data(sm->eim_first_irq + i, sm);
        }
 
index eb87a18..dd5c009 100644 (file)
@@ -136,3 +136,7 @@ fail:
        panic("Interrupt controller initialization failed!\n");
 }
 
+unsigned long intc_get_pending(int group)
+{
+       return intc_readl(&intc0, INTREQ0 + 4 * group);
+}
index d3aabfc..f1280ed 100644 (file)
@@ -25,27 +25,98 @@ struct pio_device {
        void __iomem *regs;
        const struct platform_device *pdev;
        struct clk *clk;
-       u32 alloc_mask;
+       u32 pinmux_mask;
        char name[32];
 };
 
 static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id)
+static struct pio_device *gpio_to_pio(unsigned int gpio)
 {
        struct pio_device *pio;
-       u32 mask = 1 << pin_id;
+       unsigned int index;
 
-       BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+       index = gpio >> 5;
+       if (index >= MAX_NR_PIO_DEVICES)
+               return NULL;
+       pio = &pio_dev[index];
+       if (!pio->regs)
+               return NULL;
 
-       pio = &pio_dev[portmux_id];
+       return pio;
+}
+
+/* Pin multiplexing API */
+
+void __init at32_select_periph(unsigned int pin, unsigned int periph,
+                              unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       pio = gpio_to_pio(pin);
+       if (unlikely(!pio)) {
+               printk("pio: invalid pin %u\n", pin);
+               goto fail;
+       }
 
-       if (function_id)
+       if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+               printk("%s: pin %u is busy\n", pio->name, pin_index);
+               goto fail;
+       }
+
+       pio_writel(pio, PUER, mask);
+       if (periph)
                pio_writel(pio, BSR, mask);
        else
                pio_writel(pio, ASR, mask);
+
        pio_writel(pio, PDR, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
+}
+
+void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       pio = gpio_to_pio(pin);
+       if (unlikely(!pio)) {
+               printk("pio: invalid pin %u\n", pin);
+               goto fail;
+       }
+
+       if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+               printk("%s: pin %u is busy\n", pio->name, pin_index);
+               goto fail;
+       }
+
+       pio_writel(pio, PUER, mask);
+       if (flags & AT32_GPIOF_HIGH)
+               pio_writel(pio, SODR, mask);
+       else
+               pio_writel(pio, CODR, mask);
+       if (flags & AT32_GPIOF_OUTPUT)
+               pio_writel(pio, OER, mask);
+       else
+               pio_writel(pio, ODR, mask);
+
+       pio_writel(pio, PER, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
 }
 
 static int __init pio_probe(struct platform_device *pdev)
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
deleted file mode 100644 (file)
index 03306eb..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * System Manager driver for AT32AP CPUs
- *
- * Copyright (C) 2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-
-#include <asm/intc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/sm.h>
-
-#include "sm.h"
-
-#define SM_EIM_IRQ_RESOURCE    1
-#define SM_PM_IRQ_RESOURCE     2
-#define SM_RTC_IRQ_RESOURCE    3
-
-#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
-
-struct at32_sm system_manager;
-
-int __init at32_sm_init(void)
-{
-       struct resource *regs;
-       struct at32_sm *sm = &system_manager;
-       int ret = -ENXIO;
-
-       regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
-       if (!regs)
-               goto fail;
-
-       spin_lock_init(&sm->lock);
-       sm->pdev = &at32_sm_device;
-
-       ret = -ENOMEM;
-       sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
-       if (!sm->regs)
-               goto fail;
-
-       return 0;
-
-fail:
-       printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
-       return ret;
-}
-
-/*
- * External Interrupt Module (EIM).
- *
- * EIM gets level- or edge-triggered interrupts of either polarity
- * from the outside and converts it to active-high level-triggered
- * interrupts that the internal interrupt controller can handle. EIM
- * also provides masking/unmasking of interrupts, as well as
- * acknowledging of edge-triggered interrupts.
- */
-
-static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
-                                         struct pt_regs *regs)
-{
-       printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
-       disable_irq(irq);
-       return IRQ_NONE;
-}
-
-static struct irqaction eim_spurious_action = {
-       .handler = spurious_eim_interrupt,
-};
-
-static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct irq_controller * irqc = dev_id;
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long pending;
-
-       /*
-        * No need to disable interrupts globally.  The interrupt
-        * level relevant to this group must be masked all the time,
-        * so we know that this particular EIM instance will not be
-        * re-entered.
-        */
-       spin_lock(&sm->lock);
-
-       pending = intc_get_pending(sm->irqc.irq_group);
-       if (unlikely(!pending)) {
-               printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
-                      sm->irqc.irq_group);
-               goto unlock;
-       }
-
-       do {
-               struct irqaction *action;
-               unsigned int i;
-
-               i = fls(pending) - 1;
-               pending &= ~(1 << i);
-               action = sm->action[i];
-
-               /* Acknowledge the interrupt */
-               sm_writel(sm, EIM_ICR, 1 << i);
-
-               spin_unlock(&sm->lock);
-
-               if (action->flags & SA_INTERRUPT)
-                       local_irq_disable();
-               action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
-               local_irq_enable();
-               spin_lock(&sm->lock);
-               if (action->flags & SA_SAMPLE_RANDOM)
-                       add_interrupt_randomness(sm->irqc.first_irq + i);
-       } while (pending);
-
-unlock:
-       spin_unlock(&sm->lock);
-       return IRQ_HANDLED;
-}
-
-static void eim_mask(struct irq_controller *irqc, unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned int i;
-
-       i = irq - sm->irqc.first_irq;
-       sm_writel(sm, EIM_IDR, 1 << i);
-}
-
-static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned int i;
-
-       i = irq - sm->irqc.first_irq;
-       sm_writel(sm, EIM_IER, 1 << i);
-}
-
-static int eim_setup(struct irq_controller *irqc, unsigned int irq,
-               struct irqaction *action)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       sm->action[irq - sm->irqc.first_irq] = action;
-       /* Acknowledge earlier interrupts */
-       sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
-       eim_unmask(irqc, irq);
-       return 0;
-}
-
-static void eim_free(struct irq_controller *irqc, unsigned int irq,
-               void *dev)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       eim_mask(irqc, irq);
-       sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
-}
-
-static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
-                       unsigned int type)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long flags;
-       u32 value, pattern;
-
-       spin_lock_irqsave(&sm->lock, flags);
-
-       pattern = 1 << (irq - sm->irqc.first_irq);
-
-       value = sm_readl(sm, EIM_MODE);
-       if (type & IRQ_TYPE_LEVEL)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_MODE, value);
-       value = sm_readl(sm, EIM_EDGE);
-       if (type & IRQ_EDGE_RISING)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_EDGE, value);
-       value = sm_readl(sm, EIM_LEVEL);
-       if (type & IRQ_LEVEL_HIGH)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_LEVEL, value);
-
-       spin_unlock_irqrestore(&sm->lock, flags);
-
-       return 0;
-}
-
-static unsigned int eim_get_type(struct irq_controller *irqc,
-                                unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long flags;
-       unsigned int type = 0;
-       u32 mode, edge, level, pattern;
-
-       pattern = 1 << (irq - sm->irqc.first_irq);
-
-       spin_lock_irqsave(&sm->lock, flags);
-       mode = sm_readl(sm, EIM_MODE);
-       edge = sm_readl(sm, EIM_EDGE);
-       level = sm_readl(sm, EIM_LEVEL);
-       spin_unlock_irqrestore(&sm->lock, flags);
-
-       if (mode & pattern)
-               type |= IRQ_TYPE_LEVEL;
-       if (edge & pattern)
-               type |= IRQ_EDGE_RISING;
-       if (level & pattern)
-               type |= IRQ_LEVEL_HIGH;
-
-       return type;
-}
-
-static struct irq_controller_class eim_irq_class = {
-       .typename       = "EIM",
-       .handle         = eim_handle_irq,
-       .setup          = eim_setup,
-       .free           = eim_free,
-       .mask           = eim_mask,
-       .unmask         = eim_unmask,
-       .set_type       = eim_set_type,
-       .get_type       = eim_get_type,
-};
-
-static int __init eim_init(void)
-{
-       struct at32_sm *sm = &system_manager;
-       unsigned int i;
-       u32 pattern;
-       int ret;
-
-       /*
-        * The EIM is really the same module as SM, so register
-        * mapping, etc. has been taken care of already.
-        */
-
-       /*
-        * Find out how many interrupt lines that are actually
-        * implemented in hardware.
-        */
-       sm_writel(sm, EIM_IDR, ~0UL);
-       sm_writel(sm, EIM_MODE, ~0UL);
-       pattern = sm_readl(sm, EIM_MODE);
-       sm->irqc.nr_irqs = fls(pattern);
-
-       ret = -ENOMEM;
-       sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
-                            GFP_KERNEL);
-       if (!sm->action)
-               goto out;
-
-       for (i = 0; i < sm->irqc.nr_irqs; i++)
-               sm->action[i] = &eim_spurious_action;
-
-       spin_lock_init(&sm->lock);
-       sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
-       sm->irqc.class = &eim_irq_class;
-
-       ret = intc_register_controller(&sm->irqc);
-       if (ret < 0)
-               goto out_free_actions;
-
-       printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
-              sm->regs, sm->irqc.irq_group);
-       printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
-              sm->irqc.nr_irqs, sm->irqc.first_irq);
-
-       return 0;
-
-out_free_actions:
-       kfree(sm->action);
-out:
-       return ret;
-}
-arch_initcall(eim_init);
index 44ab8a7..b68d669 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/addrspace.h>
 #include <asm/cacheflush.h>
 
-void dma_cache_sync(void *vaddr, size_t size, int direction)
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction)
 {
        /*
         * No need to sync an uncached area
index 6a1238a..3474309 100644 (file)
@@ -16,6 +16,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index e067806..424eb0e 100644 (file)
@@ -504,7 +504,7 @@ static int sync_serial_release(struct inode *inode, struct file *file)
 
 static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
 {
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        unsigned int mask = 0;
        sync_port* port;
        DEBUGPOLL( static unsigned int prev_mask = 0; );
@@ -531,7 +531,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
                  unsigned int cmd, unsigned long arg)
 {
        int return_val = 0;
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        sync_port* port;
        reg_sser_rw_tr_cfg tr_cfg;
        reg_sser_rw_rec_cfg rec_cfg;
@@ -789,7 +789,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
 static ssize_t sync_serial_write(struct file * file, const char * buf,
                                  size_t count, loff_t *ppos)
 {
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        DECLARE_WAITQUEUE(wait, current);
        sync_port *port;
        unsigned long c, c1;
@@ -919,7 +919,7 @@ static ssize_t sync_serial_write(struct file * file, const char * buf,
 static ssize_t sync_serial_read(struct file * file, char * buf,
                                size_t count, loff_t *ppos)
 {
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        int avail;
        sync_port *port;
        unsigned char* start;
index 934c510..c73e91f 100644 (file)
@@ -232,7 +232,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
         * context, we must not take the fault..
         */
 
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        down_read(&mm->mmap_sem);
index cf1c446..7561d7b 100644 (file)
@@ -41,6 +41,14 @@ config TIME_LOW_RES
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default y
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default y
+
 mainmenu "Fujitsu FR-V Kernel Configuration"
 
 source "init/Kconfig"
index eae874a..14f64b0 100644 (file)
@@ -10,9 +10,9 @@
  */
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/futex.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 /*
  * the various futex operations; MMU fault checking is ignored under no-MMU
@@ -200,7 +200,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
        if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -223,7 +223,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
                break;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index c1d9fc8..ee677ce 100644 (file)
@@ -223,7 +223,7 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
 
 static int cmode_sysctl(ctl_table *table, int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen, void **context)
+                       void __user *newval, size_t newlen)
 {
        if (oldval && oldlenp) {
                size_t oldlen;
@@ -326,7 +326,7 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
 
 static int p0_sysctl(ctl_table *table, int __user *name, int nlen,
                     void __user *oldval, size_t __user *oldlenp,
-                    void __user *newval, size_t newlen, void **context)
+                    void __user *newval, size_t newlen)
 {
        if (oldval && oldlenp) {
                size_t oldlen;
@@ -370,7 +370,7 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
 
 static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
                     void __user *oldval, size_t __user *oldlenp,
-                    void __user *newval, size_t newlen, void **context)
+                    void __user *newval, size_t newlen)
 {
        if (oldval && oldlenp) {
                size_t oldlen;
index a8c61da..1a5eb6c 100644 (file)
@@ -947,7 +947,7 @@ static void __init setup_linux_memory(void)
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) {
                        reserve_bootmem(INITRD_START, INITRD_SIZE);
-                       initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+                       initrd_start = INITRD_START + PAGE_OFFSET;
                        initrd_end = initrd_start + INITRD_SIZE;
                }
                else {
index b8a5882..85baeae 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/personality.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
index f5a6530..9477ccc 100644 (file)
@@ -110,14 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 
 #if 0
        printk("[area] l=%lx (ENOMEM) f='%s'\n",
-              len, filp ? filp->f_dentry->d_name.name : "");
+              len, filp ? filp->f_path.dentry->d_name.name : "");
 #endif
        return -ENOMEM;
 
  success:
 #if 0
        printk("[area] l=%lx ad=%lx f='%s'\n",
-              len, addr, filp ? filp->f_dentry->d_name.name : "");
+              len, addr, filp ? filp->f_path.dentry->d_name.name : "");
 #endif
        return addr;
 } /* end arch_get_unmapped_area() */
index 8b3eb50..3f12296 100644 (file)
@@ -78,7 +78,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        down_read(&mm->mmap_sem);
index f76dd03..19b13be 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/cacheflush.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
-kmem_cache_t *pgd_cache;
+struct kmem_cache *pgd_cache;
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
@@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd)
                set_page_private(next, (unsigned long) pprev);
 }
 
-void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags;
 
@@ -120,7 +120,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
 }
 
 /* never called when PTRS_PER_PMD > 1 */
-void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
 
index cabf0bf..34a84bc 100644 (file)
@@ -29,6 +29,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default n
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index 1077b71..6adf8f4 100644 (file)
@@ -116,7 +116,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #else
        if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && 
-           (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS)
+           (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS))
            /* overlap userarea */
            memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; 
 #endif
index 7787f70..0295560 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
index 756325d..f05288b 100644 (file)
@@ -70,6 +70,7 @@ SECTIONS
 #endif
         .text :
        {
+       _text = .;
 #if defined(CONFIG_ROMKERNEL)
        *(.int_redirect)
 #endif
index 8ff1c6f..0d67a0a 100644 (file)
@@ -49,6 +49,11 @@ config GENERIC_IOMAP
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -182,6 +187,18 @@ config X86_ES7000
 
 endchoice
 
+config PARAVIRT
+       bool "Paravirtualization support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       depends on !(X86_VISWS || X86_VOYAGER)
+       help
+         Paravirtualization is a way of running multiple instances of
+         Linux on the same machine, under a hypervisor.  This option
+         changes the kernel so it can modify itself when it is run
+         under a hypervisor, improving performance significantly.
+         However, when run without a hypervisor the kernel is
+         theoretically slower.  If in doubt, say N.
+
 config ACPI_SRAT
        bool
        default y
@@ -443,7 +460,8 @@ source "drivers/firmware/Kconfig"
 
 choice
        prompt "High Memory Support"
-       default NOHIGHMEM
+       default HIGHMEM4G if !X86_NUMAQ
+       default HIGHMEM64G if X86_NUMAQ
 
 config NOHIGHMEM
        bool "off"
@@ -710,20 +728,6 @@ config BOOT_IOREMAP
        depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
        default y
 
-config REGPARM
-       bool "Use register arguments"
-       default y
-       help
-       Compile the kernel with -mregparm=3. This instructs gcc to use
-       a more efficient function call ABI which passes the first three
-       arguments of a function call via registers, which results in denser
-       and faster code.
-
-       If this option is disabled, then the default ABI of passing
-       arguments via the stack is used.
-
-       If unsure, say Y.
-
 config SECCOMP
        bool "Enable seccomp to safely compute untrusted bytecode"
        depends on PROC_FS
@@ -773,23 +777,39 @@ config CRASH_DUMP
           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)
+config RELOCATABLE
+       bool "Build a relocatable kernel(EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         This build a kernel image that retains relocation information
+          so it can be loaded someplace besides the default 1MB.
+         The relocations tend to the kernel binary about 10% larger,
+          but are discarded at runtime.
+
+         One use is for the kexec on panic case where the recovery kernel
+          must live at a different physical address than the primary
+          kernel.
 
-       default "0x1000000" if CRASH_DUMP
+config PHYSICAL_ALIGN
+       hex "Alignment value to which kernel should be aligned"
        default "0x100000"
+       range 0x2000 0x400000
        help
-         This gives the physical address where the kernel is loaded. Normally
-         for regular kernels this value is 0x100000 (1MB). But in the case
-         of kexec on panic the fail safe kernel needs to run at a different
-         address than the panic-ed kernel. This option is used to set the load
-         address for kernels used to capture crash dump on being kexec'ed
-         after panic. The default value for crash dump kernels is
-         0x1000000 (16MB). This can also be set based on the "X" value as
-         specified in the "crashkernel=YM@XM" command line boot parameter
-         passed to the panic-ed kernel. Typically this parameter is set as
-         crashkernel=64M@16M. Please take a look at
-         Documentation/kdump/kdump.txt for more details about crash dumps.
+         This value puts the alignment restrictions on physical address
+         where kernel is loaded and run from. Kernel is compiled for an
+         address which meets above alignment restriction.
+
+         If bootloader loads the kernel at a non-aligned address and
+         CONFIG_RELOCATABLE is set, kernel will move itself to nearest
+         address aligned to above value and run from there.
+
+         If bootloader loads the kernel at a non-aligned address and
+         CONFIG_RELOCATABLE is not set, kernel will ignore the run time
+         load address and decompress itself to the address it has been
+         compiled for and run from there. The address for which kernel is
+         compiled already meets above alignment restrictions. Hence the
+         end result is that kernel runs from a physical address meeting
+         above alignment restrictions.
 
          Don't change this unless you know what you are doing.
 
index fc4f2ab..2aecfba 100644 (file)
@@ -103,8 +103,15 @@ config MPENTIUMM
          Select this for Intel Pentium M (not Pentium-4 M)
          notebook chips.
 
+config MCORE2
+       bool "Core 2/newer Xeon"
+       help
+         Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
+         CPUs. You can distingush newer from older Xeons by the CPU family
+         in /proc/cpuinfo. Newer ones have 6.
+
 config MPENTIUM4
-       bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon"
+       bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon"
        help
          Select this for Intel Pentium 4 chips.  This includes the
          Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
@@ -229,7 +236,7 @@ config X86_L1_CACHE_SHIFT
        default "7" if MPENTIUM4 || X86_GENERIC
        default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
        default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
-       default "6" if MK7 || MK8 || MPENTIUMM
+       default "6" if MK7 || MK8 || MPENTIUMM || MCORE2
 
 config RWSEM_GENERIC_SPINLOCK
        bool
@@ -241,6 +248,14 @@ config RWSEM_XCHGADD_ALGORITHM
        depends on !M386
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_CALIBRATE_DELAY
        bool
        default y
@@ -287,17 +302,17 @@ config X86_ALIGNMENT_16
 
 config X86_GOOD_APIC
        bool
-       depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON
+       depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2
        default y
 
 config X86_INTEL_USERCOPY
        bool
-       depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON
+       depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
        default y
 
 config X86_USE_PPRO_CHECKSUM
        bool
-       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX
+       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
        default y
 
 config X86_USE_3DNOW
@@ -312,5 +327,5 @@ config X86_OOSTORE
 
 config X86_TSC
        bool
-       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ
+       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
        default y
index b31c080..f68cc6f 100644 (file)
@@ -85,4 +85,14 @@ config DOUBLEFAULT
           option saves about 4k and might cause you much additional grey
           hair.
 
+config DEBUG_PARAVIRT
+       bool "Enable some paravirtualization debugging"
+       default y
+       depends on PARAVIRT && DEBUG_KERNEL
+       help
+         Currently deliberately clobbers regs which are allowed to be
+         clobbered in inlined paravirt hooks, even in native mode.
+         If turning this off solves a problem, then DISABLE_INTERRUPTS() or
+         ENABLE_INTERRUPTS() is lying about what registers can be clobbered.
+
 endmenu
index 0677908..f7ac1ae 100644 (file)
@@ -26,10 +26,12 @@ endif
 
 LDFLAGS                := -m elf_i386
 OBJCOPYFLAGS   := -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux :=
+ifdef CONFIG_RELOCATABLE
+LDFLAGS_vmlinux := --emit-relocs
+endif
 CHECKFLAGS     += -D__i386__
 
-CFLAGS += -pipe -msoft-float
+CFLAGS += -pipe -msoft-float -mregparm=3
 
 # prevent gcc from keeping the stack 16 byte aligned
 CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
@@ -37,8 +39,6 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 # CPU-specific tuning. Anything which can be shared with UML should go here.
 include $(srctree)/arch/i386/Makefile.cpu
 
-cflags-$(CONFIG_REGPARM) += -mregparm=3
-
 # temporary until string.h is fixed
 cflags-y += -ffreestanding
 
index a11befb..a32c031 100644 (file)
@@ -32,6 +32,7 @@ cflags-$(CONFIG_MWINCHIP2)    += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MWINCHIP3D)    += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MCYRIXIII)     += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MVIAC3_2)      += $(call cc-option,-march=c3-2,-march=i686)
+cflags-$(CONFIG_MCORE2)                += -march=i686 $(call cc-option,-mtune=core2,$(call cc-option,-mtune=generic,-mtune=i686))
 
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)      += -march=i486
index 258ea95..a661217 100644 (file)
@@ -4,22 +4,42 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
+                       vmlinux.bin.all vmlinux.relocs
 EXTRA_AFLAGS   := -traditional
 
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
+LDFLAGS_vmlinux := -T
+CFLAGS_misc.o += -fPIC
+hostprogs-y    := relocs
 
-$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
        $(call if_changed,ld)
        @:
 
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
+quiet_cmd_relocs = RELOCS  $@
+      cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
+$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
+       $(call if_changed,relocs)
+
+vmlinux.bin.all-y := $(obj)/vmlinux.bin
+vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
+quiet_cmd_relocbin = BUILD   $@
+      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
+$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
+       $(call if_changed,relocbin)
+
+ifdef CONFIG_RELOCATABLE
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
+       $(call if_changed,gzip)
+else
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
+endif
 
 LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
 
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+$(obj)/piggy.o: $(src)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
        $(call if_changed,ld)
index b5893e4..f395a4b 100644 (file)
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
+#include <asm/boot.h>
 
+.section ".text.head"
        .globl startup_32
-       
+
 startup_32:
        cld
        cli
@@ -37,93 +39,142 @@ startup_32:
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
+       movl %eax,%ss
 
-       lss stack_start,%esp
-       xorl %eax,%eax
-1:     incl %eax               # check that A20 really IS enabled
-       movl %eax,0x000000      # loop forever if it isn't
-       cmpl %eax,0x100000
-       je 1b
+/* Calculate the delta between where we were compiled to run
+ * at and where we were actually loaded at.  This can only be done
+ * with a short local call on x86.  Nothing  else will tell us what
+ * address we are running at.  The reserved chunk of the real-mode
+ * data at 0x34-0x3f are used as the stack for this calculation.
+ * Only 4 bytes are needed.
+ */
+       leal 0x40(%esi), %esp
+       call 1f
+1:     popl %ebp
+       subl $1b, %ebp
+
+/* %ebp contains the address we are loaded at by the boot loader and %ebx
+ * contains the address where we should move the kernel image temporarily
+ * for safe in-place decompression.
+ */
+
+#ifdef CONFIG_RELOCATABLE
+       movl    %ebp, %ebx
+       addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
+       andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
+#else
+       movl $LOAD_PHYSICAL_ADDR, %ebx
+#endif
+
+       /* Replace the compressed data size with the uncompressed size */
+       subl input_len(%ebp), %ebx
+       movl output_len(%ebp), %eax
+       addl %eax, %ebx
+       /* Add 8 bytes for every 32K input block */
+       shrl $12, %eax
+       addl %eax, %ebx
+       /* Add 32K + 18 bytes of extra slack */
+       addl $(32768 + 18), %ebx
+       /* Align on a 4K boundary */
+       addl $4095, %ebx
+       andl $~4095, %ebx
+
+/* Copy the compressed kernel to the end of our buffer
+ * where decompression in place becomes safe.
+ */
+       pushl %esi
+       leal _end(%ebp), %esi
+       leal _end(%ebx), %edi
+       movl $(_end - startup_32), %ecx
+       std
+       rep
+       movsb
+       cld
+       popl %esi
+
+/* Compute the kernel start address.
+ */
+#ifdef CONFIG_RELOCATABLE
+       addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
+       andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
+#else
+       movl    $LOAD_PHYSICAL_ADDR, %ebp
+#endif
 
 /*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
+ * Jump to the relocated address.
  */
-       pushl $0
-       popfl
+       leal relocated(%ebx), %eax
+       jmp *%eax
+.section ".text"
+relocated:
+
 /*
  * Clear BSS
  */
        xorl %eax,%eax
-       movl $_edata,%edi
-       movl $_end,%ecx
+       leal _edata(%ebx),%edi
+       leal _end(%ebx), %ecx
        subl %edi,%ecx
        cld
        rep
        stosb
+
+/*
+ * Setup the stack for the decompressor
+ */
+       leal stack_end(%ebx), %esp
+
 /*
  * Do the decompression, and jump to the new kernel..
  */
-       subl $16,%esp   # place for structure on the stack
-       movl %esp,%eax
+       movl output_len(%ebx), %eax
+       pushl %eax
+       pushl %ebp      # output address
+       movl input_len(%ebx), %eax
+       pushl %eax      # input_len
+       leal input_data(%ebx), %eax
+       pushl %eax      # input_data
+       leal _end(%ebx), %eax
+       pushl %eax      # end of the image as third argument
        pushl %esi      # real mode pointer as second arg
-       pushl %eax      # address of structure as first arg
        call decompress_kernel
-       orl  %eax,%eax 
-       jnz  3f
-       popl %esi       # discard address
-       popl %esi       # real mode pointer
-       xorl %ebx,%ebx
-       ljmp $(__BOOT_CS), $__PHYSICAL_START
+       addl $20, %esp
+       popl %ecx
 
+#if CONFIG_RELOCATABLE
+/* Find the address of the relocations.
+ */
+       movl %ebp, %edi
+       addl %ecx, %edi
+
+/* Calculate the delta between where vmlinux was compiled to run
+ * and where it was actually loaded.
+ */
+       movl %ebp, %ebx
+       subl $LOAD_PHYSICAL_ADDR, %ebx
+       jz   2f         /* Nothing to be done if loaded at compiled addr. */
 /*
- * We come here, if we were loaded high.
- * We need to move the move-in-place routine down to 0x1000
- * and then start it with the buffer addresses in registers,
- * which we got from the stack.
+ * Process relocations.
  */
-3:
-       movl $move_routine_start,%esi
-       movl $0x1000,%edi
-       movl $move_routine_end,%ecx
-       subl %esi,%ecx
-       addl $3,%ecx
-       shrl $2,%ecx
-       cld
-       rep
-       movsl
-
-       popl %esi       # discard the address
-       popl %ebx       # real mode pointer
-       popl %esi       # low_buffer_start
-       popl %ecx       # lcount
-       popl %edx       # high_buffer_start
-       popl %eax       # hcount
-       movl $__PHYSICAL_START,%edi
-       cli             # make sure we don't get interrupted
-       ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
+
+1:     subl $4, %edi
+       movl 0(%edi), %ecx
+       testl %ecx, %ecx
+       jz 2f
+       addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
+       jmp 1b
+2:
+#endif
 
 /*
- * Routine (template) for moving the decompressed kernel in place,
- * if we were high loaded. This _must_ PIC-code !
+ * Jump to the decompressed kernel.
  */
-move_routine_start:
-       movl %ecx,%ebp
-       shrl $2,%ecx
-       rep
-       movsl
-       movl %ebp,%ecx
-       andl $3,%ecx
-       rep
-       movsb
-       movl %edx,%esi
-       movl %eax,%ecx  # NOTE: rep movsb won't move if %ecx == 0
-       addl $3,%ecx
-       shrl $2,%ecx
-       rep
-       movsl
-       movl %ebx,%esi  # Restore setup pointer
        xorl %ebx,%ebx
-       ljmp $(__BOOT_CS), $__PHYSICAL_START
-move_routine_end:
+       jmp *%ebp
+
+.bss
+.balign 4
+stack:
+       .fill 4096, 1, 0
+stack_end:
index b2ccd54..1ce7017 100644 (file)
@@ -9,11 +9,94 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#undef CONFIG_PARAVIRT
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
 #include <linux/screen_info.h>
 #include <asm/io.h>
 #include <asm/page.h>
+#include <asm/boot.h>
+
+/* WARNING!!
+ * This code is compiled with -fPIC and it is relocated dynamically
+ * at run time, but no relocation processing is performed.
+ * This means that it is not safe to place pointers in static structures.
+ */
+
+/*
+ * Getting to provable safe in place decompression is hard.
+ * Worst case behaviours need to be analized.
+ * Background information:
+ *
+ * The file layout is:
+ *    magic[2]
+ *    method[1]
+ *    flags[1]
+ *    timestamp[4]
+ *    extraflags[1]
+ *    os[1]
+ *    compressed data blocks[N]
+ *    crc[4] orig_len[4]
+ *
+ * resulting in 18 bytes of non compressed data overhead.
+ *
+ * Files divided into blocks
+ * 1 bit (last block flag)
+ * 2 bits (block type)
+ *
+ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+ * The smallest block type encoding is always used.
+ *
+ * stored:
+ *    32 bits length in bytes.
+ *
+ * fixed:
+ *    magic fixed tree.
+ *    symbols.
+ *
+ * dynamic:
+ *    dynamic tree encoding.
+ *    symbols.
+ *
+ *
+ * The buffer for decompression in place is the length of the
+ * uncompressed data, plus a small amount extra to keep the algorithm safe.
+ * The compressed data is placed at the end of the buffer.  The output
+ * pointer is placed at the start of the buffer and the input pointer
+ * is placed where the compressed data starts.  Problems will occur
+ * when the output pointer overruns the input pointer.
+ *
+ * The output pointer can only overrun the input pointer if the input
+ * pointer is moving faster than the output pointer.  A condition only
+ * triggered by data whose compressed form is larger than the uncompressed
+ * form.
+ *
+ * The worst case at the block level is a growth of the compressed data
+ * of 5 bytes per 32767 bytes.
+ *
+ * The worst case internal to a compressed block is very hard to figure.
+ * The worst case can at least be boundined by having one bit that represents
+ * 32764 bytes and then all of the rest of the bytes representing the very
+ * very last byte.
+ *
+ * All of which is enough to compute an amount of extra data that is required
+ * to be safe.  To avoid problems at the block level allocating 5 extra bytes
+ * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
+ * adding an extra 32767 bytes (the worst case uncompressed block size) is
+ * sufficient, to ensure that in the worst case the decompressed data for
+ * block will stop the byte before the compressed data for a block begins.
+ * To avoid problems with the compressed data's meta information an extra 18
+ * bytes are needed.  Leading to the formula:
+ *
+ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+ *
+ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+ * Adding 32768 instead of 32767 just makes for round numbers.
+ * Adding the decompressor_size is necessary as it musht live after all
+ * of the data as well.  Last I measured the decompressor is about 14K.
+ * 10K of actuall data and 4K of bss.
+ *
+ */
 
 /*
  * gzip declarations
@@ -30,15 +113,20 @@ typedef unsigned char  uch;
 typedef unsigned short ush;
 typedef unsigned long  ulg;
 
-#define WSIZE 0x8000           /* Window size must be at least 32k, */
-                               /* and a power of two */
+#define WSIZE 0x80000000       /* Window size must be at least 32k,
+                                * and a power of two
+                                * We don't actually have a window just
+                                * a huge output buffer so I report
+                                * a 2G windows size, as that should
+                                * always be larger than our output buffer.
+                                */
 
-static uch *inbuf;          /* input buffer */
-static uch window[WSIZE];    /* Sliding window buffer */
+static uch *inbuf;     /* input buffer */
+static uch *window;    /* Sliding window buffer, (and final output buffer) */
 
-static unsigned insize = 0;  /* valid bytes in inbuf */
-static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;  /* bytes in output buffer */
+static unsigned insize;  /* valid bytes in inbuf */
+static unsigned inptr;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt;  /* bytes in output buffer */
 
 /* gzip flag byte */
 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
@@ -89,8 +177,6 @@ extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
 
 static void *malloc(int size);
 static void free(void *where);
@@ -100,24 +186,17 @@ static void *memcpy(void *dest, const void *src, unsigned n);
 
 static void putstr(const char *);
 
-extern int end;
-static long free_mem_ptr = (long)&end;
-static long free_mem_end_ptr;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
 
-#define INPLACE_MOVE_ROUTINE  0x1000
-#define LOW_BUFFER_START      0x2000
-#define LOW_BUFFER_MAX       0x90000
 #define HEAP_SIZE             0x3000
-static unsigned int low_buffer_end, low_buffer_size;
-static int high_loaded =0;
-static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
 
 static char *vidmem = (char *)0xb8000;
 static int vidport;
 static int lines, cols;
 
 #ifdef CONFIG_X86_NUMAQ
-static void * xquad_portio = NULL;
+void *xquad_portio;
 #endif
 
 #include "../../../../lib/inflate.c"
@@ -151,7 +230,7 @@ static void gzip_mark(void **ptr)
 
 static void gzip_release(void **ptr)
 {
-       free_mem_ptr = (long) *ptr;
+       free_mem_ptr = (unsigned long) *ptr;
 }
  
 static void scroll(void)
@@ -179,7 +258,7 @@ static void putstr(const char *s)
                                y--;
                        }
                } else {
-                       vidmem [ ( x + cols * y ) * 2 ] = c; 
+                       vidmem [ ( x + cols * y ) * 2 ] = c;
                        if ( ++x >= cols ) {
                                x = 0;
                                if ( ++y >= lines ) {
@@ -224,58 +303,31 @@ static void* memcpy(void* dest, const void* src, unsigned n)
  */
 static int fill_inbuf(void)
 {
-       if (insize != 0) {
-               error("ran out of input data");
-       }
-
-       inbuf = input_data;
-       insize = input_len;
-       inptr = 1;
-       return inbuf[0];
+       error("ran out of input data");
+       return 0;
 }
 
 /* ===========================================================================
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  * (Used for the decompressed data only.)
  */
-static void flush_window_low(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in, *out, ch;
-    
-    in = window;
-    out = &output_data[output_ptr]; 
-    for (n = 0; n < outcnt; n++) {
-           ch = *out++ = *in++;
-           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-static void flush_window_high(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in,  ch;
-    in = window;
-    for (n = 0; n < outcnt; n++) {
-       ch = *output_data++ = *in++;
-       if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
-       c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    outcnt = 0;
-}
-
 static void flush_window(void)
 {
-       if (high_loaded) flush_window_high();
-       else flush_window_low();
+       /* With my window equal to my output buffer
+        * I only need to compute the crc here.
+        */
+       ulg c = crc;         /* temporary variable */
+       unsigned n;
+       uch *in, ch;
+
+       in = window;
+       for (n = 0; n < outcnt; n++) {
+               ch = *in++;
+               c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+       }
+       crc = c;
+       bytes_out += (ulg)outcnt;
+       outcnt = 0;
 }
 
 static void error(char *x)
@@ -287,66 +339,8 @@ static void error(char *x)
        while(1);       /* Halt */
 }
 
-#define STACK_SIZE (4096)
-
-long user_stack [STACK_SIZE];
-
-struct {
-       long * a;
-       short b;
-       } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS };
-
-static void setup_normal_output_buffer(void)
-{
-#ifdef STANDARD_MEMORY_BIOS_CALL
-       if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory");
-#else
-       if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
-#endif
-       output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
-       free_mem_end_ptr = (long)real_mode;
-}
-
-struct moveparams {
-       uch *low_buffer_start;  int lcount;
-       uch *high_buffer_start; int hcount;
-};
-
-static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
-{
-       high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
-#ifdef STANDARD_MEMORY_BIOS_CALL
-       if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
-#else
-       if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
-#endif 
-       mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
-       low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
-         ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
-       low_buffer_size = low_buffer_end - LOW_BUFFER_START;
-       high_loaded = 1;
-       free_mem_end_ptr = (long)high_buffer_start;
-       if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
-               high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
-               mv->hcount = 0; /* say: we need not to move high_buffer */
-       }
-       else mv->hcount = -1;
-       mv->high_buffer_start = high_buffer_start;
-}
-
-static void close_output_buffer_if_we_run_high(struct moveparams *mv)
-{
-       if (bytes_out > low_buffer_size) {
-               mv->lcount = low_buffer_size;
-               if (mv->hcount)
-                       mv->hcount = bytes_out - low_buffer_size;
-       } else {
-               mv->lcount = bytes_out;
-               mv->hcount = 0;
-       }
-}
-
-asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
+asmlinkage void decompress_kernel(void *rmode, unsigned long end,
+                       uch *input_data, unsigned long input_len, uch *output)
 {
        real_mode = rmode;
 
@@ -361,13 +355,25 @@ asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
        lines = RM_SCREEN_INFO.orig_video_lines;
        cols = RM_SCREEN_INFO.orig_video_cols;
 
-       if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
-       else setup_output_buffer_if_we_run_high(mv);
+       window = output;        /* Output buffer (Normally at 1M) */
+       free_mem_ptr     = end; /* Heap  */
+       free_mem_end_ptr = end + HEAP_SIZE;
+       inbuf  = input_data;    /* Input buffer */
+       insize = input_len;
+       inptr  = 0;
+
+       if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
+               error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
+       if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
+               error("Destination address too large");
+#ifndef CONFIG_RELOCATABLE
+       if ((u32)output != LOAD_PHYSICAL_ADDR)
+               error("Wrong destination address");
+#endif
 
        makecrc();
        putstr("Uncompressing Linux... ");
        gunzip();
        putstr("Ok, booting the kernel.\n");
-       if (high_loaded) close_output_buffer_if_we_run_high(mv);
-       return high_loaded;
+       return;
 }
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c
new file mode 100644 (file)
index 0000000..468da89
--- /dev/null
@@ -0,0 +1,625 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <byteswap.h>
+#define USE_BSD
+#include <endian.h>
+
+#define MAX_SHDRS 100
+static Elf32_Ehdr ehdr;
+static Elf32_Shdr shdr[MAX_SHDRS];
+static Elf32_Sym  *symtab[MAX_SHDRS];
+static Elf32_Rel  *reltab[MAX_SHDRS];
+static char *strtab[MAX_SHDRS];
+static unsigned long reloc_count, reloc_idx;
+static unsigned long *relocs;
+
+/*
+ * Following symbols have been audited. There values are constant and do
+ * not change if bzImage is loaded at a different physical address than
+ * the address for which it has been compiled. Don't warn user about
+ * absolute relocations present w.r.t these symbols.
+ */
+static const char* safe_abs_relocs[] = {
+               "__kernel_vsyscall",
+               "__kernel_rt_sigreturn",
+               "__kernel_sigreturn",
+               "SYSENTER_RETURN",
+};
+
+static int is_safe_abs_reloc(const char* sym_name)
+{
+       int i, array_size;
+
+       array_size = sizeof(safe_abs_relocs)/sizeof(char*);
+
+       for(i = 0; i < array_size; i++) {
+               if (!strcmp(sym_name, safe_abs_relocs[i]))
+                       /* Match found */
+                       return 1;
+       }
+       return 0;
+}
+
+static void die(char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       exit(1);
+}
+
+static const char *sym_type(unsigned type)
+{
+       static const char *type_name[] = {
+#define SYM_TYPE(X) [X] = #X
+               SYM_TYPE(STT_NOTYPE),
+               SYM_TYPE(STT_OBJECT),
+               SYM_TYPE(STT_FUNC),
+               SYM_TYPE(STT_SECTION),
+               SYM_TYPE(STT_FILE),
+               SYM_TYPE(STT_COMMON),
+               SYM_TYPE(STT_TLS),
+#undef SYM_TYPE
+       };
+       const char *name = "unknown sym type name";
+       if (type < sizeof(type_name)/sizeof(type_name[0])) {
+               name = type_name[type];
+       }
+       return name;
+}
+
+static const char *sym_bind(unsigned bind)
+{
+       static const char *bind_name[] = {
+#define SYM_BIND(X) [X] = #X
+               SYM_BIND(STB_LOCAL),
+               SYM_BIND(STB_GLOBAL),
+               SYM_BIND(STB_WEAK),
+#undef SYM_BIND
+       };
+       const char *name = "unknown sym bind name";
+       if (bind < sizeof(bind_name)/sizeof(bind_name[0])) {
+               name = bind_name[bind];
+       }
+       return name;
+}
+
+static const char *sym_visibility(unsigned visibility)
+{
+       static const char *visibility_name[] = {
+#define SYM_VISIBILITY(X) [X] = #X
+               SYM_VISIBILITY(STV_DEFAULT),
+               SYM_VISIBILITY(STV_INTERNAL),
+               SYM_VISIBILITY(STV_HIDDEN),
+               SYM_VISIBILITY(STV_PROTECTED),
+#undef SYM_VISIBILITY
+       };
+       const char *name = "unknown sym visibility name";
+       if (visibility < sizeof(visibility_name)/sizeof(visibility_name[0])) {
+               name = visibility_name[visibility];
+       }
+       return name;
+}
+
+static const char *rel_type(unsigned type)
+{
+       static const char *type_name[] = {
+#define REL_TYPE(X) [X] = #X
+               REL_TYPE(R_386_NONE),
+               REL_TYPE(R_386_32),
+               REL_TYPE(R_386_PC32),
+               REL_TYPE(R_386_GOT32),
+               REL_TYPE(R_386_PLT32),
+               REL_TYPE(R_386_COPY),
+               REL_TYPE(R_386_GLOB_DAT),
+               REL_TYPE(R_386_JMP_SLOT),
+               REL_TYPE(R_386_RELATIVE),
+               REL_TYPE(R_386_GOTOFF),
+               REL_TYPE(R_386_GOTPC),
+#undef REL_TYPE
+       };
+       const char *name = "unknown type rel type name";
+       if (type < sizeof(type_name)/sizeof(type_name[0])) {
+               name = type_name[type];
+       }
+       return name;
+}
+
+static const char *sec_name(unsigned shndx)
+{
+       const char *sec_strtab;
+       const char *name;
+       sec_strtab = strtab[ehdr.e_shstrndx];
+       name = "<noname>";
+       if (shndx < ehdr.e_shnum) {
+               name = sec_strtab + shdr[shndx].sh_name;
+       }
+       else if (shndx == SHN_ABS) {
+               name = "ABSOLUTE";
+       }
+       else if (shndx == SHN_COMMON) {
+               name = "COMMON";
+       }
+       return name;
+}
+
+static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
+{
+       const char *name;
+       name = "<noname>";
+       if (sym->st_name) {
+               name = sym_strtab + sym->st_name;
+       }
+       else {
+               name = sec_name(shdr[sym->st_shndx].sh_name);
+       }
+       return name;
+}
+
+
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#endif
+
+static uint16_t elf16_to_cpu(uint16_t val)
+{
+       return le16_to_cpu(val);
+}
+
+static uint32_t elf32_to_cpu(uint32_t val)
+{
+       return le32_to_cpu(val);
+}
+
+static void read_ehdr(FILE *fp)
+{
+       if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
+               die("Cannot read ELF header: %s\n",
+                       strerror(errno));
+       }
+       if (memcmp(ehdr.e_ident, ELFMAG, 4) != 0) {
+               die("No ELF magic\n");
+       }
+       if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
+               die("Not a 32 bit executable\n");
+       }
+       if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
+               die("Not a LSB ELF executable\n");
+       }
+       if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
+               die("Unknown ELF version\n");
+       }
+       /* Convert the fields to native endian */
+       ehdr.e_type      = elf16_to_cpu(ehdr.e_type);
+       ehdr.e_machine   = elf16_to_cpu(ehdr.e_machine);
+       ehdr.e_version   = elf32_to_cpu(ehdr.e_version);
+       ehdr.e_entry     = elf32_to_cpu(ehdr.e_entry);
+       ehdr.e_phoff     = elf32_to_cpu(ehdr.e_phoff);
+       ehdr.e_shoff     = elf32_to_cpu(ehdr.e_shoff);
+       ehdr.e_flags     = elf32_to_cpu(ehdr.e_flags);
+       ehdr.e_ehsize    = elf16_to_cpu(ehdr.e_ehsize);
+       ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
+       ehdr.e_phnum     = elf16_to_cpu(ehdr.e_phnum);
+       ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
+       ehdr.e_shnum     = elf16_to_cpu(ehdr.e_shnum);
+       ehdr.e_shstrndx  = elf16_to_cpu(ehdr.e_shstrndx);
+
+       if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
+               die("Unsupported ELF header type\n");
+       }
+       if (ehdr.e_machine != EM_386) {
+               die("Not for x86\n");
+       }
+       if (ehdr.e_version != EV_CURRENT) {
+               die("Unknown ELF version\n");
+       }
+       if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+               die("Bad Elf header size\n");
+       }
+       if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
+               die("Bad program header entry\n");
+       }
+       if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
+               die("Bad section header entry\n");
+       }
+       if (ehdr.e_shstrndx >= ehdr.e_shnum) {
+               die("String table index out of bounds\n");
+       }
+}
+
+static void read_shdrs(FILE *fp)
+{
+       int i;
+       if (ehdr.e_shnum > MAX_SHDRS) {
+               die("%d section headers supported: %d\n",
+                       ehdr.e_shnum, MAX_SHDRS);
+       }
+       if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
+               die("Seek to %d failed: %s\n",
+                       ehdr.e_shoff, strerror(errno));
+       }
+       if (fread(&shdr, sizeof(shdr[0]), ehdr.e_shnum, fp) != ehdr.e_shnum) {
+               die("Cannot read ELF section headers: %s\n",
+                       strerror(errno));
+       }
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               shdr[i].sh_name      = elf32_to_cpu(shdr[i].sh_name);
+               shdr[i].sh_type      = elf32_to_cpu(shdr[i].sh_type);
+               shdr[i].sh_flags     = elf32_to_cpu(shdr[i].sh_flags);
+               shdr[i].sh_addr      = elf32_to_cpu(shdr[i].sh_addr);
+               shdr[i].sh_offset    = elf32_to_cpu(shdr[i].sh_offset);
+               shdr[i].sh_size      = elf32_to_cpu(shdr[i].sh_size);
+               shdr[i].sh_link      = elf32_to_cpu(shdr[i].sh_link);
+               shdr[i].sh_info      = elf32_to_cpu(shdr[i].sh_info);
+               shdr[i].sh_addralign = elf32_to_cpu(shdr[i].sh_addralign);
+               shdr[i].sh_entsize   = elf32_to_cpu(shdr[i].sh_entsize);
+       }
+
+}
+
+static void read_strtabs(FILE *fp)
+{
+       int i;
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               if (shdr[i].sh_type != SHT_STRTAB) {
+                       continue;
+               }
+               strtab[i] = malloc(shdr[i].sh_size);
+               if (!strtab[i]) {
+                       die("malloc of %d bytes for strtab failed\n",
+                               shdr[i].sh_size);
+               }
+               if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+                       die("Seek to %d failed: %s\n",
+                               shdr[i].sh_offset, strerror(errno));
+               }
+               if (fread(strtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+                       die("Cannot read symbol table: %s\n",
+                               strerror(errno));
+               }
+       }
+}
+
+static void read_symtabs(FILE *fp)
+{
+       int i,j;
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               if (shdr[i].sh_type != SHT_SYMTAB) {
+                       continue;
+               }
+               symtab[i] = malloc(shdr[i].sh_size);
+               if (!symtab[i]) {
+                       die("malloc of %d bytes for symtab failed\n",
+                               shdr[i].sh_size);
+               }
+               if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+                       die("Seek to %d failed: %s\n",
+                               shdr[i].sh_offset, strerror(errno));
+               }
+               if (fread(symtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+                       die("Cannot read symbol table: %s\n",
+                               strerror(errno));
+               }
+               for(j = 0; j < shdr[i].sh_size/sizeof(symtab[i][0]); j++) {
+                       symtab[i][j].st_name  = elf32_to_cpu(symtab[i][j].st_name);
+                       symtab[i][j].st_value = elf32_to_cpu(symtab[i][j].st_value);
+                       symtab[i][j].st_size  = elf32_to_cpu(symtab[i][j].st_size);
+                       symtab[i][j].st_shndx = elf16_to_cpu(symtab[i][j].st_shndx);
+               }
+       }
+}
+
+
+static void read_relocs(FILE *fp)
+{
+       int i,j;
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               if (shdr[i].sh_type != SHT_REL) {
+                       continue;
+               }
+               reltab[i] = malloc(shdr[i].sh_size);
+               if (!reltab[i]) {
+                       die("malloc of %d bytes for relocs failed\n",
+                               shdr[i].sh_size);
+               }
+               if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+                       die("Seek to %d failed: %s\n",
+                               shdr[i].sh_offset, strerror(errno));
+               }
+               if (fread(reltab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+                       die("Cannot read symbol table: %s\n",
+                               strerror(errno));
+               }
+               for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
+                       reltab[i][j].r_offset = elf32_to_cpu(reltab[i][j].r_offset);
+                       reltab[i][j].r_info   = elf32_to_cpu(reltab[i][j].r_info);
+               }
+       }
+}
+
+
+static void print_absolute_symbols(void)
+{
+       int i;
+       printf("Absolute symbols\n");
+       printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               char *sym_strtab;
+               Elf32_Sym *sh_symtab;
+               int j;
+               if (shdr[i].sh_type != SHT_SYMTAB) {
+                       continue;
+               }
+               sh_symtab = symtab[i];
+               sym_strtab = strtab[shdr[i].sh_link];
+               for(j = 0; j < shdr[i].sh_size/sizeof(symtab[0][0]); j++) {
+                       Elf32_Sym *sym;
+                       const char *name;
+                       sym = &symtab[i][j];
+                       name = sym_name(sym_strtab, sym);
+                       if (sym->st_shndx != SHN_ABS) {
+                               continue;
+                       }
+                       printf("%5d %08x %5d %10s %10s %12s %s\n",
+                               j, sym->st_value, sym->st_size,
+                               sym_type(ELF32_ST_TYPE(sym->st_info)),
+                               sym_bind(ELF32_ST_BIND(sym->st_info)),
+                               sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
+                               name);
+               }
+       }
+       printf("\n");
+}
+
+static void print_absolute_relocs(void)
+{
+       int i, printed = 0;
+
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               char *sym_strtab;
+               Elf32_Sym *sh_symtab;
+               unsigned sec_applies, sec_symtab;
+               int j;
+               if (shdr[i].sh_type != SHT_REL) {
+                       continue;
+               }
+               sec_symtab  = shdr[i].sh_link;
+               sec_applies = shdr[i].sh_info;
+               if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
+                       continue;
+               }
+               sh_symtab = symtab[sec_symtab];
+               sym_strtab = strtab[shdr[sec_symtab].sh_link];
+               for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
+                       Elf32_Rel *rel;
+                       Elf32_Sym *sym;
+                       const char *name;
+                       rel = &reltab[i][j];
+                       sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+                       name = sym_name(sym_strtab, sym);
+                       if (sym->st_shndx != SHN_ABS) {
+                               continue;
+                       }
+
+                       /* Absolute symbols are not relocated if bzImage is
+                        * loaded at a non-compiled address. Display a warning
+                        * to user at compile time about the absolute
+                        * relocations present.
+                        *
+                        * User need to audit the code to make sure
+                        * some symbols which should have been section
+                        * relative have not become absolute because of some
+                        * linker optimization or wrong programming usage.
+                        *
+                        * Before warning check if this absolute symbol
+                        * relocation is harmless.
+                        */
+                       if (is_safe_abs_reloc(name))
+                               continue;
+
+                       if (!printed) {
+                               printf("WARNING: Absolute relocations"
+                                       " present\n");
+                               printf("Offset     Info     Type     Sym.Value "
+                                       "Sym.Name\n");
+                               printed = 1;
+                       }
+
+                       printf("%08x %08x %10s %08x  %s\n",
+                               rel->r_offset,
+                               rel->r_info,
+                               rel_type(ELF32_R_TYPE(rel->r_info)),
+                               sym->st_value,
+                               name);
+               }
+       }
+
+       if (printed)
+               printf("\n");
+}
+
+static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
+{
+       int i;
+       /* Walk through the relocations */
+       for(i = 0; i < ehdr.e_shnum; i++) {
+               char *sym_strtab;
+               Elf32_Sym *sh_symtab;
+               unsigned sec_applies, sec_symtab;
+               int j;
+               if (shdr[i].sh_type != SHT_REL) {
+                       continue;
+               }
+               sec_symtab  = shdr[i].sh_link;
+               sec_applies = shdr[i].sh_info;
+               if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
+                       continue;
+               }
+               sh_symtab = symtab[sec_symtab];
+               sym_strtab = strtab[shdr[sec_symtab].sh_link];
+               for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
+                       Elf32_Rel *rel;
+                       Elf32_Sym *sym;
+                       unsigned r_type;
+                       rel = &reltab[i][j];
+                       sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+                       r_type = ELF32_R_TYPE(rel->r_info);
+                       /* Don't visit relocations to absolute symbols */
+                       if (sym->st_shndx == SHN_ABS) {
+                               continue;
+                       }
+                       if (r_type == R_386_PC32) {
+                               /* PC relative relocations don't need to be adjusted */
+                       }
+                       else if (r_type == R_386_32) {
+                               /* Visit relocations that need to be adjusted */
+                               visit(rel, sym);
+                       }
+                       else {
+                               die("Unsupported relocation type: %d\n", r_type);
+                       }
+               }
+       }
+}
+
+static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+       reloc_count += 1;
+}
+
+static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+       /* Remember the address that needs to be adjusted. */
+       relocs[reloc_idx++] = rel->r_offset;
+}
+
+static int cmp_relocs(const void *va, const void *vb)
+{
+       const unsigned long *a, *b;
+       a = va; b = vb;
+       return (*a == *b)? 0 : (*a > *b)? 1 : -1;
+}
+
+static void emit_relocs(int as_text)
+{
+       int i;
+       /* Count how many relocations I have and allocate space for them. */
+       reloc_count = 0;
+       walk_relocs(count_reloc);
+       relocs = malloc(reloc_count * sizeof(relocs[0]));
+       if (!relocs) {
+               die("malloc of %d entries for relocs failed\n",
+                       reloc_count);
+       }
+       /* Collect up the relocations */
+       reloc_idx = 0;
+       walk_relocs(collect_reloc);
+
+       /* Order the relocations for more efficient processing */
+       qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
+
+       /* Print the relocations */
+       if (as_text) {
+               /* Print the relocations in a form suitable that
+                * gas will like.
+                */
+               printf(".section \".data.reloc\",\"a\"\n");
+               printf(".balign 4\n");
+               for(i = 0; i < reloc_count; i++) {
+                       printf("\t .long 0x%08lx\n", relocs[i]);
+               }
+               printf("\n");
+       }
+       else {
+               unsigned char buf[4];
+               buf[0] = buf[1] = buf[2] = buf[3] = 0;
+               /* Print a stop */
+               printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
+               /* Now print each relocation */
+               for(i = 0; i < reloc_count; i++) {
+                       buf[0] = (relocs[i] >>  0) & 0xff;
+                       buf[1] = (relocs[i] >>  8) & 0xff;
+                       buf[2] = (relocs[i] >> 16) & 0xff;
+                       buf[3] = (relocs[i] >> 24) & 0xff;
+                       printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
+               }
+       }
+}
+
+static void usage(void)
+{
+       die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
+}
+
+int main(int argc, char **argv)
+{
+       int show_absolute_syms, show_absolute_relocs;
+       int as_text;
+       const char *fname;
+       FILE *fp;
+       int i;
+
+       show_absolute_syms = 0;
+       show_absolute_relocs = 0;
+       as_text = 0;
+       fname = NULL;
+       for(i = 1; i < argc; i++) {
+               char *arg = argv[i];
+               if (*arg == '-') {
+                       if (strcmp(argv[1], "--abs-syms") == 0) {
+                               show_absolute_syms = 1;
+                               continue;
+                       }
+
+                       if (strcmp(argv[1], "--abs-relocs") == 0) {
+                               show_absolute_relocs = 1;
+                               continue;
+                       }
+                       else if (strcmp(argv[1], "--text") == 0) {
+                               as_text = 1;
+                               continue;
+                       }
+               }
+               else if (!fname) {
+                       fname = arg;
+                       continue;
+               }
+               usage();
+       }
+       if (!fname) {
+               usage();
+       }
+       fp = fopen(fname, "r");
+       if (!fp) {
+               die("Cannot open %s: %s\n",
+                       fname, strerror(errno));
+       }
+       read_ehdr(fp);
+       read_shdrs(fp);
+       read_strtabs(fp);
+       read_symtabs(fp);
+       read_relocs(fp);
+       if (show_absolute_syms) {
+               print_absolute_symbols();
+               return 0;
+       }
+       if (show_absolute_relocs) {
+               print_absolute_relocs();
+               return 0;
+       }
+       emit_relocs(as_text);
+       return 0;
+}
diff --git a/arch/i386/boot/compressed/vmlinux.lds b/arch/i386/boot/compressed/vmlinux.lds
new file mode 100644 (file)
index 0000000..cc4854f
--- /dev/null
@@ -0,0 +1,43 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(startup_32)
+SECTIONS
+{
+        /* Be careful parts of head.S assume startup_32 is at
+         * address 0.
+        */
+       . =  0  ;
+       .text.head : {
+               _head = . ;
+               *(.text.head)
+               _ehead = . ;
+       }
+       .data.compressed : {
+               *(.data.compressed)
+       }
+       .text : {
+               _text = .;      /* Text */
+               *(.text)
+               *(.text.*)
+               _etext = . ;
+       }
+       .rodata : {
+               _rodata = . ;
+               *(.rodata)       /* read-only data */
+               *(.rodata.*)
+               _erodata = . ;
+       }
+       .data : {
+               _data = . ;
+               *(.data)
+               *(.data.*)
+               _edata = . ;
+       }
+       .bss : {
+               _bss = . ;
+               *(.bss)
+               *(.bss.*)
+               *(COMMON)
+               _end = . ;
+       }
+}
index 1ed9d79..707a88f 100644 (file)
@@ -1,9 +1,10 @@
 SECTIONS
 {
-  .data : { 
+  .data.compressed : {
        input_len = .;
        LONG(input_data_end - input_data) input_data = .; 
        *(.data) 
+       output_len = . - 4;
        input_data_end = .; 
        }
 }
index 3aec453..06edf1c 100644 (file)
@@ -81,7 +81,7 @@ start:
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
                .ascii  "HdrS"          # header signature
-               .word   0x0204          # header version number (>= 0x0105)
+               .word   0x0205          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
 start_sys_seg: .word   SYSSEG
@@ -160,6 +160,17 @@ ramdisk_max:       .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
                                        # The highest safe address for
                                        # the contents of an initrd
 
+kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN         #physical addr alignment
+                                               #required for protected mode
+                                               #kernel
+#ifdef CONFIG_RELOCATABLE
+relocatable_kernel:    .byte 1
+#else
+relocatable_kernel:    .byte 0
+#endif
+pad2:                  .byte 0
+pad3:                  .word 0
+
 trampoline:    call    start_of_setup
                .align 16
                                        # The offset at this point is 0x240
@@ -588,11 +599,6 @@ rmodeswtch_normal:
        call    default_switch
 
 rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
-       movl    %cs:code32_start, %eax
-       movl    %eax, %cs:code32
-
 # Now we move the system to its rightful place ... but we check if we have a
 # big-kernel. In that case we *must* not move it ...
        testb   $LOADED_HIGH, %cs:loadflags
@@ -788,11 +794,12 @@ a20_err_msg:
 a20_done:
 
 #endif /* CONFIG_X86_VOYAGER */
-# set up gdt and idt
+# set up gdt and idt and 32bit start address
        lidt    idt_48                          # load idt with 0,0
        xorl    %eax, %eax                      # Compute gdt_base
        movw    %ds, %ax                        # (Convert %ds:gdt to a linear ptr)
        shll    $4, %eax
+       addl    %eax, code32
        addl    $gdt, %eax
        movl    %eax, (gdt_48+2)
        lgdt    gdt_48                          # load gdt with whatever is
@@ -851,9 +858,26 @@ flush_instr:
 #      Manual, Mixing 16-bit and 32-bit code, page 16-6)
 
        .byte 0x66, 0xea                        # prefix + jmpi-opcode
-code32:        .long   0x1000                          # will be set to 0x100000
-                                               # for big kernels
+code32:        .long   startup_32                      # will be set to %cs+startup_32
        .word   __BOOT_CS
+.code32
+startup_32:
+       movl $(__BOOT_DS), %eax
+       movl %eax, %ds
+       movl %eax, %es
+       movl %eax, %fs
+       movl %eax, %gs
+       movl %eax, %ss
+
+       xorl %eax, %eax
+1:     incl %eax                               # check that A20 really IS enabled
+       movl %eax, 0x00000000                   # loop forever if it isn't
+       cmpl %eax, 0x00100000
+       je 1b
+
+       # Jump to the 32bit entry point
+       jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
+.code16
 
 # Here's a bunch of information about your current kernel..
 kernel_version:        .ascii  UTS_RELEASE
index 97aacd6..3265208 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2-git4
-# Sat Oct 21 03:38:56 2006
+# Linux kernel version: 2.6.19-git14
+# Sat Dec  9 21:23:14 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -12,6 +12,7 @@ CONFIG_X86=y
 CONFIG_MMU=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMI=y
@@ -40,13 +41,14 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -110,6 +112,7 @@ CONFIG_SMP=y
 # CONFIG_X86_VISWS is not set
 CONFIG_X86_GENERICARCH=y
 # CONFIG_X86_ES7000 is not set
+# CONFIG_PARAVIRT is not set
 CONFIG_X86_CYCLONE_TIMER=y
 # CONFIG_M386 is not set
 # CONFIG_M486 is not set
@@ -120,6 +123,7 @@ CONFIG_X86_CYCLONE_TIMER=y
 # CONFIG_MPENTIUMII is not set
 CONFIG_MPENTIUMIII=y
 # CONFIG_MPENTIUMM is not set
+# CONFIG_MCORE2 is not set
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
@@ -138,6 +142,8 @@ CONFIG_X86_CMPXCHG=y
 CONFIG_X86_XADD=y
 CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_INVLPG=y
@@ -197,15 +203,16 @@ CONFIG_RESOURCES_64BIT=y
 CONFIG_MTRR=y
 # CONFIG_EFI is not set
 # CONFIG_IRQBALANCE is not set
-CONFIG_REGPARM=y
 CONFIG_SECCOMP=y
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
-CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_COMPAT_VDSO=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -367,6 +374,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
@@ -559,6 +567,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -579,6 +588,7 @@ CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -638,6 +648,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -677,6 +688,7 @@ CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -850,6 +862,7 @@ CONFIG_BNX2=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -984,10 +997,6 @@ CONFIG_RTC=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_SONYPI is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=y
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_ATI is not set
@@ -1080,10 +1089,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
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_TRIDENT is not set
@@ -1092,6 +1098,11 @@ CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+
 #
 # USB support
 #
@@ -1108,6 +1119,7 @@ CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1155,8 +1167,7 @@ CONFIG_USB_STORAGE=y
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_USB_HID_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
@@ -1185,6 +1196,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1439,6 +1451,11 @@ CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Instrumentation Support
 #
@@ -1505,6 +1522,7 @@ CONFIG_DOUBLEFAULT=y
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
index 1a884b6..1e8988e 100644 (file)
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
 
 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 \
+               pci-dma.o i386_ksyms.o i387.o bootflag.o e820.o\
                quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
@@ -40,6 +40,9 @@ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
 obj-$(CONFIG_K8_NB)            += k8.o
 
+# Make sure this is linked after any other paravirt_ops structs: see head.S
+obj-$(CONFIG_PARAVIRT)         += paravirt.o
+
 EXTRA_AFLAGS   := -traditional
 
 obj-$(CONFIG_SCx200)           += scx200.o
index 4664b55..12e937c 100644 (file)
@@ -156,10 +156,8 @@ static int __init ffh_cstate_init(void)
 
 static void __exit ffh_cstate_exit(void)
 {
-       if (cpu_cstate_entry) {
-               free_percpu(cpu_cstate_entry);
-               cpu_cstate_entry = NULL;
-       }
+       free_percpu(cpu_cstate_entry);
+       cpu_cstate_entry = NULL;
 }
 
 arch_initcall(ffh_cstate_init);
index c984169..4b60af7 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
 #include <asm/apic.h>
+#include <asm/irq.h>
 
 #ifdef CONFIG_ACPI
 
@@ -49,6 +50,24 @@ static int __init check_bridge(int vendor, int device)
        return 0;
 }
 
+static void check_intel(void)
+{
+       u16 vendor, device;
+
+       vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID);
+
+       if (vendor != PCI_VENDOR_ID_INTEL)
+               return;
+
+       device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
+#ifdef CONFIG_SMP
+       if (device == PCI_DEVICE_ID_INTEL_E7320_MCH ||
+           device == PCI_DEVICE_ID_INTEL_E7520_MCH ||
+           device == PCI_DEVICE_ID_INTEL_E7525_MCH)
+               quirk_intel_irqbalance();
+#endif
+}
+
 void __init check_acpi_pci(void)
 {
        int num, slot, func;
@@ -60,6 +79,8 @@ void __init check_acpi_pci(void)
        if (!early_pci_allowed())
                return;
 
+       check_intel();
+
        /* Poor man's PCI discovery */
        for (num = 0; num < 32; num++) {
                for (slot = 0; slot < 32; slot++) {
index 535f979..9eca21b 100644 (file)
@@ -124,6 +124,20 @@ static unsigned char** find_nop_table(void)
 
 #endif /* CONFIG_X86_64 */
 
+static void nop_out(void *insns, unsigned int len)
+{
+       unsigned char **noptable = find_nop_table();
+
+       while (len > 0) {
+               unsigned int noplen = len;
+               if (noplen > ASM_NOP_MAX)
+                       noplen = ASM_NOP_MAX;
+               memcpy(insns, noptable[noplen], noplen);
+               insns += noplen;
+               len -= noplen;
+       }
+}
+
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
 extern u8 *__smp_locks[], *__smp_locks_end[];
@@ -138,10 +152,9 @@ extern u8 __smp_alt_begin[], __smp_alt_end[];
 
 void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 {
-       unsigned char **noptable = find_nop_table();
        struct alt_instr *a;
        u8 *instr;
-       int diff, i, k;
+       int diff;
 
        DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
        for (a = start; a < end; a++) {
@@ -159,13 +172,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 #endif
                memcpy(instr, a->replacement, a->replacementlen);
                diff = a->instrlen - a->replacementlen;
-               /* Pad the rest with nops */
-               for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
-                       k = diff;
-                       if (k > ASM_NOP_MAX)
-                               k = ASM_NOP_MAX;
-                       memcpy(a->instr + i, noptable[k], k);
-               }
+               nop_out(instr + a->replacementlen, diff);
        }
 }
 
@@ -209,7 +216,6 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
 
 static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
 {
-       unsigned char **noptable = find_nop_table();
        u8 **ptr;
 
        for (ptr = start; ptr < end; ptr++) {
@@ -217,7 +223,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end
                        continue;
                if (*ptr > text_end)
                        continue;
-               **ptr = noptable[1][0];
+               nop_out(*ptr, 1);
        };
 }
 
@@ -343,6 +349,40 @@ void alternatives_smp_switch(int smp)
 
 #endif
 
+#ifdef CONFIG_PARAVIRT
+void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
+{
+       struct paravirt_patch *p;
+
+       for (p = start; p < end; p++) {
+               unsigned int used;
+
+               used = paravirt_ops.patch(p->instrtype, p->clobbers, p->instr,
+                                         p->len);
+#ifdef CONFIG_DEBUG_PARAVIRT
+               {
+               int i;
+               /* Deliberately clobber regs using "not %reg" to find bugs. */
+               for (i = 0; i < 3; i++) {
+                       if (p->len - used >= 2 && (p->clobbers & (1 << i))) {
+                               memcpy(p->instr + used, "\xf7\xd0", 2);
+                               p->instr[used+1] |= i;
+                               used += 2;
+                       }
+               }
+               }
+#endif
+               /* Pad the rest with nops */
+               nop_out(p->instr + used, p->len - used);
+       }
+
+       /* Sync to be conservative, in case we patched following instructions */
+       sync_core();
+}
+extern struct paravirt_patch __start_parainstructions[],
+       __stop_parainstructions[];
+#endif /* CONFIG_PARAVIRT */
+
 void __init alternative_instructions(void)
 {
        unsigned long flags;
@@ -390,5 +430,6 @@ void __init alternative_instructions(void)
                alternatives_smp_switch(0);
        }
 #endif
+       apply_paravirt(__start_parainstructions, __stop_parainstructions);
        local_irq_restore(flags);
 }
index 2fd4b7d..776d9be 100644 (file)
@@ -647,23 +647,30 @@ static struct {
 static int lapic_suspend(struct sys_device *dev, pm_message_t state)
 {
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        apic_pm_state.apic_id = apic_read(APIC_ID);
        apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
        apic_pm_state.apic_ldr = apic_read(APIC_LDR);
        apic_pm_state.apic_dfr = apic_read(APIC_DFR);
        apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
        apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
-       apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+       if (maxlvt >= 4)
+               apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
        apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
        apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
        apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
        apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
        apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-       apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#endif
        
        local_irq_save(flags);
        disable_local_APIC();
@@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev)
 {
        unsigned int l, h;
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        local_irq_save(flags);
 
        /*
@@ -700,8 +710,12 @@ static int lapic_resume(struct sys_device *dev)
        apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
        apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
        apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
-       apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
-       apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
+#endif
+       if (maxlvt >= 4)
+               apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
        apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
        apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
        apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
index a60358f..a97847d 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/i8253.h>
+#include <asm/paravirt.h>
 
 #include "io_ports.h"
 
@@ -2235,7 +2236,7 @@ static int __init apm_init(void)
 
        dmi_check_system(apm_dmi_table);
 
-       if (apm_info.bios.version == 0) {
+       if (apm_info.bios.version == 0 || paravirt_enabled()) {
                printk(KERN_INFO "apm: BIOS not found.\n");
                return -ENODEV;
        }
index c80271f..1b2f3cd 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/elf.h>
+#include <asm/pda.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -51,13 +52,35 @@ void foo(void)
        OFFSET(TI_exec_domain, thread_info, exec_domain);
        OFFSET(TI_flags, thread_info, flags);
        OFFSET(TI_status, thread_info, status);
-       OFFSET(TI_cpu, thread_info, cpu);
        OFFSET(TI_preempt_count, thread_info, preempt_count);
        OFFSET(TI_addr_limit, thread_info, addr_limit);
        OFFSET(TI_restart_block, thread_info, restart_block);
        OFFSET(TI_sysenter_return, thread_info, sysenter_return);
        BLANK();
 
+       OFFSET(GDS_size, Xgt_desc_struct, size);
+       OFFSET(GDS_address, Xgt_desc_struct, address);
+       OFFSET(GDS_pad, Xgt_desc_struct, pad);
+       BLANK();
+
+       OFFSET(PT_EBX, pt_regs, ebx);
+       OFFSET(PT_ECX, pt_regs, ecx);
+       OFFSET(PT_EDX, pt_regs, edx);
+       OFFSET(PT_ESI, pt_regs, esi);
+       OFFSET(PT_EDI, pt_regs, edi);
+       OFFSET(PT_EBP, pt_regs, ebp);
+       OFFSET(PT_EAX, pt_regs, eax);
+       OFFSET(PT_DS,  pt_regs, xds);
+       OFFSET(PT_ES,  pt_regs, xes);
+       OFFSET(PT_GS,  pt_regs, xgs);
+       OFFSET(PT_ORIG_EAX, pt_regs, orig_eax);
+       OFFSET(PT_EIP, pt_regs, eip);
+       OFFSET(PT_CS,  pt_regs, xcs);
+       OFFSET(PT_EFLAGS, pt_regs, eflags);
+       OFFSET(PT_OLDESP, pt_regs, esp);
+       OFFSET(PT_OLDSS,  pt_regs, xss);
+       BLANK();
+
        OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
        OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
        BLANK();
@@ -74,4 +97,18 @@ void foo(void)
        DEFINE(VDSO_PRELINK, VDSO_PRELINK);
 
        OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+
+       BLANK();
+       OFFSET(PDA_cpu, i386_pda, cpu_number);
+       OFFSET(PDA_pcurrent, i386_pda, pcurrent);
+
+#ifdef CONFIG_PARAVIRT
+       BLANK();
+       OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled);
+       OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable);
+       OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable);
+       OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit);
+       OFFSET(PARAVIRT_iret, paravirt_ops, iret);
+       OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0);
+#endif
 }
index e475809..41cfea5 100644 (file)
@@ -104,10 +104,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                                        f_vide();
                                rdtscl(d2);
                                d = d2-d;
-                               
-                               /* Knock these two lines out if it debugs out ok */
-                               printk(KERN_INFO "AMD K6 stepping B detected - ");
-                               /* -- cut here -- */
+
                                if (d > 20*K6_BUG_LOOP) 
                                        printk("system stability may be impaired when more than 32 MB are used.\n");
                                else 
index d9f3e3c..1b34c56 100644 (file)
 #include <asm/apic.h>
 #include <mach_apic.h>
 #endif
+#include <asm/pda.h>
 
 #include "cpu.h"
 
 DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
 EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
 
-DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
-EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(_cpu_pda);
 
 static int cachesize_override __cpuinitdata = -1;
 static int disable_x86_fxsr __cpuinitdata;
@@ -235,29 +236,14 @@ static int __cpuinit have_cpuid_p(void)
        return flag_is_changeable_p(X86_EFLAGS_ID);
 }
 
-/* Do minimum CPU detection early.
-   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
-   The others are not touched to avoid unwanted side effects.
-
-   WARNING: this function is only called on the BP.  Don't add code here
-   that is supposed to run on all CPUs. */
-static void __init early_cpu_detect(void)
+void __init cpu_detect(struct cpuinfo_x86 *c)
 {
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       c->x86_cache_alignment = 32;
-
-       if (!have_cpuid_p())
-               return;
-
        /* Get vendor name */
        cpuid(0x00000000, &c->cpuid_level,
              (int *)&c->x86_vendor_id[0],
              (int *)&c->x86_vendor_id[8],
              (int *)&c->x86_vendor_id[4]);
 
-       get_cpu_vendor(c, 1);
-
        c->x86 = 4;
        if (c->cpuid_level >= 0x00000001) {
                u32 junk, tfms, cap0, misc;
@@ -274,6 +260,26 @@ static void __init early_cpu_detect(void)
        }
 }
 
+/* Do minimum CPU detection early.
+   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+   The others are not touched to avoid unwanted side effects.
+
+   WARNING: this function is only called on the BP.  Don't add code here
+   that is supposed to run on all CPUs. */
+static void __init early_cpu_detect(void)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+
+       c->x86_cache_alignment = 32;
+
+       if (!have_cpuid_p())
+               return;
+
+       cpu_detect(c);
+
+       get_cpu_vendor(c, 1);
+}
+
 static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 {
        u32 tfms, xlvl;
@@ -308,6 +314,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 #else
                        c->apicid = (ebx >> 24) & 0xFF;
 #endif
+                       if (c->x86_capability[0] & (1<<19))
+                               c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
                } else {
                        /* Have CPUID level 0 only - unheard of */
                        c->x86 = 4;
@@ -372,6 +380,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
        c->x86_vendor_id[0] = '\0'; /* Unset */
        c->x86_model_id[0] = '\0';  /* Unset */
        c->x86_max_cores = 1;
+       c->x86_clflush_size = 32;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
        if (!have_cpuid_p()) {
@@ -591,42 +600,24 @@ void __init early_cpu_init(void)
        disable_pse = 1;
 #endif
 }
-/*
- * cpu_init() initializes state that is per-CPU. Some data is already
- * initialized (naturally) in the bootstrap process, such as the GDT
- * and IDT. We reload them nevertheless, this function acts as a
- * 'CPU state barrier', nothing should get across.
- */
-void __cpuinit cpu_init(void)
+
+/* Make sure %gs is initialized properly in idle threads */
+struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
-       int cpu = smp_processor_id();
-       struct tss_struct * t = &per_cpu(init_tss, cpu);
-       struct thread_struct *thread = &current->thread;
-       struct desc_struct *gdt;
-       __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       memset(regs, 0, sizeof(struct pt_regs));
+       regs->xgs = __KERNEL_PDA;
+       return regs;
+}
 
-       if (cpu_test_and_set(cpu, cpu_initialized)) {
-               printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
-               for (;;) local_irq_enable();
-       }
-       printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+static __cpuinit int alloc_gdt(int cpu)
+{
+       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       struct desc_struct *gdt;
+       struct i386_pda *pda;
 
-       if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
-               clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
-       if (tsc_disable && cpu_has_tsc) {
-               printk(KERN_NOTICE "Disabling TSC...\n");
-               /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
-               clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
-               set_in_cr4(X86_CR4_TSD);
-       }
+       gdt = (struct desc_struct *)cpu_gdt_descr->address;
+       pda = cpu_pda(cpu);
 
-       /* The CPU hotplug case */
-       if (cpu_gdt_descr->address) {
-               gdt = (struct desc_struct *)cpu_gdt_descr->address;
-               memset(gdt, 0, PAGE_SIZE);
-               goto old_gdt;
-       }
        /*
         * This is a horrible hack to allocate the GDT.  The problem
         * is that cpu_init() is called really early for the boot CPU
@@ -634,43 +625,130 @@ void __cpuinit cpu_init(void)
         * CPUs, when bootmem will have gone away
         */
        if (NODE_DATA(0)->bdata->node_bootmem_map) {
-               gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
-               /* alloc_bootmem_pages panics on failure, so no check */
+               BUG_ON(gdt != NULL || pda != NULL);
+
+               gdt = alloc_bootmem_pages(PAGE_SIZE);
+               pda = alloc_bootmem(sizeof(*pda));
+               /* alloc_bootmem(_pages) panics on failure, so no check */
+
                memset(gdt, 0, PAGE_SIZE);
+               memset(pda, 0, sizeof(*pda));
        } else {
-               gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
-               if (unlikely(!gdt)) {
-                       printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
-                       for (;;)
-                               local_irq_enable();
+               /* GDT and PDA might already have been allocated if
+                  this is a CPU hotplug re-insertion. */
+               if (gdt == NULL)
+                       gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
+
+               if (pda == NULL)
+                       pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu));
+
+               if (unlikely(!gdt || !pda)) {
+                       free_pages((unsigned long)gdt, 0);
+                       kfree(pda);
+                       return 0;
                }
        }
-old_gdt:
+
+       cpu_gdt_descr->address = (unsigned long)gdt;
+       cpu_pda(cpu) = pda;
+
+       return 1;
+}
+
+/* Initial PDA used by boot CPU */
+struct i386_pda boot_pda = {
+       ._pda = &boot_pda,
+       .cpu_number = 0,
+       .pcurrent = &init_task,
+};
+
+static inline void set_kernel_gs(void)
+{
+       /* Set %gs for this CPU's PDA.  Memory clobber is to create a
+          barrier with respect to any PDA operations, so the compiler
+          doesn't move any before here. */
+       asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
+}
+
+/* Initialize the CPU's GDT and PDA.  The boot CPU does this for
+   itself, but secondaries find this done for them. */
+__cpuinit int init_gdt(int cpu, struct task_struct *idle)
+{
+       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       struct desc_struct *gdt;
+       struct i386_pda *pda;
+
+       /* For non-boot CPUs, the GDT and PDA should already have been
+          allocated. */
+       if (!alloc_gdt(cpu)) {
+               printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu);
+               return 0;
+       }
+
+       gdt = (struct desc_struct *)cpu_gdt_descr->address;
+       pda = cpu_pda(cpu);
+
+       BUG_ON(gdt == NULL || pda == NULL);
+
        /*
         * Initialize the per-CPU GDT with the boot GDT,
         * and set up the GDT descriptor:
         */
        memcpy(gdt, cpu_gdt_table, GDT_SIZE);
+       cpu_gdt_descr->size = GDT_SIZE - 1;
 
-       /* Set up GDT entry for 16bit stack */
-       *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
-               ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
-               ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
-               (CPU_16BIT_STACK_SIZE - 1);
+       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
+                       (u32 *)&gdt[GDT_ENTRY_PDA].b,
+                       (unsigned long)pda, sizeof(*pda) - 1,
+                       0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
 
-       cpu_gdt_descr->size = GDT_SIZE - 1;
-       cpu_gdt_descr->address = (unsigned long)gdt;
+       memset(pda, 0, sizeof(*pda));
+       pda->_pda = pda;
+       pda->cpu_number = cpu;
+       pda->pcurrent = idle;
+
+       return 1;
+}
+
+/* Common CPU init for both boot and secondary CPUs */
+static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+{
+       struct tss_struct * t = &per_cpu(init_tss, cpu);
+       struct thread_struct *thread = &curr->thread;
+       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
 
+       /* Reinit these anyway, even if they've already been done (on
+          the boot CPU, this will transition from the boot gdt+pda to
+          the real ones). */
        load_gdt(cpu_gdt_descr);
+       set_kernel_gs();
+
+       if (cpu_test_and_set(cpu, cpu_initialized)) {
+               printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+               for (;;) local_irq_enable();
+       }
+
+       printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+
+       if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
+               clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+       if (tsc_disable && cpu_has_tsc) {
+               printk(KERN_NOTICE "Disabling TSC...\n");
+               /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
+               clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+               set_in_cr4(X86_CR4_TSD);
+       }
+
        load_idt(&idt_descr);
 
        /*
         * Set up and load the per-CPU TSS and LDT
         */
        atomic_inc(&init_mm.mm_count);
-       current->active_mm = &init_mm;
-       BUG_ON(current->mm);
-       enter_lazy_tlb(&init_mm, current);
+       curr->active_mm = &init_mm;
+       if (curr->mm)
+               BUG();
+       enter_lazy_tlb(&init_mm, curr);
 
        load_esp0(t, thread);
        set_tss_desc(cpu,t);
@@ -682,8 +760,8 @@ old_gdt:
        __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 #endif
 
-       /* Clear %fs and %gs. */
-       asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
+       /* Clear %fs. */
+       asm volatile ("mov %0, %%fs" : : "r" (0));
 
        /* Clear all 6 debug registers: */
        set_debugreg(0, 0);
@@ -701,6 +779,37 @@ old_gdt:
        mxcsr_feature_mask_init();
 }
 
+/* Entrypoint to initialize secondary CPU */
+void __cpuinit secondary_cpu_init(void)
+{
+       int cpu = smp_processor_id();
+       struct task_struct *curr = current;
+
+       _cpu_init(cpu, curr);
+}
+
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process, such as the GDT
+ * and IDT. We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+void __cpuinit cpu_init(void)
+{
+       int cpu = smp_processor_id();
+       struct task_struct *curr = current;
+
+       /* Set up the real GDT and PDA, so we can transition from the
+          boot versions. */
+       if (!init_gdt(cpu, curr)) {
+               /* failed to allocate something; not much we can do... */
+               for (;;)
+                       local_irq_enable();
+       }
+
+       _cpu_init(cpu, curr);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 void __cpuinit cpu_uninit(void)
 {
index 94a95aa..56fe265 100644 (file)
@@ -107,7 +107,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
         * Note that the workaround only should be initialized once...
         */
        c->f00f_bug = 0;
-       if ( c->x86 == 5 ) {
+       if (!paravirt_enabled() && c->x86 == 5) {
                static int f00f_workaround_enabled = 0;
 
                c->f00f_bug = 1;
@@ -195,8 +195,16 @@ 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 (cpu_has_ds) {
+               unsigned int l1;
+               rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+               if (!(l1 & (1<<11)))
+                       set_bit(X86_FEATURE_BTS, c->x86_capability);
+               if (!(l1 & (1<<12)))
+                       set_bit(X86_FEATURE_PEBS, c->x86_capability);
+       }
+}
 
 static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
 {
index 5c43be4..80b4c5d 100644 (file)
@@ -480,12 +480,10 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
        if (num_cache_leaves == 0)
                return -ENOENT;
 
-       cpuid4_info[cpu] = kmalloc(
+       cpuid4_info[cpu] = kzalloc(
            sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
        if (unlikely(cpuid4_info[cpu] == NULL))
                return -ENOMEM;
-       memset(cpuid4_info[cpu], 0,
-           sizeof(struct _cpuid4_info) * num_cache_leaves);
 
        oldmask = current->cpus_allowed;
        retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
@@ -658,17 +656,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
                return -ENOENT;
 
        /* Allocate all required memory */
-       cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL);
+       cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
        if (unlikely(cache_kobject[cpu] == NULL))
                goto err_out;
-       memset(cache_kobject[cpu], 0, sizeof(struct kobject));
 
-       index_kobject[cpu] = kmalloc(
+       index_kobject[cpu] = kzalloc(
            sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
        if (unlikely(index_kobject[cpu] == NULL))
                goto err_out;
-       memset(index_kobject[cpu], 0,
-           sizeof(struct _index_kobject) * num_cache_leaves);
 
        return 0;
 
index 1f9153a..6b5d351 100644 (file)
@@ -51,10 +51,10 @@ static void mce_checkregs (void *info)
        }
 }
 
-static void mce_work_fn(void *data);
-static DECLARE_WORK(mce_work, mce_work_fn, NULL);
+static void mce_work_fn(struct work_struct *work);
+static DECLARE_DELAYED_WORK(mce_work, mce_work_fn);
 
-static void mce_work_fn(void *data)
+static void mce_work_fn(struct work_struct *work)
 { 
        on_each_cpu(mce_checkregs, NULL, 1, 1);
        schedule_delayed_work(&mce_work, MCE_RATE);
index bad8b44..065005c 100644 (file)
@@ -116,7 +116,6 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
        return sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
 {
        return sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
@@ -153,7 +152,6 @@ 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)
 {
index a25b701..191fc05 100644 (file)
@@ -1,5 +1,3 @@
 obj-y          := main.o if.o generic.o state.o
-obj-y          += amd.o
-obj-y          += cyrix.o
-obj-y          += centaur.o
+obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o
 
index 1a1e04b..0949cdb 100644 (file)
@@ -7,7 +7,7 @@
 
 static void
 amd_get_mtrr(unsigned int reg, unsigned long *base,
-            unsigned int *size, mtrr_type * type)
+            unsigned long *size, mtrr_type * type)
 {
        unsigned long low, high;
 
index 33f00ac..cb9aa3a 100644 (file)
@@ -17,7 +17,7 @@ static u8 centaur_mcr_type;   /* 0 for winchip, 1 for winchip2 */
  */
 
 static int
-centaur_get_free_region(unsigned long base, unsigned long size)
+centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 /*  [SUMMARY] Get a free MTRR.
     <base> The starting (base) address of the region.
     <size> The size (in bytes) of the region.
@@ -26,10 +26,11 @@ centaur_get_free_region(unsigned long base, unsigned long size)
 {
        int i, max;
        mtrr_type ltype;
-       unsigned long lbase;
-       unsigned int lsize;
+       unsigned long lbase, lsize;
 
        max = num_var_ranges;
+       if (replace_reg >= 0 && replace_reg < max)
+               return replace_reg;
        for (i = 0; i < max; ++i) {
                if (centaur_mcr_reserved & (1 << i))
                        continue;
@@ -49,7 +50,7 @@ mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 
 static void
 centaur_get_mcr(unsigned int reg, unsigned long *base,
-               unsigned int *size, mtrr_type * type)
+               unsigned long *size, mtrr_type * type)
 {
        *base = centaur_mcr[reg].high >> PAGE_SHIFT;
        *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
index 9027a98..0737a59 100644 (file)
@@ -9,7 +9,7 @@ int arr3_protected;
 
 static void
 cyrix_get_arr(unsigned int reg, unsigned long *base,
-             unsigned int *size, mtrr_type * type)
+             unsigned long *size, mtrr_type * type)
 {
        unsigned long flags;
        unsigned char arr, ccr3, rcr, shift;
@@ -77,7 +77,7 @@ cyrix_get_arr(unsigned int reg, unsigned long *base,
 }
 
 static int
-cyrix_get_free_region(unsigned long base, unsigned long size)
+cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 /*  [SUMMARY] Get a free ARR.
     <base> The starting (base) address of the region.
     <size> The size (in bytes) of the region.
@@ -86,9 +86,24 @@ cyrix_get_free_region(unsigned long base, unsigned long size)
 {
        int i;
        mtrr_type ltype;
-       unsigned long lbase;
-       unsigned int  lsize;
+       unsigned long lbase, lsize;
 
+       switch (replace_reg) {
+       case 7:
+               if (size < 0x40)
+                       break;
+       case 6:
+       case 5:
+       case 4:
+               return replace_reg;
+       case 3:
+               if (arr3_protected)
+                       break;
+       case 2:
+       case 1:
+       case 0:
+               return replace_reg;
+       }
        /* If we are to set up a region >32M then look at ARR7 immediately */
        if (size > 0x2000) {
                cyrix_get_arr(7, &lbase, &lsize, &ltype);
@@ -214,7 +229,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
 
 typedef struct {
        unsigned long base;
-       unsigned int size;
+       unsigned long size;
        mtrr_type type;
 } arr_state_t;
 
index 0b61eed..f77fc53 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
@@ -15,12 +16,19 @@ struct mtrr_state {
        struct mtrr_var_range *var_ranges;
        mtrr_type fixed_ranges[NUM_FIXED_RANGES];
        unsigned char enabled;
+       unsigned char have_fixed;
        mtrr_type def_type;
 };
 
 static unsigned long smp_changes_mask;
 static struct mtrr_state mtrr_state = {};
 
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "mtrr."
+
+static __initdata int mtrr_show;
+module_param_named(show, mtrr_show, bool, 0);
+
 /*  Get the MSR pair relating to a var range  */
 static void __init
 get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
@@ -43,6 +51,14 @@ get_fixed_ranges(mtrr_type * frs)
                rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]);
 }
 
+static void __init print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+{
+       unsigned i;
+
+       for (i = 0; i < 8; ++i, ++types, base += step)
+               printk(KERN_INFO "MTRR %05X-%05X %s\n", base, base + step - 1, mtrr_attrib_to_str(*types));
+}
+
 /*  Grab all of the MTRR state for this CPU into *state  */
 void __init get_mtrr_state(void)
 {
@@ -58,13 +74,49 @@ void __init get_mtrr_state(void)
        } 
        vrs = mtrr_state.var_ranges;
 
+       rdmsr(MTRRcap_MSR, lo, dummy);
+       mtrr_state.have_fixed = (lo >> 8) & 1;
+
        for (i = 0; i < num_var_ranges; i++)
                get_mtrr_var_range(i, &vrs[i]);
-       get_fixed_ranges(mtrr_state.fixed_ranges);
+       if (mtrr_state.have_fixed)
+               get_fixed_ranges(mtrr_state.fixed_ranges);
 
        rdmsr(MTRRdefType_MSR, lo, dummy);
        mtrr_state.def_type = (lo & 0xff);
        mtrr_state.enabled = (lo & 0xc00) >> 10;
+
+       if (mtrr_show) {
+               int high_width;
+
+               printk(KERN_INFO "MTRR default type: %s\n", mtrr_attrib_to_str(mtrr_state.def_type));
+               if (mtrr_state.have_fixed) {
+                       printk(KERN_INFO "MTRR fixed ranges %sabled:\n",
+                              mtrr_state.enabled & 1 ? "en" : "dis");
+                       print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
+                       for (i = 0; i < 2; ++i)
+                               print_fixed(0x80000 + i * 0x20000, 0x04000, mtrr_state.fixed_ranges + (i + 1) * 8);
+                       for (i = 0; i < 8; ++i)
+                               print_fixed(0xC0000 + i * 0x08000, 0x01000, mtrr_state.fixed_ranges + (i + 3) * 8);
+               }
+               printk(KERN_INFO "MTRR variable ranges %sabled:\n",
+                      mtrr_state.enabled & 2 ? "en" : "dis");
+               high_width = ((size_or_mask ? ffs(size_or_mask) - 1 : 32) - (32 - PAGE_SHIFT) + 3) / 4;
+               for (i = 0; i < num_var_ranges; ++i) {
+                       if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
+                               printk(KERN_INFO "MTRR %u base %0*X%05X000 mask %0*X%05X000 %s\n",
+                                      i,
+                                      high_width,
+                                      mtrr_state.var_ranges[i].base_hi,
+                                      mtrr_state.var_ranges[i].base_lo >> 12,
+                                      high_width,
+                                      mtrr_state.var_ranges[i].mask_hi,
+                                      mtrr_state.var_ranges[i].mask_lo >> 12,
+                                      mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
+                       else
+                               printk(KERN_INFO "MTRR %u disabled\n", i);
+               }
+       }
 }
 
 /*  Some BIOS's are fucked and don't set all MTRRs the same!  */
@@ -95,7 +147,7 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
                        smp_processor_id(), msr, a, b);
 }
 
-int generic_get_free_region(unsigned long base, unsigned long size)
+int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 /*  [SUMMARY] Get a free MTRR.
     <base> The starting (base) address of the region.
     <size> The size (in bytes) of the region.
@@ -104,10 +156,11 @@ int generic_get_free_region(unsigned long base, unsigned long size)
 {
        int i, max;
        mtrr_type ltype;
-       unsigned long lbase;
-       unsigned lsize;
+       unsigned long lbase, lsize;
 
        max = num_var_ranges;
+       if (replace_reg >= 0 && replace_reg < max)
+               return replace_reg;
        for (i = 0; i < max; ++i) {
                mtrr_if->get(i, &lbase, &lsize, &ltype);
                if (lsize == 0)
@@ -117,7 +170,7 @@ int generic_get_free_region(unsigned long base, unsigned long size)
 }
 
 static void generic_get_mtrr(unsigned int reg, unsigned long *base,
-                            unsigned int *size, mtrr_type * type)
+                            unsigned long *size, mtrr_type *type)
 {
        unsigned int mask_lo, mask_hi, base_lo, base_hi;
 
@@ -202,7 +255,9 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
        return changed;
 }
 
-static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
+static u32 deftype_lo, deftype_hi;
+
+static unsigned long set_mtrr_state(void)
 /*  [SUMMARY] Set the MTRR state for this CPU.
     <state> The MTRR state information to read.
     <ctxt> Some relevant CPU context.
@@ -217,14 +272,14 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
                if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i]))
                        change_mask |= MTRR_CHANGE_MASK_VARIABLE;
 
-       if (set_fixed_ranges(mtrr_state.fixed_ranges))
+       if (mtrr_state.have_fixed && set_fixed_ranges(mtrr_state.fixed_ranges))
                change_mask |= MTRR_CHANGE_MASK_FIXED;
 
        /*  Set_mtrr_restore restores the old value of MTRRdefType,
           so to set it we fiddle with the saved value  */
        if ((deftype_lo & 0xff) != mtrr_state.def_type
            || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
-               deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10);
+               deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type | (mtrr_state.enabled << 10);
                change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
        }
 
@@ -233,7 +288,6 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
 
 
 static unsigned long cr4 = 0;
-static u32 deftype_lo, deftype_hi;
 static DEFINE_SPINLOCK(set_atomicity_lock);
 
 /*
@@ -271,7 +325,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
        rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
 
        /*  Disable MTRRs, and set the default type to uncached  */
-       mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
+       mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & ~0xcff, deftype_hi);
 }
 
 static void post_set(void) __releases(set_atomicity_lock)
@@ -300,7 +354,7 @@ static void generic_set_all(void)
        prepare_set();
 
        /* Actually set the state */
-       mask = set_mtrr_state(deftype_lo,deftype_hi);
+       mask = set_mtrr_state();
 
        post_set();
        local_irq_restore(flags);
@@ -366,7 +420,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
                        printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
                        return -EINVAL;
                }
-               if (!(base + size < 0x70000000 || base > 0x7003FFFF) &&
+               if (!(base + size < 0x70000 || base > 0x7003F) &&
                    (type == MTRR_TYPE_WRCOMB
                     || type == MTRR_TYPE_WRBACK)) {
                        printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
index 5ac051b..5ae1705 100644 (file)
@@ -17,7 +17,7 @@ extern unsigned int *usage_table;
 
 #define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private)
 
-static char *mtrr_strings[MTRR_NUM_TYPES] =
+static const char *const mtrr_strings[MTRR_NUM_TYPES] =
 {
     "uncachable",               /* 0 */
     "write-combining",          /* 1 */
@@ -28,7 +28,7 @@ static char *mtrr_strings[MTRR_NUM_TYPES] =
     "write-back",               /* 6 */
 };
 
-char *mtrr_attrib_to_str(int x)
+const char *mtrr_attrib_to_str(int x)
 {
        return (x <= 6) ? mtrr_strings[x] : "?";
 }
@@ -44,10 +44,9 @@ mtrr_file_add(unsigned long base, unsigned long size,
 
        max = num_var_ranges;
        if (fcount == NULL) {
-               fcount = kmalloc(max * sizeof *fcount, GFP_KERNEL);
+               fcount = kzalloc(max * sizeof *fcount, GFP_KERNEL);
                if (!fcount)
                        return -ENOMEM;
-               memset(fcount, 0, max * sizeof *fcount);
                FILE_FCOUNT(file) = fcount;
        }
        if (!page) {
@@ -155,6 +154,7 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 {
        int err = 0;
        mtrr_type type;
+       unsigned long size;
        struct mtrr_sentry sentry;
        struct mtrr_gentry gentry;
        void __user *arg = (void __user *) __arg;
@@ -235,15 +235,15 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
        case MTRRIOC_GET_ENTRY:
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
-               mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
+               mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
 
                /* Hide entries that go above 4GB */
-               if (gentry.base + gentry.size > 0x100000
-                   || gentry.size == 0x100000)
+               if (gentry.base + size - 1 >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT))
+                   || size >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT)))
                        gentry.base = gentry.size = gentry.type = 0;
                else {
                        gentry.base <<= PAGE_SHIFT;
-                       gentry.size <<= PAGE_SHIFT;
+                       gentry.size = size << PAGE_SHIFT;
                        gentry.type = type;
                }
 
@@ -273,8 +273,14 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
        case MTRRIOC_GET_PAGE_ENTRY:
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
-               mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
-               gentry.type = type;
+               mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
+               /* Hide entries that would overflow */
+               if (size != (__typeof__(gentry.size))size)
+                       gentry.base = gentry.size = gentry.type = 0;
+               else {
+                       gentry.size = size;
+                       gentry.type = type;
+               }
                break;
        }
 
@@ -353,8 +359,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset)
        char factor;
        int i, max, len;
        mtrr_type type;
-       unsigned long base;
-       unsigned int size;
+       unsigned long base, size;
 
        len = 0;
        max = num_var_ranges;
@@ -373,7 +378,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset)
                        }
                        /* RED-PEN: base can be > 32bit */ 
                        len += seq_printf(seq, 
-                                  "reg%02i: base=0x%05lx000 (%4liMB), size=%4i%cB: %s, count=%d\n",
+                                  "reg%02i: base=0x%05lx000 (%4luMB), size=%4lu%cB: %s, count=%d\n",
                             i, base, base >> (20 - PAGE_SHIFT), size, factor,
                             mtrr_attrib_to_str(type), usage_table[i]);
                }
index fff90bd..16bb7ea 100644 (file)
@@ -59,7 +59,11 @@ struct mtrr_ops * mtrr_if = NULL;
 static void set_mtrr(unsigned int reg, unsigned long base,
                     unsigned long size, mtrr_type type);
 
+#ifndef CONFIG_X86_64
 extern int arr3_protected;
+#else
+#define arr3_protected 0
+#endif
 
 void set_mtrr_ops(struct mtrr_ops * ops)
 {
@@ -168,6 +172,13 @@ static void ipi_handler(void *info)
 
 #endif
 
+static inline int types_compatible(mtrr_type type1, mtrr_type type2) {
+       return type1 == MTRR_TYPE_UNCACHABLE ||
+              type2 == MTRR_TYPE_UNCACHABLE ||
+              (type1 == MTRR_TYPE_WRTHROUGH && type2 == MTRR_TYPE_WRBACK) ||
+              (type1 == MTRR_TYPE_WRBACK && type2 == MTRR_TYPE_WRTHROUGH);
+}
+
 /**
  * set_mtrr - update mtrrs on all processors
  * @reg:       mtrr in question
@@ -263,8 +274,8 @@ static void set_mtrr(unsigned int reg, unsigned long base,
 
 /**
  *     mtrr_add_page - Add a memory type region
- *     @base: Physical base address of region in pages (4 KB)
- *     @size: Physical size of region in pages (4 KB)
+ *     @base: Physical base address of region in pages (in units of 4 kB!)
+ *     @size: Physical size of region in pages (4 kB)
  *     @type: Type of MTRR desired
  *     @increment: If this is true do usage counting on the region
  *
@@ -300,11 +311,9 @@ static void set_mtrr(unsigned int reg, unsigned long base,
 int mtrr_add_page(unsigned long base, unsigned long size, 
                  unsigned int type, char increment)
 {
-       int i;
+       int i, replace, error;
        mtrr_type ltype;
-       unsigned long lbase;
-       unsigned int lsize;
-       int error;
+       unsigned long lbase, lsize;
 
        if (!mtrr_if)
                return -ENXIO;
@@ -324,12 +333,18 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                return -ENOSYS;
        }
 
+       if (!size) {
+               printk(KERN_WARNING "mtrr: zero sized request\n");
+               return -EINVAL;
+       }
+
        if (base & size_or_mask || size & size_or_mask) {
                printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n");
                return -EINVAL;
        }
 
        error = -EINVAL;
+       replace = -1;
 
        /* No CPU hotplug when we change MTRR entries */
        lock_cpu_hotplug();
@@ -337,21 +352,28 @@ int mtrr_add_page(unsigned long base, unsigned long size,
        mutex_lock(&mtrr_mutex);
        for (i = 0; i < num_var_ranges; ++i) {
                mtrr_if->get(i, &lbase, &lsize, &ltype);
-               if (base >= lbase + lsize)
-                       continue;
-               if ((base < lbase) && (base + size <= lbase))
+               if (!lsize || base > lbase + lsize - 1 || base + size - 1 < lbase)
                        continue;
                /*  At this point we know there is some kind of overlap/enclosure  */
-               if ((base < lbase) || (base + size > lbase + lsize)) {
+               if (base < lbase || base + size - 1 > lbase + lsize - 1) {
+                       if (base <= lbase && base + size - 1 >= lbase + lsize - 1) {
+                               /*  New region encloses an existing region  */
+                               if (type == ltype) {
+                                       replace = replace == -1 ? i : -2;
+                                       continue;
+                               }
+                               else if (types_compatible(type, ltype))
+                                       continue;
+                       }
                        printk(KERN_WARNING
                               "mtrr: 0x%lx000,0x%lx000 overlaps existing"
-                              " 0x%lx000,0x%x000\n", base, size, lbase,
+                              " 0x%lx000,0x%lx000\n", base, size, lbase,
                               lsize);
                        goto out;
                }
                /*  New region is enclosed by an existing region  */
                if (ltype != type) {
-                       if (type == MTRR_TYPE_UNCACHABLE)
+                       if (types_compatible(type, ltype))
                                continue;
                        printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
                             base, size, mtrr_attrib_to_str(ltype),
@@ -364,10 +386,18 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                goto out;
        }
        /*  Search for an empty MTRR  */
-       i = mtrr_if->get_free_region(base, size);
+       i = mtrr_if->get_free_region(base, size, replace);
        if (i >= 0) {
                set_mtrr(i, base, size, type);
-               usage_table[i] = 1;
+               if (likely(replace < 0))
+                       usage_table[i] = 1;
+               else {
+                       usage_table[i] = usage_table[replace] + !!increment;
+                       if (unlikely(replace != i)) {
+                               set_mtrr(replace, 0, 0, 0);
+                               usage_table[replace] = 0;
+                       }
+               }
        } else
                printk(KERN_INFO "mtrr: no more MTRRs available\n");
        error = i;
@@ -455,8 +485,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
 {
        int i, max;
        mtrr_type ltype;
-       unsigned long lbase;
-       unsigned int lsize;
+       unsigned long lbase, lsize;
        int error = -EINVAL;
 
        if (!mtrr_if)
@@ -544,9 +573,11 @@ extern void centaur_init_mtrr(void);
 
 static void __init init_ifs(void)
 {
+#ifndef CONFIG_X86_64
        amd_init_mtrr();
        cyrix_init_mtrr();
        centaur_init_mtrr();
+#endif
 }
 
 /* The suspend/resume methods are only for CPU without MTRR. CPU using generic
@@ -555,7 +586,7 @@ static void __init init_ifs(void)
 struct mtrr_value {
        mtrr_type       ltype;
        unsigned long   lbase;
-       unsigned int    lsize;
+       unsigned long   lsize;
 };
 
 static struct mtrr_value * mtrr_state;
@@ -565,10 +596,8 @@ static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
        int i;
        int size = num_var_ranges * sizeof(struct mtrr_value);
 
-       mtrr_state = kmalloc(size,GFP_ATOMIC);
-       if (mtrr_state)
-               memset(mtrr_state,0,size);
-       else
+       mtrr_state = kzalloc(size,GFP_ATOMIC);
+       if (!mtrr_state)
                return -ENOMEM;
 
        for (i = 0; i < num_var_ranges; i++) {
index 99c9f26..d61ea9d 100644 (file)
@@ -43,15 +43,16 @@ struct mtrr_ops {
        void    (*set_all)(void);
 
        void    (*get)(unsigned int reg, unsigned long *base,
-                      unsigned int *size, mtrr_type * type);
-       int     (*get_free_region) (unsigned long base, unsigned long size);
-
+                      unsigned long *size, mtrr_type * type);
+       int     (*get_free_region)(unsigned long base, unsigned long size,
+                                  int replace_reg);
        int     (*validate_add_page)(unsigned long base, unsigned long size,
                                     unsigned int type);
        int     (*have_wrcomb)(void);
 };
 
-extern int generic_get_free_region(unsigned long base, unsigned long size);
+extern int generic_get_free_region(unsigned long base, unsigned long size,
+                                  int replace_reg);
 extern int generic_validate_add_page(unsigned long base, unsigned long size,
                                     unsigned int type);
 
@@ -62,17 +63,17 @@ extern int positive_have_wrcomb(void);
 /* library functions for processor-specific routines */
 struct set_mtrr_context {
        unsigned long flags;
-       unsigned long deftype_lo;
-       unsigned long deftype_hi;
        unsigned long cr4val;
-       unsigned long ccr3;
+       u32 deftype_lo;
+       u32 deftype_hi;
+       u32 ccr3;
 };
 
 struct mtrr_var_range {
-       unsigned long base_lo;
-       unsigned long base_hi;
-       unsigned long mask_lo;
-       unsigned long mask_hi;
+       u32 base_lo;
+       u32 base_hi;
+       u32 mask_lo;
+       u32 mask_hi;
 };
 
 void set_mtrr_done(struct set_mtrr_context *ctxt);
@@ -92,6 +93,6 @@ extern struct mtrr_ops * mtrr_if;
 extern unsigned int num_var_ranges;
 
 void mtrr_state_warn(void);
-char *mtrr_attrib_to_str(int x);
+const char *mtrr_attrib_to_str(int x);
 void mtrr_wrmsr(unsigned, unsigned, unsigned);
 
index 76aac08..6624d85 100644 (file)
@@ -152,9 +152,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                                seq_printf(m, " [%d]", i);
                }
 
-       seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
+       seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
                     c->loops_per_jiffy/(500000/HZ),
                     (c->loops_per_jiffy/(5000/HZ)) % 100);
+       seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
 
        return 0;
 }
index ab0c327..51130b3 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
-#include <linux/fs.h>
 #include <linux/device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
@@ -117,7 +116,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
        char __user *tmp = buf;
        u32 data[4];
        u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
+       int cpu = iminor(file->f_path.dentry->d_inode);
 
        if (count % 16)
                return -EINVAL; /* Invalid chunk size */
@@ -135,7 +134,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
 
 static int cpuid_open(struct inode *inode, struct file *file)
 {
-       unsigned int cpu = iminor(file->f_dentry->d_inode);
+       unsigned int cpu = iminor(file->f_path.dentry->d_inode);
        struct cpuinfo_x86 *c = &(cpu_data)[cpu];
 
        if (cpu >= NR_CPUS || !cpu_online(cpu))
@@ -167,7 +166,6 @@ static int cpuid_device_create(int i)
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
@@ -187,7 +185,6 @@ static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier =
 {
        .notifier_call = cpuid_class_cpu_callback,
 };
-#endif /* !CONFIG_HOTPLUG_CPU */
 
 static int __init cpuid_init(void)
 {
index 144b432..a5e0e99 100644 (file)
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
-                                                              size_t data_len)
-{
-       struct elf_note note;
-
-       note.n_namesz = strlen(name) + 1;
-       note.n_descsz = data_len;
-       note.n_type   = type;
-       memcpy(buf, &note, sizeof(note));
-       buf += (sizeof(note) +3)/4;
-       memcpy(buf, name, note.n_namesz);
-       buf += (note.n_namesz + 3)/4;
-       memcpy(buf, data, note.n_descsz);
-       buf += (note.n_descsz + 3)/4;
-
-       return buf;
-}
-
-static void final_note(u32 *buf)
-{
-       struct elf_note note;
-
-       note.n_namesz = 0;
-       note.n_descsz = 0;
-       note.n_type   = 0;
-       memcpy(buf, &note, sizeof(note));
-}
-
-static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
-{
-       struct elf_prstatus prstatus;
-       u32 *buf;
-
-       if ((cpu < 0) || (cpu >= NR_CPUS))
-               return;
-
-       /* Using ELF notes here is opportunistic.
-        * I need a well defined structure format
-        * 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, so there is no need to invent something new.
-        */
-       buf = (u32*)per_cpu_ptr(crash_notes, cpu);
-       if (!buf)
-               return;
-       memset(&prstatus, 0, sizeof(prstatus));
-       prstatus.pr_pid = current->pid;
-       elf_core_copy_regs(&prstatus.pr_reg, regs);
-       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
-                               sizeof(prstatus));
-       final_note(buf);
-}
-
-static void crash_save_self(struct pt_regs *regs)
-{
-       int cpu;
-
-       cpu = safe_smp_processor_id();
-       crash_save_this_cpu(regs, cpu);
-}
-
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 static atomic_t waiting_for_crash_ipi;
 
@@ -121,7 +59,7 @@ static int crash_nmi_callback(struct notifier_block *self,
                crash_fixup_ss_esp(&fixed_regs, regs);
                regs = &fixed_regs;
        }
-       crash_save_this_cpu(regs, cpu);
+       crash_save_cpu(regs, cpu);
        disable_local_APIC();
        atomic_dec(&waiting_for_crash_ipi);
        /* Assume hlt works */
@@ -195,5 +133,5 @@ void machine_crash_shutdown(struct pt_regs *regs)
 #if defined(CONFIG_X86_IO_APIC)
        disable_IO_APIC();
 #endif
-       crash_save_self(regs);
+       crash_save_cpu(regs, safe_smp_processor_id());
 }
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c
new file mode 100644 (file)
index 0000000..2f7d0a9
--- /dev/null
@@ -0,0 +1,894 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/efi.h>
+#include <linux/pfn.h>
+#include <linux/uaccess.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/e820.h>
+
+#ifdef CONFIG_EFI
+int efi_enabled = 0;
+EXPORT_SYMBOL(efi_enabled);
+#endif
+
+struct e820map e820;
+struct change_member {
+       struct e820entry *pbios; /* pointer to original bios entry */
+       unsigned long long addr; /* address for this change point */
+};
+static struct change_member change_point_list[2*E820MAX] __initdata;
+static struct change_member *change_point[2*E820MAX] __initdata;
+static struct e820entry *overlap_list[E820MAX] __initdata;
+static struct e820entry new_bios[E820MAX] __initdata;
+/* For PCI or other memory-mapped resources */
+unsigned long pci_mem_start = 0x10000000;
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_mem_start);
+#endif
+extern int user_defined_memmap;
+struct resource data_resource = {
+       .name   = "Kernel data",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+struct resource code_resource = {
+       .name   = "Kernel code",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource system_rom_resource = {
+       .name   = "System ROM",
+       .start  = 0xf0000,
+       .end    = 0xfffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource extension_rom_resource = {
+       .name   = "Extension ROM",
+       .start  = 0xe0000,
+       .end    = 0xeffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource adapter_rom_resources[] = { {
+       .name   = "Adapter ROM",
+       .start  = 0xc8000,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+} };
+
+static struct resource video_rom_resource = {
+       .name   = "Video ROM",
+       .start  = 0xc0000,
+       .end    = 0xc7fff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource video_ram_resource = {
+       .name   = "Video RAM area",
+       .start  = 0xa0000,
+       .end    = 0xbffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource standard_io_resources[] = { {
+       .name   = "dma1",
+       .start  = 0x0000,
+       .end    = 0x001f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "pic1",
+       .start  = 0x0020,
+       .end    = 0x0021,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "timer0",
+       .start  = 0x0040,
+       .end    = 0x0043,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "timer1",
+       .start  = 0x0050,
+       .end    = 0x0053,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "keyboard",
+       .start  = 0x0060,
+       .end    = 0x006f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "dma page reg",
+       .start  = 0x0080,
+       .end    = 0x008f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "pic2",
+       .start  = 0x00a0,
+       .end    = 0x00a1,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "dma2",
+       .start  = 0x00c0,
+       .end    = 0x00df,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+       .name   = "fpu",
+       .start  = 0x00f0,
+       .end    = 0x00ff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+} };
+
+static int romsignature(const unsigned char *x)
+{
+       unsigned short sig;
+       int ret = 0;
+       if (probe_kernel_address((const unsigned short *)x, sig) == 0)
+               ret = (sig == 0xaa55);
+       return ret;
+}
+
+static int __init romchecksum(unsigned char *rom, unsigned long length)
+{
+       unsigned char *p, sum = 0;
+
+       for (p = rom; p < rom + length; p++)
+               sum += *p;
+       return sum == 0;
+}
+
+static void __init probe_roms(void)
+{
+       unsigned long start, length, upper;
+       unsigned char *rom;
+       int           i;
+
+       /* video rom */
+       upper = adapter_rom_resources[0].start;
+       for (start = video_rom_resource.start; start < upper; start += 2048) {
+               rom = isa_bus_to_virt(start);
+               if (!romsignature(rom))
+                       continue;
+
+               video_rom_resource.start = start;
+
+               /* 0 < length <= 0x7f * 512, historically */
+               length = rom[2] * 512;
+
+               /* if checksum okay, trust length byte */
+               if (length && romchecksum(rom, length))
+                       video_rom_resource.end = start + length - 1;
+
+               request_resource(&iomem_resource, &video_rom_resource);
+               break;
+       }
+
+       start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+       if (start < upper)
+               start = upper;
+
+       /* system rom */
+       request_resource(&iomem_resource, &system_rom_resource);
+       upper = system_rom_resource.start;
+
+       /* check for extension rom (ignore length byte!) */
+       rom = isa_bus_to_virt(extension_rom_resource.start);
+       if (romsignature(rom)) {
+               length = extension_rom_resource.end - extension_rom_resource.start + 1;
+               if (romchecksum(rom, length)) {
+                       request_resource(&iomem_resource, &extension_rom_resource);
+                       upper = extension_rom_resource.start;
+               }
+       }
+
+       /* check for adapter roms on 2k boundaries */
+       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
+               rom = isa_bus_to_virt(start);
+               if (!romsignature(rom))
+                       continue;
+
+               /* 0 < length <= 0x7f * 512, historically */
+               length = rom[2] * 512;
+
+               /* but accept any length that fits if checksum okay */
+               if (!length || start + length > upper || !romchecksum(rom, length))
+                       continue;
+
+               adapter_rom_resources[i].start = start;
+               adapter_rom_resources[i].end = start + length - 1;
+               request_resource(&iomem_resource, &adapter_rom_resources[i]);
+
+               start = adapter_rom_resources[i++].end & ~2047UL;
+       }
+}
+
+/*
+ * Request address space for all standard RAM and ROM resources
+ * and also for regions reported as reserved by the e820.
+ */
+static void __init
+legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
+{
+       int i;
+
+       probe_roms();
+       for (i = 0; i < e820.nr_map; i++) {
+               struct resource *res;
+#ifndef CONFIG_RESOURCES_64BIT
+               if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
+                       continue;
+#endif
+               res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+               switch (e820.map[i].type) {
+               case E820_RAM:  res->name = "System RAM"; break;
+               case E820_ACPI: res->name = "ACPI Tables"; break;
+               case E820_NVS:  res->name = "ACPI Non-volatile Storage"; break;
+               default:        res->name = "reserved";
+               }
+               res->start = e820.map[i].addr;
+               res->end = res->start + e820.map[i].size - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               if (request_resource(&iomem_resource, res)) {
+                       kfree(res);
+                       continue;
+               }
+               if (e820.map[i].type == E820_RAM) {
+                       /*
+                        *  We don't know which RAM region contains kernel data,
+                        *  so we try it repeatedly and let the resource manager
+                        *  test it.
+                        */
+                       request_resource(res, code_resource);
+                       request_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+                       request_resource(res, &crashk_res);
+#endif
+               }
+       }
+}
+
+/*
+ * Request address space for all standard resources
+ *
+ * This is called just before pcibios_init(), which is also a
+ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
+ */
+static int __init request_standard_resources(void)
+{
+       int i;
+
+       printk("Setting up standard PCI resources\n");
+       if (efi_enabled)
+               efi_initialize_iomem_resources(&code_resource, &data_resource);
+       else
+               legacy_init_iomem_resources(&code_resource, &data_resource);
+
+       /* EFI systems may still have VGA */
+       request_resource(&iomem_resource, &video_ram_resource);
+
+       /* request I/O space for devices used on all i[345]86 PCs */
+       for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+               request_resource(&ioport_resource, &standard_io_resources[i]);
+       return 0;
+}
+
+subsys_initcall(request_standard_resources);
+
+void __init add_memory_region(unsigned long long start,
+                             unsigned long long size, int type)
+{
+       int x;
+
+       if (!efi_enabled) {
+                       x = e820.nr_map;
+
+               if (x == E820MAX) {
+                   printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+                   return;
+               }
+
+               e820.map[x].addr = start;
+               e820.map[x].size = size;
+               e820.map[x].type = type;
+               e820.nr_map++;
+       }
+} /* add_memory_region */
+
+/*
+ * Sanitize the BIOS e820 map.
+ *
+ * Some e820 responses include overlapping entries.  The following
+ * replaces the original e820 map with a new one, removing overlaps.
+ *
+ */
+int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+{
+       struct change_member *change_tmp;
+       unsigned long current_type, last_type;
+       unsigned long long last_addr;
+       int chgidx, still_changing;
+       int overlap_entries;
+       int new_bios_entry;
+       int old_nr, new_nr, chg_nr;
+       int i;
+
+       /*
+               Visually we're performing the following (1,2,3,4 = memory types)...
+
+               Sample memory map (w/overlaps):
+                  ____22__________________
+                  ______________________4_
+                  ____1111________________
+                  _44_____________________
+                  11111111________________
+                  ____________________33__
+                  ___________44___________
+                  __________33333_________
+                  ______________22________
+                  ___________________2222_
+                  _________111111111______
+                  _____________________11_
+                  _________________4______
+
+               Sanitized equivalent (no overlap):
+                  1_______________________
+                  _44_____________________
+                  ___1____________________
+                  ____22__________________
+                  ______11________________
+                  _________1______________
+                  __________3_____________
+                  ___________44___________
+                  _____________33_________
+                  _______________2________
+                  ________________1_______
+                  _________________4______
+                  ___________________2____
+                  ____________________33__
+                  ______________________4_
+       */
+       printk("sanitize start\n");
+       /* if there's only one memory region, don't bother */
+       if (*pnr_map < 2) {
+               printk("sanitize bail 0\n");
+               return -1;
+       }
+
+       old_nr = *pnr_map;
+
+       /* bail out if we find any unreasonable addresses in bios map */
+       for (i=0; i<old_nr; i++)
+               if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
+                       printk("sanitize bail 1\n");
+                       return -1;
+               }
+
+       /* create pointers for initial change-point information (for sorting) */
+       for (i=0; i < 2*old_nr; i++)
+               change_point[i] = &change_point_list[i];
+
+       /* record all known change-points (starting and ending addresses),
+          omitting those that are for empty memory regions */
+       chgidx = 0;
+       for (i=0; i < old_nr; i++)      {
+               if (biosmap[i].size != 0) {
+                       change_point[chgidx]->addr = biosmap[i].addr;
+                       change_point[chgidx++]->pbios = &biosmap[i];
+                       change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+                       change_point[chgidx++]->pbios = &biosmap[i];
+               }
+       }
+       chg_nr = chgidx;        /* true number of change-points */
+
+       /* sort change-point list by memory addresses (low -> high) */
+       still_changing = 1;
+       while (still_changing)  {
+               still_changing = 0;
+               for (i=1; i < chg_nr; i++)  {
+                       /* if <current_addr> > <last_addr>, swap */
+                       /* or, if current=<start_addr> & last=<end_addr>, swap */
+                       if ((change_point[i]->addr < change_point[i-1]->addr) ||
+                               ((change_point[i]->addr == change_point[i-1]->addr) &&
+                                (change_point[i]->addr == change_point[i]->pbios->addr) &&
+                                (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+                          )
+                       {
+                               change_tmp = change_point[i];
+                               change_point[i] = change_point[i-1];
+                               change_point[i-1] = change_tmp;
+                               still_changing=1;
+                       }
+               }
+       }
+
+       /* create a new bios memory map, removing overlaps */
+       overlap_entries=0;       /* number of entries in the overlap table */
+       new_bios_entry=0;        /* index for creating new bios map entries */
+       last_type = 0;           /* start with undefined memory type */
+       last_addr = 0;           /* start with 0 as last starting address */
+       /* loop through change-points, determining affect on the new bios map */
+       for (chgidx=0; chgidx < chg_nr; chgidx++)
+       {
+               /* keep track of all overlapping bios entries */
+               if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+               {
+                       /* add map entry to overlap list (> 1 entry implies an overlap) */
+                       overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+               }
+               else
+               {
+                       /* remove entry from list (order independent, so swap with last) */
+                       for (i=0; i<overlap_entries; i++)
+                       {
+                               if (overlap_list[i] == change_point[chgidx]->pbios)
+                                       overlap_list[i] = overlap_list[overlap_entries-1];
+                       }
+                       overlap_entries--;
+               }
+               /* if there are overlapping entries, decide which "type" to use */
+               /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+               current_type = 0;
+               for (i=0; i<overlap_entries; i++)
+                       if (overlap_list[i]->type > current_type)
+                               current_type = overlap_list[i]->type;
+               /* continue building up new bios map based on this information */
+               if (current_type != last_type)  {
+                       if (last_type != 0)      {
+                               new_bios[new_bios_entry].size =
+                                       change_point[chgidx]->addr - last_addr;
+                               /* move forward only if the new size was non-zero */
+                               if (new_bios[new_bios_entry].size != 0)
+                                       if (++new_bios_entry >= E820MAX)
+                                               break;  /* no more space left for new bios entries */
+                       }
+                       if (current_type != 0)  {
+                               new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+                               new_bios[new_bios_entry].type = current_type;
+                               last_addr=change_point[chgidx]->addr;
+                       }
+                       last_type = current_type;
+               }
+       }
+       new_nr = new_bios_entry;   /* retain count for new bios entries */
+
+       /* copy new bios mapping into original location */
+       memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+       *pnr_map = new_nr;
+
+       printk("sanitize end\n");
+       return 0;
+}
+
+/*
+ * Copy the BIOS e820 map into a safe place.
+ *
+ * Sanity-check it while we're at it..
+ *
+ * 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.)
+ */
+int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+{
+       /* Only one memory region (or negative)? Ignore it */
+       if (nr_map < 2)
+               return -1;
+
+       do {
+               unsigned long long start = biosmap->addr;
+               unsigned long long size = biosmap->size;
+               unsigned long long end = start + size;
+               unsigned long type = biosmap->type;
+               printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type);
+
+               /* Overflow in 64 bits? Ignore the memory map. */
+               if (start > end)
+                       return -1;
+
+               /*
+                * Some BIOSes claim RAM in the 640k - 1M region.
+                * Not right. Fix it up.
+                */
+               if (type == E820_RAM) {
+                       printk("copy_e820_map() type is E820_RAM\n");
+                       if (start < 0x100000ULL && end > 0xA0000ULL) {
+                               printk("copy_e820_map() lies in range...\n");
+                               if (start < 0xA0000ULL) {
+                                       printk("copy_e820_map() start < 0xA0000ULL\n");
+                                       add_memory_region(start, 0xA0000ULL-start, type);
+                               }
+                               if (end <= 0x100000ULL) {
+                                       printk("copy_e820_map() end <= 0x100000ULL\n");
+                                       continue;
+                               }
+                               start = 0x100000ULL;
+                               size = end - start;
+                       }
+               }
+               add_memory_region(start, size, type);
+       } while (biosmap++,--nr_map);
+       return 0;
+}
+
+/*
+ * Callback for efi_memory_walk.
+ */
+static int __init
+efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+{
+       unsigned long *max_pfn = arg, pfn;
+
+       if (start < end) {
+               pfn = PFN_UP(end -1);
+               if (pfn > *max_pfn)
+                       *max_pfn = pfn;
+       }
+       return 0;
+}
+
+static int __init
+efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
+{
+       memory_present(0, PFN_UP(start), PFN_DOWN(end));
+       return 0;
+}
+
+/*
+ * Find the highest page frame number we have available
+ */
+void __init find_max_pfn(void)
+{
+       int i;
+
+       max_pfn = 0;
+       if (efi_enabled) {
+               efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+               efi_memmap_walk(efi_memory_present_wrapper, NULL);
+               return;
+       }
+
+       for (i = 0; i < e820.nr_map; i++) {
+               unsigned long start, end;
+               /* RAM? */
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+               start = PFN_UP(e820.map[i].addr);
+               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+               if (start >= end)
+                       continue;
+               if (end > max_pfn)
+                       max_pfn = end;
+               memory_present(0, start, end);
+       }
+}
+
+/*
+ * Free all available memory for boot time allocation.  Used
+ * as a callback function by efi_memory_walk()
+ */
+
+static int __init
+free_available_memory(unsigned long start, unsigned long end, void *arg)
+{
+       /* check max_low_pfn */
+       if (start >= (max_low_pfn << PAGE_SHIFT))
+               return 0;
+       if (end >= (max_low_pfn << PAGE_SHIFT))
+               end = max_low_pfn << PAGE_SHIFT;
+       if (start < end)
+               free_bootmem(start, end - start);
+
+       return 0;
+}
+/*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+{
+       int i;
+
+       if (efi_enabled) {
+               efi_memmap_walk(free_available_memory, NULL);
+               return;
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               unsigned long curr_pfn, last_pfn, size;
+               /*
+                * Reserve usable low memory
+                */
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+               /*
+                * We are rounding up the start address of usable memory:
+                */
+               curr_pfn = PFN_UP(e820.map[i].addr);
+               if (curr_pfn >= max_low_pfn)
+                       continue;
+               /*
+                * ... and at the end of the usable range downwards:
+                */
+               last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+
+               if (last_pfn > max_low_pfn)
+                       last_pfn = max_low_pfn;
+
+               /*
+                * .. finally, did all the rounding and playing
+                * around just make the area go away?
+                */
+               if (last_pfn <= curr_pfn)
+                       continue;
+
+               size = last_pfn - curr_pfn;
+               free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+       }
+}
+
+void __init register_memory(void)
+{
+       unsigned long gapstart, gapsize, round;
+       unsigned long long last;
+       int i;
+
+       /*
+        * Search for the bigest gap in the low 32 bits of the e820
+        * memory space.
+        */
+       last = 0x100000000ull;
+       gapstart = 0x10000000;
+       gapsize = 0x400000;
+       i = e820.nr_map;
+       while (--i >= 0) {
+               unsigned long long start = e820.map[i].addr;
+               unsigned long long end = start + e820.map[i].size;
+
+               /*
+                * Since "last" is at most 4GB, we know we'll
+                * fit in 32 bits if this condition is true
+                */
+               if (last > end) {
+                       unsigned long gap = last - end;
+
+                       if (gap > gapsize) {
+                               gapsize = gap;
+                               gapstart = end;
+                       }
+               }
+               if (start < last)
+                       last = start;
+       }
+
+       /*
+        * See how much we want to round up: start off with
+        * rounding to the next 1MB area.
+        */
+       round = 0x100000;
+       while ((gapsize >> 4) > round)
+               round += round;
+       /* Fun with two's complement */
+       pci_mem_start = (gapstart + round) & -round;
+
+       printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
+               pci_mem_start, gapstart, gapsize);
+}
+
+void __init print_memory_map(char *who)
+{
+       int i;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               printk(" %s: %016Lx - %016Lx ", who,
+                       e820.map[i].addr,
+                       e820.map[i].addr + e820.map[i].size);
+               switch (e820.map[i].type) {
+               case E820_RAM:  printk("(usable)\n");
+                               break;
+               case E820_RESERVED:
+                               printk("(reserved)\n");
+                               break;
+               case E820_ACPI:
+                               printk("(ACPI data)\n");
+                               break;
+               case E820_NVS:
+                               printk("(ACPI NVS)\n");
+                               break;
+               default:        printk("type %lu\n", e820.map[i].type);
+                               break;
+               }
+       }
+}
+
+static __init __always_inline void efi_limit_regions(unsigned long long size)
+{
+       unsigned long long current_addr = 0;
+       efi_memory_desc_t *md, *next_md;
+       void *p, *p1;
+       int i, j;
+
+       j = 0;
+       p1 = memmap.map;
+       for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
+               md = p;
+               next_md = p1;
+               current_addr = md->phys_addr +
+                       PFN_PHYS(md->num_pages);
+               if (is_available_memory(md)) {
+                       if (md->phys_addr >= size) continue;
+                       memcpy(next_md, md, memmap.desc_size);
+                       if (current_addr >= size) {
+                               next_md->num_pages -=
+                                       PFN_UP(current_addr-size);
+                       }
+                       p1 += memmap.desc_size;
+                       next_md = p1;
+                       j++;
+               } else if ((md->attribute & EFI_MEMORY_RUNTIME) ==
+                          EFI_MEMORY_RUNTIME) {
+                       /* In order to make runtime services
+                        * available we have to include runtime
+                        * memory regions in memory map */
+                       memcpy(next_md, md, memmap.desc_size);
+                       p1 += memmap.desc_size;
+                       next_md = p1;
+                       j++;
+               }
+       }
+       memmap.nr_map = j;
+       memmap.map_end = memmap.map +
+               (memmap.nr_map * memmap.desc_size);
+}
+
+void __init limit_regions(unsigned long long size)
+{
+       unsigned long long current_addr;
+       int i;
+
+       print_memory_map("limit_regions start");
+       if (efi_enabled) {
+               efi_limit_regions(size);
+               return;
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               current_addr = e820.map[i].addr + e820.map[i].size;
+               if (current_addr < size)
+                       continue;
+
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+
+               if (e820.map[i].addr >= size) {
+                       /*
+                        * This region starts past the end of the
+                        * requested size, skip it completely.
+                        */
+                       e820.nr_map = i;
+               } else {
+                       e820.nr_map = i + 1;
+                       e820.map[i].size -= current_addr - size;
+               }
+               print_memory_map("limit_regions endfor");
+               return;
+       }
+       print_memory_map("limit_regions endfunc");
+}
+
+ /*
+  * This function checks if the entire range <start,end> is mapped with type.
+  *
+  * Note: this function only works correct if the e820 table is sorted and
+  * not-overlapping, which is the case
+  */
+int __init
+e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
+{
+       u64 start = s;
+       u64 end = e;
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               if (type && ei->type != type)
+                       continue;
+               /* is the region (part) in overlap with the current region ?*/
+               if (ei->addr >= end || ei->addr + ei->size <= start)
+                       continue;
+               /* if the region is at the beginning of <start,end> we move
+                * start to the end of the region since it's ok until there
+                */
+               if (ei->addr <= start)
+                       start = ei->addr + ei->size;
+               /* if start is now at or beyond end, we're done, full
+                * coverage */
+               if (start >= end)
+                       return 1; /* we're done */
+       }
+       return 0;
+}
+
+static int __init parse_memmap(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       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.
+                */
+               find_max_pfn();
+               saved_max_pfn = max_pfn;
+#endif
+               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);
index 8b40648..b92c7f0 100644 (file)
@@ -194,17 +194,24 @@ inline int efi_set_rtc_mmss(unsigned long nowtime)
        return 0;
 }
 /*
- * This should only be used during kernel init and before runtime
- * services have been remapped, therefore, we'll need to call in physical
- * mode.  Note, this call isn't used later, so mark it __init.
+ * This is used during kernel init before runtime
+ * services have been remapped and also during suspend, therefore,
+ * we'll need to call both in physical and virtual modes.
  */
-inline unsigned long __init efi_get_time(void)
+inline unsigned long efi_get_time(void)
 {
        efi_status_t status;
        efi_time_t eft;
        efi_time_cap_t cap;
 
-       status = phys_efi_get_time(&eft, &cap);
+       if (efi.get_time) {
+               /* if we are in virtual mode use remapped function */
+               status = efi.get_time(&eft, &cap);
+       } else {
+               /* we are in physical mode */
+               status = phys_efi_get_time(&eft, &cap);
+       }
+
        if (status != EFI_SUCCESS)
                printk("Oops: efitime: can't read time status: 0x%lx\n",status);
 
index 5a63d6f..de34b7f 100644 (file)
  *     18(%esp) - %eax
  *     1C(%esp) - %ds
  *     20(%esp) - %es
- *     24(%esp) - orig_eax
- *     28(%esp) - %eip
- *     2C(%esp) - %cs
- *     30(%esp) - %eflags
- *     34(%esp) - %oldesp
- *     38(%esp) - %oldss
+ *     24(%esp) - %gs
+ *     28(%esp) - orig_eax
+ *     2C(%esp) - %eip
+ *     30(%esp) - %cs
+ *     34(%esp) - %eflags
+ *     38(%esp) - %oldesp
+ *     3C(%esp) - %oldss
  *
  * "current" is in register %ebx during any slow entries.
  */
 #include <asm/smp.h>
 #include <asm/page.h>
 #include <asm/desc.h>
+#include <asm/percpu.h>
 #include <asm/dwarf2.h>
 #include "irq_vectors.h"
 
-#define nr_syscalls ((syscall_table_size)/4)
+/*
+ * We use macros for low-level operations which need to be overridden
+ * for paravirtualization.  The following will never clobber any registers:
+ *   INTERRUPT_RETURN (aka. "iret")
+ *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
+ *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
+ *
+ * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
+ * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
+ * Allowing a register to be clobbered can shrink the paravirt replacement
+ * enough to patch inline, increasing performance.
+ */
 
-EBX            = 0x00
-ECX            = 0x04
-EDX            = 0x08
-ESI            = 0x0C
-EDI            = 0x10
-EBP            = 0x14
-EAX            = 0x18
-DS             = 0x1C
-ES             = 0x20
-ORIG_EAX       = 0x24
-EIP            = 0x28
-CS             = 0x2C
-EFLAGS         = 0x30
-OLDESP         = 0x34
-OLDSS          = 0x38
+#define nr_syscalls ((syscall_table_size)/4)
 
 CF_MASK                = 0x00000001
 TF_MASK                = 0x00000100
@@ -76,23 +75,16 @@ 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           DISABLE_INTERRUPTS; TRACE_IRQS_OFF
+#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
 #else
-#define preempt_stop
+#define preempt_stop(clobbers)
 #define resume_kernel          restore_nocheck
 #endif
 
 .macro TRACE_IRQS_IRET
 #ifdef CONFIG_TRACE_IRQFLAGS
-       testl $IF_MASK,EFLAGS(%esp)     # interrupts off?
+       testl $IF_MASK,PT_EFLAGS(%esp)     # interrupts off?
        jz 1f
        TRACE_IRQS_ON
 1:
@@ -107,6 +99,9 @@ VM_MASK              = 0x00020000
 
 #define SAVE_ALL \
        cld; \
+       pushl %gs; \
+       CFI_ADJUST_CFA_OFFSET 4;\
+       /*CFI_REL_OFFSET gs, 0;*/\
        pushl %es; \
        CFI_ADJUST_CFA_OFFSET 4;\
        /*CFI_REL_OFFSET es, 0;*/\
@@ -136,7 +131,9 @@ VM_MASK             = 0x00020000
        CFI_REL_OFFSET ebx, 0;\
        movl $(__USER_DS), %edx; \
        movl %edx, %ds; \
-       movl %edx, %es;
+       movl %edx, %es; \
+       movl $(__KERNEL_PDA), %edx; \
+       movl %edx, %gs
 
 #define RESTORE_INT_REGS \
        popl %ebx;      \
@@ -169,17 +166,22 @@ VM_MASK           = 0x00020000
 2:     popl %es;       \
        CFI_ADJUST_CFA_OFFSET -4;\
        /*CFI_RESTORE es;*/\
-.section .fixup,"ax";  \
-3:     movl $0,(%esp); \
-       jmp 1b;         \
+3:     popl %gs;       \
+       CFI_ADJUST_CFA_OFFSET -4;\
+       /*CFI_RESTORE gs;*/\
+.pushsection .fixup,"ax";      \
 4:     movl $0,(%esp); \
+       jmp 1b;         \
+5:     movl $0,(%esp); \
        jmp 2b;         \
-.previous;             \
+6:     movl $0,(%esp); \
+       jmp 3b;         \
 .section __ex_table,"a";\
        .align 4;       \
-       .long 1b,3b;    \
-       .long 2b,4b;    \
-.previous
+       .long 1b,4b;    \
+       .long 2b,5b;    \
+       .long 3b,6b;    \
+.popsection
 
 #define RING0_INT_FRAME \
        CFI_STARTPROC simple;\
@@ -198,18 +200,18 @@ VM_MASK           = 0x00020000
 #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;\
-       /*CFI_OFFSET es, ES-OLDESP;*/\
-       /*CFI_OFFSET ds, DS-OLDESP;*/\
-       CFI_OFFSET eax, EAX-OLDESP;\
-       CFI_OFFSET ebp, EBP-OLDESP;\
-       CFI_OFFSET edi, EDI-OLDESP;\
-       CFI_OFFSET esi, ESI-OLDESP;\
-       CFI_OFFSET edx, EDX-OLDESP;\
-       CFI_OFFSET ecx, ECX-OLDESP;\
-       CFI_OFFSET ebx, EBX-OLDESP
+       CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\
+       /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\
+       CFI_OFFSET eip, PT_EIP-PT_OLDESP;\
+       /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\
+       /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\
+       CFI_OFFSET eax, PT_EAX-PT_OLDESP;\
+       CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\
+       CFI_OFFSET edi, PT_EDI-PT_OLDESP;\
+       CFI_OFFSET esi, PT_ESI-PT_OLDESP;\
+       CFI_OFFSET edx, PT_EDX-PT_OLDESP;\
+       CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\
+       CFI_OFFSET ebx, PT_EBX-PT_OLDESP
 
 ENTRY(ret_from_fork)
        CFI_STARTPROC
@@ -237,17 +239,18 @@ ENTRY(ret_from_fork)
        ALIGN
        RING0_PTREGS_FRAME
 ret_from_exception:
-       preempt_stop
+       preempt_stop(CLBR_ANY)
 ret_from_intr:
        GET_THREAD_INFO(%ebp)
 check_userspace:
-       movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
-       movb CS(%esp), %al
+       movl PT_EFLAGS(%esp), %eax      # mix EFLAGS and CS
+       movb PT_CS(%esp), %al
        andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
        cmpl $USER_RPL, %eax
        jb resume_kernel                # not returning to v8086 or userspace
+
 ENTRY(resume_userspace)
-       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        movl TI_flags(%ebp), %ecx
@@ -258,14 +261,14 @@ ENTRY(resume_userspace)
 
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
-       DISABLE_INTERRUPTS
+       DISABLE_INTERRUPTS(CLBR_ANY)
        cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?
        jnz restore_nocheck
 need_resched:
        movl TI_flags(%ebp), %ecx       # need_resched set ?
        testb $_TIF_NEED_RESCHED, %cl
        jz restore_all
-       testl $IF_MASK,EFLAGS(%esp)     # interrupts off (exception path) ?
+       testl $IF_MASK,PT_EFLAGS(%esp)  # interrupts off (exception path) ?
        jz restore_all
        call preempt_schedule_irq
        jmp need_resched
@@ -287,7 +290,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:
         */
-       ENABLE_INTERRUPTS
+       ENABLE_INTERRUPTS(CLBR_NONE)
        pushl $(__USER_DS)
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET ss, 0*/
@@ -331,20 +334,27 @@ sysenter_past_esp:
        cmpl $(nr_syscalls), %eax
        jae syscall_badsys
        call *sys_call_table(,%eax,4)
-       movl %eax,EAX(%esp)
-       DISABLE_INTERRUPTS
+       movl %eax,PT_EAX(%esp)
+       DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX)
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx
        jne syscall_exit_work
 /* if something modifies registers it must also disable sysexit */
-       movl EIP(%esp), %edx
-       movl OLDESP(%esp), %ecx
+       movl PT_EIP(%esp), %edx
+       movl PT_OLDESP(%esp), %ecx
        xorl %ebp,%ebp
        TRACE_IRQS_ON
+1:     mov  PT_GS(%esp), %gs
        ENABLE_INTERRUPTS_SYSEXIT
        CFI_ENDPROC
-
+.pushsection .fixup,"ax"
+2:     movl $0,PT_GS(%esp)
+       jmp 1b
+.section __ex_table,"a"
+       .align 4
+       .long 1b,2b
+.popsection
 
        # system call handler stub
 ENTRY(system_call)
@@ -353,7 +363,7 @@ ENTRY(system_call)
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
-       testl $TF_MASK,EFLAGS(%esp)
+       testl $TF_MASK,PT_EFLAGS(%esp)
        jz no_singlestep
        orl $_TIF_SINGLESTEP,TI_flags(%ebp)
 no_singlestep:
@@ -365,9 +375,9 @@ no_singlestep:
        jae syscall_badsys
 syscall_call:
        call *sys_call_table(,%eax,4)
-       movl %eax,EAX(%esp)             # store the return value
+       movl %eax,PT_EAX(%esp)          # store the return value
 syscall_exit:
-       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        TRACE_IRQS_OFF
@@ -376,12 +386,12 @@ syscall_exit:
        jne syscall_exit_work
 
 restore_all:
-       movl EFLAGS(%esp), %eax         # mix EFLAGS, SS and CS
-       # Warning: OLDSS(%esp) contains the wrong/random values if we
+       movl PT_EFLAGS(%esp), %eax      # mix EFLAGS, SS and CS
+       # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
        # are returning to the kernel.
        # See comments in process.c:copy_thread() for details.
-       movb OLDSS(%esp), %ah
-       movb CS(%esp), %al
+       movb PT_OLDSS(%esp), %ah
+       movb PT_CS(%esp), %al
        andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
        cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
        CFI_REMEMBER_STATE
@@ -390,13 +400,13 @@ restore_nocheck:
        TRACE_IRQS_IRET
 restore_nocheck_notrace:
        RESTORE_REGS
-       addl $4, %esp
+       addl $4, %esp                   # skip orig_eax/error_code
        CFI_ADJUST_CFA_OFFSET -4
 1:     INTERRUPT_RETURN
 .section .fixup,"ax"
 iret_exc:
        TRACE_IRQS_ON
-       ENABLE_INTERRUPTS
+       ENABLE_INTERRUPTS(CLBR_NONE)
        pushl $0                        # no error code
        pushl $do_iret_error
        jmp error_code
@@ -408,33 +418,42 @@ iret_exc:
 
        CFI_RESTORE_STATE
 ldt_ss:
-       larl OLDSS(%esp), %eax
+       larl PT_OLDSS(%esp), %eax
        jnz restore_nocheck
        testl $0x00400000, %eax         # returning to 32bit stack?
        jnz restore_nocheck             # allright, normal return
+
+#ifdef CONFIG_PARAVIRT
+       /*
+        * The kernel can't run on a non-flat stack if paravirt mode
+        * is active.  Rather than try to fixup the high bits of
+        * ESP, bypass this code entirely.  This may break DOSemu
+        * and/or Wine support in a paravirt VM, although the option
+        * is still available to implement the setting of the high
+        * 16-bits in the INTERRUPT_RETURN paravirt-op.
+        */
+       cmpl $0, paravirt_ops+PARAVIRT_enabled
+       jne restore_nocheck
+#endif
+
        /* If returning to userspace with 16bit stack,
         * try to fix the higher word of ESP, as the CPU
         * won't restore it.
         * This is an "official" bug of all the x86-compatible
         * CPUs, which we can try to work around to make
         * dosemu and wine happy. */
-       subl $8, %esp           # reserve space for switch16 pointer
-       CFI_ADJUST_CFA_OFFSET 8
-       DISABLE_INTERRUPTS
+       movl PT_OLDESP(%esp), %eax
+       movl %esp, %edx
+       call patch_espfix_desc
+       pushl $__ESPFIX_SS
+       CFI_ADJUST_CFA_OFFSET 4
+       pushl %eax
+       CFI_ADJUST_CFA_OFFSET 4
+       DISABLE_INTERRUPTS(CLBR_EAX)
        TRACE_IRQS_OFF
-       movl %esp, %eax
-       /* Set up the 16bit stack frame with switch32 pointer on top,
-        * and a switch16 pointer on top of the current frame. */
-       call setup_x86_bogus_stack
-       CFI_ADJUST_CFA_OFFSET -8        # frame has moved
-       TRACE_IRQS_IRET
-       RESTORE_REGS
-       lss 20+4(%esp), %esp    # switch to 16bit stack
-1:     INTERRUPT_RETURN
-.section __ex_table,"a"
-       .align 4
-       .long 1b,iret_exc
-.previous
+       lss (%esp), %esp
+       CFI_ADJUST_CFA_OFFSET -8
+       jmp restore_nocheck
        CFI_ENDPROC
 
        # perform work that needs to be done immediately before resumption
@@ -445,7 +464,7 @@ work_pending:
        jz work_notifysig
 work_resched:
        call schedule
-       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        TRACE_IRQS_OFF
@@ -458,7 +477,8 @@ work_resched:
 
 work_notifysig:                                # deal with pending signals and
                                        # notify-resume requests
-       testl $VM_MASK, EFLAGS(%esp)
+#ifdef CONFIG_VM86
+       testl $VM_MASK, PT_EFLAGS(%esp)
        movl %esp, %eax
        jne work_notifysig_v86          # returning to kernel-space or
                                        # vm86-space
@@ -468,29 +488,30 @@ work_notifysig:                           # deal with pending signals and
 
        ALIGN
 work_notifysig_v86:
-#ifdef CONFIG_VM86
        pushl %ecx                      # save ti_flags for do_notify_resume
        CFI_ADJUST_CFA_OFFSET 4
        call save_v86_state             # %eax contains pt_regs pointer
        popl %ecx
        CFI_ADJUST_CFA_OFFSET -4
        movl %eax, %esp
+#else
+       movl %esp, %eax
+#endif
        xorl %edx, %edx
        call do_notify_resume
        jmp resume_userspace_sig
-#endif
 
        # perform syscall exit tracing
        ALIGN
 syscall_trace_entry:
-       movl $-ENOSYS,EAX(%esp)
+       movl $-ENOSYS,PT_EAX(%esp)
        movl %esp, %eax
        xorl %edx,%edx
        call do_syscall_trace
        cmpl $0, %eax
        jne resume_userspace            # ret != 0 -> running under PTRACE_SYSEMU,
                                        # so must skip actual syscall
-       movl ORIG_EAX(%esp), %eax
+       movl PT_ORIG_EAX(%esp), %eax
        cmpl $(nr_syscalls), %eax
        jnae syscall_call
        jmp syscall_exit
@@ -501,7 +522,7 @@ syscall_exit_work:
        testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
        jz work_pending
        TRACE_IRQS_ON
-       ENABLE_INTERRUPTS               # could let do_syscall_trace() call
+       ENABLE_INTERRUPTS(CLBR_ANY)     # could let do_syscall_trace() call
                                        # schedule() instead
        movl %esp, %eax
        movl $1, %edx
@@ -515,39 +536,38 @@ syscall_fault:
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
-       movl $-EFAULT,EAX(%esp)
+       movl $-EFAULT,PT_EAX(%esp)
        jmp resume_userspace
 
 syscall_badsys:
-       movl $-ENOSYS,EAX(%esp)
+       movl $-ENOSYS,PT_EAX(%esp)
        jmp resume_userspace
        CFI_ENDPROC
 
 #define FIXUP_ESPFIX_STACK \
-       movl %esp, %eax; \
-       /* switch to 32bit stack using the pointer on top of 16bit stack */ \
-       lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
-       /* copy data from 16bit stack to 32bit stack */ \
-       call fixup_x86_bogus_stack; \
-       /* put ESP to the proper location */ \
-       movl %eax, %esp;
-#define UNWIND_ESPFIX_STACK \
+       /* since we are on a wrong stack, we cant make it a C code :( */ \
+       movl %gs:PDA_cpu, %ebx; \
+       PER_CPU(cpu_gdt_descr, %ebx); \
+       movl GDS_address(%ebx), %ebx; \
+       GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
+       addl %esp, %eax; \
+       pushl $__KERNEL_DS; \
+       CFI_ADJUST_CFA_OFFSET 4; \
        pushl %eax; \
        CFI_ADJUST_CFA_OFFSET 4; \
+       lss (%esp), %esp; \
+       CFI_ADJUST_CFA_OFFSET -8;
+#define UNWIND_ESPFIX_STACK \
        movl %ss, %eax; \
-       /* see if on 16bit stack */ \
+       /* see if on espfix stack */ \
        cmpw $__ESPFIX_SS, %ax; \
-       je 28f; \
-27:    popl %eax; \
-       CFI_ADJUST_CFA_OFFSET -4; \
-.section .fixup,"ax"; \
-28:    movl $__KERNEL_DS, %eax; \
+       jne 27f; \
+       movl $__KERNEL_DS, %eax; \
        movl %eax, %ds; \
        movl %eax, %es; \
-       /* switch to 32bit stack */ \
+       /* switch to normal stack */ \
        FIXUP_ESPFIX_STACK; \
-       jmp 27b; \
-.previous
+27:;
 
 /*
  * Build the entry stubs and pointer table with
@@ -608,13 +628,16 @@ KPROBE_ENTRY(page_fault)
        CFI_ADJUST_CFA_OFFSET 4
        ALIGN
 error_code:
+       /* the function address is in %gs's slot on the stack */
+       pushl %es
+       CFI_ADJUST_CFA_OFFSET 4
+       /*CFI_REL_OFFSET es, 0*/
        pushl %ds
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET ds, 0*/
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET eax, 0
-       xorl %eax, %eax
        pushl %ebp
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET ebp, 0
@@ -627,7 +650,6 @@ error_code:
        pushl %edx
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET edx, 0
-       decl %eax                       # eax = -1
        pushl %ecx
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET ecx, 0
@@ -635,18 +657,20 @@ error_code:
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET ebx, 0
        cld
-       pushl %es
+       pushl %gs
        CFI_ADJUST_CFA_OFFSET 4
-       /*CFI_REL_OFFSET es, 0*/
+       /*CFI_REL_OFFSET gs, 0*/
+       movl $(__KERNEL_PDA), %ecx
+       movl %ecx, %gs
        UNWIND_ESPFIX_STACK
        popl %ecx
        CFI_ADJUST_CFA_OFFSET -4
        /*CFI_REGISTER es, ecx*/
-       movl ES(%esp), %edi             # get the function address
-       movl ORIG_EAX(%esp), %edx       # get the error code
-       movl %eax, ORIG_EAX(%esp)
-       movl %ecx, ES(%esp)
-       /*CFI_REL_OFFSET es, ES*/
+       movl PT_GS(%esp), %edi          # get the function address
+       movl PT_ORIG_EAX(%esp), %edx    # get the error code
+       movl $-1, PT_ORIG_EAX(%esp)     # no syscall to restart
+       mov  %ecx, PT_GS(%esp)
+       /*CFI_REL_OFFSET gs, ES*/
        movl $(__USER_DS), %ecx
        movl %ecx, %ds
        movl %ecx, %es
@@ -682,7 +706,7 @@ ENTRY(device_not_available)
        GET_CR0_INTO_EAX
        testl $0x4, %eax                # EM (math emulation bit)
        jne device_not_available_emulate
-       preempt_stop
+       preempt_stop(CLBR_ANY)
        call math_state_restore
        jmp ret_from_exception
 device_not_available_emulate:
@@ -754,7 +778,7 @@ KPROBE_ENTRY(nmi)
        cmpw $__ESPFIX_SS, %ax
        popl %eax
        CFI_ADJUST_CFA_OFFSET -4
-       je nmi_16bit_stack
+       je nmi_espfix_stack
        cmpl $sysenter_entry,(%esp)
        je nmi_stack_fixup
        pushl %eax
@@ -797,7 +821,7 @@ nmi_debug_stack_check:
        FIX_STACK(24,nmi_stack_correct, 1)
        jmp nmi_stack_correct
 
-nmi_16bit_stack:
+nmi_espfix_stack:
        /* We have a RING0_INT_FRAME here.
         *
         * create the pointer to lss back
@@ -806,7 +830,6 @@ nmi_16bit_stack:
        CFI_ADJUST_CFA_OFFSET 4
        pushl %esp
        CFI_ADJUST_CFA_OFFSET 4
-       movzwl %sp, %esp
        addw $4, (%esp)
        /* copy the iret frame of 12 bytes */
        .rept 3
@@ -817,11 +840,11 @@ nmi_16bit_stack:
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
        FIXUP_ESPFIX_STACK              # %eax == %esp
-       CFI_ADJUST_CFA_OFFSET -20       # the frame has now moved
        xorl %edx,%edx                  # zero error code
        call do_nmi
        RESTORE_REGS
-       lss 12+4(%esp), %esp            # back to 16bit stack
+       lss 12+4(%esp), %esp            # back to espfix stack
+       CFI_ADJUST_CFA_OFFSET -24
 1:     INTERRUPT_RETURN
        CFI_ENDPROC
 .section __ex_table,"a"
@@ -830,6 +853,19 @@ nmi_16bit_stack:
 .previous
 KPROBE_END(nmi)
 
+#ifdef CONFIG_PARAVIRT
+ENTRY(native_iret)
+1:     iret
+.section __ex_table,"a"
+       .align 4
+       .long 1b,iret_exc
+.previous
+
+ENTRY(native_irq_enable_sysexit)
+       sti
+       sysexit
+#endif
+
 KPROBE_ENTRY(int3)
        RING0_INT_FRAME
        pushl $-1                       # mark this as an int
@@ -949,26 +985,27 @@ ENTRY(arch_unwind_init_running)
        movl    4(%esp), %edx
        movl    (%esp), %ecx
        leal    4(%esp), %eax
-       movl    %ebx, EBX(%edx)
+       movl    %ebx, PT_EBX(%edx)
        xorl    %ebx, %ebx
-       movl    %ebx, ECX(%edx)
-       movl    %ebx, EDX(%edx)
-       movl    %esi, ESI(%edx)
-       movl    %edi, EDI(%edx)
-       movl    %ebp, EBP(%edx)
-       movl    %ebx, EAX(%edx)
-       movl    $__USER_DS, DS(%edx)
-       movl    $__USER_DS, ES(%edx)
-       movl    %ebx, ORIG_EAX(%edx)
-       movl    %ecx, EIP(%edx)
+       movl    %ebx, PT_ECX(%edx)
+       movl    %ebx, PT_EDX(%edx)
+       movl    %esi, PT_ESI(%edx)
+       movl    %edi, PT_EDI(%edx)
+       movl    %ebp, PT_EBP(%edx)
+       movl    %ebx, PT_EAX(%edx)
+       movl    $__USER_DS, PT_DS(%edx)
+       movl    $__USER_DS, PT_ES(%edx)
+       movl    $0, PT_GS(%edx)
+       movl    %ebx, PT_ORIG_EAX(%edx)
+       movl    %ecx, PT_EIP(%edx)
        movl    12(%esp), %ecx
-       movl    $__KERNEL_CS, CS(%edx)
-       movl    %ebx, EFLAGS(%edx)
-       movl    %eax, OLDESP(%edx)
+       movl    $__KERNEL_CS, PT_CS(%edx)
+       movl    %ebx, PT_EFLAGS(%edx)
+       movl    %eax, PT_OLDESP(%edx)
        movl    8(%esp), %eax
        movl    %ecx, 8(%esp)
-       movl    EBX(%edx), %ebx
-       movl    $__KERNEL_DS, OLDSS(%edx)
+       movl    PT_EBX(%edx), %ebx
+       movl    $__KERNEL_DS, PT_OLDSS(%edx)
        jmpl    *%eax
        CFI_ENDPROC
 ENDPROC(arch_unwind_init_running)
index ca31f18..edef508 100644 (file)
  */
 ENTRY(startup_32)
 
+#ifdef CONFIG_PARAVIRT
+        movl %cs, %eax
+        testl $0x3, %eax
+        jnz startup_paravirt
+#endif
+
 /*
  * Set segments to known values.
  */
@@ -302,6 +308,7 @@ is386:      movl $2,%ecx            # set MP
        movl %eax,%cr0
 
        call check_x87
+       call setup_pda
        lgdt cpu_gdt_descr
        lidt idt_descr
        ljmp $(__KERNEL_CS),$1f
@@ -312,10 +319,13 @@ is386:    movl $2,%ecx            # set MP
        movl %eax,%ds
        movl %eax,%es
 
-       xorl %eax,%eax                  # Clear FS/GS and LDT
+       xorl %eax,%eax                  # Clear FS and LDT
        movl %eax,%fs
-       movl %eax,%gs
        lldt %ax
+
+       movl $(__KERNEL_PDA),%eax
+       mov  %eax,%gs
+
        cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
 #ifdef CONFIG_SMP
@@ -345,6 +355,23 @@ check_x87:
        .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
        ret
 
+/*
+ * Point the GDT at this CPU's PDA.  On boot this will be
+ * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
+ * that CPU's GDT and PDA.
+ */
+setup_pda:
+       /* get the PDA pointer */
+       movl start_pda, %eax
+
+       /* slot the PDA address into the GDT */
+       mov cpu_gdt_descr+2, %ecx
+       mov %ax, (__KERNEL_PDA+0+2)(%ecx)               /* base & 0x0000ffff */
+       shr $16, %eax
+       mov %al, (__KERNEL_PDA+4+0)(%ecx)               /* base & 0x00ff0000 */
+       mov %ah, (__KERNEL_PDA+4+3)(%ecx)               /* base & 0xff000000 */
+       ret
+
 /*
  *  setup_idt
  *
@@ -465,6 +492,33 @@ ignore_int:
 #endif
        iret
 
+#ifdef CONFIG_PARAVIRT
+startup_paravirt:
+       cld
+       movl $(init_thread_union+THREAD_SIZE),%esp
+
+       /* We take pains to preserve all the regs. */
+       pushl   %edx
+       pushl   %ecx
+       pushl   %eax
+
+       /* paravirt.o is last in link, and that probe fn never returns */
+       pushl   $__start_paravirtprobe
+1:
+       movl    0(%esp), %eax
+       pushl   (%eax)
+       movl    8(%esp), %eax
+       call    *(%esp)
+       popl    %eax
+
+       movl    4(%esp), %eax
+       movl    8(%esp), %ecx
+       movl    12(%esp), %edx
+
+       addl    $4, (%esp)
+       jmp     1b
+#endif
+
 /*
  * Real beginning of normal "text" segment
  */
@@ -484,6 +538,8 @@ ENTRY(empty_zero_page)
  * This starts the data section.
  */
 .data
+ENTRY(start_pda)
+       .long boot_pda
 
 ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
@@ -525,7 +581,7 @@ idt_descr:
 
 # boot GDT descriptor (later on used by CPU#0):
        .word 0                         # 32 bit align gdt_desc.address
-cpu_gdt_descr:
+ENTRY(cpu_gdt_descr)
        .word GDT_ENTRIES*8-1
        .long cpu_gdt_table
 
@@ -584,8 +640,8 @@ ENTRY(cpu_gdt_table)
        .quad 0x00009a000000ffff        /* 0xc0 APM CS 16 code (16 bit) */
        .quad 0x004092000000ffff        /* 0xc8 APM DS    data */
 
-       .quad 0x0000920000000000        /* 0xd0 - ESPFIX 16-bit SS */
-       .quad 0x0000000000000000        /* 0xd8 - unused */
+       .quad 0x00c0920000000000        /* 0xd0 - ESPFIX SS */
+       .quad 0x00cf92000000ffff        /* 0xd8 - PDA */
        .quad 0x0000000000000000        /* 0xe0 - unused */
        .quad 0x0000000000000000        /* 0xe8 - unused */
        .quad 0x0000000000000000        /* 0xf0 - unused */
index 17647a5..45a8685 100644 (file)
@@ -34,6 +34,7 @@ static int __init init_hpet_clocksource(void)
        unsigned long hpet_period;
        void __iomem* hpet_base;
        u64 tmp;
+       int err;
 
        if (!is_hpet_enabled())
                return -ENODEV;
@@ -61,7 +62,11 @@ static int __init init_hpet_clocksource(void)
        do_div(tmp, FSEC_PER_NSEC);
        clocksource_hpet.mult = (u32)tmp;
 
-       return clocksource_register(&clocksource_hpet);
+       err = clocksource_register(&clocksource_hpet);
+       if (err)
+               iounmap(hpet_base);
+
+       return err;
 }
 
 module_init(init_hpet_clocksource);
index 62996cd..c8d4582 100644 (file)
@@ -381,7 +381,10 @@ void __init init_ISA_irqs (void)
        }
 }
 
-void __init init_IRQ(void)
+/* Overridden in paravirt.c */
+void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
+
+void __init native_init_IRQ(void)
 {
        int i;
 
index 3b7a63e..2424cc9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/pci.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
+#include <linux/freezer.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -153,14 +154,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
  * the interrupt, and we need to make sure the entry is fully populated
  * before that happens.
  */
-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+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, 0x11 + 2*pin, eu.w2);
        io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       __ioapic_write_entry(apic, pin, e);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -836,8 +843,7 @@ static int __init find_isa_irq_pin(int irq, int type)
 
                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 ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+                    mp_bus_id_to_type[lbus] == MP_BUS_MCA
                    ) &&
                    (mp_irqs[i].mpc_irqtype == type) &&
                    (mp_irqs[i].mpc_srcbusirq == irq))
@@ -856,8 +862,7 @@ static int __init find_isa_irq_apic(int irq, int type)
 
                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 ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+                    mp_bus_id_to_type[lbus] == MP_BUS_MCA
                    ) &&
                    (mp_irqs[i].mpc_irqtype == type) &&
                    (mp_irqs[i].mpc_srcbusirq == irq))
@@ -987,12 +992,6 @@ static int EISA_ELCR(unsigned int irq)
 #define default_MCA_trigger(idx)       (1)
 #define default_MCA_polarity(idx)      (0)
 
-/* NEC98 interrupts are always polarity zero edge triggered,
- * when listed as conforming in the MP table. */
-
-#define default_NEC98_trigger(idx)     (0)
-#define default_NEC98_polarity(idx)    (0)
-
 static int __init MPBIOS_polarity(int idx)
 {
        int bus = mp_irqs[idx].mpc_srcbus;
@@ -1027,11 +1026,6 @@ static int __init MPBIOS_polarity(int idx)
                                        polarity = default_MCA_polarity(idx);
                                        break;
                                }
-                               case MP_BUS_NEC98: /* NEC 98 pin */
-                               {
-                                       polarity = default_NEC98_polarity(idx);
-                                       break;
-                               }
                                default:
                                {
                                        printk(KERN_WARNING "broken BIOS!!\n");
@@ -1101,11 +1095,6 @@ static int MPBIOS_trigger(int idx)
                                        trigger = default_MCA_trigger(idx);
                                        break;
                                }
-                               case MP_BUS_NEC98: /* NEC 98 pin */
-                               {
-                                       trigger = default_NEC98_trigger(idx);
-                                       break;
-                               }
                                default:
                                {
                                        printk(KERN_WARNING "broken BIOS!!\n");
@@ -1167,7 +1156,6 @@ static int pin_2_irq(int idx, int apic, int pin)
                case MP_BUS_ISA: /* ISA pin */
                case MP_BUS_EISA:
                case MP_BUS_MCA:
-               case MP_BUS_NEC98:
                {
                        irq = mp_irqs[idx].mpc_srcbusirq;
                        break;
@@ -1235,7 +1223,7 @@ static inline int IO_APIC_irq_trigger(int irq)
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
+static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 
 static int __assign_irq_vector(int irq)
 {
@@ -1360,8 +1348,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);
+               __ioapic_write_entry(apic, pin, entry);
                set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
@@ -1926,6 +1914,15 @@ static void __init setup_ioapic_ids_from_mpc(void)
 static void __init setup_ioapic_ids_from_mpc(void) { }
 #endif
 
+static int no_timer_check __initdata;
+
+static int __init notimercheck(char *s)
+{
+       no_timer_check = 1;
+       return 1;
+}
+__setup("no_timer_check", notimercheck);
+
 /*
  * 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:
@@ -1934,10 +1931,13 @@ static void __init setup_ioapic_ids_from_mpc(void) { }
  *     - if this function detects that timer IRQs are defunct, then we fall
  *       back to ISA timer IRQs
  */
-static int __init timer_irq_works(void)
+int __init timer_irq_works(void)
 {
        unsigned long t1 = jiffies;
 
+       if (no_timer_check)
+               return 1;
+
        local_irq_enable();
        /* Let ten ticks pass... */
        mdelay((10 * 1000) / HZ);
@@ -2161,9 +2161,15 @@ static inline void unlock_ExtINT_logic(void)
        unsigned char save_control, save_freq_select;
 
        pin  = find_isa_irq_pin(8, mp_INT);
+       if (pin == -1) {
+               WARN_ON_ONCE(1);
+               return;
+       }
        apic = find_isa_irq_apic(8, mp_INT);
-       if (pin == -1)
+       if (apic == -1) {
+               WARN_ON_ONCE(1);
                return;
+       }
 
        entry0 = ioapic_read_entry(apic, pin);
        clear_IO_APIC_pin(apic, pin);
@@ -2208,7 +2214,7 @@ int timer_uses_ioapic_pin_0;
  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  * fanatically on his truly buggy board.
  */
-static inline void check_timer(void)
+static inline void __init check_timer(void)
 {
        int apic1, pin1, apic2, pin2;
        int vector;
@@ -2479,7 +2485,7 @@ device_initcall(ioapic_init_sysfs);
 int create_irq(void)
 {
        /* Allocate an unused irq */
-       int irq, new, vector;
+       int irq, new, vector = 0;
        unsigned long flags;
 
        irq = -ENOSPC;
@@ -2856,8 +2862,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);
+       __ioapic_write_entry(ioapic, pin, entry);
        set_native_irq_info(irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
index fc79e1e..af1d533 100644 (file)
@@ -184,7 +184,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
        mutex_unlock(&kprobe_mutex);
 }
 
@@ -333,7 +333,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
                return 1;
 
 ss_probe:
-#ifndef CONFIG_PREEMPT
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
        if (p->ainsn.boostable == 1 && !p->post_handler){
                /* Boost up -- we can execute copied instructions directly */
                reset_current_kprobe();
index 445211e..b410e5f 100644 (file)
@@ -160,16 +160,14 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
 {
        int err;
        unsigned long size;
-       void *address;
 
        err = 0;
-       address = &default_ldt[0];
        size = 5*sizeof(struct desc_struct);
        if (size > bytecount)
                size = bytecount;
 
        err = size;
-       if (copy_to_user(ptr, address, size))
+       if (clear_user(ptr, size))
                err = -EFAULT;
 
        return err;
index eb57a85..b83672b 100644 (file)
@@ -283,10 +283,9 @@ static int __init mca_init(void)
        bus->f.mca_transform_memory = mca_dummy_transform_memory;
 
        /* get the motherboard device */
-       mca_dev = kmalloc(sizeof(struct mca_device), GFP_KERNEL);
+       mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
        if(unlikely(!mca_dev))
                goto out_nomem;
-       memset(mca_dev, 0, sizeof(struct mca_device));
 
        /*
         * We do not expect many MCA interrupts during initialization,
@@ -310,11 +309,9 @@ static int __init mca_init(void)
        mca_dev->slot = MCA_MOTHERBOARD;
        mca_register_device(MCA_PRIMARY_BUS, mca_dev);
 
-       mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC);
+       mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
        if(unlikely(!mca_dev))
                goto out_unlock_nomem;
-       memset(mca_dev, 0, sizeof(struct mca_device));
-
 
        /* Put motherboard into video setup mode, read integrated video
         * POS registers, and turn motherboard setup off.
@@ -349,10 +346,9 @@ static int __init mca_init(void)
        }
        if(which_scsi) {
                /* found a scsi card */
-               mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC);
+               mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
                if(unlikely(!mca_dev))
                        goto out_unlock_nomem;
-               memset(mca_dev, 0, sizeof(struct mca_device));
 
                for(j = 0; j < 8; j++)
                        mca_dev->pos[j] = pos[j];
@@ -378,10 +374,9 @@ static int __init mca_init(void)
                if(!mca_read_and_store_pos(pos))
                        continue;
 
-               mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC);
+               mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
                if(unlikely(!mca_dev))
                        goto out_unlock_nomem;
-               memset(mca_dev, 0, sizeof(struct mca_device));
 
                for(j=0; j<8; j++)
                        mca_dev->pos[j]=pos[j];
index 23f5984..9723466 100644 (file)
@@ -703,7 +703,6 @@ static struct sysdev_driver mc_sysdev_driver = {
        .resume = mc_sysdev_resume,
 };
 
-#ifdef CONFIG_HOTPLUG_CPU
 static __cpuinit int
 mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 {
@@ -726,7 +725,6 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 static struct notifier_block mc_cpu_notifier = {
        .notifier_call = mc_cpu_callback,
 };
-#endif
 
 static int __init microcode_init (void)
 {
index 470cf97..3db0a54 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/bug.h>
 
 #if 0
 #define DEBUGP printk
@@ -108,7 +109,8 @@ int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
 {
-       const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL;
+       const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
+               *para = NULL;
        char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 
        for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 
@@ -118,6 +120,8 @@ int module_finalize(const Elf_Ehdr *hdr,
                        alt = s;
                if (!strcmp(".smp_locks", secstrings + s->sh_name))
                        locks= s;
+               if (!strcmp(".parainstructions", secstrings + s->sh_name))
+                       para = s;
        }
 
        if (alt) {
@@ -132,10 +136,17 @@ int module_finalize(const Elf_Ehdr *hdr,
                                            lseg, lseg + locks->sh_size,
                                            tseg, tseg + text->sh_size);
        }
-       return 0;
+
+       if (para) {
+               void *pseg = (void *)para->sh_addr;
+               apply_paravirt(pseg, pseg + para->sh_size);
+       }
+
+       return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
        alternatives_smp_module_del(mod);
+       module_bug_cleanup(mod);
 }
index 442aaf8..2ce6722 100644 (file)
@@ -249,8 +249,6 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
                mp_current_pci_id++;
        } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
-       } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
        } else {
                printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
        }
index a773f77..4a472a1 100644 (file)
@@ -172,7 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
        u32 __user *tmp = (u32 __user *) buf;
        u32 data[2];
        u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
+       int cpu = iminor(file->f_path.dentry->d_inode);
        int err;
 
        if (count % 8)
@@ -195,15 +195,14 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
 {
        const u32 __user *tmp = (const u32 __user *)buf;
        u32 data[2];
-       size_t rv;
        u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
+       int cpu = iminor(file->f_path.dentry->d_inode);
        int err;
 
        if (count % 8)
                return -EINVAL; /* Invalid chunk size */
 
-       for (rv = 0; count; count -= 8) {
+       for (; count; count -= 8) {
                if (copy_from_user(&data, tmp, 8))
                        return -EFAULT;
                err = do_wrmsr(cpu, reg, data[0], data[1]);
@@ -217,7 +216,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-       unsigned int cpu = iminor(file->f_dentry->d_inode);
+       unsigned int cpu = iminor(file->f_path.dentry->d_inode);
        struct cpuinfo_x86 *c = &(cpu_data)[cpu];
 
        if (cpu >= NR_CPUS || !cpu_online(cpu))
@@ -250,7 +249,6 @@ static int msr_device_create(int i)
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int msr_class_cpu_callback(struct notifier_block *nfb,
                                unsigned long action, void *hcpu)
 {
@@ -271,7 +269,6 @@ static struct notifier_block __cpuinitdata msr_class_cpu_notifier =
 {
        .notifier_call = msr_class_cpu_callback,
 };
-#endif
 
 static int __init msr_init(void)
 {
index eaafe23..a5e34d6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/percpu.h>
 #include <linux/dmi.h>
 #include <linux/kprobes.h>
+#include <linux/cpumask.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
@@ -42,6 +43,8 @@ int nmi_watchdog_enabled;
 static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner);
 static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]);
 
+static cpumask_t backtrace_mask = CPU_MASK_NONE;
+
 /* 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)
  */
@@ -192,6 +195,8 @@ static __cpuinit inline int nmi_known_cpu(void)
        return 0;
 }
 
+static int endflag __initdata = 0;
+
 #ifdef CONFIG_SMP
 /* The performance counters used by NMI_LOCAL_APIC don't trigger when
  * the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -199,7 +204,6 @@ static __cpuinit inline int nmi_known_cpu(void)
  */
 static __init void nmi_cpu_busy(void *data)
 {
-       volatile int *endflag = data;
        local_irq_enable_in_hardirq();
        /* Intentionally don't use cpu_relax here. This is
           to make sure that the performance counter really ticks,
@@ -207,14 +211,13 @@ static __init void nmi_cpu_busy(void *data)
           pause instruction. On a real HT machine this is fine because
           all other CPUs are busy with "useless" delay loops and don't
           care if they get somewhat less cycles. */
-       while (*endflag == 0)
-               barrier();
+       while (endflag == 0)
+               mb();
 }
 #endif
 
 static int __init check_nmi_watchdog(void)
 {
-       volatile int endflag = 0;
        unsigned int *prev_nmi_count;
        int cpu;
 
@@ -867,14 +870,16 @@ static unsigned int
 
 void touch_nmi_watchdog (void)
 {
-       int i;
+       if (nmi_watchdog > 0) {
+               unsigned cpu;
 
-       /*
-        * Just reset the alert counters, (other CPUs might be
-        * spinning on locks we hold):
-        */
-       for_each_possible_cpu(i)
-               alert_counter[i] = 0;
+               /*
+                * Just reset the alert counters, (other CPUs might be
+                * spinning on locks we hold):
+                */
+               for_each_present_cpu (cpu)
+                       alert_counter[cpu] = 0;
+       }
 
        /*
         * Tickle the softlockup detector too:
@@ -907,6 +912,16 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                touched = 1;
        }
 
+       if (cpu_isset(cpu, backtrace_mask)) {
+               static DEFINE_SPINLOCK(lock);   /* Serialise the printks */
+
+               spin_lock(&lock);
+               printk("NMI backtrace for cpu %d\n", cpu);
+               dump_stack();
+               spin_unlock(&lock);
+               cpu_clear(cpu, backtrace_mask);
+       }
+
        sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
 
        /* if the apic timer isn't firing, this cpu isn't doing much */
@@ -1033,6 +1048,19 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
 
 #endif
 
+void __trigger_all_cpu_backtrace(void)
+{
+       int i;
+
+       backtrace_mask = cpu_online_map;
+       /* Wait for up to 10 seconds for all CPUs to do the backtrace */
+       for (i = 0; i < 10 * 1000; i++) {
+               if (cpus_empty(backtrace_mask))
+                       break;
+               mdelay(1);
+       }
+}
+
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
new file mode 100644 (file)
index 0000000..3dceab5
--- /dev/null
@@ -0,0 +1,569 @@
+/*  Paravirtualization interfaces
+    Copyright (C) 2006 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+#include <linux/bcd.h>
+#include <linux/start_kernel.h>
+
+#include <asm/bug.h>
+#include <asm/paravirt.h>
+#include <asm/desc.h>
+#include <asm/setup.h>
+#include <asm/arch_hooks.h>
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/fixmap.h>
+#include <asm/apic.h>
+#include <asm/tlbflush.h>
+
+/* nop stub */
+static void native_nop(void)
+{
+}
+
+static void __init default_banner(void)
+{
+       printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
+              paravirt_ops.name);
+}
+
+char *memory_setup(void)
+{
+       return paravirt_ops.memory_setup();
+}
+
+/* Simple instruction patching code. */
+#define DEF_NATIVE(name, code)                                 \
+       extern const char start_##name[], end_##name[];         \
+       asm("start_" #name ": " code "; end_" #name ":")
+DEF_NATIVE(cli, "cli");
+DEF_NATIVE(sti, "sti");
+DEF_NATIVE(popf, "push %eax; popf");
+DEF_NATIVE(pushf, "pushf; pop %eax");
+DEF_NATIVE(pushf_cli, "pushf; pop %eax; cli");
+DEF_NATIVE(iret, "iret");
+DEF_NATIVE(sti_sysexit, "sti; sysexit");
+
+static const struct native_insns
+{
+       const char *start, *end;
+} native_insns[] = {
+       [PARAVIRT_IRQ_DISABLE] = { start_cli, end_cli },
+       [PARAVIRT_IRQ_ENABLE] = { start_sti, end_sti },
+       [PARAVIRT_RESTORE_FLAGS] = { start_popf, end_popf },
+       [PARAVIRT_SAVE_FLAGS] = { start_pushf, end_pushf },
+       [PARAVIRT_SAVE_FLAGS_IRQ_DISABLE] = { start_pushf_cli, end_pushf_cli },
+       [PARAVIRT_INTERRUPT_RETURN] = { start_iret, end_iret },
+       [PARAVIRT_STI_SYSEXIT] = { start_sti_sysexit, end_sti_sysexit },
+};
+
+static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len)
+{
+       unsigned int insn_len;
+
+       /* Don't touch it if we don't have a replacement */
+       if (type >= ARRAY_SIZE(native_insns) || !native_insns[type].start)
+               return len;
+
+       insn_len = native_insns[type].end - native_insns[type].start;
+
+       /* Similarly if we can't fit replacement. */
+       if (len < insn_len)
+               return len;
+
+       memcpy(insns, native_insns[type].start, insn_len);
+       return insn_len;
+}
+
+static fastcall unsigned long native_get_debugreg(int regno)
+{
+       unsigned long val = 0;  /* Damn you, gcc! */
+
+       switch (regno) {
+       case 0:
+               asm("movl %%db0, %0" :"=r" (val)); break;
+       case 1:
+               asm("movl %%db1, %0" :"=r" (val)); break;
+       case 2:
+               asm("movl %%db2, %0" :"=r" (val)); break;
+       case 3:
+               asm("movl %%db3, %0" :"=r" (val)); break;
+       case 6:
+               asm("movl %%db6, %0" :"=r" (val)); break;
+       case 7:
+               asm("movl %%db7, %0" :"=r" (val)); break;
+       default:
+               BUG();
+       }
+       return val;
+}
+
+static fastcall void native_set_debugreg(int regno, unsigned long value)
+{
+       switch (regno) {
+       case 0:
+               asm("movl %0,%%db0"     : /* no output */ :"r" (value));
+               break;
+       case 1:
+               asm("movl %0,%%db1"     : /* no output */ :"r" (value));
+               break;
+       case 2:
+               asm("movl %0,%%db2"     : /* no output */ :"r" (value));
+               break;
+       case 3:
+               asm("movl %0,%%db3"     : /* no output */ :"r" (value));
+               break;
+       case 6:
+               asm("movl %0,%%db6"     : /* no output */ :"r" (value));
+               break;
+       case 7:
+               asm("movl %0,%%db7"     : /* no output */ :"r" (value));
+               break;
+       default:
+               BUG();
+       }
+}
+
+void init_IRQ(void)
+{
+       paravirt_ops.init_IRQ();
+}
+
+static fastcall void native_clts(void)
+{
+       asm volatile ("clts");
+}
+
+static fastcall unsigned long native_read_cr0(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static fastcall void native_write_cr0(unsigned long val)
+{
+       asm volatile("movl %0,%%cr0": :"r" (val));
+}
+
+static fastcall unsigned long native_read_cr2(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static fastcall void native_write_cr2(unsigned long val)
+{
+       asm volatile("movl %0,%%cr2": :"r" (val));
+}
+
+static fastcall unsigned long native_read_cr3(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static fastcall void native_write_cr3(unsigned long val)
+{
+       asm volatile("movl %0,%%cr3": :"r" (val));
+}
+
+static fastcall unsigned long native_read_cr4(void)
+{
+       unsigned long val;
+       asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
+       return val;
+}
+
+static fastcall unsigned long native_read_cr4_safe(void)
+{
+       unsigned long val;
+       /* This could fault if %cr4 does not exist */
+       asm("1: movl %%cr4, %0          \n"
+               "2:                             \n"
+               ".section __ex_table,\"a\"      \n"
+               ".long 1b,2b                    \n"
+               ".previous                      \n"
+               : "=r" (val): "0" (0));
+       return val;
+}
+
+static fastcall void native_write_cr4(unsigned long val)
+{
+       asm volatile("movl %0,%%cr4": :"r" (val));
+}
+
+static fastcall unsigned long native_save_fl(void)
+{
+       unsigned long f;
+       asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
+       return f;
+}
+
+static fastcall void native_restore_fl(unsigned long f)
+{
+       asm volatile("pushl %0 ; popfl": /* no output */
+                            :"g" (f)
+                            :"memory", "cc");
+}
+
+static fastcall void native_irq_disable(void)
+{
+       asm volatile("cli": : :"memory");
+}
+
+static fastcall void native_irq_enable(void)
+{
+       asm volatile("sti": : :"memory");
+}
+
+static fastcall void native_safe_halt(void)
+{
+       asm volatile("sti; hlt": : :"memory");
+}
+
+static fastcall void native_halt(void)
+{
+       asm volatile("hlt": : :"memory");
+}
+
+static fastcall void native_wbinvd(void)
+{
+       asm volatile("wbinvd": : :"memory");
+}
+
+static fastcall unsigned long long native_read_msr(unsigned int msr, int *err)
+{
+       unsigned long long val;
+
+       asm volatile("2: rdmsr ; xorl %0,%0\n"
+                    "1:\n\t"
+                    ".section .fixup,\"ax\"\n\t"
+                    "3:  movl %3,%0 ; jmp 1b\n\t"
+                    ".previous\n\t"
+                    ".section __ex_table,\"a\"\n"
+                    "   .align 4\n\t"
+                    "   .long  2b,3b\n\t"
+                    ".previous"
+                    : "=r" (*err), "=A" (val)
+                    : "c" (msr), "i" (-EFAULT));
+
+       return val;
+}
+
+static fastcall int native_write_msr(unsigned int msr, unsigned long long val)
+{
+       int err;
+       asm volatile("2: wrmsr ; xorl %0,%0\n"
+                    "1:\n\t"
+                    ".section .fixup,\"ax\"\n\t"
+                    "3:  movl %4,%0 ; jmp 1b\n\t"
+                    ".previous\n\t"
+                    ".section __ex_table,\"a\"\n"
+                    "   .align 4\n\t"
+                    "   .long  2b,3b\n\t"
+                    ".previous"
+                    : "=a" (err)
+                    : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
+                      "i" (-EFAULT));
+       return err;
+}
+
+static fastcall unsigned long long native_read_tsc(void)
+{
+       unsigned long long val;
+       asm volatile("rdtsc" : "=A" (val));
+       return val;
+}
+
+static fastcall unsigned long long native_read_pmc(void)
+{
+       unsigned long long val;
+       asm volatile("rdpmc" : "=A" (val));
+       return val;
+}
+
+static fastcall void native_load_tr_desc(void)
+{
+       asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static fastcall void native_load_gdt(const struct Xgt_desc_struct *dtr)
+{
+       asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static fastcall void native_load_idt(const struct Xgt_desc_struct *dtr)
+{
+       asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static fastcall void native_store_gdt(struct Xgt_desc_struct *dtr)
+{
+       asm ("sgdt %0":"=m" (*dtr));
+}
+
+static fastcall void native_store_idt(struct Xgt_desc_struct *dtr)
+{
+       asm ("sidt %0":"=m" (*dtr));
+}
+
+static fastcall unsigned long native_store_tr(void)
+{
+       unsigned long tr;
+       asm ("str %0":"=r" (tr));
+       return tr;
+}
+
+static fastcall void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+#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 native_write_dt_entry(void *dt, int entry, u32 entry_low, u32 entry_high)
+{
+       u32 *lp = (u32 *)((char *)dt + entry*8);
+       lp[0] = entry_low;
+       lp[1] = entry_high;
+}
+
+static fastcall void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
+{
+       native_write_dt_entry(dt, entrynum, low, high);
+}
+
+static fastcall void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
+{
+       native_write_dt_entry(dt, entrynum, low, high);
+}
+
+static fastcall void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
+{
+       native_write_dt_entry(dt, entrynum, low, high);
+}
+
+static fastcall void native_load_esp0(struct tss_struct *tss,
+                                     struct thread_struct *thread)
+{
+       tss->esp0 = thread->esp0;
+
+       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
+       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+               tss->ss1 = thread->sysenter_cs;
+               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+       }
+}
+
+static fastcall void native_io_delay(void)
+{
+       asm volatile("outb %al,$0x80");
+}
+
+static fastcall void native_flush_tlb(void)
+{
+       __native_flush_tlb();
+}
+
+/*
+ * Global pages have to be flushed a bit differently. Not a real
+ * performance problem because this does not happen often.
+ */
+static fastcall void native_flush_tlb_global(void)
+{
+       __native_flush_tlb_global();
+}
+
+static fastcall void native_flush_tlb_single(u32 addr)
+{
+       __native_flush_tlb_single(addr);
+}
+
+#ifndef CONFIG_X86_PAE
+static fastcall void native_set_pte(pte_t *ptep, pte_t pteval)
+{
+       *ptep = pteval;
+}
+
+static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
+{
+       *ptep = pteval;
+}
+
+static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+       *pmdp = pmdval;
+}
+
+#else /* CONFIG_X86_PAE */
+
+static fastcall void native_set_pte(pte_t *ptep, pte_t pte)
+{
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
+}
+
+static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+{
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
+}
+
+static fastcall void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+       ptep->pte_low = 0;
+       smp_wmb();
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
+}
+
+static fastcall void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
+{
+       set_64bit((unsigned long long *)ptep,pte_val(pteval));
+}
+
+static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+       set_64bit((unsigned long long *)pmdp,pmd_val(pmdval));
+}
+
+static fastcall void native_set_pud(pud_t *pudp, pud_t pudval)
+{
+       *pudp = pudval;
+}
+
+static fastcall void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       ptep->pte_low = 0;
+       smp_wmb();
+       ptep->pte_high = 0;
+}
+
+static fastcall void native_pmd_clear(pmd_t *pmd)
+{
+       u32 *tmp = (u32 *)pmd;
+       *tmp = 0;
+       smp_wmb();
+       *(tmp + 1) = 0;
+}
+#endif /* CONFIG_X86_PAE */
+
+/* These are in entry.S */
+extern fastcall void native_iret(void);
+extern fastcall void native_irq_enable_sysexit(void);
+
+static int __init print_banner(void)
+{
+       paravirt_ops.banner();
+       return 0;
+}
+core_initcall(print_banner);
+
+/* We simply declare start_kernel to be the paravirt probe of last resort. */
+paravirt_probe(start_kernel);
+
+struct paravirt_ops paravirt_ops = {
+       .name = "bare hardware",
+       .paravirt_enabled = 0,
+       .kernel_rpl = 0,
+
+       .patch = native_patch,
+       .banner = default_banner,
+       .arch_setup = native_nop,
+       .memory_setup = machine_specific_memory_setup,
+       .get_wallclock = native_get_wallclock,
+       .set_wallclock = native_set_wallclock,
+       .time_init = time_init_hook,
+       .init_IRQ = native_init_IRQ,
+
+       .cpuid = native_cpuid,
+       .get_debugreg = native_get_debugreg,
+       .set_debugreg = native_set_debugreg,
+       .clts = native_clts,
+       .read_cr0 = native_read_cr0,
+       .write_cr0 = native_write_cr0,
+       .read_cr2 = native_read_cr2,
+       .write_cr2 = native_write_cr2,
+       .read_cr3 = native_read_cr3,
+       .write_cr3 = native_write_cr3,
+       .read_cr4 = native_read_cr4,
+       .read_cr4_safe = native_read_cr4_safe,
+       .write_cr4 = native_write_cr4,
+       .save_fl = native_save_fl,
+       .restore_fl = native_restore_fl,
+       .irq_disable = native_irq_disable,
+       .irq_enable = native_irq_enable,
+       .safe_halt = native_safe_halt,
+       .halt = native_halt,
+       .wbinvd = native_wbinvd,
+       .read_msr = native_read_msr,
+       .write_msr = native_write_msr,
+       .read_tsc = native_read_tsc,
+       .read_pmc = native_read_pmc,
+       .load_tr_desc = native_load_tr_desc,
+       .set_ldt = native_set_ldt,
+       .load_gdt = native_load_gdt,
+       .load_idt = native_load_idt,
+       .store_gdt = native_store_gdt,
+       .store_idt = native_store_idt,
+       .store_tr = native_store_tr,
+       .load_tls = native_load_tls,
+       .write_ldt_entry = native_write_ldt_entry,
+       .write_gdt_entry = native_write_gdt_entry,
+       .write_idt_entry = native_write_idt_entry,
+       .load_esp0 = native_load_esp0,
+
+       .set_iopl_mask = native_set_iopl_mask,
+       .io_delay = native_io_delay,
+       .const_udelay = __const_udelay,
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       .apic_write = native_apic_write,
+       .apic_write_atomic = native_apic_write_atomic,
+       .apic_read = native_apic_read,
+#endif
+
+       .flush_tlb_user = native_flush_tlb,
+       .flush_tlb_kernel = native_flush_tlb_global,
+       .flush_tlb_single = native_flush_tlb_single,
+
+       .set_pte = native_set_pte,
+       .set_pte_at = native_set_pte_at,
+       .set_pmd = native_set_pmd,
+       .pte_update = (void *)native_nop,
+       .pte_update_defer = (void *)native_nop,
+#ifdef CONFIG_X86_PAE
+       .set_pte_atomic = native_set_pte_atomic,
+       .set_pte_present = native_set_pte_present,
+       .set_pud = native_set_pud,
+       .pte_clear = native_pte_clear,
+       .pmd_clear = native_pmd_clear,
+#endif
+
+       .irq_enable_sysexit = native_irq_enable_sysexit,
+       .iret = native_iret,
+};
+EXPORT_SYMBOL(paravirt_ops);
index 5c8c6ef..41af692 100644 (file)
@@ -92,14 +92,12 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
        if (!mem_base)
                goto out;
 
-       dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+       dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
        if (!dev->dma_mem)
                goto out;
-       memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
-       dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL);
+       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
        if (!dev->dma_mem->bitmap)
                goto free1_out;
-       memset(dev->dma_mem->bitmap, 0, bitmap_size);
 
        dev->dma_mem->virt_base = mem_base;
        dev->dma_mem->device_base = device_addr;
index dd53c58..9930851 100644 (file)
@@ -56,6 +56,7 @@
 
 #include <asm/tlbflush.h>
 #include <asm/cpu.h>
+#include <asm/pda.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -99,22 +100,18 @@ EXPORT_SYMBOL(enable_hlt);
  */
 void default_idle(void)
 {
-       local_irq_enable();
-
        if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
                current_thread_info()->status &= ~TS_POLLING;
                smp_mb__after_clear_bit();
-               while (!need_resched()) {
-                       local_irq_disable();
-                       if (!need_resched())
-                               safe_halt();
-                       else
-                               local_irq_enable();
-               }
+               local_irq_disable();
+               if (!need_resched())
+                       safe_halt();    /* enables interrupts racelessly */
+               else
+                       local_irq_enable();
                current_thread_info()->status |= TS_POLLING;
        } else {
-               while (!need_resched())
-                       cpu_relax();
+               /* loop is done by the caller */
+               cpu_relax();
        }
 }
 #ifdef CONFIG_APM_MODULE
@@ -128,14 +125,7 @@ EXPORT_SYMBOL(default_idle);
  */
 static void poll_idle (void)
 {
-       local_irq_enable();
-
-       asm volatile(
-               "2:"
-               "testl %0, %1;"
-               "rep; nop;"
-               "je 2b;"
-               : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
+       cpu_relax();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -256,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
 static void mwait_idle(void)
 {
        local_irq_enable();
-       while (!need_resched())
-               mwait_idle_with_hints(0, 0);
+       mwait_idle_with_hints(0, 0);
 }
 
 void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
@@ -314,8 +303,8 @@ void show_regs(struct pt_regs * regs)
                regs->eax,regs->ebx,regs->ecx,regs->edx);
        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
                regs->esi, regs->edi, regs->ebp);
-       printk(" DS: %04x ES: %04x\n",
-               0xffff & regs->xds,0xffff & regs->xes);
+       printk(" DS: %04x ES: %04x GS: %04x\n",
+              0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
 
        cr0 = read_cr0();
        cr2 = read_cr2();
@@ -346,6 +335,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 
        regs.xds = __USER_DS;
        regs.xes = __USER_DS;
+       regs.xgs = __KERNEL_PDA;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
        regs.xcs = __KERNEL_CS | get_kernel_rpl();
@@ -431,7 +421,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
        p->thread.eip = (unsigned long) ret_from_fork;
 
        savesegment(fs,p->thread.fs);
-       savesegment(gs,p->thread.gs);
 
        tsk = current;
        if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
@@ -508,7 +497,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        dump->regs.ds = regs->xds;
        dump->regs.es = regs->xes;
        savesegment(fs,dump->regs.fs);
-       savesegment(gs,dump->regs.gs);
+       dump->regs.gs = regs->xgs;
        dump->regs.orig_eax = regs->orig_eax;
        dump->regs.eip = regs->eip;
        dump->regs.cs = regs->xcs;
@@ -648,22 +637,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 
        __unlazy_fpu(prev_p);
 
+
+       /* we're going to use this soon, after a few expensive things */
+       if (next_p->fpu_counter > 5)
+               prefetch(&next->i387.fxsave);
+
        /*
         * Reload esp0.
         */
        load_esp0(tss, next);
 
        /*
-        * Save away %fs and %gs. No need to save %es and %ds, as
-        * those are always kernel segments while inside the kernel.
-        * Doing this before setting the new TLS descriptors avoids
-        * the situation where we temporarily have non-reloadable
-        * segments in %fs and %gs.  This could be an issue if the
-        * NMI handler ever used %fs or %gs (it does not today), or
-        * if the kernel is running inside of a hypervisor layer.
+        * Save away %fs. No need to save %gs, as it was saved on the
+        * stack on entry.  No need to save %es and %ds, as those are
+        * always kernel segments while inside the kernel.  Doing this
+        * before setting the new TLS descriptors avoids the situation
+        * where we temporarily have non-reloadable segments in %fs
+        * and %gs.  This could be an issue if the NMI handler ever
+        * used %fs or %gs (it does not today), or if the kernel is
+        * running inside of a hypervisor layer.
         */
        savesegment(fs, prev->fs);
-       savesegment(gs, prev->gs);
 
        /*
         * Load the per-thread Thread-Local Storage descriptor.
@@ -671,22 +665,14 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        load_TLS(next, cpu);
 
        /*
-        * Restore %fs and %gs if needed.
+        * Restore %fs if needed.
         *
-        * Glibc normally makes %fs be zero, and %gs is one of
-        * the TLS segments.
+        * Glibc normally makes %fs be zero.
         */
        if (unlikely(prev->fs | next->fs))
                loadsegment(fs, next->fs);
 
-       if (prev->gs | next->gs)
-               loadsegment(gs, next->gs);
-
-       /*
-        * Restore IOPL if needed.
-        */
-       if (unlikely(prev->iopl != next->iopl))
-               set_iopl_mask(next->iopl);
+       write_pda(pcurrent, next_p);
 
        /*
         * Now maybe handle debug registers and/or IO bitmaps
@@ -697,6 +683,13 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 
        disable_tsc(prev_p, next_p);
 
+       /* 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;
 }
 
index 775f50e..f3f94ac 100644 (file)
@@ -94,13 +94,9 @@ static int putreg(struct task_struct *child,
                                return -EIO;
                        child->thread.fs = value;
                        return 0;
-               case GS:
-                       if (value && (value & 3) != 3)
-                               return -EIO;
-                       child->thread.gs = value;
-                       return 0;
                case DS:
                case ES:
+               case GS:
                        if (value && (value & 3) != 3)
                                return -EIO;
                        value &= 0xffff;
@@ -116,8 +112,8 @@ static int putreg(struct task_struct *child,
                        value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
                        break;
        }
-       if (regno > GS*4)
-               regno -= 2*4;
+       if (regno > ES*4)
+               regno -= 1*4;
        put_stack_long(child, regno - sizeof(struct pt_regs), value);
        return 0;
 }
@@ -131,18 +127,16 @@ static unsigned long getreg(struct task_struct *child,
                case FS:
                        retval = child->thread.fs;
                        break;
-               case GS:
-                       retval = child->thread.gs;
-                       break;
                case DS:
                case ES:
+               case GS:
                case SS:
                case CS:
                        retval = 0xffff;
                        /* fall through */
                default:
-                       if (regno > GS*4)
-                               regno -= 2*4;
+                       if (regno > ES*4)
+                               regno -= 1*4;
                        regno = regno - sizeof(struct pt_regs);
                        retval &= get_stack_long(child, regno);
        }
index 9f6ab17..34874c3 100644 (file)
@@ -3,10 +3,12 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <asm/pci-direct.h>
+#include <asm/genapic.h>
+#include <asm/cpu.h>
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
-
-static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
 {
        u8 config, rev;
        u32 word;
@@ -14,14 +16,12 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
        /* BIOS may enable hardware IRQ balancing for
         * E7520/E7320/E7525(revision ID 0x9 and below)
         * based platforms.
-        * Disable SW irqbalance/affinity on those platforms.
+        * For those platforms, make sure that the genapic is set to 'flat'
         */
        pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
        if (rev > 0x9)
                return;
 
-       printk(KERN_INFO "Intel E7520/7320/7525 detected.");
-
        /* enable access to config space*/
        pci_read_config_byte(dev, 0xf4, &config);
        pci_write_config_byte(dev, 0xf4, config|0x2);
@@ -29,6 +29,44 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
        /* read xTPR register */
        raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
+       if (!(word & (1 << 13))) {
+#ifdef CONFIG_X86_64
+               if (genapic !=  &apic_flat)
+                       panic("APIC mode must be flat on this system\n");
+#elif defined(CONFIG_X86_GENERICARCH)
+               if (genapic != &apic_default)
+                       panic("APIC mode must be default(flat) on this system. Use apic=default\n");
+#endif
+       }
+
+       /* put back the original value for config space*/
+       if (!(config & 0x2))
+               pci_write_config_byte(dev, 0xf4, config);
+}
+
+void __init quirk_intel_irqbalance(void)
+{
+       u8 config, rev;
+       u32 word;
+
+       /* BIOS may enable hardware IRQ balancing for
+        * E7520/E7320/E7525(revision ID 0x9 and below)
+        * based platforms.
+        * Disable SW irqbalance/affinity on those platforms.
+        */
+       rev = read_pci_config_byte(0, 0, 0, PCI_CLASS_REVISION);
+       if (rev > 0x9)
+               return;
+
+       printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
+       /* enable access to config space */
+       config = read_pci_config_byte(0, 0, 0, 0xf4);
+       write_pci_config_byte(0, 0, 0, 0xf4, config|0x2);
+
+       /* read xTPR register */
+       word = read_pci_config_16(0, 0, 0x40, 0x4c);
+
        if (!(word & (1 << 13))) {
                printk(KERN_INFO "Disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
@@ -37,14 +75,25 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
                noirqdebug_setup("");
 #ifdef CONFIG_PROC_FS
                no_irq_affinity = 1;
+#endif
+#ifdef CONFIG_HOTPLUG_CPU
+               printk(KERN_INFO "Disabling cpu hotplug control\n");
+               enable_cpu_hotplug = 0;
+#endif
+#ifdef CONFIG_X86_64
+               /* force the genapic selection to flat mode so that
+                * interrupts can be redirected to more than one CPU.
+                */
+               genapic_force = &apic_flat;
 #endif
        }
 
-       /* put back the original value for config space*/
+       /* put back the original value for config space */
        if (!(config & 0x2))
-               pci_write_config_byte(dev, 0xf4, config);
+               write_pci_config_byte(0, 0, 0, 0xf4, config);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  verify_quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  verify_quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  verify_quirk_intel_irqbalance);
+
 #endif
index 84278e0..3514b41 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/dmi.h>
 #include <linux/ctype.h>
 #include <linux/pm.h>
+#include <linux/reboot.h>
 #include <asm/uaccess.h>
 #include <asm/apic.h>
 #include <asm/desc.h>
index 141041d..79df6e6 100644 (file)
@@ -63,9 +63,6 @@
 #include <setup_arch.h>
 #include <bios_ebda.h>
 
-/* Forward Declaration. */
-void __init find_max_pfn(void);
-
 /* This value is set up by the early boot code to point to the value
    immediately after the boot time page tables.  It contains a *physical*
    address, and must not be in the .bss segment! */
@@ -76,11 +73,8 @@ int disable_pse __devinitdata = 0;
 /*
  * Machine setup..
  */
-
-#ifdef CONFIG_EFI
-int efi_enabled = 0;
-EXPORT_SYMBOL(efi_enabled);
-#endif
+extern struct resource code_resource;
+extern struct resource data_resource;
 
 /* cpu data as detected by the assembly code in head.S */
 struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
@@ -99,12 +93,6 @@ unsigned int machine_submodel_id;
 unsigned int BIOS_revision;
 unsigned int mca_pentium_flag;
 
-/* For PCI or other memory-mapped resources */
-unsigned long pci_mem_start = 0x10000000;
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_mem_start);
-#endif
-
 /* Boot loader ID as an integer, for the benefit of proc_dointvec */
 int bootloader_type;
 
@@ -134,7 +122,6 @@ struct ist_info ist_info;
        defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
 EXPORT_SYMBOL(ist_info);
 #endif
-struct e820map e820;
 
 extern void early_cpu_init(void);
 extern int root_mountflags;
@@ -149,516 +136,6 @@ static char command_line[COMMAND_LINE_SIZE];
 
 unsigned char __initdata boot_params[PARAM_SIZE];
 
-static struct resource data_resource = {
-       .name   = "Kernel data",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource code_resource = {
-       .name   = "Kernel code",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource system_rom_resource = {
-       .name   = "System ROM",
-       .start  = 0xf0000,
-       .end    = 0xfffff,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource extension_rom_resource = {
-       .name   = "Extension ROM",
-       .start  = 0xe0000,
-       .end    = 0xeffff,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource adapter_rom_resources[] = { {
-       .name   = "Adapter ROM",
-       .start  = 0xc8000,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-       .name   = "Adapter ROM",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-       .name   = "Adapter ROM",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-       .name   = "Adapter ROM",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-       .name   = "Adapter ROM",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-       .name   = "Adapter ROM",
-       .start  = 0,
-       .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-} };
-
-static struct resource video_rom_resource = {
-       .name   = "Video ROM",
-       .start  = 0xc0000,
-       .end    = 0xc7fff,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource video_ram_resource = {
-       .name   = "Video RAM area",
-       .start  = 0xa0000,
-       .end    = 0xbffff,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource standard_io_resources[] = { {
-       .name   = "dma1",
-       .start  = 0x0000,
-       .end    = 0x001f,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "pic1",
-       .start  = 0x0020,
-       .end    = 0x0021,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "timer0",
-       .start  = 0x0040,
-       .end    = 0x0043,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "timer1",
-       .start  = 0x0050,
-       .end    = 0x0053,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "keyboard",
-       .start  = 0x0060,
-       .end    = 0x006f,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "dma page reg",
-       .start  = 0x0080,
-       .end    = 0x008f,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "pic2",
-       .start  = 0x00a0,
-       .end    = 0x00a1,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "dma2",
-       .start  = 0x00c0,
-       .end    = 0x00df,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-       .name   = "fpu",
-       .start  = 0x00f0,
-       .end    = 0x00ff,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
-} };
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static int __init romchecksum(unsigned char *rom, unsigned long length)
-{
-       unsigned char *p, sum = 0;
-
-       for (p = rom; p < rom + length; p++)
-               sum += *p;
-       return sum == 0;
-}
-
-static void __init probe_roms(void)
-{
-       unsigned long start, length, upper;
-       unsigned char *rom;
-       int           i;
-
-       /* video rom */
-       upper = adapter_rom_resources[0].start;
-       for (start = video_rom_resource.start; start < upper; start += 2048) {
-               rom = isa_bus_to_virt(start);
-               if (!romsignature(rom))
-                       continue;
-
-               video_rom_resource.start = start;
-
-               /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
-
-               /* if checksum okay, trust length byte */
-               if (length && romchecksum(rom, length))
-                       video_rom_resource.end = start + length - 1;
-
-               request_resource(&iomem_resource, &video_rom_resource);
-               break;
-       }
-
-       start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
-       if (start < upper)
-               start = upper;
-
-       /* system rom */
-       request_resource(&iomem_resource, &system_rom_resource);
-       upper = system_rom_resource.start;
-
-       /* check for extension rom (ignore length byte!) */
-       rom = isa_bus_to_virt(extension_rom_resource.start);
-       if (romsignature(rom)) {
-               length = extension_rom_resource.end - extension_rom_resource.start + 1;
-               if (romchecksum(rom, length)) {
-                       request_resource(&iomem_resource, &extension_rom_resource);
-                       upper = extension_rom_resource.start;
-               }
-       }
-
-       /* check for adapter roms on 2k boundaries */
-       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
-               rom = isa_bus_to_virt(start);
-               if (!romsignature(rom))
-                       continue;
-
-               /* 0 < length <= 0x7f * 512, historically */
-               length = rom[2] * 512;
-
-               /* but accept any length that fits if checksum okay */
-               if (!length || start + length > upper || !romchecksum(rom, length))
-                       continue;
-
-               adapter_rom_resources[i].start = start;
-               adapter_rom_resources[i].end = start + length - 1;
-               request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
-               start = adapter_rom_resources[i++].end & ~2047UL;
-       }
-}
-
-static void __init limit_regions(unsigned long long size)
-{
-       unsigned long long current_addr = 0;
-       int i;
-
-       if (efi_enabled) {
-               efi_memory_desc_t *md;
-               void *p;
-
-               for (p = memmap.map, i = 0; p < memmap.map_end;
-                       p += memmap.desc_size, i++) {
-                       md = p;
-                       current_addr = md->phys_addr + (md->num_pages << 12);
-                       if (md->type == EFI_CONVENTIONAL_MEMORY) {
-                               if (current_addr >= size) {
-                                       md->num_pages -=
-                                               (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
-                                       memmap.nr_map = i + 1;
-                                       return;
-                               }
-                       }
-               }
-       }
-       for (i = 0; i < e820.nr_map; i++) {
-               current_addr = e820.map[i].addr + e820.map[i].size;
-               if (current_addr < size)
-                       continue;
-
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-
-               if (e820.map[i].addr >= size) {
-                       /*
-                        * This region starts past the end of the
-                        * requested size, skip it completely.
-                        */
-                       e820.nr_map = i;
-               } else {
-                       e820.nr_map = i + 1;
-                       e820.map[i].size -= current_addr - size;
-               }
-               return;
-       }
-}
-
-void __init add_memory_region(unsigned long long start,
-                             unsigned long long size, int type)
-{
-       int x;
-
-       if (!efi_enabled) {
-                       x = e820.nr_map;
-
-               if (x == E820MAX) {
-                   printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
-                   return;
-               }
-
-               e820.map[x].addr = start;
-               e820.map[x].size = size;
-               e820.map[x].type = type;
-               e820.nr_map++;
-       }
-} /* add_memory_region */
-
-#define E820_DEBUG     1
-
-static void __init print_memory_map(char *who)
-{
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               printk(" %s: %016Lx - %016Lx ", who,
-                       e820.map[i].addr,
-                       e820.map[i].addr + e820.map[i].size);
-               switch (e820.map[i].type) {
-               case E820_RAM:  printk("(usable)\n");
-                               break;
-               case E820_RESERVED:
-                               printk("(reserved)\n");
-                               break;
-               case E820_ACPI:
-                               printk("(ACPI data)\n");
-                               break;
-               case E820_NVS:
-                               printk("(ACPI NVS)\n");
-                               break;
-               default:        printk("type %lu\n", e820.map[i].type);
-                               break;
-               }
-       }
-}
-
-/*
- * Sanitize the BIOS e820 map.
- *
- * Some e820 responses include overlapping entries.  The following 
- * replaces the original e820 map with a new one, removing overlaps.
- *
- */
-struct change_member {
-       struct e820entry *pbios; /* pointer to original bios entry */
-       unsigned long long addr; /* address for this change point */
-};
-static struct change_member change_point_list[2*E820MAX] __initdata;
-static struct change_member *change_point[2*E820MAX] __initdata;
-static struct e820entry *overlap_list[E820MAX] __initdata;
-static struct e820entry new_bios[E820MAX] __initdata;
-
-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
-{
-       struct change_member *change_tmp;
-       unsigned long current_type, last_type;
-       unsigned long long last_addr;
-       int chgidx, still_changing;
-       int overlap_entries;
-       int new_bios_entry;
-       int old_nr, new_nr, chg_nr;
-       int i;
-
-       /*
-               Visually we're performing the following (1,2,3,4 = memory types)...
-
-               Sample memory map (w/overlaps):
-                  ____22__________________
-                  ______________________4_
-                  ____1111________________
-                  _44_____________________
-                  11111111________________
-                  ____________________33__
-                  ___________44___________
-                  __________33333_________
-                  ______________22________
-                  ___________________2222_
-                  _________111111111______
-                  _____________________11_
-                  _________________4______
-
-               Sanitized equivalent (no overlap):
-                  1_______________________
-                  _44_____________________
-                  ___1____________________
-                  ____22__________________
-                  ______11________________
-                  _________1______________
-                  __________3_____________
-                  ___________44___________
-                  _____________33_________
-                  _______________2________
-                  ________________1_______
-                  _________________4______
-                  ___________________2____
-                  ____________________33__
-                  ______________________4_
-       */
-
-       /* if there's only one memory region, don't bother */
-       if (*pnr_map < 2)
-               return -1;
-
-       old_nr = *pnr_map;
-
-       /* bail out if we find any unreasonable addresses in bios map */
-       for (i=0; i<old_nr; i++)
-               if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
-                       return -1;
-
-       /* create pointers for initial change-point information (for sorting) */
-       for (i=0; i < 2*old_nr; i++)
-               change_point[i] = &change_point_list[i];
-
-       /* record all known change-points (starting and ending addresses),
-          omitting those that are for empty memory regions */
-       chgidx = 0;
-       for (i=0; i < old_nr; i++)      {
-               if (biosmap[i].size != 0) {
-                       change_point[chgidx]->addr = biosmap[i].addr;
-                       change_point[chgidx++]->pbios = &biosmap[i];
-                       change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
-                       change_point[chgidx++]->pbios = &biosmap[i];
-               }
-       }
-       chg_nr = chgidx;        /* true number of change-points */
-
-       /* sort change-point list by memory addresses (low -> high) */
-       still_changing = 1;
-       while (still_changing)  {
-               still_changing = 0;
-               for (i=1; i < chg_nr; i++)  {
-                       /* if <current_addr> > <last_addr>, swap */
-                       /* or, if current=<start_addr> & last=<end_addr>, swap */
-                       if ((change_point[i]->addr < change_point[i-1]->addr) ||
-                               ((change_point[i]->addr == change_point[i-1]->addr) &&
-                                (change_point[i]->addr == change_point[i]->pbios->addr) &&
-                                (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
-                          )
-                       {
-                               change_tmp = change_point[i];
-                               change_point[i] = change_point[i-1];
-                               change_point[i-1] = change_tmp;
-                               still_changing=1;
-                       }
-               }
-       }
-
-       /* create a new bios memory map, removing overlaps */
-       overlap_entries=0;       /* number of entries in the overlap table */
-       new_bios_entry=0;        /* index for creating new bios map entries */
-       last_type = 0;           /* start with undefined memory type */
-       last_addr = 0;           /* start with 0 as last starting address */
-       /* loop through change-points, determining affect on the new bios map */
-       for (chgidx=0; chgidx < chg_nr; chgidx++)
-       {
-               /* keep track of all overlapping bios entries */
-               if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
-               {
-                       /* add map entry to overlap list (> 1 entry implies an overlap) */
-                       overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
-               }
-               else
-               {
-                       /* remove entry from list (order independent, so swap with last) */
-                       for (i=0; i<overlap_entries; i++)
-                       {
-                               if (overlap_list[i] == change_point[chgidx]->pbios)
-                                       overlap_list[i] = overlap_list[overlap_entries-1];
-                       }
-                       overlap_entries--;
-               }
-               /* if there are overlapping entries, decide which "type" to use */
-               /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
-               current_type = 0;
-               for (i=0; i<overlap_entries; i++)
-                       if (overlap_list[i]->type > current_type)
-                               current_type = overlap_list[i]->type;
-               /* continue building up new bios map based on this information */
-               if (current_type != last_type)  {
-                       if (last_type != 0)      {
-                               new_bios[new_bios_entry].size =
-                                       change_point[chgidx]->addr - last_addr;
-                               /* move forward only if the new size was non-zero */
-                               if (new_bios[new_bios_entry].size != 0)
-                                       if (++new_bios_entry >= E820MAX)
-                                               break;  /* no more space left for new bios entries */
-                       }
-                       if (current_type != 0)  {
-                               new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
-                               new_bios[new_bios_entry].type = current_type;
-                               last_addr=change_point[chgidx]->addr;
-                       }
-                       last_type = current_type;
-               }
-       }
-       new_nr = new_bios_entry;   /* retain count for new bios entries */
-
-       /* copy new bios mapping into original location */
-       memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
-       *pnr_map = new_nr;
-
-       return 0;
-}
-
-/*
- * Copy the BIOS e820 map into a safe place.
- *
- * Sanity-check it while we're at it..
- *
- * 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.)
- */
-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
-{
-       /* Only one memory region (or negative)? Ignore it */
-       if (nr_map < 2)
-               return -1;
-
-       do {
-               unsigned long long start = biosmap->addr;
-               unsigned long long size = biosmap->size;
-               unsigned long long end = start + size;
-               unsigned long type = biosmap->type;
-
-               /* Overflow in 64 bits? Ignore the memory map. */
-               if (start > end)
-                       return -1;
-
-               /*
-                * Some BIOSes claim RAM in the 640k - 1M region.
-                * Not right. Fix it up.
-                */
-               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;
-}
-
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
 #ifdef CONFIG_EDD_MODULE
@@ -682,7 +159,7 @@ static inline void copy_edd(void)
 }
 #endif
 
-static int __initdata user_defined_memmap = 0;
+int __initdata user_defined_memmap = 0;
 
 /*
  * "mem=nopentium" disables the 4MB page tables.
@@ -719,51 +196,6 @@ static int __init parse_mem(char *arg)
 }
 early_param("mem", parse_mem);
 
-static int __init parse_memmap(char *arg)
-{
-       if (!arg)
-               return -EINVAL;
-
-       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.
-                */
-               find_max_pfn();
-               saved_max_pfn = max_pfn;
-#endif
-               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);
-
 #ifdef CONFIG_PROC_VMCORE
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel.
@@ -827,90 +259,6 @@ static int __init parse_reservetop(char *arg)
 }
 early_param("reservetop", parse_reservetop);
 
-/*
- * Callback for efi_memory_walk.
- */
-static int __init
-efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
-{
-       unsigned long *max_pfn = arg, pfn;
-
-       if (start < end) {
-               pfn = PFN_UP(end -1);
-               if (pfn > *max_pfn)
-                       *max_pfn = pfn;
-       }
-       return 0;
-}
-
-static int __init
-efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
-{
-       memory_present(0, PFN_UP(start), PFN_DOWN(end));
-       return 0;
-}
-
- /*
-  * This function checks if the entire range <start,end> is mapped with type.
-  *
-  * Note: this function only works correct if the e820 table is sorted and
-  * not-overlapping, which is the case
-  */
-int __init
-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
-{
-       u64 start = s;
-       u64 end = e;
-       int i;
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i];
-               if (type && ei->type != type)
-                       continue;
-               /* is the region (part) in overlap with the current region ?*/
-               if (ei->addr >= end || ei->addr + ei->size <= start)
-                       continue;
-               /* if the region is at the beginning of <start,end> we move
-                * start to the end of the region since it's ok until there
-                */
-               if (ei->addr <= start)
-                       start = ei->addr + ei->size;
-               /* if start is now at or beyond end, we're done, full
-                * coverage */
-               if (start >= end)
-                       return 1; /* we're done */
-       }
-       return 0;
-}
-
-/*
- * Find the highest page frame number we have available
- */
-void __init find_max_pfn(void)
-{
-       int i;
-
-       max_pfn = 0;
-       if (efi_enabled) {
-               efi_memmap_walk(efi_find_max_pfn, &max_pfn);
-               efi_memmap_walk(efi_memory_present_wrapper, NULL);
-               return;
-       }
-
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long start, end;
-               /* RAM? */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               start = PFN_UP(e820.map[i].addr);
-               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-               if (start >= end)
-                       continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-               memory_present(0, start, end);
-       }
-}
-
 /*
  * Determine low and high memory ranges:
  */
@@ -970,68 +318,6 @@ unsigned long __init find_max_low_pfn(void)
        return max_low_pfn;
 }
 
-/*
- * Free all available memory for boot time allocation.  Used
- * as a callback function by efi_memory_walk()
- */
-
-static int __init
-free_available_memory(unsigned long start, unsigned long end, void *arg)
-{
-       /* check max_low_pfn */
-       if (start >= (max_low_pfn << PAGE_SHIFT))
-               return 0;
-       if (end >= (max_low_pfn << PAGE_SHIFT))
-               end = max_low_pfn << PAGE_SHIFT;
-       if (start < end)
-               free_bootmem(start, end - start);
-
-       return 0;
-}
-/*
- * Register fully available low RAM pages with the bootmem allocator.
- */
-static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
-{
-       int i;
-
-       if (efi_enabled) {
-               efi_memmap_walk(free_available_memory, NULL);
-               return;
-       }
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long curr_pfn, last_pfn, size;
-               /*
-                * Reserve usable low memory
-                */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               /*
-                * We are rounding up the start address of usable memory:
-                */
-               curr_pfn = PFN_UP(e820.map[i].addr);
-               if (curr_pfn >= max_low_pfn)
-                       continue;
-               /*
-                * ... and at the end of the usable range downwards:
-                */
-               last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
-               /*
-                * .. finally, did all the rounding and playing
-                * around just make the area go away?
-                */
-               if (last_pfn <= curr_pfn)
-                       continue;
-
-               size = last_pfn - curr_pfn;
-               free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
-       }
-}
-
 /*
  * workaround for Dell systems that neglect to reserve EBDA
  */
@@ -1118,8 +404,8 @@ void __init setup_bootmem_allocator(void)
         * the (very unlikely) case of us accidentally initializing the
         * bootmem allocator with an invalid RAM area.
         */
-       reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
-                        bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
+       reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
+                        bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text));
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -1162,8 +448,7 @@ void __init setup_bootmem_allocator(void)
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
                        reserve_bootmem(INITRD_START, INITRD_SIZE);
-                       initrd_start =
-                               INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+                       initrd_start = INITRD_START + PAGE_OFFSET;
                        initrd_end = initrd_start+INITRD_SIZE;
                }
                else {
@@ -1200,126 +485,6 @@ void __init remapped_pgdat_init(void)
        }
 }
 
-/*
- * Request address space for all standard RAM and ROM resources
- * and also for regions reported as reserved by the e820.
- */
-static void __init
-legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
-{
-       int i;
-
-       probe_roms();
-       for (i = 0; i < e820.nr_map; i++) {
-               struct resource *res;
-#ifndef CONFIG_RESOURCES_64BIT
-               if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
-                       continue;
-#endif
-               res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
-               switch (e820.map[i].type) {
-               case E820_RAM:  res->name = "System RAM"; break;
-               case E820_ACPI: res->name = "ACPI Tables"; break;
-               case E820_NVS:  res->name = "ACPI Non-volatile Storage"; break;
-               default:        res->name = "reserved";
-               }
-               res->start = e820.map[i].addr;
-               res->end = res->start + e820.map[i].size - 1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-               if (request_resource(&iomem_resource, res)) {
-                       kfree(res);
-                       continue;
-               }
-               if (e820.map[i].type == E820_RAM) {
-                       /*
-                        *  We don't know which RAM region contains kernel data,
-                        *  so we try it repeatedly and let the resource manager
-                        *  test it.
-                        */
-                       request_resource(res, code_resource);
-                       request_resource(res, data_resource);
-#ifdef CONFIG_KEXEC
-                       request_resource(res, &crashk_res);
-#endif
-               }
-       }
-}
-
-/*
- * Request address space for all standard resources
- *
- * This is called just before pcibios_init(), which is also a
- * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
- */
-static int __init request_standard_resources(void)
-{
-       int i;
-
-       printk("Setting up standard PCI resources\n");
-       if (efi_enabled)
-               efi_initialize_iomem_resources(&code_resource, &data_resource);
-       else
-               legacy_init_iomem_resources(&code_resource, &data_resource);
-
-       /* EFI systems may still have VGA */
-       request_resource(&iomem_resource, &video_ram_resource);
-
-       /* request I/O space for devices used on all i[345]86 PCs */
-       for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
-               request_resource(&ioport_resource, &standard_io_resources[i]);
-       return 0;
-}
-
-subsys_initcall(request_standard_resources);
-
-static void __init register_memory(void)
-{
-       unsigned long gapstart, gapsize, round;
-       unsigned long long last;
-       int i;
-
-       /*
-        * Search for the bigest gap in the low 32 bits of the e820
-        * memory space.
-        */
-       last = 0x100000000ull;
-       gapstart = 0x10000000;
-       gapsize = 0x400000;
-       i = e820.nr_map;
-       while (--i >= 0) {
-               unsigned long long start = e820.map[i].addr;
-               unsigned long long end = start + e820.map[i].size;
-
-               /*
-                * Since "last" is at most 4GB, we know we'll
-                * fit in 32 bits if this condition is true
-                */
-               if (last > end) {
-                       unsigned long gap = last - end;
-
-                       if (gap > gapsize) {
-                               gapsize = gap;
-                               gapstart = end;
-                       }
-               }
-               if (start < last)
-                       last = start;
-       }
-
-       /*
-        * See how much we want to round up: start off with
-        * rounding to the next 1MB area.
-        */
-       round = 0x100000;
-       while ((gapsize >> 4) > round)
-               round += round;
-       /* Fun with two's complement */
-       pci_mem_start = (gapstart + round) & -round;
-
-       printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
-               pci_mem_start, gapstart, gapsize);
-}
-
 #ifdef CONFIG_MCA
 static void set_mca_bus(int x)
 {
@@ -1329,6 +494,12 @@ static void set_mca_bus(int x)
 static void set_mca_bus(int x) { }
 #endif
 
+/* Overridden in paravirt.c if CONFIG_PARAVIRT */
+char * __attribute__((weak)) memory_setup(void)
+{
+       return machine_specific_memory_setup();
+}
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -1381,7 +552,7 @@ void __init setup_arch(char **cmdline_p)
                efi_init();
        else {
                printk(KERN_INFO "BIOS-provided physical RAM map:\n");
-               print_memory_map(machine_specific_memory_setup());
+               print_memory_map(memory_setup());
        }
 
        copy_edd();
index 43002cf..65d7620 100644 (file)
@@ -128,7 +128,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
                         X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
                         X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
 
-       GET_SEG(gs);
+       COPY_SEG(gs);
        GET_SEG(fs);
        COPY_SEG(es);
        COPY_SEG(ds);
@@ -244,9 +244,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
 {
        int tmp, err = 0;
 
-       tmp = 0;
-       savesegment(gs, tmp);
-       err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
+       err |= __put_user(regs->xgs, (unsigned int __user *)&sc->gs);
        savesegment(fs, tmp);
        err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
 
index 31e5c65..5285aff 100644 (file)
@@ -321,7 +321,6 @@ static inline void leave_mm (unsigned long cpu)
 
 fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(regs);
        unsigned long cpu;
 
        cpu = get_cpu();
@@ -352,7 +351,6 @@ fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
        smp_mb__after_clear_bit();
 out:
        put_cpu_no_resched();
-       set_irq_regs(old_regs);
 }
 
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
@@ -607,14 +605,11 @@ void smp_send_stop(void)
  */
 fastcall void smp_reschedule_interrupt(struct pt_regs *regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(regs);
        ack_APIC_irq();
-       set_irq_regs(old_regs);
 }
 
 fastcall void smp_call_function_interrupt(struct pt_regs *regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(regs);
        void (*func) (void *info) = call_data->func;
        void *info = call_data->info;
        int wait = call_data->wait;
@@ -637,7 +632,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
                mb();
                atomic_inc(&call_data->finished);
        }
-       set_irq_regs(old_regs);
 }
 
 /*
@@ -699,6 +693,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
                put_cpu();
                return -EBUSY;
        }
+
+       /* Can deadlock when called with interrupts disabled */
+       WARN_ON(irqs_disabled());
+
        spin_lock_bh(&call_lock);
        __smp_call_function_single(cpu, func, info, nonatomic, wait);
        spin_unlock_bh(&call_lock);
index 4bb8b77..b0f84e5 100644 (file)
  *             Dave Jones      :       Report invalid combinations of Athlon CPUs.
 *              Rusty Russell   :       Hacked into shape for new "hotplug" boot process. */
 
+
+/* SMP boot always wants to use real time delay to allow sufficient time for
+ * the APs to come online */
+#define USE_REAL_TIME_DELAY
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -52,6 +57,8 @@
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include <asm/nmi.h>
+#include <asm/pda.h>
+#include <asm/genapic.h>
 
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
@@ -62,7 +69,7 @@ static int __devinitdata smp_b_stepping;
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
-#ifdef CONFIG_X86_HT
+#ifdef CONFIG_SMP
 EXPORT_SYMBOL(smp_num_siblings);
 #endif
 
@@ -536,11 +543,11 @@ set_cpu_sibling_map(int cpu)
 static void __devinit start_secondary(void *unused)
 {
        /*
-        * Dont put anything before smp_callin(), SMP
+        * Don't put *anything* before secondary_cpu_init(), SMP
         * booting is too fragile that we want to limit the
         * things done here to the most necessary things.
         */
-       cpu_init();
+       secondary_cpu_init();
        preempt_disable();
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
@@ -599,13 +606,16 @@ void __devinit initialize_secondary(void)
                "movl %0,%%esp\n\t"
                "jmp *%1"
                :
-               :"r" (current->thread.esp),"r" (current->thread.eip));
+               :"m" (current->thread.esp),"m" (current->thread.eip));
 }
 
+/* Static state in head.S used to set up a CPU */
 extern struct {
        void * esp;
        unsigned short ss;
 } stack_start;
+extern struct i386_pda *start_pda;
+extern struct Xgt_desc_struct cpu_gdt_descr;
 
 #ifdef CONFIG_NUMA
 
@@ -936,9 +946,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
        unsigned long start_eip;
        unsigned short nmi_high = 0, nmi_low = 0;
 
-       ++cpucount;
-       alternatives_smp_switch(1);
-
        /*
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
@@ -946,15 +953,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
        idle = alloc_idle_task(cpu);
        if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
+
+       /* Pre-allocate and initialize the CPU's GDT and PDA so it
+          doesn't have to do any memory allocation during the
+          delicate CPU-bringup phase. */
+       if (!init_gdt(cpu, idle)) {
+               printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
+               return -1;      /* ? */
+       }
+
        idle->thread.eip = (unsigned long) start_secondary;
        /* start_eip had better be page-aligned! */
        start_eip = setup_trampoline();
 
+       ++cpucount;
+       alternatives_smp_switch(1);
+
        /* So we see what's up   */
        printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
        /* Stack for startup_32 can be just as for start_secondary onwards */
        stack_start.esp = (void *) idle->thread.esp;
 
+       start_pda = cpu_pda(cpu);
+       cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu);
+
        irq_ctx_init(cpu);
 
        x86_cpu_to_apicid[cpu] = apicid;
@@ -1049,13 +1071,15 @@ void cpu_exit_clear(void)
 
 struct warm_boot_cpu_info {
        struct completion *complete;
+       struct work_struct task;
        int apicid;
        int cpu;
 };
 
-static void __cpuinit do_warm_boot_cpu(void *p)
+static void __cpuinit do_warm_boot_cpu(struct work_struct *work)
 {
-       struct warm_boot_cpu_info *info = p;
+       struct warm_boot_cpu_info *info =
+               container_of(work, struct warm_boot_cpu_info, task);
        do_boot_cpu(info->apicid, info->cpu);
        complete(info->complete);
 }
@@ -1064,7 +1088,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct warm_boot_cpu_info info;
-       struct work_struct task;
        int     apicid, ret;
        struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
 
@@ -1089,15 +1112,15 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
        info.complete = &done;
        info.apicid = apicid;
        info.cpu = cpu;
-       INIT_WORK(&task, do_warm_boot_cpu, &info);
+       INIT_WORK(&info.task, do_warm_boot_cpu);
 
        tsc_sync_disabled = 1;
 
        /* init low mem mapping */
        clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
-                       KERNEL_PGD_PTRS);
+                       min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
        flush_tlb_all();
-       schedule_work(&task);
+       schedule_work(&info.task);
        wait_for_completion(&done);
 
        tsc_sync_disabled = 0;
@@ -1108,34 +1131,15 @@ exit:
 }
 #endif
 
-static void smp_tune_scheduling (void)
+static void smp_tune_scheduling(void)
 {
        unsigned long cachesize;       /* kB   */
-       unsigned long bandwidth = 350; /* MB/s */
-       /*
-        * Rough estimation for SMP scheduling, this is the number of
-        * cycles it takes for a fully memory-limited process to flush
-        * the SMP-local cache.
-        *
-        * (For a P5 this pretty much means we will choose another idle
-        *  CPU almost always at wakeup time (this is due to the small
-        *  L1 cache), on PIIs it's around 50-100 usecs, depending on
-        *  the cache size)
-        */
 
-       if (!cpu_khz) {
-               /*
-                * this basically disables processor-affinity
-                * scheduling on SMP without a TSC.
-                */
-               return;
-       } else {
+       if (cpu_khz) {
                cachesize = boot_cpu_data.x86_cache_size;
-               if (cachesize == -1) {
-                       cachesize = 16; /* Pentiums, 2x8kB cache */
-                       bandwidth = 100;
-               }
-               max_cache_size = cachesize * 1024;
+
+               if (cachesize > 0)
+                       max_cache_size = cachesize * 1024;
        }
 }
 
@@ -1461,6 +1465,12 @@ int __devinit __cpu_up(unsigned int cpu)
        cpu_set(cpu, smp_commenced_mask);
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
+
+#ifdef CONFIG_X86_GENERICARCH
+       if (num_online_cpus() > 8 && genapic == &apic_default)
+               panic("Default flat APIC routing can't be used with > 8 cpus\n");
+#endif
+
        return 0;
 }
 
index 713ba39..7de9117 100644 (file)
  * Should the kernel map a VDSO page into processes and pass its
  * address down to glibc upon exec()?
  */
+#ifdef CONFIG_PARAVIRT
+unsigned int __read_mostly vdso_enabled = 0;
+#else
 unsigned int __read_mostly vdso_enabled = 1;
+#endif
 
 EXPORT_SYMBOL_GPL(vdso_enabled);
 
@@ -132,7 +136,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
                goto up_fail;
        }
 
-       vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
        if (!vma) {
                ret = -ENOMEM;
                goto up_fail;
index 78af572..c505b16 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/time.h>
 
 #include "mach_time.h"
 
@@ -116,10 +117,7 @@ static int set_rtc_mmss(unsigned long nowtime)
        /* gets recalled with irq locally disabled */
        /* XXX - does irqsave resolve this? -johnstul */
        spin_lock_irqsave(&rtc_lock, flags);
-       if (efi_enabled)
-               retval = efi_set_rtc_mmss(nowtime);
-       else
-               retval = mach_set_rtc_mmss(nowtime);
+       retval = set_wallclock(nowtime);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        return retval;
@@ -223,10 +221,7 @@ unsigned long get_cmos_time(void)
 
        spin_lock_irqsave(&rtc_lock, flags);
 
-       if (efi_enabled)
-               retval = efi_get_time();
-       else
-               retval = mach_get_cmos_time();
+       retval = get_wallclock();
 
        spin_unlock_irqrestore(&rtc_lock, flags);
 
@@ -370,7 +365,7 @@ static void __init hpet_time_init(void)
                printk("Using HPET for base-timer\n");
        }
 
-       time_init_hook();
+       do_time_init();
 }
 #endif
 
@@ -392,5 +387,5 @@ void __init time_init(void)
 
        do_settimeofday(&ts);
 
-       time_init_hook();
+       do_time_init();
 }
index 1a2a979..1e4702d 100644 (file)
@@ -132,14 +132,20 @@ int __init hpet_enable(void)
         * the single HPET timer for system time.
         */
 #ifdef CONFIG_HPET_EMULATE_RTC
-       if (!(id & HPET_ID_NUMBER))
+       if (!(id & HPET_ID_NUMBER)) {
+               iounmap(hpet_virt_address);
+               hpet_virt_address = NULL;
                return -1;
+       }
 #endif
 
 
        hpet_period = hpet_readl(HPET_PERIOD);
-       if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD))
+       if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) {
+               iounmap(hpet_virt_address);
+               hpet_virt_address = NULL;
                return -1;
+       }
 
        /*
         * 64 bit math
@@ -156,8 +162,11 @@ int __init hpet_enable(void)
 
        hpet_use_timer = id & HPET_ID_LEGSUP;
 
-       if (hpet_timer_stop_set_go(hpet_tick))
+       if (hpet_timer_stop_set_go(hpet_tick)) {
+               iounmap(hpet_virt_address);
+               hpet_virt_address = NULL;
                return -1;
+       }
 
        use_hpet = 1;
 
index 07d6da3..79cf608 100644 (file)
@@ -40,14 +40,18 @@ int arch_register_cpu(int num)
         * restrictions and assumptions in kernel. This basically
         * doesnt add a control file, one cannot attempt to offline
         * BSP.
+        *
+        * Also certain PCI quirks require not to enable hotplug control
+        * for all CPU's.
         */
-       if (!num)
-               cpu_devices[num].cpu.no_control = 1;
+       if (num && enable_cpu_hotplug)
+               cpu_devices[num].cpu.hotpluggable = 1;
 
        return register_cpu(&cpu_devices[num].cpu, num);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+int enable_cpu_hotplug = 1;
 
 void arch_unregister_cpu(int num) {
        return unregister_cpu(&cpu_devices[num].cpu);
index fe9c5e8..2b30dbf 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/kexec.h>
 #include <linux/unwind.h>
 #include <linux/uaccess.h>
+#include <linux/nmi.h>
+#include <linux/bug.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -61,9 +63,6 @@ int panic_on_unrecovered_nmi;
 
 asmlinkage int system_call(void);
 
-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
-               { 0, 0 }, { 0, 0 } };
-
 /* Do we ignore FPU interrupts ? */
 char ignore_fpu_irq = 0;
 
@@ -94,7 +93,7 @@ asmlinkage void alignment_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
-static int kstack_depth_to_print = 24;
+int kstack_depth_to_print = 24;
 #ifdef CONFIG_STACK_UNWIND
 static int call_trace = 1;
 #else
@@ -163,16 +162,25 @@ dump_trace_unwind(struct unwind_frame_info *info, void *data)
 {
        struct ops_and_data *oad = (struct ops_and_data *)data;
        int n = 0;
+       unsigned long sp = UNW_SP(info);
 
+       if (arch_unw_user_mode(info))
+               return -1;
        while (unwind(info) == 0 && UNW_PC(info)) {
                n++;
                oad->ops->address(oad->data, UNW_PC(info));
                if (arch_unw_user_mode(info))
                        break;
+               if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
+                   && sp > UNW_SP(info))
+                       break;
+               sp = UNW_SP(info);
        }
        return n;
 }
 
+#define MSG(msg) ops->warning(data, msg)
+
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
                unsigned long *stack,
                struct stacktrace_ops *ops, void *data)
@@ -191,29 +199,31 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                        if (unwind_init_frame_info(&info, task, regs) == 0)
                                unw_ret = dump_trace_unwind(&info, &oad);
                } else if (task == current)
-                       unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+                       unw_ret = unwind_init_running(&info, dump_trace_unwind,
+                                                     &oad);
                else {
                        if (unwind_init_blocked(&info, task) == 0)
                                unw_ret = dump_trace_unwind(&info, &oad);
                }
                if (unw_ret > 0) {
                        if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-                               ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+                               ops->warning_symbol(data,
+                                            "DWARF2 unwinder stuck at %s",
                                             UNW_PC(&info));
                                if (UNW_SP(&info) >= PAGE_OFFSET) {
-                                       ops->warning(data, "Leftover inexact backtrace:\n");
+                                       MSG("Leftover inexact backtrace:");
                                        stack = (void *)UNW_SP(&info);
                                        if (!stack)
                                                return;
                                        ebp = UNW_FP(&info);
                                } else
-                                       ops->warning(data, "Full inexact backtrace again:\n");
+                                       MSG("Full inexact backtrace again:");
                        } else if (call_trace >= 1)
                                return;
                        else
-                               ops->warning(data, "Full inexact backtrace again:\n");
+                               MSG("Full inexact backtrace again:");
                } else
-                       ops->warning(data, "Inexact backtrace:\n");
+                       MSG("Inexact backtrace:");
        }
        if (!stack) {
                unsigned long dummy;
@@ -247,6 +257,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                stack = (unsigned long*)context->previous_esp;
                if (!stack)
                        break;
+               touch_nmi_watchdog();
        }
 }
 EXPORT_SYMBOL(dump_trace);
@@ -379,7 +390,7 @@ void show_registers(struct pt_regs *regs)
         * time of the fault..
         */
        if (in_kernel) {
-               u8 __user *eip;
+               u8 *eip;
                int code_bytes = 64;
                unsigned char c;
 
@@ -388,18 +399,20 @@ void show_registers(struct pt_regs *regs)
 
                printk(KERN_EMERG "Code: ");
 
-               eip = (u8 __user *)regs->eip - 43;
-               if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
+               eip = (u8 *)regs->eip - 43;
+               if (eip < (u8 *)PAGE_OFFSET ||
+                       probe_kernel_address(eip, c)) {
                        /* try starting at EIP */
-                       eip = (u8 __user *)regs->eip;
+                       eip = (u8 *)regs->eip;
                        code_bytes = 32;
                }
                for (i = 0; i < code_bytes; i++, eip++) {
-                       if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
+                       if (eip < (u8 *)PAGE_OFFSET ||
+                               probe_kernel_address(eip, c)) {
                                printk(" Bad EIP value.");
                                break;
                        }
-                       if (eip == (u8 __user *)regs->eip)
+                       if (eip == (u8 *)regs->eip)
                                printk("<%02x> ", c);
                        else
                                printk("%02x ", c);
@@ -408,43 +421,22 @@ void show_registers(struct pt_regs *regs)
        printk("\n");
 }      
 
-static void handle_BUG(struct pt_regs *regs)
+int is_valid_bugaddr(unsigned long eip)
 {
-       unsigned long eip = regs->eip;
        unsigned short ud2;
 
        if (eip < PAGE_OFFSET)
-               return;
-       if (probe_kernel_address((unsigned short __user *)eip, ud2))
-               return;
-       if (ud2 != 0x0b0f)
-               return;
-
-       printk(KERN_EMERG "------------[ cut here ]------------\n");
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-       do {
-               unsigned short line;
-               char *file;
-               char c;
-
-               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))
-                       file = "<bad filename>";
+               return 0;
+       if (probe_kernel_address((unsigned short *)eip, ud2))
+               return 0;
 
-               printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
-               return;
-       } while (0);
-#endif
-       printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
+       return ud2 == 0x0b0f;
 }
 
-/* This is gone through when something in the kernel
- * has done something bad and is about to be terminated.
-*/
+/*
+ * This is gone through when something in the kernel has done something bad and
+ * is about to be terminated.
+ */
 void die(const char * str, struct pt_regs * regs, long err)
 {
        static struct {
@@ -452,7 +444,7 @@ void die(const char * str, struct pt_regs * regs, long err)
                u32 lock_owner;
                int lock_owner_depth;
        } die = {
-               .lock =                 SPIN_LOCK_UNLOCKED,
+               .lock =                 __SPIN_LOCK_UNLOCKED(die.lock),
                .lock_owner =           -1,
                .lock_owner_depth =     0
        };
@@ -476,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err)
                unsigned long esp;
                unsigned short ss;
 
-               handle_BUG(regs);
+               report_bug(regs->eip);
+
                printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
                printk(KERN_EMERG "PREEMPT ");
@@ -707,8 +700,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
        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");
+       printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
        if (panic_on_unrecovered_nmi)
                 panic("NMI: Not continuing");
 
@@ -773,7 +765,6 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
        printk(" on CPU%d, eip %08lx, registers:\n",
                smp_processor_id(), regs->eip);
        show_registers(regs);
-       printk(KERN_EMERG "console shuts up ...\n");
        console_silent();
        spin_unlock(&nmi_print_lock);
        bust_spinlocks(0);
@@ -1088,49 +1079,24 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
 #endif
 }
 
-fastcall void setup_x86_bogus_stack(unsigned char * stk)
-{
-       unsigned long *switch16_ptr, *switch32_ptr;
-       struct pt_regs *regs;
-       unsigned long stack_top, stack_bot;
-       unsigned short iret_frame16_off;
-       int cpu = smp_processor_id();
-       /* reserve the space on 32bit stack for the magic switch16 pointer */
-       memmove(stk, stk + 8, sizeof(struct pt_regs));
-       switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
-       regs = (struct pt_regs *)stk;
-       /* now the switch32 on 16bit stack */
-       stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
-       stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
-       switch32_ptr = (unsigned long *)(stack_top - 8);
-       iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
-       /* copy iret frame on 16bit stack */
-       memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
-       /* fill in the switch pointers */
-       switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
-       switch16_ptr[1] = __ESPFIX_SS;
-       switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
-               8 - CPU_16BIT_STACK_SIZE;
-       switch32_ptr[1] = __KERNEL_DS;
-}
-
-fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
+fastcall unsigned long patch_espfix_desc(unsigned long uesp,
+                                         unsigned long kesp)
 {
-       unsigned long *switch32_ptr;
-       unsigned char *stack16, *stack32;
-       unsigned long stack_top, stack_bot;
-       int len;
        int cpu = smp_processor_id();
-       stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
-       stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
-       switch32_ptr = (unsigned long *)(stack_top - 8);
-       /* copy the data from 16bit stack to 32bit stack */
-       len = CPU_16BIT_STACK_SIZE - 8 - sp;
-       stack16 = (unsigned char *)(stack_bot + sp);
-       stack32 = (unsigned char *)
-               (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
-       memcpy(stack32, stack16, len);
-       return stack32;
+       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
+       unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+       unsigned long new_kesp = kesp - base;
+       unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+       __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
+       /* Set up base for espfix segment */
+       desc &= 0x00f0ff0000000000ULL;
+       desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+               ((((__u64)base) << 32) & 0xff00000000000000ULL) |
+               ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+               (lim_pages & 0xffff);
+       *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
+       return new_kesp;
 }
 
 /*
@@ -1143,7 +1109,7 @@ fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
  * Must be called with kernel preemption disabled (in this case,
  * local interrupts are disabled at the call-site in entry.S).
  */
-asmlinkage void math_state_restore(struct pt_regs regs)
+asmlinkage void math_state_restore(void)
 {
        struct thread_info *thread = current_thread_info();
        struct task_struct *tsk = thread->task;
@@ -1153,6 +1119,7 @@ asmlinkage void math_state_restore(struct pt_regs regs)
                init_fpu(tsk);
        restore_fpu(tsk);
        thread->status |= TS_USEDFPU;   /* So we fnsave on switch_to() */
+       tsk->fpu_counter++;
 }
 
 #ifndef CONFIG_MATH_EMULATION
index fbc9582..1bbe45d 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/delay.h>
 #include <asm/tsc.h>
-#include <asm/delay.h>
 #include <asm/io.h>
 
 #include "mach_timer.h"
@@ -217,7 +216,7 @@ static unsigned int cpufreq_delayed_issched = 0;
 static unsigned int cpufreq_init = 0;
 static struct work_struct cpufreq_delayed_get_work;
 
-static void handle_cpufreq_delayed_get(void *v)
+static void handle_cpufreq_delayed_get(struct work_struct *work)
 {
        unsigned int cpu;
 
@@ -306,7 +305,7 @@ static int __init cpufreq_tsc(void)
 {
        int ret;
 
-       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
        ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
                                        CPUFREQ_TRANSITION_NOTIFIER);
        if (!ret)
index cbcd61d..be2f96e 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/highmem.h>
 #include <linux/ptrace.h>
 #include <linux/audit.h>
+#include <linux/stddef.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 /*
  * 8- and 16-bit register defines..
  */
-#define AL(regs)       (((unsigned char *)&((regs)->eax))[0])
-#define AH(regs)       (((unsigned char *)&((regs)->eax))[1])
-#define IP(regs)       (*(unsigned short *)&((regs)->eip))
-#define SP(regs)       (*(unsigned short *)&((regs)->esp))
+#define AL(regs)       (((unsigned char *)&((regs)->pt.eax))[0])
+#define AH(regs)       (((unsigned char *)&((regs)->pt.eax))[1])
+#define IP(regs)       (*(unsigned short *)&((regs)->pt.eip))
+#define SP(regs)       (*(unsigned short *)&((regs)->pt.esp))
 
 /*
  * virtual flags (16 and 32-bit versions)
 #define SAFE_MASK      (0xDD5)
 #define RETURN_MASK    (0xDFF)
 
-#define VM86_REGS_PART2 orig_eax
-#define VM86_REGS_SIZE1 \
-        ( (unsigned)( & (((struct kernel_vm86_regs *)0)->VM86_REGS_PART2) ) )
-#define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
+/* convert kernel_vm86_regs to vm86_regs */
+static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
+                                 const struct kernel_vm86_regs *regs)
+{
+       int ret = 0;
+
+       /* kernel_vm86_regs is missing xfs, so copy everything up to
+          (but not including) xgs, and then rest after xgs. */
+       ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.xgs));
+       ret += copy_to_user(&user->__null_gs, &regs->pt.xgs,
+                           sizeof(struct kernel_vm86_regs) -
+                           offsetof(struct kernel_vm86_regs, pt.xgs));
+
+       return ret;
+}
+
+/* convert vm86_regs to kernel_vm86_regs */
+static int copy_vm86_regs_from_user(struct kernel_vm86_regs *regs,
+                                   const struct vm86_regs __user *user,
+                                   unsigned extra)
+{
+       int ret = 0;
+
+       ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.xgs));
+       ret += copy_from_user(&regs->pt.xgs, &user->__null_gs,
+                             sizeof(struct kernel_vm86_regs) -
+                             offsetof(struct kernel_vm86_regs, pt.xgs) +
+                             extra);
+
+       return ret;
+}
 
 struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
 struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
@@ -112,10 +140,8 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
                printk("no vm86_info: BAD\n");
                do_exit(SIGSEGV);
        }
-       set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
-       tmp = copy_to_user(&current->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);
-       tmp += copy_to_user(&current->thread.vm86_info->regs.VM86_REGS_PART2,
-               &regs->VM86_REGS_PART2, VM86_REGS_SIZE2);
+       set_flags(regs->pt.eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
+       tmp = copy_vm86_regs_to_user(&current->thread.vm86_info->regs,regs);
        tmp += put_user(current->thread.screen_bitmap,&current->thread.vm86_info->screen_bitmap);
        if (tmp) {
                printk("vm86: could not access userspace vm86_info\n");
@@ -129,9 +155,11 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
        current->thread.saved_esp0 = 0;
        put_cpu();
 
-       loadsegment(fs, current->thread.saved_fs);
-       loadsegment(gs, current->thread.saved_gs);
        ret = KVM86->regs32;
+
+       loadsegment(fs, current->thread.saved_fs);
+       ret->xgs = current->thread.saved_gs;
+
        return ret;
 }
 
@@ -183,9 +211,9 @@ asmlinkage int sys_vm86old(struct pt_regs regs)
        tsk = current;
        if (tsk->thread.saved_esp0)
                goto out;
-       tmp  = copy_from_user(&info, v86, VM86_REGS_SIZE1);
-       tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
-               (long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
+       tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
+                                      offsetof(struct kernel_vm86_struct, vm86plus) -
+                                      sizeof(info.regs));
        ret = -EFAULT;
        if (tmp)
                goto out;
@@ -233,9 +261,9 @@ asmlinkage int sys_vm86(struct pt_regs regs)
        if (tsk->thread.saved_esp0)
                goto out;
        v86 = (struct vm86plus_struct __user *)regs.ecx;
-       tmp  = copy_from_user(&info, v86, VM86_REGS_SIZE1);
-       tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
-               (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
+       tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
+                                      offsetof(struct kernel_vm86_struct, regs32) -
+                                      sizeof(info.regs));
        ret = -EFAULT;
        if (tmp)
                goto out;
@@ -252,15 +280,15 @@ out:
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
 {
        struct tss_struct *tss;
-       long eax;
 /*
  * make sure the vm86() system call doesn't try to do anything silly
  */
-       info->regs.__null_ds = 0;
-       info->regs.__null_es = 0;
+       info->regs.pt.xds = 0;
+       info->regs.pt.xes = 0;
+       info->regs.pt.xgs = 0;
 
-/* we are clearing fs,gs later just before "jmp resume_userspace",
- * because starting with Linux 2.1.x they aren't no longer saved/restored
+/* we are clearing fs later just before "jmp resume_userspace",
+ * because it is not saved/restored.
  */
 
 /*
@@ -268,10 +296,10 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
  * has set it up safely, so this makes sure interrupt etc flags are
  * inherited from protected mode.
  */
-       VEFLAGS = info->regs.eflags;
-       info->regs.eflags &= SAFE_MASK;
-       info->regs.eflags |= info->regs32->eflags & ~SAFE_MASK;
-       info->regs.eflags |= VM_MASK;
+       VEFLAGS = info->regs.pt.eflags;
+       info->regs.pt.eflags &= SAFE_MASK;
+       info->regs.pt.eflags |= info->regs32->eflags & ~SAFE_MASK;
+       info->regs.pt.eflags |= VM_MASK;
 
        switch (info->cpu_type) {
                case CPU_286:
@@ -294,7 +322,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        info->regs32->eax = 0;
        tsk->thread.saved_esp0 = tsk->thread.esp0;
        savesegment(fs, tsk->thread.saved_fs);
-       savesegment(gs, tsk->thread.saved_gs);
+       tsk->thread.saved_gs = info->regs32->xgs;
 
        tss = &per_cpu(init_tss, get_cpu());
        tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -306,19 +334,18 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        tsk->thread.screen_bitmap = info->screen_bitmap;
        if (info->flags & VM86_SCREEN_BITMAP)
                mark_screen_rdonly(tsk->mm);
-       __asm__ __volatile__("xorl %eax,%eax; movl %eax,%fs; movl %eax,%gs\n\t");
-       __asm__ __volatile__("movl %%eax, %0\n" :"=r"(eax));
 
        /*call audit_syscall_exit since we do not exit via the normal paths */
        if (unlikely(current->audit_context))
-               audit_syscall_exit(AUDITSC_RESULT(eax), eax);
+               audit_syscall_exit(AUDITSC_RESULT(0), 0);
 
        __asm__ __volatile__(
                "movl %0,%%esp\n\t"
                "movl %1,%%ebp\n\t"
+               "mov  %2, %%fs\n\t"
                "jmp resume_userspace"
                : /* no outputs */
-               :"r" (&info->regs), "r" (task_thread_info(tsk)));
+               :"r" (&info->regs), "r" (task_thread_info(tsk)), "r" (0));
        /* we never return here */
 }
 
@@ -348,12 +375,12 @@ static inline void clear_IF(struct kernel_vm86_regs * regs)
 
 static inline void clear_TF(struct kernel_vm86_regs * regs)
 {
-       regs->eflags &= ~TF_MASK;
+       regs->pt.eflags &= ~TF_MASK;
 }
 
 static inline void clear_AC(struct kernel_vm86_regs * regs)
 {
-       regs->eflags &= ~AC_MASK;
+       regs->pt.eflags &= ~AC_MASK;
 }
 
 /* It is correct to call set_IF(regs) from the set_vflags_*
@@ -370,7 +397,7 @@ static inline void clear_AC(struct kernel_vm86_regs * regs)
 static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs)
 {
        set_flags(VEFLAGS, eflags, current->thread.v86mask);
-       set_flags(regs->eflags, eflags, SAFE_MASK);
+       set_flags(regs->pt.eflags, eflags, SAFE_MASK);
        if (eflags & IF_MASK)
                set_IF(regs);
        else
@@ -380,7 +407,7 @@ static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs
 static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
 {
        set_flags(VFLAGS, flags, current->thread.v86mask);
-       set_flags(regs->eflags, flags, SAFE_MASK);
+       set_flags(regs->pt.eflags, flags, SAFE_MASK);
        if (flags & IF_MASK)
                set_IF(regs);
        else
@@ -389,7 +416,7 @@ static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_reg
 
 static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
 {
-       unsigned long flags = regs->eflags & RETURN_MASK;
+       unsigned long flags = regs->pt.eflags & RETURN_MASK;
 
        if (VEFLAGS & VIF_MASK)
                flags |= IF_MASK;
@@ -493,7 +520,7 @@ static void do_int(struct kernel_vm86_regs *regs, int i,
        unsigned long __user *intr_ptr;
        unsigned long segoffs;
 
-       if (regs->cs == BIOSSEG)
+       if (regs->pt.xcs == BIOSSEG)
                goto cannot_handle;
        if (is_revectored(i, &KVM86->int_revectored))
                goto cannot_handle;
@@ -505,9 +532,9 @@ static void do_int(struct kernel_vm86_regs *regs, int i,
        if ((segoffs >> 16) == BIOSSEG)
                goto cannot_handle;
        pushw(ssp, sp, get_vflags(regs), cannot_handle);
-       pushw(ssp, sp, regs->cs, cannot_handle);
+       pushw(ssp, sp, regs->pt.xcs, cannot_handle);
        pushw(ssp, sp, IP(regs), cannot_handle);
-       regs->cs = segoffs >> 16;
+       regs->pt.xcs = segoffs >> 16;
        SP(regs) -= 6;
        IP(regs) = segoffs & 0xffff;
        clear_TF(regs);
@@ -524,7 +551,7 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno
        if (VMPI.is_vm86pus) {
                if ( (trapno==3) || (trapno==1) )
                        return_to_32bit(regs, VM86_TRAP + (trapno << 8));
-               do_int(regs, trapno, (unsigned char __user *) (regs->ss << 4), SP(regs));
+               do_int(regs, trapno, (unsigned char __user *) (regs->pt.xss << 4), SP(regs));
                return 0;
        }
        if (trapno !=1)
@@ -560,10 +587,10 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
                handle_vm86_trap(regs, 0, 1); \
        return; } while (0)
 
-       orig_flags = *(unsigned short *)&regs->eflags;
+       orig_flags = *(unsigned short *)&regs->pt.eflags;
 
-       csp = (unsigned char __user *) (regs->cs << 4);
-       ssp = (unsigned char __user *) (regs->ss << 4);
+       csp = (unsigned char __user *) (regs->pt.xcs << 4);
+       ssp = (unsigned char __user *) (regs->pt.xss << 4);
        sp = SP(regs);
        ip = IP(regs);
 
@@ -650,7 +677,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
                        SP(regs) += 6;
                }
                IP(regs) = newip;
-               regs->cs = newcs;
+               regs->pt.xcs = newcs;
                CHECK_IF_IN_TRAP;
                if (data32) {
                        set_vflags_long(newflags, regs);
index c6f84a0..a53c8b1 100644 (file)
@@ -1,18 +1,32 @@
 /* ld script to make i386 Linux kernel
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ *
+ * Don't define absolute symbols until and unless you know that symbol
+ * value is should remain constant even if kernel image is relocated
+ * at run time. Absolute symbols are not relocated. If symbol value should
+ * change if kernel is relocated, make the symbol section relative and
+ * put it inside the section definition.
  */
 
+/* Don't define absolute symbols until and unless you know that symbol
+ * value is should remain constant even if kernel image is relocated
+ * at run time. Absolute symbols are not relocated. If symbol value should
+ * change if kernel is relocated, make the symbol section relative and
+ * put it inside the section definition.
+ */
 #define LOAD_OFFSET __PAGE_OFFSET
 
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include <asm/cache.h>
+#include <asm/boot.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
 ENTRY(phys_startup_32)
 jiffies = jiffies_64;
+_proxy_pda = 0;
 
 PHDRS {
        text PT_LOAD FLAGS(5);  /* R_E */
@@ -21,34 +35,37 @@ PHDRS {
 }
 SECTIONS
 {
-  . = __KERNEL_START;
+  . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
   phys_startup_32 = startup_32 - LOAD_OFFSET;
   /* read-only */
-  _text = .;                   /* Text and read-only data */
   .text : AT(ADDR(.text) - LOAD_OFFSET) {
+       _text = .;                      /* Text and read-only data */
        *(.text)
        SCHED_TEXT
        LOCK_TEXT
        KPROBES_TEXT
        *(.fixup)
        *(.gnu.warning)
-       } :text = 0x9090
-
-  _etext = .;                  /* End of text section */
+       _etext = .;                     /* End of text section */
+  } :text = 0x9090
 
   . = ALIGN(16);               /* Exception table */
-  __start___ex_table = .;
-  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
-  __stop___ex_table = .;
+  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+       __start___ex_table = .;
+        *(__ex_table)
+       __stop___ex_table = .;
+  }
 
   RODATA
 
+  BUG_TABLE
+
   . = ALIGN(4);
-  __tracedata_start = .;
   .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
+       __tracedata_start = .;
        *(.tracedata)
+       __tracedata_end = .;
   }
-  __tracedata_end = .;
 
   /* writeable */
   . = ALIGN(4096);
@@ -57,11 +74,19 @@ SECTIONS
        CONSTRUCTORS
        } :data
 
+  .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) {
+       __start_paravirtprobe = .;
+       *(.paravirtprobe)
+       __stop_paravirtprobe = .;
+  }
+
   . = ALIGN(4096);
-  __nosave_begin = .;
-  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
+  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+       __nosave_begin = .;
+       *(.data.nosave)
+       . = ALIGN(4096);
+       __nosave_end = .;
+  }
 
   . = ALIGN(4096);
   .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
@@ -75,17 +100,10 @@ SECTIONS
 
   /* rarely changed data like cpu maps */
   . = ALIGN(32);
-  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
-  _edata = .;                  /* End of data section */
-
-#ifdef CONFIG_STACK_UNWIND
-  . = ALIGN(4);
-  .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {
-       __start_unwind = .;
-       *(.eh_frame)
-       __end_unwind = .;
+  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+       *(.data.read_mostly)
+       _edata = .;             /* End of data section */
   }
-#endif
 
   . = ALIGN(THREAD_SIZE);      /* init_task */
   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
@@ -94,88 +112,102 @@ SECTIONS
 
   /* might get freed after init */
   . = ALIGN(4096);
-  __smp_alt_begin = .;
-  __smp_alt_instructions = .;
   .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) {
+       __smp_alt_begin = .;
+       __smp_alt_instructions = .;
        *(.smp_altinstructions)
+       __smp_alt_instructions_end = .;
   }
-  __smp_alt_instructions_end = .;
   . = ALIGN(4);
-  __smp_locks = .;
   .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+       __smp_locks = .;
        *(.smp_locks)
+       __smp_locks_end = .;
   }
-  __smp_locks_end = .;
   .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) {
        *(.smp_altinstr_replacement)
+       __smp_alt_end = .;
   }
+  /* will be freed after init
+   * Following ALIGN() is required to make sure no other data falls on the
+   * same page where __smp_alt_end is pointing as that page might be freed
+   * after boot. Always make sure that ALIGN() directive is present after
+   * the section which contains __smp_alt_end.
+   */
   . = ALIGN(4096);
-  __smp_alt_end = .;
 
   /* will be freed after init */
   . = ALIGN(4096);             /* Init code and data */
-  __init_begin = .;
   .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+       __init_begin = .;
        _sinittext = .;
        *(.init.text)
        _einittext = .;
   }
   .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
   . = ALIGN(16);
-  __setup_start = .;
-  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
-  __setup_end = .;
-  __initcall_start = .;
+  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+       __setup_start = .;
+       *(.init.setup)
+       __setup_end = .;
+   }
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+       __initcall_start = .;
        INITCALLS
+       __initcall_end = .;
   }
-  __initcall_end = .;
-  __con_initcall_start = .;
   .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+       __con_initcall_start = .;
        *(.con_initcall.init)
+       __con_initcall_end = .;
   }
-  __con_initcall_end = .;
   SECURITY_INIT
   . = ALIGN(4);
-  __alt_instructions = .;
   .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+       __alt_instructions = .;
        *(.altinstructions)
+       __alt_instructions_end = .;
   }
-  __alt_instructions_end = .; 
   .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
        *(.altinstr_replacement)
   }
+  . = ALIGN(4);
+  .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
+       __start_parainstructions = .;
+       *(.parainstructions)
+       __stop_parainstructions = .;
+  }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
   .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
   .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
   . = ALIGN(4096);
-  __initramfs_start = .;
-  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
-  __initramfs_end = .;
+  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+       __initramfs_start = .;
+       *(.init.ramfs)
+       __initramfs_end = .;
+  }
   . = ALIGN(L1_CACHE_BYTES);
-  __per_cpu_start = .;
-  .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
-  __per_cpu_end = .;
+  .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
+       __per_cpu_start = .;
+       *(.data.percpu)
+       __per_cpu_end = .;
+  }
   . = ALIGN(4096);
-  __init_end = .;
   /* freed after init ends here */
        
-  __bss_start = .;             /* BSS */
-  .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
-       *(.bss.page_aligned)
-  }
   .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+       __init_end = .;
+       __bss_start = .;                /* BSS */
+       *(.bss.page_aligned)
        *(.bss)
+       . = ALIGN(4);
+       __bss_stop = .;
+       _end = . ;
+       /* This is where the kernel creates the early boot page tables */
+       . = ALIGN(4096);
+       pg0 = . ;
   }
-  . = ALIGN(4);
-  __bss_stop = .; 
-
-  _end = . ;
-
-  /* This is where the kernel creates the early boot page tables */
-  . = ALIGN(4096);
-  pg0 = .;
 
   /* Sections to be discarded */
   /DISCARD/ : {
index 94b1fd9..a7b3999 100644 (file)
@@ -45,7 +45,9 @@ static int __init parse_apic(char *arg)
                        return 0;
                }
        }
-       return -ENOENT;
+
+       /* Parsed again by __setup for debug/verbose */
+       return 0;
 }
 early_param("apic", parse_apic);
 
index 885c7cb..233ee20 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/fixmap.h>
 #include <asm/arch_hooks.h>
@@ -142,6 +143,8 @@ void __init time_init_hook(void)
 
 unsigned long sgivwfb_mem_phys;
 unsigned long sgivwfb_mem_size;
+EXPORT_SYMBOL(sgivwfb_mem_phys);
+EXPORT_SYMBOL(sgivwfb_mem_size);
 
 long long mem_size __initdata = 0;
 
index f50c6c6..943a947 100644 (file)
@@ -776,7 +776,7 @@ voyager_cat_init(void)
                for(asic=0; asic < (*modpp)->num_asics; asic++) {
                        int j;
                        voyager_asic_t *asicp = *asicpp 
-                               = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/
+                               = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/
                        voyager_sp_table_t *sp_table;
                        voyager_at_t *asic_table;
                        voyager_jtt_t *jtag_table;
@@ -785,7 +785,6 @@ voyager_cat_init(void)
                                printk("**WARNING** kmalloc failure in cat_init\n");
                                continue;
                        }
-                       memset(asicp, 0, sizeof(voyager_asic_t));
                        asicpp = &(asicp->next);
                        asicp->asic_location = asic;
                        sp_table = (voyager_sp_table_t *)(eprom_buf + sp_offset);
@@ -851,8 +850,7 @@ voyager_cat_init(void)
 #endif
 
                {
-                       struct resource *res = kmalloc(sizeof(struct resource),GFP_KERNEL);
-                       memset(res, 0, sizeof(struct resource));
+                       struct resource *res = kzalloc(sizeof(struct resource),GFP_KERNEL);
                        res->name = kmalloc(128, GFP_KERNEL);
                        sprintf((char *)res->name, "Voyager %s Quad CPI", cat_module_name(i));
                        res->start = qic_addr;
index f3fea2a..55428e6 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/arch_hooks.h>
+#include <asm/pda.h>
 
 /* TLB state -- visible externally, indexed physically */
 DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
@@ -422,6 +423,7 @@ find_smp_config(void)
             VOYAGER_SUS_IN_CONTROL_PORT);
 
        current_thread_info()->cpu = boot_cpu_id;
+       write_pda(cpu_number, boot_cpu_id);
 }
 
 /*
@@ -458,7 +460,7 @@ start_secondary(void *unused)
        /* external functions not defined in the headers */
        extern void calibrate_delay(void);
 
-       cpu_init();
+       secondary_cpu_init();
 
        /* OK, we're in the routine */
        ack_CPI(VIC_CPU_BOOT_CPI);
@@ -578,6 +580,15 @@ do_boot_cpu(__u8 cpu)
        /* init_tasks (in sched.c) is indexed logically */
        stack_start.esp = (void *) idle->thread.esp;
 
+       /* Pre-allocate and initialize the CPU's GDT and PDA so it
+          doesn't have to do any memory allocation during the
+          delicate CPU-bringup phase. */
+       if (!init_gdt(cpu, idle)) {
+               printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
+               cpucount--;
+               return;
+       }
+
        irq_ctx_init(cpu);
 
        /* Note: Don't modify initial ss override */
@@ -1963,4 +1974,5 @@ void __init
 smp_setup_processor_id(void)
 {
        current_thread_info()->cpu = hard_smp_processor_id();
+       write_pda(cpu_number, hard_smp_processor_id());
 }
index d62b20a..65120f5 100644 (file)
@@ -57,6 +57,7 @@
 #define TAG_Special    Const(2)        /* De-normal, + or - infinity,
                                           or Not a Number */
 #define TAG_Empty      Const(3)        /* empty */
+#define TAG_Error      Const(0x80)     /* probably need to abort */
 
 #define LOADED_DATA    Const(10101)    /* Special st() number to identify
                                           loaded data (not on stack). */
index d93f16e..ddf8fa3 100644 (file)
@@ -742,7 +742,8 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
   S387->fcs &= ~0xf8000000;
   S387->fos |= 0xffff0000;
 #endif /* PECULIAR_486 */
-  __copy_to_user(d, &S387->cwd, 7*4);
+  if (__copy_to_user(d, &S387->cwd, 7*4))
+    return -1;
   RE_ENTRANT_CHECK_ON;
 
   d += 7*4;
index bf26341..a3ae28c 100644 (file)
@@ -68,6 +68,7 @@
 
 #define FPU_access_ok(x,y,z)   if ( !access_ok(x,y,z) ) \
                                math_abort(FPU_info,SIGSEGV)
+#define FPU_abort              math_abort(FPU_info, SIGSEGV)
 
 #undef FPU_IGNORE_CODE_SEGV
 #ifdef FPU_IGNORE_CODE_SEGV
index 85314be..eebd6fb 100644 (file)
@@ -227,6 +227,8 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
     case 027:      /* fild m64int */
       clear_C1();
       loaded_tag = FPU_load_int64((long long __user *)data_address);
+      if (loaded_tag == TAG_Error)
+       return 0;
       FPU_settag0(loaded_tag);
       break;
     case 030:     /* fstenv  m14/28byte */
index f06ed41..e976cae 100644 (file)
@@ -244,7 +244,8 @@ int FPU_load_int64(long long __user *_s)
 
   RE_ENTRANT_CHECK_OFF;
   FPU_access_ok(VERIFY_READ, _s, 8);
-  copy_from_user(&s,_s,8);
+  if (copy_from_user(&s,_s,8))
+    FPU_abort;
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
@@ -907,7 +908,8 @@ int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
 
   RE_ENTRANT_CHECK_OFF;
   FPU_access_ok(VERIFY_WRITE,d,8);
-  copy_to_user(d, &tll, 8);
+  if (copy_to_user(d, &tll, 8))
+    FPU_abort;
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1336,7 +1338,8 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
       I387.soft.fcs &= ~0xf8000000;
       I387.soft.fos |= 0xffff0000;
 #endif /* PECULIAR_486 */
-      __copy_to_user(d, &control_word, 7*4);
+      if (__copy_to_user(d, &control_word, 7*4))
+       FPU_abort;
       RE_ENTRANT_CHECK_ON;
       d += 0x1c;
     }
@@ -1359,9 +1362,11 @@ void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
   FPU_access_ok(VERIFY_WRITE,d,80);
 
   /* Copy all registers in stack order. */
-  __copy_to_user(d, register_base+offset, other);
+  if (__copy_to_user(d, register_base+offset, other))
+    FPU_abort;
   if ( offset )
-    __copy_to_user(d+other, register_base, offset);
+    if (__copy_to_user(d+other, register_base, offset))
+      FPU_abort;
   RE_ENTRANT_CHECK_ON;
 
   finit();
index 4de11f5..4de95a1 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #undef CONFIG_X86_PAE
+#undef CONFIG_PARAVIRT
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
index ddbdb03..103b76e 100644 (file)
@@ -168,7 +168,7 @@ static void __init allocate_pgdat(int nid)
        if (nid && node_has_online_mem(nid))
                NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
        else {
-               NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
+               NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(min_low_pfn));
                min_low_pfn += PFN_UP(sizeof(pg_data_t));
        }
 }
index 2581575..aaaa4d2 100644 (file)
@@ -22,9 +22,9 @@
 #include <linux/highmem.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
+#include <linux/uaccess.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/kdebug.h>
 #include <asm/segment.h>
@@ -167,7 +167,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
 static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
 { 
        unsigned long limit;
-       unsigned long instr = get_segment_eip (regs, &limit);
+       unsigned char *instr = (unsigned char *)get_segment_eip (regs, &limit);
        int scan_more = 1;
        int prefetch = 0; 
        int i;
@@ -177,9 +177,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
                unsigned char instr_hi;
                unsigned char instr_lo;
 
-               if (instr > limit)
+               if (instr > (unsigned char *)limit)
                        break;
-               if (__get_user(opcode, (unsigned char __user *) instr))
+               if (probe_kernel_address(instr, opcode))
                        break; 
 
                instr_hi = opcode & 0xf0; 
@@ -204,9 +204,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
                case 0x00:
                        /* Prefetch instruction is 0x0F0D or 0x0F18 */
                        scan_more = 0;
-                       if (instr > limit)
+                       if (instr > (unsigned char *)limit)
                                break;
-                       if (__get_user(opcode, (unsigned char __user *) instr))
+                       if (probe_kernel_address(instr, opcode))
                                break;
                        prefetch = (instr_lo == 0xF) &&
                                (opcode == 0x0D || opcode == 0x18);
index f9f647c..e0fa6cb 100644 (file)
@@ -32,7 +32,7 @@ void *kmap_atomic(struct page *page, enum km_type type)
        unsigned long vaddr;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-       inc_preempt_count();
+       pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
@@ -50,26 +50,22 @@ 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();
 
-#ifdef CONFIG_DEBUG_HIGHMEM
-       if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
-               dec_preempt_count();
-               preempt_check_resched();
-               return;
-       }
-
-       if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
-               BUG();
-#endif
        /*
         * Force other mappings to Oops if they'll try to access this pte
         * without first remap it.  Keeping stale mappings around is a bad idea
         * also, in case the page changes cacheability attributes or becomes
         * a protected page in a hypervisor.
         */
-       kpte_clear_flush(kmap_pte-idx, vaddr);
+       if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+               kpte_clear_flush(kmap_pte-idx, vaddr);
+       else {
+#ifdef CONFIG_DEBUG_HIGHMEM
+               BUG_ON(vaddr < PAGE_OFFSET);
+               BUG_ON(vaddr >= (unsigned long)high_memory);
+#endif
+       }
 
-       dec_preempt_count();
-       preempt_check_resched();
+       pagefault_enable();
 }
 
 /* This is the same as kmap_atomic() but can map memory that doesn't
@@ -80,7 +76,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
        enum fixed_addresses idx;
        unsigned long vaddr;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
index 1719a81..34728e4 100644 (file)
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
+static unsigned long page_table_shareable(struct vm_area_struct *svma,
+                               struct vm_area_struct *vma,
+                               unsigned long addr, pgoff_t idx)
+{
+       unsigned long saddr = ((idx - svma->vm_pgoff) << PAGE_SHIFT) +
+                               svma->vm_start;
+       unsigned long sbase = saddr & PUD_MASK;
+       unsigned long s_end = sbase + PUD_SIZE;
+
+       /*
+        * match the virtual addresses, permission and the alignment of the
+        * page table page.
+        */
+       if (pmd_index(addr) != pmd_index(saddr) ||
+           vma->vm_flags != svma->vm_flags ||
+           sbase < svma->vm_start || svma->vm_end < s_end)
+               return 0;
+
+       return saddr;
+}
+
+static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
+{
+       unsigned long base = addr & PUD_MASK;
+       unsigned long end = base + PUD_SIZE;
+
+       /*
+        * check on proper vm_flags and page table alignment
+        */
+       if (vma->vm_flags & VM_MAYSHARE &&
+           vma->vm_start <= base && end <= vma->vm_end)
+               return 1;
+       return 0;
+}
+
+/*
+ * search for a shareable pmd page for hugetlb.
+ */
+static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+{
+       struct vm_area_struct *vma = find_vma(mm, addr);
+       struct address_space *mapping = vma->vm_file->f_mapping;
+       pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) +
+                       vma->vm_pgoff;
+       struct prio_tree_iter iter;
+       struct vm_area_struct *svma;
+       unsigned long saddr;
+       pte_t *spte = NULL;
+
+       if (!vma_shareable(vma, addr))
+               return;
+
+       spin_lock(&mapping->i_mmap_lock);
+       vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) {
+               if (svma == vma)
+                       continue;
+
+               saddr = page_table_shareable(svma, vma, addr, idx);
+               if (saddr) {
+                       spte = huge_pte_offset(svma->vm_mm, saddr);
+                       if (spte) {
+                               get_page(virt_to_page(spte));
+                               break;
+                       }
+               }
+       }
+
+       if (!spte)
+               goto out;
+
+       spin_lock(&mm->page_table_lock);
+       if (pud_none(*pud))
+               pud_populate(mm, pud, (unsigned long) spte & PAGE_MASK);
+       else
+               put_page(virt_to_page(spte));
+       spin_unlock(&mm->page_table_lock);
+out:
+       spin_unlock(&mapping->i_mmap_lock);
+}
+
+/*
+ * unmap huge page backed by shared pte.
+ *
+ * Hugetlb pte page is ref counted at the time of mapping.  If pte is shared
+ * indicated by page_count > 1, unmap is achieved by clearing pud and
+ * decrementing the ref count. If count == 1, the pte page is not shared.
+ *
+ * called with vma->vm_mm->page_table_lock held.
+ *
+ * returns: 1 successfully unmapped a shared pte page
+ *         0 the underlying pte page is not shared, or it is the last user
+ */
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       pgd_t *pgd = pgd_offset(mm, *addr);
+       pud_t *pud = pud_offset(pgd, *addr);
+
+       BUG_ON(page_count(virt_to_page(ptep)) == 0);
+       if (page_count(virt_to_page(ptep)) == 1)
+               return 0;
+
+       pud_clear(pud);
+       put_page(virt_to_page(ptep));
+       *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
+       return 1;
+}
+
 pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
@@ -25,8 +132,11 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 
        pgd = pgd_offset(mm, addr);
        pud = pud_alloc(mm, pgd, addr);
-       if (pud)
+       if (pud) {
+               if (pud_none(*pud))
+                       huge_pmd_share(mm, addr, pud);
                pte = (pte_t *) pmd_alloc(mm, pud, addr);
+       }
        BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
 
        return pte;
index 1674161..84697df 100644 (file)
@@ -192,8 +192,6 @@ static inline int page_kills_ppro(unsigned long pagenr)
        return 0;
 }
 
-extern int is_available_memory(efi_memory_desc_t *);
-
 int page_is_ram(unsigned long pagenr)
 {
        int i;
@@ -699,8 +697,8 @@ int remove_memory(u64 start, u64 size)
 #endif
 #endif
 
-kmem_cache_t *pgd_cache;
-kmem_cache_t *pmd_cache;
+struct kmem_cache *pgd_cache;
+struct kmem_cache *pmd_cache;
 
 void __init pgtable_cache_init(void)
 {
index 8564b6a..ad91528 100644 (file)
@@ -67,11 +67,17 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        return base;
 } 
 
-static void flush_kernel_map(void *dummy) 
+static void flush_kernel_map(void *arg)
 { 
-       /* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
-       if (boot_cpu_data.x86_model >= 4) 
+       unsigned long adr = (unsigned long)arg;
+
+       if (adr && cpu_has_clflush) {
+               int i;
+               for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+                       asm volatile("clflush (%0)" :: "r" (adr + i));
+       } else if (boot_cpu_data.x86_model >= 4)
                wbinvd();
+
        /* Flush all to work around Errata in early athlons regarding 
         * large page flushing. 
         */
@@ -173,9 +179,9 @@ __change_page_attr(struct page *page, pgprot_t prot)
        return 0;
 } 
 
-static inline void flush_map(void)
+static inline void flush_map(void *adr)
 {
-       on_each_cpu(flush_kernel_map, NULL, 1, 1);
+       on_each_cpu(flush_kernel_map, adr, 1, 1);
 }
 
 /*
@@ -217,9 +223,13 @@ void global_flush_tlb(void)
        spin_lock_irq(&cpa_lock);
        list_replace_init(&df_list, &l);
        spin_unlock_irq(&cpa_lock);
-       flush_map();
-       list_for_each_entry_safe(pg, next, &l, lru)
+       if (!cpu_has_clflush)
+               flush_map(0);
+       list_for_each_entry_safe(pg, next, &l, lru) {
+               if (cpu_has_clflush)
+                       flush_map(page_address(pg));
                __free_page(pg);
+       }
 }
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
index 10126e3..f349eaf 100644 (file)
@@ -95,8 +95,11 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
                return;
        }
        pte = pte_offset_kernel(pmd, vaddr);
-       /* <pfn,flags> stored as-is, to permit clearing entries */
-       set_pte(pte, pfn_pte(pfn, flags));
+       if (pgprot_val(flags))
+               /* <pfn,flags> stored as-is, to permit clearing entries */
+               set_pte(pte, pfn_pte(pfn, flags));
+       else
+               pte_clear(&init_mm, vaddr, pte);
 
        /*
         * It's enough to flush this one mapping.
@@ -193,7 +196,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
        return pte;
 }
 
-void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags)
+void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags)
 {
        memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
 }
@@ -233,7 +236,7 @@ static inline void pgd_list_del(pgd_t *pgd)
                set_page_private(next, (unsigned long)pprev);
 }
 
-void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags;
 
@@ -253,7 +256,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
 }
 
 /* never called when PTRS_PER_PMD > 1 */
-void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
 
index 713d6c8..42df4b6 100644 (file)
@@ -45,6 +45,13 @@ void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
        outl(val, 0xcfc);
 }
 
+void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
+{
+       PDprintk("%x writing to %x: %x\n", slot, offset, val);
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       outb(val, 0xcfc);
+}
+
 int early_pci_allowed(void)
 {
        return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
index e65551c..f2cb942 100644 (file)
@@ -764,7 +764,7 @@ static void __init pirq_find_router(struct irq_router *r)
        DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
            rt->rtr_vendor, rt->rtr_device);
 
-       pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
+       pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
        if (!pirq_router_dev) {
                DBG(KERN_DEBUG "PCI: Interrupt router not found at "
                        "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
@@ -784,6 +784,8 @@ static void __init pirq_find_router(struct irq_router *r)
                pirq_router_dev->vendor,
                pirq_router_dev->device,
                pci_name(pirq_router_dev));
+
+       /* The device remains referenced for the kernel lifetime */
 }
 
 static struct irq_info *pirq_get_info(struct pci_dev *dev)
index ed1512a..5f51934 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/uaccess.h>
 #include "pci.h"
 #include "pci-functions.h"
 
@@ -314,6 +315,10 @@ static struct pci_raw_ops * __devinit pci_find_bios(void)
        for (check = (union bios32 *) __va(0xe0000);
             check <= (union bios32 *) __va(0xffff0);
             ++check) {
+               long sig;
+               if (probe_kernel_address(&check->fields.signature, sig))
+                       continue;
+
                if (check->fields.signature != BIOS32_SIGNATURE)
                        continue;
                length = check->fields.length * 16;
@@ -331,11 +336,13 @@ static struct pci_raw_ops * __devinit pci_find_bios(void)
                }
                DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
                if (check->fields.entry >= 0x100000) {
-                       printk("PCI: BIOS32 entry (0x%p) in high memory, cannot use.\n", check);
+                       printk("PCI: BIOS32 entry (0x%p) in high memory, "
+                                       "cannot use.\n", check);
                        return NULL;
                } else {
                        unsigned long bios32_entry = check->fields.entry;
-                       DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
+                       DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n",
+                                       bios32_entry);
                        bios32_indirect.address = bios32_entry + PAGE_OFFSET;
                        if (check_pcibios())
                                return &pci_bios_access;
index 8cfa4e8..2de7bbf 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_PM)               += cpu.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o suspend.o
index 5a1abef..2c15500 100644 (file)
@@ -26,8 +26,8 @@ void __save_processor_state(struct saved_context *ctxt)
        /*
         * descriptor tables
         */
-       store_gdt(&ctxt->gdt_limit);
-       store_idt(&ctxt->idt_limit);
+       store_gdt(&ctxt->gdt);
+       store_idt(&ctxt->idt);
        store_tr(ctxt->tr);
 
        /*
@@ -99,8 +99,8 @@ void __restore_processor_state(struct saved_context *ctxt)
         * now restore the descriptor tables to their proper values
         * ltr is done i fix_processor_context().
         */
-       load_gdt(&ctxt->gdt_limit);
-       load_idt(&ctxt->idt_limit);
+       load_gdt(&ctxt->gdt);
+       load_idt(&ctxt->idt);
 
        /*
         * segment registers
diff --git a/arch/i386/power/suspend.c b/arch/i386/power/suspend.c
new file mode 100644 (file)
index 0000000..db5e98d
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Suspend support specific for i386 - temporary page tables
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ */
+
+#include <linux/suspend.h>
+#include <linux/bootmem.h>
+
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/* Defined in arch/i386/power/swsusp.S */
+extern int restore_image(void);
+
+/* Pointer to the temporary resume page tables */
+pgd_t *resume_pg_dir;
+
+/* The following three functions are based on the analogous code in
+ * arch/i386/mm/init.c
+ */
+
+/*
+ * Create a middle page table on a resume-safe page and put a pointer to it in
+ * the given global directory entry.  This only returns the gd entry
+ * in non-PAE compilation mode, since the middle layer is folded.
+ */
+static pmd_t *resume_one_md_table_init(pgd_t *pgd)
+{
+       pud_t *pud;
+       pmd_t *pmd_table;
+
+#ifdef CONFIG_X86_PAE
+       pmd_table = (pmd_t *)get_safe_page(GFP_ATOMIC);
+       if (!pmd_table)
+               return NULL;
+
+       set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+       pud = pud_offset(pgd, 0);
+
+       BUG_ON(pmd_table != pmd_offset(pud, 0));
+#else
+       pud = pud_offset(pgd, 0);
+       pmd_table = pmd_offset(pud, 0);
+#endif
+
+       return pmd_table;
+}
+
+/*
+ * Create a page table on a resume-safe page and place a pointer to it in
+ * a middle page directory entry.
+ */
+static pte_t *resume_one_page_table_init(pmd_t *pmd)
+{
+       if (pmd_none(*pmd)) {
+               pte_t *page_table = (pte_t *)get_safe_page(GFP_ATOMIC);
+               if (!page_table)
+                       return NULL;
+
+               set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+
+               BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+
+               return page_table;
+       }
+
+       return pte_offset_kernel(pmd, 0);
+}
+
+/*
+ * This maps the physical memory to kernel virtual address space, a total
+ * of max_low_pfn pages, by creating page tables starting from address
+ * PAGE_OFFSET.  The page tables are allocated out of resume-safe pages.
+ */
+static int resume_physical_mapping_init(pgd_t *pgd_base)
+{
+       unsigned long pfn;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       int pgd_idx, pmd_idx;
+
+       pgd_idx = pgd_index(PAGE_OFFSET);
+       pgd = pgd_base + pgd_idx;
+       pfn = 0;
+
+       for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+               pmd = resume_one_md_table_init(pgd);
+               if (!pmd)
+                       return -ENOMEM;
+
+               if (pfn >= max_low_pfn)
+                       continue;
+
+               for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
+                       if (pfn >= max_low_pfn)
+                               break;
+
+                       /* Map with big pages if possible, otherwise create
+                        * normal page tables.
+                        * NOTE: We can mark everything as executable here
+                        */
+                       if (cpu_has_pse) {
+                               set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
+                               pfn += PTRS_PER_PTE;
+                       } else {
+                               pte_t *max_pte;
+
+                               pte = resume_one_page_table_init(pmd);
+                               if (!pte)
+                                       return -ENOMEM;
+
+                               max_pte = pte + PTRS_PER_PTE;
+                               for (; pte < max_pte; pte++, pfn++) {
+                                       if (pfn >= max_low_pfn)
+                                               break;
+
+                                       set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+static inline void resume_init_first_level_page_table(pgd_t *pg_dir)
+{
+#ifdef CONFIG_X86_PAE
+       int i;
+
+       /* Init entries of the first-level page table to the zero page */
+       for (i = 0; i < PTRS_PER_PGD; i++)
+               set_pgd(pg_dir + i,
+                       __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+#endif
+}
+
+int swsusp_arch_resume(void)
+{
+       int error;
+
+       resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
+       if (!resume_pg_dir)
+               return -ENOMEM;
+
+       resume_init_first_level_page_table(resume_pg_dir);
+       error = resume_physical_mapping_init(resume_pg_dir);
+       if (error)
+               return error;
+
+       /* We have got enough memory and from now on we cannot recover */
+       restore_image();
+       return 0;
+}
index 8a2b50a..53662e0 100644 (file)
@@ -28,8 +28,9 @@ ENTRY(swsusp_arch_suspend)
        call swsusp_save
        ret
 
-ENTRY(swsusp_arch_resume)
-       movl    $swsusp_pg_dir-__PAGE_OFFSET, %ecx
+ENTRY(restore_image)
+       movl    resume_pg_dir, %ecx
+       subl    $__PAGE_OFFSET, %ecx
        movl    %ecx, %cr3
 
        movl    restore_pblist, %edx
@@ -51,6 +52,10 @@ copy_loop:
        .p2align 4,,7
 
 done:
+       /* go back to the original page tables */
+       movl    $swapper_pg_dir, %ecx
+       subl    $__PAGE_OFFSET, %ecx
+       movl    %ecx, %cr3
        /* Flush TLB, including "global" things (vmalloc) */
        movl    mmu_cr4_features, %eax
        movl    %eax, %edx
index 683b12c..fcacfe2 100644 (file)
@@ -34,6 +34,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
@@ -434,6 +442,29 @@ config IA64_ESI
 
 source "drivers/sn/Kconfig"
 
+config KEXEC
+       bool "kexec system call (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+       help
+         kexec is a system call that implements the ability to shutdown your
+         current kernel, and to start another kernel.  It is like a reboot
+         but it is indepedent of the system firmware.   And like a reboot
+         you can start any kernel with it, not just Linux.
+
+         The name comes from the similiarity to the exec system call.
+
+         It is an ongoing process to be certain the hardware in a machine
+         is properly shutdown, so do not be surprised if this code does not
+         initially work for you.  It may help to enable device hotplugging
+         support.  As of this writing the exact hardware interface is
+         strongly in flux, so no good recommendation can be made.
+
+config CRASH_DUMP
+         bool "kernel crash dumps (EXPERIMENTAL)"
+         depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+         help
+           Generate crash dump after being started by kexec.
+
 source "drivers/firmware/Kconfig"
 
 source "fs/Kconfig.binfmt"
index 14691cd..ce49fe3 100644 (file)
@@ -1672,15 +1672,13 @@ ioc_sac_init(struct ioc *ioc)
         * SAC (single address cycle) addressable, so allocate a
         * pseudo-device to enforce that.
         */
-       sac = kmalloc(sizeof(*sac), GFP_KERNEL);
+       sac = kzalloc(sizeof(*sac), GFP_KERNEL);
        if (!sac)
                panic(PFX "Couldn't allocate struct pci_dev");
-       memset(sac, 0, sizeof(*sac));
 
-       controller = kmalloc(sizeof(*controller), GFP_KERNEL);
+       controller = kzalloc(sizeof(*controller), GFP_KERNEL);
        if (!controller)
                panic(PFX "Couldn't allocate struct pci_controller");
-       memset(controller, 0, sizeof(*controller));
 
        controller->iommu = ioc;
        sac->sysdata = controller;
@@ -1737,12 +1735,10 @@ ioc_init(u64 hpa, void *handle)
        struct ioc *ioc;
        struct ioc_iommu *info;
 
-       ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
+       ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
        if (!ioc)
                return NULL;
 
-       memset(ioc, 0, sizeof(*ioc));
-
        ioc->next = ioc_list;
        ioc_list = ioc;
 
index caab986..1f16ebb 100644 (file)
@@ -209,7 +209,7 @@ static void do_serial_bh(void)
 }
 #endif
 
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *private_)
 {
        printk(KERN_ERR "simserial: do_softint called\n");
 }
@@ -684,12 +684,11 @@ static int get_async_struct(int line, struct async_struct **ret_info)
                *ret_info = sstate->info;
                return 0;
        }
-       info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
+       info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
        if (!info) {
                sstate->count--;
                return -ENOMEM;
        }
-       memset(info, 0, sizeof(struct async_struct));
        init_waitqueue_head(&info->open_wait);
        init_waitqueue_head(&info->close_wait);
        init_waitqueue_head(&info->delta_msr_wait);
@@ -698,7 +697,7 @@ static int get_async_struct(int line, struct async_struct **ret_info)
        info->flags = sstate->flags;
        info->xmit_fifo_size = sstate->xmit_fifo_size;
        info->line = line;
-       INIT_WORK(&info->work, do_softint, info);
+       INIT_WORK(&info->work, do_softint);
        info->state = sstate;
        if (sstate->info) {
                kfree(info);
index daa6b91..578737e 100644 (file)
@@ -91,7 +91,7 @@ ia64_elf32_init (struct pt_regs *regs)
         * it with privilege level 3 because the IVE uses non-privileged accesses to these
         * tables.  IA-32 segmentation is used to protect against IA-32 accesses to them.
         */
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (vma) {
                memset(vma, 0, sizeof(*vma));
                vma->vm_mm = current->mm;
@@ -117,7 +117,7 @@ ia64_elf32_init (struct pt_regs *regs)
         * code is locked in specific gate page, which is pointed by pretcode
         * when setup_frame_ia32
         */
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (vma) {
                memset(vma, 0, sizeof(*vma));
                vma->vm_mm = current->mm;
@@ -142,7 +142,7 @@ ia64_elf32_init (struct pt_regs *regs)
         * Install LDT as anonymous memory.  This gives us all-zero segment descriptors
         * until a task modifies them via modify_ldt().
         */
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (vma) {
                memset(vma, 0, sizeof(*vma));
                vma->vm_mm = current->mm;
@@ -214,7 +214,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
                bprm->loader += stack_base;
        bprm->exec += stack_base;
 
-       mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!mpnt)
                return -ENOMEM;
 
index c187743..6af400a 100644 (file)
@@ -249,7 +249,7 @@ ia32_init (void)
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
        {
-               extern kmem_cache_t *partial_page_cachep;
+               extern struct kmem_cache *partial_page_cachep;
 
                partial_page_cachep = kmem_cache_create("partial_page_cache",
                                                        sizeof(struct partial_page), 0, 0,
index 703a67c..cfa0bc0 100644 (file)
@@ -330,8 +330,6 @@ struct old_linux32_dirent {
 void ia64_elf32_init(struct pt_regs *regs);
 #define ELF_PLAT_INIT(_r, load_addr)   ia64_elf32_init(_r)
 
-#define elf_addr_t     u32
-
 /* This macro yields a bitmask that programs can use to figure out
    what instruction set this CPU supports.  */
 #define ELF_HWCAP      0
index 9d6a3f2..957681c 100644 (file)
@@ -235,7 +235,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 
        if (!(flags & MAP_ANONYMOUS)) {
                /* read the file contents */
-               inode = file->f_dentry->d_inode;
+               inode = file->f_path.dentry->d_inode;
                if (!inode->i_fop || !file->f_op->read
                    || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0))
                {
@@ -254,7 +254,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 }
 
 /* SLAB cache for partial_page structures */
-kmem_cache_t *partial_page_cachep;
+struct kmem_cache *partial_page_cachep;
 
 /*
  * init partial_page_list.
@@ -837,7 +837,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
 
        if (!is_congruent) {
                /* read the file contents */
-               inode = file->f_dentry->d_inode;
+               inode = file->f_path.dentry->d_inode;
                if (!inode->i_fop || !file->f_op->read
                    || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff)
                        < 0))
index cfa099b..8ae384e 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_IA64_CYCLONE)    += cyclone.o
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_IA64_MCA_RECOVERY)        += mca_recovery.o
 obj-$(CONFIG_KPROBES)          += kprobes.o jprobes.o
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)  += uncached.o
 obj-$(CONFIG_AUDIT)            += audit.o
 obj-$(CONFIG_PCI_MSI)          += msi_ia64.o
index 86faf22..088f130 100644 (file)
@@ -68,7 +68,8 @@ processor_get_pstate (
 
        dprintk("processor_get_pstate\n");
 
-       retval = ia64_pal_get_pstate(&pstate_index);
+       retval = ia64_pal_get_pstate(&pstate_index,
+                                    PAL_GET_PSTATE_TYPE_INSTANT);
        *value = (u32) pstate_index;
 
        if (retval)
@@ -91,7 +92,7 @@ extract_clock (
        dprintk("extract_clock\n");
 
        for (i = 0; i < data->acpi_data.state_count; i++) {
-               if (value >= data->acpi_data.states[i].control)
+               if (value == data->acpi_data.states[i].status)
                        return data->acpi_data.states[i].core_frequency;
        }
        return data->acpi_data.states[i-1].core_frequency;
@@ -117,11 +118,7 @@ processor_get_freq (
                goto migrate_end;
        }
 
-       /*
-        * processor_get_pstate gets the average frequency since the
-        * last get. So, do two PAL_get_freq()...
-        */
-       ret = processor_get_pstate(&value);
+       /* processor_get_pstate gets the instantaneous frequency */
        ret = processor_get_pstate(&value);
 
        if (ret) {
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
new file mode 100644 (file)
index 0000000..0aabedf
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * arch/ia64/kernel/crash.c
+ *
+ * Architecture specific (ia64) functions for kexec based crash dumps.
+ *
+ * Created by: Khalid Aziz <khalid.aziz@hp.com>
+ * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2005 Intel Corp       Zou Nan hai <nanhai.zou@intel.com>
+ *
+ */
+#include <linux/smp.h>
+#include <linux/delay.h>
+#include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <linux/kexec.h>
+#include <linux/elfcore.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+
+#include <asm/kdebug.h>
+#include <asm/mca.h>
+#include <asm/uaccess.h>
+
+int kdump_status[NR_CPUS];
+atomic_t kdump_cpu_freezed;
+atomic_t kdump_in_progress;
+int kdump_on_init = 1;
+ssize_t
+copy_oldmem_page(unsigned long pfn, char *buf,
+               size_t csize, unsigned long offset, int userbuf)
+{
+       void  *vaddr;
+
+       if (!csize)
+               return 0;
+       vaddr = __va(pfn<<PAGE_SHIFT);
+       if (userbuf) {
+               if (copy_to_user(buf, (vaddr + offset), csize)) {
+                       return -EFAULT;
+               }
+       } else
+               memcpy(buf, (vaddr + offset), csize);
+       return csize;
+}
+
+static inline Elf64_Word
+*append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
+               size_t data_len)
+{
+       struct elf_note *note = (struct elf_note *)buf;
+       note->n_namesz = strlen(name) + 1;
+       note->n_descsz = data_len;
+       note->n_type   = type;
+       buf += (sizeof(*note) + 3)/4;
+       memcpy(buf, name, note->n_namesz);
+       buf += (note->n_namesz + 3)/4;
+       memcpy(buf, data, data_len);
+       buf += (data_len + 3)/4;
+       return buf;
+}
+
+static void
+final_note(void *buf)
+{
+       memset(buf, 0, sizeof(struct elf_note));
+}
+
+extern void ia64_dump_cpu_regs(void *);
+
+static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
+
+void
+crash_save_this_cpu()
+{
+       void *buf;
+       unsigned long cfm, sof, sol;
+
+       int cpu = smp_processor_id();
+       struct elf_prstatus *prstatus = &per_cpu(elf_prstatus, cpu);
+
+       elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
+       memset(prstatus, 0, sizeof(*prstatus));
+       prstatus->pr_pid = current->pid;
+
+       ia64_dump_cpu_regs(dst);
+       cfm = dst[43];
+       sol = (cfm >> 7) & 0x7f;
+       sof = cfm & 0x7f;
+       dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46],
+                       sof - sol);
+
+       buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
+       if (!buf)
+               return;
+       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus,
+                       sizeof(*prstatus));
+       final_note(buf);
+}
+
+static int
+kdump_wait_cpu_freeze(void)
+{
+       int cpu_num = num_online_cpus() - 1;
+       int timeout = 1000;
+       while(timeout-- > 0) {
+               if (atomic_read(&kdump_cpu_freezed) == cpu_num)
+                       return 0;
+               udelay(1000);
+       }
+       return 1;
+}
+
+void
+machine_crash_shutdown(struct pt_regs *pt)
+{
+       /* This function is only called after the system
+        * has paniced or is otherwise in a critical state.
+        * The minimum amount of code to allow a kexec'd kernel
+        * to run successfully needs to happen here.
+        *
+        * In practice this means shooting down the other cpus in
+        * an SMP system.
+        */
+       kexec_disable_iosapic();
+#ifdef CONFIG_SMP
+       kdump_smp_send_stop();
+       if (kdump_wait_cpu_freeze() && kdump_on_init)   {
+               //not all cpu response to IPI, send INIT to freeze them
+               kdump_smp_send_init();
+       }
+#endif
+}
+
+static void
+machine_kdump_on_init(void)
+{
+       local_irq_disable();
+       kexec_disable_iosapic();
+       machine_kexec(ia64_kimage);
+}
+
+void
+kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
+{
+       int cpuid;
+       local_irq_disable();
+       cpuid = smp_processor_id();
+       crash_save_this_cpu();
+       current->thread.ksp = (__u64)info->sw - 16;
+       atomic_inc(&kdump_cpu_freezed);
+       kdump_status[cpuid] = 1;
+       mb();
+       if (cpuid == 0) {
+               for (;;)
+                       cpu_relax();
+       } else
+               ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
+}
+
+static int
+kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
+{
+       struct ia64_mca_notify_die *nd;
+       struct die_args *args = data;
+
+       if (!kdump_on_init)
+               return NOTIFY_DONE;
+
+       if (val != DIE_INIT_MONARCH_ENTER &&
+           val != DIE_INIT_SLAVE_ENTER &&
+           val != DIE_MCA_RENDZVOUS_LEAVE &&
+           val != DIE_MCA_MONARCH_LEAVE)
+               return NOTIFY_DONE;
+
+       nd = (struct ia64_mca_notify_die *)args->err;
+       /* Reason code 1 means machine check rendezous*/
+       if ((val == DIE_INIT_MONARCH_ENTER || DIE_INIT_SLAVE_ENTER) &&
+                nd->sos->rv_rc == 1)
+               return NOTIFY_DONE;
+
+       switch (val) {
+               case DIE_INIT_MONARCH_ENTER:
+                       machine_kdump_on_init();
+                       break;
+               case DIE_INIT_SLAVE_ENTER:
+                       unw_init_running(kdump_cpu_freeze, NULL);
+                       break;
+               case DIE_MCA_RENDZVOUS_LEAVE:
+                       if (atomic_read(&kdump_in_progress))
+                               unw_init_running(kdump_cpu_freeze, NULL);
+                       break;
+               case DIE_MCA_MONARCH_LEAVE:
+                    /* die_register->signr indicate if MCA is recoverable */
+                       if (!args->signr)
+                               machine_kdump_on_init();
+                       break;
+       }
+       return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_SYSCTL
+static ctl_table kdump_on_init_table[] = {
+       {
+               .ctl_name = CTL_UNNUMBERED,
+               .procname = "kdump_on_init",
+               .data = &kdump_on_init,
+               .maxlen = sizeof(int),
+               .mode = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table sys_table[] = {
+       {
+         .ctl_name = CTL_KERN,
+         .procname = "kernel",
+         .mode = 0555,
+         .child = kdump_on_init_table,
+       },
+       { .ctl_name = 0 }
+};
+#endif
+
+static int
+machine_crash_setup(void)
+{
+       char *from = strstr(saved_command_line, "elfcorehdr=");
+       static struct notifier_block kdump_init_notifier_nb = {
+               .notifier_call = kdump_init_notifier,
+       };
+       int ret;
+       if (from)
+               elfcorehdr_addr = memparse(from+11, &from);
+       saved_max_pfn = (unsigned long)-1;
+       if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
+               return ret;
+#ifdef CONFIG_SYSCTL
+       register_sysctl_table(sys_table, 0);
+#endif
+       return 0;
+}
+
+__initcall(machine_crash_setup);
+
index bb8770a..0b25a7d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/efi.h>
+#include <linux/kexec.h>
 
 #include <asm/io.h>
 #include <asm/kregs.h>
@@ -41,7 +42,7 @@ extern efi_status_t efi_call_phys (void *, ...);
 struct efi efi;
 EXPORT_SYMBOL(efi);
 static efi_runtime_services_t *runtime;
-static unsigned long mem_limit = ~0UL, max_addr = ~0UL;
+static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
 
 #define efi_call_virt(f, args...)      (*(f))(args)
 
@@ -224,7 +225,7 @@ efi_gettimeofday (struct timespec *ts)
 }
 
 static int
-is_available_memory (efi_memory_desc_t *md)
+is_memory_available (efi_memory_desc_t *md)
 {
        if (!(md->attribute & EFI_MEMORY_WB))
                return 0;
@@ -421,6 +422,8 @@ efi_init (void)
                        mem_limit = memparse(cp + 4, &cp);
                } else if (memcmp(cp, "max_addr=", 9) == 0) {
                        max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
+               } else if (memcmp(cp, "min_addr=", 9) == 0) {
+                       min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
                } else {
                        while (*cp != ' ' && *cp)
                                ++cp;
@@ -428,6 +431,8 @@ efi_init (void)
                                ++cp;
                }
        }
+       if (min_addr != 0UL)
+               printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20);
        if (max_addr != ~0UL)
                printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
 
@@ -887,14 +892,15 @@ find_memmap_space (void)
                        }
                        contig_high = GRANULEROUNDDOWN(contig_high);
                }
-               if (!is_available_memory(md) || md->type == EFI_LOADER_DATA)
+               if (!is_memory_available(md) || md->type == EFI_LOADER_DATA)
                        continue;
 
                /* Round ends inward to granule boundaries */
                as = max(contig_low, md->phys_addr);
                ae = min(contig_high, efi_md_end(md));
 
-               /* keep within max_addr= command line arg */
+               /* keep within max_addr= and min_addr= command line arg */
+               as = max(as, min_addr);
                ae = min(ae, max_addr);
                if (ae <= as)
                        continue;
@@ -962,7 +968,7 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
                        }
                        contig_high = GRANULEROUNDDOWN(contig_high);
                }
-               if (!is_available_memory(md))
+               if (!is_memory_available(md))
                        continue;
 
                /*
@@ -1004,7 +1010,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
                } else
                        ae = efi_md_end(md);
 
-               /* keep within max_addr= command line arg */
+               /* keep within max_addr= and min_addr= command line arg */
+               as = max(as, min_addr);
                ae = min(ae, max_addr);
                if (ae <= as)
                        continue;
@@ -1116,6 +1123,58 @@ efi_initialize_iomem_resources(struct resource *code_resource,
                         */
                        insert_resource(res, code_resource);
                        insert_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+                        insert_resource(res, &efi_memmap_res);
+                        insert_resource(res, &boot_param_res);
+                       if (crashk_res.end > crashk_res.start)
+                               insert_resource(res, &crashk_res);
+#endif
                }
        }
 }
+
+#ifdef CONFIG_KEXEC
+/* find a block of memory aligned to 64M exclude reserved regions
+   rsvd_regions are sorted
+ */
+unsigned long
+kdump_find_rsvd_region (unsigned long size,
+               struct rsvd_region *r, int n)
+{
+  int i;
+  u64 start, end;
+  u64 alignment = 1UL << _PAGE_SIZE_64M;
+  void *efi_map_start, *efi_map_end, *p;
+  efi_memory_desc_t *md;
+  u64 efi_desc_size;
+
+  efi_map_start = __va(ia64_boot_param->efi_memmap);
+  efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+  efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+  for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+         md = p;
+         if (!efi_wb(md))
+                 continue;
+         start = ALIGN(md->phys_addr, alignment);
+         end = efi_md_end(md);
+         for (i = 0; i < n; i++) {
+               if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
+                       if (__pa(r[i].start) > start + size)
+                               return start;
+                       start = ALIGN(__pa(r[i].end), alignment);
+                       if (i < n-1 && __pa(r[i+1].start) < start + size)
+                               continue;
+                       else
+                               break;
+               }
+         }
+         if (end > start + size)
+               return start;
+  }
+
+  printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n",
+       size);
+  return ~0UL;
+}
+#endif
index 3390b7c..15234ed 100644 (file)
@@ -1575,7 +1575,7 @@ sys_call_table:
        data8 sys_mq_timedreceive               // 1265
        data8 sys_mq_notify
        data8 sys_mq_getsetattr
-       data8 sys_ni_syscall                    // reserved for kexec_load
+       data8 sys_kexec_load
        data8 sys_ni_syscall                    // reserved for vserver
        data8 sys_waitid                        // 1270
        data8 sys_add_key
index 879c181..bd17190 100644 (file)
@@ -14,6 +14,7 @@ EXPORT_SYMBOL(strlen);
 
 #include <asm/checksum.h>
 EXPORT_SYMBOL(ip_fast_csum);           /* hand-coded assembly */
+EXPORT_SYMBOL(csum_ipv6_magic);
 
 #include <asm/semaphore.h>
 EXPORT_SYMBOL(__down);
index 60d6495..0fc5fb7 100644 (file)
@@ -288,6 +288,27 @@ nop (unsigned int irq)
        /* do nothing... */
 }
 
+
+#ifdef CONFIG_KEXEC
+void
+kexec_disable_iosapic(void)
+{
+       struct iosapic_intr_info *info;
+       struct iosapic_rte_info *rte;
+       u8 vec = 0;
+       for (info = iosapic_intr_info; info <
+                       iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) {
+               list_for_each_entry(rte, &info->rtes,
+                               rte_list) {
+                       iosapic_write(rte->addr,
+                                       IOSAPIC_RTE_LOW(rte->rte_index),
+                                       IOSAPIC_MASK|vec);
+                       iosapic_eoi(rte->addr, vec);
+               }
+       }
+}
+#endif
+
 static void
 mask_irq (unsigned int irq)
 {
index 51217d6..76e7789 100644 (file)
@@ -481,7 +481,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, 0);
        mutex_unlock(&kprobe_mutex);
 }
 /*
@@ -851,7 +851,7 @@ static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
                        return;
                }
        } while (unw_unwind(info) >= 0);
-       lp->bsp = 0;
+       lp->bsp = NULL;
        lp->cfm = 0;
        return;
 }
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
new file mode 100644 (file)
index 0000000..468233f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * arch/ia64/kernel/machine_kexec.c
+ *
+ * Handle transition of Linux booting another kernel
+ * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
+ * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
+ * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/cpu.h>
+#include <linux/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/setup.h>
+#include <asm/delay.h>
+#include <asm/meminit.h>
+
+typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long,
+               struct ia64_boot_param *, unsigned long);
+
+struct kimage *ia64_kimage;
+
+struct resource efi_memmap_res = {
+        .name  = "EFI Memory Map",
+        .start = 0,
+        .end   = 0,
+        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+struct resource boot_param_res = {
+        .name  = "Boot parameter",
+        .start = 0,
+        .end   = 0,
+        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+
+/*
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+       void *control_code_buffer;
+       const unsigned long *func;
+
+       func = (unsigned long *)&relocate_new_kernel;
+       /* Pre-load control code buffer to minimize work in kexec path */
+       control_code_buffer = page_address(image->control_code_page);
+       memcpy((void *)control_code_buffer, (const void *)func[0],
+                       relocate_new_kernel_size);
+       flush_icache_range((unsigned long)control_code_buffer,
+                       (unsigned long)control_code_buffer + relocate_new_kernel_size);
+       ia64_kimage = image;
+
+       return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void machine_shutdown(void)
+{
+       int cpu;
+
+       for_each_online_cpu(cpu) {
+               if (cpu != smp_processor_id())
+                       cpu_down(cpu);
+       }
+       kexec_disable_iosapic();
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+extern void *efi_get_pal_addr(void);
+static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
+{
+       struct kimage *image = arg;
+       relocate_new_kernel_t rnk;
+       void *pal_addr = efi_get_pal_addr();
+       unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
+       unsigned long vector;
+       int ii;
+
+       if (image->type == KEXEC_TYPE_CRASH) {
+               crash_save_this_cpu();
+               current->thread.ksp = (__u64)info->sw - 16;
+       }
+
+       /* Interrupts aren't acceptable while we reboot */
+       local_irq_disable();
+
+       /* Mask CMC and Performance Monitor interrupts */
+       ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
+       ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
+
+       /* Mask ITV and Local Redirect Registers */
+       ia64_set_itv(1 << 16);
+       ia64_set_lrr0(1 << 16);
+       ia64_set_lrr1(1 << 16);
+
+       /* terminate possible nested in-service interrupts */
+       for (ii = 0; ii < 16; ii++)
+               ia64_eoi();
+
+       /* unmask TPR and clear any pending interrupts */
+       ia64_setreg(_IA64_REG_CR_TPR, 0);
+       ia64_srlz_d();
+       vector = ia64_get_ivr();
+       while (vector != IA64_SPURIOUS_INT_VECTOR) {
+               ia64_eoi();
+               vector = ia64_get_ivr();
+       }
+       platform_kernel_launch_event();
+       rnk = (relocate_new_kernel_t)&code_addr;
+       (*rnk)(image->head, image->start, ia64_boot_param,
+                    GRANULEROUNDDOWN((unsigned long) pal_addr));
+       BUG();
+}
+
+void machine_kexec(struct kimage *image)
+{
+       unw_init_running(ia64_machine_kexec, image);
+       for(;;);
+}
index 7cfa63a..87c1c4f 100644 (file)
@@ -82,6 +82,7 @@
 #include <asm/system.h>
 #include <asm/sal.h>
 #include <asm/mca.h>
+#include <asm/kexec.h>
 
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
@@ -678,7 +679,7 @@ ia64_mca_cmc_vector_enable (void *dummy)
  * disable the cmc interrupt vector.
  */
 static void
-ia64_mca_cmc_vector_disable_keventd(void *unused)
+ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused)
 {
        on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0);
 }
@@ -690,7 +691,7 @@ ia64_mca_cmc_vector_disable_keventd(void *unused)
  * enable the cmc interrupt vector.
  */
 static void
-ia64_mca_cmc_vector_enable_keventd(void *unused)
+ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused)
 {
        on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0);
 }
@@ -1238,6 +1239,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        } else {
                /* Dump buffered message to console */
                ia64_mlogbuf_finish(1);
+#ifdef CONFIG_CRASH_DUMP
+               atomic_set(&kdump_in_progress, 1);
+               monarch_cpu = -1;
+#endif
        }
        if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
                        == NOTIFY_STOP)
@@ -1247,8 +1252,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        monarch_cpu = -1;
 }
 
-static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL);
-static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL);
+static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd);
+static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd);
 
 /*
  * ia64_mca_cmc_int_handler
index 0b546e2..a71df9a 100644 (file)
@@ -16,6 +16,7 @@
  * 02/05/2001   S.Eranian      fixed module support
  * 10/23/2001  S.Eranian       updated pal_perf_mon_info bug fixes
  * 03/24/2004  Ashok Raj       updated to work with CPU Hotplug
+ * 10/26/2006   Russ Anderson  updated processor features to rev 2.2 spec
  */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -314,13 +315,20 @@ vm_info(char *page)
                     "Protection Key Registers(PKR)  : %d\n"
                     "Implemented bits in PKR.key    : %d\n"
                     "Hash Tag ID                    : 0x%x\n"
-                    "Size of RR.rid                 : %d\n",
+                    "Size of RR.rid                 : %d\n"
+                    "Max Purges                     : ",
                     vm_info_1.pal_vm_info_1_s.phys_add_size,
                     vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
                     vm_info_1.pal_vm_info_1_s.max_pkr+1,
                     vm_info_1.pal_vm_info_1_s.key_size,
                     vm_info_1.pal_vm_info_1_s.hash_tag_id,
                     vm_info_2.pal_vm_info_2_s.rid_size);
+               if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
+                       p += sprintf(p, "unlimited\n");
+               else
+                       p += sprintf(p, "%d\n",
+                               vm_info_2.pal_vm_info_2_s.max_purges ?
+                               vm_info_2.pal_vm_info_2_s.max_purges : 1);
        }
 
        if (ia64_pal_mem_attrib(&attrib) == 0) {
@@ -467,7 +475,11 @@ static const char *proc_features[]={
        NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
        NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
        NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,
-       NULL,NULL,NULL,NULL,NULL,
+       "Unimplemented instruction address fault",
+       "INIT, PMI, and LINT pins",
+       "Simple unimplemented instr addresses",
+       "Variable P-state performance",
+       "Virtual machine features implemented",
        "XIP,XPSR,XFS implemented",
        "XR1-XR3 implemented",
        "Disable dynamic predicate prediction",
@@ -475,7 +487,11 @@ static const char *proc_features[]={
        "Disable dynamic data cache prefetch",
        "Disable dynamic inst cache prefetch",
        "Disable dynamic branch prediction",
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL,
+       "Disable P-states",
+       "Enable MCA on Data Poisoning",
+       "Enable vmsw instruction",
+       "Enable extern environmental notification",
        "Disable BINIT on processor time-out",
        "Disable dynamic power management (DPM)",
        "Disable coherency",
@@ -952,7 +968,6 @@ remove_palinfo_proc_entries(unsigned int hcpu)
        }
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int palinfo_cpu_callback(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
@@ -974,7 +989,6 @@ static struct notifier_block palinfo_cpu_notifier =
        .notifier_call = palinfo_cpu_callback,
        .priority = 0,
 };
-#endif
 
 static int __init
 palinfo_init(void)
index 3aaede0..aa94f60 100644 (file)
@@ -853,9 +853,8 @@ pfm_context_alloc(void)
         * allocate context descriptor 
         * must be able to free with interrupts disabled
         */
-       ctx = kmalloc(sizeof(pfm_context_t), GFP_KERNEL);
+       ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL);
        if (ctx) {
-               memset(ctx, 0, sizeof(pfm_context_t));
                DPRINT(("alloc ctx @%p\n", ctx));
        }
        return ctx;
@@ -2189,13 +2188,13 @@ pfm_alloc_fd(struct file **cfile)
        /*
         * allocate a new dcache entry
         */
-       file->f_dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
-       if (!file->f_dentry) goto out;
+       file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+       if (!file->f_path.dentry) goto out;
 
-       file->f_dentry->d_op = &pfmfs_dentry_operations;
+       file->f_path.dentry->d_op = &pfmfs_dentry_operations;
 
-       d_add(file->f_dentry, inode);
-       file->f_vfsmnt = mntget(pfmfs_mnt);
+       d_add(file->f_path.dentry, inode);
+       file->f_path.mnt = mntget(pfmfs_mnt);
        file->f_mapping = inode->i_mapping;
 
        file->f_op    = &pfm_file_ops;
@@ -2302,7 +2301,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
        DPRINT(("smpl_buf @%p\n", smpl_buf));
 
        /* allocate vma */
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!vma) {
                DPRINT(("Cannot allocate vma\n"));
                goto error_kmem;
index cd06ac6..7f8da4c 100644 (file)
@@ -45,16 +45,16 @@ static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={
 /* pmc29 */ { PFM_REG_NOTIMPL, },
 /* pmc30 */ { PFM_REG_NOTIMPL, },
 /* pmc31 */ { PFM_REG_NOTIMPL, },
-/* pmc32 */ { PFM_REG_CONFIG,  0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
-/* pmc33 */ { PFM_REG_CONFIG,  0, 0x0,  0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
-/* pmc34 */ { PFM_REG_CONFIG,  0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
-/* pmc35 */ { PFM_REG_CONFIG,  0, 0x0,  0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc32 */ { PFM_REG_CONFIG,  0, 0x30f01ffffffffffUL, 0x30f01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc33 */ { PFM_REG_CONFIG,  0, 0x0,  0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc34 */ { PFM_REG_CONFIG,  0, 0xf01ffffffffffUL, 0xf01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc35 */ { PFM_REG_CONFIG,  0, 0x0,  0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
 /* pmc36 */ { PFM_REG_CONFIG,  0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
 /* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}},
 /* pmc38 */ { PFM_REG_CONFIG,  0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
 /* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
 /* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}},
-/* pmc41 */ { PFM_REG_CONFIG,  0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc41 */ { PFM_REG_CONFIG,  0, 0x00002078fefefefeUL, 0x1e00018181818UL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
 /* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
            { PFM_REG_END    , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
 };
@@ -185,7 +185,7 @@ pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cn
        DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded));
 
        if (cnum == 41 && is_loaded 
-           && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
+           && (tmpval & 0x1e00000000000UL) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
 
                DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval));
 
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
new file mode 100644 (file)
index 0000000..ae473e3
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * arch/ia64/kernel/relocate_kernel.S
+ *
+ * Relocate kexec'able kernel and start it
+ *
+ * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2005 Khalid Aziz  <khalid.aziz@hp.com>
+ * Copyright (C) 2005 Intel Corp,  Zou Nan hai <nanhai.zou@intel.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+#include <asm/asmmacro.h>
+#include <asm/kregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mca_asm.h>
+
+       /* Must be relocatable PIC code callable as a C function
+        */
+GLOBAL_ENTRY(relocate_new_kernel)
+       .prologue
+       alloc r31=ar.pfs,4,0,0,0
+        .body
+.reloc_entry:
+{
+       rsm psr.i| psr.ic
+       mov r2=ip
+}
+       ;;
+{
+        flushrs                         // must be first insn in group
+        srlz.i
+}
+       ;;
+       dep r2=0,r2,61,3                //to physical address
+       ;;
+       //first switch to physical mode
+       add r3=1f-.reloc_entry, r2
+       movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
+       mov ar.rsc=0                    // put RSE in enforced lazy mode
+       ;;
+       add sp=(memory_stack_end - 16 - .reloc_entry),r2
+       add r8=(register_stack - .reloc_entry),r2
+       ;;
+       mov r18=ar.rnat
+       mov ar.bspstore=r8
+       ;;
+        mov cr.ipsr=r16
+        mov cr.iip=r3
+        mov cr.ifs=r0
+       srlz.i
+       ;;
+       mov ar.rnat=r18
+       rfi
+       ;;
+1:
+       //physical mode code begin
+       mov b6=in1
+       dep r28=0,in2,61,3      //to physical address
+
+       // purge all TC entries
+#define O(member)       IA64_CPUINFO_##member##_OFFSET
+        GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
+        ;;
+        addl r17=O(PTCE_STRIDE),r2
+        addl r2=O(PTCE_BASE),r2
+        ;;
+        ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));;            // r18=ptce_base
+        ld4 r19=[r2],4                                  // r19=ptce_count[0]
+        ld4 r21=[r17],4                                 // r21=ptce_stride[0]
+        ;;
+        ld4 r20=[r2]                                    // r20=ptce_count[1]
+        ld4 r22=[r17]                                   // r22=ptce_stride[1]
+        mov r24=r0
+        ;;
+        adds r20=-1,r20
+        ;;
+#undef O
+2:
+        cmp.ltu p6,p7=r24,r19
+(p7)    br.cond.dpnt.few 4f
+        mov ar.lc=r20
+3:
+        ptc.e r18
+        ;;
+        add r18=r22,r18
+        br.cloop.sptk.few 3b
+        ;;
+        add r18=r21,r18
+        add r24=1,r24
+        ;;
+        br.sptk.few 2b
+4:
+        srlz.i
+        ;;
+       //purge TR entry for kernel text and data
+        movl r16=KERNEL_START
+        mov r18=KERNEL_TR_PAGE_SHIFT<<2
+        ;;
+        ptr.i r16, r18
+        ptr.d r16, r18
+        ;;
+        srlz.i
+        ;;
+
+       // purge TR entry for percpu data
+        movl r16=PERCPU_ADDR
+        mov r18=PERCPU_PAGE_SHIFT<<2
+        ;;
+        ptr.d r16,r18
+        ;;
+        srlz.d
+       ;;
+
+        // purge TR entry for pal code
+        mov r16=in3
+        mov r18=IA64_GRANULE_SHIFT<<2
+        ;;
+        ptr.i r16,r18
+        ;;
+        srlz.i
+       ;;
+
+        // purge TR entry for stack
+        mov r16=IA64_KR(CURRENT_STACK)
+        ;;
+        shl r16=r16,IA64_GRANULE_SHIFT
+        movl r19=PAGE_OFFSET
+        ;;
+        add r16=r19,r16
+        mov r18=IA64_GRANULE_SHIFT<<2
+        ;;
+        ptr.d r16,r18
+        ;;
+        srlz.i
+       ;;
+
+       //copy segments
+       movl r16=PAGE_MASK
+        mov  r30=in0                    // in0 is page_list
+        br.sptk.few .dest_page
+       ;;
+.loop:
+       ld8  r30=[in0], 8;;
+.dest_page:
+       tbit.z p0, p6=r30, 0;;          // 0x1 dest page
+(p6)   and r17=r30, r16
+(p6)   br.cond.sptk.few .loop;;
+
+       tbit.z p0, p6=r30, 1;;          // 0x2 indirect page
+(p6)   and in0=r30, r16
+(p6)   br.cond.sptk.few .loop;;
+
+       tbit.z p0, p6=r30, 2;;          // 0x4 end flag
+(p6)   br.cond.sptk.few .end_loop;;
+
+       tbit.z p6, p0=r30, 3;;          // 0x8 source page
+(p6)   br.cond.sptk.few .loop
+
+       and r18=r30, r16
+
+       // simple copy page, may optimize later
+       movl r14=PAGE_SIZE/8 - 1;;
+       mov ar.lc=r14;;
+1:
+       ld8 r14=[r18], 8;;
+       st8 [r17]=r14;;
+       fc.i r17
+       add r17=8, r17
+       br.ctop.sptk.few 1b
+       br.sptk.few .loop
+       ;;
+
+.end_loop:
+       sync.i                  // for fc.i
+       ;;
+       srlz.i
+       ;;
+       srlz.d
+       ;;
+       br.call.sptk.many b0=b6;;
+
+.align  32
+memory_stack:
+       .fill           8192, 1, 0
+memory_stack_end:
+register_stack:
+       .fill           8192, 1, 0
+register_stack_end:
+relocate_new_kernel_end:
+END(relocate_new_kernel)
+
+.global relocate_new_kernel_size
+relocate_new_kernel_size:
+       data8   relocate_new_kernel_end - relocate_new_kernel
+
+GLOBAL_ENTRY(ia64_dump_cpu_regs)
+        .prologue
+        alloc loc0=ar.pfs,1,2,0,0
+        .body
+        mov     ar.rsc=0                // put RSE in enforced lazy mode
+        add     loc1=4*8, in0           // save r4 and r5 first
+        ;;
+{
+        flushrs                         // flush dirty regs to backing store
+        srlz.i
+}
+        st8 [loc1]=r4, 8
+        ;;
+        st8 [loc1]=r5, 8
+        ;;
+        add loc1=32*8, in0
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r0, 8                        // r0
+        st8 [loc1]=r4, 8               // rnat
+        mov r5=pr
+        ;;
+        st8 [in0]=r1, 8                        // r1
+        st8 [loc1]=r5, 8               // pr
+        mov r4=b0
+        ;;
+        st8 [in0]=r2, 8                        // r2
+        st8 [loc1]=r4, 8               // b0
+        mov r5=b1;
+        ;;
+        st8 [in0]=r3, 24               // r3
+        st8 [loc1]=r5, 8               // b1
+        mov r4=b2
+        ;;
+        st8 [in0]=r6, 8                        // r6
+        st8 [loc1]=r4, 8               // b2
+       mov r5=b3
+        ;;
+        st8 [in0]=r7, 8                        // r7
+        st8 [loc1]=r5, 8               // b3
+        mov r4=b4
+        ;;
+        st8 [in0]=r8, 8                        // r8
+        st8 [loc1]=r4, 8               // b4
+        mov r5=b5
+        ;;
+        st8 [in0]=r9, 8                        // r9
+        st8 [loc1]=r5, 8               // b5
+        mov r4=b6
+        ;;
+        st8 [in0]=r10, 8               // r10
+        st8 [loc1]=r5, 8               // b6
+        mov r5=b7
+        ;;
+        st8 [in0]=r11, 8               // r11
+        st8 [loc1]=r5, 8               // b7
+        mov r4=b0
+        ;;
+        st8 [in0]=r12, 8               // r12
+        st8 [loc1]=r4, 8               // ip
+        mov r5=loc0
+       ;;
+        st8 [in0]=r13, 8               // r13
+        extr.u r5=r5, 0, 38            // ar.pfs.pfm
+       mov r4=r0                       // user mask
+        ;;
+        st8 [in0]=r14, 8               // r14
+        st8 [loc1]=r5, 8               // cfm
+        ;;
+        st8 [in0]=r15, 8               // r15
+        st8 [loc1]=r4, 8               // user mask
+       mov r5=ar.rsc
+        ;;
+        st8 [in0]=r16, 8               // r16
+        st8 [loc1]=r5, 8               // ar.rsc
+        mov r4=ar.bsp
+        ;;
+        st8 [in0]=r17, 8               // r17
+        st8 [loc1]=r4, 8               // ar.bsp
+        mov r5=ar.bspstore
+        ;;
+        st8 [in0]=r18, 8               // r18
+        st8 [loc1]=r5, 8               // ar.bspstore
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r19, 8               // r19
+        st8 [loc1]=r4, 8               // ar.rnat
+        mov r5=ar.ccv
+        ;;
+        st8 [in0]=r20, 8               // r20
+       st8 [loc1]=r5, 8                // ar.ccv
+        mov r4=ar.unat
+        ;;
+        st8 [in0]=r21, 8               // r21
+        st8 [loc1]=r4, 8               // ar.unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r22, 8               // r22
+        st8 [loc1]=r5, 8               // ar.fpsr
+        mov r4 = ar.unat
+        ;;
+        st8 [in0]=r23, 8               // r23
+        st8 [loc1]=r4, 8               // unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r24, 8               // r24
+        st8 [loc1]=r5, 8               // fpsr
+        mov r4 = ar.pfs
+        ;;
+        st8 [in0]=r25, 8               // r25
+        st8 [loc1]=r4, 8               // ar.pfs
+        mov r5 = ar.lc
+        ;;
+        st8 [in0]=r26, 8               // r26
+        st8 [loc1]=r5, 8               // ar.lc
+        mov r4 = ar.ec
+        ;;
+        st8 [in0]=r27, 8               // r27
+        st8 [loc1]=r4, 8               // ar.ec
+        mov r5 = ar.csd
+        ;;
+        st8 [in0]=r28, 8               // r28
+        st8 [loc1]=r5, 8               // ar.csd
+        mov r4 = ar.ssd
+        ;;
+        st8 [in0]=r29, 8               // r29
+        st8 [loc1]=r4, 8               // ar.ssd
+        ;;
+        st8 [in0]=r30, 8               // r30
+        ;;
+       st8 [in0]=r31, 8                // r31
+        mov ar.pfs=loc0
+        ;;
+        br.ret.sptk.many rp
+END(ia64_dump_cpu_regs)
+
+
index e63b8ca..e375a2f 100644 (file)
@@ -302,7 +302,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
 static ssize_t
 salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
        struct salinfo_data *data = entry->data;
        char cmd[32];
@@ -464,7 +464,7 @@ retry:
 static ssize_t
 salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
        struct salinfo_data *data = entry->data;
        u8 *buf;
@@ -525,7 +525,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
 static ssize_t
 salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry *entry = PDE(inode);
        struct salinfo_data *data = entry->data;
        char cmd[32];
@@ -575,7 +575,6 @@ static struct file_operations salinfo_data_fops = {
        .write   = salinfo_log_write,
 };
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int __devinit
 salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 {
@@ -620,7 +619,6 @@ static struct notifier_block salinfo_cpu_notifier =
        .notifier_call = salinfo_cpu_callback,
        .priority = 0,
 };
-#endif /* CONFIG_HOTPLUG_CPU */
 
 static int __init
 salinfo_init(void)
index d10404a..14e1200 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/initrd.h>
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
 
 #include <asm/ia32.h>
 #include <asm/machvec.h>
@@ -252,6 +254,41 @@ reserve_memory (void)
        efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
        n++;
 
+#ifdef CONFIG_KEXEC
+       /* crashkernel=size@offset specifies the size to reserve for a crash
+        * kernel.(offset is ingored for keep compatibility with other archs)
+        * 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.
+        */
+       {
+               char *from = strstr(saved_command_line, "crashkernel=");
+               unsigned long base, size;
+               if (from) {
+                       size = memparse(from + 12, &from);
+                       if (size) {
+                               sort_regions(rsvd_region, n);
+                               base = kdump_find_rsvd_region(size,
+                               rsvd_region, n);
+                               if (base != ~0UL) {
+                                       rsvd_region[n].start =
+                                               (unsigned long)__va(base);
+                                       rsvd_region[n].end =
+                                               (unsigned long)__va(base + size);
+                                       n++;
+                                       crashk_res.start = base;
+                                       crashk_res.end = base + size - 1;
+                               }
+                       }
+               }
+               efi_memmap_res.start = ia64_boot_param->efi_memmap;
+                efi_memmap_res.end = efi_memmap_res.start +
+                        ia64_boot_param->efi_memmap_size;
+                boot_param_res.start = __pa(ia64_boot_param);
+                boot_param_res.end = boot_param_res.start +
+                        sizeof(*ia64_boot_param);
+       }
+#endif
        /* end of memory marker */
        rsvd_region[n].start = ~0UL;
        rsvd_region[n].end   = ~0UL;
@@ -263,6 +300,7 @@ reserve_memory (void)
        sort_regions(rsvd_region, num_rsvd_regions);
 }
 
+
 /**
  * find_initrd - get initrd parameters from the boot parameter structure
  *
index 6ab95ce..b1b9aa4 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/efi.h>
 #include <linux/bitops.h>
+#include <linux/kexec.h>
 
 #include <asm/atomic.h>
 #include <asm/current.h>
@@ -66,6 +67,7 @@ static volatile struct call_data_struct *call_data;
 
 #define IPI_CALL_FUNC          0
 #define IPI_CPU_STOP           1
+#define IPI_KDUMP_CPU_STOP     3
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
 static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
@@ -155,7 +157,11 @@ handle_IPI (int irq, void *dev_id)
                              case IPI_CPU_STOP:
                                stop_this_cpu();
                                break;
-
+#ifdef CONFIG_CRASH_DUMP
+                             case IPI_KDUMP_CPU_STOP:
+                               unw_init_running(kdump_cpu_freeze, NULL);
+                               break;
+#endif
                              default:
                                printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
                                break;
@@ -213,6 +219,26 @@ send_IPI_self (int op)
        send_IPI_single(smp_processor_id(), op);
 }
 
+#ifdef CONFIG_CRASH_DUMP
+void
+kdump_smp_send_stop()
+{
+       send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
+}
+
+void
+kdump_smp_send_init()
+{
+       unsigned int cpu, self_cpu;
+       self_cpu = smp_processor_id();
+       for_each_online_cpu(cpu) {
+               if (cpu != self_cpu) {
+                       if(kdump_status[cpu] == 0)
+                               platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
+               }
+       }
+}
+#endif
 /*
  * Called with preeemption disabled.
  */
index f7d7f56..b21ddec 100644 (file)
@@ -463,15 +463,17 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 }
 
 struct create_idle {
+       struct work_struct work;
        struct task_struct *idle;
        struct completion done;
        int cpu;
 };
 
 void
-do_fork_idle(void *_c_idle)
+do_fork_idle(struct work_struct *work)
 {
-       struct create_idle *c_idle = _c_idle;
+       struct create_idle *c_idle =
+               container_of(work, struct create_idle, work);
 
        c_idle->idle = fork_idle(c_idle->cpu);
        complete(&c_idle->done);
@@ -482,10 +484,10 @@ do_boot_cpu (int sapicid, int cpu)
 {
        int timeout;
        struct create_idle c_idle = {
+               .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle),
                .cpu    = cpu,
                .done   = COMPLETION_INITIALIZER(c_idle.done),
        };
-       DECLARE_WORK(work, do_fork_idle, &c_idle);
 
        c_idle.idle = get_idle_for_cpu(cpu);
        if (c_idle.idle) {
@@ -497,9 +499,9 @@ do_boot_cpu (int sapicid, int cpu)
         * We can't use kernel_thread since we must avoid to reschedule the child.
         */
        if (!keventd_up() || current_is_keventd())
-               work.func(work.data);
+               c_idle.work.func(&c_idle.work);
        else {
-               schedule_work(&work);
+               schedule_work(&c_idle.work);
                wait_for_completion(&c_idle.done);
        }
 
index 5629b45..687500d 100644 (file)
@@ -31,11 +31,11 @@ int arch_register_cpu(int num)
 {
 #if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
        /*
-        * If CPEI cannot be re-targetted, and this is
-        * CPEI target, then dont create the control file
+        * If CPEI can be re-targetted or if this is not
+        * CPEI target, then it is hotpluggable
         */
-       if (!can_cpei_retarget() && is_cpu_cpei_target(num))
-               sysfs_cpus[num].cpu.no_control = 1;
+       if (can_cpei_retarget() || !is_cpu_cpei_target(num))
+               sysfs_cpus[num].cpu.hotpluggable = 1;
        map_cpu_to_node(num, node_cpuid[num].nid);
 #endif
 
index 19674ca..1f86aeb 100644 (file)
@@ -8,8 +8,8 @@
  *      in0: address of buffer to checksum (char *)
  *      in1: length of the buffer (int)
  *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
+ * Copyright (C) 2002, 2006 Intel Corp.
+ * Copyright (C) 2002, 2006 Ken Chen <kenneth.w.chen@intel.com>
  */
 
 #include <asm/asmmacro.h>
@@ -25,6 +25,9 @@
 
 #define in0    r32
 #define in1    r33
+#define in2    r34
+#define in3    r35
+#define in4    r36
 #define ret0   r8
 
 GLOBAL_ENTRY(ip_fast_csum)
@@ -65,8 +68,9 @@ GLOBAL_ENTRY(ip_fast_csum)
        zxt2    r20=r20
        ;;
        add     r20=ret0,r20
+       mov     r9=0xffff
        ;;
-       andcm   ret0=-1,r20
+       andcm   ret0=r9,r20
        .restore sp             // reset frame state
        br.ret.sptk.many b0
        ;;
@@ -88,3 +92,51 @@ GLOBAL_ENTRY(ip_fast_csum)
        mov     b0=r34
        br.ret.sptk.many b0
 END(ip_fast_csum)
+
+GLOBAL_ENTRY(csum_ipv6_magic)
+       ld4     r20=[in0],4
+       ld4     r21=[in1],4
+       dep     r15=in3,in2,32,16
+       ;;
+       ld4     r22=[in0],4
+       ld4     r23=[in1],4
+       mux1    r15=r15,@rev
+       ;;
+       ld4     r24=[in0],4
+       ld4     r25=[in1],4
+       shr.u   r15=r15,16
+       add     r16=r20,r21
+       add     r17=r22,r23
+       ;;
+       ld4     r26=[in0],4
+       ld4     r27=[in1],4
+       add     r18=r24,r25
+       add     r8=r16,r17
+       ;;
+       add     r19=r26,r27
+       add     r8=r8,r18
+       ;;
+       add     r8=r8,r19
+       add     r15=r15,in4
+       ;;
+       add     r8=r8,r15
+       ;;
+       shr.u   r10=r8,32       // now fold sum into short
+       zxt4    r11=r8
+       ;;
+       add     r8=r10,r11
+       ;;
+       shr.u   r10=r8,16       // yeah, keep it rolling
+       zxt2    r11=r8
+       ;;
+       add     r8=r10,r11
+       ;;
+       shr.u   r10=r8,16       // three times lucky
+       zxt2    r11=r8
+       ;;
+       add     r8=r10,r11
+       mov     r9=0xffff
+       ;;
+       andcm   r8=r9,r8
+       br.ret.sptk.many b0
+END(csum_ipv6_magic)
index f3a9585..0c7e94e 100644 (file)
@@ -64,6 +64,11 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       return 0;
+}
+
 #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
 
 /*
index ff87a5c..56dc202 100644 (file)
@@ -156,7 +156,7 @@ ia64_init_addr_space (void)
         * the problem.  When the process attempts to write to the register backing store
         * for the first time, it will get a SEGFAULT in this case.
         */
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (vma) {
                memset(vma, 0, sizeof(*vma));
                vma->vm_mm = current->mm;
@@ -175,7 +175,7 @@ ia64_init_addr_space (void)
 
        /* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
        if (!(current->personality & MMAP_PAGE_ZERO)) {
-               vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+               vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
                if (vma) {
                        memset(vma, 0, sizeof(*vma));
                        vma->vm_mm = current->mm;
index f4edfbf..474d179 100644 (file)
@@ -125,11 +125,10 @@ alloc_pci_controller (int seg)
 {
        struct pci_controller *controller;
 
-       controller = kmalloc(sizeof(*controller), GFP_KERNEL);
+       controller = kzalloc(sizeof(*controller), GFP_KERNEL);
        if (!controller)
                return NULL;
 
-       memset(controller, 0, sizeof(*controller));
        controller->segment = seg;
        controller->node = -1;
        return controller;
@@ -564,8 +563,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
 void
 pcibios_disable_device (struct pci_dev *dev)
 {
-       if (dev->is_enabled)
-               acpi_pci_irq_disable(dev);
+       BUG_ON(atomic_read(&dev->enable_cnt));
+       acpi_pci_irq_disable(dev);
 }
 
 void
index 0b49459..8c5bee0 100644 (file)
@@ -117,7 +117,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
                                       nasid_t nasid, int slice)
 {
        int vector;
+       int cpuid;
+#ifdef CONFIG_SMP
        int cpuphys;
+#endif
        int64_t bridge;
        int local_widget, status;
        nasid_t local_nasid;
@@ -146,7 +149,6 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
        vector = sn_irq_info->irq_irq;
        /* Free the old PROM new_irq_info structure */
        sn_intr_free(local_nasid, local_widget, new_irq_info);
-       /* Update kernels new_irq_info with new target info */
        unregister_intr_pda(new_irq_info);
 
        /* allocate a new PROM new_irq_info struct */
@@ -160,8 +162,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
                return NULL;
        }
 
-       cpuphys = nasid_slice_to_cpuid(nasid, slice);
-       new_irq_info->irq_cpuid = cpuphys;
+       /* Update kernels new_irq_info with new target info */
+       cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
+                                    new_irq_info->irq_slice);
+       new_irq_info->irq_cpuid = cpuid;
        register_intr_pda(new_irq_info);
 
        pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
@@ -180,6 +184,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
        call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
 
 #ifdef CONFIG_SMP
+       cpuphys = cpu_physical_id(cpuid);
        set_irq_affinity_info((vector & 0xff), cpuphys, 0);
 #endif
 
@@ -299,6 +304,9 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
        nasid_t nasid = sn_irq_info->irq_nasid;
        int slice = sn_irq_info->irq_slice;
        int cpu = nasid_slice_to_cpuid(nasid, slice);
+#ifdef CONFIG_SMP
+       int cpuphys;
+#endif
 
        pci_dev_get(pci_dev);
        sn_irq_info->irq_cpuid = cpu;
@@ -311,6 +319,10 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
        spin_unlock(&sn_irq_info_lock);
 
        register_intr_pda(sn_irq_info);
+#ifdef CONFIG_SMP
+       cpuphys = cpu_physical_id(cpu);
+       set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
+#endif
 }
 
 void sn_irq_unfixup(struct pci_dev *pci_dev)
index 6ffd1f8..b3a435f 100644 (file)
@@ -136,10 +136,6 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
         */
        msg.data = 0x100 + irq;
 
-#ifdef CONFIG_SMP
-       set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
-#endif
-
        write_msi_msg(irq, &msg);
        set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
index 1d009f9..a934ad0 100644 (file)
@@ -769,5 +769,13 @@ int sn_prom_feature_available(int id)
                return 0;
        return test_bit(id, sn_prom_features);
 }
+
+void
+sn_kernel_launch_event(void)
+{
+       /* ignore status until we understand possible failure, if any*/
+       if (ia64_sn_kernel_launch_event())
+               printk(KERN_ERR "KEXEC is not supported in this PROM, Please update the PROM.\n");
+}
 EXPORT_SYMBOL(sn_prom_feature_available);
 
index 41fd490..f383dab 100644 (file)
@@ -214,6 +214,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default n
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index bce8af5..ee3c8be 100644 (file)
@@ -2,6 +2,7 @@
  * arch/m32r/boot/compressed/m32r_sio.c
  *
  * 2003-02-12: Takeo Takahashi
+ * 2006-11-30: OPSPUT support by Kazuhiro Inaoka
  *
  */
 
@@ -16,7 +17,7 @@ static int puts(const char *s)
        return 0;
 }
 
-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT)
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
 #include <asm/m32r.h>
 #include <asm/io.h>
 
@@ -31,7 +32,11 @@ static int puts(const char *s)
 #define BOOT_SIO0TXB   (volatile unsigned short *)(0x02c00000 + 0x2000c)
 #else
 #undef PLD_BASE
+#if defined(CONFIG_PLAT_OPSPUT)
+#define PLD_BASE       0x1cc00000
+#else
 #define PLD_BASE       0xa4c00000
+#endif
 #define BOOT_SIO0STS   PLD_ESIO0STS
 #define BOOT_SIO0TXB   PLD_ESIO0TXB
 #endif
index ac6d840..a2c472c 100644 (file)
  *     updated in fork.c:copy_thread, signal.c:do_signal,
  *     ptrace.c and ptrace.h
  *
- * M32Rx/M32R2                         M32R
- *       @(sp)      - r4               ditto
- *       @(0x04,sp) - r5               ditto
- *       @(0x08,sp) - r6               ditto
- *       @(0x0c,sp) - *pt_regs         ditto
- *       @(0x10,sp) - r0               ditto
- *       @(0x14,sp) - r1               ditto
- *       @(0x18,sp) - r2               ditto
- *       @(0x1c,sp) - r3               ditto
- *       @(0x20,sp) - r7               ditto
- *       @(0x24,sp) - r8               ditto
- *       @(0x28,sp) - r9               ditto
- *       @(0x2c,sp) - r10              ditto
- *       @(0x30,sp) - r11              ditto
- *       @(0x34,sp) - r12              ditto
- *       @(0x38,sp) - syscall_nr       ditto
- *       @(0x3c,sp) - acc0h            @(0x3c,sp) - acch
- *       @(0x40,sp) - acc0l            @(0x40,sp) - accl
- *       @(0x44,sp) - acc1h            @(0x44,sp) - dummy_acc1h
- *       @(0x48,sp) - acc1l            @(0x48,sp) - dummy_acc1l
- *       @(0x4c,sp) - psw              ditto
- *       @(0x50,sp) - bpc              ditto
- *       @(0x54,sp) - bbpsw            ditto
- *       @(0x58,sp) - bbpc             ditto
- *       @(0x5c,sp) - spu (cr3)                ditto
- *       @(0x60,sp) - fp (r13)         ditto
- *       @(0x64,sp) - lr (r14)         ditto
- *       @(0x68,sp) - spi (cr2)                ditto
- *       @(0x6c,sp) - orig_r0          ditto
+ * M32R/M32Rx/M32R2
+ *       @(sp)      - r4
+ *       @(0x04,sp) - r5
+ *       @(0x08,sp) - r6
+ *       @(0x0c,sp) - *pt_regs
+ *       @(0x10,sp) - r0
+ *       @(0x14,sp) - r1
+ *       @(0x18,sp) - r2
+ *       @(0x1c,sp) - r3
+ *       @(0x20,sp) - r7
+ *       @(0x24,sp) - r8
+ *       @(0x28,sp) - r9
+ *       @(0x2c,sp) - r10
+ *       @(0x30,sp) - r11
+ *       @(0x34,sp) - r12
+ *       @(0x38,sp) - syscall_nr
+ *       @(0x3c,sp) - acc0h
+ *       @(0x40,sp) - acc0l
+ *       @(0x44,sp) - acc1h            ; ISA_DSP_LEVEL2 only
+ *       @(0x48,sp) - acc1l            ; ISA_DSP_LEVEL2 only
+ *       @(0x4c,sp) - psw
+ *       @(0x50,sp) - bpc
+ *       @(0x54,sp) - bbpsw
+ *       @(0x58,sp) - bbpc
+ *       @(0x5c,sp) - spu (cr3)
+ *       @(0x60,sp) - fp (r13)
+ *       @(0x64,sp) - lr (r14)
+ *       @(0x68,sp) - spi (cr2)
+ *       @(0x6c,sp) - orig_r0
  */
 
 #include <linux/linkage.h>
 #define R11(reg)               @(0x30,reg)
 #define R12(reg)               @(0x34,reg)
 #define SYSCALL_NR(reg)                @(0x38,reg)
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
 #define ACC0H(reg)             @(0x3C,reg)
 #define ACC0L(reg)             @(0x40,reg)
 #define ACC1H(reg)             @(0x44,reg)
 #define ACC1L(reg)             @(0x48,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg)              @(0x3C,reg)
-#define ACCL(reg)              @(0x40,reg)
-#else
-#error unknown isa configuration
-#endif
 #define PSW(reg)               @(0x4C,reg)
 #define BPC(reg)               @(0x50,reg)
 #define BBPSW(reg)             @(0x54,reg)
@@ -603,8 +596,6 @@ ENTRY(ace_handler)
        beqz    r1, inst
 oprand:
        ld      r2, @(low(MDEVA_offset),r2)     ; set address
-       srli    r2, #12
-       slli    r2, #12
        srli    r1, #1
        bra     1f
 inst:
index da6c5f5..3cbb1f7 100644 (file)
@@ -30,14 +30,34 @@ extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
 extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
 #endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
 
-#define PORT2ADDR(port)  _port2addr(port)
-#define PORT2ADDR_USB(port) _port2addr_usb(port)
+#define PORT2ADDR(port)                _port2addr(port)
+#define PORT2ADDR_USB(port)    _port2addr_usb(port)
 
 static inline void *_port2addr(unsigned long port)
 {
        return (void *)(port | NONCACHE_OFFSET);
 }
 
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static inline void *__port2addr_ata(unsigned long port)
+{
+       static int      dummy_reg;
+
+       switch (port) {
+       case 0x1f0:     return (void *)(0x0c002000 | NONCACHE_OFFSET);
+       case 0x1f1:     return (void *)(0x0c012800 | NONCACHE_OFFSET);
+       case 0x1f2:     return (void *)(0x0c012002 | NONCACHE_OFFSET);
+       case 0x1f3:     return (void *)(0x0c012802 | NONCACHE_OFFSET);
+       case 0x1f4:     return (void *)(0x0c012004 | NONCACHE_OFFSET);
+       case 0x1f5:     return (void *)(0x0c012804 | NONCACHE_OFFSET);
+       case 0x1f6:     return (void *)(0x0c012006 | NONCACHE_OFFSET);
+       case 0x1f7:     return (void *)(0x0c012806 | NONCACHE_OFFSET);
+       case 0x3f6:     return (void *)(0x0c01200e | NONCACHE_OFFSET);
+       default:        return (void *)&dummy_reg;
+       }
+}
+#endif
+
 /*
  * OPSPUT-LAN is located in the extended bus space
  * from 0x10000000 to 0x13ffffff on physical address.
@@ -97,6 +117,12 @@ unsigned char _inb(unsigned long port)
 {
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned char *)__port2addr_ata(port);
+       }
+#endif
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                unsigned char b;
@@ -112,6 +138,11 @@ unsigned short _inw(unsigned long port)
 {
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               return *(volatile unsigned short *)__port2addr_ata(port);
+       }
+#endif
 #if defined(CONFIG_USB)
        else if(port >= 0x340 && port < 0x3a0)
                return *(volatile unsigned short *)PORT2ADDR_USB(port);
@@ -164,6 +195,11 @@ void _outb(unsigned char b, unsigned long port)
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                _ne_outb(b, PORT2ADDR_NE(port));
        else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned char *)__port2addr_ata(port) = b;
+       } else
+#endif
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
@@ -177,6 +213,11 @@ void _outw(unsigned short w, unsigned long port)
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                _ne_outw(w, PORT2ADDR_NE(port));
        else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               *(volatile unsigned short *)__port2addr_ata(port) = w;
+       } else
+#endif
 #if defined(CONFIG_USB)
        if(port >= 0x340 && port < 0x3a0)
                *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
@@ -222,6 +263,14 @@ void _insb(unsigned int port, void *addr, unsigned long count)
 {
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                _ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               unsigned char *buf = addr;
+               unsigned char *portp = __port2addr_ata(port);
+               while (count--)
+                       *buf++ = *(volatile unsigned char *)portp;
+       }
+#endif
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
@@ -253,6 +302,12 @@ void _insw(unsigned int port, void *addr, unsigned long count)
        } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
                                count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while (count--)
+                       *buf++ = *(volatile unsigned short *)portp;
 #endif
        } else {
                portp = PORT2ADDR(port);
@@ -280,6 +335,12 @@ void _outsb(unsigned int port, const void *addr, unsigned long count)
                portp = PORT2ADDR_NE(port);
                while (count--)
                        _ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while (count--)
+                       *(volatile unsigned char *)portp = *buf++;
+#endif
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
@@ -305,6 +366,12 @@ void _outsw(unsigned int port, const void *addr, unsigned long count)
                portp = PORT2ADDR_NE(port);
                while (count--)
                        *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+       } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+               portp = __port2addr_ata(port);
+               while (count--)
+                       *(volatile unsigned short *)portp = *buf++;
+#endif
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
index 0e7778b..936205f 100644 (file)
@@ -196,9 +196,7 @@ static unsigned long __init setup_memory(void)
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
                        reserve_bootmem(INITRD_START, INITRD_SIZE);
-                       initrd_start = INITRD_START ?
-                               INITRD_START + PAGE_OFFSET : 0;
-
+                       initrd_start = INITRD_START + PAGE_OFFSET;
                        initrd_end = initrd_start + INITRD_SIZE;
                        printk("initrd:start[%08lx],size[%08lx]\n",
                                initrd_start, INITRD_SIZE);
index 61d3b01..62d6b71 100644 (file)
@@ -218,13 +218,13 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq)
 
 static struct hw_interrupt_type opsput_lanpld_irq_type =
 {
-       "OPSPUT-PLD-LAN-IRQ",
-       startup_opsput_lanpld_irq,
-       shutdown_opsput_lanpld_irq,
-       enable_opsput_lanpld_irq,
-       disable_opsput_lanpld_irq,
-       mask_and_ack_opsput_lanpld,
-       end_opsput_lanpld_irq
+       .typename = "OPSPUT-PLD-LAN-IRQ",
+       .startup = startup_opsput_lanpld_irq,
+       .shutdown = shutdown_opsput_lanpld_irq,
+       .enable = enable_opsput_lanpld_irq,
+       .disable = disable_opsput_lanpld_irq,
+       .ack = mask_and_ack_opsput_lanpld,
+       .end = end_opsput_lanpld_irq
 };
 
 /*
@@ -374,7 +374,6 @@ void __init init_IRQ(void)
        disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
-#if defined(CONFIG_M32R_CFC)
        /* INT#1: CFC IREQ on PLD */
        irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
        irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type;
@@ -398,8 +397,6 @@ void __init init_IRQ(void)
        irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
        pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;    /* 'H' edge sense */
        disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
-#endif /* CONFIG_M32R_CFC */
-
 
        /*
         * INT0# is used for LAN, DIO
index b60cea4..092ea86 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/personality.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
index abb34cc..c7efdb0 100644 (file)
@@ -105,9 +105,7 @@ unsigned long __init setup_memory(void)
                if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) {
                        reserve_bootmem_node(NODE_DATA(0), INITRD_START,
                                INITRD_SIZE);
-                       initrd_start = INITRD_START ?
-                               INITRD_START + PAGE_OFFSET : 0;
-
+                       initrd_start = INITRD_START + PAGE_OFFSET;
                        initrd_end = initrd_start + INITRD_SIZE;
                        printk("initrd:start[%08lx],size[%08lx]\n",
                                initrd_start, INITRD_SIZE);
index 8d5f551..9b9feb0 100644 (file)
@@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
                goto good_area;
        if (!(vma->vm_flags & VM_GROWSDOWN))
                goto bad_area;
-#if 0
+
        if (error_code & ACE_USERMODE) {
                /*
                 * accessing the stack below "spu" is always a bug.
@@ -184,7 +184,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
                if (address + 4 < regs->spu)
                        goto bad_area;
        }
-#endif
+
        if (expand_stack(vma, address))
                goto bad_area;
 /*
index 7bc1446..70a577c 100644 (file)
@@ -17,6 +17,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_HWEIGHT
        bool
        default y
index de1304c..fa015d8 100644 (file)
@@ -52,10 +52,9 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
 #ifdef DEBUG
     printk("amiga_chip_alloc: allocate %ld bytes\n", size);
 #endif
-    res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+    res = kzalloc(sizeof(struct resource), GFP_KERNEL);
     if (!res)
        return NULL;
-    memset(res, 0, sizeof(struct resource));
     res->name = name;
 
     if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
index 6ca57b6..bee2b14 100644 (file)
@@ -375,10 +375,9 @@ struct pci_bus_info * __init init_hades_pci(void)
         * Allocate memory for bus info structure.
         */
 
-       bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
+       bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
        if (!bus)
                return NULL;
-       memset(bus, 0, sizeof(struct pci_bus_info));
 
        /*
         * Claim resources. The m68k has no separate I/O space, both
index d64b580..d01deb4 100644 (file)
@@ -174,7 +174,7 @@ int stdma_islocked(void)
 void __init stdma_init(void)
 {
        stdma_isr = NULL;
-       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
+       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | SA_SHIRQ,
                    "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
 }
 
index bffd69a..4b5f050 100644 (file)
@@ -67,16 +67,6 @@ ENTRY(_start)
 1:     lea     init_task,%curptr                       | get initial thread...
        lea     init_thread_union+THREAD_SIZE,%sp       | ...and its stack.
 
-/* copy bootinfo records from the loader to _end */
-       lea     _end, %a1
-       lea     BI_START, %a0
-       /* number of longs to copy */
-       movel   %a0@, %d0
-1:     addl    #4, %a0
-       movel   %a0@, %a1@
-       addl    #4, %a1
-       dbf     %d0, 1b
-
 /* Point MSP at an invalid page to trap if it's used. --m */
        movl    #(PAGESIZE),%d0
        movc    %d0,%msp
index 2550b4a..8c7eccb 100644 (file)
@@ -8,7 +8,7 @@ ENTRY(_start)
 jiffies = jiffies_64 + 4;
 SECTIONS
 {
-  . = 0xE004000;
+  . = 0xE002000;
   _text = .;                   /* Text and read-only data */
   .text : {
        *(.head)
index 911f2ce..2adbeb1 100644 (file)
@@ -99,7 +99,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        down_read(&mm->mmap_sem);
index 0f88812..13c0b4a 100644 (file)
@@ -299,7 +299,7 @@ void cache_clear (unsigned long paddr, int len)
        mach_l2_flush(0);
 #endif
 }
-EXPORT_SYMBOL(cache_clear);    /* probably can be unexported */
+EXPORT_SYMBOL(cache_clear);
 
 
 /*
@@ -352,7 +352,7 @@ void cache_push (unsigned long paddr, int len)
        mach_l2_flush(1);
 #endif
 }
-EXPORT_SYMBOL(cache_push);     /* probably can be unexported */
+EXPORT_SYMBOL(cache_push);
 
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
 int mm_end_of_chunk (unsigned long addr, int len)
index ac6640a..6a6513a 100644 (file)
@@ -49,7 +49,6 @@ void __init paging_init(void)
        unsigned long zones_size[MAX_NR_ZONES] = { 0, };
        unsigned long size;
 
-
 #ifdef TEST_VERIFY_AREA
        wp_works_ok = 0;
 #endif
@@ -94,7 +93,11 @@ void __init paging_init(void)
        /* memory sizing is a hack stolen from motorola.c..  hope it works for us */
        zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
 
-       free_area_init(zones_size);
+       /* I really wish I knew why the following change made things better...  -- Sam */
+/*     free_area_init(zones_size); */
+       free_area_init_node(0, NODE_DATA(0), zones_size,
+                           (__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL);
+
 
 }
 
index aa70dde..25993c2 100644 (file)
@@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default n
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index 58afa8b..2b2a10d 100644 (file)
@@ -60,6 +60,7 @@ SECTIONS {
 #endif
 
        .text : {
+               _text = .;
                _stext = . ;
                *(.text)
                SCHED_TEXT
index 24781f0..e5668af 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *     timers.c -- generic ColdFire hardware timer support.
  *
- *     Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ *     Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com)
  */
 
 /***************************************************************************/
@@ -44,6 +44,14 @@ unsigned int mcf_timerlevel = 5;
 extern void mcf_settimericr(int timer, int level);
 extern int mcf_timerirqpending(int timer);
 
+#if defined(CONFIG_M532x)
+#define        __raw_readtrr   __raw_readl
+#define        __raw_writetrr  __raw_writel
+#else
+#define        __raw_readtrr   __raw_readw
+#define        __raw_writetrr  __raw_writew
+#endif
+
 /***************************************************************************/
 
 void coldfire_tick(void)
@@ -57,7 +65,7 @@ void coldfire_tick(void)
 void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
        __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
-       __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+       __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
        __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
                MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
 
@@ -76,7 +84,7 @@ unsigned long coldfire_timer_offset(void)
        unsigned long trr, tcn, offset;
 
        tcn = __raw_readw(TA(MCFTIMER_TCN));
-       trr = __raw_readw(TA(MCFTIMER_TRR));
+       trr = __raw_readtrr(TA(MCFTIMER_TRR));
        offset = (tcn * (1000000 / HZ)) / trr;
 
        /* Check if we just wrapped the counters and maybe missed a tick */
@@ -120,7 +128,7 @@ void coldfire_profile_init(void)
        /* Set up TIMER 2 as high speed profile clock */
        __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
 
-       __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
+       __raw_writetrr(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
        __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
                MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
 
index c5482e3..1b36f62 100644 (file)
@@ -114,7 +114,7 @@ void BSP_gettod (int *yearp, int *monp, int *dayp,
 {
 }
 
-int BSP_hwclk(int op, struct hwclk_time *t)
+int BSP_hwclk(int op, struct rtc_time *t)
 {
   if (!op) {
     /* read */
index 4d64960..fd2ff06 100644 (file)
@@ -165,6 +165,7 @@ config MIPS_COBALT
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_LITTLE_ENDIAN
+       select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config MACH_DECSTATION
        bool "DECstations"
@@ -225,6 +226,7 @@ config MACH_JAZZ
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_100HZ
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
         This a family of machines based on the MIPS R4030 chipset which was
         used by several vendors to build RISC/os and Windows NT workstations.
@@ -242,6 +244,7 @@ config LASAT
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_LITTLE_ENDIAN
+       select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config MIPS_ATLAS
        bool "MIPS Atlas board"
@@ -265,6 +268,7 @@ config MIPS_ATLAS
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_MULTITHREADING if EXPERIMENTAL
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          This enables support for the MIPS Technologies Atlas evaluation
          board.
@@ -419,6 +423,7 @@ config MOMENCO_OCELOT_C
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          The Ocelot is a MIPS-based Single Board Computer (SBC) made by
          Momentum Computer <http://www.momenco.com/>.
@@ -456,6 +461,11 @@ config PNX8550_JBS
        select PNX8550
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
+config PNX8550_STB810
+       bool "Support for Philips PNX8550 based STB810 board"
+       select PNX8550
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+
 config DDB5477
        bool "NEC DDB Vrc-5477"
        select DDB5XXX_COMMON
@@ -479,6 +489,7 @@ config MACH_VR41XX
        select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+       select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config PMC_YOSEMITE
        bool "PMC-Sierra Yosemite eval board"
@@ -512,6 +523,7 @@ config QEMU
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select ARCH_SPARSEMEM_ENABLE
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          Qemu is a software emulator which among other architectures also
          can simulate a MIPS32 4Kc system.  This patch adds support for the
@@ -569,6 +581,7 @@ config SGI_IP27
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_NUMA
        select SYS_SUPPORTS_SMP
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
          workstations.  To compile a Linux kernel that runs on these, say Y
@@ -697,8 +710,8 @@ config SIBYTE_CRHONE
        select SYS_SUPPORTS_HIGHMEM
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
-config SNI_RM200_PCI
-       bool "SNI RM200 PCI"
+config SNI_RM
+       bool "SNI RM200/300/400"
        select ARC if CPU_LITTLE_ENDIAN
        select ARC32 if CPU_LITTLE_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
@@ -721,8 +734,8 @@ config SNI_RM200_PCI
        select SYS_SUPPORTS_HIGHMEM
        select SYS_SUPPORTS_LITTLE_ENDIAN
        help
-         The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
-         Nixdorf Informationssysteme (SNI), parent company of Pyramid
+         The SNI RM200/300/400 are MIPS-based machines manufactured by
+         Siemens Nixdorf Informationssysteme (SNI), parent company of Pyramid
          Technology and now in turn merged with Fujitsu.  Say Y here to
          support this machine type.
 
@@ -750,6 +763,7 @@ config TOSHIBA_RBTX4927
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select TOSHIBA_BOARDS
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          This Toshiba board is based on the TX4927 processor. Say Y here to
          support this machine type
@@ -769,6 +783,7 @@ config TOSHIBA_RBTX4938
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_BIG_ENDIAN
        select TOSHIBA_BOARDS
+       select GENERIC_HARDIRQS_NO__DO_IRQ
        help
          This Toshiba board is based on the TX4938 processor. Say Y here to
          support this machine type
@@ -815,6 +830,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
@@ -835,6 +858,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
        default y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       bool
+       default n
+
 #
 # Select some configuration options automatically based on user selections.
 #
@@ -996,6 +1023,7 @@ config SOC_PNX8550
        select HW_HAS_PCI
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_SUPPORTS_32BIT_KERNEL
+       select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config SWAP_IO_SPACE
        bool
@@ -1053,16 +1081,16 @@ config HAVE_STD_PC_SERIAL_PORT
 
 config ARC_CONSOLE
        bool "ARC console support"
-       depends on SGI_IP22 || SNI_RM200_PCI
+       depends on SGI_IP22 || SNI_RM
 
 config ARC_MEMORY
        bool
-       depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
+       depends on MACH_JAZZ || SNI_RM || SGI_IP32
        default y
 
 config ARC_PROMLIB
        bool
-       depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
+       depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP32
        default y
 
 config ARC64
index 641aa30..d1b026a 100644 (file)
@@ -463,6 +463,11 @@ libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
 #cflags-$(CONFIG_PNX8550_JBS)  += -Iinclude/asm-mips/mach-pnx8550
 load-$(CONFIG_PNX8550_JBS)     += 0xffffffff80060000
 
+# Philips PNX8550 STB810 board
+#
+libs-$(CONFIG_PNX8550_STB810)  += arch/mips/philips/pnx8550/stb810/
+load-$(CONFIG_PNX8550_STB810)  += 0xffffffff80060000
+
 # NEC EMMA2RH boards
 #
 core-$(CONFIG_EMMA2RH)          += arch/mips/emma2rh/common/
@@ -569,11 +574,11 @@ libs-$(CONFIG_SIBYTE_BIGSUR)      += arch/mips/sibyte/swarm/
 load-$(CONFIG_SIBYTE_BIGSUR)   := 0xffffffff80100000
 
 #
-# SNI RM200 PCI
+# SNI RM
 #
-core-$(CONFIG_SNI_RM200_PCI)   += arch/mips/sni/
-cflags-$(CONFIG_SNI_RM200_PCI) += -Iinclude/asm-mips/mach-rm200
-load-$(CONFIG_SNI_RM200_PCI)   += 0xffffffff80600000
+core-$(CONFIG_SNI_RM)          += arch/mips/sni/
+cflags-$(CONFIG_SNI_RM)                += -Iinclude/asm-mips/mach-rm
+load-$(CONFIG_SNI_RM)          += 0xffffffff80600000
 
 #
 # Toshiba JMR-TX3927 board
@@ -695,7 +700,7 @@ ifdef CONFIG_QEMU
 all:   vmlinux.bin
 endif
 
-ifdef CONFIG_SNI_RM200_PCI
+ifdef CONFIG_SNI_RM
 all:   vmlinux.ecoff
 endif
 
index 35931be..ac18916 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_ATLAS=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index ba3bf73..9554257 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_SIBYTE_BIGSUR=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index e535812..49590d4 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index adf1e8c..0607fc2 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_COBALT=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 4fd29ff..1a57b33 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1000=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 025b960..0055ec4 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1100=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 80c9dd9..c41823b 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1200=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 6caa90b..7d6d921 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1500=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index c6cae86..c681c91 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1550=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 72f2400..dd4bb00 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_DDB5477=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index fe1387e..8a31ce4 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_DECSTATION=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 6133c28..6fa4f91 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index a484b7d..4c9d040 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MARKEINS=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 21bfcde..d5b4973 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_EV64120=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 1a5b06c..697140c 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_BASLER_EXCITE=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 21d53e0..f9812d1 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_SGI_IP22=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index e3e94c7..96090f2 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_SGI_IP27=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index b4ab2be..61e069a 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_SGI_IP32=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 9d4d17a..8896666 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_JAGUAR_ATX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 382083e..835764d 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_MACH_JAZZ=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index d037466..50fd955 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
 # 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_SNI_RM is not set
 CONFIG_TOSHIBA_JMR3927=y
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 1db8249..05f539f 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_LASAT=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 101e803..96e9410 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_MIPS_MALTA=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
@@ -644,7 +644,85 @@ CONFIG_CONNECTOR=m
 #
 # 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 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
+# CONFIG_SSFDC 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=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+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=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
index a3cbd23..03efcfd 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_SIM=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 6570b47..e4221aa 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 440d65f..32b1afd 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_3=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index c2c7ae7..ebe75c1 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_C=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 67efe27..5a9603c 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index a10f34d..46a942c 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_G=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 9e672f6..7d3c688 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1100=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index d0c0f4a..a77805a 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1500=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 3db7427..8318d74 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1550=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 280a800..fcb8fea 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_PNX8550_JBS=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
new file mode 100644 (file)
index 0000000..f38a2c1
--- /dev/null
@@ -0,0 +1,1229 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Thu Dec  7 16:35:12 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_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_PNX8550_STB810=y
+# 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
+# CONFIG_KEXEC is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# 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 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_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_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC 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=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=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_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD 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=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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE 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_IDECD=m
+# 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 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_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=y
+# CONFIG_BLK_DEV_JMICRON 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_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# 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_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP 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_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# 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_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO 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
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_PNX8XXX is not set
+# 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_HW_RANDOM=y
+# 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
+# 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
+
+#
+# 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# 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
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD 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_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+
+#
+# USB DSL modem 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
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# 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_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY 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_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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# 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=m
+# 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=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# 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 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_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK 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_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+CONFIG_HEADERS_CHECK=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+# 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_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_DES is not set
+# 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=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_PLIST=y
index 64b9fbf..5bc3248 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_PNX8550_V2PCI=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 9b0dab8..aa61f0f 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_QEMU=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index dd02960..f9e8f41 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 CONFIG_TOSHIBA_RBTX4938=y
index d8a498d..496aa67 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
 # CONFIG_SIBYTE_LITTLESUR is not set
 # CONFIG_SIBYTE_CRHINE is not set
 # CONFIG_SIBYTE_CRHONE is not set
-CONFIG_SNI_RM200_PCI=y
+CONFIG_SNI_RM=y
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 805a4fe..e33c172 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_SIBYTE_SWARM=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 6fcb656..83fb932 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MIPS_SEAD=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index dc312f1..e9d4eae 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 85615d9..c19597f 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index f7e8194..97d94f9 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 863f6a7..553734a 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index c10267d..d3dfb70 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_WR_PPMC=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 4d3c132..b9f74d6 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_PMC_YOSEMITE=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index c8430c0..6d55e8a 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/cpu.h>
 #include <asm/irq_regs.h>
 #include <asm/processor.h>
+#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 
index 269b22b..4c7cb40 100644 (file)
@@ -67,7 +67,6 @@ static struct irq_chip ioasic_irq_type = {
        .mask = mask_ioasic_irq,
        .mask_ack = ack_ioasic_irq,
        .unmask = unmask_ioasic_irq,
-       .end = end_ioasic_irq,
 };
 
 
@@ -106,8 +105,7 @@ void __init init_ioasic_irqs(int base)
                set_irq_chip_and_handler(i, &ioasic_irq_type,
                                         handle_level_irq);
        for (; i < base + IO_IRQ_LINES; i++)
-               set_irq_chip_and_handler(i, &ioasic_dma_irq_type,
-                                        handle_level_irq);
+               set_irq_chip(i, &ioasic_dma_irq_type);
 
        ioasic_irq_base = base;
 }
index f19b461..d3b8002 100644 (file)
 #include <linux/types.h>
 
 #include <asm/inst.h>
+#include <asm/irq_regs.h>
 #include <asm/mipsregs.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
index 5a9be4c..916e46b 100644 (file)
@@ -57,19 +57,12 @@ static void ack_kn02_irq(unsigned int irq)
        iob();
 }
 
-static void end_kn02_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               unmask_kn02_irq(irq);
-}
-
 static struct irq_chip kn02_irq_type = {
        .typename = "KN02-CSR",
        .ack = ack_kn02_irq,
        .mask = mask_kn02_irq,
        .mask_ack = ack_kn02_irq,
        .unmask = unmask_kn02_irq,
-       .end = end_kn02_irq,
 };
 
 
index 21d53e0..f9812d1 100644 (file)
@@ -59,7 +59,7 @@ CONFIG_SGI_IP22=y
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
index 59b9829..8d880f0 100644 (file)
@@ -56,19 +56,12 @@ static void emma2rh_irq_disable(unsigned int irq)
        ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
 }
 
-static void emma2rh_irq_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
-}
-
 struct irq_chip emma2rh_irq_controller = {
        .typename = "emma2rh_irq",
        .ack = emma2rh_irq_disable,
        .mask = emma2rh_irq_disable,
        .mask_ack = emma2rh_irq_disable,
        .unmask = emma2rh_irq_enable,
-       .end = emma2rh_irq_end,
 };
 
 void emma2rh_irq_init(u32 irq_base)
index 3ac4e40..2116d9b 100644 (file)
@@ -48,19 +48,12 @@ static void emma2rh_sw_irq_disable(unsigned int irq)
        ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
 }
 
-static void emma2rh_sw_irq_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
-}
-
 struct irq_chip emma2rh_sw_irq_controller = {
        .typename = "emma2rh_sw_irq",
        .ack = emma2rh_sw_irq_disable,
        .mask = emma2rh_sw_irq_disable,
        .mask_ack = emma2rh_sw_irq_disable,
        .unmask = emma2rh_sw_irq_enable,
-       .end = emma2rh_sw_irq_end,
 };
 
 void emma2rh_sw_irq_init(u32 irq_base)
index 5c4f50c..f8d417b 100644 (file)
@@ -39,19 +39,12 @@ void disable_r4030_irq(unsigned int irq)
        spin_unlock_irqrestore(&r4030_lock, flags);
 }
 
-static void end_r4030_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_r4030_irq(irq);
-}
-
 static struct irq_chip r4030_irq_type = {
        .typename = "R4030",
        .ack = disable_r4030_irq,
        .mask = disable_r4030_irq,
        .mask_ack = disable_r4030_irq,
        .unmask = enable_r4030_irq,
-       .end = end_r4030_irq,
 };
 
 void __init init_r4030_ints(void)
index 4a9f1ec..9b34238 100644 (file)
@@ -90,7 +90,6 @@ struct elf_prpsinfo32
        char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
 };
 
-#define elf_addr_t     u32
 #define elf_caddr_t    u32
 #define init_elf_binfmt init_elfn32_binfmt
 
index e318137..993f7ec 100644 (file)
@@ -92,7 +92,6 @@ struct elf_prpsinfo32
        char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
 };
 
-#define elf_addr_t     u32
 #define elf_caddr_t    u32
 #define init_elf_binfmt init_elf32_binfmt
 
index a2e095a..9a7811d 100644 (file)
 EXPORT(stext)                                  # used for profiling
 EXPORT(_stext)
 
-#if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM)
+#ifdef CONFIG_MIPS_SIM
        /*
         * Give us a fighting chance of running if execution beings at the
         * kernel load address.  This is needed because this platform does
index 2526c0c..b59a676 100644 (file)
@@ -19,9 +19,6 @@
 #include <asm/i8259.h>
 #include <asm/io.h>
 
-void enable_8259A_irq(unsigned int irq);
-void disable_8259A_irq(unsigned int irq);
-
 /*
  * This is the 'legacy' 8259A Programmable Interrupt Controller,
  * present in the majority of PC/AT boxes.
@@ -31,23 +28,16 @@ void disable_8259A_irq(unsigned int irq);
  * moves to arch independent land
  */
 
+static int i8259A_auto_eoi;
 DEFINE_SPINLOCK(i8259A_lock);
-
-static void end_8259A_irq (unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
-           irq_desc[irq].action)
-               enable_8259A_irq(irq);
-}
-
+/* some platforms call this... */
 void mask_and_ack_8259A(unsigned int);
 
-static struct irq_chip i8259A_irq_type = {
-       .typename = "XT-PIC",
-       .enable = enable_8259A_irq,
-       .disable = disable_8259A_irq,
-       .ack = mask_and_ack_8259A,
-       .end = end_8259A_irq,
+static struct irq_chip i8259A_chip = {
+       .name           = "XT-PIC",
+       .mask           = disable_8259A_irq,
+       .unmask         = enable_8259A_irq,
+       .mask_ack       = mask_and_ack_8259A,
 };
 
 /*
@@ -59,8 +49,8 @@ static struct irq_chip i8259A_irq_type = {
  */
 static unsigned int cached_irq_mask = 0xffff;
 
-#define cached_21      (cached_irq_mask)
-#define cached_A1      (cached_irq_mask >> 8)
+#define cached_master_mask     (cached_irq_mask)
+#define cached_slave_mask      (cached_irq_mask >> 8)
 
 void disable_8259A_irq(unsigned int irq)
 {
@@ -70,9 +60,9 @@ void disable_8259A_irq(unsigned int irq)
        spin_lock_irqsave(&i8259A_lock, flags);
        cached_irq_mask |= mask;
        if (irq & 8)
-               outb(cached_A1,0xA1);
+               outb(cached_slave_mask, PIC_SLAVE_IMR);
        else
-               outb(cached_21,0x21);
+               outb(cached_master_mask, PIC_MASTER_IMR);
        spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
@@ -84,9 +74,9 @@ void enable_8259A_irq(unsigned int irq)
        spin_lock_irqsave(&i8259A_lock, flags);
        cached_irq_mask &= mask;
        if (irq & 8)
-               outb(cached_A1,0xA1);
+               outb(cached_slave_mask, PIC_SLAVE_IMR);
        else
-               outb(cached_21,0x21);
+               outb(cached_master_mask, PIC_MASTER_IMR);
        spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
@@ -98,9 +88,9 @@ int i8259A_irq_pending(unsigned int irq)
 
        spin_lock_irqsave(&i8259A_lock, flags);
        if (irq < 8)
-               ret = inb(0x20) & mask;
+               ret = inb(PIC_MASTER_CMD) & mask;
        else
-               ret = inb(0xA0) & (mask >> 8);
+               ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
        spin_unlock_irqrestore(&i8259A_lock, flags);
 
        return ret;
@@ -109,7 +99,7 @@ int i8259A_irq_pending(unsigned int irq)
 void make_8259A_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
-       set_irq_chip(irq, &i8259A_irq_type);
+       set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
        enable_irq(irq);
 }
 
@@ -125,14 +115,14 @@ static inline int i8259A_irq_real(unsigned int irq)
        int irqmask = 1 << irq;
 
        if (irq < 8) {
-               outb(0x0B,0x20);                /* ISR register */
-               value = inb(0x20) & irqmask;
-               outb(0x0A,0x20);                /* back to the IRR register */
+               outb(0x0B,PIC_MASTER_CMD);      /* ISR register */
+               value = inb(PIC_MASTER_CMD) & irqmask;
+               outb(0x0A,PIC_MASTER_CMD);      /* back to the IRR register */
                return value;
        }
-       outb(0x0B,0xA0);                /* ISR register */
-       value = inb(0xA0) & (irqmask >> 8);
-       outb(0x0A,0xA0);                /* back to the IRR register */
+       outb(0x0B,PIC_SLAVE_CMD);       /* ISR register */
+       value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
+       outb(0x0A,PIC_SLAVE_CMD);       /* back to the IRR register */
        return value;
 }
 
@@ -149,17 +139,19 @@ void mask_and_ack_8259A(unsigned int irq)
 
        spin_lock_irqsave(&i8259A_lock, flags);
        /*
-        * Lightweight spurious IRQ detection. We do not want to overdo
-        * spurious IRQ handling - it's usually a sign of hardware problems, so
-        * we only do the checks we can do without slowing down good hardware
-        * nnecesserily.
+        * Lightweight spurious IRQ detection. We do not want
+        * to overdo spurious IRQ handling - it's usually a sign
+        * of hardware problems, so we only do the checks we can
+        * do without slowing down good hardware unnecessarily.
         *
-        * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
-        * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A.
-        * Thus we can check spurious 8259A IRQs without doing the quite slow
-        * i8259A_irq_real() call for every IRQ.  This does not cover 100% of
-        * spurious interrupts, but should be enough to warn the user that
-        * there is something bad going on ...
+        * Note that IRQ7 and IRQ15 (the two spurious IRQs
+        * usually resulting from the 8259A-1|2 PICs) occur
+        * even if the IRQ is masked in the 8259A. Thus we
+        * can check spurious 8259A IRQs without doing the
+        * quite slow i8259A_irq_real() call for every IRQ.
+        * This does not cover 100% of spurious interrupts,
+        * but should be enough to warn the user that there
+        * is something bad going on ...
         */
        if (cached_irq_mask & irqmask)
                goto spurious_8259A_irq;
@@ -167,14 +159,14 @@ void mask_and_ack_8259A(unsigned int irq)
 
 handle_real_irq:
        if (irq & 8) {
-               inb(0xA1);              /* DUMMY - (do we need this?) */
-               outb(cached_A1,0xA1);
-               outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
-               outb(0x62,0x20);        /* 'Specific EOI' to master-IRQ2 */
+               inb(PIC_SLAVE_IMR);     /* DUMMY - (do we need this?) */
+               outb(cached_slave_mask, PIC_SLAVE_IMR);
+               outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
+               outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
        } else {
-               inb(0x21);              /* DUMMY - (do we need this?) */
-               outb(cached_21,0x21);
-               outb(0x60+irq,0x20);    /* 'Specific EOI' to master */
+               inb(PIC_MASTER_IMR);    /* DUMMY - (do we need this?) */
+               outb(cached_master_mask, PIC_MASTER_IMR);
+               outb(0x60+irq,PIC_MASTER_CMD);  /* 'Specific EOI to master */
        }
 #ifdef CONFIG_MIPS_MT_SMTC
         if (irq_hwmask[irq] & ST0_IM)
@@ -195,7 +187,7 @@ spurious_8259A_irq:
                goto handle_real_irq;
 
        {
-               static int spurious_irq_mask = 0;
+               static int spurious_irq_mask;
                /*
                 * At this point we can be sure the IRQ is spurious,
                 * lets ACK and report it. [once per IRQ]
@@ -216,13 +208,25 @@ spurious_8259A_irq:
 
 static int i8259A_resume(struct sys_device *dev)
 {
-       init_8259A(0);
+       init_8259A(i8259A_auto_eoi);
+       return 0;
+}
+
+static int i8259A_shutdown(struct sys_device *dev)
+{
+       /* Put the i8259A into a quiescent state that
+        * the kernel initialization code can get it
+        * out of.
+        */
+       outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
+       outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-1 */
        return 0;
 }
 
 static struct sysdev_class i8259_sysdev_class = {
        set_kset_name("i8259"),
        .resume = i8259A_resume,
+       .shutdown = i8259A_shutdown,
 };
 
 static struct sys_device device_i8259A = {
@@ -244,41 +248,41 @@ void __init 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 */
-       outb(0xff, 0xA1);       /* mask all of 8259A-2 */
+       outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
+       outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-2 */
 
        /*
         * outb_p - this has to work on a wide range of PC hardware.
         */
-       outb_p(0x11, 0x20);     /* ICW1: select 8259A-1 init */
-       outb_p(0x00, 0x21);     /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */
-       outb_p(0x04, 0x21);     /* 8259A-1 (the master) has a slave on IR2 */
-       if (auto_eoi)
-               outb_p(0x03, 0x21);     /* master does Auto EOI */
-       else
-               outb_p(0x01, 0x21);     /* master expects normal EOI */
-
-       outb_p(0x11, 0xA0);     /* ICW1: select 8259A-2 init */
-       outb_p(0x08, 0xA1);     /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */
-       outb_p(0x02, 0xA1);     /* 8259A-2 is a slave on master's IR2 */
-       outb_p(0x01, 0xA1);     /* (slave's support for AEOI in flat mode
-                                   is to be investigated) */
-
+       outb_p(0x11, PIC_MASTER_CMD);   /* ICW1: select 8259A-1 init */
+       outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR);    /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */
+       outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);   /* 8259A-1 (the master) has a slave on IR2 */
+       if (auto_eoi)   /* master does Auto EOI */
+               outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
+       else            /* master expects normal EOI */
+               outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
+
+       outb_p(0x11, PIC_SLAVE_CMD);    /* ICW1: select 8259A-2 init */
+       outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR);     /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */
+       outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR);  /* 8259A-2 is a slave on master's IR2 */
+       outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
        if (auto_eoi)
                /*
-                * in AEOI mode we just have to mask the interrupt
+                * In AEOI mode we just have to mask the interrupt
                 * when acking.
                 */
-               i8259A_irq_type.ack = disable_8259A_irq;
+               i8259A_chip.mask_ack = disable_8259A_irq;
        else
-               i8259A_irq_type.ack = mask_and_ack_8259A;
+               i8259A_chip.mask_ack = mask_and_ack_8259A;
 
        udelay(100);            /* wait for 8259A to initialize */
 
-       outb(cached_21, 0x21);  /* restore master IRQ mask */
-       outb(cached_A1, 0xA1);  /* restore slave IRQ mask */
+       outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
+       outb(cached_slave_mask, PIC_SLAVE_IMR);   /* restore slave IRQ mask */
 
        spin_unlock_irqrestore(&i8259A_lock, flags);
 }
@@ -291,11 +295,17 @@ static struct irqaction irq2 = {
 };
 
 static struct resource pic1_io_resource = {
-       .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY
+       .name = "pic1",
+       .start = PIC_MASTER_CMD,
+       .end = PIC_MASTER_IMR,
+       .flags = IORESOURCE_BUSY
 };
 
 static struct resource pic2_io_resource = {
-       .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY
+       .name = "pic2",
+       .start = PIC_SLAVE_CMD,
+       .end = PIC_SLAVE_IMR,
+       .flags = IORESOURCE_BUSY
 };
 
 /*
@@ -313,7 +323,7 @@ void __init init_i8259_irqs (void)
        init_8259A(0);
 
        for (i = 0; i < 16; i++)
-               set_irq_chip(i, &i8259A_irq_type);
+               set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
 
-       setup_irq(2, &irq2);
+       setup_irq(PIC_CASCADE_IR, &irq2);
 }
index ab12c8f..37cad5d 100644 (file)
@@ -52,10 +52,6 @@ static struct linux_binfmt irix_format = {
        irix_core_dump, PAGE_SIZE
 };
 
-#ifndef elf_addr_t
-#define elf_addr_t unsigned long
-#endif
-
 #ifdef DEBUG
 /* Debugging routines. */
 static char *get_elf_p_type(Elf32_Word p_type)
@@ -1013,7 +1009,7 @@ static int notesize(struct memelfnote *en)
        int sz;
 
        sz = sizeof(struct elf_note);
-       sz += roundup(strlen(en->name), 4);
+       sz += roundup(strlen(en->name) + 1, 4);
        sz += roundup(en->datasz, 4);
 
        return sz;
@@ -1032,7 +1028,7 @@ static int writenote(struct memelfnote *men, struct file *file)
 {
        struct elf_note en;
 
-       en.n_namesz = strlen(men->name);
+       en.n_namesz = strlen(men->name) + 1;
        en.n_descsz = men->datasz;
        en.n_type = men->type;
 
@@ -1149,7 +1145,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
        psinfo.pr_pid = prstatus.pr_pid = current->pid;
        psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
        psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current);
-       psinfo.pr_sid = prstatus.pr_sid = current->signal->session;
+       psinfo.pr_sid = prstatus.pr_sid = process_session(current);
        if (current->pid == current->tgid) {
                /*
                 * This is the record for the group leader.  Add in the
index 6cfb31c..efbd219 100644 (file)
@@ -66,15 +66,6 @@ static inline void unmask_mv64340_irq(unsigned int irq)
        }
 }
 
-/*
- * End IRQ processing
- */
-static void end_mv64340_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               unmask_mv64340_irq(irq);
-}
-
 /*
  * Interrupt handler for interrupts coming from the Marvell chip.
  * It could be built in ethernet ports etc...
@@ -106,7 +97,6 @@ struct irq_chip mv64340_irq_type = {
        .mask = mask_mv64340_irq,
        .mask_ack = mask_mv64340_irq,
        .unmask = unmask_mv64340_irq,
-       .end = end_mv64340_irq,
 };
 
 void __init mv64340_irq_init(unsigned int base)
index ddcc2a5..123324b 100644 (file)
@@ -29,19 +29,12 @@ static inline void mask_rm7k_irq(unsigned int irq)
        clear_c0_intcontrol(0x100 << (irq - irq_base));
 }
 
-static void rm7k_cpu_irq_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               unmask_rm7k_irq(irq);
-}
-
 static struct irq_chip rm7k_irq_controller = {
        .typename = "RM7000",
        .ack = mask_rm7k_irq,
        .mask = mask_rm7k_irq,
        .mask_ack = mask_rm7k_irq,
        .unmask = unmask_rm7k_irq,
-       .end = rm7k_cpu_irq_end,
 };
 
 void __init rm7k_cpu_irq_init(int base)
index ba6440c..0e6f4c5 100644 (file)
@@ -80,19 +80,12 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
        on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
 }
 
-static void rm9k_cpu_irq_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               unmask_rm9k_irq(irq);
-}
-
 static struct irq_chip rm9k_irq_controller = {
        .typename = "RM9000",
        .ack = mask_rm9k_irq,
        .mask = mask_rm9k_irq,
        .mask_ack = mask_rm9k_irq,
        .unmask = unmask_rm9k_irq,
-       .end = rm9k_cpu_irq_end,
 };
 
 static struct irq_chip rm9k_perfcounter_irq = {
@@ -103,7 +96,6 @@ static struct irq_chip rm9k_perfcounter_irq = {
        .mask = mask_rm9k_irq,
        .mask_ack = mask_rm9k_irq,
        .unmask = unmask_rm9k_irq,
-       .end = rm9k_cpu_irq_end,
 };
 
 unsigned int rm9000_perfcount_irq;
index b339798..2fe4c86 100644 (file)
@@ -117,7 +117,7 @@ int show_interrupts(struct seq_file *p, void *v)
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
 
                for (action=action->next; action; action = action->next)
index be5ac23..fcc86b9 100644 (file)
@@ -50,12 +50,6 @@ static inline void mask_mips_irq(unsigned int irq)
        irq_disable_hazard();
 }
 
-static void mips_cpu_irq_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               unmask_mips_irq(irq);
-}
-
 static struct irq_chip mips_cpu_irq_controller = {
        .typename       = "MIPS",
        .ack            = mask_mips_irq,
@@ -63,7 +57,6 @@ static struct irq_chip mips_cpu_irq_controller = {
        .mask_ack       = mask_mips_irq,
        .unmask         = unmask_mips_irq,
        .eoi            = unmask_mips_irq,
-       .end            = mips_cpu_irq_end,
 };
 
 /*
@@ -96,8 +89,6 @@ static void mips_mt_cpu_irq_ack(unsigned int irq)
        mask_mips_mt_irq(irq);
 }
 
-#define mips_mt_cpu_irq_end mips_cpu_irq_end
-
 static struct irq_chip mips_mt_cpu_irq_controller = {
        .typename       = "MIPS",
        .startup        = mips_mt_cpu_irq_startup,
@@ -106,7 +97,6 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
        .mask_ack       = mips_mt_cpu_irq_ack,
        .unmask         = unmask_mips_mt_irq,
        .eoi            = unmask_mips_mt_irq,
-       .end            = mips_mt_cpu_irq_end,
 };
 
 void __init mips_cpu_irq_init(int irq_base)
index f06a144..5929f88 100644 (file)
@@ -301,7 +301,7 @@ static void sp_cleanup(void)
        for (;;) {
                unsigned long set;
                i = j * __NFDBITS;
-               if (i >= fdt->max_fdset || i >= fdt->max_fds)
+               if (i >= fdt->max_fds)
                        break;
                set = fdt->open_fds->fds_bits[j++];
                while (set) {
@@ -319,7 +319,7 @@ static void sp_cleanup(void)
 static int channel_open = 0;
 
 /* the work handler */
-static void sp_work(void *data)
+static void sp_work(struct work_struct *unused)
 {
        if (!channel_open) {
                if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
@@ -354,7 +354,7 @@ static void startwork(int vpe)
                        return;
                }
 
-               INIT_WORK(&work, sp_work, NULL);
+               INIT_WORK(&work, sp_work);
                queue_work(workqueue, &work);
        } else
                queue_work(workqueue, &work);
index 621037d..060563a 100644 (file)
@@ -23,6 +23,8 @@ void (*_machine_restart)(char *command);
 void (*_machine_halt)(void);
 void (*pm_power_off)(void);
 
+EXPORT_SYMBOL(pm_power_off);
+
 void machine_restart(char *command)
 {
        if (_machine_restart)
index 8c8c832..5a99e3e 100644 (file)
@@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
        int minor;
        unsigned int mask = 0;
 
-       minor = iminor(file->f_dentry->d_inode);
+       minor = iminor(file->f_path.dentry->d_inode);
 
        poll_wait(file, &channel_wqs[minor].rt_queue, wait);
        poll_wait(file, &channel_wqs[minor].lx_queue, wait);
@@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
 static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
                         loff_t * ppos)
 {
-       int minor = iminor(file->f_dentry->d_inode);
+       int minor = iminor(file->f_path.dentry->d_inode);
 
        /* data available? */
        if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
@@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
        struct rtlx_channel *rt;
        DECLARE_WAITQUEUE(wait, current);
 
-       minor = iminor(file->f_dentry->d_inode);
+       minor = iminor(file->f_path.dentry->d_inode);
        rt = &rtlx->channel[minor];
 
        /* any space left... */
index 93c74fe..6c2406a 100644 (file)
@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
                goto out;
        }
 
-       error = vfs_statfs(file->f_dentry, &kbuf);
+       error = vfs_statfs(file->f_path.dentry, &kbuf);
        if (error)
                goto out_f;
 
@@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
                        unsigned long old_pos;
                        long max_size = offset + len;
 
-                       if (max_size > file->f_dentry->d_inode->i_size) {
+                       if (max_size > file->f_path.dentry->d_inode->i_size) {
                                old_pos = sys_lseek (fd, max_size - 1, 0);
                                sys_write (fd, (void __user *) "", 1);
                                sys_lseek (fd, old_pos, 0);
@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
                error = -EBADF;
                goto out;
        }
-       error = vfs_statfs(file->f_dentry, &kbuf);
+       error = vfs_statfs(file->f_path.dentry, &kbuf);
        if (error)
                goto out_f;
 
@@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
                        unsigned long old_pos;
                        long max_size = off2 + len;
 
-                       if (max_size > file->f_dentry->d_inode->i_size) {
+                       if (max_size > file->f_path.dentry->d_inode->i_size) {
                                old_pos = sys_lseek (fd, max_size - 1, 0);
                                sys_write (fd, (void __user *) "", 1);
                                sys_lseek (fd, old_pos, 0);
@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
                error = -EBADF;
                goto out;
        }
-       error = vfs_statfs(file->f_dentry, &kbuf);
+       error = vfs_statfs(file->f_path.dentry, &kbuf);
        if (error)
                goto out_f;
 
index 79f0317..cecff24 100644 (file)
@@ -112,6 +112,7 @@ SECTIONS
     /* .exit.text is discarded at runtime, not link time, to deal with
      references from .rodata */
   .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
   . = ALIGN(_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
@@ -139,7 +140,6 @@ SECTIONS
 
   /* Sections to be discarded */
   /DISCARD/ : {
-        *(.exit.data)
         *(.exitcall.exit)
 
        /* ABI crap starts here */
index 51ddd21..666bef4 100644 (file)
@@ -1179,7 +1179,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
        size_t ret = count;
        struct vpe *v;
 
-       minor = iminor(file->f_dentry->d_inode);
+       minor = iminor(file->f_path.dentry->d_inode);
        if ((v = get_vpe(minor)) == NULL)
                return -ENODEV;
 
index 4a84a7b..2affa5f 100644 (file)
@@ -44,19 +44,12 @@ void enable_lasat_irq(unsigned int irq_nr)
        *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
 }
 
-static void end_lasat_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_lasat_irq(irq);
-}
-
 static struct irq_chip lasat_irq_type = {
        .typename = "Lasat",
        .ack = disable_lasat_irq,
        .mask = disable_lasat_irq,
        .mask_ack = disable_lasat_irq,
        .unmask = enable_lasat_irq,
-       .end = end_lasat_irq,
 };
 
 static inline int ls1bit32(unsigned int x)
index 6dd7ae1..1287835 100644 (file)
@@ -40,12 +40,12 @@ static DEFINE_MUTEX(lasat_info_mutex);
 /* Strategy function to write EEPROM after changing string entry */
 int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
                void *oldval, size_t *oldlenp,
-               void *newval, size_t newlen, void **context)
+               void *newval, size_t newlen)
 {
        int r;
        mutex_lock(&lasat_info_mutex);
        r = sysctl_string(table, name,
-                         nlen, oldval, oldlenp, newval, newlen, context);
+                         nlen, oldval, oldlenp, newval, newlen);
        if (r < 0) {
                mutex_unlock(&lasat_info_mutex);
                return r;
@@ -119,11 +119,11 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
 /* Sysctl for setting the IP addresses */
 int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
                    void *oldval, size_t *oldlenp,
-                   void *newval, size_t newlen, void **context)
+                   void *newval, size_t newlen)
 {
        int r;
        mutex_lock(&lasat_info_mutex);
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
        if (r < 0) {
                mutex_unlock(&lasat_info_mutex);
                return r;
@@ -139,14 +139,14 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
 /* Same for RTC */
 int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
                    void *oldval, size_t *oldlenp,
-                   void *newval, size_t newlen, void **context)
+                   void *newval, size_t newlen)
 {
        int r;
        mutex_lock(&lasat_info_mutex);
        rtctmp = ds1603_read();
        if (rtctmp < 0)
                rtctmp = 0;
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
        if (r < 0) {
                mutex_unlock(&lasat_info_mutex);
                return r;
@@ -251,13 +251,12 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
 
 static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
                                     void *oldval, size_t *oldlenp,
-                                    void *newval, size_t newlen,
-                                    void **context)
+                                    void *newval, size_t newlen)
 {
        int r;
 
        mutex_lock(&lasat_info_mutex);
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
        if (r < 0) {
                mutex_unlock(&lasat_info_mutex);
                return r;
@@ -286,11 +285,11 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
                mutex_unlock(&lasat_info_mutex);
                return r;
        }
-       if (filp && filp->f_dentry)
+       if (filp && filp->f_path.dentry)
        {
-               if (!strcmp(filp->f_dentry->d_name.name, "prid"))
+               if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
                        lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
-               if (!strcmp(filp->f_dentry->d_name.name, "debugaccess"))
+               if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
                        lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
        }
        lasat_write_eeprom_info();
index 15611d9..9db3572 100644 (file)
 #include <asm/regdef.h>
 
 #ifdef CONFIG_64BIT
-#define T0     ta0
-#define T1     ta1
-#define T2     ta2
-#define T3     ta3
-#define T4     t0
-#define T7     t3
-#else
-#define T0     t0
-#define T1     t1
-#define T2     t2
-#define T3     t3
-#define T4     t4
-#define T7     t7
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0     $8
+#define t1     $9
+#define t2     $10
+#define t3     $11
+#define t4     $12
+#define t5     $13
+#define t6     $14
+#define t7     $15
+
+#define USE_DOUBLE
 #endif
 
+#ifdef USE_DOUBLE
+
+#define LOAD   ld
+#define ADD    daddu
+#define NBYTES 8
+
+#else
+
+#define LOAD   lw
+#define ADD    addu
+#define NBYTES 4
+
+#endif /* USE_DOUBLE */
+
+#define UNIT(unit)  ((unit)*NBYTES)
+
 #define ADDC(sum,reg)                                          \
-       addu    sum, reg;                                       \
+       ADD     sum, reg;                                       \
        sltu    v1, sum, reg;                                   \
-       addu    sum, v1
+       ADD     sum, v1
 
-#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3)    \
-       lw      _t0, (offset + 0x00)(src);                      \
-       lw      _t1, (offset + 0x04)(src);                      \
-       lw      _t2, (offset + 0x08)(src);                      \
-       lw      _t3, (offset + 0x0c)(src);                      \
-       ADDC(sum, _t0);                                         \
-       ADDC(sum, _t1);                                         \
-       ADDC(sum, _t2);                                         \
-       ADDC(sum, _t3);                                         \
-       lw      _t0, (offset + 0x10)(src);                      \
-       lw      _t1, (offset + 0x14)(src);                      \
-       lw      _t2, (offset + 0x18)(src);                      \
-       lw      _t3, (offset + 0x1c)(src);                      \
+#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)   \
+       LOAD    _t0, (offset + UNIT(0))(src);                   \
+       LOAD    _t1, (offset + UNIT(1))(src);                   \
+       LOAD    _t2, (offset + UNIT(2))(src);                   \
+       LOAD    _t3, (offset + UNIT(3))(src);                   \
        ADDC(sum, _t0);                                         \
        ADDC(sum, _t1);                                         \
        ADDC(sum, _t2);                                         \
-       ADDC(sum, _t3);                                         \
+       ADDC(sum, _t3)
+
+#ifdef USE_DOUBLE
+#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3)    \
+       CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)
+#else
+#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3)    \
+       CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3);   \
+       CSUM_BIGCHUNK1(src, offset + 0x10, sum, _t0, _t1, _t2, _t3)
+#endif
 
 /*
  * a0: source address
 
        .text
        .set    noreorder
-
-/* unknown src alignment and < 8 bytes to go  */
-small_csumcpy:
-       move    a1, T2
-
-       andi    T0, a1, 4
-       beqz    T0, 1f
-        andi   T0, a1, 2
-
-       /* Still a full word to go  */
-       ulw     T1, (src)
-       PTR_ADDIU       src, 4
-       ADDC(sum, T1)
-
-1:     move    T1, zero
-       beqz    T0, 1f
-        andi   T0, a1, 1
-
-       /* Still a halfword to go  */
-       ulhu    T1, (src)
-       PTR_ADDIU       src, 2
-
-1:     beqz    T0, 1f
-        sll    T1, T1, 16
-
-       lbu     T2, (src)
-        nop
-
-#ifdef __MIPSEB__
-       sll     T2, T2, 8
-#endif
-       or      T1, T2
-
-1:     ADDC(sum, T1)
-
-       /* fold checksum */
-       sll     v1, sum, 16
-       addu    sum, v1
-       sltu    v1, sum, v1
-       srl     sum, sum, 16
-       addu    sum, v1
-
-       /* odd buffer alignment? */
-       beqz    T7, 1f
-        nop
-       sll     v1, sum, 8
-       srl     sum, sum, 8
-       or      sum, v1
-       andi    sum, 0xffff
-1:
-       .set    reorder
-       /* Add the passed partial csum.  */
-       ADDC(sum, a2)
-       jr      ra
-       .set    noreorder
-
-/* ------------------------------------------------------------------------- */
-
        .align  5
 LEAF(csum_partial)
        move    sum, zero
-       move    T7, zero
+       move    t7, zero
 
        sltiu   t8, a1, 0x8
        bnez    t8, small_csumcpy               /* < 8 bytes to copy */
-        move   T2, a1
+        move   t2, a1
 
-       beqz    a1, out
-        andi   T7, src, 0x1                    /* odd buffer? */
+       andi    t7, src, 0x1                    /* odd buffer? */
 
 hword_align:
-       beqz    T7, word_align
+       beqz    t7, word_align
         andi   t8, src, 0x2
 
-       lbu     T0, (src)
+       lbu     t0, (src)
        LONG_SUBU       a1, a1, 0x1
 #ifdef __MIPSEL__
-       sll     T0, T0, 8
+       sll     t0, t0, 8
 #endif
-       ADDC(sum, T0)
+       ADDC(sum, t0)
        PTR_ADDU        src, src, 0x1
        andi    t8, src, 0x2
 
@@ -148,9 +112,9 @@ word_align:
        beqz    t8, dword_align
         sltiu  t8, a1, 56
 
-       lhu     T0, (src)
+       lhu     t0, (src)
        LONG_SUBU       a1, a1, 0x2
-       ADDC(sum, T0)
+       ADDC(sum, t0)
        sltiu   t8, a1, 56
        PTR_ADDU        src, src, 0x2
 
@@ -162,9 +126,9 @@ dword_align:
        beqz    t8, qword_align
         andi   t8, src, 0x8
 
-       lw      T0, 0x00(src)
+       lw      t0, 0x00(src)
        LONG_SUBU       a1, a1, 0x4
-       ADDC(sum, T0)
+       ADDC(sum, t0)
        PTR_ADDU        src, src, 0x4
        andi    t8, src, 0x8
 
@@ -172,11 +136,17 @@ qword_align:
        beqz    t8, oword_align
         andi   t8, src, 0x10
 
-       lw      T0, 0x00(src)
-       lw      T1, 0x04(src)
+#ifdef USE_DOUBLE
+       ld      t0, 0x00(src)
+       LONG_SUBU       a1, a1, 0x8
+       ADDC(sum, t0)
+#else
+       lw      t0, 0x00(src)
+       lw      t1, 0x04(src)
        LONG_SUBU       a1, a1, 0x8
-       ADDC(sum, T0)
-       ADDC(sum, T1)
+       ADDC(sum, t0)
+       ADDC(sum, t1)
+#endif
        PTR_ADDU        src, src, 0x8
        andi    t8, src, 0x10
 
@@ -184,75 +154,120 @@ oword_align:
        beqz    t8, begin_movement
         LONG_SRL       t8, a1, 0x7
 
-       lw      T3, 0x08(src)
-       lw      T4, 0x0c(src)
-       lw      T0, 0x00(src)
-       lw      T1, 0x04(src)
-       ADDC(sum, T3)
-       ADDC(sum, T4)
-       ADDC(sum, T0)
-       ADDC(sum, T1)
+#ifdef USE_DOUBLE
+       ld      t0, 0x00(src)
+       ld      t1, 0x08(src)
+       ADDC(sum, t0)
+       ADDC(sum, t1)
+#else
+       CSUM_BIGCHUNK1(src, 0x00, sum, t0, t1, t3, t4)
+#endif
        LONG_SUBU       a1, a1, 0x10
        PTR_ADDU        src, src, 0x10
        LONG_SRL        t8, a1, 0x7
 
 begin_movement:
        beqz    t8, 1f
-        andi   T2, a1, 0x40
+        andi   t2, a1, 0x40
 
 move_128bytes:
-       CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
-       CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
-       CSUM_BIGCHUNK(src, 0x40, sum, T0, T1, T3, T4)
-       CSUM_BIGCHUNK(src, 0x60, sum, T0, T1, T3, T4)
+       CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+       CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+       CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
+       CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
        LONG_SUBU       t8, t8, 0x01
        bnez    t8, move_128bytes
         PTR_ADDU       src, src, 0x80
 
 1:
-       beqz    T2, 1f
-        andi   T2, a1, 0x20
+       beqz    t2, 1f
+        andi   t2, a1, 0x20
 
 move_64bytes:
-       CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
-       CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
+       CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+       CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
        PTR_ADDU        src, src, 0x40
 
 1:
-       beqz    T2, do_end_words
+       beqz    t2, do_end_words
         andi   t8, a1, 0x1c
 
 move_32bytes:
-       CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
+       CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
        andi    t8, a1, 0x1c
        PTR_ADDU        src, src, 0x20
 
 do_end_words:
-       beqz    t8, maybe_end_cruft
-        LONG_SRL       t8, t8, 0x2
+       beqz    t8, small_csumcpy
+        andi   t2, a1, 0x3
+       LONG_SRL        t8, t8, 0x2
 
 end_words:
-       lw      T0, (src)
+       lw      t0, (src)
        LONG_SUBU       t8, t8, 0x1
-       ADDC(sum, T0)
+       ADDC(sum, t0)
        bnez    t8, end_words
         PTR_ADDU       src, src, 0x4
 
-maybe_end_cruft:
-       andi    T2, a1, 0x3
+/* unknown src alignment and < 8 bytes to go  */
+small_csumcpy:
+       move    a1, t2
 
-small_memcpy:
- j small_csumcpy; move a1, T2          /* XXX ??? */
-       beqz    t2, out
-        move   a1, T2
+       andi    t0, a1, 4
+       beqz    t0, 1f
+        andi   t0, a1, 2
 
-end_bytes:
-       lb      T0, (src)
-       LONG_SUBU       a1, a1, 0x1
-       bnez    a2, end_bytes
-        PTR_ADDU       src, src, 0x1
+       /* Still a full word to go  */
+       ulw     t1, (src)
+       PTR_ADDIU       src, 4
+       ADDC(sum, t1)
+
+1:     move    t1, zero
+       beqz    t0, 1f
+        andi   t0, a1, 1
+
+       /* Still a halfword to go  */
+       ulhu    t1, (src)
+       PTR_ADDIU       src, 2
+
+1:     beqz    t0, 1f
+        sll    t1, t1, 16
+
+       lbu     t2, (src)
+        nop
 
-out:
+#ifdef __MIPSEB__
+       sll     t2, t2, 8
+#endif
+       or      t1, t2
+
+1:     ADDC(sum, t1)
+
+       /* fold checksum */
+#ifdef USE_DOUBLE
+       dsll32  v1, sum, 0
+       daddu   sum, v1
+       sltu    v1, sum, v1
+       dsra32  sum, sum, 0
+       addu    sum, v1
+#endif
+       sll     v1, sum, 16
+       addu    sum, v1
+       sltu    v1, sum, v1
+       srl     sum, sum, 16
+       addu    sum, v1
+
+       /* odd buffer alignment? */
+       beqz    t7, 1f
+        nop
+       sll     v1, sum, 8
+       srl     sum, sum, 8
+       or      sum, v1
+       andi    sum, 0xffff
+1:
+       .set    reorder
+       /* Add the passed partial csum.  */
+       ADDC(sum, a2)
        jr      ra
-        move   v0, sum
+       .set    noreorder
        END(csum_partial)
index 1720f2c..0677104 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 1998, 1999 Ralf Baechle
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/string.h>
@@ -29,6 +30,8 @@ __wsum csum_partial_copy_nocheck(const void *src,
        return sum;
 }
 
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
 /*
  * Copy from userspace and compute checksum.  If we catch an exception
  * then zero the rest of the buffer.
index 77ee5c6..b662c75 100644 (file)
@@ -19,5 +19,5 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_mtd.o malta_setup.o
 obj-$(CONFIG_SMP) += malta_smp.o
index 282f3e5..56ea766 100644 (file)
 #include <linux/pci.h>
 #include <linux/screen_info.h>
 
-#ifdef CONFIG_MTD
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#endif
-
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
@@ -58,30 +51,6 @@ struct resource standard_io_resources[] = {
        { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY },
 };
 
-#ifdef CONFIG_MTD
-static struct mtd_partition malta_mtd_partitions[] = {
-       {
-               .name =         "YAMON",
-               .offset =       0x0,
-               .size =         0x100000,
-               .mask_flags =   MTD_WRITEABLE
-       },
-       {
-               .name =         "User FS",
-               .offset =       0x100000,
-               .size =         0x2e0000
-       },
-       {
-               .name =         "Board Config",
-               .offset =       0x3e0000,
-               .size =         0x020000,
-               .mask_flags =   MTD_WRITEABLE
-       }
-};
-
-#define number_partitions      (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition))
-#endif
-
 const char *get_system_type(void)
 {
        return "MIPS Malta";
@@ -211,14 +180,6 @@ void __init plat_mem_setup(void)
 #endif
 #endif
 
-#ifdef CONFIG_MTD
-       /*
-        * Support for MTD on Malta. Use the generic physmap driver
-        */
-       physmap_configure(0x1e000000, 0x400000, 4, NULL);
-       physmap_set_partitions(malta_mtd_partitions, number_partitions);
-#endif
-
        mips_reboot_setup();
 
        board_time_init = mips_time_init;
index caf807d..1f954a2 100644 (file)
@@ -32,6 +32,7 @@ void (*local_flush_data_cache_page)(void * addr);
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
+EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
 EXPORT_SYMBOL(flush_data_cache_page);
 
 #ifdef CONFIG_DMA_NONCOHERENT
index 7fa5fd1..5697c6e 100644 (file)
@@ -190,14 +190,14 @@ int dma_supported(struct device *dev, u64 mask)
 
 EXPORT_SYMBOL(dma_supported);
 
-int dma_is_consistent(dma_addr_t dma_addr)
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 1;
 }
 
 EXPORT_SYMBOL(dma_is_consistent);
 
-void dma_cache_sync(void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
index 8da19fd..f088344 100644 (file)
@@ -197,14 +197,14 @@ int dma_supported(struct device *dev, u64 mask)
 
 EXPORT_SYMBOL(dma_supported);
 
-int dma_is_consistent(dma_addr_t dma_addr)
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 1;
 }
 
 EXPORT_SYMBOL(dma_is_consistent);
 
-void dma_cache_sync(void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
index ec54ed0..b42b6f7 100644 (file)
@@ -363,14 +363,15 @@ int dma_supported(struct device *dev, u64 mask)
 
 EXPORT_SYMBOL(dma_supported);
 
-int dma_is_consistent(dma_addr_t dma_addr)
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 1;
 }
 
 EXPORT_SYMBOL(dma_is_consistent);
 
-void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+       enum dma_data_direction direction)
 {
        if (direction == DMA_NONE)
                return;
index 2eeffe5..8cecef0 100644 (file)
@@ -299,14 +299,15 @@ int dma_supported(struct device *dev, u64 mask)
 
 EXPORT_SYMBOL(dma_supported);
 
-int dma_is_consistent(dma_addr_t dma_addr)
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 1;
 }
 
 EXPORT_SYMBOL(dma_is_consistent);
 
-void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+       enum dma_data_direction direction)
 {
        if (direction == DMA_NONE)
                return;
index 99ebf3c..675502a 100644 (file)
@@ -39,7 +39,7 @@ void *__kmap_atomic(struct page *page, enum km_type type)
        unsigned long vaddr;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-       inc_preempt_count();
+       pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
@@ -62,8 +62,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
        if (vaddr < FIXADDR_START) { // FIXME
-               dec_preempt_count();
-               preempt_check_resched();
+               pagefault_enable();
                return;
        }
 
@@ -78,8 +77,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
        local_flush_tlb_one(vaddr);
 #endif
 
-       dec_preempt_count();
-       preempt_check_resched();
+       pagefault_enable();
 }
 
 #ifndef CONFIG_LIMITED_DMA
@@ -92,7 +90,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
        enum fixed_addresses idx;
        unsigned long vaddr;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
index 9e29ba9..ea2d153 100644 (file)
@@ -316,7 +316,7 @@ static int __init page_is_ram(unsigned long pagenr)
 void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-       unsigned long max_dma, high, low;
+       unsigned long max_dma, low;
 #ifndef CONFIG_FLATMEM
        unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
        unsigned long i, j, pfn;
@@ -331,7 +331,6 @@ void __init paging_init(void)
 
        max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
        low = max_low_pfn;
-       high = highend_pfn;
 
 #ifdef CONFIG_ISA
        if (low < max_dma)
@@ -344,13 +343,13 @@ void __init paging_init(void)
        zones_size[ZONE_DMA] = low;
 #endif
 #ifdef CONFIG_HIGHMEM
-       if (cpu_has_dc_aliases) {
-               printk(KERN_WARNING "This processor doesn't support highmem.");
-               if (high - low)
-                       printk(" %ldk highmem ignored", high - low);
-               printk("\n");
-       } else
-               zones_size[ZONE_HIGHMEM] = high - low;
+       zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
+
+       if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) {
+               printk(KERN_WARNING "This processor doesn't support highmem."
+                      " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]);
+               zones_size[ZONE_HIGHMEM] = 0;
+       }
 #endif
 
 #ifdef CONFIG_FLATMEM
index cea7d0e..fc2c96f 100644 (file)
@@ -6,98 +6,13 @@
  * (C) Copyright 1995 1996 Linus Torvalds
  * (C) Copyright 2001, 2002 Ralf Baechle
  */
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
 #include <linux/vmalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
-       phys_t size, phys_t phys_addr, unsigned long flags)
-{
-       phys_t end;
-       unsigned long pfn;
-       pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
-                                  | __WRITEABLE | flags);
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, pfn_pte(pfn, pgprot));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
-       phys_t size, phys_t phys_addr, unsigned long flags)
-{
-       phys_t end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, phys_t phys_addr,
-       phys_t size, unsigned long flags)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset(&init_mm, address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pud_t *pud;
-               pmd_t *pmd;
-
-               error = -ENOMEM;
-               pud = pud_alloc(&init_mm, dir, address);
-               if (!pud)
-                       break;
-               pmd = pmd_alloc(&init_mm, pud, address);
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                        phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return error;
-}
+#include <linux/io.h>
 
 /*
  * Generic mapping function (not visible outside):
@@ -121,6 +36,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
        unsigned long offset;
        phys_t last_addr;
        void * addr;
+       pgprot_t pgprot;
 
        phys_addr = fixup_bigphys_addr(phys_addr, size);
 
@@ -152,6 +68,9 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
                                return NULL;
        }
 
+       pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+                         | __WRITEABLE | flags);
+
        /*
         * Mappings have to be page-aligned
         */
@@ -166,7 +85,8 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
        if (!area)
                return NULL;
        addr = area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, pgprot)) {
                vunmap(addr);
                return NULL;
        }
index e5a4a0a..bb11fef 100644 (file)
@@ -65,15 +65,6 @@ static inline void unmask_cpci_irq(unsigned int irq)
        value = OCELOT_FPGA_READ(INTMASK);
 }
 
-/*
- * End IRQ processing
- */
-static void end_cpci_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               unmask_cpci_irq(irq);
-}
-
 /*
  * Interrupt handler for interrupts coming from the FPGA chip.
  * It could be built in ethernet ports etc...
@@ -98,7 +89,6 @@ struct irq_chip cpci_irq_type = {
        .mask = mask_cpci_irq,
        .mask_ack = mask_cpci_irq,
        .unmask = unmask_cpci_irq,
-       .end = end_cpci_irq,
 };
 
 void cpci_irq_init(void)
index 0029f00..a7a80c0 100644 (file)
@@ -59,15 +59,6 @@ static inline void unmask_uart_irq(unsigned int irq)
        value = OCELOT_FPGA_READ(UART_INTMASK);
 }
 
-/*
- * End IRQ processing
- */
-static void end_uart_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               unmask_uart_irq(irq);
-}
-
 /*
  * Interrupt handler for interrupts coming from the FPGA chip.
  */
@@ -91,7 +82,6 @@ struct irq_chip uart_irq_type = {
        .mask = mask_uart_irq,
        .mask_ack = mask_uart_irq,
        .unmask = unmask_uart_irq,
-       .end = end_uart_irq,
 };
 
 void uart_irq_init(void)
index 70cb55b..82b20c2 100644 (file)
@@ -43,7 +43,7 @@ obj-$(CONFIG_SGI_IP32)                += fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)    += fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM112X)   += fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM1x80)   += pci-bcm1480.o pci-bcm1480ht.o
-obj-$(CONFIG_SNI_RM200_PCI)    += fixup-sni.o ops-sni.o
+obj-$(CONFIG_SNI_RM)           += fixup-sni.o ops-sni.o
 obj-$(CONFIG_TANBAC_TB0219)    += fixup-tb0219.o
 obj-$(CONFIG_TANBAC_TB0226)    += fixup-tb0226.o
 obj-$(CONFIG_TANBAC_TB0287)    += fixup-tb0287.o
index 4256b3b..50546da 100644 (file)
@@ -33,7 +33,7 @@
 #define        DBG(x...)
 #endif
 
-extern char irq_tab_jbs[][5];
+extern char pnx8550_irq_tab[][5];
 
 void __init pcibios_fixup_resources(struct pci_dev *dev)
 {
@@ -47,7 +47,7 @@ void __init pcibios_fixup(void)
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       return irq_tab_jbs[slot][pin];
+       return pnx8550_irq_tab[slot][pin];
 }
 
 /* Do platform specific device initialization at pci_enable_device() time */
index 0dc2393..2c36c10 100644 (file)
@@ -158,20 +158,12 @@ int pnx8550_set_gic_priority(int irq, int priority)
        return prev_priority;
 }
 
-static void end_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-               unmask_irq(irq);
-       }
-}
-
 static struct irq_chip level_irq_type = {
        .typename =     "PNX Level IRQ",
        .ack =          mask_irq,
        .mask =         mask_irq,
        .mask_ack =     mask_irq,
        .unmask =       unmask_irq,
-       .end =          end_irq,
 };
 
 static struct irqaction gic_action = {
index f8952c1..eb6ec11 100644 (file)
@@ -35,23 +35,15 @@ char * prom_getcmdline(void)
        return &(arcs_cmdline[0]);
 }
 
-void  prom_init_cmdline(void)
+void __init prom_init_cmdline(void)
 {
-       char *cp;
-       int actr;
-
-       actr = 1; /* Always ignore argv[0] */
+       int i;
 
-       cp = &(arcs_cmdline[0]);
-       while(actr < prom_argc) {
-               strcpy(cp, prom_argv[actr]);
-               cp += strlen(prom_argv[actr]);
-               *cp++ = ' ';
-               actr++;
+       arcs_cmdline[0] = '\0';
+       for (i = 0; i < prom_argc; i++) {
+               strcat(arcs_cmdline, prom_argv[i]);
+               strcat(arcs_cmdline, " ");
        }
-       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-               --cp;
-       *cp = '\0';
 }
 
 char *prom_getenv(char *envname)
index f78e042..98c3429 100644 (file)
@@ -28,9 +28,9 @@
 #include <linux/init.h>
 #include <int.h>
 
-char irq_tab_jbs[][5] __initdata = {
[8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
[9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
[17] =        { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+char pnx8550_irq_tab[][5] __initdata = {
      [8]     = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
      [9]     = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
      [17]    = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
 };
 
diff --git a/arch/mips/philips/pnx8550/stb810/Makefile b/arch/mips/philips/pnx8550/stb810/Makefile
new file mode 100644 (file)
index 0000000..f14b592
--- /dev/null
@@ -0,0 +1,4 @@
+
+# Makefile for the Philips STB810 Board.
+
+lib-y := prom_init.o board_setup.o irqmap.o
diff --git a/arch/mips/philips/pnx8550/stb810/board_setup.c b/arch/mips/philips/pnx8550/stb810/board_setup.c
new file mode 100644 (file)
index 0000000..345d71e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  STB810 specific board startup routines.
+ *
+ *  Based on the arch/mips/philips/pnx8550/jbs/board_setup.c
+ *
+ *  Author: MontaVista Software, Inc.
+ *          source@mvista.com
+ *
+ *  Copyright 2005 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+
+#include <glb.h>
+
+void __init board_setup(void)
+{
+       unsigned long config0, configpr;
+
+       config0 = read_c0_config();
+
+       /* clear all three cache coherency fields */
+       config0 &= ~(0x7 | (7<<25) | (7<<28));
+       config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
+                       (CONF_CM_DEFAULT<<28));
+       write_c0_config(config0);
+
+       configpr = read_c0_config7();
+       configpr |= (1<<19); /* enable tlb */
+       write_c0_config7(configpr);
+}
diff --git a/arch/mips/philips/pnx8550/stb810/irqmap.c b/arch/mips/philips/pnx8550/stb810/irqmap.c
new file mode 100644 (file)
index 0000000..5ee11e1
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Philips STB810 board irqmap.
+ *
+ *  Author: MontaVista Software, Inc.
+ *          source@mvista.com
+ *
+ *  Copyright 2005 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/init.h>
+#include <int.h>
+
+char pnx8550_irq_tab[][5] __initdata = {
+       [8]     = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+       [9]     = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+       [10]    = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+};
+
diff --git a/arch/mips/philips/pnx8550/stb810/prom_init.c b/arch/mips/philips/pnx8550/stb810/prom_init.c
new file mode 100644 (file)
index 0000000..ea5b4e0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  STB810 specific prom routines
+ *
+ *  Author: MontaVista Software, Inc.
+ *          source@mvista.com
+ *
+ *  Copyright 2005 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+       return "Philips PNX8550/STB810";
+}
+
+void __init prom_init(void)
+{
+       unsigned long memsize;
+
+       prom_argc = (int) fw_arg0;
+       prom_argv = (char **) fw_arg1;
+       prom_envp = (char **) fw_arg2;
+
+       prom_init_cmdline();
+
+       mips_machgroup = MACH_GROUP_PHILIPS;
+       mips_machtype = MACH_PHILIPS_STB810;
+
+       memsize = 0x08000000; /* Trimedia uses memory above */
+       add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
index c7b1380..c44f8be 100644 (file)
@@ -51,19 +51,12 @@ static void disable_local0_irq(unsigned int irq)
        sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
 }
 
-static void end_local0_irq (unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_local0_irq(irq);
-}
-
 static struct irq_chip ip22_local0_irq_type = {
        .typename       = "IP22 local 0",
        .ack            = disable_local0_irq,
        .mask           = disable_local0_irq,
        .mask_ack       = disable_local0_irq,
        .unmask         = enable_local0_irq,
-       .end            = end_local0_irq,
 };
 
 static void enable_local1_irq(unsigned int irq)
@@ -79,19 +72,12 @@ void disable_local1_irq(unsigned int irq)
        sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1));
 }
 
-static void end_local1_irq (unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_local1_irq(irq);
-}
-
 static struct irq_chip ip22_local1_irq_type = {
        .typename       = "IP22 local 1",
        .ack            = disable_local1_irq,
        .mask           = disable_local1_irq,
        .mask_ack       = disable_local1_irq,
        .unmask         = enable_local1_irq,
-       .end            = end_local1_irq,
 };
 
 static void enable_local2_irq(unsigned int irq)
@@ -107,19 +93,12 @@ void disable_local2_irq(unsigned int irq)
                sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
 }
 
-static void end_local2_irq (unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_local2_irq(irq);
-}
-
 static struct irq_chip ip22_local2_irq_type = {
        .typename       = "IP22 local 2",
        .ack            = disable_local2_irq,
        .mask           = disable_local2_irq,
        .mask_ack       = disable_local2_irq,
        .unmask         = enable_local2_irq,
-       .end            = end_local2_irq,
 };
 
 static void enable_local3_irq(unsigned int irq)
@@ -135,19 +114,12 @@ void disable_local3_irq(unsigned int irq)
                sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
 }
 
-static void end_local3_irq (unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_local3_irq(irq);
-}
-
 static struct irq_chip ip22_local3_irq_type = {
        .typename       = "IP22 local 3",
        .ack            = disable_local3_irq,
        .mask           = disable_local3_irq,
        .mask_ack       = disable_local3_irq,
        .unmask         = enable_local3_irq,
-       .end            = end_local3_irq,
 };
 
 static void indy_local0_irqdispatch(void)
index 5f8835b..319f880 100644 (file)
@@ -332,13 +332,6 @@ static inline void disable_bridge_irq(unsigned int irq)
        intr_disconnect_level(cpu, swlevel);
 }
 
-static void end_bridge_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
-           irq_desc[irq].action)
-               enable_bridge_irq(irq);
-}
-
 static struct irq_chip bridge_irq_type = {
        .typename       = "bridge",
        .startup        = startup_bridge_irq,
@@ -347,7 +340,6 @@ static struct irq_chip bridge_irq_type = {
        .mask           = disable_bridge_irq,
        .mask_ack       = disable_bridge_irq,
        .unmask         = enable_bridge_irq,
-       .end            = end_bridge_irq,
 };
 
 void __devinit register_bridge_irq(unsigned int irq)
index 7d36172..c20e989 100644 (file)
@@ -180,10 +180,6 @@ static void disable_rt_irq(unsigned int irq)
 {
 }
 
-static void end_rt_irq(unsigned int irq)
-{
-}
-
 static struct irq_chip rt_irq_type = {
        .typename       = "SN HUB RT timer",
        .ack            = disable_rt_irq,
@@ -191,7 +187,6 @@ static struct irq_chip rt_irq_type = {
        .mask_ack       = disable_rt_irq,
        .unmask         = enable_rt_irq,
        .eoi            = enable_rt_irq,
-       .end            = end_rt_irq,
 };
 
 static struct irqaction rt_irqaction = {
index 21873de..ed4a19a 100644 (file)
 #define TX4927_IRQ_CP0_INIT     ( 1 << 10 )
 #define TX4927_IRQ_CP0_ENABLE   ( 1 << 13 )
 #define TX4927_IRQ_CP0_DISABLE  ( 1 << 14 )
-#define TX4927_IRQ_CP0_ENDIRQ   ( 1 << 16 )
 
 #define TX4927_IRQ_PIC_INIT     ( 1 << 20 )
 #define TX4927_IRQ_PIC_ENABLE   ( 1 << 23 )
 #define TX4927_IRQ_PIC_DISABLE  ( 1 << 24 )
-#define TX4927_IRQ_PIC_ENDIRQ   ( 1 << 26 )
 
 #define TX4927_IRQ_ALL         0xffffffff
 #endif
@@ -82,12 +80,10 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE
                                          | TX4927_IRQ_WARN | TX4927_IRQ_EROR
 //                                       | TX4927_IRQ_CP0_INIT
 //                                       | TX4927_IRQ_CP0_ENABLE
-//                                       | TX4927_IRQ_CP0_DISABLE
 //                                       | TX4927_IRQ_CP0_ENDIRQ
 //                                       | TX4927_IRQ_PIC_INIT
 //                                       | TX4927_IRQ_PIC_ENABLE
 //                                       | TX4927_IRQ_PIC_DISABLE
-//                                       | TX4927_IRQ_PIC_ENDIRQ
 //                                       | TX4927_IRQ_INIT
 //                                       | TX4927_IRQ_NEST1
 //                                       | TX4927_IRQ_NEST2
@@ -114,11 +110,9 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE
 
 static void tx4927_irq_cp0_enable(unsigned int irq);
 static void tx4927_irq_cp0_disable(unsigned int irq);
-static void tx4927_irq_cp0_end(unsigned int irq);
 
 static void tx4927_irq_pic_enable(unsigned int irq);
 static void tx4927_irq_pic_disable(unsigned int irq);
-static void tx4927_irq_pic_end(unsigned int irq);
 
 /*
  * Kernel structs for all pic's
@@ -131,7 +125,6 @@ static struct irq_chip tx4927_irq_cp0_type = {
        .mask           = tx4927_irq_cp0_disable,
        .mask_ack       = tx4927_irq_cp0_disable,
        .unmask         = tx4927_irq_cp0_enable,
-       .end            = tx4927_irq_cp0_end,
 };
 
 #define TX4927_PIC_NAME "TX4927-PIC"
@@ -141,7 +134,6 @@ static struct irq_chip tx4927_irq_pic_type = {
        .mask           = tx4927_irq_pic_disable,
        .mask_ack       = tx4927_irq_pic_disable,
        .unmask         = tx4927_irq_pic_enable,
-       .end            = tx4927_irq_pic_end,
 };
 
 #define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL }
@@ -214,15 +206,6 @@ static void tx4927_irq_cp0_disable(unsigned int irq)
        tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0);
 }
 
-static void tx4927_irq_cp0_end(unsigned int irq)
-{
-       TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq);
-
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               tx4927_irq_cp0_enable(irq);
-       }
-}
-
 /*
  * Functions for pic
  */
@@ -376,15 +359,6 @@ static void tx4927_irq_pic_disable(unsigned int irq)
                              tx4927_irq_pic_mask(irq), 0);
 }
 
-static void tx4927_irq_pic_end(unsigned int irq)
-{
-       TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq);
-
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               tx4927_irq_pic_enable(irq);
-       }
-}
-
 /*
  * Main init functions
  */
index 34cdb2a..b54b529 100644 (file)
@@ -153,13 +153,11 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB
 #define TOSHIBA_RBTX4927_IRQ_IOC_INIT      ( 1 << 10 )
 #define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE    ( 1 << 13 )
 #define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE   ( 1 << 14 )
-#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ    ( 1 << 16 )
 
 #define TOSHIBA_RBTX4927_IRQ_ISA_INIT      ( 1 << 20 )
 #define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE    ( 1 << 23 )
 #define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE   ( 1 << 24 )
 #define TOSHIBA_RBTX4927_IRQ_ISA_MASK      ( 1 << 25 )
-#define TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ    ( 1 << 26 )
 
 #define TOSHIBA_RBTX4927_SETUP_ALL         0xffffffff
 #endif
@@ -172,12 +170,10 @@ static const u32 toshiba_rbtx4927_irq_debug_flag =
 //                                                 | TOSHIBA_RBTX4927_IRQ_IOC_INIT
 //                                                 | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE
 //                                                 | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE
-//                                                 | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ
 //                                                 | TOSHIBA_RBTX4927_IRQ_ISA_INIT
 //                                                 | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
 //                                                 | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
 //                                                 | TOSHIBA_RBTX4927_IRQ_ISA_MASK
-//                                                 | TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ
     );
 #endif
 
@@ -223,13 +219,11 @@ extern void mask_and_ack_8259A(unsigned int irq);
 
 static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq);
 static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq);
-static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq);
 
 #ifdef CONFIG_TOSHIBA_FPCIB0
 static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq);
 static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq);
 static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq);
-static void toshiba_rbtx4927_irq_isa_end(unsigned int irq);
 #endif
 
 #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
@@ -239,7 +233,6 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
        .mask = toshiba_rbtx4927_irq_ioc_disable,
        .mask_ack = toshiba_rbtx4927_irq_ioc_disable,
        .unmask = toshiba_rbtx4927_irq_ioc_enable,
-       .end = toshiba_rbtx4927_irq_ioc_end,
 };
 #define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000
 #define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006
@@ -253,7 +246,6 @@ static struct irq_chip toshiba_rbtx4927_irq_isa_type = {
        .mask = toshiba_rbtx4927_irq_isa_disable,
        .mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
        .unmask = toshiba_rbtx4927_irq_isa_enable,
-       .end = toshiba_rbtx4927_irq_isa_end,
 };
 #endif
 
@@ -388,23 +380,6 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq)
        TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v);
 }
 
-static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq)
-{
-       TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ,
-                                    "irq=%d\n", irq);
-
-       if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
-           || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
-               TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
-                                            "bad irq=%d\n", irq);
-               panic("\n");
-       }
-
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               toshiba_rbtx4927_irq_ioc_enable(irq);
-       }
-}
-
 
 /**********************************************************************************/
 /* Functions for isa                                                              */
@@ -423,7 +398,8 @@ static void __init toshiba_rbtx4927_irq_isa_init(void)
 
        for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG;
             i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++)
-               set_irq_chip(i, &toshiba_rbtx4927_irq_isa_type);
+               set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_isa_type,
+                                        handle_level_irq);
 
        setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC,
                  &toshiba_rbtx4927_irq_isa_master);
@@ -491,26 +467,6 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq)
 #endif
 
 
-#ifdef CONFIG_TOSHIBA_FPCIB0
-static void toshiba_rbtx4927_irq_isa_end(unsigned int irq)
-{
-       TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ,
-                                    "irq=%d\n", irq);
-
-       if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
-           || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
-               TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
-                                            "bad irq=%d\n", irq);
-               panic("\n");
-       }
-
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               toshiba_rbtx4927_irq_isa_enable(irq);
-       }
-}
-#endif
-
-
 void __init arch_init_irq(void)
 {
        extern void tx4927_irq_init(void);
index 42e1276..a347b42 100644 (file)
 
 static void tx4938_irq_cp0_enable(unsigned int irq);
 static void tx4938_irq_cp0_disable(unsigned int irq);
-static void tx4938_irq_cp0_end(unsigned int irq);
 
 static void tx4938_irq_pic_enable(unsigned int irq);
 static void tx4938_irq_pic_disable(unsigned int irq);
-static void tx4938_irq_pic_end(unsigned int irq);
 
 /**********************************************************************************/
 /* Kernel structs for all pic's                                                   */
@@ -56,7 +54,6 @@ static struct irq_chip tx4938_irq_cp0_type = {
        .mask = tx4938_irq_cp0_disable,
        .mask_ack = tx4938_irq_cp0_disable,
        .unmask = tx4938_irq_cp0_enable,
-       .end = tx4938_irq_cp0_end,
 };
 
 #define TX4938_PIC_NAME "TX4938-PIC"
@@ -66,7 +63,6 @@ static struct irq_chip tx4938_irq_pic_type = {
        .mask = tx4938_irq_pic_disable,
        .mask_ack = tx4938_irq_pic_disable,
        .unmask = tx4938_irq_pic_enable,
-       .end = tx4938_irq_pic_end,
 };
 
 static struct irqaction tx4938_irq_pic_action = {
@@ -104,14 +100,6 @@ tx4938_irq_cp0_disable(unsigned int irq)
        clear_c0_status(tx4938_irq_cp0_mask(irq));
 }
 
-static void
-tx4938_irq_cp0_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               tx4938_irq_cp0_enable(irq);
-       }
-}
-
 /**********************************************************************************/
 /* Functions for pic                                                              */
 /**********************************************************************************/
@@ -269,14 +257,6 @@ tx4938_irq_pic_disable(unsigned int irq)
                              tx4938_irq_pic_mask(irq), 0);
 }
 
-static void
-tx4938_irq_pic_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               tx4938_irq_pic_enable(irq);
-       }
-}
-
 /**********************************************************************************/
 /* Main init functions                                                            */
 /**********************************************************************************/
index 8c87a35..b6f363d 100644 (file)
@@ -89,7 +89,6 @@ IRQ  Device
 
 static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
 static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
-static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq);
 
 #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
 static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
@@ -98,7 +97,6 @@ static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
        .mask = toshiba_rbtx4938_irq_ioc_disable,
        .mask_ack = toshiba_rbtx4938_irq_ioc_disable,
        .unmask = toshiba_rbtx4938_irq_ioc_enable,
-       .end = toshiba_rbtx4938_irq_ioc_end,
 };
 
 #define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000
@@ -167,14 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
        TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
 }
 
-static void
-toshiba_rbtx4938_irq_ioc_end(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-               toshiba_rbtx4938_irq_ioc_enable(irq);
-       }
-}
-
 extern void __init txx9_spi_irqinit(int irc_irq);
 
 void __init arch_init_irq(void)
index 54b92a7..c075261 100644 (file)
@@ -427,19 +427,12 @@ static void enable_sysint1_irq(unsigned int irq)
        icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
 }
 
-static void end_sysint1_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
-}
-
 static struct irq_chip sysint1_irq_type = {
        .typename       = "SYSINT1",
        .ack            = disable_sysint1_irq,
        .mask           = disable_sysint1_irq,
        .mask_ack       = disable_sysint1_irq,
        .unmask         = enable_sysint1_irq,
-       .end            = end_sysint1_irq,
 };
 
 static void disable_sysint2_irq(unsigned int irq)
@@ -452,19 +445,12 @@ static void enable_sysint2_irq(unsigned int irq)
        icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
 }
 
-static void end_sysint2_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
-}
-
 static struct irq_chip sysint2_irq_type = {
        .typename       = "SYSINT2",
        .ack            = disable_sysint2_irq,
        .mask           = disable_sysint2_irq,
        .mask_ack       = disable_sysint2_irq,
        .unmask         = enable_sysint2_irq,
-       .end            = end_sysint2_irq,
 };
 
 static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
index a039bb7..128ed8d 100644 (file)
@@ -45,19 +45,12 @@ static void ack_i8259_irq(unsigned int irq)
        mask_and_ack_8259A(irq - I8259_IRQ_BASE);
 }
 
-static void end_i8259_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
 static struct irq_chip i8259_irq_type = {
        .typename       = "XT-PIC",
        .ack            = ack_i8259_irq,
        .mask           = disable_i8259_irq,
        .mask_ack       = ack_i8259_irq,
        .unmask         = enable_i8259_irq,
-       .end            = end_i8259_irq,
 };
 
 static int i8259_get_irq_number(int irq)
@@ -92,7 +85,7 @@ void __init rockhopper_init_irq(void)
        }
 
        for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
-               set_irq_chip(i, &i8259_irq_type);
+               set_irq_chip_and_handler(i, &i8259_irq_type, handle_level_irq);
 
        setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
 
index d210123..0f9ff61 100644 (file)
@@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_FIND_NEXT_BIT
        bool
        default y
index 2e2dc4f..d883092 100644 (file)
@@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs_hpux(file->f_dentry, &tmp);
+       error = vfs_statfs_hpux(file->f_path.dentry, &tmp);
        if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                error = -EFAULT;
        fput(file);
index 1e64e7b..ecb10a4 100644 (file)
@@ -75,7 +75,6 @@ struct elf_prpsinfo32
        char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
 };
 
-#define elf_addr_t     unsigned int
 #define init_elf_binfmt init_elf32_binfmt
 
 #define ELF_PLATFORM  ("PARISC32\0")
index 64785e4..641f9c9 100644 (file)
@@ -152,7 +152,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
        const struct exception_table_entry *fix;
        unsigned long acc_type;
 
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        down_read(&mm->mmap_sem);
index 47a1d2a..44b42c7 100644 (file)
@@ -9,110 +9,8 @@
 #include <linux/vmalloc.h>
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
-
-static inline void 
-remap_area_pte(pte_t *pte, unsigned long address, unsigned long size,
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end, pfn;
-       pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
-                                  _PAGE_ACCESSED | flags);
-
-       address &= ~PMD_MASK;
-
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-
-       BUG_ON(address >= end);
-
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               BUG_ON(!pte_none(*pte));
-
-               set_pte(pte, pfn_pte(pfn, pgprot));
-
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int 
-remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-
-       BUG_ON(address >= end);
-
-       phys_addr -= address;
-       do {
-               pte_t *pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-
-               remap_area_pte(pte, address, end - address, 
-                              address + phys_addr, flags);
-
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-
-       return 0;
-}
-
-static int 
-remap_area_pages(unsigned long address, unsigned long phys_addr,
-                unsigned long size, unsigned long flags)
-{
-       pgd_t *dir;
-       int error = 0;
-       unsigned long end = address + size;
-
-       BUG_ON(address >= end);
-
-       phys_addr -= address;
-       dir = pgd_offset_k(address);
-
-       flush_cache_all();
-
-       do {
-               pud_t *pud;
-               pmd_t *pmd;
-
-               error = -ENOMEM;
-               pud = pud_alloc(&init_mm, dir, address);
-               if (!pud)
-                       break;
-
-               pmd = pmd_alloc(&init_mm, pud, address);
-               if (!pmd)
-                       break;
-
-               if (remap_area_pmd(pmd, address, end - address,
-                                  phys_addr + address, flags))
-                       break;
-
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-
-       flush_tlb_all();
-
-       return error;
-}
 
 /*
  * Generic mapping function (not visible outside):
@@ -131,6 +29,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        void *addr;
        struct vm_struct *area;
        unsigned long offset, last_addr;
+       pgprot_t pgprot;
 
 #ifdef CONFIG_EISA
        unsigned long end = phys_addr + size - 1;
@@ -164,6 +63,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
                }
        }
 
+       pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+                         _PAGE_ACCESSED | flags);
+
        /*
         * Mappings have to be page-aligned
         */
@@ -179,7 +81,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
                return NULL;
 
        addr = area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, pgprot)) {
                vfree(addr);
                return NULL;
        }
index 291c95a..8699dad 100644 (file)
@@ -41,6 +41,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default y
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default y if 64BIT
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -99,6 +107,11 @@ config AUDIT_ARCH
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
 config DEFAULT_UIMAGE
        bool
        help
@@ -470,6 +483,7 @@ config PPC_MAPLE
        select PPC_UDBG_16550
        select PPC_970_NAP
        select PPC_NATIVE
+       select PPC_RTAS
        default n
        help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -706,7 +720,7 @@ config FORCE_MAX_ZONEORDER
 
 config MATH_EMULATION
        bool "Math emulation"
-       depends on 4xx || 8xx || E200 || E500
+       depends on 4xx || 8xx || E200 || PPC_83xx || E500
        ---help---
          Some PowerPC chips designed for embedded applications do not have
          a floating-point unit and therefore do not implement the
index f2d888e..70ed613 100644 (file)
@@ -157,6 +157,7 @@ CONFIG_SPU_BASE=y
 CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_DYNAMIC_DMA=y
 CONFIG_PS3_USE_LPAR_ADDR=y
+CONFIG_PS3_VUART=y
 
 #
 # Kernel options
index 4fe53d0..d2ded19 100644 (file)
@@ -77,6 +77,7 @@ endif
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 extra-y += lparmap.s
+$(obj)/head_64.o:      $(obj)/lparmap.s
 AFLAGS_head_64.o += -I$(obj)
 endif
 
index 9d1614c..b742013 100644 (file)
@@ -833,7 +833,7 @@ static struct cpu_spec cpu_specs[] = {
                .pvr_mask               = 0x7fff0000,
                .pvr_value              = 0x00840000,
                .cpu_name               = "e300c2",
-               .cpu_features           = CPU_FTRS_E300,
+               .cpu_features           = CPU_FTRS_E300C2,
                .cpu_user_features      = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
@@ -1136,8 +1136,7 @@ static struct cpu_spec cpu_specs[] = {
                .pvr_mask               = 0xff000fff,
                .pvr_value              = 0x53000890,
                .cpu_name               = "440SPe Rev. A",
-               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
-                       CPU_FTR_USE_TB,
+               .cpu_features           = CPU_FTRS_44X,
                .cpu_user_features      = COMMON_USER_BOOKE,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
index 89b03c8..d3f2080 100644 (file)
@@ -46,61 +46,6 @@ int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
-                                                              size_t data_len)
-{
-       struct elf_note note;
-
-       note.n_namesz = strlen(name) + 1;
-       note.n_descsz = data_len;
-       note.n_type   = type;
-       memcpy(buf, &note, sizeof(note));
-       buf += (sizeof(note) +3)/4;
-       memcpy(buf, name, note.n_namesz);
-       buf += (note.n_namesz + 3)/4;
-       memcpy(buf, data, note.n_descsz);
-       buf += (note.n_descsz + 3)/4;
-
-       return buf;
-}
-
-static void final_note(u32 *buf)
-{
-       struct elf_note note;
-
-       note.n_namesz = 0;
-       note.n_descsz = 0;
-       note.n_type   = 0;
-       memcpy(buf, &note, sizeof(note));
-}
-
-static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
-{
-       struct elf_prstatus prstatus;
-       u32 *buf;
-
-       if ((cpu < 0) || (cpu >= NR_CPUS))
-               return;
-
-       /* Using ELF notes here is opportunistic.
-        * I need a well defined structure format
-        * 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.
-        */
-       buf = (u32*)per_cpu_ptr(crash_notes, cpu);
-       if (!buf) 
-               return;
-
-       memset(&prstatus, 0, sizeof(prstatus));
-       prstatus.pr_pid = current->pid;
-       elf_core_copy_regs(&prstatus.pr_reg, regs);
-       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
-                       sizeof(prstatus));
-       final_note(buf);
-}
-
 #ifdef CONFIG_SMP
 static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
 
@@ -113,7 +58,7 @@ void crash_ipi_callback(struct pt_regs *regs)
 
        hard_irq_disable();
        if (!cpu_isset(cpu, cpus_in_crash))
-               crash_save_this_cpu(regs, cpu);
+               crash_save_cpu(regs, cpu);
        cpu_set(cpu, cpus_in_crash);
 
        /*
@@ -306,7 +251,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
         * such that another IPI will not be sent.
         */
        crashing_cpu = smp_processor_id();
-       crash_save_this_cpu(regs, crashing_cpu);
+       crash_save_cpu(regs, crashing_cpu);
        crash_kexec_prepare_cpus(crashing_cpu);
        cpu_set(crashing_cpu, cpus_in_crash);
        if (ppc_md.kexec_cpu_down)
index d88e182..9417cf5 100644 (file)
@@ -437,6 +437,13 @@ Alignment:
 /* Floating-point unavailable */
        . = 0x800
 FPUnavailable:
+BEGIN_FTR_SECTION
+/*
+ * Certain Freescale cores don't have a FPU and treat fp instructions
+ * as a FP Unavailable exception.  Redirect to illegal/emulation handling.
+ */
+       b       ProgramCheck
+END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
        EXCEPTION_PROLOG
        bne     load_up_fpu             /* if from user, just load it up */
        addi    r3,r1,STACK_FRAME_OVERHEAD
index 7b8d12b..4657563 100644 (file)
@@ -85,7 +85,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, 0);
        mutex_unlock(&kprobe_mutex);
 }
 
index e2c3c6a..8339fd6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/cache.h>
+#include <linux/bug.h>
 
 #include "setup.h"
 
@@ -290,23 +291,11 @@ int module_finalize(const Elf_Ehdr *hdr,
                    struct module *me)
 {
        const Elf_Shdr *sect;
+       int err;
 
-       me->arch.bug_table = NULL;
-       me->arch.num_bugs = 0;
-
-       /* Find the __bug_table section, if present */
-       sect = find_section(hdr, sechdrs, "__bug_table");
-       if (sect != NULL) {
-               me->arch.bug_table = (void *) sect->sh_addr;
-               me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
-       }
-
-       /*
-        * Strictly speaking this should have a spinlock to protect against
-        * traversals, but since we only traverse on BUG()s, a spinlock
-        * could potentially lead to deadlock and thus be counter-productive.
-        */
-       list_add(&me->arch.bug_list, &module_bug_list);
+       err = module_bug_finalize(hdr, sechdrs, me);
+       if (err)                /* never true, currently */
+               return err;
 
        /* Apply feature fixups */
        sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -320,7 +309,7 @@ int module_finalize(const Elf_Ehdr *hdr,
 
 void module_arch_cleanup(struct module *mod)
 {
-       list_del(&mod->arch.bug_list);
+       module_bug_cleanup(mod);
 }
 
 struct bug_entry *module_find_bug(unsigned long bugaddr)
index 8dd1f0a..75c7c4f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/moduleloader.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/bug.h>
 #include <asm/module.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
@@ -439,23 +440,11 @@ int module_finalize(const Elf_Ehdr *hdr,
                const Elf_Shdr *sechdrs, struct module *me)
 {
        const Elf_Shdr *sect;
+       int err;
 
-       me->arch.bug_table = NULL;
-       me->arch.num_bugs = 0;
-
-       /* Find the __bug_table section, if present */
-       sect = find_section(hdr, sechdrs, "__bug_table");
-       if (sect != NULL) {
-               me->arch.bug_table = (void *) sect->sh_addr;
-               me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
-       }
-
-       /*
-        * Strictly speaking this should have a spinlock to protect against
-        * traversals, but since we only traverse on BUG()s, a spinlock
-        * could potentially lead to deadlock and thus be counter-productive.
-        */
-       list_add(&me->arch.bug_list, &module_bug_list);
+       err = module_bug_finalize(hdr, sechdrs, me);
+       if (err)
+               return err;
 
        /* Apply feature fixups */
        sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -475,7 +464,7 @@ int module_finalize(const Elf_Ehdr *hdr,
 
 void module_arch_cleanup(struct module *mod)
 {
-       list_del(&mod->arch.bug_list);
+       module_bug_cleanup(mod);
 }
 
 struct bug_entry *module_find_bug(unsigned long bugaddr)
index 8a06724..e921514 100644 (file)
@@ -109,9 +109,7 @@ int of_device_register(struct of_device *ofdev)
        if (rc)
                return rc;
 
-       device_create_file(&ofdev->dev, &dev_attr_devspec);
-
-       return 0;
+       return device_create_file(&ofdev->dev, &dev_attr_devspec);
 }
 
 void of_device_unregister(struct of_device *ofdev)
index b3189d0..3002ea3 100644 (file)
@@ -169,7 +169,7 @@ static void of_platform_make_bus_id(struct of_device *dev)
        char *name = dev->dev.bus_id;
        const u32 *reg;
        u64 addr;
-       long magic;
+       int magic;
 
        /*
         * If it's a DCR based device, use 'd' for native DCRs
index 2f54cd8..8336dea 100644 (file)
@@ -736,25 +736,51 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
        return NULL;
 }
 
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
+                                              unsigned int devfn)
 {
-       const unsigned int *reg;
-       u8* fdata = (u8*)data;
-       
-       reg = get_property(node, "reg", NULL);
-       if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
-               && ((reg[0] >> 16) & 0xff) == fdata[0])
-               return 1;
-       return 0;
+       struct device_node *np = NULL;
+       const u32 *reg;
+       unsigned int psize;
+
+       while ((np = of_get_next_child(parent, np)) != NULL) {
+               reg = get_property(np, "reg", &psize);
+               if (reg == NULL || psize < 4)
+                       continue;
+               if (((reg[0] >> 8) & 0xff) == devfn)
+                       return np;
+       }
+       return NULL;
 }
 
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+
+static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
 {
-       u8 filter_data[2] = {bus, dev_fn};
+       struct device_node *parent, *np;
+
+       /* Are we a root bus ? */
+       if (bus->self == NULL || bus->parent == NULL) {
+               struct pci_controller *hose = pci_bus_to_hose(bus->number);
+               if (hose == NULL)
+                       return NULL;
+               return of_node_get(hose->arch_data);
+       }
+
+       /* not a root bus, we need to get our parent */
+       parent = scan_OF_for_pci_bus(bus->parent);
+       if (parent == NULL)
+               return NULL;
+
+       /* now iterate for children for a match */
+       np = scan_OF_for_pci_dev(parent, bus->self->devfn);
+       of_node_put(parent);
 
-       return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+       /* sanity check */
+       if (strcmp(np->type, "pci") != 0)
+               printk(KERN_WARNING "pci: wrong type \"%s\" for bridge %s\n",
+                      np->type, np->full_name);
+
+       return np;
 }
 
 /*
@@ -763,43 +789,25 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
 struct device_node *
 pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
 {
-       struct pci_controller *hose;
-       struct device_node *node;
-       int busnr;
+       struct device_node *parent, *np;
 
        if (!have_of)
                return NULL;
-       
-       /* Lookup the hose */
-       busnr = bus->number;
-       hose = pci_bus_to_hose(busnr);
-       if (!hose)
-               return NULL;
 
-       /* Check it has an OF node associated */
-       node = (struct device_node *) hose->arch_data;
-       if (!node)
+       DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
+       parent = scan_OF_for_pci_bus(bus);
+       if (parent == NULL)
                return NULL;
-
-       /* Fixup bus number according to what OF think it is. */
-#ifdef CONFIG_PPC_PMAC
-       /* The G5 need a special case here. Basically, we don't remap all
-        * busses on it so we don't create the pci-OF-map. However, we do
-        * remap the AGP bus and so have to deal with it. A future better
-        * fix has to be done by making the remapping per-host and always
-        * filling the pci_to_OF map. --BenH
+       DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
+       np = scan_OF_for_pci_dev(parent, devfn);
+       of_node_put(parent);
+       DBG(" result is %s\n", np ? np->full_name : "<NULL>");
+
+       /* XXX most callers don't release the returned node
+        * mostly because ppc64 doesn't increase the refcount,
+        * we need to fix that.
         */
-       if (machine_is(powermac) && busnr >= 0xf0)
-               busnr -= 0xf0;
-       else
-#endif
-       if (pci_to_OF_bus_map)
-               busnr = pci_to_OF_bus_map[busnr];
-       if (busnr == 0xff)
-               return NULL;
-       
-       /* Now, lookup childs of the hose */
-       return scan_OF_childs_for_device(node->child, busnr, devfn);
+       return np;
 }
 EXPORT_SYMBOL(pci_busdev_to_OF_node);
 
@@ -1544,7 +1552,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
 
 
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-                                              unsigned long *offset,
+                                              resource_size_t *offset,
                                               enum pci_mmap_state mmap_state)
 {
        struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -1556,7 +1564,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
 
        /* If memory, add on the PCI bridge address offset */
        if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
                *offset += hose->pci_mem_offset;
+#endif
                res_bit = IORESOURCE_MEM;
        } else {
                io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
@@ -1624,9 +1634,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
        else
                prot |= _PAGE_GUARDED;
 
-       printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev),
-               (unsigned long long)rp->start, prot);
-
        return __pgprot(prot);
 }
 
@@ -1695,7 +1702,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state,
                        int write_combine)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
        struct resource *rp;
        int ret;
 
@@ -1808,22 +1815,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
                          resource_size_t *start, resource_size_t *end)
 {
        struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-       unsigned long offset = 0;
+       resource_size_t offset = 0;
 
        if (hose == NULL)
                return;
 
        if (rsrc->flags & IORESOURCE_IO)
-               offset = (void __iomem *)_IO_BASE - hose->io_base_virt
-                       + hose->io_base_phys;
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+       /* We pass a fully fixed up address to userland for MMIO instead of
+        * a BAR value because X is lame and expects to be able to use that
+        * to pass to /dev/mem !
+        *
+        * That means that we'll have potentially 64 bits values where some
+        * userland apps only expect 32 (like X itself since it thinks only
+        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+        * 32 bits CHRPs :-(
+        *
+        * Hopefully, the sysfs insterface is immune to that gunk. Once X
+        * has been fixed (and the fix spread enough), we can re-enable the
+        * 2 lines below and pass down a BAR value to userland. In that case
+        * we'll also have to re-enable the matching code in
+        * __pci_mmap_make_offset().
+        *
+        * BenH.
+        */
+#if 0
+       else if (rsrc->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+#endif
 
-       *start = rsrc->start + offset;
-       *end = rsrc->end + offset;
+       *start = rsrc->start - offset;
+       *end = rsrc->end - offset;
 }
 
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
-                 int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+                             resource_size_t end, int flags, char *name)
 {
        res->start = start;
        res->end = end;
index 6fa9a0a..a6b7692 100644 (file)
@@ -682,7 +682,7 @@ int pci_proc_domain(struct pci_bus *bus)
  * Returns negative error code on failure, zero on success.
  */
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-                                              unsigned long *offset,
+                                              resource_size_t *offset,
                                               enum pci_mmap_state mmap_state)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -694,7 +694,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
 
        /* If memory, add on the PCI bridge address offset */
        if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
                *offset += hose->pci_mem_offset;
+#endif
                res_bit = IORESOURCE_MEM;
        } else {
                io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
@@ -762,9 +764,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
        else
                prot |= _PAGE_GUARDED;
 
-       printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
-              prot);
-
        return __pgprot(prot);
 }
 
@@ -832,7 +831,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state, int write_combine)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
        struct resource *rp;
        int ret;
 
@@ -1333,20 +1332,41 @@ EXPORT_SYMBOL(pci_read_irq_line);
 
 void pci_resource_to_user(const struct pci_dev *dev, int bar,
                          const struct resource *rsrc,
-                         u64 *start, u64 *end)
+                         resource_size_t *start, resource_size_t *end)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       unsigned long offset = 0;
+       resource_size_t offset = 0;
 
        if (hose == NULL)
                return;
 
        if (rsrc->flags & IORESOURCE_IO)
-               offset = pci_io_base - (unsigned long)hose->io_base_virt +
-                       hose->io_base_phys;
+               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+       /* We pass a fully fixed up address to userland for MMIO instead of
+        * a BAR value because X is lame and expects to be able to use that
+        * to pass to /dev/mem !
+        *
+        * That means that we'll have potentially 64 bits values where some
+        * userland apps only expect 32 (like X itself since it thinks only
+        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+        * 32 bits CHRPs :-(
+        *
+        * Hopefully, the sysfs insterface is immune to that gunk. Once X
+        * has been fixed (and the fix spread enough), we can re-enable the
+        * 2 lines below and pass down a BAR value to userland. In that case
+        * we'll also have to re-enable the matching code in
+        * __pci_mmap_make_offset().
+        *
+        * BenH.
+        */
+#if 0
+       else if (rsrc->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+#endif
 
-       *start = rsrc->start + offset;
-       *end = rsrc->end + offset;
+       *start = rsrc->start - offset;
+       *end = rsrc->end - offset;
 }
 
 struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
index 9179f07..95776b6 100644 (file)
@@ -208,7 +208,7 @@ EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
 extern long *intercept_table;
 EXPORT_SYMBOL(intercept_table);
 #endif /* CONFIG_PPC_STD_MMU_32 */
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_DCR_NATIVE
 EXPORT_SYMBOL(__mtdcr);
 EXPORT_SYMBOL(__mfdcr);
 #endif
index f598cb5..dd7001c 100644 (file)
@@ -83,7 +83,7 @@ __initcall(proc_ppc64_init);
 static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 {
        loff_t new;
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
 
        switch(whence) {
        case 0:
@@ -106,13 +106,13 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
                              loff_t *ppos)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
 }
 
 static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
 
        if ((vma->vm_end - vma->vm_start) > dp->size)
                return -EINVAL;
index c18dbe7..1fc732a 100644 (file)
@@ -804,6 +804,56 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
        return of_read_ulong(p, s);
 }
 
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Interpret the ibm,dynamic-memory property in the
+ * /ibm,dynamic-reconfiguration-memory node.
+ * This contains a list of memory blocks along with NUMA affinity
+ * information.
+ */
+static int __init early_init_dt_scan_drconf_memory(unsigned long node)
+{
+       cell_t *dm, *ls;
+       unsigned long l, n;
+       unsigned long base, size, lmb_size, flags;
+
+       ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
+       if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
+               return 0;
+       lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
+
+       dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
+       if (dm == NULL || l < sizeof(cell_t))
+               return 0;
+
+       n = *dm++;      /* number of entries */
+       if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
+               return 0;
+
+       for (; n != 0; --n) {
+               base = dt_mem_next_cell(dt_root_addr_cells, &dm);
+               flags = dm[3];
+               /* skip DRC index, pad, assoc. list index, flags */
+               dm += 4;
+               /* skip this block if the reserved bit is set in flags (0x80)
+                  or if the block is not assigned to this partition (0x8) */
+               if ((flags & 0x80) || !(flags & 0x8))
+                       continue;
+               size = lmb_size;
+               if (iommu_is_off) {
+                       if (base >= 0x80000000ul)
+                               continue;
+                       if ((base + size) > 0x80000000ul)
+                               size = 0x80000000ul - base;
+               }
+               lmb_add(base, size);
+       }
+       lmb_dump_all();
+       return 0;
+}
+#else
+#define early_init_dt_scan_drconf_memory(node) 0
+#endif /* CONFIG_PPC_PSERIES */
 
 static int __init early_init_dt_scan_memory(unsigned long node,
                                            const char *uname, int depth, void *data)
@@ -812,6 +862,11 @@ static int __init early_init_dt_scan_memory(unsigned long node,
        cell_t *reg, *endp;
        unsigned long l;
 
+       /* Look for the ibm,dynamic-reconfiguration-memory node */
+       if (depth == 1 &&
+           strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
+               return early_init_dt_scan_drconf_memory(node);
+
        /* We are scanning "memory" nodes only */
        if (type == NULL) {
                /*
index 46cf326..520ef42 100644 (file)
@@ -679,7 +679,7 @@ static unsigned char ibm_architecture_vec[] = {
        /* option vector 5: PAPR/OF options */
        3 - 2,                          /* length */
        0,                              /* don't ignore, don't halt */
-       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
index 387ed0d..76b5d7e 100644 (file)
@@ -303,6 +303,12 @@ int rtas_token(const char *service)
 }
 EXPORT_SYMBOL(rtas_token);
 
+int rtas_service_present(const char *service)
+{
+       return rtas_token(service) != RTAS_UNKNOWN_SERVICE;
+}
+EXPORT_SYMBOL(rtas_service_present);
+
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 /*
  * Return the firmware-specified size of the error log buffer
@@ -810,32 +816,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-/* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
-       /* The token is initialized for real in setup_system() */
-       .token = RTAS_UNKNOWN_SERVICE,
-       .nargs = 0,
-       .nret = 1,
-       .rets = &rtas_stop_self_args.args[0],
-};
-
-void rtas_stop_self(void)
-{
-       struct rtas_args *rtas_args = &rtas_stop_self_args;
-
-       local_irq_disable();
-
-       BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
-
-       printk("cpu %u (hwid %u) Ready to die...\n",
-              smp_processor_id(), hard_smp_processor_id());
-       enter_rtas(__pa(rtas_args));
-
-       panic("Alas, I survived.\n");
-}
-#endif
-
 /*
  * Call early during boot, before mem init or bootmem, to retrieve the RTAS
  * informations from the device-tree and allocate the RMO buffer for userland
@@ -880,9 +860,6 @@ void __init rtas_initialize(void)
 #endif
        rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
 
-#ifdef CONFIG_HOTPLUG_CPU
-       rtas_stop_self_args.token = rtas_token("stop-self");
-#endif /* CONFIG_HOTPLUG_CPU */
 #ifdef CONFIG_RTAS_ERROR_LOGGING
        rtas_last_error_token = rtas_token("rtas-last-error");
 #endif
index b9561d3..0c4fcd3 100644 (file)
@@ -101,7 +101,7 @@ struct flash_block_list_header { /* just the header of flash_block_list */
 static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
 
 /* Use slab cache to guarantee 4k alignment */
-static kmem_cache_t *flash_block_cache = NULL;
+static struct kmem_cache *flash_block_cache = NULL;
 
 #define FLASH_BLOCK_LIST_VERSION (1UL)
 
@@ -193,7 +193,7 @@ static void free_flash_list(struct flash_block_list *f)
 
 static int rtas_flash_release(struct inode *inode, struct file *file)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_update_flash_t *uf;
        
        uf = (struct rtas_update_flash_t *) dp->data;
@@ -255,7 +255,7 @@ static void get_flash_status_msg(int status, char *buf)
 static ssize_t rtas_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_update_flash_t *uf;
        char msg[RTAS_MSG_MAXLEN];
        int msglen;
@@ -286,7 +286,7 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf,
 }
 
 /* constructor for flash_block_cache */
-void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags)
+void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags)
 {
        memset(ptr, 0, RTAS_BLK_SIZE);
 }
@@ -299,7 +299,7 @@ void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags)
 static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
                                size_t count, loff_t *off)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_update_flash_t *uf;
        char *p;
        int next_free;
@@ -391,7 +391,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf)
 static ssize_t manage_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_manage_flash_t *args_buf;
        char msg[RTAS_MSG_MAXLEN];
        int msglen;
@@ -421,7 +421,7 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf,
 static ssize_t manage_flash_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *off)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_manage_flash_t *args_buf;
        const char reject_str[] = "0";
        const char commit_str[] = "1";
@@ -492,7 +492,7 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
 static ssize_t validate_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_validate_flash_t *args_buf;
        char msg[RTAS_MSG_MAXLEN];
        int msglen;
@@ -520,7 +520,7 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
 static ssize_t validate_flash_write(struct file *file, const char __user *buf,
                                    size_t count, loff_t *off)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_validate_flash_t *args_buf;
        int rc;
 
@@ -569,7 +569,7 @@ done:
 
 static int validate_flash_release(struct inode *inode, struct file *file)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        struct rtas_validate_flash_t *args_buf;
 
        args_buf = (struct rtas_validate_flash_t *) dp->data;
index 320353f..e4ebe1a 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/stddef.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #endif
 
 #include <asm/uaccess.h>
index 22123a0..400ab2b 100644 (file)
@@ -181,6 +181,8 @@ SYSFS_PMCSETUP(pmc6, SPRN_PMC6);
 SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
 SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
 SYSFS_PMCSETUP(purr, SPRN_PURR);
+SYSFS_PMCSETUP(spurr, SPRN_SPURR);
+SYSFS_PMCSETUP(dscr, SPRN_DSCR);
 
 static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0);
 static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1);
@@ -194,6 +196,8 @@ static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6);
 static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7);
 static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8);
 static SYSDEV_ATTR(purr, 0600, show_purr, NULL);
+static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
+static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
 
 static void register_cpu_online(unsigned int cpu)
 {
@@ -231,6 +235,12 @@ static void register_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_PURR))
                sysdev_create_file(s, &attr_purr);
+
+       if (cpu_has_feature(CPU_FTR_SPURR))
+               sysdev_create_file(s, &attr_spurr);
+
+       if (cpu_has_feature(CPU_FTR_DSCR))
+               sysdev_create_file(s, &attr_dscr);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -239,7 +249,7 @@ static void unregister_cpu_online(unsigned int cpu)
        struct cpu *c = &per_cpu(cpu_devices, cpu);
        struct sys_device *s = &c->sysdev;
 
-       BUG_ON(c->no_control);
+       BUG_ON(!c->hotpluggable);
 
        if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
                        cpu_has_feature(CPU_FTR_SMT))
@@ -272,6 +282,12 @@ static void unregister_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_PURR))
                sysdev_remove_file(s, &attr_purr);
+
+       if (cpu_has_feature(CPU_FTR_SPURR))
+               sysdev_remove_file(s, &attr_spurr);
+
+       if (cpu_has_feature(CPU_FTR_DSCR))
+               sysdev_remove_file(s, &attr_dscr);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -424,10 +440,10 @@ static int __init topology_init(void)
                 * CPU.  For instance, the boot cpu might never be valid
                 * for hotplugging.
                 */
-               if (!ppc_md.cpu_die)
-                       c->no_control = 1;
+               if (ppc_md.cpu_die)
+                       c->hotpluggable = 1;
 
-               if (cpu_online(cpu) || (c->no_control == 0)) {
+               if (cpu_online(cpu) || c->hotpluggable) {
                        register_cpu(c, cpu);
 
                        sysdev_create_file(&c->sysdev, &attr_physical_id);
index 0d4e203..535f506 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
 #include <linux/backlight.h>
+#include <linux/bug.h>
 
 #include <asm/kdebug.h>
 #include <asm/pgtable.h>
@@ -727,54 +728,9 @@ static int emulate_instruction(struct pt_regs *regs)
        return -EINVAL;
 }
 
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x)     NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
+int is_valid_bugaddr(unsigned long addr)
 {
-       struct bug_entry *bug;
-
-       for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
-               if (bugaddr == bug->bug_addr)
-                       return bug;
-       return module_find_bug(bugaddr);
-}
-
-static int check_bug_trap(struct pt_regs *regs)
-{
-       struct bug_entry *bug;
-       unsigned long addr;
-
-       if (regs->msr & MSR_PR)
-               return 0;       /* not in kernel */
-       addr = regs->nip;       /* address of trap instruction */
-       if (addr < PAGE_OFFSET)
-               return 0;
-       bug = find_bug(regs->nip);
-       if (bug == NULL)
-               return 0;
-       if (bug->line & BUG_WARNING_TRAP) {
-               /* this is a WARN_ON rather than BUG/BUG_ON */
-               printk(KERN_ERR "Badness in %s at %s:%ld\n",
-                      bug->function, bug->file,
-                      bug->line & ~BUG_WARNING_TRAP);
-               dump_stack();
-               return 1;
-       }
-       printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-              bug->function, bug->file, bug->line);
-
-       return 0;
+       return is_kernel_addr(addr);
 }
 
 void __kprobes program_check_exception(struct pt_regs *regs)
@@ -782,6 +738,8 @@ void __kprobes program_check_exception(struct pt_regs *regs)
        unsigned int reason = get_reason(regs);
        extern int do_mathemu(struct pt_regs *regs);
 
+       /* We can now get here via a FP Unavailable exception if the core
+        * has no FPU, in that case no reason flags will be set */
 #ifdef CONFIG_MATH_EMULATION
        /* (reason & REASON_ILLEGAL) would be the obvious thing here,
         * but there seems to be a hardware bug on the 405GP (RevD)
@@ -808,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                        return;
                if (debugger_bpt(regs))
                        return;
-               if (check_bug_trap(regs)) {
+
+               if (!(regs->msr & MSR_PR) &&  /* not user-mode */
+                   report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
                        regs->nip += 4;
                        return;
                }
index c913ad5..a4b28c7 100644 (file)
@@ -264,7 +264,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 
 
        /* Allocate a VMA structure and fill it up */
-       vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
        if (vma == NULL) {
                rc = -ENOMEM;
                goto fail_mmapsem;
index e8342d8..04b8e71 100644 (file)
@@ -33,6 +33,7 @@ SECTIONS
 
        /* Text and gots */
        .text : {
+               _text = .;
                *(.text .text.*)
                SCHED_TEXT
                LOCK_TEXT
@@ -61,11 +62,7 @@ SECTIONS
                __stop___ex_table = .;
        }
 
-       __bug_table : {
-               __start___bug_table = .;
-               *(__bug_table)
-               __stop___bug_table = .;
-       }
+       BUG_TABLE
 
 /*
  * Init sections discarded at runtime
index 506d897..89c836d 100644 (file)
@@ -146,6 +146,11 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return hugepte_offset(hpdp, addr);
 }
 
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       return 0;
+}
+
 static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
 {
        pte_t *hugepte = hugepd_page(*hpdp);
@@ -1042,7 +1047,7 @@ repeat:
        return err;
 }
 
-static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
 {
        memset(addr, 0, kmem_cache_size(cache));
 }
index 9a17854..d12a87e 100644 (file)
@@ -141,7 +141,7 @@ static int __init setup_kcore(void)
 }
 module_init(setup_kcore);
 
-static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
 {
        memset(addr, 0, kmem_cache_size(cache));
 }
@@ -166,9 +166,9 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
 /* Hugepages need one extra cache, initialized in hugetlbpage.c.  We
  * can't put into the tables above, because HPAGE_SHIFT is not compile
  * time constant. */
-kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
 #else
-kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
 #endif
 
 void pgtable_cache_init(void)
index 9da01dc..2627909 100644 (file)
@@ -295,6 +295,63 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start,
        return lmb_end_of_DRAM() - start;
 }
 
+/*
+ * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
+ * node.  This assumes n_mem_{addr,size}_cells have been set.
+ */
+static void __init parse_drconf_memory(struct device_node *memory)
+{
+       const unsigned int *lm, *dm, *aa;
+       unsigned int ls, ld, la;
+       unsigned int n, aam, aalen;
+       unsigned long lmb_size, size;
+       int nid, default_nid = 0;
+       unsigned int start, ai, flags;
+
+       lm = get_property(memory, "ibm,lmb-size", &ls);
+       dm = get_property(memory, "ibm,dynamic-memory", &ld);
+       aa = get_property(memory, "ibm,associativity-lookup-arrays", &la);
+       if (!lm || !dm || !aa ||
+           ls < sizeof(unsigned int) || ld < sizeof(unsigned int) ||
+           la < 2 * sizeof(unsigned int))
+               return;
+
+       lmb_size = read_n_cells(n_mem_size_cells, &lm);
+       n = *dm++;              /* number of LMBs */
+       aam = *aa++;            /* number of associativity lists */
+       aalen = *aa++;          /* length of each associativity list */
+       if (ld < (n * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int) ||
+           la < (aam * aalen + 2) * sizeof(unsigned int))
+               return;
+
+       for (; n != 0; --n) {
+               start = read_n_cells(n_mem_addr_cells, &dm);
+               ai = dm[2];
+               flags = dm[3];
+               dm += 4;
+               /* 0x80 == reserved, 0x8 = assigned to us */
+               if ((flags & 0x80) || !(flags & 0x8))
+                       continue;
+               nid = default_nid;
+               /* flags & 0x40 means associativity index is invalid */
+               if (min_common_depth > 0 && min_common_depth <= aalen &&
+                   (flags & 0x40) == 0 && ai < aam) {
+                       /* this is like of_node_to_nid_single */
+                       nid = aa[ai * aalen + min_common_depth - 1];
+                       if (nid == 0xffff || nid >= MAX_NUMNODES)
+                               nid = default_nid;
+               }
+               node_set_online(nid);
+
+               size = numa_enforce_memory_limit(start, lmb_size);
+               if (!size)
+                       continue;
+
+               add_active_range(nid, start >> PAGE_SHIFT,
+                                (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
+       }
+}
+
 static int __init parse_numa_properties(void)
 {
        struct device_node *cpu = NULL;
@@ -385,6 +442,14 @@ new_range:
                        goto new_range;
        }
 
+       /*
+        * Now do the same thing for each LMB listed in the ibm,dynamic-memory
+        * property in the ibm,dynamic-reconfiguration-memory node.
+        */
+       memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+       if (memory)
+               parse_drconf_memory(memory);
+
        return 0;
 }
 
index a375c15..eaff71e 100644 (file)
@@ -40,8 +40,6 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
 #include <asm/of_platform.h>
 
 #include <asm/mpc52xx.h>
index 616a0a3..70e0d96 100644 (file)
@@ -115,6 +115,7 @@ static struct sysdev_attribute attr_spu_temperature = {
 
 static struct attribute *spu_attributes[] = {
        &attr_spu_temperature.attr,
+       NULL,
 };
 
 static struct attribute_group spu_attribute_group = {
@@ -135,6 +136,7 @@ static struct sysdev_attribute attr_ppe_temperature1 = {
 static struct attribute *ppe_attributes[] = {
        &attr_ppe_temperature0.attr,
        &attr_ppe_temperature1.attr,
+       NULL,
 };
 
 static struct attribute_group ppe_attribute_group = {
index 99c6120..d04ae16 100644 (file)
@@ -382,11 +382,14 @@ static irqreturn_t cbe_pm_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int __init cbe_init_pm_irq(void)
+static int __init cbe_init_pm_irq(void)
 {
        unsigned int irq;
        int rc, node;
 
+       if (!machine_is(cell))
+               return 0;
+
        for_each_node(node) {
                irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
                                               (node << IIC_IRQ_NODE_SHIFT));
index 26945c4..725e195 100644 (file)
@@ -147,7 +147,7 @@ static int spufs_arch_notes_size(void)
        struct fdtable *fdt = files_fdtable(current->files);
        int size = 0, fd;
 
-       for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) {
+       for (fd = 0; fd < fdt->max_fds; fd++) {
                if (FD_ISSET(fd, fdt->open_fds)) {
                        struct file *file = fcheck(fd);
 
index c7d0107..738b924 100644 (file)
@@ -40,7 +40,7 @@
 
 #include "spufs.h"
 
-static kmem_cache_t *spufs_inode_cache;
+static struct kmem_cache *spufs_inode_cache;
 char *isolated_loader;
 
 static struct inode *
@@ -48,7 +48,7 @@ spufs_alloc_inode(struct super_block *sb)
 {
        struct spufs_inode_info *ei;
 
-       ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL);
+       ei = kmem_cache_alloc(spufs_inode_cache, GFP_KERNEL);
        if (!ei)
                return NULL;
 
@@ -65,7 +65,7 @@ spufs_destroy_inode(struct inode *inode)
 }
 
 static void
-spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags)
+spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags)
 {
        struct spufs_inode_info *ei = p;
 
@@ -205,7 +205,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
        struct dentry *dir;
        int ret;
 
-       dir = file->f_dentry;
+       dir = file->f_path.dentry;
        parent = dir->d_parent->d_inode;
        ctx = SPUFS_I(dir->d_inode)->i_ctx;
 
@@ -363,7 +363,7 @@ static int spufs_gang_close(struct inode *inode, struct file *file)
        struct dentry *dir;
        int ret;
 
-       dir = file->f_dentry;
+       dir = file->f_path.dentry;
        parent = dir->d_parent->d_inode;
 
        ret = spufs_rmgang(parent, dir);
index a6d1ae4..8e37bdf 100644 (file)
@@ -46,7 +46,7 @@ static long do_spu_run(struct file *filp,
        if (filp->f_op != &spufs_context_fops)
                goto out;
 
-       i = SPUFS_I(filp->f_dentry->d_inode);
+       i = SPUFS_I(filp->f_path.dentry->d_inode);
        ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
 
        if (put_user(npc, unpc))
index 31bcdae..0e83776 100644 (file)
@@ -14,7 +14,7 @@ static unsigned long avr_clock;
 
 static struct work_struct wd_work;
 
-static void wd_stop(void *unused)
+static void wd_stop(struct work_struct *unused)
 {
        const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK";
        int i = 0, rescue = 8;
@@ -122,7 +122,7 @@ static int __init ls_uarts_init(void)
 
        ls_uart_init();
 
-       INIT_WORK(&wd_work, wd_stop, NULL);
+       INIT_WORK(&wd_work, wd_stop);
        schedule_work(&wd_work);
 
        return 0;
index b5737d6..cff15ae 100644 (file)
@@ -1178,7 +1178,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
                                      const char __user *buf,
                                      size_t count, loff_t *ppos)
 {
-       struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
        ssize_t rc;
        dma_addr_t dma_addr;
        char *page;
index 3a32ded..3f6a69f 100644 (file)
@@ -562,7 +562,7 @@ void __init maple_pci_init(void)
        for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
                if (np->name == NULL)
                        continue;
-               if (strcmp(np->name, "pci") == 0) {
+               if (!strcmp(np->name, "pci") || !strcmp(np->name, "pcie")) {
                        if (add_bridge(np) == 0)
                                of_node_get(np);
                }
index 094989d..f12d5c6 100644 (file)
@@ -60,6 +60,7 @@
 #include <asm/of_device.h>
 #include <asm/lmb.h>
 #include <asm/mpic.h>
+#include <asm/rtas.h>
 #include <asm/udbg.h>
 
 #include "maple.h"
@@ -166,6 +167,16 @@ struct smp_ops_t maple_smp_ops = {
 };
 #endif /* CONFIG_SMP */
 
+static void __init maple_use_rtas_reboot_and_halt_if_present(void)
+{
+       if (rtas_service_present("system-reboot") &&
+           rtas_service_present("power-off")) {
+               ppc_md.restart = rtas_restart;
+               ppc_md.power_off = rtas_power_off;
+               ppc_md.halt = rtas_halt;
+       }
+}
+
 void __init maple_setup_arch(void)
 {
        /* init to some ~sane value until calibrate_delay() runs */
@@ -181,6 +192,7 @@ void __init maple_setup_arch(void)
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
 #endif
+       maple_use_rtas_reboot_and_halt_if_present();
 
        printk(KERN_DEBUG "Using native/NAP idle loop\n");
 }
index afa593a..c3a8941 100644 (file)
 
 #define OLD_BACKLIGHT_MAX 15
 
-static void pmac_backlight_key_worker(void *data);
-static void pmac_backlight_set_legacy_worker(void *data);
+static void pmac_backlight_key_worker(struct work_struct *work);
+static void pmac_backlight_set_legacy_worker(struct work_struct *work);
 
-static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
-static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL);
+static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker);
+static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker);
 
 /* Although these variables are used in interrupt context, it makes no sense to
  * protect them. No user is able to produce enough key events per second and
@@ -94,7 +94,7 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value)
        return level;
 }
 
-static void pmac_backlight_key_worker(void *data)
+static void pmac_backlight_key_worker(struct work_struct *work)
 {
        if (atomic_read(&kernel_backlight_disabled))
                return;
@@ -166,7 +166,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
        return error;
 }
 
-static void pmac_backlight_set_legacy_worker(void *data)
+static void pmac_backlight_set_legacy_worker(struct work_struct *work)
 {
        if (atomic_read(&kernel_backlight_disabled))
                return;
index 451bfcd..de52ec4 100644 (file)
@@ -40,4 +40,15 @@ config PS3_USE_LPAR_ADDR
 
          If you have any doubt, choose the default y.
 
+config PS3_VUART
+       depends on PPC_PS3
+       bool "PS3 Virtual UART support"
+       default y
+       help
+         Include support for the PS3 Virtual UART.
+
+         This support is required for several system services
+         including the System Manager and AV Settings.  In
+         general, all users will say Y.
+
 endmenu
index 997243a..69590fb 100644 (file)
@@ -10,6 +10,8 @@ obj-$(CONFIG_XICS)    += xics.o
 obj-$(CONFIG_SCANLOG)  += scanlog.o
 obj-$(CONFIG_EEH)      += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
 
+obj-$(CONFIG_HOTPLUG_CPU)      += hotplug-cpu.o
+
 obj-$(CONFIG_HVC_CONSOLE)      += hvconsole.o
 obj-$(CONFIG_HVCS)             += hvcserver.o
 obj-$(CONFIG_HCALL_STATS)      += hvCall_inst.o
index 3c2d63e..da6e536 100644 (file)
@@ -337,6 +337,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
                        printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n",
                                pdn->eeh_check_count);
                        dump_stack();
+                       msleep(5000);
                        
                        /* re-read the slot reset state */
                        if (read_slot_reset_state(pdn, rets) != 0)
index c2bc990..cbd6b07 100644 (file)
@@ -170,14 +170,19 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
 static void eeh_report_resume(struct pci_dev *dev, void *userdata)
 {
        struct pci_driver *driver = dev->driver;
+       struct device_node *dn = pci_device_to_OF_node(dev);
 
        dev->error_state = pci_channel_io_normal;
 
        if (!driver)
                return;
-       if (!driver->err_handler)
-               return;
-       if (!driver->err_handler->resume)
+
+       if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+               PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+               enable_irq(dev->irq);
+       }
+       if (!driver->err_handler ||
+           !driver->err_handler->resume)
                return;
 
        driver->err_handler->resume(dev);
@@ -407,6 +412,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
 
                if (rc)
                        result = PCI_ERS_RESULT_NEED_RESET;
+               else
+                       result = PCI_ERS_RESULT_RECOVERED;
        }
 
        /* If any device has a hard failure, then shut off everything. */
index 1370774..49037ed 100644 (file)
@@ -37,8 +37,8 @@
 /* EEH event workqueue setup. */
 static DEFINE_SPINLOCK(eeh_eventlist_lock);
 LIST_HEAD(eeh_eventlist);
-static void eeh_thread_launcher(void *);
-DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
+static void eeh_thread_launcher(struct work_struct *);
+DECLARE_WORK(eeh_event_wq, eeh_thread_launcher);
 
 /* Serialize reset sequences for a given pci device */
 DEFINE_MUTEX(eeh_event_mutex);
@@ -103,7 +103,7 @@ static int eeh_event_handler(void * dummy)
  * eeh_thread_launcher
  * @dummy - unused
  */
-static void eeh_thread_launcher(void *dummy)
+static void eeh_thread_launcher(struct work_struct *dummy)
 {
        if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0)
                printk(KERN_ERR "Failed to start EEH daemon\n");
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
new file mode 100644 (file)
index 0000000..f460b9c
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * pseries CPU Hotplug infrastructure.
+ *
+ * Split out from arch/powerpc/platforms/pseries/setup.c
+ *  arch/powerpc/kernel/rtas.c, and arch/powerpc/platforms/pseries/smp.c
+ *
+ * Peter Bergner, IBM  March 2001.
+ * Copyright (C) 2001 IBM.
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ * Plus various changes from other IBM teams...
+ *
+ * Copyright (C) 2006 Michael Ellerman, IBM Corporation
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/firmware.h>
+#include <asm/machdep.h>
+#include <asm/vdso_datapage.h>
+#include <asm/pSeries_reconfig.h>
+#include "xics.h"
+
+/* This version can't take the spinlock, because it never returns */
+static struct rtas_args rtas_stop_self_args = {
+       .token = RTAS_UNKNOWN_SERVICE,
+       .nargs = 0,
+       .nret = 1,
+       .rets = &rtas_stop_self_args.args[0],
+};
+
+static void rtas_stop_self(void)
+{
+       struct rtas_args *args = &rtas_stop_self_args;
+
+       local_irq_disable();
+
+       BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+
+       printk("cpu %u (hwid %u) Ready to die...\n",
+              smp_processor_id(), hard_smp_processor_id());
+       enter_rtas(__pa(args));
+
+       panic("Alas, I survived.\n");
+}
+
+static void pseries_mach_cpu_die(void)
+{
+       local_irq_disable();
+       idle_task_exit();
+       xics_teardown_cpu(0);
+       rtas_stop_self();
+       /* Should never get here... */
+       BUG();
+       for(;;);
+}
+
+static int qcss_tok;   /* query-cpu-stopped-state token */
+
+/* Get state of physical CPU.
+ * Return codes:
+ *     0       - The processor is in the RTAS stopped state
+ *     1       - stop-self is in progress
+ *     2       - The processor is not in the RTAS stopped state
+ *     -1      - Hardware Error
+ *     -2      - Hardware Busy, Try again later.
+ */
+static int query_cpu_stopped(unsigned int pcpu)
+{
+       int cpu_status, status;
+
+       status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+       if (status != 0) {
+               printk(KERN_ERR
+                      "RTAS query-cpu-stopped-state failed: %i\n", status);
+               return status;
+       }
+
+       return cpu_status;
+}
+
+static int pseries_cpu_disable(void)
+{
+       int cpu = smp_processor_id();
+
+       cpu_clear(cpu, cpu_online_map);
+       vdso_data->processorCount--;
+
+       /*fix boot_cpuid here*/
+       if (cpu == boot_cpuid)
+               boot_cpuid = any_online_cpu(cpu_online_map);
+
+       /* FIXME: abstract this to not be platform specific later on */
+       xics_migrate_irqs_away();
+       return 0;
+}
+
+static void pseries_cpu_die(unsigned int cpu)
+{
+       int tries;
+       int cpu_status;
+       unsigned int pcpu = get_hard_smp_processor_id(cpu);
+
+       for (tries = 0; tries < 25; tries++) {
+               cpu_status = query_cpu_stopped(pcpu);
+               if (cpu_status == 0 || cpu_status == -1)
+                       break;
+               msleep(200);
+       }
+       if (cpu_status != 0) {
+               printk("Querying DEAD? cpu %i (%i) shows %i\n",
+                      cpu, pcpu, cpu_status);
+       }
+
+       /* Isolation and deallocation are definatly done by
+        * drslot_chrp_cpu.  If they were not they would be
+        * done here.  Change isolate state to Isolate and
+        * change allocation-state to Unusable.
+        */
+       paca[cpu].cpu_start = 0;
+}
+
+/*
+ * Update cpu_present_map and paca(s) for a new cpu node.  The wrinkle
+ * here is that a cpu device node may represent up to two logical cpus
+ * in the SMT case.  We must honor the assumption in other code that
+ * the logical ids for sibling SMT threads x and y are adjacent, such
+ * that x^1 == y and y^1 == x.
+ */
+static int pseries_add_processor(struct device_node *np)
+{
+       unsigned int cpu;
+       cpumask_t candidate_map, tmp = CPU_MASK_NONE;
+       int err = -ENOSPC, len, nthreads, i;
+       const u32 *intserv;
+
+       intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+       if (!intserv)
+               return 0;
+
+       nthreads = len / sizeof(u32);
+       for (i = 0; i < nthreads; i++)
+               cpu_set(i, tmp);
+
+       lock_cpu_hotplug();
+
+       BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
+
+       /* Get a bitmap of unoccupied slots. */
+       cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
+       if (cpus_empty(candidate_map)) {
+               /* If we get here, it most likely means that NR_CPUS is
+                * less than the partition's max processors setting.
+                */
+               printk(KERN_ERR "Cannot add cpu %s; this system configuration"
+                      " supports %d logical cpus.\n", np->full_name,
+                      cpus_weight(cpu_possible_map));
+               goto out_unlock;
+       }
+
+       while (!cpus_empty(tmp))
+               if (cpus_subset(tmp, candidate_map))
+                       /* Found a range where we can insert the new cpu(s) */
+                       break;
+               else
+                       cpus_shift_left(tmp, tmp, nthreads);
+
+       if (cpus_empty(tmp)) {
+               printk(KERN_ERR "Unable to find space in cpu_present_map for"
+                      " processor %s with %d thread(s)\n", np->name,
+                      nthreads);
+               goto out_unlock;
+       }
+
+       for_each_cpu_mask(cpu, tmp) {
+               BUG_ON(cpu_isset(cpu, cpu_present_map));
+               cpu_set(cpu, cpu_present_map);
+               set_hard_smp_processor_id(cpu, *intserv++);
+       }
+       err = 0;
+out_unlock:
+       unlock_cpu_hotplug();
+       return err;
+}
+
+/*
+ * Update the present map for a cpu node which is going away, and set
+ * the hard id in the paca(s) to -1 to be consistent with boot time
+ * convention for non-present cpus.
+ */
+static void pseries_remove_processor(struct device_node *np)
+{
+       unsigned int cpu;
+       int len, nthreads, i;
+       const u32 *intserv;
+
+       intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+       if (!intserv)
+               return;
+
+       nthreads = len / sizeof(u32);
+
+       lock_cpu_hotplug();
+       for (i = 0; i < nthreads; i++) {
+               for_each_present_cpu(cpu) {
+                       if (get_hard_smp_processor_id(cpu) != intserv[i])
+                               continue;
+                       BUG_ON(cpu_online(cpu));
+                       cpu_clear(cpu, cpu_present_map);
+                       set_hard_smp_processor_id(cpu, -1);
+                       break;
+               }
+               if (cpu == NR_CPUS)
+                       printk(KERN_WARNING "Could not find cpu to remove "
+                              "with physical id 0x%x\n", intserv[i]);
+       }
+       unlock_cpu_hotplug();
+}
+
+static int pseries_smp_notifier(struct notifier_block *nb,
+                               unsigned long action, void *node)
+{
+       int err = NOTIFY_OK;
+
+       switch (action) {
+       case PSERIES_RECONFIG_ADD:
+               if (pseries_add_processor(node))
+                       err = NOTIFY_BAD;
+               break;
+       case PSERIES_RECONFIG_REMOVE:
+               pseries_remove_processor(node);
+               break;
+       default:
+               err = NOTIFY_DONE;
+               break;
+       }
+       return err;
+}
+
+static struct notifier_block pseries_smp_nb = {
+       .notifier_call = pseries_smp_notifier,
+};
+
+static int __init pseries_cpu_hotplug_init(void)
+{
+       rtas_stop_self_args.token = rtas_token("stop-self");
+       qcss_tok = rtas_token("query-cpu-stopped-state");
+
+       if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+                       qcss_tok == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_INFO "CPU Hotplug not supported by firmware "
+                               "- disabling.\n");
+               return 0;
+       }
+
+       ppc_md.cpu_die = pseries_mach_cpu_die;
+       smp_ops->cpu_disable = pseries_cpu_disable;
+       smp_ops->cpu_die = pseries_cpu_die;
+
+       /* Processors can be added/removed only on LPAR */
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               pSeries_reconfig_notifier_register(&pseries_smp_nb);
+
+       return 0;
+}
+arch_initcall(pseries_cpu_hotplug_init);
index 446e17d..80181c4 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->i_private;
+       seq->private = file->f_path.dentry->d_inode->i_private;
 
        return rc;
 }
index 77a5bb1..45368a5 100644 (file)
@@ -47,7 +47,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump;       /* The proc file */
 static ssize_t scanlog_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
-        struct inode * inode = file->f_dentry->d_inode;
+        struct inode * inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry *dp;
        unsigned int *data;
        int status;
index 0dc2548..042ecae 100644 (file)
@@ -347,21 +347,6 @@ static int __init pSeries_init_panel(void)
 }
 arch_initcall(pSeries_init_panel);
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void pSeries_mach_cpu_die(void)
-{
-       local_irq_disable();
-       idle_task_exit();
-       xics_teardown_cpu(0);
-       rtas_stop_self();
-       /* Should never get here... */
-       BUG();
-       for(;;);
-}
-#else
-#define pSeries_mach_cpu_die NULL
-#endif
-
 static int pseries_set_dabr(unsigned long dabr)
 {
        return plpar_hcall_norets(H_SET_DABR, dabr);
@@ -437,19 +422,14 @@ static int __init pSeries_probe_hypertas(unsigned long node,
        if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
                powerpc_firmware_features |= FW_FEATURE_LPAR;
 
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               hpte_init_lpar();
-       else
-               hpte_init_native();
-
        return 1;
 }
 
 static int __init pSeries_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
-       char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "device_type", NULL);
+       char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
+
        if (dtype == NULL)
                return 0;
        if (strcmp(dtype, "chrp"))
@@ -467,6 +447,11 @@ static int __init pSeries_probe(void)
        /* Now try to figure out if we are running on LPAR */
        of_scan_flat_dt(pSeries_probe_hypertas, NULL);
 
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               hpte_init_lpar();
+       else
+               hpte_init_native();
+
        DBG("Machine is%s LPAR !\n",
            (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
 
@@ -561,7 +546,6 @@ define_machine(pseries) {
        .power_off              = rtas_power_off,
        .halt                   = rtas_halt,
        .panic                  = rtas_os_term,
-       .cpu_die                = pSeries_mach_cpu_die,
        .get_boot_time          = rtas_get_boot_time,
        .get_rtc_time           = rtas_get_rtc_time,
        .set_rtc_time           = rtas_set_rtc_time,
index c6624b8..4408518 100644 (file)
@@ -64,197 +64,6 @@ static cpumask_t of_spin_map;
 
 extern void generic_secondary_smp_init(unsigned long);
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-/* Get state of physical CPU.
- * Return codes:
- *     0       - The processor is in the RTAS stopped state
- *     1       - stop-self is in progress
- *     2       - The processor is not in the RTAS stopped state
- *     -1      - Hardware Error
- *     -2      - Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
-       int cpu_status;
-       int status, qcss_tok;
-
-       qcss_tok = rtas_token("query-cpu-stopped-state");
-       if (qcss_tok == RTAS_UNKNOWN_SERVICE)
-               return -1;
-       status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-       if (status != 0) {
-               printk(KERN_ERR
-                      "RTAS query-cpu-stopped-state failed: %i\n", status);
-               return status;
-       }
-
-       return cpu_status;
-}
-
-static int pSeries_cpu_disable(void)
-{
-       int cpu = smp_processor_id();
-
-       cpu_clear(cpu, cpu_online_map);
-       vdso_data->processorCount--;
-
-       /*fix boot_cpuid here*/
-       if (cpu == boot_cpuid)
-               boot_cpuid = any_online_cpu(cpu_online_map);
-
-       /* FIXME: abstract this to not be platform specific later on */
-       xics_migrate_irqs_away();
-       return 0;
-}
-
-static void pSeries_cpu_die(unsigned int cpu)
-{
-       int tries;
-       int cpu_status;
-       unsigned int pcpu = get_hard_smp_processor_id(cpu);
-
-       for (tries = 0; tries < 25; tries++) {
-               cpu_status = query_cpu_stopped(pcpu);
-               if (cpu_status == 0 || cpu_status == -1)
-                       break;
-               msleep(200);
-       }
-       if (cpu_status != 0) {
-               printk("Querying DEAD? cpu %i (%i) shows %i\n",
-                      cpu, pcpu, cpu_status);
-       }
-
-       /* Isolation and deallocation are definatly done by
-        * drslot_chrp_cpu.  If they were not they would be
-        * done here.  Change isolate state to Isolate and
-        * change allocation-state to Unusable.
-        */
-       paca[cpu].cpu_start = 0;
-}
-
-/*
- * Update cpu_present_map and paca(s) for a new cpu node.  The wrinkle
- * here is that a cpu device node may represent up to two logical cpus
- * in the SMT case.  We must honor the assumption in other code that
- * the logical ids for sibling SMT threads x and y are adjacent, such
- * that x^1 == y and y^1 == x.
- */
-static int pSeries_add_processor(struct device_node *np)
-{
-       unsigned int cpu;
-       cpumask_t candidate_map, tmp = CPU_MASK_NONE;
-       int err = -ENOSPC, len, nthreads, i;
-       const u32 *intserv;
-
-       intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
-       if (!intserv)
-               return 0;
-
-       nthreads = len / sizeof(u32);
-       for (i = 0; i < nthreads; i++)
-               cpu_set(i, tmp);
-
-       lock_cpu_hotplug();
-
-       BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
-
-       /* Get a bitmap of unoccupied slots. */
-       cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
-       if (cpus_empty(candidate_map)) {
-               /* If we get here, it most likely means that NR_CPUS is
-                * less than the partition's max processors setting.
-                */
-               printk(KERN_ERR "Cannot add cpu %s; this system configuration"
-                      " supports %d logical cpus.\n", np->full_name,
-                      cpus_weight(cpu_possible_map));
-               goto out_unlock;
-       }
-
-       while (!cpus_empty(tmp))
-               if (cpus_subset(tmp, candidate_map))
-                       /* Found a range where we can insert the new cpu(s) */
-                       break;
-               else
-                       cpus_shift_left(tmp, tmp, nthreads);
-
-       if (cpus_empty(tmp)) {
-               printk(KERN_ERR "Unable to find space in cpu_present_map for"
-                      " processor %s with %d thread(s)\n", np->name,
-                      nthreads);
-               goto out_unlock;
-       }
-
-       for_each_cpu_mask(cpu, tmp) {
-               BUG_ON(cpu_isset(cpu, cpu_present_map));
-               cpu_set(cpu, cpu_present_map);
-               set_hard_smp_processor_id(cpu, *intserv++);
-       }
-       err = 0;
-out_unlock:
-       unlock_cpu_hotplug();
-       return err;
-}
-
-/*
- * Update the present map for a cpu node which is going away, and set
- * the hard id in the paca(s) to -1 to be consistent with boot time
- * convention for non-present cpus.
- */
-static void pSeries_remove_processor(struct device_node *np)
-{
-       unsigned int cpu;
-       int len, nthreads, i;
-       const u32 *intserv;
-
-       intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
-       if (!intserv)
-               return;
-
-       nthreads = len / sizeof(u32);
-
-       lock_cpu_hotplug();
-       for (i = 0; i < nthreads; i++) {
-               for_each_present_cpu(cpu) {
-                       if (get_hard_smp_processor_id(cpu) != intserv[i])
-                               continue;
-                       BUG_ON(cpu_online(cpu));
-                       cpu_clear(cpu, cpu_present_map);
-                       set_hard_smp_processor_id(cpu, -1);
-                       break;
-               }
-               if (cpu == NR_CPUS)
-                       printk(KERN_WARNING "Could not find cpu to remove "
-                              "with physical id 0x%x\n", intserv[i]);
-       }
-       unlock_cpu_hotplug();
-}
-
-static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node)
-{
-       int err = NOTIFY_OK;
-
-       switch (action) {
-       case PSERIES_RECONFIG_ADD:
-               if (pSeries_add_processor(node))
-                       err = NOTIFY_BAD;
-               break;
-       case PSERIES_RECONFIG_REMOVE:
-               pSeries_remove_processor(node);
-               break;
-       default:
-               err = NOTIFY_DONE;
-               break;
-       }
-       return err;
-}
-
-static struct notifier_block pSeries_smp_nb = {
-       .notifier_call = pSeries_smp_notifier,
-};
-
-#endif /* CONFIG_HOTPLUG_CPU */
-
 /**
  * smp_startup_cpu() - start the given cpu
  *
@@ -422,15 +231,6 @@ static void __init smp_init_pseries(void)
 
        DBG(" -> smp_init_pSeries()\n");
 
-#ifdef CONFIG_HOTPLUG_CPU
-       smp_ops->cpu_disable = pSeries_cpu_disable;
-       smp_ops->cpu_die = pSeries_cpu_die;
-
-       /* Processors can be added/removed only on LPAR */
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               pSeries_reconfig_notifier_register(&pSeries_smp_nb);
-#endif
-
        /* Mark threads which are still spinning in hold loops. */
        if (cpu_has_feature(CPU_FTR_SMT)) {
                for_each_present_cpu(i) { 
index 6cc3459..04d4917 100644 (file)
@@ -5,7 +5,8 @@ endif
 obj-$(CONFIG_MPIC)             += mpic.o
 obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
-obj-$(CONFIG_PPC_DCR)          += dcr.o dcr-low.o
+obj-$(CONFIG_PPC_DCR)          += dcr.o
+obj-$(CONFIG_PPC_DCR_NATIVE)   += dcr-low.o
 obj-$(CONFIG_U3_DART)          += dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)       += mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S
deleted file mode 100644 (file)
index 2078f39..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * "Indirect" DCR access
- *
- * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of  the GNU General Public License as published by the
- * Free Software Foundation;  either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-
-#define DCR_ACCESS_PROLOG(table) \
-       rlwinm  r3,r3,4,18,27;   \
-       lis     r5,table@h;      \
-       ori     r5,r5,table@l;   \
-       add     r3,r3,r5;        \
-       mtctr   r3;              \
-       bctr
-
-_GLOBAL(__mfdcr)
-       DCR_ACCESS_PROLOG(__mfdcr_table)
-
-_GLOBAL(__mtdcr)
-       DCR_ACCESS_PROLOG(__mtdcr_table)
-
-__mfdcr_table:
-       mfdcr  r3,0; blr
-__mtdcr_table:
-       mtdcr  0,r4; blr
-
-dcr     = 1
-        .rept   1023
-       mfdcr   r3,dcr; blr
-       mtdcr   dcr,r4; blr
-       dcr     = dcr + 1
-       .endr
index 6995f51..74e48d9 100644 (file)
@@ -223,23 +223,15 @@ static void qe_ic_mask_irq(unsigned int virq)
        qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
                    temp & ~qe_ic_info[src].mask);
 
-       spin_unlock_irqrestore(&qe_ic_lock, flags);
-}
-
-static void qe_ic_mask_irq_and_ack(unsigned int virq)
-{
-       struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-       unsigned int src = virq_to_hw(virq);
-       unsigned long flags;
-       u32 temp;
-
-       spin_lock_irqsave(&qe_ic_lock, flags);
-
-       temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
-       qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
-                   temp & ~qe_ic_info[src].mask);
-
-       /* There is nothing to do for ack here, ack is handled in ISR */
+       /* Flush the above write before enabling interrupts; otherwise,
+        * spurious interrupts will sometimes happen.  To be 100% sure
+        * that the write has reached the device before interrupts are
+        * enabled, the mask register would have to be read back; however,
+        * this is not required for correctness, only to avoid wasting
+        * time on a large number of spurious interrupts.  In testing,
+        * a sync reduced the observed spurious interrupts to zero.
+        */
+       mb();
 
        spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
@@ -248,7 +240,7 @@ static struct irq_chip qe_ic_irq_chip = {
        .typename = " QEIC  ",
        .unmask = qe_ic_unmask_irq,
        .mask = qe_ic_mask_irq,
-       .mask_ack = qe_ic_mask_irq_and_ack,
+       .mask_ack = qe_ic_mask_irq,
 };
 
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
@@ -331,34 +323,22 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
        return irq_linear_revmap(qe_ic->irqhost, irq);
 }
 
-/* FIXME: We mask all the QE Low interrupts while handling.  We should
- * let other interrupt come in, but BAD interrupts are generated */
 void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = desc->handler_data;
-       struct irq_chip *chip = irq_desc[irq].chip;
-
        unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
 
-       chip->mask_ack(irq);
        if (cascade_irq != NO_IRQ)
                generic_handle_irq(cascade_irq);
-       chip->unmask(irq);
 }
 
-/* FIXME: We mask all the QE High interrupts while handling.  We should
- * let other interrupt come in, but BAD interrupts are generated */
 void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = desc->handler_data;
-       struct irq_chip *chip = irq_desc[irq].chip;
-
        unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
 
-       chip->mask_ack(irq);
        if (cascade_irq != NO_IRQ)
                generic_handle_irq(cascade_irq);
-       chip->unmask(irq);
 }
 
 void __init qe_ic_init(struct device_node *node, unsigned int flags)
index bf5b3f1..c855a3b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <asm/of_device.h>
+#include <asm/of_platform.h>
 
 static int __init powerpc_flash_init(void)
 {
index a34ed49..77540a2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/bug.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -35,7 +36,6 @@
 #include <asm/cputable.h>
 #include <asm/rtas.h>
 #include <asm/sstep.h>
-#include <asm/bug.h>
 #include <asm/irq_regs.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
@@ -1346,7 +1346,7 @@ static void backtrace(struct pt_regs *excp)
 
 static void print_bug_trap(struct pt_regs *regs)
 {
-       struct bug_entry *bug;
+       const struct bug_entry *bug;
        unsigned long addr;
 
        if (regs->msr & MSR_PR)
@@ -1357,11 +1357,11 @@ static void print_bug_trap(struct pt_regs *regs)
        bug = find_bug(regs->nip);
        if (bug == NULL)
                return;
-       if (bug->line & BUG_WARNING_TRAP)
+       if (is_warning_bug(bug))
                return;
 
-       printf("kernel BUG in %s at %s:%d!\n",
-              bug->function, bug->file, (unsigned int)bug->line);
+       printf("kernel BUG at %s:%u!\n",
+              bug->file, bug->line);
 }
 
 void excprint(struct pt_regs *fp)
index 2e1943e..709952c 100644 (file)
@@ -385,6 +385,7 @@ struct fcc_enet_private {
        phy_info_t      *phy;
        struct work_struct phy_relink;
        struct work_struct phy_display_config;
+       struct net_device *dev;
 
        uint    sequence_done;
 
@@ -1391,10 +1392,11 @@ static phy_info_t *phy_info[] = {
        NULL
 };
 
-static void mii_display_status(void *data)
+static void mii_display_status(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       volatile struct fcc_enet_private *fep = dev->priv;
+       volatile struct fcc_enet_private *fep =
+               container_of(work, struct fcc_enet_private, phy_relink);
+       struct net_device *dev = fep->dev;
        uint s = fep->phy_status;
 
        if (!fep->link && !fep->old_link) {
@@ -1428,10 +1430,12 @@ static void mii_display_status(void *data)
        printk(".\n");
 }
 
-static void mii_display_config(void *data)
+static void mii_display_config(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       volatile struct fcc_enet_private *fep = dev->priv;
+       volatile struct fcc_enet_private *fep =
+               container_of(work, struct fcc_enet_private,
+                            phy_display_config);
+       struct net_device *dev = fep->dev;
        uint s = fep->phy_status;
 
        printk("%s: config: auto-negotiation ", dev->name);
@@ -1758,8 +1762,9 @@ static int __init fec_enet_init(void)
                cep->phy_id_done = 0;
                cep->phy_addr = fip->fc_phyaddr;
                mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy);
-               INIT_WORK(&cep->phy_relink, mii_display_status, dev);
-               INIT_WORK(&cep->phy_display_config, mii_display_config, dev);
+               INIT_WORK(&cep->phy_relink, mii_display_status);
+               INIT_WORK(&cep->phy_display_config, mii_display_config);
+               cep->dev = dev;
 #endif /* CONFIG_USE_MDIO */
 
                fip++;
index 959d31c..c71ef3c 100644 (file)
@@ -2165,7 +2165,7 @@ static int sq_release(struct inode *inode, struct file *file)
        int rc = 0;
 
        if (sq.busy)
-               rc = sq_fsync(file, file->f_dentry);
+               rc = sq_fsync(file, file->f_path.dentry);
        sound.soft = sound.dsp;
        sound.hard = sound.dsp;
        sound_silence();
@@ -2218,25 +2218,25 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
                return 0;
        case SNDCTL_DSP_POST:
        case SNDCTL_DSP_SYNC:
-               return sq_fsync(file, file->f_dentry);
+               return sq_fsync(file, file->f_path.dentry);
 
                /* ++TeSche: before changing any of these it's
                 * probably wise to wait until sound playing has
                 * settled down. */
        case SNDCTL_DSP_SPEED:
-               sq_fsync(file, file->f_dentry);
+               sq_fsync(file, file->f_path.dentry);
                IOCTL_IN(arg, data);
                return IOCTL_OUT(arg, sound_set_speed(data));
        case SNDCTL_DSP_STEREO:
-               sq_fsync(file, file->f_dentry);
+               sq_fsync(file, file->f_path.dentry);
                IOCTL_IN(arg, data);
                return IOCTL_OUT(arg, sound_set_stereo(data));
        case SOUND_PCM_WRITE_CHANNELS:
-               sq_fsync(file, file->f_dentry);
+               sq_fsync(file, file->f_path.dentry);
                IOCTL_IN(arg, data);
                return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
        case SNDCTL_DSP_SETFMT:
-               sq_fsync(file, file->f_dentry);
+               sq_fsync(file, file->f_path.dentry);
                IOCTL_IN(arg, data);
                return IOCTL_OUT(arg, sound_set_format(data));
        case SNDCTL_DSP_GETFMTS:
index 2f9fa9e..e6c28fb 100644 (file)
@@ -173,6 +173,7 @@ struct fec_enet_private {
        uint    phy_speed;
        phy_info_t      *phy;
        struct work_struct phy_task;
+       struct net_device *dev;
 
        uint    sequence_done;
 
@@ -1263,10 +1264,11 @@ static void mii_display_status(struct net_device *dev)
        printk(".\n");
 }
 
-static void mii_display_config(void *priv)
+static void mii_display_config(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *)priv;
-       struct fec_enet_private *fep = dev->priv;
+       struct fec_enet_private *fep =
+               container_of(work, struct fec_enet_private, phy_task);
+       struct net_device *dev = fep->dev;
        volatile uint *s = &(fep->phy_status);
 
        printk("%s: config: auto-negotiation ", dev->name);
@@ -1295,10 +1297,11 @@ static void mii_display_config(void *priv)
        fep->sequence_done = 1;
 }
 
-static void mii_relink(void *priv)
+static void mii_relink(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *)priv;
-       struct fec_enet_private *fep = dev->priv;
+       struct fec_enet_private *fep =
+               container_of(work, struct fec_enet_private, phy_task);
+       struct net_device *dev = fep->dev;
        int duplex;
 
        fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
@@ -1325,7 +1328,8 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = dev->priv;
 
-       INIT_WORK(&fep->phy_task, mii_relink, (void *)dev);
+       fep->dev = dev;
+       INIT_WORK(&fep->phy_task, mii_relink);
        schedule_work(&fep->phy_task);
 }
 
@@ -1333,7 +1337,8 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = dev->priv;
 
-       INIT_WORK(&fep->phy_task, mii_display_config, (void *)dev);
+       fep->dev = dev;
+       INIT_WORK(&fep->phy_task, mii_display_config);
        schedule_work(&fep->phy_task);
 }
 
index edf71a4..692b5ba 100644 (file)
@@ -19,6 +19,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default y
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -52,6 +60,11 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
 source "init/Kconfig"
 
 menu "Processor"
index 63808e0..5e723c4 100644 (file)
@@ -879,7 +879,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
 
 
 static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-                                              unsigned long *offset,
+                                              resource_size_t *offset,
                                               enum pci_mmap_state mmap_state)
 {
        struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -891,7 +891,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
 
        /* If memory, add on the PCI bridge address offset */
        if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
                *offset += hose->pci_mem_offset;
+#endif
                res_bit = IORESOURCE_MEM;
        } else {
                io_offset = hose->io_base_virt - ___IO_BASE;
@@ -1030,7 +1032,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state,
                        int write_combine)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
        struct resource *rp;
        int ret;
 
@@ -1132,21 +1134,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
                          resource_size_t *start, resource_size_t *end)
 {
        struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-       unsigned long offset = 0;
+       resource_size_t offset = 0;
 
        if (hose == NULL)
                return;
 
        if (rsrc->flags & IORESOURCE_IO)
-               offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+       /* We pass a fully fixed up address to userland for MMIO instead of
+        * a BAR value because X is lame and expects to be able to use that
+        * to pass to /dev/mem !
+        *
+        * That means that we'll have potentially 64 bits values where some
+        * userland apps only expect 32 (like X itself since it thinks only
+        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+        * 32 bits CHRPs :-(
+        *
+        * Hopefully, the sysfs insterface is immune to that gunk. Once X
+        * has been fixed (and the fix spread enough), we can re-enable the
+        * 2 lines below and pass down a BAR value to userland. In that case
+        * we'll also have to re-enable the matching code in
+        * __pci_mmap_make_offset().
+        *
+        * BenH.
+        */
+#if 0
+       else if (rsrc->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+#endif
 
-       *start = rsrc->start + offset;
-       *end = rsrc->end + offset;
+       *start = rsrc->start - offset;
+       *end = rsrc->end - offset;
 }
 
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
-                 int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+                             resource_size_t end, int flags, char *name)
 {
        res->start = start;
        res->end = end;
index 2f835b9..810f7aa 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/prctl.h>
+#include <linux/bug.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -559,64 +560,9 @@ static void emulate_single_step(struct pt_regs *regs)
        }
 }
 
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x)     NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
-{
-       struct bug_entry *bug;
-
-       for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
-               if (bugaddr == bug->bug_addr)
-                       return bug;
-       return module_find_bug(bugaddr);
-}
-
-int check_bug_trap(struct pt_regs *regs)
+int is_valid_bugaddr(unsigned long addr)
 {
-       struct bug_entry *bug;
-       unsigned long addr;
-
-       if (regs->msr & MSR_PR)
-               return 0;       /* not in kernel */
-       addr = regs->nip;       /* address of trap instruction */
-       if (addr < PAGE_OFFSET)
-               return 0;
-       bug = find_bug(regs->nip);
-       if (bug == NULL)
-               return 0;
-       if (bug->line & BUG_WARNING_TRAP) {
-               /* this is a WARN_ON rather than BUG/BUG_ON */
-#ifdef CONFIG_XMON
-               xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
-                      bug->function, bug->file,
-                      bug->line & ~BUG_WARNING_TRAP);
-#endif /* CONFIG_XMON */               
-               printk(KERN_ERR "Badness in %s at %s:%ld\n",
-                      bug->function, bug->file,
-                      bug->line & ~BUG_WARNING_TRAP);
-               dump_stack();
-               return 1;
-       }
-#ifdef CONFIG_XMON
-       xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-              bug->function, bug->file, bug->line);
-       xmon(regs);
-#endif /* CONFIG_XMON */
-       printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-              bug->function, bug->file, bug->line);
-
-       return 0;
+       return addr >= PAGE_OFFSET;
 }
 
 void program_check_exception(struct pt_regs *regs)
@@ -671,7 +617,9 @@ void program_check_exception(struct pt_regs *regs)
                /* trap exception */
                if (debugger_bpt(regs))
                        return;
-               if (check_bug_trap(regs)) {
+
+               if (!(regs->msr & MSR_PR) &&  /* not user-mode */
+                   report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
                        regs->nip += 4;
                        return;
                }
index 16e8661..6192126 100644 (file)
@@ -31,6 +31,7 @@ SECTIONS
   .plt : { *(.plt) }
   .text      :
   {
+    _text = .;
     *(.text)
     SCHED_TEXT
     LOCK_TEXT
index 583d9ff..ff69056 100644 (file)
@@ -22,6 +22,14 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config GENERIC_HWEIGHT
        bool
        default y
@@ -233,8 +241,14 @@ config WARN_STACK_SIZE
          This allows you to specify the maximum frame size a function may
          have without the compiler complaining about it.
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 source "mm/Kconfig"
 
+config HOLES_IN_ZONE
+       def_bool y
+
 comment "I/O subsystem configuration"
 
 config MACHCHK_WARNING
@@ -258,14 +272,6 @@ config QDIO
 
          If unsure, say Y.
 
-config QDIO_PERF_STATS
-       bool "Performance statistics in /proc"
-       depends on QDIO
-       help
-         Say Y here to get performance statistics in /proc/qdio_perf
-
-         If unsure, say N.
-
 config QDIO_DEBUG
        bool "Extended debugging information"
        depends on QDIO
index af1e8fc..b8c2372 100644 (file)
@@ -92,8 +92,8 @@ static int appldata_timer_active;
  * Work queue
  */
 static struct workqueue_struct *appldata_wq;
-static void appldata_work_fn(void *data);
-static DECLARE_WORK(appldata_work, appldata_work_fn, NULL);
+static void appldata_work_fn(struct work_struct *work);
+static DECLARE_WORK(appldata_work, appldata_work_fn);
 
 
 /*
@@ -125,7 +125,7 @@ static void appldata_timer_function(unsigned long data)
  *
  * call data gathering function for each (active) module
  */
-static void appldata_work_fn(void *data)
+static void appldata_work_fn(struct work_struct *work)
 {
        struct list_head *lh;
        struct appldata_ops *ops;
@@ -561,7 +561,6 @@ appldata_offline_cpu(int cpu)
        spin_unlock(&appldata_timer_lock);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit
 appldata_cpu_notify(struct notifier_block *self,
                    unsigned long action, void *hcpu)
@@ -582,7 +581,6 @@ appldata_cpu_notify(struct notifier_block *self,
 static struct notifier_block appldata_nb = {
        .notifier_call = appldata_cpu_notify,
 };
-#endif
 
 /*
  * appldata_init()
index 7cd51e7..a6ec919 100644 (file)
@@ -134,7 +134,6 @@ CONFIG_RESOURCES_64BIT=y
 #
 CONFIG_MACHCHK_WARNING=y
 CONFIG_QDIO=y
-# CONFIG_QDIO_PERF_STATS is not set
 # CONFIG_QDIO_DEBUG is not set
 
 #
index cd702ae..b6716c4 100644 (file)
@@ -109,7 +109,7 @@ static void hypfs_drop_inode(struct inode *inode)
 
 static int hypfs_open(struct inode *inode, struct file *filp)
 {
-       char *data = filp->f_dentry->d_inode->i_private;
+       char *data = filp->f_path.dentry->d_inode->i_private;
        struct hypfs_sb_info *fs_info;
 
        if (filp->f_mode & FMODE_WRITE) {
@@ -174,7 +174,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct hypfs_sb_info *fs_info;
        size_t count = iov_length(iov, nr_segs);
 
-       sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
+       sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb;
        fs_info = sb->s_fs_info;
        /*
         * Currently we only allow one update per second for two reasons:
index 9565a2d..5c46054 100644 (file)
@@ -176,7 +176,6 @@ struct elf_prpsinfo32
 
 #include <linux/highuid.h>
 
-#define elf_addr_t     u32
 /*
 #define init_elf_binfmt init_elf32_binfmt
 */
index 43f3d0c..ef5266f 100644 (file)
@@ -603,13 +603,13 @@ debug_open(struct inode *inode, struct file *file)
        debug_info_t *debug_info, *debug_info_snapshot;
 
        down(&debug_lock);
-       debug_info = file->f_dentry->d_inode->i_private;
+       debug_info = file->f_path.dentry->d_inode->i_private;
        /* find debug view */
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                if (!debug_info->views[i])
                        continue;
                else if (debug_info->debugfs_entries[i] ==
-                        file->f_dentry) {
+                        file->f_path.dentry) {
                        goto found;     /* found view ! */
                }
        }
index 67914fe..576368c 100644 (file)
@@ -200,7 +200,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, 0);
        mutex_unlock(&kprobe_mutex);
 }
 
index b928fec..49ef206 100644 (file)
@@ -64,9 +64,8 @@ unsigned int console_devno = -1;
 unsigned int console_irq = -1;
 unsigned long machine_flags = 0;
 
-struct mem_chunk memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
-unsigned long __initdata zholes_size[MAX_NR_ZONES];
 static unsigned long __initdata memory_end;
 
 /*
@@ -354,21 +353,6 @@ void machine_power_off(void)
  */
 void (*pm_power_off)(void) = machine_power_off;
 
-static void __init
-add_memory_hole(unsigned long start, unsigned long end)
-{
-       unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
-
-       if (end <= dma_pfn)
-               zholes_size[ZONE_DMA] += end - start + 1;
-       else if (start > dma_pfn)
-               zholes_size[ZONE_NORMAL] += end - start + 1;
-       else {
-               zholes_size[ZONE_DMA] += dma_pfn - start + 1;
-               zholes_size[ZONE_NORMAL] += end - dma_pfn;
-       }
-}
-
 static int __init early_parse_mem(char *p)
 {
        memory_end = memparse(p, &p);
@@ -521,7 +505,6 @@ setup_memory(void)
 {
         unsigned long bootmap_size;
        unsigned long start_pfn, end_pfn, init_pfn;
-       unsigned long last_rw_end;
        int i;
 
        /*
@@ -577,39 +560,27 @@ setup_memory(void)
        /*
         * Register RAM areas with the bootmem allocator.
         */
-       last_rw_end = start_pfn;
 
        for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
-               unsigned long start_chunk, end_chunk;
+               unsigned long start_chunk, end_chunk, pfn;
 
                if (memory_chunk[i].type != CHUNK_READ_WRITE)
                        continue;
-               start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
-               start_chunk >>= PAGE_SHIFT;
-               end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
-               end_chunk >>= PAGE_SHIFT;
-               if (start_chunk < start_pfn)
-                       start_chunk = start_pfn;
-               if (end_chunk > end_pfn)
-                       end_chunk = end_pfn;
-               if (start_chunk < end_chunk) {
-                       /* Initialize storage key for RAM pages */
-                       for (init_pfn = start_chunk ; init_pfn < end_chunk;
-                            init_pfn++)
-                               page_set_storage_key(init_pfn << PAGE_SHIFT,
-                                                    PAGE_DEFAULT_KEY);
-                       free_bootmem(start_chunk << PAGE_SHIFT,
-                                    (end_chunk - start_chunk) << PAGE_SHIFT);
-                       if (last_rw_end < start_chunk)
-                               add_memory_hole(last_rw_end, start_chunk - 1);
-                       last_rw_end = end_chunk;
-               }
+               start_chunk = PFN_DOWN(memory_chunk[i].addr);
+               end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1;
+               end_chunk = min(end_chunk, end_pfn);
+               if (start_chunk >= end_chunk)
+                       continue;
+               add_active_range(0, start_chunk, end_chunk);
+               pfn = max(start_chunk, start_pfn);
+               for (; pfn <= end_chunk; pfn++)
+                       page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
        }
 
        psw_set_key(PAGE_DEFAULT_KEY);
 
-       if (last_rw_end < end_pfn - 1)
-               add_memory_hole(last_rw_end, end_pfn - 1);
+       free_bootmem_with_active_regions(0, max_pfn);
+       reserve_bootmem(0, PFN_PHYS(start_pfn));
 
        /*
         * Reserve the bootmem bitmap itself as well. We do this in two
index 8741bdc..633249c 100644 (file)
@@ -8,8 +8,8 @@
  */
 
 #include <linux/errno.h>
-#include <asm/uaccess.h>
 #include <linux/mm.h>
+#include <asm/uaccess.h>
 #include <asm/futex.h>
 
 static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
@@ -60,8 +60,9 @@ out:
 
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
+               down_read(&mm->mmap_sem);
                goto survive;
        }
        printk("VM: killing process %s\n", current->comm);
index 2d549ed..bbaca66 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/futex.h>
 
 #ifndef __s390x__
@@ -258,7 +258,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
 {
        int oldval = 0, newval, ret;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -284,7 +284,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
        default:
                ret = -ENOSYS;
        }
-       dec_preempt_count();
+       pagefault_enable();
        *old = oldval;
        return ret;
 }
index aa9a42b..8e09db1 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y   := init.o fault.o ioremap.o extmem.o mmap.o
+obj-y   := init.o fault.o ioremap.o extmem.o mmap.o vmem.o
 obj-$(CONFIG_CMM) += cmm.o
 
index 9e9bc48..775bf19 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/bootmem.h>
 #include <linux/ctype.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/ebcdic.h>
 #include <asm/errno.h>
 #include <asm/extmem.h>
@@ -237,65 +238,6 @@ query_segment_type (struct dcss_segment *seg)
        return rc;
 }
 
-/*
- * check if the given segment collides with guest storage.
- * returns 1 if this is the case, 0 if no collision was found
- */
-static int
-segment_overlaps_storage(struct dcss_segment *seg)
-{
-       int i;
-
-       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
-               if (memory_chunk[i].type != CHUNK_READ_WRITE)
-                       continue;
-               if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
-                       continue;
-               if (((memory_chunk[i].addr + memory_chunk[i].size - 1) >> 20)
-                               < (seg->start_addr >> 20))
-                       continue;
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * check if segment collides with other segments that are currently loaded
- * returns 1 if this is the case, 0 if no collision was found
- */
-static int
-segment_overlaps_others (struct dcss_segment *seg)
-{
-       struct list_head *l;
-       struct dcss_segment *tmp;
-
-       BUG_ON(!mutex_is_locked(&dcss_lock));
-       list_for_each(l, &dcss_list) {
-               tmp = list_entry(l, struct dcss_segment, list);
-               if ((tmp->start_addr >> 20) > (seg->end >> 20))
-                       continue;
-               if ((tmp->end >> 20) < (seg->start_addr >> 20))
-                       continue;
-               if (seg == tmp)
-                       continue;
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * check if segment exceeds the kernel mapping range (detected or set via mem=)
- * returns 1 if this is the case, 0 if segment fits into the range
- */
-static inline int
-segment_exceeds_range (struct dcss_segment *seg)
-{
-       int seg_last_pfn = (seg->end) >> PAGE_SHIFT;
-       if (seg_last_pfn > max_pfn)
-               return 1;
-       return 0;
-}
-
 /*
  * get info about a segment
  * possible return values:
@@ -341,24 +283,26 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
        rc = query_segment_type (seg);
        if (rc < 0)
                goto out_free;
-       if (segment_exceeds_range(seg)) {
-               PRINT_WARN ("segment_load: not loading segment %s - exceeds"
-                               " kernel mapping range\n",name);
-               rc = -ERANGE;
+
+       rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+
+       switch (rc) {
+       case 0:
+               break;
+       case -ENOSPC:
+               PRINT_WARN("segment_load: not loading segment %s - overlaps "
+                          "storage/segment\n", name);
                goto out_free;
-       }
-       if (segment_overlaps_storage(seg)) {
-               PRINT_WARN ("segment_load: not loading segment %s - overlaps"
-                               " storage\n",name);
-               rc = -ENOSPC;
+       case -ERANGE:
+               PRINT_WARN("segment_load: not loading segment %s - exceeds "
+                          "kernel mapping range\n", name);
                goto out_free;
-       }
-       if (segment_overlaps_others(seg)) {
-               PRINT_WARN ("segment_load: not loading segment %s - overlaps"
-                               " other segments\n",name);
-               rc = -EBUSY;
+       default:
+               PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
+                          name, rc);
                goto out_free;
        }
+
        if (do_nonshared)
                dcss_command = DCSS_LOADNSR;
        else
@@ -372,7 +316,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                rc = dcss_diag_translate_rc (seg->end);
                dcss_diag(DCSS_PURGESEG, seg->dcss_name,
                                &seg->start_addr, &seg->end);
-               goto out_free;
+               goto out_shared;
        }
        seg->do_nonshared = do_nonshared;
        atomic_set(&seg->ref_count, 1);
@@ -391,6 +335,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                                (void*)seg->start_addr, (void*)seg->end,
                                segtype_string[seg->vm_segtype]);
        goto out;
+ out_shared:
+       remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
  out_free:
        kfree(seg);
  out:
@@ -530,12 +476,12 @@ segment_unload(char *name)
                                "please report to linux390@de.ibm.com\n",name);
                goto out_unlock;
        }
-       if (atomic_dec_return(&seg->ref_count) == 0) {
-               list_del(&seg->list);
-               dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-                         &dummy, &dummy);
-               kfree(seg);
-       }
+       if (atomic_dec_return(&seg->ref_count) != 0)
+               goto out_unlock;
+       remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+       list_del(&seg->list);
+       dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+       kfree(seg);
 out_unlock:
        mutex_unlock(&dcss_lock);
 }
index e1881c3..4bb21be 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
+#include <linux/poison.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -69,6 +70,8 @@ void show_mem(void)
         printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
         i = max_mapnr;
         while (i-- > 0) {
+               if (!pfn_valid(i))
+                       continue;
                page = pfn_to_page(i);
                 total++;
                if (PageReserved(page))
@@ -84,150 +87,52 @@ void show_mem(void)
         printk("%d pages swap cached\n",cached);
 }
 
-extern unsigned long __initdata zholes_size[];
-/*
- * paging_init() sets up the page tables
- */
-
-#ifndef CONFIG_64BIT
-void __init paging_init(void)
+static void __init setup_ro_region(void)
 {
-        pgd_t * pg_dir;
-        pte_t * pg_table;
-        pte_t   pte;
-       int     i;
-        unsigned long tmp;
-        unsigned long pfn = 0;
-        unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
-        static const int ssm_mask = 0x04000000L;
-       unsigned long ro_start_pfn, ro_end_pfn;
-       unsigned long zones_size[MAX_NR_ZONES];
-
-       ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
-       ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
-
-       memset(zones_size, 0, sizeof(zones_size));
-       zones_size[ZONE_DMA] = max_low_pfn;
-       free_area_init_node(0, &contig_page_data, zones_size,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT,
-                           zholes_size);
-
-       /* unmap whole virtual address space */
-       
-        pg_dir = swapper_pg_dir;
-
-       for (i = 0; i < PTRS_PER_PGD; i++)
-               pmd_clear((pmd_t *) pg_dir++);
-               
-       /*
-        * map whole physical memory to virtual memory (identity mapping) 
-        */
-
-        pg_dir = swapper_pg_dir;
-
-        while (pfn < max_low_pfn) {
-                /*
-                 * pg_table is physical at this point
-                 */
-               pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
-
-               pmd_populate_kernel(&init_mm, (pmd_t *) pg_dir, pg_table);
-                pg_dir++;
-
-                for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
-                       if (pfn >= ro_start_pfn && pfn < ro_end_pfn)
-                               pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
-                       else
-                               pte = pfn_pte(pfn, PAGE_KERNEL);
-                        if (pfn >= max_low_pfn)
-                               pte_val(pte) = _PAGE_TYPE_EMPTY;
-                       set_pte(pg_table, pte);
-                        pfn++;
-                }
-        }
-
-       S390_lowcore.kernel_asce = pgdir_k;
-
-        /* enable virtual mapping in kernel mode */
-       __ctl_load(pgdir_k, 1, 1);
-       __ctl_load(pgdir_k, 7, 7);
-       __ctl_load(pgdir_k, 13, 13);
-       __raw_local_irq_ssm(ssm_mask);
-
-        local_flush_tlb();
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t new_pte;
+       unsigned long address, end;
+
+       address = ((unsigned long)&__start_rodata) & PAGE_MASK;
+       end = PFN_ALIGN((unsigned long)&__end_rodata);
+
+       for (; address < end; address += PAGE_SIZE) {
+               pgd = pgd_offset_k(address);
+               pmd = pmd_offset(pgd, address);
+               pte = pte_offset_kernel(pmd, address);
+               new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
+               set_pte(pte, new_pte);
+       }
 }
 
-#else /* CONFIG_64BIT */
+extern void vmem_map_init(void);
 
+/*
+ * paging_init() sets up the page tables
+ */
 void __init paging_init(void)
 {
-        pgd_t * pg_dir;
-       pmd_t * pm_dir;
-        pte_t * pt_dir;
-        pte_t   pte;
-       int     i,j,k;
-        unsigned long pfn = 0;
-        unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) |
-          _KERN_REGION_TABLE;
+       pgd_t *pg_dir;
+       int i;
+       unsigned long pgdir_k;
        static const int ssm_mask = 0x04000000L;
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long dma_pfn, high_pfn;
-       unsigned long ro_start_pfn, ro_end_pfn;
-
-       memset(zones_size, 0, sizeof(zones_size));
-       dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
-       high_pfn = max_low_pfn;
-       ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
-       ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
-
-       if (dma_pfn > high_pfn)
-               zones_size[ZONE_DMA] = high_pfn;
-       else {
-               zones_size[ZONE_DMA] = dma_pfn;
-               zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
-       }
-
-       /* Initialize mem_map[].  */
-       free_area_init_node(0, &contig_page_data, zones_size,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
-       /*
-        * map whole physical memory to virtual memory (identity mapping) 
-        */
-
-        pg_dir = swapper_pg_dir;
-       
-        for (i = 0 ; i < PTRS_PER_PGD ; i++,pg_dir++) {
+       pg_dir = swapper_pg_dir;
        
-                if (pfn >= max_low_pfn) {
-                        pgd_clear(pg_dir);
-                        continue;
-                }          
-        
-               pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4);
-                pgd_populate(&init_mm, pg_dir, pm_dir);
-
-                for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
-                        if (pfn >= max_low_pfn) {
-                                pmd_clear(pm_dir);
-                                continue; 
-                        }          
-                        
-                       pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
-                        pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
-       
-                        for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
-                               if (pfn >= ro_start_pfn && pfn < ro_end_pfn)
-                                       pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
-                               else
-                                       pte = pfn_pte(pfn, PAGE_KERNEL);
-                               if (pfn >= max_low_pfn)
-                                       pte_val(pte) = _PAGE_TYPE_EMPTY;
-                                set_pte(pt_dir, pte);
-                                pfn++;
-                        }
-                }
-        }
+#ifdef CONFIG_64BIT
+       pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE;
+       for (i = 0; i < PTRS_PER_PGD; i++)
+               pgd_clear(pg_dir + i);
+#else
+       pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
+       for (i = 0; i < PTRS_PER_PGD; i++)
+               pmd_clear((pmd_t *)(pg_dir + i));
+#endif
+       vmem_map_init();
+       setup_ro_region();
 
        S390_lowcore.kernel_asce = pgdir_k;
 
@@ -237,9 +142,11 @@ void __init paging_init(void)
        __ctl_load(pgdir_k, 13, 13);
        __raw_local_irq_ssm(ssm_mask);
 
-        local_flush_tlb();
+       memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+       max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
+       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+       free_area_init_nodes(max_zone_pfns);
 }
-#endif /* CONFIG_64BIT */
 
 void __init mem_init(void)
 {
@@ -269,6 +176,8 @@ void __init mem_init(void)
        printk("Write protected kernel read-only data: %#lx - %#lx\n",
               (unsigned long)&__start_rodata,
               PFN_ALIGN((unsigned long)&__end_rodata) - 1);
+       printk("Virtual memmap size: %ldk\n",
+              (max_pfn * sizeof(struct page)) >> 10);
 }
 
 void free_initmem(void)
@@ -279,6 +188,7 @@ void free_initmem(void)
         for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
+               memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
                free_page(addr);
                totalram_pages++;
         }
index 0f6e9ec..3d2100a 100644 (file)
 
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-        unsigned long phys_addr, unsigned long flags)
-{
-        unsigned long end;
-        unsigned long pfn;
-
-        address &= ~PMD_MASK;
-        end = address + size;
-        if (end > PMD_SIZE)
-                end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-        pfn = phys_addr >> PAGE_SHIFT;
-        do {
-                if (!pte_none(*pte)) {
-                        printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-                set_pte(pte, pfn_pte(pfn, __pgprot(flags)));
-                address += PAGE_SIZE;
-                pfn++;
-                pte++;
-        } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-        unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                                unsigned long size, unsigned long flags)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset(&init_mm, address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pmd_t *pmd;
-               pmd = pmd_alloc(&init_mm, dir, address);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                        phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return 0;
-}
 
 /*
  * Generic mapping function (not visible outside):
@@ -122,7 +43,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
        if (!area)
                return NULL;
        addr = area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, __pgprot(flags))) {
                vfree(addr);
                return NULL;
        }
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
new file mode 100644 (file)
index 0000000..7f2944d
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ *  arch/s390/mm/vmem.c
+ *
+ *    Copyright IBM Corp. 2006
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/tlbflush.h>
+
+unsigned long vmalloc_end;
+EXPORT_SYMBOL(vmalloc_end);
+
+static struct page *vmem_map;
+static DEFINE_MUTEX(vmem_mutex);
+
+struct memory_segment {
+       struct list_head list;
+       unsigned long start;
+       unsigned long size;
+};
+
+static LIST_HEAD(mem_segs);
+
+void memmap_init(unsigned long size, int nid, unsigned long zone,
+                unsigned long start_pfn)
+{
+       struct page *start, *end;
+       struct page *map_start, *map_end;
+       int i;
+
+       start = pfn_to_page(start_pfn);
+       end = start + size;
+
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+               unsigned long cstart, cend;
+
+               cstart = PFN_DOWN(memory_chunk[i].addr);
+               cend = cstart + PFN_DOWN(memory_chunk[i].size);
+
+               map_start = mem_map + cstart;
+               map_end = mem_map + cend;
+
+               if (map_start < start)
+                       map_start = start;
+               if (map_end > end)
+                       map_end = end;
+
+               map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1))
+                       / sizeof(struct page);
+               map_end += ((PFN_ALIGN((unsigned long) map_end)
+                            - (unsigned long) map_end)
+                           / sizeof(struct page));
+
+               if (map_start < map_end)
+                       memmap_init_zone((unsigned long)(map_end - map_start),
+                                        nid, zone, page_to_pfn(map_start));
+       }
+}
+
+static inline void *vmem_alloc_pages(unsigned int order)
+{
+       if (slab_is_available())
+               return (void *)__get_free_pages(GFP_KERNEL, order);
+       return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
+}
+
+static inline pmd_t *vmem_pmd_alloc(void)
+{
+       pmd_t *pmd;
+       int i;
+
+       pmd = vmem_alloc_pages(PMD_ALLOC_ORDER);
+       if (!pmd)
+               return NULL;
+       for (i = 0; i < PTRS_PER_PMD; i++)
+               pmd_clear(pmd + i);
+       return pmd;
+}
+
+static inline pte_t *vmem_pte_alloc(void)
+{
+       pte_t *pte;
+       pte_t empty_pte;
+       int i;
+
+       pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
+       if (!pte)
+               return NULL;
+       pte_val(empty_pte) = _PAGE_TYPE_EMPTY;
+       for (i = 0; i < PTRS_PER_PTE; i++)
+               set_pte(pte + i, empty_pte);
+       return pte;
+}
+
+/*
+ * Add a physical memory range to the 1:1 mapping.
+ */
+static int vmem_add_range(unsigned long start, unsigned long size)
+{
+       unsigned long address;
+       pgd_t *pg_dir;
+       pmd_t *pm_dir;
+       pte_t *pt_dir;
+       pte_t  pte;
+       int ret = -ENOMEM;
+
+       for (address = start; address < start + size; address += PAGE_SIZE) {
+               pg_dir = pgd_offset_k(address);
+               if (pgd_none(*pg_dir)) {
+                       pm_dir = vmem_pmd_alloc();
+                       if (!pm_dir)
+                               goto out;
+                       pgd_populate(&init_mm, pg_dir, pm_dir);
+               }
+
+               pm_dir = pmd_offset(pg_dir, address);
+               if (pmd_none(*pm_dir)) {
+                       pt_dir = vmem_pte_alloc();
+                       if (!pt_dir)
+                               goto out;
+                       pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
+               }
+
+               pt_dir = pte_offset_kernel(pm_dir, address);
+               pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
+               set_pte(pt_dir, pte);
+       }
+       ret = 0;
+out:
+       flush_tlb_kernel_range(start, start + size);
+       return ret;
+}
+
+/*
+ * Remove a physical memory range from the 1:1 mapping.
+ * Currently only invalidates page table entries.
+ */
+static void vmem_remove_range(unsigned long start, unsigned long size)
+{
+       unsigned long address;
+       pgd_t *pg_dir;
+       pmd_t *pm_dir;
+       pte_t *pt_dir;
+       pte_t  pte;
+
+       pte_val(pte) = _PAGE_TYPE_EMPTY;
+       for (address = start; address < start + size; address += PAGE_SIZE) {
+               pg_dir = pgd_offset_k(address);
+               if (pgd_none(*pg_dir))
+                       continue;
+               pm_dir = pmd_offset(pg_dir, address);
+               if (pmd_none(*pm_dir))
+                       continue;
+               pt_dir = pte_offset_kernel(pm_dir, address);
+               set_pte(pt_dir, pte);
+       }
+       flush_tlb_kernel_range(start, start + size);
+}
+
+/*
+ * Add a backed mem_map array to the virtual mem_map array.
+ */
+static int vmem_add_mem_map(unsigned long start, unsigned long size)
+{
+       unsigned long address, start_addr, end_addr;
+       struct page *map_start, *map_end;
+       pgd_t *pg_dir;
+       pmd_t *pm_dir;
+       pte_t *pt_dir;
+       pte_t  pte;
+       int ret = -ENOMEM;
+
+       map_start = vmem_map + PFN_DOWN(start);
+       map_end = vmem_map + PFN_DOWN(start + size);
+
+       start_addr = (unsigned long) map_start & PAGE_MASK;
+       end_addr = PFN_ALIGN((unsigned long) map_end);
+
+       for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+               pg_dir = pgd_offset_k(address);
+               if (pgd_none(*pg_dir)) {
+                       pm_dir = vmem_pmd_alloc();
+                       if (!pm_dir)
+                               goto out;
+                       pgd_populate(&init_mm, pg_dir, pm_dir);
+               }
+
+               pm_dir = pmd_offset(pg_dir, address);
+               if (pmd_none(*pm_dir)) {
+                       pt_dir = vmem_pte_alloc();
+                       if (!pt_dir)
+                               goto out;
+                       pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
+               }
+
+               pt_dir = pte_offset_kernel(pm_dir, address);
+               if (pte_none(*pt_dir)) {
+                       unsigned long new_page;
+
+                       new_page =__pa(vmem_alloc_pages(0));
+                       if (!new_page)
+                               goto out;
+                       pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
+                       set_pte(pt_dir, pte);
+               }
+       }
+       ret = 0;
+out:
+       flush_tlb_kernel_range(start_addr, end_addr);
+       return ret;
+}
+
+static int vmem_add_mem(unsigned long start, unsigned long size)
+{
+       int ret;
+
+       ret = vmem_add_range(start, size);
+       if (ret)
+               return ret;
+       return vmem_add_mem_map(start, size);
+}
+
+/*
+ * Add memory segment to the segment list if it doesn't overlap with
+ * an already present segment.
+ */
+static int insert_memory_segment(struct memory_segment *seg)
+{
+       struct memory_segment *tmp;
+
+       if (PFN_DOWN(seg->start + seg->size) > max_pfn ||
+           seg->start + seg->size < seg->start)
+               return -ERANGE;
+
+       list_for_each_entry(tmp, &mem_segs, list) {
+               if (seg->start >= tmp->start + tmp->size)
+                       continue;
+               if (seg->start + seg->size <= tmp->start)
+                       continue;
+               return -ENOSPC;
+       }
+       list_add(&seg->list, &mem_segs);
+       return 0;
+}
+
+/*
+ * Remove memory segment from the segment list.
+ */
+static void remove_memory_segment(struct memory_segment *seg)
+{
+       list_del(&seg->list);
+}
+
+static void __remove_shared_memory(struct memory_segment *seg)
+{
+       remove_memory_segment(seg);
+       vmem_remove_range(seg->start, seg->size);
+}
+
+int remove_shared_memory(unsigned long start, unsigned long size)
+{
+       struct memory_segment *seg;
+       int ret;
+
+       mutex_lock(&vmem_mutex);
+
+       ret = -ENOENT;
+       list_for_each_entry(seg, &mem_segs, list) {
+               if (seg->start == start && seg->size == size)
+                       break;
+       }
+
+       if (seg->start != start || seg->size != size)
+               goto out;
+
+       ret = 0;
+       __remove_shared_memory(seg);
+       kfree(seg);
+out:
+       mutex_unlock(&vmem_mutex);
+       return ret;
+}
+
+int add_shared_memory(unsigned long start, unsigned long size)
+{
+       struct memory_segment *seg;
+       struct page *page;
+       unsigned long pfn, num_pfn, end_pfn;
+       int ret;
+
+       mutex_lock(&vmem_mutex);
+       ret = -ENOMEM;
+       seg = kzalloc(sizeof(*seg), GFP_KERNEL);
+       if (!seg)
+               goto out;
+       seg->start = start;
+       seg->size = size;
+
+       ret = insert_memory_segment(seg);
+       if (ret)
+               goto out_free;
+
+       ret = vmem_add_mem(start, size);
+       if (ret)
+               goto out_remove;
+
+       pfn = PFN_DOWN(start);
+       num_pfn = PFN_DOWN(size);
+       end_pfn = pfn + num_pfn;
+
+       page = pfn_to_page(pfn);
+       memset(page, 0, num_pfn * sizeof(struct page));
+
+       for (; pfn < end_pfn; pfn++) {
+               page = pfn_to_page(pfn);
+               init_page_count(page);
+               reset_page_mapcount(page);
+               SetPageReserved(page);
+               INIT_LIST_HEAD(&page->lru);
+       }
+       goto out;
+
+out_remove:
+       __remove_shared_memory(seg);
+out_free:
+       kfree(seg);
+out:
+       mutex_unlock(&vmem_mutex);
+       return ret;
+}
+
+/*
+ * map whole physical memory to virtual memory (identity mapping)
+ */
+void __init vmem_map_init(void)
+{
+       unsigned long map_size;
+       int i;
+
+       map_size = ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * sizeof(struct page);
+       vmalloc_end = PFN_ALIGN(VMALLOC_END_INIT) - PFN_ALIGN(map_size);
+       vmem_map = (struct page *) vmalloc_end;
+       NODE_DATA(0)->node_mem_map = vmem_map;
+
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
+               vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
+}
+
+/*
+ * Convert memory chunk array to a memory segment list so there is a single
+ * list that contains both r/w memory and shared memory segments.
+ */
+static int __init vmem_convert_memory_chunk(void)
+{
+       struct memory_segment *seg;
+       int i;
+
+       mutex_lock(&vmem_mutex);
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+               if (!memory_chunk[i].size)
+                       continue;
+               seg = kzalloc(sizeof(*seg), GFP_KERNEL);
+               if (!seg)
+                       panic("Out of memory...\n");
+               seg->start = memory_chunk[i].addr;
+               seg->size = memory_chunk[i].size;
+               insert_memory_segment(seg);
+       }
+       mutex_unlock(&vmem_mutex);
+       return 0;
+}
+
+core_initcall(vmem_convert_memory_chunk);
index bffc7e1..8e24c40 100644 (file)
@@ -51,6 +51,22 @@ config GENERIC_TIME
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
+config STACKTRACE_SUPPORT
+       bool
+       default y
+
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 source "init/Kconfig"
 
 menu "System type"
@@ -219,6 +235,20 @@ config SH_SHMIN
        help
          Select SHMIN if configuring for the SHMIN board.
 
+config SH_7206_SOLUTION_ENGINE
+       bool "SolutionEngine7206"
+       select CPU_SUBTYPE_SH7206
+       help
+         Select 7206 SolutionEngine if configuring for a Hitachi SH7206
+         evaluation board.
+
+config SH_7619_SOLUTION_ENGINE
+       bool "SolutionEngine7619"
+       select CPU_SUBTYPE_SH7619
+       help
+         Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+         evaluation board.
+
 config SH_UNKNOWN
        bool "BareCPU"
        help
@@ -280,12 +310,20 @@ config CF_BASE_ADDR
 
 menu "Processor features"
 
-config CPU_LITTLE_ENDIAN
-       bool "Little Endian"
+choice
+       prompt "Endianess selection" 
+       default CPU_LITTLE_ENDIAN
        help
          Some SuperH machines can be configured for either little or big
-         endian byte order. These modes require different kernels. Say Y if
-         your machine is little endian, N if it's a big endian machine.
+         endian byte order. These modes require different kernels.
+
+config CPU_LITTLE_ENDIAN
+       bool "Little Endian"
+
+config CPU_BIG_ENDIAN
+       bool "Big Endian"
+
+endchoice
 
 config SH_FPU
        bool "FPU support"
@@ -345,6 +383,9 @@ config CPU_HAS_MASKREG_IRQ
 config CPU_HAS_INTC2_IRQ
        bool
 
+config CPU_HAS_IPR_IRQ
+       bool
+
 config CPU_HAS_SR_RB
        bool "CPU has SR.RB"
        depends on CPU_SH3 || CPU_SH4
@@ -357,6 +398,9 @@ config CPU_HAS_SR_RB
          See <file:Documentation/sh/register-banks.txt> for further
          information on SR.RB and register banking in the kernel in general.
 
+config CPU_HAS_PTEA
+       bool
+
 endmenu
 
 menu "Timer support"
@@ -364,10 +408,25 @@ depends on !GENERIC_TIME
 
 config SH_TMU
        bool "TMU timer support"
+       depends on CPU_SH3 || CPU_SH4
        default y
        help
          This enables the use of the TMU as the system timer.
 
+config SH_CMT
+       bool "CMT timer support"
+       depends on CPU_SH2
+       default y
+       help
+         This enables the use of the CMT as the system timer.
+
+config SH_MTU2
+       bool "MTU2 timer support"
+       depends on CPU_SH2A
+       default n
+       help
+         This enables the use of the MTU2 as the system timer.
+
 endmenu
 
 source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
@@ -376,19 +435,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 
 source "arch/sh/boards/renesas/r7780rp/Kconfig"
 
+config SH_TIMER_IRQ
+       int
+       default "28" if CPU_SUBTYPE_SH7780
+       default "86" if CPU_SUBTYPE_SH7619
+       default "140" if CPU_SUBTYPE_SH7206
+       default "16"
+
+config NO_IDLE_HZ
+       bool "Dynamic tick timer"
+       help
+         Select this option if you want to disable continuous timer ticks
+         and have them programmed to occur as required. This option saves
+         power as the system can remain in idle state for longer.
+
+         By default dynamic tick is disabled during the boot, and can be
+         manually enabled with:
+
+           echo 1 > /sys/devices/system/timer/timer0/dyn_tick
+
+         Alternatively, if you want dynamic tick automatically enabled
+         during boot, pass "dyntick=enable" via the kernel command string.
+
+         Please note that dynamic tick may affect the accuracy of
+         timekeeping on some platforms depending on the implementation.
+
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
+       default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
+       default "31250000" if CPU_SUBTYPE_SH7619
+       default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
+                             CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
+                             CPU_SUBTYPE_SH7206
        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 || CPU_SUBTYPE_SH7705
-       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.
          This is necessary for determining the reference clock value on
          platforms lacking an RTC.
 
+config SH_CLK_MD
+       int "CPU Mode Pin Setting"
+       depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
+       help
+         MD2 - MD0 Setting.
+
 menu "CPU Frequency scaling"
 
 source "drivers/cpufreq/Kconfig"
@@ -421,6 +513,8 @@ config HEARTBEAT
          behavior is platform-dependent, but normally the flash frequency is
          a hyperbolic function of the 5-minute load average.
 
+source "arch/sh/drivers/Kconfig"
+
 endmenu
 
 config ISA_DMA_API
index 48479e0..66a25ef 100644 (file)
@@ -1,5 +1,9 @@
 menu "Kernel hacking"
 
+config TRACE_IRQFLAGS_SUPPORT
+       bool
+       default y
+
 source "lib/Kconfig.debug"
 
 config SH_STANDARD_BIOS
@@ -17,7 +21,18 @@ config SH_STANDARD_BIOS
 
 config EARLY_SCIF_CONSOLE
        bool "Use early SCIF console"
-       depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS
+       help
+         This enables an early console using a fixed SCIF port. This can
+         be used by platforms that are either not running the SH
+         standard BIOS, or do not wish to use the BIOS callbacks for the
+         serial I/O.
+
+config EARLY_SCIF_CONSOLE_PORT
+       hex "SCIF port for early console"
+       depends on EARLY_SCIF_CONSOLE
+       default "0xffe00000" if CPU_SUBTYPE_SH7780
+       default "0xfffe9800" if CPU_SUBTYPE_SH72060
+       default "0xffe80000" if CPU_SH4
 
 config EARLY_PRINTK
        bool "Early printk support"
@@ -30,6 +45,11 @@ config EARLY_PRINTK
          when the kernel may crash or hang before the serial console is
          initialised. If unsure, say N.
 
+         On devices that are running SH-IPL and want to keep the port
+         initialization consistent while not using the BIOS callbacks,
+         select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
+         the kernel command line option to toggle back and forth.
+
 config DEBUG_STACKOVERFLOW
        bool "Check for stack overflows"
        depends on DEBUG_KERNEL
index 26d62ff..d10bba5 100644 (file)
 # for "archclean" and "archdep" for cleaning up and making dependencies for
 # this architecture
 #
-
-cflags-y                               := -mb
-cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     := -ml
-
 isa-y                                  := any
 isa-$(CONFIG_SH_DSP)                   := sh
 isa-$(CONFIG_CPU_SH2)                  := sh2
@@ -38,13 +34,16 @@ isa-y                       := $(isa-y)-nofpu
 endif
 endif
 
-cflags-y       += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
-
-cflags-$(CONFIG_CPU_SH2)               += -m2
-cflags-$(CONFIG_CPU_SH3)               += -m3
-cflags-$(CONFIG_CPU_SH4)               += -m4 \
+cflags-$(CONFIG_CPU_SH2)               := -m2
+cflags-$(CONFIG_CPU_SH3)               := -m3
+cflags-$(CONFIG_CPU_SH4)               := -m4 \
        $(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A)              += $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A)              := -m4a $(call cc-option,-m4a-nofpu,)
+
+cflags-$(CONFIG_CPU_BIG_ENDIAN)                += -mb
+cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     += -ml
+
+cflags-y       += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
 
 cflags-$(CONFIG_SH_DSP)                        += -Wa,-dsp
 cflags-$(CONFIG_SH_KGDB)               += -g
@@ -59,7 +58,9 @@ OBJCOPYFLAGS  := -O binary -R .note -R .comment -R .stab -R .stabstr -S
 # never be used by anyone. Use a board-specific defconfig that has a
 # reasonable chance of being current instead.
 #
-KBUILD_DEFCONFIG := rts7751r2d_defconfig
+KBUILD_DEFCONFIG := r7780rp_defconfig
+
+KBUILD_IMAGE   := arch/sh/boot/zImage
 
 #
 # Choosing incompatible machines durings configuration will result in
@@ -109,6 +110,8 @@ 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_7206_SOLUTION_ENGINE)      := se/7206
+machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)      := se/7619
 machdir-$(CONFIG_SH_UNKNOWN)                   := unknown
 
 incdir-y                       := $(notdir $(machdir-y))
@@ -124,6 +127,7 @@ core-$(CONFIG_HD64465)              += arch/sh/cchips/hd6446x/hd64465/
 core-$(CONFIG_VOYAGERGX)       += arch/sh/cchips/voyagergx/
 
 cpuincdir-$(CONFIG_CPU_SH2)    := cpu-sh2
+cpuincdir-$(CONFIG_CPU_SH2A)   := cpu-sh2a
 cpuincdir-$(CONFIG_CPU_SH3)    := cpu-sh3
 cpuincdir-$(CONFIG_CPU_SH4)    := cpu-sh4
 
index f1776d0..574b031 100644 (file)
@@ -3,4 +3,6 @@
 #
 
 obj-y   := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT)        += led.o
+
+obj-$(CONFIG_HEARTBEAT)                += led.o
+obj-$(CONFIG_PUSH_SWITCH)      += psw.o
index aa15ec5..cc381e1 100644 (file)
@@ -10,6 +10,7 @@
  */
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/r7780rp.h>
 
diff --git a/arch/sh/boards/renesas/r7780rp/psw.c b/arch/sh/boards/renesas/r7780rp/psw.c
new file mode 100644 (file)
index 0000000..c844dfa
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * arch/sh/boards/renesas/r7780rp/psw.c
+ *
+ * push switch support for RDBRP-1/RDBREVRP-1 debug boards.
+ *
+ * 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/io.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/mach/r7780rp.h>
+#include <asm/push-switch.h>
+
+static irqreturn_t psw_irq_handler(int irq, void *arg)
+{
+       struct platform_device *pdev = arg;
+       struct push_switch *psw = platform_get_drvdata(pdev);
+       struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
+       unsigned int l, mask;
+       int ret = 0;
+
+       l = ctrl_inw(PA_DBSW);
+
+       /* Nothing to do if there's no state change */
+       if (psw->state) {
+               ret = 1;
+               goto out;
+       }
+
+       mask = l & 0x70;
+       /* Figure out who raised it */
+       if (mask & (1 << psw_info->bit)) {
+               psw->state = !!(mask & (1 << psw_info->bit));
+               if (psw->state) /* debounce */
+                       mod_timer(&psw->debounce, jiffies + 50);
+
+               ret = 1;
+       }
+
+out:
+       /* Clear the switch IRQs */
+       l |= (0x7 << 12);
+       ctrl_outw(l, PA_DBSW);
+
+       return IRQ_RETVAL(ret);
+}
+
+static struct resource psw_resources[] = {
+       [0] = {
+               .start  = IRQ_PSW,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct push_switch_platform_info s2_platform_data = {
+       .name           = "s2",
+       .bit            = 6,
+       .irq_flags      = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+                         IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct platform_device s2_switch_device = {
+       .name           = "push-switch",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(psw_resources),
+       .resource       = psw_resources,
+       .dev            = {
+               .platform_data = &s2_platform_data,
+       },
+};
+
+static struct push_switch_platform_info s3_platform_data = {
+       .name           = "s3",
+       .bit            = 5,
+       .irq_flags      = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+                         IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct platform_device s3_switch_device = {
+       .name           = "push-switch",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(psw_resources),
+       .resource       = psw_resources,
+       .dev            = {
+               .platform_data = &s3_platform_data,
+       },
+};
+
+static struct push_switch_platform_info s4_platform_data = {
+       .name           = "s4",
+       .bit            = 4,
+       .irq_flags      = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+                         IRQF_SHARED,
+       .irq_handler    = psw_irq_handler,
+};
+
+static struct platform_device s4_switch_device = {
+       .name           = "push-switch",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(psw_resources),
+       .resource       = psw_resources,
+       .dev            = {
+               .platform_data = &s4_platform_data,
+       },
+};
+
+static struct platform_device *psw_devices[] = {
+       &s2_switch_device, &s3_switch_device, &s4_switch_device,
+};
+
+static int __init psw_init(void)
+{
+       return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
+}
+module_init(psw_init);
index c331cae..9f89c8d 100644 (file)
@@ -44,8 +44,37 @@ static struct platform_device m66596_usb_host_device = {
        .resource       = m66596_usb_host_resources,
 };
 
+static struct resource cf_ide_resources[] = {
+       [0] = {
+               .start  = 0x1f0,
+               .end    = 0x1f0 + 8,
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               .start  = 0x1f0 + 0x206,
+               .end    = 0x1f0 + 8 + 0x206 + 8,
+               .flags  = IORESOURCE_IO,
+       },
+       [2] = {
+#ifdef CONFIG_SH_R7780MP
+               .start  = 1,
+#else
+               .start  = 4,
+#endif
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_ide_device  = {
+       .name           = "pata_platform",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(cf_ide_resources),
+       .resource       = cf_ide_resources,
+};
+
 static struct platform_device *r7780rp_devices[] __initdata = {
        &m66596_usb_host_device,
+       &cf_ide_device,
 };
 
 static int __init r7780rp_devices_setup(void)
diff --git a/arch/sh/boards/se/7206/Makefile b/arch/sh/boards/se/7206/Makefile
new file mode 100644 (file)
index 0000000..63950f4
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7206 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/7206/io.c b/arch/sh/boards/se/7206/io.c
new file mode 100644 (file)
index 0000000..b557273
--- /dev/null
@@ -0,0 +1,123 @@
+/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+ *
+ * linux/arch/sh/boards/se/7206/io.c
+ *
+ * Copyright (C) 2006 Yoshinori Sato
+ *
+ * I/O routine for Hitachi 7206 SolutionEngine.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se7206.h>
+
+
+static inline void delay(void)
+{
+       ctrl_inw(0x20000000);  /* P2 ROM Area */
+}
+
+/* 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.  */
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+       if (port >= 0x2000)
+               return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+       else if (port >= 0x300 || port < 0x310)
+               return (volatile __u16 *) (PA_SMSC + (port - 0x300));
+}
+
+unsigned char se7206_inb(unsigned long port)
+{
+       return (*port2adr(port))&0xff; 
+}
+
+unsigned char se7206_inb_p(unsigned long port)
+{
+       unsigned long v;
+
+       v = (*port2adr(port))&0xff; 
+       delay();
+       return v;
+}
+
+unsigned short se7206_inw(unsigned long port)
+{
+       return *port2adr(port);;
+}
+
+unsigned int se7206_inl(unsigned long port)
+{
+       maybebadio(port);
+       return 0;
+}
+
+void se7206_outb(unsigned char value, unsigned long port)
+{
+       *(port2adr(port)) = value;
+}
+
+void se7206_outb_p(unsigned char value, unsigned long port)
+{
+       *(port2adr(port)) = value;
+       delay();
+}
+
+void se7206_outw(unsigned short value, unsigned long port)
+{
+       *port2adr(port) = value;
+}
+
+void se7206_outl(unsigned int value, unsigned long port)
+{
+       maybebadio(port);
+}
+
+void se7206_insb(unsigned long port, void *addr, unsigned long count)
+{
+       volatile __u16 *p = port2adr(port);
+       __u8 *ap = addr;
+
+       while (count--)
+               *ap++ = *p;
+}
+
+void se7206_insw(unsigned long port, void *addr, unsigned long count)
+{
+       volatile __u16 *p = port2adr(port);
+       __u16 *ap = addr;
+       while (count--)
+               *ap++ = *p;
+}
+
+void se7206_insl(unsigned long port, void *addr, unsigned long count)
+{
+       maybebadio(port);
+}
+
+void se7206_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+       volatile __u16 *p = port2adr(port);
+       const __u8 *ap = addr;
+
+       while (count--)
+               *p = *ap++;
+}
+
+void se7206_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+       volatile __u16 *p = port2adr(port);
+       const __u16 *ap = addr;
+       while (count--)
+               *p = *ap++;
+}
+
+void se7206_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+       maybebadio(port);
+}
diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c
new file mode 100644 (file)
index 0000000..3fb0c5f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/sh/boards/se/7206/irq.c
+ *
+ * Copyright (C) 2005,2006 Yoshinori Sato
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/se7206.h>
+
+#define INTSTS0 0x31800000
+#define INTSTS1 0x31800002
+#define INTMSK0 0x31800004
+#define INTMSK1 0x31800006
+#define INTSEL  0x31800008
+
+static void disable_se7206_irq(unsigned int irq)
+{
+       unsigned short val;
+       unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
+       unsigned short msk0,msk1;
+
+       /* Set the priority in IPR to 0 */
+       val = ctrl_inw(INTC_IPR01);
+       val &= mask;
+       ctrl_outw(val, INTC_IPR01);
+       /* FPGA mask set */
+       msk0 = ctrl_inw(INTMSK0);
+       msk1 = ctrl_inw(INTMSK1);
+
+       switch (irq) {
+       case IRQ0_IRQ:
+               msk0 |= 0x0010;
+               break;
+       case IRQ1_IRQ:
+               msk0 |= 0x000f;
+               break;
+       case IRQ2_IRQ:
+               msk0 |= 0x0f00;
+               msk1 |= 0x00ff;
+               break;
+       }
+       ctrl_outw(msk0, INTMSK0);
+       ctrl_outw(msk1, INTMSK1);
+}
+
+static void enable_se7206_irq(unsigned int irq)
+{
+       unsigned short val;
+       unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
+       unsigned short msk0,msk1;
+
+       /* Set priority in IPR back to original value */
+       val = ctrl_inw(INTC_IPR01);
+       val |= value;
+       ctrl_outw(val, INTC_IPR01);
+
+       /* FPGA mask reset */
+       msk0 = ctrl_inw(INTMSK0);
+       msk1 = ctrl_inw(INTMSK1);
+
+       switch (irq) {
+       case IRQ0_IRQ:
+               msk0 &= ~0x0010;
+               break;
+       case IRQ1_IRQ:
+               msk0 &= ~0x000f;
+               break;
+       case IRQ2_IRQ:
+               msk0 &= ~0x0f00;
+               msk1 &= ~0x00ff;
+               break;
+       }
+       ctrl_outw(msk0, INTMSK0);
+       ctrl_outw(msk1, INTMSK1);
+}
+
+static void eoi_se7206_irq(unsigned int irq)
+{
+       unsigned short sts0,sts1;
+
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_se7206_irq(irq);
+       /* FPGA isr clear */
+       sts0 = ctrl_inw(INTSTS0);
+       sts1 = ctrl_inw(INTSTS1);
+
+       switch (irq) {
+       case IRQ0_IRQ:
+               sts0 &= ~0x0010;
+               break;
+       case IRQ1_IRQ:
+               sts0 &= ~0x000f;
+               break;
+       case IRQ2_IRQ:
+               sts0 &= ~0x0f00;
+               sts1 &= ~0x00ff;
+               break;
+       }
+       ctrl_outw(sts0, INTSTS0);
+       ctrl_outw(sts1, INTSTS1);
+}
+
+static struct irq_chip se7206_irq_chip __read_mostly = {
+       .name           = "SE7206-FPGA-IRQ",
+       .mask           = disable_se7206_irq,
+       .unmask         = enable_se7206_irq,
+       .mask_ack       = disable_se7206_irq,
+       .eoi            = eoi_se7206_irq,
+};
+
+static void make_se7206_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
+                                     handle_level_irq, "level");
+       disable_se7206_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se7206_IRQ(void)
+{
+       make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
+       make_se7206_irq(IRQ1_IRQ); /* ATA */
+       make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
+       ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
+
+       /* FPGA System register setup*/
+       ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
+       ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
+       /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
+       ctrl_outw(0x0001,INTSEL);
+}
diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c
new file mode 100644 (file)
index 0000000..ef79460
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/se7206.h>
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_se(void)
+{
+       static unsigned int cnt = 0, period = 0;
+       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+       static unsigned bit = 0, up = 1;
+
+       cnt += 1;
+       if (cnt < period) {
+               return;
+       }
+
+       cnt = 0;
+
+       /* Go through the points (roughly!):
+        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+        */
+       period = 110 - ( (300<<FSHIFT)/
+                        ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+       if (up) {
+               if (bit == 7) {
+                       bit--;
+                       up=0;
+               } else {
+                       bit ++;
+               }
+       } else {
+               if (bit == 0) {
+                       bit++;
+                       up=1;
+               } else {
+                       bit--;
+               }
+       }
+       *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
new file mode 100644 (file)
index 0000000..0f42e91
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *
+ * linux/arch/sh/boards/se/7206/setup.c
+ *
+ * Copyright (C) 2006  Yoshinori Sato
+ *
+ * Hitachi 7206 SolutionEngine Support.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/se7206.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start          = 0x300,
+               .end            = 0x300 + 0x020 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = 64,
+               .end            = 64,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static int __init se7206_devices_setup(void)
+{
+       return platform_device_register(&smc91x_device);
+}
+
+__initcall(se7206_devices_setup);
+
+void heartbeat_se(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+       .mv_name                = "SolutionEngine",
+       .mv_nr_irqs             = 256,
+       .mv_inb                 = se7206_inb,
+       .mv_inw                 = se7206_inw,
+       .mv_inl                 = se7206_inl,
+       .mv_outb                = se7206_outb,
+       .mv_outw                = se7206_outw,
+       .mv_outl                = se7206_outl,
+
+       .mv_inb_p               = se7206_inb_p,
+       .mv_inw_p               = se7206_inw,
+       .mv_inl_p               = se7206_inl,
+       .mv_outb_p              = se7206_outb_p,
+       .mv_outw_p              = se7206_outw,
+       .mv_outl_p              = se7206_outl,
+
+       .mv_insb                = se7206_insb,
+       .mv_insw                = se7206_insw,
+       .mv_insl                = se7206_insl,
+       .mv_outsb               = se7206_outsb,
+       .mv_outsw               = se7206_outsw,
+       .mv_outsl               = se7206_outsl,
+
+       .mv_init_irq            = init_se7206_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile
new file mode 100644 (file)
index 0000000..3666eca
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the 7619 SolutionEngine specific parts of the kernel
+#
+
+obj-y   := setup.o io.o
diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c
new file mode 100644 (file)
index 0000000..176f1f3
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *
+ * linux/arch/sh/boards/se/7619/io.c
+ *
+ * Copyright (C) 2006  Yoshinori Sato
+ *
+ * I/O routine for Hitachi 7619 SolutionEngine.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se7619.h>
+#include <asm/irq.h>
+
+/* FIXME: M3A-ZAB7 Compact Flash Slot support */
+
+static inline void delay(void)
+{
+       ctrl_inw(0xa0000000);   /* Uncached ROM area (P2) */
+}
+
+#define badio(name,port) \
+  printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
+        #name, (port), (__u32) __builtin_return_address(0))
+
+unsigned char se7619___inb(unsigned long port)
+{
+       badio(inb, port);
+       return 0;
+}
+
+unsigned char se7619___inb_p(unsigned long port)
+{
+       badio(inb_p, port);
+       delay();
+       return 0;
+}
+
+unsigned short se7619___inw(unsigned long port)
+{
+       badio(inw, port);
+       return 0;
+}
+
+unsigned int se7619___inl(unsigned long port)
+{
+       badio(inl, port);
+       return 0;
+}
+
+void se7619___outb(unsigned char value, unsigned long port)
+{
+       badio(outb, port);
+}
+
+void se7619___outb_p(unsigned char value, unsigned long port)
+{
+       badio(outb_p, port);
+       delay();
+}
+
+void se7619___outw(unsigned short value, unsigned long port)
+{
+       badio(outw, port);
+}
+
+void se7619___outl(unsigned int value, unsigned long port)
+{
+       badio(outl, port);
+}
+
+void se7619___insb(unsigned long port, void *addr, unsigned long count)
+{
+       badio(inw, port);
+}
+
+void se7619___insw(unsigned long port, void *addr, unsigned long count)
+{
+       badio(inw, port);
+}
+
+void se7619___insl(unsigned long port, void *addr, unsigned long count)
+{
+       badio(insl, port);
+}
+
+void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
+{
+       badio(insl, port);
+}
+
+void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
+{
+       badio(insl, port);
+}
+
+void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
+{
+       badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
new file mode 100644 (file)
index 0000000..e627b26
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/boards/se/7619/setup.c
+ *
+ * Copyright (C) 2006 Yoshinori Sato
+ *
+ * Hitachi SH7619 SolutionEngine Support.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/se7619.h>
+#include <asm/machvec.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+       .mv_name                = "SolutionEngine",
+       .mv_nr_irqs             = 108,
+       .mv_inb                 = se7619___inb,
+       .mv_inw                 = se7619___inw,
+       .mv_inl                 = se7619___inl,
+       .mv_outb                = se7619___outb,
+       .mv_outw                = se7619___outw,
+       .mv_outl                = se7619___outl,
+
+       .mv_inb_p               = se7619___inb_p,
+       .mv_inw_p               = se7619___inw,
+       .mv_inl_p               = se7619___inl,
+       .mv_outb_p              = se7619___outb_p,
+       .mv_outw_p              = se7619___outw,
+       .mv_outl_p              = se7619___outl,
+
+       .mv_insb                = se7619___insb,
+       .mv_insw                = se7619___insw,
+       .mv_insl                = se7619___insl,
+       .mv_outsb               = se7619___outsb,
+       .mv_outsw               = se7619___outsw,
+       .mv_outsl               = se7619___outsl,
+};
+ALIAS_MV(se)
index a6046d9..6bcd939 100644 (file)
@@ -1,26 +1,30 @@
 /*
- *     Setup for Titan
+ * arch/sh/boards/titan/setup.c - Setup for Titan
+ *
+ *  Copyright (C) 2006  Jamie Lenehan
+ *
+ * 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 <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/titan.h>
 #include <asm/io.h>
 
-extern void __init pcibios_init_platform(void);
-
 static struct ipr_data titan_ipr_map[] = {
-       { TITAN_IRQ_WAN,        IRL0_IPR_ADDR,  IRL0_IPR_POS,   IRL0_PRIORITY },
-       { TITAN_IRQ_LAN,        IRL1_IPR_ADDR,  IRL1_IPR_POS,   IRL1_PRIORITY },
-       { TITAN_IRQ_MPCIA,      IRL2_IPR_ADDR,  IRL2_IPR_POS,   IRL2_PRIORITY },
-       { TITAN_IRQ_USB,        IRL3_IPR_ADDR,  IRL3_IPR_POS,   IRL3_PRIORITY },
+       /* IRQ, IPR idx, shift, prio */
+       { TITAN_IRQ_WAN,   3, 12, 8 },  /* eth0 (WAN) */
+       { TITAN_IRQ_LAN,   3,  8, 8 },  /* eth1 (LAN) */
+       { TITAN_IRQ_MPCIA, 3,  4, 8 },  /* mPCI A (top) */
+       { TITAN_IRQ_USB,   3,  0, 8 },  /* mPCI B (bottom), USB */
 };
 
 static void __init init_titan_irq(void)
 {
        /* enable individual interrupt mode for externals */
-       ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
-
+       ipr_irq_enable_irlm();
+       /* register ipr irqs */
        make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
 }
 
@@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = {
        .mv_ioport_map = titan_ioport_map,
 
        .mv_init_irq =  init_titan_irq,
-       .mv_init_pci =  pcibios_init_platform,
 };
 ALIAS_MV(titan)
index f2fed5c..35452d8 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <asm/uaccess.h>
+#include <asm/addrspace.h>
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
 #endif
@@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE];
 void decompress_kernel(void)
 {
        output_data = 0;
-       output_ptr = (unsigned long)&_text+0x20001000;
+       output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
        free_mem_ptr = (unsigned long)&_end;
        free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
 
index 34e2046..2b75b48 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc3
-# Tue Oct 31 12:32:06 2006
+# Linux kernel version: 2.6.19
+# Wed Dec  6 11:59:38 2006
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -37,6 +39,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -118,6 +121,8 @@ CONFIG_SH_R7780RP=y
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -130,6 +135,12 @@ CONFIG_CPU_SH4A=y
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -165,6 +176,7 @@ CONFIG_CPU_SH4A=y
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 CONFIG_CPU_SUBTYPE_SH7780=y
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
@@ -181,8 +193,14 @@ CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 # CONFIG_32BIT is not set
 CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,12 +222,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_INTC2_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
 # Timer support
@@ -220,6 +240,8 @@ CONFIG_SH_TMU=y
 # R7780RP options
 #
 CONFIG_SH_R7780MP=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=32000000
 
 #
@@ -237,6 +259,11 @@ CONFIG_SH_PCLK_FREQ=32000000
 #
 # CONFIG_HD6446X_SERIES is not set
 
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_PUSH_SWITCH=y
+
 #
 # Kernel features
 #
@@ -244,7 +271,7 @@ CONFIG_SH_PCLK_FREQ=32000000
 CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
-# CONFIG_KEXEC is not set
+CONFIG_KEXEC=y
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
@@ -278,10 +305,7 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 #
 # 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
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -341,6 +365,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -556,6 +581,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -572,6 +598,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
 # CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -688,6 +715,7 @@ CONFIG_R8169=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -830,10 +858,6 @@ CONFIG_HW_RANDOM=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1020,7 +1044,7 @@ CONFIG_INOTIFY_USER=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1153,28 +1177,33 @@ CONFIG_NLS_ISO8859_1=y
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
 
 #
 # Kernel hacking
 #
-# CONFIG_PRINTK_TIME is not set
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_PREEMPT 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_BUGVERBOSE is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
@@ -1184,7 +1213,7 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
 # CONFIG_KGDB is not set
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
new file mode 100644 (file)
index 0000000..36cec0b
--- /dev/null
@@ -0,0 +1,826 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19-rc4
+# Sun Nov  5 16:20:10 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
+# CONFIG_GENERIC_TIME is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+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_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_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 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 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_7206_SOLUTION_ENGINE=y
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH2=y
+CONFIG_CPU_SH2A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+CONFIG_CPU_SUBTYPE_SH7206=y
+
+#
+# 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_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+
+#
+# Memory management options
+#
+CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+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
+
+#
+# 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 is not set
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+
+#
+# Timer support
+#
+CONFIG_SH_CMT=y
+# CONFIG_SH_MTU2 is not set
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_MD=6
+
+#
+# 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=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# 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
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_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 is not set
+# CONFIG_UNIX is not set
+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_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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY 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
+# CONFIG_SSFDC 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 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=0x20000000
+CONFIG_MTD_PHYSMAP_LEN=0x1000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_UCLINUX 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=y
+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
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE 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
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+# CONFIG_NETDEVICES 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 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=4
+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_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# 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=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# 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
+
+#
+# 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_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# 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_SYSCTL=y
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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 is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS 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_ENABLE_MUST_CHECK=y
+# 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_BUGVERBOSE is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK 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
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/drivers/Kconfig b/arch/sh/drivers/Kconfig
new file mode 100644 (file)
index 0000000..c54c758
--- /dev/null
@@ -0,0 +1,9 @@
+menu "Additional SuperH Device Drivers"
+
+config PUSH_SWITCH
+       tristate "Push switch support"
+       help
+         This enables support for the push switch framework, a simple
+         framework that allows for sysfs driven switch status reporting.
+
+endmenu
index 338c372..bf18dbf 100644 (file)
@@ -5,4 +5,4 @@
 obj-$(CONFIG_PCI)              += pci/
 obj-$(CONFIG_SH_DMA)           += dma/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
-
+obj-$(CONFIG_PUSH_SWITCH)      += push-switch.o
index 065d4c9..db1295d 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the SuperH DMA specific kernel interface routines under Linux.
 #
 
-obj-y                          += dma-api.o dma-isa.o
+obj-y                          += dma-api.o
+obj-$(CONFIG_ISA_DMA_API)      += dma-isa.o
 obj-$(CONFIG_SYSFS)            += dma-sysfs.o
 obj-$(CONFIG_SH_DMA)           += dma-sh.o
 obj-$(CONFIG_SH_DREAMCAST)     += dma-pvr2.o dma-g2.o
-
index 47c3e83..e062067 100644 (file)
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
 #include <linux/list.h>
 #include <linux/platform_device.h>
+#include <linux/mm.h>
 #include <asm/dma.h>
 
 DEFINE_SPINLOCK(dma_spin_lock);
 static LIST_HEAD(registered_dmac_list);
 
-/*
- * A brief note about the reasons for this API as it stands.
- *
- * For starters, the old ISA DMA API didn't work for us for a number of
- * reasons, for one, the vast majority of channels on the SH DMAC are
- * dual-address mode only, and both the new and the old DMA APIs are after the
- * concept of managing a DMA buffer, which doesn't overly fit this model very
- * well. In addition to which, the new API is largely geared at IOMMUs and
- * GARTs, and doesn't even support the channel notion very well.
- *
- * The other thing that's a marginal issue, is the sheer number of random DMA
- * engines that are present (ie, in boards like the Dreamcast), some of which
- * cascade off of the SH DMAC, and others do not. As such, there was a real
- * need for a scalable subsystem that could deal with both single and
- * dual-address mode usage, in addition to interoperating with cascaded DMACs.
- *
- * There really isn't any reason why this needs to be SH specific, though I'm
- * not aware of too many other processors (with the exception of some MIPS)
- * that have the same concept of a dual address mode, or any real desire to
- * actually make use of the DMAC even if such a subsystem were exposed
- * elsewhere.
- *
- * The idea for this was derived from the ARM port, which acted as an excellent
- * reference when trying to address these issues.
- *
- * It should also be noted that the decision to add Yet Another DMA API(tm) to
- * the kernel wasn't made easily, and was only decided upon after conferring
- * with jejb with regards to the state of the old and new APIs as they applied
- * to these circumstances. Philip Blundell was also a great help in figuring
- * out some single-address mode DMA semantics that were otherwise rather
- * confusing.
- */
-
 struct dma_info *get_dma_info(unsigned int chan)
 {
        struct dma_info *info;
-       unsigned int total = 0;
 
        /*
         * Look for each DMAC's range to determine who the owner of
         * the channel is.
         */
        list_for_each_entry(info, &registered_dmac_list, list) {
-               total += info->nr_channels;
-               if (chan > total)
+               if ((chan <  info->first_channel_nr) ||
+                   (chan >= info->first_channel_nr + info->nr_channels))
                        continue;
 
                return info;
@@ -73,6 +39,22 @@ struct dma_info *get_dma_info(unsigned int chan)
 
        return NULL;
 }
+EXPORT_SYMBOL(get_dma_info);
+
+struct dma_info *get_dma_info_by_name(const char *dmac_name)
+{
+       struct dma_info *info;
+
+       list_for_each_entry(info, &registered_dmac_list, list) {
+               if (dmac_name && (strcmp(dmac_name, info->name) != 0))
+                       continue;
+               else
+                       return info;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(get_dma_info_by_name);
 
 static unsigned int get_nr_channels(void)
 {
@@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void)
 struct dma_channel *get_dma_channel(unsigned int chan)
 {
        struct dma_info *info = get_dma_info(chan);
+       struct dma_channel *channel;
+       int i;
 
-       if (!info)
+       if (unlikely(!info))
                return ERR_PTR(-EINVAL);
 
-       return info->channels + chan;
+       for (i = 0; i < info->nr_channels; i++) {
+               channel = &info->channels[i];
+               if (channel->chan == chan)
+                       return channel;
+       }
+
+       return NULL;
 }
+EXPORT_SYMBOL(get_dma_channel);
 
 int get_dma_residue(unsigned int chan)
 {
        struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       struct dma_channel *channel = get_dma_channel(chan);
 
        if (info->ops->get_residue)
                return info->ops->get_residue(channel);
 
        return 0;
 }
+EXPORT_SYMBOL(get_dma_residue);
 
-int request_dma(unsigned int chan, const char *dev_id)
+static int search_cap(const char **haystack, const char *needle)
 {
-       struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       const char **p;
+
+       for (p = haystack; *p; p++)
+               if (strcmp(*p, needle) == 0)
+                       return 1;
+
+       return 0;
+}
+
+/**
+ * request_dma_bycap - Allocate a DMA channel based on its capabilities
+ * @dmac: List of DMA controllers to search
+ * @caps: List of capabilites
+ *
+ * Search all channels of all DMA controllers to find a channel which
+ * matches the requested capabilities. The result is the channel
+ * number if a match is found, or %-ENODEV if no match is found.
+ *
+ * Note that not all DMA controllers export capabilities, in which
+ * case they can never be allocated using this API, and so
+ * request_dma() must be used specifying the channel number.
+ */
+int request_dma_bycap(const char **dmac, const char **caps, const char *dev_id)
+{
+       unsigned int found = 0;
+       struct dma_info *info;
+       const char **p;
+       int i;
+
+       BUG_ON(!dmac || !caps);
+
+       list_for_each_entry(info, &registered_dmac_list, list)
+               if (strcmp(*dmac, info->name) == 0) {
+                       found = 1;
+                       break;
+               }
+
+       if (!found)
+               return -ENODEV;
+
+       for (i = 0; i < info->nr_channels; i++) {
+               struct dma_channel *channel = &info->channels[i];
+
+               if (unlikely(!channel->caps))
+                       continue;
+
+               for (p = caps; *p; p++) {
+                       if (!search_cap(channel->caps, *p))
+                               break;
+                       if (request_dma(channel->chan, dev_id) == 0)
+                               return channel->chan;
+               }
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(request_dma_bycap);
+
+int dmac_search_free_channel(const char *dev_id)
+{
+       struct dma_channel *channel = { 0 };
+       struct dma_info *info = get_dma_info(0);
+       int i;
+
+       for (i = 0; i < info->nr_channels; i++) {
+               channel = &info->channels[i];
+               if (unlikely(!channel))
+                       return -ENODEV;
+
+               if (atomic_read(&channel->busy) == 0)
+                       break;
+       }
 
-       down(&channel->sem);
+       if (info->ops->request) {
+               int result = info->ops->request(channel);
+               if (result)
+                       return result;
 
-       if (!info->ops || chan >= MAX_DMA_CHANNELS) {
-               up(&channel->sem);
-               return -EINVAL;
+               atomic_set(&channel->busy, 1);
+               return channel->chan;
        }
 
-       atomic_set(&channel->busy, 1);
+       return -ENOSYS;
+}
+
+int request_dma(unsigned int chan, const char *dev_id)
+{
+       struct dma_channel *channel = { 0 };
+       struct dma_info *info = get_dma_info(chan);
+       int result;
+
+       channel = get_dma_channel(chan);
+       if (atomic_xchg(&channel->busy, 1))
+               return -EBUSY;
 
        strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
 
-       up(&channel->sem);
+       if (info->ops->request) {
+               result = info->ops->request(channel);
+               if (result)
+                       atomic_set(&channel->busy, 0);
 
-       if (info->ops->request)
-               return info->ops->request(channel);
+               return result;
+       }
 
        return 0;
 }
+EXPORT_SYMBOL(request_dma);
 
 void free_dma(unsigned int chan)
 {
        struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       struct dma_channel *channel = get_dma_channel(chan);
 
        if (info->ops->free)
                info->ops->free(channel);
 
        atomic_set(&channel->busy, 0);
 }
+EXPORT_SYMBOL(free_dma);
 
 void dma_wait_for_completion(unsigned int chan)
 {
        struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       struct dma_channel *channel = get_dma_channel(chan);
 
        if (channel->flags & DMA_TEI_CAPABLE) {
                wait_event(channel->wait_queue,
@@ -158,21 +238,52 @@ void dma_wait_for_completion(unsigned int chan)
        while (info->ops->get_residue(channel))
                cpu_relax();
 }
+EXPORT_SYMBOL(dma_wait_for_completion);
+
+int register_chan_caps(const char *dmac, struct dma_chan_caps *caps)
+{
+       struct dma_info *info;
+       unsigned int found = 0;
+       int i;
+
+       list_for_each_entry(info, &registered_dmac_list, list)
+               if (strcmp(dmac, info->name) == 0) {
+                       found = 1;
+                       break;
+               }
+
+       if (unlikely(!found))
+               return -ENODEV;
+
+       for (i = 0; i < info->nr_channels; i++, caps++) {
+               struct dma_channel *channel;
+
+               if ((info->first_channel_nr + i) != caps->ch_num)
+                       return -EINVAL;
+
+               channel = &info->channels[i];
+               channel->caps = caps->caplist;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(register_chan_caps);
 
 void dma_configure_channel(unsigned int chan, unsigned long flags)
 {
        struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       struct dma_channel *channel = get_dma_channel(chan);
 
        if (info->ops->configure)
                info->ops->configure(channel, flags);
 }
+EXPORT_SYMBOL(dma_configure_channel);
 
 int dma_xfer(unsigned int chan, unsigned long from,
             unsigned long to, size_t size, unsigned int mode)
 {
        struct dma_info *info = get_dma_info(chan);
-       struct dma_channel *channel = &info->channels[chan];
+       struct dma_channel *channel = get_dma_channel(chan);
 
        channel->sar    = from;
        channel->dar    = to;
@@ -181,8 +292,20 @@ int dma_xfer(unsigned int chan, unsigned long from,
 
        return info->ops->xfer(channel);
 }
+EXPORT_SYMBOL(dma_xfer);
+
+int dma_extend(unsigned int chan, unsigned long op, void *param)
+{
+       struct dma_info *info = get_dma_info(chan);
+       struct dma_channel *channel = get_dma_channel(chan);
+
+       if (info->ops->extend)
+               return info->ops->extend(channel, op, param);
+
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(dma_extend);
 
-#ifdef CONFIG_PROC_FS
 static int dma_read_proc(char *buf, char **start, off_t off,
                         int len, int *eof, void *data)
 {
@@ -214,8 +337,6 @@ static int dma_read_proc(char *buf, char **start, off_t off,
 
        return p - buf;
 }
-#endif
-
 
 int register_dmac(struct dma_info *info)
 {
@@ -224,8 +345,7 @@ int register_dmac(struct dma_info *info)
        INIT_LIST_HEAD(&info->list);
 
        printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
-              info->name, info->nr_channels,
-              info->nr_channels > 1 ? "s" : "");
+              info->name, info->nr_channels, info->nr_channels > 1 ? "s" : "");
 
        BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
 
@@ -242,28 +362,26 @@ int register_dmac(struct dma_info *info)
 
                size = sizeof(struct dma_channel) * info->nr_channels;
 
-               info->channels = kmalloc(size, GFP_KERNEL);
+               info->channels = kzalloc(size, GFP_KERNEL);
                if (!info->channels)
                        return -ENOMEM;
-
-               memset(info->channels, 0, size);
        }
 
        total_channels = get_nr_channels();
        for (i = 0; i < info->nr_channels; i++) {
-               struct dma_channel *chan = info->channels + i;
+               struct dma_channel *chan = &info->channels[i];
+
+               atomic_set(&chan->busy, 0);
 
-               chan->chan = i;
-               chan->vchan = i + total_channels;
+               chan->chan  = info->first_channel_nr + i;
+               chan->vchan = info->first_channel_nr + i + total_channels;
 
                memcpy(chan->dev_id, "Unused", 7);
 
                if (info->flags & DMAC_CHANNELS_TEI_CAPABLE)
                        chan->flags |= DMA_TEI_CAPABLE;
 
-               init_MUTEX(&chan->sem);
                init_waitqueue_head(&chan->wait_queue);
-
                dma_create_sysfs_files(chan, info);
        }
 
@@ -271,6 +389,7 @@ int register_dmac(struct dma_info *info)
 
        return 0;
 }
+EXPORT_SYMBOL(register_dmac);
 
 void unregister_dmac(struct dma_info *info)
 {
@@ -285,31 +404,16 @@ void unregister_dmac(struct dma_info *info)
        list_del(&info->list);
        platform_device_unregister(info->pdev);
 }
+EXPORT_SYMBOL(unregister_dmac);
 
 static int __init dma_api_init(void)
 {
-       printk("DMA: Registering DMA API.\n");
-
-#ifdef CONFIG_PROC_FS
+       printk(KERN_NOTICE "DMA: Registering DMA API.\n");
        create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
-#endif
-
        return 0;
 }
-
 subsys_initcall(dma_api_init);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("DMA API for SuperH");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(request_dma);
-EXPORT_SYMBOL(free_dma);
-EXPORT_SYMBOL(register_dmac);
-EXPORT_SYMBOL(get_dma_residue);
-EXPORT_SYMBOL(get_dma_info);
-EXPORT_SYMBOL(get_dma_channel);
-EXPORT_SYMBOL(dma_xfer);
-EXPORT_SYMBOL(dma_wait_for_completion);
-EXPORT_SYMBOL(dma_configure_channel);
-
index 6607860..f63721e 100644 (file)
@@ -94,20 +94,13 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
        if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
                return 0;
 
-       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, chan->name, chan);
+                          IRQF_DISABLED, chan->dev_id, chan);
 }
 
 static void sh_dmac_free_dma(struct dma_channel *chan)
 {
        free_irq(get_dmte_irq(chan->chan), chan);
-       kfree(chan->name);
 }
 
 static void
index 29b8ef9..eebcd47 100644 (file)
@@ -3,7 +3,7 @@
  *
  * sysfs interface for SH DMA API
  *
- * Copyright (C) 2004, 2005  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
@@ -21,7 +21,6 @@
 static struct sysdev_class dma_sysclass = {
        set_kset_name("dma"),
 };
-
 EXPORT_SYMBOL(dma_sysclass);
 
 static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
@@ -31,7 +30,10 @@ static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
 
        for (i = 0; i < MAX_DMA_CHANNELS; i++) {
                struct dma_info *info = get_dma_info(i);
-               struct dma_channel *channel = &info->channels[i];
+               struct dma_channel *channel = get_dma_channel(i);
+
+               if (unlikely(!info) || !channel)
+                       continue;
 
                len += sprintf(buf + len, "%2d: %14s    %s\n",
                               channel->chan, info->name,
@@ -125,11 +127,16 @@ int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
        if (ret)
                return ret;
 
-       sysdev_create_file(dev, &attr_dev_id);
-       sysdev_create_file(dev, &attr_count);
-       sysdev_create_file(dev, &attr_mode);
-       sysdev_create_file(dev, &attr_flags);
-       sysdev_create_file(dev, &attr_config);
+       ret |= sysdev_create_file(dev, &attr_dev_id);
+       ret |= sysdev_create_file(dev, &attr_count);
+       ret |= sysdev_create_file(dev, &attr_mode);
+       ret |= sysdev_create_file(dev, &attr_flags);
+       ret |= sysdev_create_file(dev, &attr_config);
+
+       if (unlikely(ret)) {
+               dev_err(&info->pdev->dev, "Failed creating attrs\n");
+               return ret;
+       }
 
        snprintf(name, sizeof(name), "dma%d", chan->chan);
        return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name);
index cd56d53..ac8ee23 100644 (file)
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/titan.h>
 #include "pci-sh4.h"
 
+static char titan_irq_tab[] __initdata = {
+       TITAN_IRQ_WAN,
+       TITAN_IRQ_LAN,
+       TITAN_IRQ_MPCIA,
+       TITAN_IRQ_MPCIB,
+       TITAN_IRQ_USB,
+};
+
 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;
-       }
+       int irq = titan_irq_tab[slot];
 
        printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
                slot, pin - 1 + 'A', irq);
index d6e6352..602b644 100644 (file)
 #include <linux/delay.h>
 #include "pci-sh4.h"
 
+#define INTC_BASE      0xffd00000
+#define INTC_ICR0      (INTC_BASE+0x0)
+#define INTC_ICR1      (INTC_BASE+0x1c)
+#define INTC_INTPRI    (INTC_BASE+0x10)
+#define INTC_INTREQ    (INTC_BASE+0x24)
+#define INTC_INTMSK0   (INTC_BASE+0x44)
+#define INTC_INTMSK1   (INTC_BASE+0x48)
+#define INTC_INTMSK2   (INTC_BASE+0x40080)
+#define INTC_INTMSKCLR0        (INTC_BASE+0x64)
+#define INTC_INTMSKCLR1        (INTC_BASE+0x68)
+#define INTC_INTMSKCLR2        (INTC_BASE+0x40084)
+#define INTC_INT2MSKR  (INTC_BASE+0x40038)
+#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
+
 /*
  * 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
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
new file mode 100644 (file)
index 0000000..f2b9157
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Generic push-switch framework
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/push-switch.h>
+
+#define DRV_NAME "push-switch"
+#define DRV_VERSION "0.1.0"
+
+static ssize_t switch_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       struct push_switch_platform_info *psw_info = dev->platform_data;
+       return sprintf(buf, "%s\n", psw_info->name);
+}
+static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL);
+
+static void switch_timer(unsigned long data)
+{
+       struct push_switch *psw = (struct push_switch *)data;
+
+       schedule_work(&psw->work);
+}
+
+static void switch_work_handler(void *data)
+{
+       struct platform_device *pdev = data;
+       struct push_switch *psw = platform_get_drvdata(pdev);
+
+       psw->state = 0;
+
+       kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
+}
+
+static int switch_drv_probe(struct platform_device *pdev)
+{
+       struct push_switch_platform_info *psw_info;
+       struct push_switch *psw;
+       int ret, irq;
+
+       psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
+       if (unlikely(!psw))
+               return -ENOMEM;
+
+       irq = platform_get_irq(pdev, 0);
+       if (unlikely(irq < 0)) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       psw_info = pdev->dev.platform_data;
+       BUG_ON(!psw_info);
+
+       ret = request_irq(irq, psw_info->irq_handler,
+                         IRQF_DISABLED | psw_info->irq_flags,
+                         psw_info->name ? psw_info->name : DRV_NAME, pdev);
+       if (unlikely(ret < 0))
+               goto err;
+
+       if (psw_info->name) {
+               ret = device_create_file(&pdev->dev, &dev_attr_switch);
+               if (unlikely(ret)) {
+                       dev_err(&pdev->dev, "Failed creating device attrs\n");
+                       ret = -EINVAL;
+                       goto err_irq;
+               }
+       }
+
+       INIT_WORK(&psw->work, switch_work_handler, pdev);
+       init_timer(&psw->debounce);
+
+       psw->debounce.function = switch_timer;
+       psw->debounce.data = (unsigned long)psw;
+
+       platform_set_drvdata(pdev, psw);
+
+       return 0;
+
+err_irq:
+       free_irq(irq, pdev);
+err:
+       kfree(psw);
+       return ret;
+}
+
+static int switch_drv_remove(struct platform_device *pdev)
+{
+       struct push_switch *psw = platform_get_drvdata(pdev);
+       struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
+       int irq = platform_get_irq(pdev, 0);
+
+       if (psw_info->name)
+               device_remove_file(&pdev->dev, &dev_attr_switch);
+
+       platform_set_drvdata(pdev, NULL);
+       flush_scheduled_work();
+       del_timer_sync(&psw->debounce);
+       free_irq(irq, pdev);
+
+       kfree(psw);
+
+       return 0;
+}
+
+static struct platform_driver switch_driver = {
+       .probe          = switch_drv_probe,
+       .remove         = switch_drv_remove,
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init switch_init(void)
+{
+       printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
+       return platform_driver_register(&switch_driver);
+}
+
+static void __exit switch_exit(void)
+{
+       platform_driver_unregister(&switch_driver);
+}
+module_init(switch_init);
+module_exit(switch_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt");
+MODULE_LICENSE("GPLv2");
index 5da88a4..99c7e52 100644 (file)
@@ -4,7 +4,7 @@
 
 extra-y        := head.o init_task.o vmlinux.lds
 
-obj-y  := process.o signal.o entry.o traps.o irq.o \
+obj-y  := process.o signal.o traps.o irq.o \
        ptrace.o setup.o time.o sys_sh.o semaphore.o \
        io.o io_generic.o sh_ksyms.o syscalls.o
 
@@ -21,3 +21,4 @@ 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
+obj-$(CONFIG_STACKTRACE)       += stacktrace.o
index fb5dac0..0582e67 100644 (file)
@@ -2,11 +2,12 @@
 # Makefile for the Linux/SuperH CPU-specifc backends.
 #
 
-obj-y  += irq/ init.o clock.o
-
-obj-$(CONFIG_CPU_SH2)          += sh2/
-obj-$(CONFIG_CPU_SH3)          += sh3/
-obj-$(CONFIG_CPU_SH4)          += sh4/
+obj-$(CONFIG_CPU_SH2)          = sh2/
+obj-$(CONFIG_CPU_SH2A)         = sh2a/
+obj-$(CONFIG_CPU_SH3)          = sh3/
+obj-$(CONFIG_CPU_SH4)          = sh4/
 
 obj-$(CONFIG_UBC_WAKEUP)       += ubc.o
 obj-$(CONFIG_SH_ADC)           += adc.o
+
+obj-y  += irq/ init.o clock.o
index 51ec64c..abb586b 100644 (file)
@@ -5,9 +5,11 @@
  *
  * This clock framework is derived from the OMAP version by:
  *
- *     Copyright (C) 2004 Nokia Corporation
+ *     Copyright (C) 2004 - 2005 Nokia Corporation
  *     Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
+ *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.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.
@@ -20,6 +22,7 @@
 #include <linux/kref.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
+#include <linux/platform_device.h>
 #include <asm/clock.h>
 #include <asm/timer.h>
 
@@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk)
                propagate_rate(clk);
 }
 
-struct clk *clk_get(const char *id)
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
+       int idno;
+
+       if (dev == NULL || dev->bus != &platform_bus_type)
+               idno = -1;
+       else
+               idno = to_platform_device(dev)->id;
 
        mutex_lock(&clock_list_sem);
+       list_for_each_entry(p, &clock_list, node) {
+               if (p->id == idno &&
+                   strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       goto found;
+               }
+       }
+
        list_for_each_entry(p, &clock_list, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
+
+found:
        mutex_unlock(&clock_list_sem);
 
        return clk;
index bfb90eb..4812176 100644 (file)
@@ -68,12 +68,14 @@ static void __init cache_init(void)
 
                waysize = cpu_data->dcache.sets;
 
+#ifdef CCR_CACHE_ORA
                /*
                 * If the OC is already in RAM mode, we only have
                 * half of the entries to flush..
                 */
                if (ccr & CCR_CACHE_ORA)
                        waysize >>= 1;
+#endif
 
                waysize <<= cpu_data->dcache.entry_shift;
 
index 1c034c2..0049d21 100644 (file)
@@ -1,8 +1,9 @@
 #
 # Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
 #
-obj-y  += ipr.o imask.o
+obj-y  += imask.o
 
+obj-$(CONFIG_CPU_HAS_IPR_IRQ)          += ipr.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 a33ae3e..301b505 100644 (file)
@@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip)
 {
        unsigned long __dummy;
 
-       asm volatile("ldc       %2, r6_bank\n\t"
+       asm volatile(
+#ifdef CONFIG_CPU_HAS_SR_RB
+                    "ldc       %2, r6_bank\n\t"
+#endif
                     "stc       sr, %0\n\t"
                     "and       #0xf0, %0\n\t"
                     "shlr2     %0\n\t"
index 74ca576..74defe7 100644 (file)
  * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
  */
 #include <linux/kernel.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
-#include <asm/system.h>
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define INTC2_BASE     0xfe080000
+#define INTC2_INTMSK   (INTC2_BASE + 0x40)
+#define INTC2_INTMSKCLR        (INTC2_BASE + 0x60)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define INTC2_BASE     0xffd40000
+#define INTC2_INTMSK   (INTC2_BASE + 0x38)
+#define INTC2_INTMSKCLR        (INTC2_BASE + 0x3c)
+#endif
 
 static void disable_intc2_irq(unsigned int irq)
 {
        struct intc2_data *p = get_irq_chip_data(irq);
-       ctrl_outl(1 << p->msk_shift,
-                 INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
+       ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
 }
 
 static void enable_intc2_irq(unsigned int irq)
 {
        struct intc2_data *p = get_irq_chip_data(irq);
-       ctrl_outl(1 << p->msk_shift,
-                 INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
+       ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
 }
 
 static struct irq_chip intc2_irq_chip = {
@@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
                /* Set the priority level */
                local_irq_save(flags);
 
-               ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET +
-                              p->ipr_offset);
+               ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
                ipr &= ~(0xf << p->ipr_shift);
                ipr |= p->priority << p->ipr_shift;
-               ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET +
-                         p->ipr_offset);
+               ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
 
                local_irq_restore(flags);
 
index a008956..35eb575 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/module.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-
+#include <linux/io.h>
+#include <linux/interrupt.h>
 
 static void disable_ipr_irq(unsigned int irq)
 {
        struct ipr_data *p = get_irq_chip_data(irq);
-       int shift = p->shift*4;
        /* Set the priority in IPR to 0 */
-       ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr);
+       ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
        struct ipr_data *p = get_irq_chip_data(irq);
-       int shift = p->shift*4;
        /* Set priority in IPR back to original value */
-       ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr);
+       ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
 }
 
 static struct irq_chip ipr_irq_chip = {
@@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
 
        for (i = 0; i < nr_irqs; i++) {
                unsigned int irq = table[i].irq;
+               table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+               /* could the IPR index be mapped, if not we ignore this */
+               if (table[i].addr == 0)
+                       continue;
                disable_irq_nosync(irq);
                set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
                                      handle_level_irq, "level");
@@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
 }
 EXPORT_SYMBOL(make_ipr_irq);
 
-static struct ipr_data sys_ipr_map[] = {
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
-       { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
-       { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY },
-#ifdef RTC_IRQ
-       { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY },
-#endif
-#ifdef SCI_ERI_IRQ
-       { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
-       { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
-       { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
-#endif
-#ifdef SCIF1_ERI_IRQ
-       { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
-       { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
-       { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
-       { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-       { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
-       { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
-#endif
-#ifdef SCIF_ERI_IRQ
-       { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
-       { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
-       { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
-       { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
-#endif
-#ifdef IRDA_ERI_IRQ
-       { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
-       { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
-       { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
-       { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
-#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)
-        * registers to their power on values
-        */
-
-       /*
-        * Enable external irq (INTC IRQ mode).
-        * You should set corresponding bits of PFC to "00"
-        * to enable these interrupts.
-        */
-       { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY },
-       { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY },
-       { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY },
-       { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY },
-       { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY },
-       { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY },
-#endif
-#endif
-};
-
-void __init init_IRQ(void)
-{
-       make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map));
-
-#ifdef CONFIG_CPU_HAS_PINT_IRQ
-       init_IRQ_pint();
-#endif
-
-#ifdef CONFIG_CPU_HAS_INTC2_IRQ
-       init_IRQ_intc2();
-#endif
-       /* 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)
 int ipr_irq_demux(int irq)
 {
index 389353f..f0f059a 100644 (file)
@@ -2,5 +2,6 @@
 # Makefile for the Linux/SuperH SH-2 backends.
 #
 
-obj-y  := probe.o
+obj-y  := ex.o probe.o entry.o
 
+obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
new file mode 100644 (file)
index 0000000..d0440b2
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * arch/sh/kernel/cpu/sh2/clock-sh7619.c
+ *
+ * SH7619 support for the clock framework
+ *
+ *  Copyright (C) 2006  Yoshinori Sato
+ *
+ * Based on clock-sh4.c
+ *  Copyright (C) 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+const static int pll1rate[]={1,2};
+const static int pfc_divisors[]={1,2,0,4};
+
+#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
+#define PLL2 (4)
+#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
+#define PLL2 (2)
+#else
+#error "Illigal Clock Mode!"
+#endif
+
+static void master_clk_init(struct clk *clk)
+{
+       clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+}
+
+static struct clk_ops sh7619_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(FREQCR) & 0x0007);
+       clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7619_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+}
+
+static struct clk_ops sh7619_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       clk->rate = clk->parent->rate;
+}
+
+static struct clk_ops sh7619_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7619_clk_ops[] = {
+       &sh7619_master_clk_ops,
+       &sh7619_module_clk_ops,
+       &sh7619_bus_clk_ops,
+       &sh7619_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7619_clk_ops))
+               *ops = sh7619_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
new file mode 100644 (file)
index 0000000..34d51b3
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * arch/sh/kernel/cpu/sh2/entry.S
+ *
+ * The SH-2 exception entry
+ *
+ * Copyright (C) 2005,2006 Yoshinori Sato
+ * Copyright (C) 2005  AXE,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/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpu/mmu_context.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/page.h>
+       
+/* Offsets to the stack */
+OFF_R0  =  0           /* Return value. New ABI also arg4 */
+OFF_R1  =  4           /* New ABI: arg5 */
+OFF_R2  =  8           /* New ABI: arg6 */
+OFF_R3  =  12          /* New ABI: syscall_nr */
+OFF_R4  =  16          /* New ABI: arg0 */
+OFF_R5  =  20          /* New ABI: arg1 */
+OFF_R6  =  24          /* New ABI: arg2 */
+OFF_R7  =  28          /* New ABI: arg3 */
+OFF_SP =  (15*4)
+OFF_PC  =  (16*4)
+OFF_SR =  (16*4+2*4)
+OFF_TRA        =  (16*4+6*4)
+
+#include <asm/entry-macros.S>
+
+ENTRY(exception_handler)
+       ! already saved r0/r1
+       mov.l   r2,@-sp
+       mov.l   r3,@-sp
+       mov     r0,r1
+       cli
+       mov.l   $cpu_mode,r2
+       mov.l   @r2,r0
+       mov.l   @(5*4,r15),r3   ! previous SR
+       shll2   r3              ! set "S" flag
+       rotl    r0              ! T <- "S" flag
+       rotl    r0              ! "S" flag is LSB
+       rotcr   r3              ! T -> r3:b30
+       shlr    r3
+       shlr    r0
+       bt/s    1f
+        mov.l  r3,@(5*4,r15)   ! copy cpu mode to SR
+       ! switch to kernel mode
+       mov     #1,r0
+       rotr    r0
+       rotr    r0
+       mov.l   r0,@r2          ! enter kernel mode
+       mov.l   $current_thread_info,r2
+       mov.l   @r2,r2
+       mov     #0x20,r0
+       shll8   r0
+       add     r2,r0
+       mov     r15,r2          ! r2 = user stack top
+       mov     r0,r15          ! switch kernel stack
+       add     #-4,r15         ! dummy
+       mov.l   r1,@-r15        ! TRA
+       sts.l   macl, @-r15
+       sts.l   mach, @-r15
+       stc.l   gbr, @-r15
+       mov.l   @(4*4,r2),r0
+       mov.l   @(5*4,r2),r1
+       mov.l   r1,@-r15        ! original SR
+       sts.l   pr,@-r15
+       mov.l   r0,@-r15        ! original PC
+       mov     r2,r3
+       add     #(4+2)*4,r3     ! rewind r0 - r3 + exception frame
+       mov.l   r3,@-r15        ! original SP
+       mov.l   r14,@-r15
+       mov.l   r13,@-r15
+       mov.l   r12,@-r15
+       mov.l   r11,@-r15
+       mov.l   r10,@-r15
+       mov.l   r9,@-r15
+       mov.l   r8,@-r15
+       mov.l   r7,@-r15
+       mov.l   r6,@-r15
+       mov.l   r5,@-r15
+       mov.l   r4,@-r15
+       mov     r2,r8           ! copy user -> kernel stack
+       mov.l   @r8+,r3
+       mov.l   r3,@-r15
+       mov.l   @r8+,r2
+       mov.l   r2,@-r15
+       mov.l   @r8+,r1
+       mov.l   r1,@-r15
+       mov.l   @r8+,r0
+       bra     2f
+        mov.l  r0,@-r15
+1:
+       ! in kernel exception
+       mov     #(22-4-4-1)*4+4,r0
+       mov     r15,r2
+       sub     r0,r15
+       mov.l   @r2+,r0         ! old R3
+       mov.l   r0,@-r15        
+       mov.l   @r2+,r0         ! old R2
+       mov.l   r0,@-r15        
+       mov.l   @r2+,r0         ! old R1
+       mov.l   r0,@-r15        
+       mov.l   @r2+,r0         ! old R0
+       mov.l   r0,@-r15        
+       mov.l   @r2+,r3         ! old PC
+       mov.l   @r2+,r0         ! old SR
+       add     #-4,r2          ! exception frame stub (sr)
+       mov.l   r1,@-r2         ! TRA
+       sts.l   macl, @-r2
+       sts.l   mach, @-r2
+       stc.l   gbr, @-r2
+       mov.l   r0,@-r2         ! save old SR
+       sts.l   pr,@-r2
+       mov.l   r3,@-r2         ! save old PC
+       mov     r2,r0
+       add     #8*4,r0
+       mov.l   r0,@-r2         ! save old SP
+       mov.l   r14,@-r2
+       mov.l   r13,@-r2
+       mov.l   r12,@-r2
+       mov.l   r11,@-r2
+       mov.l   r10,@-r2
+       mov.l   r9,@-r2
+       mov.l   r8,@-r2
+       mov.l   r7,@-r2
+       mov.l   r6,@-r2
+       mov.l   r5,@-r2
+       mov.l   r4,@-r2
+       mov.l   @(OFF_R0,r15),r0
+       mov.l   @(OFF_R1,r15),r1
+       mov.l   @(OFF_R2,r15),r2
+       mov.l   @(OFF_R3,r15),r3
+2:
+       mov     #OFF_TRA,r8
+       add     r15,r8
+       mov.l   @r8,r9  
+       mov     #64,r8
+       cmp/hs  r8,r9
+       bt      interrupt_entry ! vec >= 64 is interrupt
+       mov     #32,r8
+       cmp/hs  r8,r9
+       bt      trap_entry      ! 64 > vec >= 32  is trap
+       mov.l   4f,r8
+       mov     r9,r4
+       shll2   r9
+       add     r9,r8
+       mov.l   @r8,r8
+       mov     #0,r9
+       cmp/eq  r9,r8
+       bf      3f
+       mov.l   8f,r8           ! unhandled exception
+3:
+       mov.l   5f,r10
+       jmp     @r8
+        lds    r10,pr
+
+interrupt_entry:
+       mov     r9,r4
+       mov.l   6f,r9
+       mov.l   7f,r8
+       jmp     @r8
+        lds    r9,pr
+
+       .align  2
+4:     .long   exception_handling_table
+5:     .long   ret_from_exception
+6:     .long   ret_from_irq
+7:     .long   do_IRQ
+8:     .long   do_exception_error
+       
+trap_entry:    
+       add     #-0x10,r9
+       shll2   r9                      ! TRA
+       mov     #OFF_TRA,r8
+       add     r15,r8
+       mov.l   r9,@r8
+       mov     r9,r8
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   5f, r9
+       jsr     @r9
+        nop
+#endif
+       sti
+       bra     system_call
+        nop
+       
+       .align  2
+1:     .long   syscall_exit
+2:     .long   break_point_trap_software
+3:     .long   NR_syscalls
+4:     .long   sys_call_table
+#ifdef CONFIG_TRACE_IRQFLAGS
+5:     .long   trace_hardirqs_on
+#endif
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+       /* Unwind the stack and jmp to the debug entry */
+debug_kernel_fw:
+       mov     r15,r0
+       add     #(22-4)*4-4,r0
+       ldc.l   @r0+,gbr
+       lds.l   @r0+,mach
+       lds.l   @r0+,macl
+       mov     r15,r0
+       mov.l   @(OFF_SP,r0),r1
+       mov     #OFF_SR,r2
+       mov.l   @(r0,r2),r3
+       mov.l   r3,@-r1
+       mov     #OFF_SP,r2
+       mov.l   @(r0,r2),r3
+       mov.l   r3,@-r1
+       mov     r15,r0
+       add     #(22-4)*4-8,r0
+       mov.l   1f,r2
+       mov.l   @r2,r2
+       stc     sr,r3
+       mov.l   r2,@r0
+       mov.l   r3,@r0
+       mov.l   r1,@(8,r0)      
+       mov.l   @r15+, r0
+       mov.l   @r15+, r1
+       mov.l   @r15+, r2
+       mov.l   @r15+, r3
+       mov.l   @r15+, r4
+       mov.l   @r15+, r5
+       mov.l   @r15+, r6
+       mov.l   @r15+, r7
+       mov.l   @r15+, r8
+       mov.l   @r15+, r9
+       mov.l   @r15+, r10
+       mov.l   @r15+, r11
+       mov.l   @r15+, r12
+       mov.l   @r15+, r13
+       mov.l   @r15+, r14
+       add     #8,r15
+       lds.l   @r15+, pr
+       rte
+        mov.l  @r15+,r15
+       .align  2
+1:     .long   gdb_vbr_vector
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
+ENTRY(address_error_handler)
+       mov     r15,r4                          ! regs
+       add     #4,r4
+       mov     #OFF_PC,r0
+       mov.l   @(r0,r15),r6                    ! pc
+       mov.l   1f,r0
+       jmp     @r0
+        mov    #0,r5                           ! writeaccess is unknown
+       .align  2
+
+1:     .long   do_address_error
+
+restore_all:
+       cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   3f, r0
+       jsr     @r0
+        nop
+#endif
+       mov     r15,r0
+       mov.l   $cpu_mode,r2
+       mov     #OFF_SR,r3
+       mov.l   @(r0,r3),r1
+       mov.l   r1,@r2
+       shll2   r1                              ! clear MD bit
+       shlr2   r1
+       mov.l   @(OFF_SP,r0),r2
+       add     #-8,r2
+       mov.l   r2,@(OFF_SP,r0)                 ! point exception frame top
+       mov.l   r1,@(4,r2)                      ! set sr
+       mov     #OFF_PC,r3
+       mov.l   @(r0,r3),r1
+       mov.l   r1,@r2                          ! set pc
+       add     #4*16+4,r0
+       lds.l   @r0+,pr
+       add     #4,r0                           ! skip sr
+       ldc.l   @r0+,gbr
+       lds.l   @r0+,mach
+       lds.l   @r0+,macl
+       get_current_thread_info r0, r1
+       mov.l   $current_thread_info,r1
+       mov.l   r0,@r1
+       mov.l   @r15+,r0
+       mov.l   @r15+,r1
+       mov.l   @r15+,r2
+       mov.l   @r15+,r3
+       mov.l   @r15+,r4
+       mov.l   @r15+,r5
+       mov.l   @r15+,r6
+       mov.l   @r15+,r7
+       mov.l   @r15+,r8
+       mov.l   @r15+,r9
+       mov.l   @r15+,r10
+       mov.l   @r15+,r11
+       mov.l   @r15+,r12
+       mov.l   @r15+,r13
+       mov.l   @r15+,r14
+       mov.l   @r15,r15
+       rte
+        nop
+2:
+       mov.l   1f,r8
+       mov.l   2f,r9
+       jmp     @r9
+        lds    r8,pr
+
+       .align  2
+$current_thread_info:
+       .long   __current_thread_info
+$cpu_mode:     
+       .long   __cpu_mode
+#ifdef CONFIG_TRACE_IRQFLAGS
+3:     .long   trace_hardirqs_off
+#endif
+               
+! common exception handler
+#include "../../entry-common.S"
+       
+       .data
+! cpu operation mode 
+! bit30 = MD (compatible SH3/4)
+__cpu_mode:
+       .long   0x40000000
+               
+       .section        .bss
+__current_thread_info:
+       .long   0
+
+ENTRY(exception_handling_table)
+       .space  4*32
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S
new file mode 100644 (file)
index 0000000..6d285af
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * arch/sh/kernel/cpu/sh2/ex.S
+ *
+ * The SH-2 exception vector table
+ *
+ * Copyright (C) 2005 Yoshinori Sato
+ *
+ * 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>
+
+!
+! convert Exception Vector to Exception Number
+!
+exception_entry:       
+no     =       0
+       .rept   256
+       mov.l   r0,@-sp
+       mov     #no,r0
+       bra     exception_trampoline
+       and     #0xff,r0
+no     =       no + 1
+       .endr
+exception_trampoline:
+       mov.l   r1,@-sp
+       mov.l   $exception_handler,r1
+       jmp     @r1
+
+       .align  2
+$exception_entry:
+       .long   exception_entry
+$exception_handler:
+       .long   exception_handler
+!
+! Exception Vector Base
+!
+       .align  2
+ENTRY(vbr_base)
+vector =       0
+       .rept   256
+       .long   exception_entry + vector * 8
+vector =       vector + 1
+       .endr
index f17a2a0..ba527d9 100644 (file)
 
 int __init detect_cpu_and_cache_system(void)
 {
-       /*
-        * For now, assume SH7604 .. fix this later.
-        */
+#if defined(CONFIG_CPU_SUBTYPE_SH7604)
        cpu_data->type                  = CPU_SH7604;
        cpu_data->dcache.ways           = 4;
-       cpu_data->dcache.way_shift      = 6;
+       cpu_data->dcache.way_incr       = (1<<10);
        cpu_data->dcache.sets           = 64;
        cpu_data->dcache.entry_shift    = 4;
        cpu_data->dcache.linesz         = L1_CACHE_BYTES;
        cpu_data->dcache.flags          = 0;
-
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+       cpu_data->type                  = CPU_SH7619;
+       cpu_data->dcache.ways           = 4;
+       cpu_data->dcache.way_incr       = (1<<12);
+       cpu_data->dcache.sets           = 256;
+       cpu_data->dcache.entry_shift    = 4;
+       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
+       cpu_data->dcache.flags          = 0;
+#endif
        /*
         * SH-2 doesn't have separate caches
         */
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
new file mode 100644 (file)
index 0000000..82c2d90
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7619 Setup
+ *
+ *  Copyright (C) 2006  Yoshinori Sato
+ *
+ * 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        = 0xf8400000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 88, 89, 91, 90},
+       }, {
+               .mapbase        = 0xf8410000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 92, 93, 95, 94},
+       }, {
+               .mapbase        = 0xf8420000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 96, 97, 99, 98},
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7619_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7619_devices_setup(void)
+{
+       return platform_add_devices(sh7619_devices,
+                                   ARRAY_SIZE(sh7619_devices));
+}
+__initcall(sh7619_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
new file mode 100644 (file)
index 0000000..350972a
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the Linux/SuperH SH-2A backends.
+#
+
+obj-y  := common.o probe.o
+
+common-y       += $(addprefix ../sh2/, ex.o)
+common-y       += $(addprefix ../sh2/, entry.o)
+
+obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
new file mode 100644 (file)
index 0000000..a9ad309
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7206.c
+ *
+ * SH7206 support for the clock framework
+ *
+ *  Copyright (C) 2006  Yoshinori Sato
+ *
+ * Based on clock-sh4.c
+ *  Copyright (C) 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+const static int pll1rate[]={1,2,3,4,6,8};
+const static int pfc_divisors[]={1,2,3,4,6,8,12};
+#define ifc_divisors pfc_divisors
+
+#if (CONFIG_SH_CLK_MD == 2)
+#define PLL2 (4)
+#elif (CONFIG_SH_CLK_MD == 6)
+#define PLL2 (2)
+#elif (CONFIG_SH_CLK_MD == 7)
+#define PLL2 (1)
+#else
+#error "Illigal Clock Mode!"
+#endif
+
+static void master_clk_init(struct clk *clk)
+{
+       clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+}
+
+static struct clk_ops sh7206_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(FREQCR) & 0x0007);
+       clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7206_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+}
+
+static struct clk_ops sh7206_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(FREQCR) & 0x0007);
+       clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7206_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7206_clk_ops[] = {
+       &sh7206_master_clk_ops,
+       &sh7206_module_clk_ops,
+       &sh7206_bus_clk_ops,
+       &sh7206_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7206_clk_ops))
+               *ops = sh7206_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
new file mode 100644 (file)
index 0000000..87c6c05
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/probe.c
+ *
+ * CPU Subtype Probing for SH-2A.
+ *
+ * Copyright (C) 2004, 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.
+ */
+
+#include <linux/init.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+int __init detect_cpu_and_cache_system(void)
+{
+       /* Just SH7206 for now .. */
+       cpu_data->type                  = CPU_SH7206;
+
+       cpu_data->dcache.ways           = 4;
+       cpu_data->dcache.way_incr       = (1 << 11);
+       cpu_data->dcache.sets           = 128;
+       cpu_data->dcache.entry_shift    = 4;
+       cpu_data->dcache.linesz         = L1_CACHE_BYTES;
+       cpu_data->dcache.flags          = 0;
+
+       /*
+        * The icache is the same as the dcache as far as this setup is
+        * concerned. The only real difference in hardware is that the icache
+        * lacks the U bit that the dcache has, none of this has any bearing
+        * on the cache info.
+        */
+       cpu_data->icache                = cpu_data->dcache;
+
+       return 0;
+}
+
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
new file mode 100644 (file)
index 0000000..cdfeef4
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * SH7206 Setup
+ *
+ *  Copyright (C) 2006  Yoshinori Sato
+ *
+ * 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        = 0xfffe8000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 240, 241, 242, 243},
+       }, {
+               .mapbase        = 0xfffe8800,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 244, 245, 246, 247},
+       }, {
+               .mapbase        = 0xfffe9000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 248, 249, 250, 251},
+       }, {
+               .mapbase        = 0xfffe9800,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           =  { 252, 253, 254, 255},
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7206_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7206_devices_setup(void)
+{
+       return platform_add_devices(sh7206_devices,
+                                   ARRAY_SIZE(sh7206_devices));
+}
+__initcall(sh7206_devices_setup);
index 58d3815..83905e4 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH SH-3 backends.
 #
 
-obj-y  := ex.o probe.o
+obj-y  := ex.o probe.o entry.o
 
 # CPU subtype setup
 obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o
index 10461a7..b791a29 100644 (file)
@@ -24,7 +24,7 @@ static int pfc_divisors[]    = { 1, 2, 4, 1, 3, 6, 1, 1 };
 
 static void set_bus_parent(struct clk *clk)
 {
-       struct clk *bus_clk = clk_get("bus_clk");
+       struct clk *bus_clk = clk_get(NULL, "bus_clk");
        clk->parent = bus_clk;
        clk_put(bus_clk);
 }
similarity index 58%
rename from arch/sh/kernel/entry.S
rename to arch/sh/kernel/cpu/sh3/entry.S
index 39aaefb..8c0dc27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/sh/entry.S
+ * arch/sh/kernel/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2006  Paul Mundt
@@ -7,15 +7,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/sys.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
-#include <asm/cpu/mmu_context.h>
 #include <asm/unistd.h>
+#include <asm/cpu/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -81,6 +82,8 @@ OFF_TRA       =  (16*4+6*4)
 #define k_g_imask      r6_bank /* r6_bank1 */
 #define current                r7      /* r7_bank1 */
 
+#include <asm/entry-macros.S>
+       
 /*
  * Kernel mode register usage:
  *     k0      scratch
@@ -107,26 +110,6 @@ OFF_TRA    =  (16*4+6*4)
 ! this first version depends *much* on C implementation.
 !
 
-#define CLI()                          \
-       stc     sr, r0;                 \
-       or      #0xf0, r0;              \
-       ldc     r0, sr
-
-#define STI()                          \
-       mov.l   __INV_IMASK, r11;       \
-       stc     sr, r10;                \
-       and     r11, r10;               \
-       stc     k_g_imask, r11;         \
-       or      r11, r10;               \
-       ldc     r10, sr
-
-#if defined(CONFIG_PREEMPT)
-#  define preempt_stop()       CLI()
-#else
-#  define preempt_stop()
-#  define resume_kernel                restore_all
-#endif
-
 #if defined(CONFIG_MMU)
        .align  2
 ENTRY(tlb_miss_load)
@@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store)
 
 call_dpf:
        mov.l   1f, r0
-       mov     r5, r8
-       mov.l   @r0, r6
-       mov     r6, r9
-       mov.l   2f, r0
-       sts     pr, r10
-       jsr     @r0
-        mov    r15, r4
-       !
-       tst     r0, r0
-       bf/s    0f
-        lds    r10, pr
-       rts
-        nop
-0:     STI()
+       mov.l   @r0, r6         ! address
        mov.l   3f, r0
-       mov     r9, r6
-       mov     r8, r5
+
        jmp     @r0
-        mov    r15, r4
+        mov    r15, r4         ! regs
 
        .align 2
 1:     .long   MMU_TEA
-2:     .long   __do_page_fault
 3:     .long   do_page_fault
 
        .align  2
@@ -203,32 +171,6 @@ call_dae:
 2:     .long   do_address_error
 #endif /* CONFIG_MMU */
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
-! If both are configured, handle the debug traps (breakpoints) in SW,
-! but still allow BIOS traps to FW.
-
-       .align  2
-debug_kernel:
-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
-       /* Force BIOS call to FW (debug_trap put TRA in r8) */
-       mov     r8,r0
-       shlr2   r0
-       cmp/eq  #0x3f,r0
-       bt      debug_kernel_fw
-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
-
-debug_enter:           
-#if defined(CONFIG_SH_KGDB)
-       /* Jump to kgdb, pass stacked regs as arg */
-debug_kernel_sw:
-       mov.l   3f, r0
-       jmp     @r0
-        mov    r15, r4
-       .align  2
-3:     .long   kgdb_handle_exception
-#endif /* CONFIG_SH_KGDB */
-
 #if defined(CONFIG_SH_STANDARD_BIOS)
        /* Unwind the stack and jmp to the debug entry */
 debug_kernel_fw:
@@ -269,276 +211,6 @@ debug_kernel_fw:
 2:     .long   gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
 
-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-
-
-       .align  2
-debug_trap:    
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-       mov     #OFF_SR, r0
-       mov.l   @(r0,r15), r0           ! get status register
-       shll    r0
-       shll    r0                      ! kernel space?
-       bt/s    debug_kernel
-#endif
-        mov.l  @r15, r0                ! Restore R0 value
-       mov.l   1f, r8
-       jmp     @r8
-        nop
-
-       .align  2
-ENTRY(exception_error)
-       !
-       STI()
-       mov.l   2f, r0
-       jmp     @r0
-        nop
-
-!
-       .align  2
-1:     .long   break_point_trap_software
-2:     .long   do_exception_error
-
-       .align  2
-ret_from_exception:
-       preempt_stop()
-ENTRY(ret_from_irq)
-       !
-       mov     #OFF_SR, r0
-       mov.l   @(r0,r15), r0   ! get status register
-       shll    r0
-       shll    r0              ! kernel space?
-       bt/s    resume_kernel   ! Yes, it's from kernel, go back soon
-        GET_THREAD_INFO(r8)
-
-#ifdef CONFIG_PREEMPT
-       bra     resume_userspace
-        nop
-ENTRY(resume_kernel)
-       mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
-       tst     r0, r0
-       bf      noresched
-need_resched:
-       mov.l   @(TI_FLAGS,r8), r0      ! current_thread_info->flags
-       tst     #_TIF_NEED_RESCHED, r0  ! need_resched set?
-       bt      noresched
-
-       mov     #OFF_SR, r0
-       mov.l   @(r0,r15), r0           ! get status register
-       and     #0xf0, r0               ! interrupts off (exception path)?
-       cmp/eq  #0xf0, r0
-       bt      noresched
-
-       mov.l   1f, r0
-       mov.l   r0, @(TI_PRE_COUNT,r8)
-
-       STI()
-       mov.l   2f, r0
-       jsr     @r0
-        nop
-       mov     #0, r0
-       mov.l   r0, @(TI_PRE_COUNT,r8)
-       CLI()
-
-       bra     need_resched
-        nop
-noresched:
-       bra     restore_all
-        nop
-
-       .align 2
-1:     .long   PREEMPT_ACTIVE
-2:     .long   schedule
-#endif
-
-ENTRY(resume_userspace)
-       ! r8: current_thread_info
-       CLI()
-       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_WORK_MASK, r0
-       bt/s    restore_all
-        tst    #_TIF_NEED_RESCHED, r0
-
-       .align  2
-work_pending:
-       ! r0: current_thread_info->flags
-       ! r8: current_thread_info
-       ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
-       bf/s    work_resched
-        tst    #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
-work_notifysig:
-       bt/s    restore_all
-        mov    r15, r4
-       mov     r12, r5         ! set arg1(save_r0)
-       mov     r0, r6
-       mov.l   2f, r1
-       mova    restore_all, r0
-       jmp     @r1
-        lds    r0, pr
-work_resched:
-#ifndef CONFIG_PREEMPT
-       ! gUSA handling
-       mov.l   @(OFF_SP,r15), r0       ! get user space stack pointer
-       mov     r0, r1
-       shll    r0
-       bf/s    1f
-        shll   r0
-       bf/s    1f
-        mov    #OFF_PC, r0
-       !                                 SP >= 0xc0000000 : gUSA mark
-       mov.l   @(r0,r15), r2           ! get user space PC (program counter)
-       mov.l   @(OFF_R0,r15), r3       ! end point
-       cmp/hs  r3, r2                  ! r2 >= r3? 
-       bt      1f
-       add     r3, r1                  ! rewind point #2
-       mov.l   r1, @(r0,r15)           ! reset PC to rewind point #2
-       !
-1:
-#endif
-       mov.l   1f, r1
-       jsr     @r1                             ! schedule
-        nop
-       CLI()
-       !
-       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_WORK_MASK, r0
-       bt      restore_all
-       bra     work_pending
-        tst    #_TIF_NEED_RESCHED, r0
-
-       .align  2
-1:     .long   schedule
-2:     .long   do_notify_resume
-
-       .align  2
-syscall_exit_work:
-       ! r0: current_thread_info->flags
-       ! r8: current_thread_info
-       tst     #_TIF_SYSCALL_TRACE, r0
-       bt/s    work_pending
-        tst    #_TIF_NEED_RESCHED, r0
-       STI()
-       ! XXX setup arguments...
-       mov.l   4f, r0                  ! do_syscall_trace
-       jsr     @r0
-        nop
-       bra     resume_userspace
-        nop
-
-       .align  2
-syscall_trace_entry:
-       !                       Yes it is traced.
-       ! XXX setup arguments...
-       mov.l   4f, r11         ! Call do_syscall_trace which notifies
-       jsr     @r11            ! superior (will chomp R[0-7])
-        nop
-       !                       Reload R0-R4 from kernel stack, where the
-       !                       parent may have modified them using
-       !                       ptrace(POKEUSR).  (Note that R0-R2 are
-       !                       used by the system call handler directly
-       !                       from the kernel stack anyway, so don't need
-       !                       to be reloaded here.)  This allows the parent
-       !                       to rewrite system calls and args on the fly.
-       mov.l   @(OFF_R4,r15), r4   ! arg0
-       mov.l   @(OFF_R5,r15), r5
-       mov.l   @(OFF_R6,r15), r6
-       mov.l   @(OFF_R7,r15), r7   ! arg3
-       mov.l   @(OFF_R3,r15), r3   ! syscall_nr
-       !                   Arrange for do_syscall_trace to be called
-       !                   again as the system call returns.
-       mov.l   2f, r10                 ! Number of syscalls
-       cmp/hs  r10, r3
-       bf      syscall_call
-       mov     #-ENOSYS, r0
-       bra     syscall_exit
-        mov.l  r0, @(OFF_R0,r15)       ! Return value
-
-/*
- * Syscall interface:
- *
- *     Syscall #: R3
- *     Arguments #0 to #3: R4--R7
- *     Arguments #4 to #6: R0, R1, R2
- *     TRA: (number of arguments + 0x10) x 4
- *
- * This code also handles delegating other traps to the BIOS/gdb stub
- * according to:
- *
- * Trap number
- * (TRA>>2)        Purpose
- * --------        -------
- * 0x0-0xf         old syscall ABI
- * 0x10-0x1f       new syscall ABI
- * 0x20-0xff       delegated through debug_trap to BIOS/gdb stub.
- *
- * Note: When we're first called, the TRA value must be shifted
- * right 2 bits in order to get the value that was used as the "trapa"
- * argument.
- */
-
-       .align  2
-       .globl  ret_from_fork
-ret_from_fork:
-       mov.l   1f, r8
-       jsr     @r8
-        mov    r0, r4
-       bra     syscall_exit
-        nop
-       .align  2
-1:     .long   schedule_tail
-       !
-ENTRY(system_call)
-       mov.l   1f, r9
-       mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
-       !
-       ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-       mov     #0x7f, r9
-       cmp/hi  r9, r8
-       bt/s    0f
-        mov    #OFF_TRA, r9
-       add     r15, r9
-       !
-       mov.l   r8, @r9                 ! set TRA value to tra
-       STI()
-       !                   Call the system call handler through the table.
-       !                   First check for bad syscall number
-       mov     r3, r9
-       mov.l   2f, r8                  ! Number of syscalls
-       cmp/hs  r8, r9
-       bf/s    good_system_call
-        GET_THREAD_INFO(r8)
-syscall_badsys:                        ! Bad syscall number
-       mov     #-ENOSYS, r0
-       bra     resume_userspace
-        mov.l  r0, @(OFF_R0,r15)       ! Return value
-       !
-0:
-       bra     debug_trap
-        nop
-       !
-good_system_call:              ! Good syscall number
-       mov.l   @(TI_FLAGS,r8), r8
-       mov     #_TIF_SYSCALL_TRACE, r10
-       tst     r10, r8
-       bf      syscall_trace_entry
-       !
-syscall_call:
-       shll2   r9              ! x4
-       mov.l   3f, r8          ! Load the address of sys_call_table
-       add     r8, r9
-       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:
-       CLI()
-       !
-       GET_THREAD_INFO(r8)
-       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
-       tst     #_TIF_ALLWORK_MASK, r0
-       bf      syscall_exit_work
 restore_all:
        mov.l   @r15+, r0
        mov.l   @r15+, r1
@@ -606,7 +278,9 @@ skip_restore:
        !
        ! Calculate new SR value
        mov     k3, k2                  ! original SR value
-       mov.l   9f, k1
+       mov     #0xf0, k1
+       extu.b  k1, k1
+       not     k1, k1
        and     k1, k2                  ! Mask orignal SR value
        !
        mov     k3, k0                  ! Calculate IMASK-bits
@@ -632,16 +306,12 @@ skip_restore:
         nop
 
        .align  2
-1:     .long   TRA
-2:     .long   NR_syscalls
-3:     .long   sys_call_table
-4:     .long   do_syscall_trace
 5:     .long   0x00001000      ! DSP
 7:     .long   0x30000000
-9:
-__INV_IMASK:
-       .long   0xffffff0f      ! ~(IMASK)
 
+! common exception handler
+#include "../../entry-common.S"
+       
 ! Exception Vector Base
 !
 !      Should be aligned page boundary.
@@ -661,9 +331,176 @@ general_exception:
 2:     .long   ret_from_exception
 !
 !
+
+/* This code makes some assumptions to improve performance.
+ * Make sure they are stil true. */
+#if PTRS_PER_PGD != PTRS_PER_PTE
+#error PGD and PTE sizes don't match
+#endif
+
+/* gas doesn't flag impossible values for mov #immediate as an error */
+#if (_PAGE_PRESENT >> 2) > 0x7f
+#error cannot load PAGE_PRESENT as an immediate
+#endif
+#if _PAGE_DIRTY > 0x7f
+#error cannot load PAGE_DIRTY as an immediate
+#endif
+#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
+#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
+#endif
+
+#if defined(CONFIG_CPU_SH4)
+#define ldmmupteh(r)   mov.l   8f, r
+#else
+#define ldmmupteh(r)   mov     #MMU_PTEH, r
+#endif
+
        .balign         1024,0,1024
 tlb_miss:
-       mov.l   1f, k2
+#ifdef COUNT_EXCEPTIONS
+       ! Increment the counts
+       mov.l   9f, k1
+       mov.l   @k1, k2
+       add     #1, k2
+       mov.l   k2, @k1
+#endif
+
+       ! k0 scratch
+       ! k1 pgd and pte pointers
+       ! k2 faulting address
+       ! k3 pgd and pte index masks
+       ! k4 shift
+
+       ! Load up the pgd entry (k1)
+
+       ldmmupteh(k0)                   !  9 LS (latency=2)     MMU_PTEH
+
+       mov.w   4f, k3                  !  8 LS (latency=2)     (PTRS_PER_PGD-1) << 2
+       mov     #-(PGDIR_SHIFT-2), k4   !  6 EX
+
+       mov.l   @(MMU_TEA-MMU_PTEH,k0), k2      ! 18 LS (latency=2)
+
+       mov.l   @(MMU_TTB-MMU_PTEH,k0), k1      ! 18 LS (latency=2)
+
+       mov     k2, k0                  !   5 MT (latency=0)
+       shld    k4, k0                  !  99 EX
+
+       and     k3, k0                  !  78 EX
+
+       mov.l   @(k0, k1), k1           !  21 LS (latency=2)
+       mov     #-(PAGE_SHIFT-2), k4    !   6 EX
+
+       ! Load up the pte entry (k2)
+
+       mov     k2, k0                  !   5 MT (latency=0)
+       shld    k4, k0                  !  99 EX
+
+       tst     k1, k1                  !  86 MT
+
+       bt      20f                     ! 110 BR
+
+       and     k3, k0                  !  78 EX
+       mov.w   5f, k4                  !   8 LS (latency=2)    _PAGE_PRESENT
+
+       mov.l   @(k0, k1), k2           !  21 LS (latency=2)
+       add     k0, k1                  !  49 EX
+
+#ifdef CONFIG_CPU_HAS_PTEA
+       ! Test the entry for present and _PAGE_ACCESSED
+
+       mov     #-28, k3                !   6 EX
+       mov     k2, k0                  !   5 MT (latency=0)
+
+       tst     k4, k2                  !  68 MT
+       shld    k3, k0                  !  99 EX
+
+       bt      20f                     ! 110 BR
+
+       ! Set PTEA register
+       ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
+       !
+       ! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
+
+       and     #0xe, k0                !  79 EX
+
+       mov     k0, k3                  !   5 MT (latency=0)
+       mov     k2, k0                  !   5 MT (latency=0)
+
+       and     #1, k0                  !  79 EX
+
+       or      k0, k3                  !  82 EX
+
+       ldmmupteh(k0)                   !   9 LS (latency=2)
+       shll2   k4                      ! 101 EX                _PAGE_ACCESSED
+
+       tst     k4, k2                  !  68 MT
+
+       mov.l   k3, @(MMU_PTEA-MMU_PTEH,k0)     ! 27 LS
+
+       mov.l   7f, k3                  !   9 LS (latency=2)    _PAGE_FLAGS_HARDWARE_MASK
+
+       ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
+#else
+
+       ! Test the entry for present and _PAGE_ACCESSED
+
+       mov.l   7f, k3                  !   9 LS (latency=2)    _PAGE_FLAGS_HARDWARE_MASK
+       tst     k4, k2                  !  68 MT
+
+       shll2   k4                      ! 101 EX                _PAGE_ACCESSED
+       ldmmupteh(k0)                   !   9 LS (latency=2)
+
+       bt      20f                     ! 110 BR
+       tst     k4, k2                  !  68 MT
+
+       ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
+
+#endif
+
+       ! Set up the entry
+
+       and     k2, k3                  !  78 EX
+       bt/s    10f                     ! 108 BR
+
+        mov.l  k3, @(MMU_PTEL-MMU_PTEH,k0)     ! 27 LS
+
+       ldtlb                           ! 128 CO
+
+       ! At least one instruction between ldtlb and rte
+       nop                             ! 119 NOP
+
+       rte                             ! 126 CO
+
+        nop                            ! 119 NOP
+
+
+10:    or      k4, k2                  !  82 EX
+
+       ldtlb                           ! 128 CO
+
+       ! At least one instruction between ldtlb and rte
+       mov.l   k2, @k1                 !  27 LS
+
+       rte                             ! 126 CO
+
+       ! Note we cannot execute mov here, because it is executed after
+       ! restoring SSR, so would be executed in user space.
+        nop                            ! 119 NOP
+
+
+       .align 5
+       ! Once cache line if possible...
+1:     .long   swapper_pg_dir
+4:     .short  (PTRS_PER_PGD-1) << 2
+5:     .short  _PAGE_PRESENT
+7:     .long   _PAGE_FLAGS_HARDWARE_MASK
+8:     .long   MMU_PTEH
+#ifdef COUNT_EXCEPTIONS
+9:     .long   exception_count_miss
+#endif
+
+       ! Either pgd or pte not present
+20:    mov.l   1f, k2
        mov.l   4f, k3
        bra     handle_exception
         mov.l  @k2, k2
@@ -710,8 +547,9 @@ ENTRY(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     #(THREAD_SIZE >> 8), k1
+       mov     #(THREAD_SIZE >> 10), k1
        shll8   k1              ! k1 := THREAD_SIZE
+       shll2   k1
        add     current, k1
        mov     k1, r15         ! change to kernel stack
        !
@@ -761,7 +599,7 @@ skip_save:
        ! Save the user registers on the stack.
        mov.l   k2, @-r15       ! EXPEVT
 
-       mov     #-1, k4
+       mov     #-1, k4
        mov.l   k4, @-r15       ! set TRA (default: -1)
        !
        sts.l   macl, @-r15
@@ -813,6 +651,15 @@ skip_save:
        bf      interrupt_exception
        shlr2   r8
        shlr    r8
+
+#ifdef COUNT_EXCEPTIONS
+       mov.l   5f, r9
+       add     r8, r9
+       mov.l   @r9, r10
+       add     #1, r10
+       mov.l   r10, @r9
+#endif
+
        mov.l   4f, r9
        add     r8, r9
        mov.l   @r9, r9
@@ -826,6 +673,9 @@ skip_save:
 2:     .long   0x000080f0      ! FD=1, IMASK=15
 3:     .long   0xcfffffff      ! RB=0, BL=0
 4:     .long   exception_handling_table
+#ifdef COUNT_EXCEPTIONS
+5:     .long   exception_count_table
+#endif
 
 interrupt_exception:
        mov.l   1f, r9
index 8dbf389..6e415ba 100644 (file)
@@ -2,7 +2,8 @@
 # Makefile for the Linux/SuperH SH-4 backends.
 #
 
-obj-y  := ex.o probe.o
+obj-y  := ex.o probe.o common.o
+common-y       += $(addprefix ../sh3/, entry.o)
 
 obj-$(CONFIG_SH_FPU)                    += fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)          += sq.o
index bfdf5fe..fa2019a 100644 (file)
@@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk)
 
 static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
 {
-       struct clk *bclk = clk_get("bus_clk");
+       struct clk *bclk = clk_get(NULL, "bus_clk");
        unsigned long bclk_rate = clk_get_rate(bclk);
 
        clk_put(bclk);
@@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = {
 
 static int __init sh4202_clk_init(void)
 {
-       struct clk *clk = clk_get("master_clk");
+       struct clk *clk = clk_get(NULL, "master_clk");
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
index 93ad367..9e6a216 100644 (file)
@@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = {
 
 static int __init sh7780_clk_init(void)
 {
-       struct clk *clk = clk_get("master_clk");
+       struct clk *clk = clk_get(NULL, "master_clk");
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
index f486c07..7624677 100644 (file)
@@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs)
                        grab_fpu(regs);
                        restore_fpu(tsk);
                        set_tsk_thread_flag(tsk, TIF_USEDFPU);
-               } else {
-                       tsk->thread.trap_no = 11;
-                       tsk->thread.error_code = 0;
+               } else
                        force_sig(SIGFPE, tsk);
-               }
 
                regs->pc = nextpc;
                return 1;
@@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs)
 }
 
 asmlinkage void
-do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
-            struct pt_regs regs)
+do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
+            unsigned long r7, struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        struct task_struct *tsk = current;
 
-       if (ieee_fpe_handler (&regs))
+       if (ieee_fpe_handler(regs))
                return;
 
-       regs.pc += 2;
-       save_fpu(tsk, &regs);
-       tsk->thread.trap_no = 11;
-       tsk->thread.error_code = 0;
+       regs->pc += 2;
+       save_fpu(tsk, regs);
        force_sig(SIGFPE, tsk);
 }
 
 asmlinkage void
 do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
-                    unsigned long r7, struct pt_regs regs)
+                    unsigned long r7, struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        struct task_struct *tsk = current;
 
-       grab_fpu(&regs);
-       if (!user_mode(&regs)) {
+       grab_fpu(regs);
+       if (!user_mode(regs)) {
                printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
                return;
        }
index c294de1..afe0f1b 100644 (file)
@@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void)
        case 0x205:
                cpu_data->type = CPU_SH7750;
                cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
-                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
+                                  CPU_HAS_PERF_COUNTER;
                break;
        case 0x206:
                cpu_data->type = CPU_SH7750S;
                cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
-                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
+                                  CPU_HAS_PERF_COUNTER;
                break;
        case 0x1100:
                cpu_data->type = CPU_SH7751;
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+               cpu_data->flags |= CPU_HAS_FPU;
                break;
        case 0x2000:
                cpu_data->type = CPU_SH73180;
@@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void)
                break;
        case 0x8000:
                cpu_data->type = CPU_ST40RA;
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+               cpu_data->flags |= CPU_HAS_FPU;
                break;
        case 0x8100:
                cpu_data->type = CPU_ST40GX1;
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+               cpu_data->flags |= CPU_HAS_FPU;
                break;
        case 0x700:
                cpu_data->type = CPU_SH4_501;
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
-               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;
+               cpu_data->flags |= CPU_HAS_FPU;
                break;
        case 0x500 ... 0x501:
                switch (prr) {
@@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void)
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
 
-               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+               cpu_data->flags |= CPU_HAS_FPU;
 
                break;
        default:
@@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void)
        cpu_data->dcache.ways = 1;
 #endif
 
+#ifdef CONFIG_CPU_HAS_PTEA
+       cpu_data->flags |= CPU_HAS_PTEA;
+#endif
+
        /*
         * On anything that's not a direct-mapped cache, look to the CVR
         * for I/D-cache specifics.
index 50812d5..bbcb06f 100644 (file)
@@ -2,6 +2,7 @@
  * SH7750/SH7751 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006  Jamie Lenehan
  *
  * 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
@@ -10,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/io.h>
 #include <asm/sci.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void)
                                    ARRAY_SIZE(sh7750_devices));
 }
 __initcall(sh7750_devices_setup);
+
+static struct ipr_data sh7750_ipr_map[] = {
+       /* IRQ, IPR-idx, shift, priority */
+       { 16, 0, 12, 2 }, /* TMU0 TUNI*/
+       { 17, 0, 12, 2 }, /* TMU1 TUNI */
+       { 18, 0,  4, 2 }, /* TMU2 TUNI */
+       { 19, 0,  4, 2 }, /* TMU2 TIPCI */
+       { 27, 1, 12, 2 }, /* WDT ITI */
+       { 20, 0,  0, 2 }, /* RTC ATI (alarm) */
+       { 21, 0,  0, 2 }, /* RTC PRI (period) */
+       { 22, 0,  0, 2 }, /* RTC CUI (carry) */
+       { 23, 1,  4, 3 }, /* SCI ERI */
+       { 24, 1,  4, 3 }, /* SCI RXI */
+       { 25, 1,  4, 3 }, /* SCI TXI */
+       { 40, 2,  4, 3 }, /* SCIF ERI */
+       { 41, 2,  4, 3 }, /* SCIF RXI */
+       { 42, 2,  4, 3 }, /* SCIF BRI */
+       { 43, 2,  4, 3 }, /* SCIF TXI */
+       { 34, 2,  8, 7 }, /* DMAC DMTE0 */
+       { 35, 2,  8, 7 }, /* DMAC DMTE1 */
+       { 36, 2,  8, 7 }, /* DMAC DMTE2 */
+       { 37, 2,  8, 7 }, /* DMAC DMTE3 */
+       { 28, 2,  8, 7 }, /* DMAC DMAE */
+};
+
+static struct ipr_data sh7751_ipr_map[] = {
+       { 44, 2,  8, 7 }, /* DMAC DMTE4 */
+       { 45, 2,  8, 7 }, /* DMAC DMTE5 */
+       { 46, 2,  8, 7 }, /* DMAC DMTE6 */
+       { 47, 2,  8, 7 }, /* DMAC DMTE7 */
+       /* The following use INTC_INPRI00 for masking, which is a 32-bit
+          register, not a 16-bit register like the IPRx registers, so it
+          would need special support */
+       /*{ 72, INTPRI00,  8, ? },*/ /* TMU3 TUNI */
+       /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
+};
+
+static unsigned long ipr_offsets[] = {
+       0xffd00004UL,   /* 0: IPRA */
+       0xffd00008UL,   /* 1: IPRB */
+       0xffd0000cUL,   /* 2: IPRC */
+       0xffd00010UL,   /* 3: IPRD */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (idx >= ARRAY_SIZE(ipr_offsets))
+               return 0;
+       return ipr_offsets[idx];
+}
+
+#define INTC_ICR       0xffd00000UL
+#define INTC_ICR_IRLM   (1<<7)
+
+/* enable individual interrupt mode for external interupts */
+void ipr_irq_enable_irlm(void)
+{
+       ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+}
+
+void __init init_IRQ_ipr()
+{
+       make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+       make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
+#endif
+}
index 814ddb2..9aeaa2d 100644 (file)
@@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void)
 __initcall(sh7780_devices_setup);
 
 static struct intc2_data intc2_irq_table[] = {
-       { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 },
-       { 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 },
-       { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+       { 28, 0, 24, 0, 0, 2 },         /* TMU0 */
 
-       { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-       { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-       { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-       { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+       { 21, 1,  0, 0, 2, 2 },
+       { 22, 1,  1, 0, 2, 2 },
+       { 23, 1,  2, 0, 2, 2 },
 
-       { PCIC0_IRQ, 0x10,  8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
-       { PCIC1_IRQ, 0x10,  0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
-       { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
-       { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
-       { PCIC4_IRQ, 0x14,  8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
+       { 40, 8, 24, 0, 3, 3 },         /* SCIF0 ERI */
+       { 41, 8, 24, 0, 3, 3 },         /* SCIF0 RXI */
+       { 42, 8, 24, 0, 3, 3 },         /* SCIF0 BRI */
+       { 43, 8, 24, 0, 3, 3 },         /* SCIF0 TXI */
+
+       { 76, 8, 16, 0, 4, 3 },         /* SCIF1 ERI */
+       { 77, 8, 16, 0, 4, 3 },         /* SCIF1 RXI */
+       { 78, 8, 16, 0, 4, 3 },         /* SCIF1 BRI */
+       { 79, 8, 16, 0, 4, 3 },         /* SCIF1 TXI */
+
+       { 64, 0x10,  8, 0, 14, 2 },     /* PCIC0 */
+       { 65, 0x10,  0, 0, 15, 2 },     /* PCIC1 */
+       { 66, 0x14, 24, 0, 16, 2 },     /* PCIC2 */
+       { 67, 0x14, 16, 0, 17, 2 },     /* PCIC3 */
+       { 68, 0x14,  8, 0, 18, 2 },     /* PCIC4 */
 };
 
 void __init init_IRQ_intc2(void)
index 7bcc73f..0c9ea38 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu/sq.h>
@@ -38,7 +38,7 @@ struct sq_mapping {
 
 static struct sq_mapping *sq_mapping_list;
 static DEFINE_SPINLOCK(sq_mapping_lock);
-static kmem_cache_t *sq_cache;
+static struct kmem_cache *sq_cache;
 static unsigned long *sq_bitmap;
 
 #define store_queue_barrier()                  \
@@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len)
        /* Wait for completion */
        store_queue_barrier();
 }
+EXPORT_SYMBOL(sq_flush_range);
 
 static inline void sq_mapping_list_add(struct sq_mapping *map)
 {
@@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
        map->size = size;
        map->name = name;
 
-       page = bitmap_find_free_region(sq_bitmap, 0x04000000,
+       page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT,
                                       get_order(map->size));
        if (unlikely(page < 0)) {
                ret = -ENOSPC;
@@ -193,6 +194,7 @@ out:
        kmem_cache_free(sq_cache, map);
        return ret;
 }
+EXPORT_SYMBOL(sq_remap);
 
 /**
  * sq_unmap - Unmap a Store Queue allocation
@@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr)
 
        kmem_cache_free(sq_cache, map);
 }
+EXPORT_SYMBOL(sq_unmap);
 
 /*
  * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
@@ -402,7 +405,3 @@ 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");
-
-EXPORT_SYMBOL(sq_remap);
-EXPORT_SYMBOL(sq_unmap);
-EXPORT_SYMBOL(sq_flush_range);
index a000227..6034082 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/console.h>
 #include <linux/tty.h>
 #include <linux/init.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
@@ -62,17 +62,9 @@ static struct console bios_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,
+       .mapbase        = CONFIG_EARLY_SCIF_CONSOLE_PORT,
+       .membase        = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
 };
 
 static void scif_sercon_putc(int c)
@@ -113,23 +105,29 @@ static struct console scif_console = {
        .index          = -1,
 };
 
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
+/*
+ * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
+ * devices that aren't using sh-ipl+g.
+ */
 static void scif_sercon_init(int baud)
 {
-       ctrl_outw(0, SCIF_REG + 8);
-       ctrl_outw(0, SCIF_REG);
+       ctrl_outw(0, scif_port.mapbase + 8);
+       ctrl_outw(0, scif_port.mapbase);
 
        /* Set baud rate */
        ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
-                 (32 * baud) - 1, SCIF_REG + 4);
-
-       ctrl_outw(12, SCIF_REG + 24);
-       ctrl_outw(8, SCIF_REG + 24);
-       ctrl_outw(0, SCIF_REG + 32);
-       ctrl_outw(0x60, SCIF_REG + 16);
-       ctrl_outw(0, SCIF_REG + 36);
-       ctrl_outw(0x30, SCIF_REG + 8);
+                 (32 * baud) - 1, scif_port.mapbase + 4);
+
+       ctrl_outw(12, scif_port.mapbase + 24);
+       ctrl_outw(8, scif_port.mapbase + 24);
+       ctrl_outw(0, scif_port.mapbase + 32);
+       ctrl_outw(0x60, scif_port.mapbase + 16);
+       ctrl_outw(0, scif_port.mapbase + 36);
+       ctrl_outw(0x30, scif_port.mapbase + 8);
 }
-#endif
+#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
+#endif /* CONFIG_EARLY_SCIF_CONSOLE */
 
 /*
  * Setup a default console, if more than one is compiled in, rely on the
@@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt)
        if (!strncmp(buf, "serial", 6)) {
                early_console = &scif_console;
 
-#ifdef CONFIG_CPU_SH4
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
                scif_sercon_init(115200);
 #endif
        }
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
new file mode 100644 (file)
index 0000000..29136a3
--- /dev/null
@@ -0,0 +1,433 @@
+/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
+ *
+ *  linux/arch/sh/entry.S
+ *
+ *  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.
+ *
+ */
+
+! 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.
+
+/*     
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * NOTE: This code uses a convention that instructions in the delay slot
+ * of a transfer-control instruction are indented by an extra space, thus:
+ *
+ *    jmp      @k0         ! control-transfer instruction
+ *     ldc     k1, ssr     ! delay slot
+ *
+ * Stack layout in 'ret_from_syscall':
+ *     ptrace needs to have all regs on the stack.
+ *     if the order here is changed, it needs to be
+ *     updated in ptrace.c and ptrace.h
+ *
+ *     r0
+ *      ...
+ *     r15 = stack pointer
+ *     spc
+ *     pr
+ *     ssr
+ *     gbr
+ *     mach
+ *     macl
+ *     syscall #
+ *
+ */
+
+#if defined(CONFIG_PREEMPT)
+#  define preempt_stop()       cli
+#else
+#  define preempt_stop()
+#  define resume_kernel                __restore_all
+#endif
+
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
+! If both are configured, handle the debug traps (breakpoints) in SW,
+! but still allow BIOS traps to FW.
+
+       .align  2
+debug_kernel:
+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
+       /* Force BIOS call to FW (debug_trap put TRA in r8) */
+       mov     r8,r0
+       shlr2   r0
+       cmp/eq  #0x3f,r0
+       bt      debug_kernel_fw
+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
+
+debug_enter:           
+#if defined(CONFIG_SH_KGDB)
+       /* Jump to kgdb, pass stacked regs as arg */
+debug_kernel_sw:
+       mov.l   3f, r0
+       jmp     @r0
+        mov    r15, r4
+       .align  2
+3:     .long   kgdb_handle_exception
+#endif /* CONFIG_SH_KGDB */
+
+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+
+
+       .align  2
+debug_trap:    
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+       mov     #OFF_SR, r0
+       mov.l   @(r0,r15), r0           ! get status register
+       shll    r0
+       shll    r0                      ! kernel space?
+       bt/s    debug_kernel
+#endif
+        mov.l  @r15, r0                ! Restore R0 value
+       mov.l   1f, r8
+       jmp     @r8
+        nop
+
+       .align  2
+ENTRY(exception_error)
+       !
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   3f, r0
+       jsr     @r0
+        nop
+#endif
+       sti
+       mov.l   2f, r0
+       jmp     @r0
+        nop
+
+!
+       .align  2
+1:     .long   break_point_trap_software
+2:     .long   do_exception_error
+#ifdef CONFIG_TRACE_IRQFLAGS
+3:     .long   trace_hardirqs_on
+#endif
+
+       .align  2
+ret_from_exception:
+       preempt_stop()
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   4f, r0
+       jsr     @r0
+        nop
+#endif
+ENTRY(ret_from_irq)
+       !
+       mov     #OFF_SR, r0
+       mov.l   @(r0,r15), r0   ! get status register
+       shll    r0
+       shll    r0              ! kernel space?
+       get_current_thread_info r8, r0
+       bt      resume_kernel   ! Yes, it's from kernel, go back soon
+
+#ifdef CONFIG_PREEMPT
+       bra     resume_userspace
+        nop
+ENTRY(resume_kernel)
+       mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
+       tst     r0, r0
+       bf      noresched
+need_resched:
+       mov.l   @(TI_FLAGS,r8), r0      ! current_thread_info->flags
+       tst     #_TIF_NEED_RESCHED, r0  ! need_resched set?
+       bt      noresched
+
+       mov     #OFF_SR, r0
+       mov.l   @(r0,r15), r0           ! get status register
+       and     #0xf0, r0               ! interrupts off (exception path)?
+       cmp/eq  #0xf0, r0
+       bt      noresched
+
+       mov.l   1f, r0
+       mov.l   r0, @(TI_PRE_COUNT,r8)
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   3f, r0
+       jsr     @r0
+        nop
+#endif
+       sti
+       mov.l   2f, r0
+       jsr     @r0
+        nop
+       mov     #0, r0
+       mov.l   r0, @(TI_PRE_COUNT,r8)
+       cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   4f, r0
+       jsr     @r0
+        nop
+#endif
+
+       bra     need_resched
+        nop
+
+noresched:
+       bra     __restore_all
+        nop
+
+       .align 2
+1:     .long   PREEMPT_ACTIVE
+2:     .long   schedule
+#ifdef CONFIG_TRACE_IRQFLAGS
+3:     .long   trace_hardirqs_on
+4:     .long   trace_hardirqs_off
+#endif
+#endif
+
+ENTRY(resume_userspace)
+       ! r8: current_thread_info
+       cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   5f, r0
+       jsr     @r0
+        nop
+#endif
+       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
+       tst     #_TIF_WORK_MASK, r0
+       bt/s    __restore_all
+        tst    #_TIF_NEED_RESCHED, r0
+
+       .align  2
+work_pending:
+       ! r0: current_thread_info->flags
+       ! r8: current_thread_info
+       ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
+       bf/s    work_resched
+        tst    #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
+work_notifysig:
+       bt/s    __restore_all
+        mov    r15, r4
+       mov     r12, r5         ! set arg1(save_r0)
+       mov     r0, r6
+       mov.l   2f, r1
+       mov.l   3f, r0
+       jmp     @r1
+        lds    r0, pr
+work_resched:
+#ifndef CONFIG_PREEMPT
+       ! gUSA handling
+       mov.l   @(OFF_SP,r15), r0       ! get user space stack pointer
+       mov     r0, r1
+       shll    r0
+       bf/s    1f
+        shll   r0
+       bf/s    1f
+        mov    #OFF_PC, r0
+       !                                 SP >= 0xc0000000 : gUSA mark
+       mov.l   @(r0,r15), r2           ! get user space PC (program counter)
+       mov.l   @(OFF_R0,r15), r3       ! end point
+       cmp/hs  r3, r2                  ! r2 >= r3? 
+       bt      1f
+       add     r3, r1                  ! rewind point #2
+       mov.l   r1, @(r0,r15)           ! reset PC to rewind point #2
+       !
+1:
+#endif
+       mov.l   1f, r1
+       jsr     @r1                             ! schedule
+        nop
+       cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   5f, r0
+       jsr     @r0
+        nop
+#endif
+       !
+       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
+       tst     #_TIF_WORK_MASK, r0
+       bt      __restore_all
+       bra     work_pending
+        tst    #_TIF_NEED_RESCHED, r0
+
+       .align  2
+1:     .long   schedule
+2:     .long   do_notify_resume
+3:     .long   restore_all
+#ifdef CONFIG_TRACE_IRQFLAGS
+4:     .long   trace_hardirqs_on
+5:     .long   trace_hardirqs_off
+#endif
+
+       .align  2
+syscall_exit_work:
+       ! r0: current_thread_info->flags
+       ! r8: current_thread_info
+       tst     #_TIF_SYSCALL_TRACE, r0
+       bt/s    work_pending
+        tst    #_TIF_NEED_RESCHED, r0
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   5f, r0
+       jsr     @r0
+        nop
+#endif
+       sti
+       ! XXX setup arguments...
+       mov.l   4f, r0                  ! do_syscall_trace
+       jsr     @r0
+        nop
+       bra     resume_userspace
+        nop
+
+       .align  2
+syscall_trace_entry:
+       !                       Yes it is traced.
+       ! XXX setup arguments...
+       mov.l   4f, r11         ! Call do_syscall_trace which notifies
+       jsr     @r11            ! superior (will chomp R[0-7])
+        nop
+       !                       Reload R0-R4 from kernel stack, where the
+       !                       parent may have modified them using
+       !                       ptrace(POKEUSR).  (Note that R0-R2 are
+       !                       used by the system call handler directly
+       !                       from the kernel stack anyway, so don't need
+       !                       to be reloaded here.)  This allows the parent
+       !                       to rewrite system calls and args on the fly.
+       mov.l   @(OFF_R4,r15), r4   ! arg0
+       mov.l   @(OFF_R5,r15), r5
+       mov.l   @(OFF_R6,r15), r6
+       mov.l   @(OFF_R7,r15), r7   ! arg3
+       mov.l   @(OFF_R3,r15), r3   ! syscall_nr
+       !
+       mov.l   2f, r10                 ! Number of syscalls
+       cmp/hs  r10, r3
+       bf      syscall_call
+       mov     #-ENOSYS, r0
+       bra     syscall_exit
+        mov.l  r0, @(OFF_R0,r15)       ! Return value
+
+__restore_all:
+       mov.l   1f, r0
+       jmp     @r0
+        nop
+
+       .align  2
+1:     .long   restore_all
+
+       .align  2
+not_syscall_tra:       
+       bra     debug_trap
+        nop
+
+       .align  2
+syscall_badsys:                        ! Bad syscall number
+       mov     #-ENOSYS, r0
+       bra     resume_userspace
+        mov.l  r0, @(OFF_R0,r15)       ! Return value
+       
+
+/*
+ * Syscall interface:
+ *
+ *     Syscall #: R3
+ *     Arguments #0 to #3: R4--R7
+ *     Arguments #4 to #6: R0, R1, R2
+ *     TRA: (number of arguments + 0x10) x 4
+ *
+ * This code also handles delegating other traps to the BIOS/gdb stub
+ * according to:
+ *
+ * Trap number
+ * (TRA>>2)        Purpose
+ * --------        -------
+ * 0x0-0xf         old syscall ABI
+ * 0x10-0x1f       new syscall ABI
+ * 0x20-0xff       delegated through debug_trap to BIOS/gdb stub.
+ *
+ * Note: When we're first called, the TRA value must be shifted
+ * right 2 bits in order to get the value that was used as the "trapa"
+ * argument.
+ */
+
+       .align  2
+       .globl  ret_from_fork
+ret_from_fork:
+       mov.l   1f, r8
+       jsr     @r8
+        mov    r0, r4
+       bra     syscall_exit
+        nop
+       .align  2
+1:     .long   schedule_tail
+       !
+ENTRY(system_call)
+#if !defined(CONFIG_CPU_SH2)
+       mov.l   1f, r9
+       mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
+#endif
+       !
+       ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
+       mov     #0x7f, r9
+       cmp/hi  r9, r8
+       bt/s    not_syscall_tra
+        mov    #OFF_TRA, r9
+       add     r15, r9
+       mov.l   r8, @r9                 ! set TRA value to tra
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   5f, r10
+       jsr     @r10
+        nop
+#endif
+       sti
+
+       !
+       get_current_thread_info r8, r10
+       mov.l   @(TI_FLAGS,r8), r8
+       mov     #_TIF_SYSCALL_TRACE, r10
+       tst     r10, r8
+       bf      syscall_trace_entry
+       !
+       mov.l   2f, r8                  ! Number of syscalls
+       cmp/hs  r8, r3
+       bt      syscall_badsys
+       !
+syscall_call:
+       shll2   r3              ! x4
+       mov.l   3f, r8          ! Load the address of sys_call_table
+       add     r8, r3
+       mov.l   @r3, 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:
+       cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+       mov.l   6f, r0
+       jsr     @r0
+        nop
+#endif
+       !
+       get_current_thread_info r8, r0
+       mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
+       tst     #_TIF_ALLWORK_MASK, r0
+       bf      syscall_exit_work
+       bra     __restore_all
+        nop
+       .align  2
+#if !defined(CONFIG_CPU_SH2)
+1:     .long   TRA
+#endif
+2:     .long   NR_syscalls
+3:     .long   sys_call_table
+4:     .long   do_syscall_trace
+#ifdef CONFIG_TRACE_IRQFLAGS
+5:     .long   trace_hardirqs_on
+6:     .long   trace_hardirqs_off
+#endif
index f5f53d1..6aca4bc 100644 (file)
@@ -33,7 +33,7 @@ ENTRY(empty_zero_page)
        .long   0x00360000      /* INITRD_START */
        .long   0x000a0000      /* INITRD_SIZE */
        .long   0
-       .balign 4096,0,4096
+       .balign PAGE_SIZE,0,PAGE_SIZE
 
        .text   
 /*
@@ -53,8 +53,10 @@ ENTRY(_stext)
        ldc     r0, sr
        !                       Initialize global interrupt mask
        mov     #0, r0
+#ifdef CONFIG_CPU_HAS_SR_RB
        ldc     r0, r6_bank
-
+#endif
+       
        /*
         * Prefetch if possible to reduce cache miss penalty.
         *
@@ -68,11 +70,14 @@ ENTRY(_stext)
        !
        mov.l   2f, r0
        mov     r0, r15         ! Set initial r15 (stack pointer)
-       mov     #(THREAD_SIZE >> 8), r1
+       mov     #(THREAD_SIZE >> 10), r1
        shll8   r1              ! r1 = THREAD_SIZE
+       shll2   r1
        sub     r1, r0          !
+#ifdef CONFIG_CPU_HAS_SR_RB
        ldc     r0, r7_bank     ! ... and initial thread_info
-
+#endif
+       
        !                       Clear BSS area
        mov.l   3f, r1
        add     #4, r1
@@ -95,7 +100,11 @@ ENTRY(_stext)
         nop
 
        .balign 4
+#if defined(CONFIG_CPU_SH2)
+1:     .long   0x000000F0              ! IMASK=0xF
+#else
 1:     .long   0x400080F0              ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
+#endif
 2:     .long   init_thread_union+THREAD_SIZE
 3:     .long   __bss_start
 4:     .long   _end
index 944128c..67be2b6 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/io.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
@@ -78,15 +78,16 @@ union irq_ctx {
        u32                     stack[THREAD_SIZE/sizeof(u32)];
 };
 
-static union irq_ctx *hardirq_ctx[NR_CPUS];
-static union irq_ctx *softirq_ctx[NR_CPUS];
+static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 #endif
 
 asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
                      unsigned long r6, unsigned long r7,
-                     struct pt_regs regs)
+                     struct pt_regs __regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(&regs);
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       struct pt_regs *old_regs = set_irq_regs(regs);
        int irq;
 #ifdef CONFIG_4KSTACKS
        union irq_ctx *curctx, *irqctx;
@@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
 #endif
 
 #ifdef CONFIG_CPU_HAS_INTEVT
-       irq = (ctrl_inl(INTEVT) >> 5) - 16;
+       irq = evt2irq(ctrl_inl(INTEVT));
 #else
        irq = r4;
 #endif
@@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
                irqctx->tinfo.task = curctx->tinfo.task;
                irqctx->tinfo.previous_sp = current_stack_pointer;
 
+               /*
+                * Copy the softirq bits in preempt_count so that the
+                * softirq checks work in the hardirq context.
+                */
+               irqctx->tinfo.preempt_count =
+                       (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+                       (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+
                __asm__ __volatile__ (
                        "mov    %0, r4          \n"
-                       "mov    r15, r9         \n"
+                       "mov    r15, r8         \n"
                        "jsr    @%1             \n"
                        /* swith to the irq stack */
                        " mov   %2, r15         \n"
                        /* restore the stack (ring zero) */
-                       "mov    r9, r15         \n"
+                       "mov    r8, r15         \n"
                        : /* no outputs */
                        : "r" (irq), "r" (generic_handle_irq), "r" (isp)
-                       /* XXX: A somewhat excessive clobber list? -PFM */
                        : "memory", "r0", "r1", "r2", "r3", "r4",
                          "r5", "r6", "r7", "r8", "t", "pr"
                );
@@ -193,7 +201,7 @@ void irq_ctx_init(int cpu)
        irqctx->tinfo.task              = NULL;
        irqctx->tinfo.exec_domain       = NULL;
        irqctx->tinfo.cpu               = cpu;
-       irqctx->tinfo.preempt_count     = SOFTIRQ_OFFSET;
+       irqctx->tinfo.preempt_count     = 0;
        irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
 
        softirq_ctx[cpu] = irqctx;
@@ -239,13 +247,38 @@ asmlinkage void do_softirq(void)
                        "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"
                );
+
+               /*
+                * Shouldnt happen, we returned above if in_interrupt():
+                */
+               WARN_ON_ONCE(softirq_count());
        }
 
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL(do_softirq);
 #endif
+
+void __init init_IRQ(void)
+{
+#ifdef CONFIG_CPU_HAS_PINT_IRQ
+       init_IRQ_pint();
+#endif
+
+#ifdef CONFIG_CPU_HAS_INTC2_IRQ
+       init_IRQ_intc2();
+#endif
+
+#ifdef CONFIG_CPU_HAS_IPR_IRQ
+       init_IRQ_ipr();
+#endif
+
+       /* Perform the machine specific initialisation */
+       if (sh_mv.mv_init_irq)
+               sh_mv.mv_init_irq();
+
+       irq_ctx_init(smp_processor_id());
+}
index a52b13a..f3e2631 100644 (file)
@@ -385,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
 
 asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
                        unsigned long r6, unsigned long r7,
-                       struct pt_regs regs)
+                       struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 #ifdef CONFIG_MMU
-       return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
 #else
        /* fork almost works, enough to trick you into looking elsewhere :-( */
        return -EINVAL;
@@ -398,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
                         unsigned long parent_tidptr,
                         unsigned long child_tidptr,
-                        struct pt_regs regs)
+                        struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        if (!newsp)
-               newsp = regs.regs[15];
-       return do_fork(clone_flags, newsp, &regs, 0,
+               newsp = regs->regs[15];
+       return do_fork(clone_flags, newsp, regs, 0,
                        (int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
@@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
  */
 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
-                        struct pt_regs regs)
+                        struct pt_regs __regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs,
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
                       0, NULL, NULL);
 }
 
@@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
  */
 asmlinkage int sys_execve(char *ufilename, char **uargv,
                          char **uenvp, unsigned long r7,
-                         struct pt_regs regs)
+                         struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int error;
        char *filename;
 
@@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
        error = do_execve(filename,
                          (char __user * __user *)uargv,
                          (char __user * __user *)uenvp,
-                         &regs);
+                         regs);
        if (error == 0) {
                task_lock(current);
                current->ptrace &= ~PT_DTRACE;
@@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_struct *p)
        return pc;
 }
 
-asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
-                                unsigned long r6, unsigned long r7,
-                                struct pt_regs regs)
+asmlinkage void break_point_trap(void)
 {
        /* Clear tracing.  */
 #if defined(CONFIG_CPU_SH4A)
@@ -492,8 +494,10 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
 
 asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
                                          unsigned long r6, unsigned long r7,
-                                         struct pt_regs regs)
+                                         struct pt_regs __regs)
 {
-       regs.pc -= 2;
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+
+       regs->pc -= 2;
        force_sig(SIGTRAP, current);
 }
index 8221b37..c66cb32 100644 (file)
@@ -7,11 +7,9 @@
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
  */
-
 #include <linux/linkage.h>
-
-#define PAGE_SIZE      4096 /* must be same value as in <asm/page.h> */
-
+#include <asm/addrspace.h>
+#include <asm/page.h>
 
                .globl relocate_new_kernel
 relocate_new_kernel:
@@ -20,8 +18,8 @@ relocate_new_kernel:
        /* r6 = start_address      */
        /* r7 = vbr_reg            */
 
-       mov.l   10f,r8    /* 4096 */
-       mov.l   11f,r9    /* 0xa0000000 */
+       mov.l   10f,r8    /* PAGE_SIZE */
+       mov.l   11f,r9    /* P2SEG */
 
        /*  stack setting */
        add     r8,r5
@@ -32,7 +30,7 @@ relocate_new_kernel:
 0:
        mov.l   @r4+,r0   /* cmd = *ind++ */
 
-1:     /* addr = (cmd | 0xa0000000) & 0xfffffff0 */
+1:     /* addr = (cmd | P2SEG) & 0xfffffff0 */
        mov     r0,r2
        or      r9,r2
        mov     #-16,r1
@@ -92,7 +90,7 @@ relocate_new_kernel:
 10:
        .long   PAGE_SIZE
 11:
-       .long   0xa0000000
+       .long   P2SEG
 
 relocate_new_kernel_end:
 
index 36d86f9..f8dd6b7 100644 (file)
@@ -332,8 +332,7 @@ void __init setup_arch(char **cmdline_p)
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
                        reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
-                       initrd_start =
-                               INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
+                       initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START;
                        initrd_end = initrd_start + INITRD_SIZE;
                } else {
                        printk("initrd extends beyond end of memory "
@@ -392,6 +391,7 @@ static int __init topology_init(void)
 subsys_initcall(topology_init);
 
 static const char *cpu_name[] = {
+       [CPU_SH7206]    = "SH7206",     [CPU_SH7619]    = "SH7619",
        [CPU_SH7604]    = "SH7604",     [CPU_SH7300]    = "SH7300",
        [CPU_SH7705]    = "SH7705",     [CPU_SH7706]    = "SH7706",
        [CPU_SH7707]    = "SH7707",     [CPU_SH7708]    = "SH7708",
@@ -404,6 +404,7 @@ static const char *cpu_name[] = {
        [CPU_SH4_202]   = "SH4-202",    [CPU_SH4_501]   = "SH4-501",
        [CPU_SH7770]    = "SH7770",     [CPU_SH7780]    = "SH7780",
        [CPU_SH7781]    = "SH7781",     [CPU_SH7343]    = "SH7343",
+       [CPU_SH7785]    = "SH7785",
        [CPU_SH_NONE]   = "Unknown"
 };
 
index 8a2fd19..ceee791 100644 (file)
@@ -73,8 +73,6 @@ DECLARE_EXPORT(__lshrdi3);
 DECLARE_EXPORT(__movstr);
 DECLARE_EXPORT(__movstrSI16);
 
-EXPORT_SYMBOL(strcpy);
-
 #ifdef CONFIG_CPU_SH4
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
@@ -101,10 +99,6 @@ 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);
index 5213f5b..bb1c480 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/elf.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
+#include <linux/freezer.h>
 
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -37,7 +38,7 @@
 asmlinkage int
 sys_sigsuspend(old_sigset_t mask,
               unsigned long r5, unsigned long r6, unsigned long r7,
-              struct pt_regs regs)
+              struct pt_regs __regs)
 {
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
@@ -52,7 +53,7 @@ sys_sigsuspend(old_sigset_t mask,
        return -ERESTARTNOHAND;
 }
 
-asmlinkage int 
+asmlinkage int
 sys_sigaction(int sig, const struct old_sigaction __user *act,
              struct old_sigaction __user *oact)
 {
@@ -87,9 +88,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 asmlinkage int
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                unsigned long r6, unsigned long r7,
-               struct pt_regs regs)
+               struct pt_regs __regs)
 {
-       return do_sigaltstack(uss, uoss, regs.regs[15]);
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+
+       return do_sigaltstack(uss, uoss, regs->regs[15]);
 }
 
 
@@ -98,7 +101,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
  */
 
 #define MOVW(n)         (0x9300|((n)-2))       /* Move mem word at PC+n to R3 */
-#define TRAP16  0xc310                 /* Syscall w/no args (NR in R3) */
+#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
+#define TRAP_NOARG 0xc320              /* Syscall w/no args (NR in R3) */
+#else
+#define TRAP_NOARG 0xc310              /* Syscall w/no args (NR in R3) */
+#endif
 #define OR_R0_R0 0x200b                        /* or r0,r0 (insert to avoid hardware bug) */
 
 struct sigframe
@@ -194,9 +201,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
 
 asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
                             unsigned long r6, unsigned long r7,
-                            struct pt_regs regs)
+                            struct pt_regs __regs)
 {
-       struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15];
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15];
        sigset_t set;
        int r0;
 
@@ -216,7 +224,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(&regs, &frame->sc, &r0))
+       if (restore_sigcontext(regs, &frame->sc, &r0))
                goto badframe;
        return r0;
 
@@ -227,9 +235,10 @@ badframe:
 
 asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
                                unsigned long r6, unsigned long r7,
-                               struct pt_regs regs)
+                               struct pt_regs __regs)
 {
-       struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15];
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
        sigset_t set;
        stack_t st;
        int r0;
@@ -246,14 +255,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
                goto badframe;
 
        if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
                goto badframe;
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
-       do_sigaltstack(&st, NULL, regs.regs[15]);
+       do_sigaltstack(&st, NULL, regs->regs[15]);
 
        return r0;
 
@@ -350,7 +359,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
        } else {
                /* Generate return code (system call to sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
-               err |= __put_user(TRAP16, &frame->retcode[1]);
+               err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
                err |= __put_user(OR_R0_R0, &frame->retcode[2]);
                err |= __put_user(OR_R0_R0, &frame->retcode[3]);
                err |= __put_user(OR_R0_R0, &frame->retcode[4]);
@@ -430,7 +439,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        } else {
                /* Generate return code (system call to rt_sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
-               err |= __put_user(TRAP16, &frame->retcode[1]);
+               err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
                err |= __put_user(OR_R0_R0, &frame->retcode[2]);
                err |= __put_user(OR_R0_R0, &frame->retcode[3]);
                err |= __put_user(OR_R0_R0, &frame->retcode[4]);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..0d5268a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ *  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/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       unsigned long *sp;
+
+       if (!task)
+               task = current;
+       if (task == current)
+               sp = (unsigned long *)current_stack_pointer;
+       else
+               sp = (unsigned long *)task->thread.sp;
+
+       while (!kstack_end(sp)) {
+               unsigned long addr = *sp++;
+
+               if (__kernel_text_address(addr)) {
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = addr;
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
+       }
+}
index 8fde950..5083b6e 100644 (file)
  */
 asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
        unsigned long r6, unsigned long r7,
-       struct pt_regs regs)
+       struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int fd[2];
        int error;
 
        error = do_pipe(fd);
        if (!error) {
-               regs.regs[1] = fd[1];
+               regs->regs[1] = fd[1];
                return fd[0];
        }
        return error;
@@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
 
 EXPORT_SYMBOL(shm_align_mask);
 
+#ifdef CONFIG_MMU
 /*
  * To avoid cache aliases, we map the shared page with same color.
  */
@@ -135,6 +137,7 @@ full_search:
                        addr = COLOUR_ALIGN(addr, pgoff);
        }
 }
+#endif /* CONFIG_MMU */
 
 static inline long
 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 
index 57e708d..c206c95 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/profile.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
 #include <asm/clock.h>
 #include <asm/rtc.h>
 #include <asm/timer.h>
@@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void)
 #ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
+       unsigned long flags;
        unsigned long seq;
        unsigned long usec, sec;
 
        do {
-               seq = read_seqbegin(&xtime_lock);
+               /*
+                * Turn off IRQs when grabbing xtime_lock, so that
+                * the sys_timer get_offset code doesn't have to handle it.
+                */
+               seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = get_timer_offset();
                sec = xtime.tv_sec;
-               usec += xtime.tv_nsec / 1000;
-       } while (read_seqretry(&xtime_lock, seq));
+               usec += xtime.tv_nsec / NSEC_PER_USEC;
+       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
        while (usec >= 1000000) {
                usec -= 1000000;
@@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * made, and then undo it!
         */
-       nsec -= 1000 * get_timer_offset();
+       nsec -= get_timer_offset() * NSEC_PER_USEC;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = {
        .resume  = timer_resume,
 };
 
+#ifdef CONFIG_NO_IDLE_HZ
+static int timer_dyn_tick_enable(void)
+{
+       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
+       unsigned long flags;
+       int ret = -ENODEV;
+
+       if (dyn_tick) {
+               spin_lock_irqsave(&dyn_tick->lock, flags);
+               ret = 0;
+               if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
+                       ret = dyn_tick->enable();
+
+                       if (ret == 0)
+                               dyn_tick->state |= DYN_TICK_ENABLED;
+               }
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
+       }
+
+       return ret;
+}
+
+static int timer_dyn_tick_disable(void)
+{
+       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
+       unsigned long flags;
+       int ret = -ENODEV;
+
+       if (dyn_tick) {
+               spin_lock_irqsave(&dyn_tick->lock, flags);
+               ret = 0;
+               if (dyn_tick->state & DYN_TICK_ENABLED) {
+                       ret = dyn_tick->disable();
+
+                       if (ret == 0)
+                               dyn_tick->state &= ~DYN_TICK_ENABLED;
+               }
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
+       }
+
+       return ret;
+}
+
+/*
+ * Reprogram the system timer for at least the calculated time interval.
+ * This function should be called from the idle thread with IRQs disabled,
+ * immediately before sleeping.
+ */
+void timer_dyn_reprogram(void)
+{
+       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
+       unsigned long next, seq, flags;
+
+       if (!dyn_tick)
+               return;
+
+       spin_lock_irqsave(&dyn_tick->lock, flags);
+       if (dyn_tick->state & DYN_TICK_ENABLED) {
+               next = next_timer_interrupt();
+               do {
+                       seq = read_seqbegin(&xtime_lock);
+                       dyn_tick->reprogram(next - jiffies);
+               } while (read_seqretry(&xtime_lock, seq));
+       }
+       spin_unlock_irqrestore(&dyn_tick->lock, flags);
+}
+
+static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+{
+       return sprintf(buf, "%i\n",
+                      (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
+}
+
+static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
+                                 size_t count)
+{
+       unsigned int enable = simple_strtoul(buf, NULL, 2);
+
+       if (enable)
+               timer_dyn_tick_enable();
+       else
+               timer_dyn_tick_disable();
+
+       return count;
+}
+static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
+
+/*
+ * dyntick=enable|disable
+ */
+static char dyntick_str[4] __initdata = "";
+
+static int __init dyntick_setup(char *str)
+{
+       if (str)
+               strlcpy(dyntick_str, str, sizeof(dyntick_str));
+       return 1;
+}
+
+__setup("dyntick=", dyntick_setup);
+#endif
+
 static int __init timer_init_sysfs(void)
 {
        int ret = sysdev_class_register(&timer_sysclass);
@@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void)
                return ret;
 
        sys_timer->dev.cls = &timer_sysclass;
-       return sysdev_register(&sys_timer->dev);
+       ret = sysdev_register(&sys_timer->dev);
+
+#ifdef CONFIG_NO_IDLE_HZ
+       if (ret == 0 && sys_timer->dyn_tick) {
+               ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
+
+               /*
+                * Turn on dynamic tick after calibrate delay
+                * for correct bogomips
+                */
+               if (ret == 0 && dyntick_str[0] == 'e')
+                       ret = timer_dyn_tick_enable();
+       }
+#endif
+
+       return ret;
 }
 device_initcall(timer_init_sysfs);
 
@@ -200,6 +324,11 @@ void __init time_init(void)
        sys_timer = get_sys_timer();
        printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
 
+#ifdef CONFIG_NO_IDLE_HZ
+       if (sys_timer->dyn_tick)
+               spin_lock_init(&sys_timer->dyn_tick->lock);
+#endif
+
 #if defined(CONFIG_SH_KGDB)
        /*
         * Set up kgdb as requested. We do it here because the serial
index 151a6a3..bcf244f 100644 (file)
@@ -5,4 +5,6 @@
 obj-y  := timer.o
 
 obj-$(CONFIG_SH_TMU)           += timer-tmu.o
+obj-$(CONFIG_SH_MTU2)          += timer-mtu2.o
+obj-$(CONFIG_SH_CMT)           += timer-cmt.o
 
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c
new file mode 100644 (file)
index 0000000..a574b93
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
+ *
+ *  Copyright (C) 2005  Yoshinori Sato
+ *
+ * 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/interrupt.h>
+#include <linux/seqlock.h>
+#include <asm/timer.h>
+#include <asm/rtc.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/clock.h>
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
+#define CMT_CMSTR      0xf84a0070
+#define CMT_CMCSR_0    0xf84a0072
+#define CMT_CMCNT_0    0xf84a0074
+#define CMT_CMCOR_0    0xf84a0076
+#define CMT_CMCSR_1    0xf84a0078
+#define CMT_CMCNT_1    0xf84a007a
+#define CMT_CMCOR_1    0xf84a007c
+
+#define STBCR3         0xf80a0000
+#define cmt_clock_enable() do {        ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
+#define CMT_CMCSR_INIT 0x0040
+#define CMT_CMCSR_CALIB        0x0000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
+#define CMT_CMSTR      0xfffec000
+#define CMT_CMCSR_0    0xfffec002
+#define CMT_CMCNT_0    0xfffec004
+#define CMT_CMCOR_0    0xfffec006
+
+#define STBCR4         0xfffe040c
+#define cmt_clock_enable() do {        ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
+#define CMT_CMCSR_INIT 0x0040
+#define CMT_CMCSR_CALIB        0x0000
+#else
+#error "Unknown CPU SUBTYPE"
+#endif
+
+static unsigned long cmt_timer_get_offset(void)
+{
+       int count;
+       static unsigned short count_p = 0xffff;    /* for the first call after boot */
+       static unsigned long jiffies_p = 0;
+
+       /*
+        * cache volatile jiffies temporarily; we have IRQs turned off.
+        */
+       unsigned long jiffies_t;
+
+       /* timer count may underflow right here */
+       count =  ctrl_inw(CMT_CMCOR_0);
+       count -= ctrl_inw(CMT_CMCNT_0);
+
+       jiffies_t = jiffies;
+
+       /*
+        * avoiding timer inconsistencies (they are rare, but they happen)...
+        * there is one kind of problem that must be avoided here:
+        *  1. the timer counter underflows
+        */
+
+       if (jiffies_t == jiffies_p) {
+               if (count > count_p) {
+                       /* the nutcase */
+                       if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
+                               count -= LATCH;
+                       } else {
+                               printk("%s (): hardware timer problem?\n",
+                                      __FUNCTION__);
+                       }
+               }
+       } else
+               jiffies_p = jiffies_t;
+
+       count_p = count;
+
+       count = ((LATCH-1) - count) * TICK_SIZE;
+       count = (count + LATCH/2) / LATCH;
+
+       return count;
+}
+
+static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
+{
+       unsigned long timer_status;
+
+       /* Clear CMF bit */
+       timer_status = ctrl_inw(CMT_CMCSR_0);
+       timer_status &= ~0x80;
+       ctrl_outw(timer_status, CMT_CMCSR_0);
+
+       /*
+        * Here we are in the timer irq handler. We just have irqs locally
+        * disabled but we don't know if the timer_bh is running on the other
+        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+        * the irq version of write_lock because as just said we have irq
+        * locally disabled. -arca
+        */
+       write_seqlock(&xtime_lock);
+       handle_timer_tick();
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction cmt_irq = {
+       .name           = "timer",
+       .handler        = cmt_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+static void cmt_clk_init(struct clk *clk)
+{
+       u8 divisor = CMT_CMCSR_INIT & 0x3;
+       ctrl_inw(CMT_CMCSR_0);
+       ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
+       clk->parent = clk_get(NULL, "module_clk");
+       clk->rate = clk->parent->rate / (8 << (divisor << 1));
+}
+
+static void cmt_clk_recalc(struct clk *clk)
+{
+       u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
+       clk->rate = clk->parent->rate / (8 << (divisor << 1));
+}
+
+static struct clk_ops cmt_clk_ops = {
+       .init           = cmt_clk_init,
+       .recalc         = cmt_clk_recalc,
+};
+
+static struct clk cmt0_clk = {
+       .name           = "cmt0_clk",
+       .ops            = &cmt_clk_ops,
+};
+
+static int cmt_timer_start(void)
+{
+       ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
+       return 0;
+}
+
+static int cmt_timer_stop(void)
+{
+       ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
+       return 0;
+}
+
+static int cmt_timer_init(void)
+{
+       unsigned long interval;
+
+       cmt_clock_enable();
+
+       setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
+
+       cmt0_clk.parent = clk_get(NULL, "module_clk");
+
+       cmt_timer_stop();
+
+       interval = cmt0_clk.parent->rate / 8 / HZ;
+       printk(KERN_INFO "Interval = %ld\n", interval);
+
+       ctrl_outw(interval, CMT_CMCOR_0);
+
+       clk_register(&cmt0_clk);
+       clk_enable(&cmt0_clk);
+
+       cmt_timer_start();
+
+       return 0;
+}
+
+struct sys_timer_ops cmt_timer_ops = {
+       .init           = cmt_timer_init,
+       .start          = cmt_timer_start,
+       .stop           = cmt_timer_stop,
+#ifndef CONFIG_GENERIC_TIME
+       .get_offset     = cmt_timer_get_offset,
+#endif
+};
+
+struct sys_timer cmt_timer = {
+       .name   = "cmt",
+       .ops    = &cmt_timer_ops,
+};
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
new file mode 100644 (file)
index 0000000..fffcd1c
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
+ *
+ *  Copyright (C) 2005  Paul Mundt
+ *
+ * Based off of arch/sh/kernel/timers/timer-tmu.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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/seqlock.h>
+#include <asm/timer.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/clock.h>
+
+/*
+ * We use channel 1 for our lowly system timer. Channel 2 would be the other
+ * likely candidate, but we leave it alone as it has higher divisors that
+ * would be of more use to other more interesting applications.
+ *
+ * TODO: Presently we only implement a 16-bit single-channel system timer.
+ * However, we can implement channel cascade if we go the overflow route and
+ * get away with using 2 MTU2 channels as a 32-bit timer.
+ */
+#define MTU2_TSTR      0xfffe4280
+#define MTU2_TCR_1     0xfffe4380
+#define MTU2_TMDR_1    0xfffe4381
+#define MTU2_TIOR_1    0xfffe4382
+#define MTU2_TIER_1    0xfffe4384
+#define MTU2_TSR_1     0xfffe4385
+#define MTU2_TCNT_1    0xfffe4386      /* 16-bit counter */
+#define MTU2_TGRA_1    0xfffe438a
+
+#define STBCR3         0xfffe0408
+
+#define MTU2_TSTR_CST1 (1 << 1)        /* Counter Start 1 */
+
+#define MTU2_TSR_TGFA  (1 << 0)        /* GRA compare match */
+
+#define MTU2_TIER_TGIEA        (1 << 0)        /* GRA compare match  interrupt enable */
+
+#define MTU2_TCR_INIT  0x22
+
+#define MTU2_TCR_CALIB  0x00
+
+static unsigned long mtu2_timer_get_offset(void)
+{
+       int count;
+       static int count_p = 0x7fff;    /* for the first call after boot */
+       static unsigned long jiffies_p = 0;
+
+       /*
+        * cache volatile jiffies temporarily; we have IRQs turned off.
+        */
+       unsigned long jiffies_t;
+
+       /* timer count may underflow right here */
+       count = ctrl_inw(MTU2_TCNT_1);  /* read the latched count */
+
+       jiffies_t = jiffies;
+
+       /*
+        * avoiding timer inconsistencies (they are rare, but they happen)...
+        * there is one kind of problem that must be avoided here:
+        *  1. the timer counter underflows
+        */
+
+       if (jiffies_t == jiffies_p) {
+               if (count > count_p) {
+                       if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
+                               count -= LATCH;
+                       } else {
+                               printk("%s (): hardware timer problem?\n",
+                                      __FUNCTION__);
+                       }
+               }
+       } else
+               jiffies_p = jiffies_t;
+
+       count_p = count;
+
+       count = ((LATCH-1) - count) * TICK_SIZE;
+       count = (count + LATCH/2) / LATCH;
+
+       return count;
+}
+
+static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
+{
+       unsigned long timer_status;
+
+       /* Clear TGFA bit */
+       timer_status = ctrl_inb(MTU2_TSR_1);
+       timer_status &= ~MTU2_TSR_TGFA;
+       ctrl_outb(timer_status, MTU2_TSR_1);
+
+       /* Do timer tick */
+       write_seqlock(&xtime_lock);
+       handle_timer_tick();
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction mtu2_irq = {
+       .name           = "timer",
+       .handler        = mtu2_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
+
+static void mtu2_clk_init(struct clk *clk)
+{
+       u8 idx = MTU2_TCR_INIT & 0x7;
+
+       clk->rate = clk->parent->rate / divisors[idx];
+       /* Start TCNT counting */
+       ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
+
+}
+
+static void mtu2_clk_recalc(struct clk *clk)
+{
+       u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
+       clk->rate = clk->parent->rate / divisors[idx];
+}
+
+static struct clk_ops mtu2_clk_ops = {
+       .init           = mtu2_clk_init,
+       .recalc         = mtu2_clk_recalc,
+};
+
+static struct clk mtu2_clk1 = {
+       .name           = "mtu2_clk1",
+       .ops            = &mtu2_clk_ops,
+};
+
+static int mtu2_timer_start(void)
+{
+       ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
+       return 0;
+}
+
+static int mtu2_timer_stop(void)
+{
+       ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
+       return 0;
+}
+
+static int mtu2_timer_init(void)
+{
+       u8 tmp;
+       unsigned long interval;
+
+       setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
+
+       mtu2_clk1.parent = clk_get(NULL, "module_clk");
+
+       ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
+
+       /* Normal operation */
+       ctrl_outb(0, MTU2_TMDR_1);
+       ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
+       ctrl_outb(0x01, MTU2_TIOR_1);
+
+       /* Enable underflow interrupt */
+       ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
+
+       interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
+       printk(KERN_INFO "Interval = %ld\n", interval);
+
+       ctrl_outw(interval, MTU2_TGRA_1);
+       ctrl_outw(0, MTU2_TCNT_1);
+
+       clk_register(&mtu2_clk1);
+       clk_enable(&mtu2_clk1);
+
+       return 0;
+}
+
+struct sys_timer_ops mtu2_timer_ops = {
+       .init           = mtu2_timer_init,
+       .start          = mtu2_timer_start,
+       .stop           = mtu2_timer_stop,
+#ifndef CONFIG_GENERIC_TIME
+       .get_offset     = mtu2_timer_get_offset,
+#endif
+};
+
+struct sys_timer mtu2_timer = {
+       .name   = "mtu2",
+       .ops    = &mtu2_timer_ops,
+};
index 2492701..e060e71 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
 #include <linux/seqlock.h>
 #include <asm/timer.h>
 #include <asm/rtc.h>
 
 #define TMU0_TCR_CALIB 0x0000
 
-static DEFINE_SPINLOCK(tmu0_lock);
-
 static unsigned long tmu_timer_get_offset(void)
 {
        int count;
-       unsigned long flags;
-
        static int count_p = 0x7fffffff;    /* for the first call after boot */
        static unsigned long jiffies_p = 0;
 
@@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void)
         */
        unsigned long jiffies_t;
 
-       spin_lock_irqsave(&tmu0_lock, flags);
        /* timer count may underflow right here */
        count = ctrl_inl(TMU0_TCNT);    /* read the latched count */
 
@@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void)
                jiffies_p = jiffies_t;
 
        count_p = count;
-       spin_unlock_irqrestore(&tmu0_lock, flags);
 
        count = ((LATCH-1) - count) * TICK_SIZE;
        count = (count + LATCH/2) / LATCH;
@@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 static struct irqaction tmu_irq = {
        .name           = "timer",
        .handler        = tmu_timer_interrupt,
-       .flags          = IRQF_DISABLED,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
        .mask           = CPU_MASK_NONE,
 };
 
@@ -149,9 +142,9 @@ static int tmu_timer_init(void)
 {
        unsigned long interval;
 
-       setup_irq(TIMER_IRQ, &tmu_irq);
+       setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
 
-       tmu0_clk.parent = clk_get("module_clk");
+       tmu0_clk.parent = clk_get(NULL, "module_clk");
 
        /* Start TMU0 */
        tmu_timer_stop();
index dc1f631..a6bcc91 100644 (file)
 static struct sys_timer *sys_timers[] __initdata = {
 #ifdef CONFIG_SH_TMU
        &tmu_timer,
+#endif
+#ifdef CONFIG_SH_MTU2
+       &mtu2_timer,
+#endif
+#ifdef CONFIG_SH_CMT
+       &cmt_timer,
 #endif
        NULL,
 };
index 53dfa55..3762d9d 100644 (file)
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/io.h>
+#include <linux/debug_locks.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs)                         \
-{                                              \
+#define CHK_REMOTE_DEBUG(regs)                 \
+{                                              \
        if (kgdb_debug_hook && !user_mode(regs))\
                (*kgdb_debug_hook)(regs);       \
 }
 #endif
 
 #ifdef CONFIG_CPU_SH2
-#define TRAP_RESERVED_INST     4
-#define TRAP_ILLEGAL_SLOT_INST 6
+# define TRAP_RESERVED_INST    4
+# define TRAP_ILLEGAL_SLOT_INST        6
+# define TRAP_ADDRESS_ERROR    9
+# ifdef CONFIG_CPU_SH2A
+#  define TRAP_DIVZERO_ERROR   17
+#  define TRAP_DIVOVF_ERROR    18
+# endif
 #else
 #define TRAP_RESERVED_INST     12
 #define TRAP_ILLEGAL_SLOT_INST 13
@@ -88,7 +94,7 @@ void die(const char * str, struct pt_regs * regs, long err)
 
        if (!user_mode(regs) || in_interrupt())
                dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
-                        (unsigned long)task_stack_page(current));
+                        (unsigned long)task_stack_page(current));
 
        bust_spinlocks(0);
        spin_unlock_irq(&die_lock);
@@ -102,8 +108,6 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
                die(str, regs, err);
 }
 
-static int handle_unaligned_notify_count = 10;
-
 /*
  * try and fix up kernelspace address errors
  * - userspace errors just cause EFAULT to be returned, resulting in SEGV
@@ -198,7 +202,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
                if (copy_to_user(dst,src,4))
                        goto fetch_fault;
                ret = 0;
-               break;
+               break;
 
        case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
                if (instruction & 4)
@@ -222,7 +226,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
                if (copy_from_user(dst,src,4))
                        goto fetch_fault;
                ret = 0;
-               break;
+               break;
 
        case 6: /* mov.[bwl] from memory, possibly with post-increment */
                src = (unsigned char*) *rm;
@@ -230,7 +234,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
                        *rm += count;
                dst = (unsigned char*) rn;
                *(unsigned long*)dst = 0;
-               
+
 #ifdef __LITTLE_ENDIAN__
                if (copy_from_user(dst, src, count))
                        goto fetch_fault;
@@ -241,7 +245,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
                }
 #else
                dst += 4-count;
-               
+
                if (copy_from_user(dst, src, count))
                        goto fetch_fault;
 
@@ -320,7 +324,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
                        return -EFAULT;
 
                /* kernel */
-               die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0);
+               die("delay-slot-insn faulting in handle_unaligned_delayslot",
+                   regs, 0);
        }
 
        return handle_unaligned_ins(instruction,regs);
@@ -342,6 +347,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
 #define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
 #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
 
+/*
+ * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
+ * opcodes..
+ */
+#ifndef CONFIG_CPU_SH2A
+static int handle_unaligned_notify_count = 10;
+
 static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
 {
        u_int rm;
@@ -354,7 +366,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
        if (user_mode(regs) && handle_unaligned_notify_count>0) {
                handle_unaligned_notify_count--;
 
-               printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+               printk(KERN_NOTICE "Fixing up unaligned userspace access "
+                      "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
                       current->comm,current->pid,(u16*)regs->pc,instruction);
        }
 
@@ -478,32 +491,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
                regs->pc += 2;
        return ret;
 }
+#endif /* CONFIG_CPU_SH2A */
+
+#ifdef CONFIG_CPU_HAS_SR_RB
+#define lookup_exception_vector(x)     \
+       __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x)))
+#else
+#define lookup_exception_vector(x)     \
+       __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x)))
+#endif
 
 /*
- * Handle various address error exceptions
+ * Handle various address error exceptions:
+ *  - instruction address error:
+ *       misaligned PC
+ *       PC >= 0x80000000 in user mode
+ *  - data address error (read and write)
+ *       misaligned data access
+ *       access to >= 0x80000000 is user mode
+ * Unfortuntaly we can't distinguish between instruction address error
+ * and data address errors caused by read acceses.
  */
-asmlinkage void do_address_error(struct pt_regs *regs, 
+asmlinkage void do_address_error(struct pt_regs *regs,
                                 unsigned long writeaccess,
                                 unsigned long address)
 {
-       unsigned long error_code;
+       unsigned long error_code = 0;
        mm_segment_t oldfs;
+       siginfo_t info;
+#ifndef CONFIG_CPU_SH2A
        u16 instruction;
        int tmp;
+#endif
 
-       asm volatile("stc       r2_bank,%0": "=r" (error_code));
+       /* Intentional ifdef */
+#ifdef CONFIG_CPU_HAS_SR_RB
+       lookup_exception_vector(error_code);
+#endif
 
        oldfs = get_fs();
 
        if (user_mode(regs)) {
+               int si_code = BUS_ADRERR;
+
                local_irq_enable();
-               current->thread.error_code = error_code;
-               current->thread.trap_no = (writeaccess) ? 8 : 7;
 
                /* bad PC is not something we can fix */
-               if (regs->pc & 1)
+               if (regs->pc & 1) {
+                       si_code = BUS_ADRALN;
                        goto uspace_segv;
+               }
 
+#ifndef CONFIG_CPU_SH2A
                set_fs(USER_DS);
                if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
                        /* Argh. Fault on the instruction itself.
@@ -518,14 +557,23 @@ asmlinkage void do_address_error(struct pt_regs *regs,
 
                if (tmp==0)
                        return; /* sorted */
+#endif
 
-       uspace_segv:
-               printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
-               force_sig(SIGSEGV, current);
+uspace_segv:
+               printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
+                      "access (PC %lx PR %lx)\n", current->comm, regs->pc,
+                      regs->pr);
+
+               info.si_signo = SIGBUS;
+               info.si_errno = 0;
+               info.si_code = si_code;
+               info.si_addr = (void *) address;
+               force_sig_info(SIGBUS, &info, current);
        } else {
                if (regs->pc & 1)
                        die("unaligned program counter", regs, error_code);
 
+#ifndef CONFIG_CPU_SH2A
                set_fs(KERNEL_DS);
                if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
                        /* Argh. Fault on the instruction itself.
@@ -537,6 +585,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
 
                handle_unaligned_access(instruction, regs);
                set_fs(oldfs);
+#else
+               printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
+                      "access\n", current->comm);
+
+               force_sig(SIGSEGV, current);
+#endif
        }
 }
 
@@ -548,7 +602,7 @@ int is_dsp_inst(struct pt_regs *regs)
 {
        unsigned short inst;
 
-       /* 
+       /*
         * Safe guard if DSP mode is already enabled or we're lacking
         * the DSP altogether.
         */
@@ -569,27 +623,49 @@ int is_dsp_inst(struct pt_regs *regs)
 #define is_dsp_inst(regs)      (0)
 #endif /* CONFIG_SH_DSP */
 
+#ifdef CONFIG_CPU_SH2A
+asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs)
+{
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       siginfo_t info;
+
+       switch (r4) {
+       case TRAP_DIVZERO_ERROR:
+               info.si_code = FPE_INTDIV;
+               break;
+       case TRAP_DIVOVF_ERROR:
+               info.si_code = FPE_INTOVF;
+               break;
+       }
+
+       force_sig_info(SIGFPE, &info, current);
+}
+#endif
+
 /* arch/sh/kernel/cpu/sh4/fpu.c */
 extern int do_fpu_inst(unsigned short, struct pt_regs *);
 extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
-               unsigned long r6, unsigned long r7, struct pt_regs regs);
+               unsigned long r6, unsigned long r7, struct pt_regs __regs);
 
 asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
                                unsigned long r6, unsigned long r7,
-                               struct pt_regs regs)
+                               struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        unsigned long error_code;
        struct task_struct *tsk = current;
 
 #ifdef CONFIG_SH_FPU_EMU
-       unsigned short inst;
+       unsigned short inst = 0;
        int err;
 
-       get_user(inst, (unsigned short*)regs.pc);
+       get_user(inst, (unsigned short*)regs->pc);
 
-       err = do_fpu_inst(inst, &regs);
+       err = do_fpu_inst(inst, regs);
        if (!err) {
-               regs.pc += 2;
+               regs->pc += 2;
                return;
        }
        /* not a FPU inst. */
@@ -597,20 +673,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 
 #ifdef CONFIG_SH_DSP
        /* Check if it's a DSP instruction */
-       if (is_dsp_inst(&regs)) {
+       if (is_dsp_inst(regs)) {
                /* Enable DSP mode, and restart instruction. */
-               regs.sr |= SR_DSP;
+               regs->sr |= SR_DSP;
                return;
        }
 #endif
 
-       asm volatile("stc       r2_bank, %0": "=r" (error_code));
+       lookup_exception_vector(error_code);
+
        local_irq_enable();
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = TRAP_RESERVED_INST;
-       CHK_REMOTE_DEBUG(&regs);
+       CHK_REMOTE_DEBUG(regs);
        force_sig(SIGILL, tsk);
-       die_if_no_fixup("reserved instruction", &regs, error_code);
+       die_if_no_fixup("reserved instruction", regs, error_code);
 }
 
 #ifdef CONFIG_SH_FPU_EMU
@@ -658,39 +733,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs)
 
 asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
                                unsigned long r6, unsigned long r7,
-                               struct pt_regs regs)
+                               struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        unsigned long error_code;
        struct task_struct *tsk = current;
 #ifdef CONFIG_SH_FPU_EMU
-       unsigned short inst;
+       unsigned short inst = 0;
 
-       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))
+       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));
+       lookup_exception_vector(error_code);
+
        local_irq_enable();
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = TRAP_RESERVED_INST;
-       CHK_REMOTE_DEBUG(&regs);
+       CHK_REMOTE_DEBUG(regs);
        force_sig(SIGILL, tsk);
-       die_if_no_fixup("illegal slot instruction", &regs, error_code);
+       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,
-                                  struct pt_regs regs)
+                                  struct pt_regs __regs)
 {
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        long ex;
-       asm volatile("stc       r2_bank, %0" : "=r" (ex));
-       die_if_kernel("exception", &regs, ex);
+
+       lookup_exception_vector(ex);
+       die_if_kernel("exception", regs, ex);
 }
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
@@ -735,12 +812,16 @@ void *set_exception_table_vec(unsigned int vec, void *handler)
 {
        extern void *exception_handling_table[];
        void *old_handler;
-       
+
        old_handler = exception_handling_table[vec];
        exception_handling_table[vec] = handler;
        return old_handler;
 }
 
+extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5,
+                                            unsigned long r6, unsigned long r7,
+                                            struct pt_regs __regs);
+
 void __init trap_init(void)
 {
        set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
@@ -759,7 +840,15 @@ void __init trap_init(void)
        set_exception_table_evt(0x800, do_fpu_state_restore);
        set_exception_table_evt(0x820, do_fpu_state_restore);
 #endif
-               
+
+#ifdef CONFIG_CPU_SH2
+       set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler);
+#endif
+#ifdef CONFIG_CPU_SH2A
+       set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
+       set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
+#endif
+
        /* Setup VBR for boot cpu */
        per_cpu_trap_init();
 }
@@ -784,6 +873,11 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
        }
 
        printk("\n");
+
+       if (!tsk)
+               tsk = current;
+
+       debug_show_held_locks(tsk);
 }
 
 void show_stack(struct task_struct *tsk, unsigned long *sp)
index 075d6cc..deb4694 100644 (file)
@@ -97,7 +97,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
                goto up_fail;
        }
 
-       vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
        if (!vma) {
                ret = -ENOMEM;
                goto up_fail;
index 9dd6064..4e0362f 100644 (file)
@@ -4,8 +4,12 @@ menu "Processor selection"
 # Processor families
 #
 config CPU_SH2
+       select SH_WRITETHROUGH if !CPU_SH2A
        bool
-       select SH_WRITETHROUGH
+
+config CPU_SH2A
+       bool
+       select CPU_SH2
 
 config CPU_SH3
        bool
@@ -16,6 +20,7 @@ config CPU_SH4
        bool
        select CPU_HAS_INTEVT
        select CPU_HAS_SR_RB
+       select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
 
 config CPU_SH4A
        bool
@@ -40,6 +45,16 @@ config CPU_SUBTYPE_SH7604
        bool "Support SH7604 processor"
        select CPU_SH2
 
+config CPU_SUBTYPE_SH7619
+       bool "Support SH7619 processor"
+       select CPU_SH2
+
+comment "SH-2A Processor Support"
+
+config CPU_SUBTYPE_SH7206
+       bool "Support SH7206 processor"
+       select CPU_SH2A
+
 comment "SH-3 Processor Support"
 
 config CPU_SUBTYPE_SH7300
@@ -89,6 +104,7 @@ comment "SH-4 Processor Support"
 config CPU_SUBTYPE_SH7750
        bool "Support SH7750 processor"
        select CPU_SH4
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
 
@@ -104,15 +120,18 @@ config CPU_SUBTYPE_SH7750R
        bool "Support SH7750R processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7750
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7750S
        bool "Support SH7750S processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7750
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7751
        bool "Support SH7751 processor"
        select CPU_SH4
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
          or if you have a HD6417751R CPU.
@@ -121,6 +140,7 @@ config CPU_SUBTYPE_SH7751R
        bool "Support SH7751R processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7751
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7760
        bool "Support SH7760 processor"
@@ -157,6 +177,11 @@ config CPU_SUBTYPE_SH7780
        select CPU_SH4A
        select CPU_HAS_INTC2_IRQ
 
+config CPU_SUBTYPE_SH7785
+       bool "Support SH7785 processor"
+       select CPU_SH4A
+       select CPU_HAS_INTC2_IRQ
+
 comment "SH4AL-DSP Processor Support"
 
 config CPU_SUBTYPE_SH73180
@@ -216,13 +241,22 @@ config MEMORY_SIZE
 
 config 32BIT
        bool "Support 32-bit physical addressing through PMB"
-       depends on CPU_SH4A && MMU
+       depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
        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 X2TLB
+       bool "Enable extended TLB mode"
+       depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
+       help
+         Selecting this option will enable the extended mode of the SH-X2
+         TLB. For legacy SH-X behaviour and interoperability, say N. For
+         all of the fun new features and a willingless to submit bug reports,
+         say Y.
+
 config VSYSCALL
        bool "Support vsyscall page"
        depends on MMU
@@ -236,17 +270,53 @@ config VSYSCALL
          For systems with an MMU that can afford to give up a page,
          (the default value) say Y.
 
+choice
+       prompt "Kernel page size"
+       default PAGE_SIZE_4KB
+
+config PAGE_SIZE_4KB
+       bool "4kB"
+       help
+         This is the default page size used by all SuperH CPUs.
+
+config PAGE_SIZE_8KB
+       bool "8kB"
+       depends on EXPERIMENTAL && X2TLB
+       help
+         This enables 8kB pages as supported by SH-X2 and later MMUs.
+
+config PAGE_SIZE_64KB
+       bool "64kB"
+       depends on EXPERIMENTAL && CPU_SH4
+       help
+         This enables support for 64kB pages, possible on all SH-4
+         CPUs and later. Highly experimental, not recommended.
+
+endchoice
+
 choice
        prompt "HugeTLB page size"
        depends on HUGETLB_PAGE && CPU_SH4 && MMU
        default HUGETLB_PAGE_SIZE_64K
 
 config HUGETLB_PAGE_SIZE_64K
-       bool "64K"
+       bool "64kB"
+
+config HUGETLB_PAGE_SIZE_256K
+       bool "256kB"
+       depends on X2TLB
 
 config HUGETLB_PAGE_SIZE_1MB
        bool "1MB"
 
+config HUGETLB_PAGE_SIZE_4MB
+       bool "4MB"
+       depends on X2TLB
+
+config HUGETLB_PAGE_SIZE_64MB
+       bool "64MB"
+       depends on X2TLB
+
 endchoice
 
 source "mm/Kconfig"
@@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED
 
 config SH_WRITETHROUGH
        bool "Use write-through caching"
-       default y if CPU_SH2
        help
          Selecting this option will configure the caches in write-through
          mode, as opposed to the default write-back configuration.
index 2689cb2..6614033 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
+
 #include <linux/init.h>
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 
-/*
- * Calculate the OC address and set the way bit on the SH-2.
- *
- * We must have already jump_to_P2()'ed prior to calling this
- * function, since we rely on CCR manipulation to do the
- * Right Thing(tm).
- */
-unsigned long __get_oc_addr(unsigned long set, unsigned long way)
+void __flush_wback_region(void *start, int size)
 {
-       unsigned long ccr;
-
-       /*
-        * On SH-2 the way bit isn't tracked in the address field
-        * if we're doing address array access .. instead, we need
-        * to manually switch out the way in the CCR.
-        */
-       ccr = ctrl_inl(CCR);
-       ccr &= ~0x00c0;
-       ccr |= way << cpu_data->dcache.way_shift;
-
-       /*
-        * Despite the number of sets being halved, we end up losing
-        * the first 2 ways to OCRAM instead of the last 2 (if we're
-        * 4-way). As a result, forcibly setting the W1 bit handily
-        * bumps us up 2 ways.
-        */
-       if (ccr & CCR_CACHE_ORA)
-               ccr |= 1 << (cpu_data->dcache.way_shift + 1);
-
-       ctrl_outl(ccr, CCR);
-
-       return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift);
+       unsigned long v;
+       unsigned long begin, end;
+
+       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+               /* FIXME cache purge */
+               ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
+       }
+}
+
+void __flush_purge_region(void *start, int size)
+{
+       unsigned long v;
+       unsigned long begin, end;
+
+       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+               ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
+       }
+}
+
+void __flush_invalidate_region(void *start, int size)
+{
+       unsigned long v;
+       unsigned long begin, end;
+
+       begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+       end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+               & ~(L1_CACHE_BYTES-1);
+       for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+               ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
+       }
 }
 
index e48cc22..ae531af 100644 (file)
  */
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <asm/addrspace.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/pgalloc.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
@@ -83,9 +79,9 @@ static void __init emit_cache_params(void)
  */
 
 /* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
-#define MAX_P3_SEMAPHORES 16
+#define MAX_P3_MUTEXES 16
 
-struct semaphore p3map_sem[MAX_P3_SEMAPHORES];
+struct mutex p3map_mutex[MAX_P3_MUTEXES];
 
 void __init p3_cache_init(void)
 {
@@ -115,7 +111,7 @@ void __init p3_cache_init(void)
                panic("%s failed.", __FUNCTION__);
 
        for (i = 0; i < cpu_data->dcache.n_aliases; i++)
-               sema_init(&p3map_sem[i], 1);
+               mutex_init(&p3map_mutex[i]);
 }
 
 /*
@@ -229,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start,
         */
        if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
            (start < CACHE_OC_ADDRESS_ARRAY))
-               exec_offset = 0x20000000;
+               exec_offset = 0x20000000;
 
        local_irq_save(flags);
        __flush_cache_4096(start | SH_CACHE_ASSOC,
@@ -250,7 +246,7 @@ void flush_dcache_page(struct page *page)
 
                /* Loop all the D-cache */
                n = cpu_data->dcache.n_aliases;
-               for (i = 0; i < n; i++, addr += PAGE_SIZE)
+               for (i = 0; i < n; i++, addr += 4096)
                        flush_cache_4096(addr, phys);
        }
 
index 7b96425..8a70613 100644 (file)
@@ -1,12 +1,12 @@
-/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $
- *
+/*
  * __clear_user_page, __clear_user, clear_page implementation of SuperH
  *
  * Copyright (C) 2001  Kaz Kojima
  * Copyright (C) 2001, 2002  Niibe Yutaka
- *
+ * Copyright (C) 2006  Paul Mundt
  */
 #include <linux/linkage.h>
+#include <asm/page.h>
 
 /*
  * clear_page_slow
 /*
  * r0 --- scratch
  * r4 --- to
- * r5 --- to + 4096
+ * r5 --- to + PAGE_SIZE
  */
 ENTRY(clear_page_slow)
        mov     r4,r5
-       mov.w   .Llimit,r0
+       mov.l   .Llimit,r0
        add     r0,r5
        mov     #0,r0
        !
@@ -50,7 +50,7 @@ ENTRY(clear_page_slow)
        !
        rts
         nop
-.Llimit:       .word   (4096-28)
+.Llimit:       .long   (PAGE_SIZE-28)
 
 ENTRY(__clear_user)
        !
@@ -164,10 +164,10 @@ ENTRY(__clear_user)
  * r0 --- scratch 
  * r4 --- to
  * r5 --- orig_to
- * r6 --- to + 4096
+ * r6 --- to + PAGE_SIZE
  */
 ENTRY(__clear_user_page)
-       mov.w   .L4096,r0
+       mov.l   .Lpsz,r0
        mov     r4,r6
        add     r0,r6
        mov     #0,r0
@@ -191,7 +191,7 @@ ENTRY(__clear_user_page)
        !
        rts
         nop
-.L4096:        .word   4096
+.Lpsz: .long   PAGE_SIZE
 
 #endif
 
index 1addffe..397c94c 100644 (file)
@@ -1,12 +1,12 @@
-/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $
- *
+/*
  * copy_page, __copy_user_page, __copy_user implementation of SuperH
  *
  * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
  * Copyright (C) 2002  Toshinobu Sugioka
- *
+ * Copyright (C) 2006  Paul Mundt
  */
 #include <linux/linkage.h>
+#include <asm/page.h>
 
 /*
  * copy_page_slow
@@ -18,7 +18,7 @@
 
 /*
  * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 
- * r8 --- from + 4096
+ * r8 --- from + PAGE_SIZE
  * r9 --- not used
  * r10 --- to
  * r11 --- from
@@ -30,7 +30,7 @@ ENTRY(copy_page_slow)
        mov     r4,r10
        mov     r5,r11
        mov     r5,r8
-       mov.w   .L4096,r0
+       mov.l   .Lpsz,r0
        add     r0,r8
        !
 1:     mov.l   @r11+,r0
@@ -80,7 +80,7 @@ ENTRY(copy_page_slow)
 
 /*
  * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 
- * r8 --- from + 4096
+ * r8 --- from + PAGE_SIZE
  * r9 --- orig_to
  * r10 --- to
  * r11 --- from
@@ -94,7 +94,7 @@ ENTRY(__copy_user_page)
        mov     r5,r11
        mov     r6,r9
        mov     r5,r8
-       mov.w   .L4096,r0
+       mov.l   .Lpsz,r0
        add     r0,r8
        !
 1:     ocbi    @r9
@@ -129,7 +129,7 @@ ENTRY(__copy_user_page)
        rts
         nop
 #endif
-.L4096:        .word   4096
+.Lpsz: .long   PAGE_SIZE
 /*
  * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
  * Return the number of bytes NOT copied
index 68663b8..716ebf5 100644 (file)
@@ -26,13 +26,19 @@ extern void die(const char *,struct pt_regs *,long);
  * and the problem, and then passes it off to one of the appropriate
  * routines.
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-                             unsigned long address)
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+                                       unsigned long writeaccess,
+                                       unsigned long address)
 {
        struct task_struct *tsk;
        struct mm_struct *mm;
        struct vm_area_struct * vma;
        unsigned long page;
+       int si_code;
+       siginfo_t info;
+
+       trace_hardirqs_on();
+       local_irq_enable();
 
 #ifdef CONFIG_SH_KGDB
        if (kgdb_nofault && kgdb_bus_err_hook)
@@ -41,6 +47,46 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
 
        tsk = current;
        mm = tsk->mm;
+       si_code = SEGV_MAPERR;
+
+       if (unlikely(address >= TASK_SIZE)) {
+               /*
+                * Synchronize this task's top level page-table
+                * with the 'reference' page table.
+                *
+                * Do _not_ use "tsk" here. We might be inside
+                * an interrupt in the middle of a task switch..
+                */
+               int offset = pgd_index(address);
+               pgd_t *pgd, *pgd_k;
+               pud_t *pud, *pud_k;
+               pmd_t *pmd, *pmd_k;
+
+               pgd = get_TTB() + offset;
+               pgd_k = swapper_pg_dir + offset;
+
+               /* This will never happen with the folded page table. */
+               if (!pgd_present(*pgd)) {
+                       if (!pgd_present(*pgd_k))
+                               goto bad_area_nosemaphore;
+                       set_pgd(pgd, *pgd_k);
+                       return;
+               }
+
+               pud = pud_offset(pgd, address);
+               pud_k = pud_offset(pgd_k, address);
+               if (pud_present(*pud) || !pud_present(*pud_k))
+                       goto bad_area_nosemaphore;
+               set_pud(pud, *pud_k);
+
+               pmd = pmd_offset(pud, address);
+               pmd_k = pmd_offset(pud_k, address);
+               if (pmd_present(*pmd) || !pmd_present(*pmd_k))
+                       goto bad_area_nosemaphore;
+               set_pmd(pmd, *pmd_k);
+
+               return;
+       }
 
        /*
         * If we're in an interrupt or have no user
@@ -65,6 +111,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
  * we can handle it..
  */
 good_area:
+       si_code = SEGV_ACCERR;
        if (writeaccess) {
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
@@ -104,10 +151,13 @@ survive:
 bad_area:
        up_read(&mm->mmap_sem);
 
+bad_area_nosemaphore:
        if (user_mode(regs)) {
-               tsk->thread.address = address;
-               tsk->thread.error_code = writeaccess;
-               force_sig(SIGSEGV, tsk);
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               info.si_code = si_code;
+               info.si_addr = (void *) address;
+               force_sig_info(SIGSEGV, &info, tsk);
                return;
        }
 
@@ -127,11 +177,9 @@ no_context:
                printk(KERN_ALERT "Unable to handle kernel paging request");
        printk(" at virtual address %08lx\n", address);
        printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-       asm volatile("mov.l     %1, %0"
-                    : "=r" (page)
-                    : "m" (__m(MMU_TTB)));
+       page = (unsigned long)get_TTB();
        if (page) {
-               page = ((unsigned long *) page)[address >> 22];
+               page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
                printk(KERN_ALERT "*pde = %08lx\n", page);
                if (page & _PAGE_PRESENT) {
                        page &= PAGE_MASK;
@@ -166,98 +214,13 @@ do_sigbus:
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
-       tsk->thread.address = address;
-       tsk->thread.error_code = writeaccess;
-       tsk->thread.trap_no = 14;
-       force_sig(SIGBUS, tsk);
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = BUS_ADRERR;
+       info.si_addr = (void *)address;
+       force_sig_info(SIGBUS, &info, tsk);
 
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
                goto no_context;
 }
-
-#ifdef CONFIG_SH_STORE_QUEUES
-/*
- * This is a special case for the SH-4 store queues, as pages for this
- * space still need to be faulted in before it's possible to flush the
- * store queue cache for writeout to the remapped region.
- */
-#define P3_ADDR_MAX            (P4SEG_STORE_QUE + 0x04000000)
-#else
-#define P3_ADDR_MAX            P4SEG
-#endif
-
-/*
- * Called with interrupts disabled.
- */
-asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
-                                        unsigned long writeaccess,
-                                        unsigned long address)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       pte_t entry;
-       struct mm_struct *mm = current->mm;
-       spinlock_t *ptl;
-       int ret = 1;
-
-#ifdef CONFIG_SH_KGDB
-       if (kgdb_nofault && kgdb_bus_err_hook)
-               kgdb_bus_err_hook();
-#endif
-
-       /*
-        * We don't take page faults for P1, P2, and parts of P4, these
-        * are always mapped, whether it be due to legacy behaviour in
-        * 29-bit mode, or due to PMB configuration in 32-bit mode.
-        */
-       if (address >= P3SEG && address < P3_ADDR_MAX) {
-               pgd = pgd_offset_k(address);
-               mm = NULL;
-       } else {
-               if (unlikely(address >= TASK_SIZE || !mm))
-                       return 1;
-
-               pgd = pgd_offset(mm, address);
-       }
-
-       pud = pud_offset(pgd, address);
-       if (pud_none_or_clear_bad(pud))
-               return 1;
-       pmd = pmd_offset(pud, address);
-       if (pmd_none_or_clear_bad(pmd))
-               return 1;
-
-       if (mm)
-               pte = pte_offset_map_lock(mm, pmd, address, &ptl);
-       else
-               pte = pte_offset_kernel(pmd, address);
-
-       entry = *pte;
-       if (unlikely(pte_none(entry) || pte_not_present(entry)))
-               goto unlock;
-       if (unlikely(writeaccess && !pte_write(entry)))
-               goto unlock;
-
-       if (writeaccess)
-               entry = pte_mkdirty(entry);
-       entry = pte_mkyoung(entry);
-
-#ifdef CONFIG_CPU_SH4
-       /*
-        * ITLB is not affected by "ldtlb" instruction.
-        * So, we need to flush the entry by ourselves.
-        */
-       __flush_tlb_page(get_asid(), address & PAGE_MASK);
-#endif
-
-       set_pte(pte, entry);
-       update_mmu_cache(NULL, address, entry);
-       ret = 0;
-unlock:
-       if (mm)
-               pte_unmap_unlock(pte, ptl);
-       return ret;
-}
index 329059d..cf2c2ee 100644 (file)
@@ -63,6 +63,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       return 0;
+}
+
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
index 7154d1c..59f4cc1 100644 (file)
@@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
        pmd_t *pmd;
        pte_t *pte;
 
-       pgd = swapper_pg_dir + pgd_index(addr);
+       pgd = pgd_offset_k(addr);
        if (pgd_none(*pgd)) {
                pgd_ERROR(*pgd);
                return;
        }
 
-       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;
-               }
+       pud = pud_alloc(NULL, pgd, addr);
+       if (unlikely(!pud)) {
+               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));
-               if (pte != pte_offset_kernel(pmd, 0)) {
-                       pmd_ERROR(*pmd);
-                       return;
-               }
+       pmd = pmd_alloc(NULL, pud, addr);
+       if (unlikely(!pmd)) {
+               pmd_ERROR(*pmd);
+               return;
        }
 
        pte = pte_offset_kernel(pmd, addr);
@@ -155,9 +147,6 @@ extern char __init_begin, __init_end;
 
 /*
  * paging_init() sets up the page tables
- *
- * This routines also unmaps the page at virtual kernel address 0, so
- * that we can trap those pesky NULL-reference errors in the kernel.
  */
 void __init paging_init(void)
 {
@@ -180,14 +169,11 @@ void __init paging_init(void)
         */
        {
                unsigned long max_dma, low, start_pfn;
-               pgd_t *pg_dir;
-               int i;
-
-               /* We don't need kernel mapping as hardware support that. */
-               pg_dir = swapper_pg_dir;
 
-               for (i = 0; i < PTRS_PER_PGD; i++)
-                       pgd_val(pg_dir[i]) = 0;
+               /* We don't need to map the kernel through the TLB, as
+                * it is permanatly mapped using P1. So clear the
+                * entire pgd. */
+               memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
 
                /* Turn on the MMU */
                enable_mmu();
@@ -206,6 +192,10 @@ void __init paging_init(void)
                }
        }
 
+       /* Set an initial value for the MMU.TTB so we don't have to
+        * check for a null value. */
+       set_TTB(swapper_pg_dir);
+
 #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
        /*
         * If we don't have CONFIG_MMU set and the processor in question
@@ -227,7 +217,6 @@ static struct kcore_list kcore_mem, kcore_vmalloc;
 
 void __init mem_init(void)
 {
-       extern unsigned long empty_zero_page[1024];
        int codesize, reservedpages, datasize, initsize;
        int tmp;
        extern unsigned long memory_start;
index a9fe80c..90b494a 100644 (file)
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/addrspace.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
-       unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-       unsigned long pfn;
-       pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
-                                  _PAGE_DIRTY | _PAGE_ACCESSED |
-                                  _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, pfn_pte(pfn, pgprot));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
-       unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                    unsigned long size, unsigned long flags)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset_k(address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pud_t *pud;
-               pmd_t *pmd;
-
-               error = -ENOMEM;
-
-               pud = pud_alloc(&init_mm, dir, address);
-               if (!pud)
-                       break;
-               pmd = pmd_alloc(&init_mm, pud, address);
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                       phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return error;
-}
-
 /*
  * Remap an arbitrary physical address space into the kernel virtual
  * address space. Needed when the kernel wants to access high addresses
@@ -123,6 +37,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
 {
        struct vm_struct * area;
        unsigned long offset, last_addr, addr, orig_addr;
+       pgprot_t pgprot;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -192,8 +107,9 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
        }
 #endif
 
+       pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
        if (likely(size))
-               if (remap_area_pages(addr, phys_addr, size, flags)) {
+               if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
                        vunmap((void *)orig_addr);
                        return NULL;
                }
index 1406d2e..bb23679 100644 (file)
@@ -39,8 +39,6 @@ static void copy_page_dma(void *to, void *from)
 
 static void clear_page_dma(void *to)
 {
-       extern unsigned long empty_zero_page[1024];
-
        /*
         * We get invoked quite early on, if the DMAC hasn't been initialized
         * yet, fall back on the slow manual implementation.
index 07371ed..3f98d2a 100644 (file)
@@ -6,22 +6,12 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#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 <linux/mutex.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-extern struct semaphore p3map_sem[];
+extern struct mutex p3map_mutex[];
 
 #define CACHE_ALIAS (cpu_data->dcache.alias_mask)
 
@@ -37,10 +27,6 @@ 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 |
-                                          _PAGE_RW | _PAGE_CACHABLE |
-                                          _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 *pgd = pgd_offset_k(p3_addr);
@@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
                pte_t entry;
                unsigned long flags;
 
-               entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
-               down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+               entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
+               mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
                set_pte(pte, entry);
                local_irq_save(flags);
                __flush_tlb_page(get_asid(), p3_addr);
@@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
                update_mmu_cache(NULL, p3_addr, entry);
                __clear_user_page((void *)p3_addr, to);
                pte_clear(&init_mm, p3_addr, pte);
-               up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+               mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
        }
 }
 
@@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from, unsigned long address,
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                copy_page(to, from);
        else {
-               pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
-                                          _PAGE_RW | _PAGE_CACHABLE |
-                                          _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 *pgd = pgd_offset_k(p3_addr);
@@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from, unsigned long address,
                pte_t entry;
                unsigned long flags;
 
-               entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
-               down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+               entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
+               mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
                set_pte(pte, entry);
                local_irq_save(flags);
                __flush_tlb_page(get_asid(), p3_addr);
@@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from, unsigned long address,
                update_mmu_cache(NULL, p3_addr, entry);
                __copy_user_page((void *)p3_addr, from, to);
                pte_clear(&init_mm, p3_addr, pte);
-               up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+               mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
        }
 }
 
@@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t
        }
        return pte;
 }
-
index 92e7453..b60ad83 100644 (file)
@@ -30,7 +30,7 @@
 
 #define NR_PMB_ENTRIES 16
 
-static kmem_cache_t *pmb_cache;
+static struct kmem_cache *pmb_cache;
 static unsigned long pmb_map;
 
 static struct pmb_entry pmb_init_map[] = {
@@ -283,7 +283,7 @@ void pmb_unmap(unsigned long addr)
        } while (pmbe);
 }
 
-static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
 {
        struct pmb_entry *pmbe = pmb;
 
@@ -297,7 +297,7 @@ static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
        spin_unlock_irq(&pmb_list_lock);
 }
 
-static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+static void pmb_cache_dtor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
 {
        spin_lock_irq(&pmb_list_lock);
        pmb_list_del(pmb);
index c265185..60402ee 100644 (file)
@@ -142,7 +142,7 @@ static u64 sh7750_read_counter(int counter)
  */
 static inline int to_counter(struct file *file)
 {
-       const unsigned char *name = file->f_dentry->d_parent->d_name.name;
+       const unsigned char *name = file->f_path.dentry->d_parent->d_name.name;
 
        return (int)simple_strtol(name, NULL, 10);
 }
index ac57638..0571755 100644 (file)
@@ -30,3 +30,5 @@ R7780MP                       SH_R7780MP
 TITAN                  SH_TITAN
 SHMIN                  SH_SHMIN
 7710VOIPGW             SH_7710VOIPGW
+7206SE                 SH_7206_SOLUTION_ENGINE
+7619SE                 SH_7619_SOLUTION_ENGINE
index 58c678e..7bc0744 100644 (file)
@@ -39,6 +39,14 @@ config RWSEM_XCHGADD_ALGORITHM
 config GENERIC_ISA_DMA
        bool
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 source init/Kconfig
 
 menu "System type"
index ffb310e..b9e7d54 100644 (file)
@@ -243,9 +243,7 @@ void __init setup_arch(char **cmdline_p)
                if (INITRD_START + INITRD_SIZE <= (PFN_PHYS(last_pfn))) {
                        reserve_bootmem_node(NODE_DATA(0), INITRD_START + __MEMORY_START, INITRD_SIZE);
 
-                       initrd_start =
-                         (long) INITRD_START ? INITRD_START + PAGE_OFFSET +  __MEMORY_START : 0;
-
+                       initrd_start = (long) INITRD_START + PAGE_OFFSET + __MEMORY_START;
                        initrd_end = initrd_start + INITRD_SIZE;
                } else {
                        printk("initrd extends beyond end of memory "
index 9e2ffc4..1666d3e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/personality.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
index 8e2f6c2..4f72ab3 100644 (file)
@@ -154,7 +154,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        /* TLB misses upon some cache flushes get done under cli() */
index 187cf01..4b455f6 100644 (file)
@@ -53,6 +53,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       return 0;
+}
+
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                     pte_t *ptep, pte_t entry)
 {
index 80c5675..ff26c02 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <linux/ioport.h>
 static void shmedia_mapioaddr(unsigned long, unsigned long);
 static unsigned long shmedia_ioremap(struct resource *, u32, int);
 
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-       unsigned long pfn;
-       pgprot_t pgprot = __pgprot(_PAGE_PRESENT  | _PAGE_READ   |
-                                  _PAGE_WRITE    | _PAGE_DIRTY  |
-                                  _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-
-       pfn = phys_addr >> PAGE_SHIFT;
-
-       pr_debug("    %s: pte %p address %lx size %lx phys_addr %lx\n",
-                __FUNCTION__,pte,address,size,phys_addr);
-
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-
-               set_pte(pte, pfn_pte(pfn, pgprot));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-
-       phys_addr -= address;
-
-       if (address >= end)
-               BUG();
-
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                                unsigned long size, unsigned long flags)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset_k(address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                  phys_addr + address, flags)) {
-                        break;
-               }
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return 0;
-}
-
 /*
  * Generic mapping function (not visible outside):
  */
@@ -136,12 +46,17 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
        void * addr;
        struct vm_struct * area;
        unsigned long offset, last_addr;
+       pgprot_t pgprot;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
        if (!size || last_addr < phys_addr)
                return NULL;
 
+       pgprot = __pgprot(_PAGE_PRESENT  | _PAGE_READ   |
+                         _PAGE_WRITE    | _PAGE_DIRTY  |
+                         _PAGE_ACCESSED | _PAGE_SHARED | flags);
+
        /*
         * Mappings have to be page-aligned
         */
@@ -158,7 +73,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
                return NULL;
        area->phys_addr = phys_addr;
        addr = area->addr;
-       if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, pgprot)) {
                vunmap(addr);
                return NULL;
        }
index 92a7c8a..d0dec1e 100644 (file)
@@ -166,6 +166,14 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config SUN_PM
        bool
        default y
index 54d51b4..cbbc988 100644 (file)
@@ -317,9 +317,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
        if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0)
                goto err_nopages;
 
-       if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+       if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
                goto err_nomem;
-       memset((char*)res, 0, sizeof(struct resource));
 
        if (allocate_resource(&_sparc_dvma, res, len_total,
            _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
@@ -589,12 +588,11 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
                return NULL;
        }
 
-       if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+       if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
                free_pages(va, order);
                printk("pci_alloc_consistent: no core\n");
                return NULL;
        }
-       memset((char*)res, 0, sizeof(struct resource));
 
        if (allocate_resource(&_sparc_dvma, res, len_total,
            _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
index 46200c4..dab6169 100644 (file)
@@ -793,10 +793,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
 {
        struct of_device *dev;
 
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
-       memset(dev, 0, sizeof(*dev));
 
        dev->dev.parent = parent;
        dev->dev.bus = bus;
index 1baf13e..003f8ee 100644 (file)
@@ -289,7 +289,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
-               pt_succ_return(regs, 0);
+               if (ret < 0)
+                       pt_error_return(regs, -ret);
+               else
+                       pt_succ_return(regs, 0);
                goto out;
        }
 
index d4f9da8..cf1b8ba 100644 (file)
@@ -545,8 +545,11 @@ void __init sun4d_init_sbi_irq(void)
        nsbi = 0;
        for_each_sbus(sbus)
                nsbi++;
-       sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
-       memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
+       sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
+       if (!sbus_actions) {
+               prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
+               prom_halt();
+       }
        for_each_sbus(sbus) {
 #ifdef CONFIG_SMP      
                extern unsigned char boot_cpu_id;
index 6f3ac54..0bf8c16 100644 (file)
@@ -94,8 +94,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
         * SunOS is so stupid some times... hmph!
         */
        if (file) {
-               if (imajor(file->f_dentry->d_inode) == MEM_MAJOR &&
-                   iminor(file->f_dentry->d_inode) == 5) {
+               if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR &&
+                   iminor(file->f_path.dentry->d_inode) == 5) {
                        flags |= MAP_ANONYMOUS;
                        fput(file);
                        file = NULL;
@@ -655,7 +655,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
        if (!file)
                goto out;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        socket = SOCKET_I(inode);
        local.sin_family = AF_INET;
index 5cc5ff7..b73e6b9 100644 (file)
@@ -11,6 +11,7 @@ SECTIONS
   . = 0x10000 + SIZEOF_HEADERS;
   .text 0xf0004000 :
   {
+    _text = .;
     *(.text)
     SCHED_TEXT
     LOCK_TEXT
index 4d8ed9c..01fc6c2 100644 (file)
@@ -35,7 +35,7 @@ void *kmap_atomic(struct page *page, enum km_type type)
        unsigned long vaddr;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-       inc_preempt_count();
+       pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
@@ -70,8 +70,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
        unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
 
        if (vaddr < FIXADDR_START) { // FIXME
-               dec_preempt_count();
-               preempt_check_resched();
+               pagefault_enable();
                return;
        }
 
@@ -97,8 +96,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
 #endif
 #endif
 
-       dec_preempt_count();
-       preempt_check_resched();
+       pagefault_enable();
 }
 
 /* We may be fed a pagetable here by ptep_to_xxx and others. */
index 2bb1309..4ccda77 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/dma.h>
+#include <asm/oplib.h>
 
 /* #define IOUNIT_DEBUG */
 #ifdef IOUNIT_DEBUG
@@ -41,9 +42,12 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
        struct linux_prom_registers iommu_promregs[PROMREG_MAX];
        struct resource r;
 
-       iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+       iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+       if (!iounit) {
+               prom_printf("SUN4D: Cannot alloc iounit, halting.\n");
+               prom_halt();
+       }
 
-       memset(iounit, 0, sizeof(*iounit));
        iounit->limit[0] = IOUNIT_BMAP1_START;
        iounit->limit[1] = IOUNIT_BMAP2_START;
        iounit->limit[2] = IOUNIT_BMAPM_START;
index b627f8d..d41f66a 100644 (file)
@@ -26,6 +26,14 @@ config MMU
        bool
        default y
 
+config STACKTRACE_SUPPORT
+       bool
+       default y
+
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
 config TIME_INTERPOLATION
        bool
        default y
@@ -34,6 +42,14 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 config AUDIT_ARCH
        bool
        default y
index afe0a77..1f130f3 100644 (file)
@@ -1,5 +1,9 @@
 menu "Kernel hacking"
 
+config TRACE_IRQFLAGS_SUPPORT
+       bool
+       default y
+
 source "lib/Kconfig.debug"
 
 config DEBUG_STACK_USAGE
index 2f4612f..0f0d38f 100644 (file)
@@ -1,24 +1,29 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Tue Oct 17 19:29:20 2006
+# Linux kernel version: 2.6.19
+# Sat Dec  9 15:41:30 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_SPARC64_PAGE_SIZE_8KB=y
 # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
 # CONFIG_SPARC64_PAGE_SIZE_512KB is not set
 # CONFIG_SPARC64_PAGE_SIZE_4MB is not set
 CONFIG_SECCOMP=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+CONFIG_HZ=100
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -42,13 +47,14 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -203,6 +209,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -219,7 +226,6 @@ CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -238,6 +244,8 @@ CONFIG_IP_DCCP_CCID2=m
 # CONFIG_IP_DCCP_CCID2_DEBUG is not set
 CONFIG_IP_DCCP_CCID3=m
 CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
 
 #
 # DCCP Kernel Hacking
@@ -405,6 +413,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -425,6 +434,7 @@ CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -468,6 +478,7 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -598,6 +609,7 @@ CONFIG_BNX2=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -724,10 +736,6 @@ CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1038,6 +1046,11 @@ CONFIG_SND_SUN_CS4231=m
 #
 # CONFIG_SOUND_PRIME is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+
 #
 # USB support
 #
@@ -1053,6 +1066,7 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1089,8 +1103,7 @@ CONFIG_USB_UHCI_HCD=m
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_USB_HID_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
@@ -1119,6 +1132,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -1363,6 +1377,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Instrumentation Support
 #
@@ -1373,6 +1392,7 @@ CONFIG_KPROBES=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
@@ -1387,6 +1407,8 @@ CONFIG_SCHEDSTATS=y
 # 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
@@ -1420,8 +1442,9 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -1430,8 +1453,10 @@ CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1456,6 +1481,7 @@ CONFIG_CRYPTO_TEST=m
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
index e1eabeb..eff0c01 100644 (file)
@@ -14,6 +14,7 @@ obj-y         := process.o setup.o cpu.o idprom.o \
                   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
                   visemul.o prom.o of_device.o
 
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-$(CONFIG_PCI)       += ebus.o isa.o pci_common.o pci_iommu.o \
                            pci_psycho.o pci_sabre.o pci_schizo.o \
                            pci_sun4v.o pci_sun4v_asm.o
index d7caa60..f205fc7 100644 (file)
@@ -209,7 +209,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
             N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
            N_TRSIZE(ex) || N_DRSIZE(ex) ||
-           bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+           bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
                return -ENOEXEC;
        }
 
@@ -349,7 +349,7 @@ static int load_aout32_library(struct file *file)
        int retval;
        struct exec ex;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        retval = -ENOEXEC;
        error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
index a98f3ae..9ad84ff 100644 (file)
@@ -141,7 +141,6 @@ cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
        value->tv_sec = jiffies / HZ;
 }
 
-#define elf_addr_t     u32
 #undef start_thread
 #define start_thread start_thread32
 #define init_elf_binfmt init_elf32_binfmt
index 259f37e..9699abe 100644 (file)
@@ -341,7 +341,7 @@ static void fetch_decode_regs(struct mctrl_info *mp)
 
 static int init_one_mctrl(struct device_node *dp)
 {
-       struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+       struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
        int portid = of_getintprop_default(dp, "portid", -1);
        struct linux_prom64_registers *regs;
        void *pval;
@@ -349,7 +349,6 @@ static int init_one_mctrl(struct device_node *dp)
 
        if (!mp)
                return -1;
-       memset(mp, 0, sizeof(*mp));
        if (portid == -1)
                goto fail;
 
index 6f28bec..c15a3ed 100644 (file)
@@ -597,7 +597,12 @@ __spitfire_cee_trap_continue:
 1:     ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
 
-2:     mov             %l4, %o1
+2:
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call    trace_hardirqs_off
+        nop
+#endif
+       mov             %l4, %o1
        mov             %l5, %o2
        call            spitfire_access_error
         add            %sp, PTREGS_OFF, %o0
@@ -824,6 +829,10 @@ do_cheetah_plus_data_parity:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             0x0, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
@@ -855,6 +864,10 @@ do_cheetah_plus_insn_parity:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             0x1, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
@@ -1183,6 +1196,10 @@ c_fast_ecc:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_fecc_handler
@@ -1211,6 +1228,10 @@ c_cee:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_cee_handler
@@ -1239,6 +1260,10 @@ c_deferred:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_deferred_handler
index c8e9dc9..03ffaf8 100644 (file)
@@ -489,6 +489,14 @@ tlb_fixup_done:
        call    __bzero
         sub    %o1, %o0, %o1
 
+#ifdef CONFIG_LOCKDEP
+       /* We have this call this super early, as even prom_init can grab
+        * spinlocks and thus call into the lockdep code.
+        */
+       call    lockdep_init
+        nop
+#endif
+
        mov     %l6, %o1                        ! OpenPROM stack
        call    prom_init
         mov    %l7, %o0                        ! OpenPROM cif handler
index f028e68..ad1c4f5 100644 (file)
@@ -72,14 +72,12 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
                struct linux_prom_registers *regs;
                struct sparc_isa_device *isa_dev;
 
-               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+               isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
                if (!isa_dev) {
                        fatal_err("cannot allocate child isa_dev");
                        prom_halt();
                }
 
-               memset(isa_dev, 0, sizeof(*isa_dev));
-
                /* Link it in to parent. */
                isa_dev->next = parent_isa_dev->child;
                parent_isa_dev->child = isa_dev;
@@ -104,14 +102,12 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
                struct linux_prom_registers *regs;
                struct sparc_isa_device *isa_dev;
 
-               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+               isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
                if (!isa_dev) {
                        printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
                        return;
                }
 
-               memset(isa_dev, 0, sizeof(*isa_dev));
-
                isa_dev->ofdev.node = dp;
                isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
                isa_dev->ofdev.dev.bus = &isa_bus_type;
@@ -180,14 +176,12 @@ void __init isa_init(void)
                pbm = pdev_cookie->pbm;
                dp = pdev_cookie->prom_node;
 
-               isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
+               isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
                if (!isa_br) {
                        printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
                        return;
                }
 
-               memset(isa_br, 0, sizeof(*isa_br));
-
                isa_br->ofdev.node = dp;
                isa_br->ofdev.dev.parent = &pdev->dev;
                isa_br->ofdev.dev.bus = &isa_bus_type;
index 8e75ed7..ae221f0 100644 (file)
@@ -45,7 +45,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        p->ainsn.insn[0] = *p->addr;
+       flushi(&p->ainsn.insn[0]);
+
        p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
+       flushi(&p->ainsn.insn[1]);
+
        p->opcode = *p->addr;
        return 0;
 }
@@ -185,16 +189,19 @@ no_kprobe:
 /* If INSN is a relative control transfer instruction,
  * return the corrected branch destination value.
  *
- * The original INSN location was REAL_PC, it actually
- * executed at PC and produced destination address NPC.
+ * regs->tpc and regs->tnpc still hold the values of the
+ * program counters at the time of trap due to the execution
+ * of the BREAKPOINT_INSTRUCTION_2 at p->ainsn.insn[1]
+ * 
  */
-static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
-                                              unsigned long pc,
-                                              unsigned long npc)
+static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p,
+                                              struct pt_regs *regs)
 {
+       unsigned long real_pc = (unsigned long) p->addr;
+
        /* Branch not taken, no mods necessary.  */
-       if (npc == pc + 0x4UL)
-               return real_pc + 0x4UL;
+       if (regs->tnpc == regs->tpc + 0x4UL)
+               return real_pc + 0x8UL;
 
        /* The three cases are call, branch w/prediction,
         * and traditional branch.
@@ -202,14 +209,21 @@ static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
        if ((insn & 0xc0000000) == 0x40000000 ||
            (insn & 0xc1c00000) == 0x00400000 ||
            (insn & 0xc1c00000) == 0x00800000) {
+               unsigned long ainsn_addr;
+
+               ainsn_addr = (unsigned long) &p->ainsn.insn[0];
+
                /* The instruction did all the work for us
                 * already, just apply the offset to the correct
                 * instruction location.
                 */
-               return (real_pc + (npc - pc));
+               return (real_pc + (regs->tnpc - ainsn_addr));
        }
 
-       return real_pc + 0x4UL;
+       /* It is jmpl or some other absolute PC modification instruction,
+        * leave NPC as-is.
+        */
+       return regs->tnpc;
 }
 
 /* If INSN is an instruction which writes it's PC location
@@ -220,12 +234,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
 {
        unsigned long *slot = NULL;
 
-       /* Simplest cast is call, which always uses %o7 */
+       /* Simplest case is 'call', which always uses %o7 */
        if ((insn & 0xc0000000) == 0x40000000) {
                slot = &regs->u_regs[UREG_I7];
        }
 
-       /* Jmpl encodes the register inside of the opcode */
+       /* 'jmpl' encodes the register inside of the opcode */
        if ((insn & 0xc1f80000) == 0x81c00000) {
                unsigned long rd = ((insn >> 25) & 0x1f);
 
@@ -247,11 +261,11 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
 
 /*
  * Called after single-stepping.  p->addr is the address of the
- * instruction whose first byte has been replaced by the breakpoint
+ * instruction which has been replaced by the breakpoint
  * instruction.  To avoid the SMP problems that can occur when we
  * temporarily put back the original opcode to single-step, we
  * single-stepped a copy of the instruction.  The address of this
- * copy is p->ainsn.insn.
+ * copy is &p->ainsn.insn[0].
  *
  * This function prepares to return from the post-single-step
  * breakpoint trap.
@@ -261,11 +275,11 @@ static void __kprobes resume_execution(struct kprobe *p,
 {
        u32 insn = p->ainsn.insn[0];
 
+       regs->tnpc = relbranch_fixup(insn, p, regs);
+
+       /* This assignment must occur after relbranch_fixup() */
        regs->tpc = kcb->kprobe_orig_tnpc;
-       regs->tnpc = relbranch_fixup(insn,
-                                    (unsigned long) p->addr,
-                                    (unsigned long) &p->ainsn.insn[0],
-                                    regs->tnpc);
+
        retpc_fixup(regs, insn, (unsigned long) p->addr);
 
        regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
@@ -430,17 +444,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        struct jprobe *jp = container_of(p, struct jprobe, kp);
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-       kcb->jprobe_saved_regs_location = regs;
        memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs));
 
-       /* Save a whole stack frame, this gets arguments
-        * pushed onto the stack after using up all the
-        * arg registers.
-        */
-       memcpy(&(kcb->jprobe_saved_stack),
-              (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-              sizeof(kcb->jprobe_saved_stack));
-
        regs->tpc  = (unsigned long) jp->entry;
        regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
        regs->tstate |= TSTATE_PIL;
@@ -450,10 +455,19 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
-       __asm__ __volatile__(
-               ".globl jprobe_return_trap_instruction\n"
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       register unsigned long orig_fp asm("g1");
+
+       orig_fp = kcb->jprobe_saved_regs.u_regs[UREG_FP];
+       __asm__ __volatile__("\n"
+"1:    cmp             %%sp, %0\n\t"
+       "blu,a,pt       %%xcc, 1b\n\t"
+       " restore\n\t"
+       ".globl         jprobe_return_trap_instruction\n"
 "jprobe_return_trap_instruction:\n\t"
-               "ta 0x70");
+       "ta             0x70"
+       : /* no outputs */
+       : "r" (orig_fp));
 }
 
 extern void jprobe_return_trap_instruction(void);
@@ -466,26 +480,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
        if (addr == (u32 *) jprobe_return_trap_instruction) {
-               if (kcb->jprobe_saved_regs_location != regs) {
-                       printk("JPROBE: Current regs (%p) does not match "
-                              "saved regs (%p).\n",
-                              regs, kcb->jprobe_saved_regs_location);
-                       printk("JPROBE: Saved registers\n");
-                       __show_regs(kcb->jprobe_saved_regs_location);
-                       printk("JPROBE: Current registers\n");
-                       __show_regs(regs);
-                       BUG();
-               }
-               /* Restore old register state.  Do pt_regs
-                * first so that UREG_FP is the original one for
-                * the stack frame restore.
-                */
                memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs));
-
-               memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-                      &(kcb->jprobe_saved_stack),
-                      sizeof(kcb->jprobe_saved_stack));
-
                preempt_enable_no_resched();
                return 1;
        }
index 8cc14fc..cec0ece 100644 (file)
@@ -1007,10 +1007,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
 {
        struct of_device *dev;
 
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
-       memset(dev, 0, sizeof(*dev));
 
        dev->dev.parent = parent;
        dev->dev.bus = bus;
index 03ad4c0..6b04794 100644 (file)
@@ -798,7 +798,7 @@ static struct pci_ops pci_sun4v_ops = {
 static void pbm_scan_bus(struct pci_controller_info *p,
                         struct pci_pbm_info *pbm)
 {
-       struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+       struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
 
        if (!cookie) {
                prom_printf("%s: Critical allocation failure.\n", pbm->name);
@@ -806,7 +806,6 @@ static void pbm_scan_bus(struct pci_controller_info *p,
        }
 
        /* All we care about is the PBM. */
-       memset(cookie, 0, sizeof(*cookie));
        cookie->pbm = pbm;
 
        pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm);
@@ -1048,12 +1047,11 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
        /* Allocate and initialize the free area map.  */
        sz = num_tsb_entries / 8;
        sz = (sz + 7UL) & ~7UL;
-       iommu->arena.map = kmalloc(sz, GFP_KERNEL);
+       iommu->arena.map = kzalloc(sz, GFP_KERNEL);
        if (!iommu->arena.map) {
                prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
                prom_halt();
        }
-       memset(iommu->arena.map, 0, sz);
        iommu->arena.limit = num_tsb_entries;
 
        sz = probe_existing_entries(pbm, iommu);
@@ -1164,24 +1162,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
                per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
        }
 
-       p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+       p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
        if (!p)
                goto fatal_memory_error;
 
-       memset(p, 0, sizeof(*p));
-
-       iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
        if (!iommu)
                goto fatal_memory_error;
 
-       memset(iommu, 0, sizeof(*iommu));
        p->pbm_A.iommu = iommu;
 
-       iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
        if (!iommu)
                goto fatal_memory_error;
 
-       memset(iommu, 0, sizeof(*iommu));
        p->pbm_B.iommu = iommu;
 
        p->next = pci_controller_root;
index d31975e..81111a1 100644 (file)
@@ -202,7 +202,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 #endif
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
-               pt_succ_return(regs, 0);
+               if (ret < 0)
+                       pt_error_return(regs, -ret);
+               else
+                       pt_succ_return(regs, 0);
                goto out;
        }
 
index 3522cd6..079d18a 100644 (file)
@@ -165,14 +165,26 @@ rtrap:
 __handle_softirq_continue:
 rtrap_xcall:
                sethi                   %hi(0xf << 20), %l4
-               andcc                   %l1, TSTATE_PRIV, %l3
                and                     %l1, %l4, %l4
+               andn                    %l1, %l4, %l1
+               srl                     %l4, 20, %l4
+#ifdef CONFIG_TRACE_IRQFLAGS
+               brnz,pn                 %l4, rtrap_no_irq_enable
+                nop
+               call                    trace_hardirqs_on
+                nop
+               wrpr                    %l4, %pil
+rtrap_no_irq_enable:
+#endif
+               andcc                   %l1, TSTATE_PRIV, %l3
                bne,pn                  %icc, to_kernel
-                andn                   %l1, %l4, %l1
+                nop
 
                /* We must hold IRQs off and atomically test schedule+signal
                 * state, then hold them off all the way back to userspace.
-                * If we are returning to kernel, none of this matters.
+                * If we are returning to kernel, none of this matters.  Note
+                * that we are disabling interrupts via PSTATE_IE, not using
+                * %pil.
                 *
                 * If we do not do this, there is a window where we would do
                 * the tests, later the signal/resched event arrives but we do
@@ -256,7 +268,6 @@ rt_continue:        ldx                     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 
                ld                      [%sp + PTREGS_OFF + PT_V9_Y], %o3
                wr                      %o3, %g0, %y
-               srl                     %l4, 20, %l4
                wrpr                    %l4, 0x0, %pil
                wrpr                    %g0, 0x1, %tl
                wrpr                    %l1, %g0, %tstate
@@ -374,8 +385,8 @@ to_kernel:
                 ldx                    [%g6 + TI_FLAGS], %l5
                andcc                   %l5, _TIF_NEED_RESCHED, %g0
                be,pt                   %xcc, kern_fpucheck
-                srl                    %l4, 20, %l5
-               cmp                     %l5, 0
+                nop
+               cmp                     %l4, 0
                bne,pn                  %xcc, kern_fpucheck
                 sethi                  %hi(PREEMPT_ACTIVE), %l6
                stw                     %l6, [%g6 + TI_PRE_COUNT]
diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..c4d15f2
--- /dev/null
@@ -0,0 +1,41 @@
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       unsigned long ksp, fp, thread_base;
+       struct thread_info *tp;
+
+       if (!task)
+               task = current;
+       tp = task_thread_info(task);
+       if (task == current) {
+               flushw_all();
+               __asm__ __volatile__(
+                       "mov    %%fp, %0"
+                       : "=r" (ksp)
+               );
+       } else
+               ksp = tp->ksp;
+
+       fp = ksp + STACK_BIAS;
+       thread_base = (unsigned long) tp;
+       do {
+               struct reg_window *rw;
+
+               /* Bogus frame pointer? */
+               if (fp < (thread_base + sizeof(struct thread_info)) ||
+                   fp >= (thread_base + THREAD_SIZE))
+                       break;
+
+               rw = (struct reg_window *) fp;
+               if (trace->skip > 0)
+                       trace->skip--;
+               else
+                       trace->entries[trace->nr_entries++] = rw->ins[7];
+
+               fp = rw->ins[6] + STACK_BIAS;
+       } while (trace->nr_entries < trace->max_entries);
+}
index 49703c3..405855d 100644 (file)
@@ -190,7 +190,10 @@ sun4v_res_mondo:
        mov     %g1, %g4
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        /* Log the event.  */
        add     %sp, PTREGS_OFF, %o0
        call    sun4v_resum_error
@@ -216,7 +219,10 @@ sun4v_res_mondo_queue_full:
        wrpr    %g0, 15, %pil
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call    sun4v_resum_overflow
         add    %sp, PTREGS_OFF, %o0
 
@@ -295,7 +301,10 @@ sun4v_nonres_mondo:
        mov     %g1, %g4
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        /* Log the event.  */
        add     %sp, PTREGS_OFF, %o0
        call    sun4v_nonresum_error
@@ -321,7 +330,10 @@ sun4v_nonres_mondo_queue_full:
        wrpr    %g0, 15, %pil
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call    sun4v_nonresum_overflow
         add    %sp, PTREGS_OFF, %o0
 
index 7da72d3..4446f66 100644 (file)
@@ -83,7 +83,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
                file = fget(fd);
                if (!file)
                        goto out;
-               inode = file->f_dentry->d_inode;
+               inode = file->f_path.dentry->d_inode;
                if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
                        flags |= MAP_ANONYMOUS;
                        fput(file);
@@ -615,7 +615,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
        if (!file)
                return 0;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        socket = SOCKET_I(inode);
        local.sin_family = AF_INET;
index fe1796c..ad67784 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>  /* for jiffies */
+#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/kallsyms.h>
 #include <linux/signal.h>
@@ -1873,6 +1873,16 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
 
        put_cpu();
 
+       if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
+               /* If err_type is 0x4, it's a powerdown request.  Do
+                * not do the usual resumable error log because that
+                * makes it look like some abnormal error.
+                */
+               printk(KERN_INFO "Power down request...\n");
+               kill_cad_pid(SIGINT, 1);
+               return;
+       }
+
        sun4v_log_error(regs, &local_copy, cpu,
                        KERN_ERR "RESUMABLE ERROR",
                        &sun4v_resum_oflow_cnt);
@@ -2261,8 +2271,12 @@ void die_if_kernel(char *str, struct pt_regs *regs)
        do_exit(SIGSEGV);
 }
 
+#define VIS_OPCODE_MASK        ((0x3 << 30) | (0x3f << 19))
+#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
+
 extern int handle_popc(u32 insn, struct pt_regs *regs);
 extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
+extern int vis_emul(struct pt_regs *, unsigned int);
 
 void do_illegal_instruction(struct pt_regs *regs)
 {
@@ -2287,10 +2301,18 @@ void do_illegal_instruction(struct pt_regs *regs)
                        if (handle_ldf_stq(insn, regs))
                                return;
                } else if (tlb_type == hypervisor) {
-                       extern int vis_emul(struct pt_regs *, unsigned int);
+                       if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) {
+                               if (!vis_emul(regs, insn))
+                                       return;
+                       } else {
+                               struct fpustate *f = FPUSTATE;
 
-                       if (!vis_emul(regs, insn))
-                               return;
+                               /* XXX maybe verify XFSR bits like
+                                * XXX do_fpother() does?
+                                */
+                               if (do_mathemu(regs, f))
+                                       return;
+                       }
                }
        }
        info.si_signo = SIGILL;
index a9b7652..bc18d48 100644 (file)
@@ -243,7 +243,7 @@ static inline int ok_for_kernel(unsigned int insn)
        return !floating_point_load_or_store_p(insn);
 }
 
-static void kernel_mna_trap_fault(void)
+static void kernel_mna_trap_fault(int fixup_tstate_asi)
 {
        struct pt_regs *regs = current_thread_info()->kern_una_regs;
        unsigned int insn = current_thread_info()->kern_una_insn;
@@ -274,18 +274,15 @@ static void kernel_mna_trap_fault(void)
        regs->tpc = entry->fixup;
        regs->tnpc = regs->tpc + 4;
 
-       regs->tstate &= ~TSTATE_ASI;
-       regs->tstate |= (ASI_AIUS << 24UL);
+       if (fixup_tstate_asi) {
+               regs->tstate &= ~TSTATE_ASI;
+               regs->tstate |= (ASI_AIUS << 24UL);
+       }
 }
 
-asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+static void log_unaligned(struct pt_regs *regs)
 {
        static unsigned long count, last_time;
-       enum direction dir = decode_direction(insn);
-       int size = decode_access_size(insn);
-
-       current_thread_info()->kern_una_regs = regs;
-       current_thread_info()->kern_una_insn = insn;
 
        if (jiffies - last_time > 5 * HZ)
                count = 0;
@@ -295,6 +292,28 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                printk("Kernel unaligned access at TPC[%lx] ", regs->tpc);
                print_symbol("%s\n", regs->tpc);
        }
+}
+
+asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+{
+       enum direction dir = decode_direction(insn);
+       int size = decode_access_size(insn);
+       int orig_asi, asi;
+
+       current_thread_info()->kern_una_regs = regs;
+       current_thread_info()->kern_una_insn = insn;
+
+       orig_asi = asi = decode_asi(insn, regs);
+
+       /* If this is a {get,put}_user() on an unaligned userspace pointer,
+        * just signal a fault and do not log the event.
+        */
+       if (asi == ASI_AIUS) {
+               kernel_mna_trap_fault(0);
+               return;
+       }
+
+       log_unaligned(regs);
 
        if (!ok_for_kernel(insn) || dir == both) {
                printk("Unsupported unaligned load/store trap for kernel "
@@ -302,10 +321,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                unaligned_panic("Kernel does fpu/atomic "
                                "unaligned load/store.", regs);
 
-               kernel_mna_trap_fault();
+               kernel_mna_trap_fault(0);
        } else {
                unsigned long addr, *reg_addr;
-               int orig_asi, asi, err;
+               int err;
 
                addr = compute_effective_address(regs, insn,
                                                 ((insn >> 25) & 0x1f));
@@ -315,7 +334,6 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                       regs->tpc, dirstrings[dir], addr, size,
                       regs->u_regs[UREG_RETPC]);
 #endif
-               orig_asi = asi = decode_asi(insn, regs);
                switch (asi) {
                case ASI_NL:
                case ASI_AIUPL:
@@ -365,7 +383,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                        /* Not reached... */
                }
                if (unlikely(err))
-                       kernel_mna_trap_fault();
+                       kernel_mna_trap_fault(1);
                else
                        advance(regs);
        }
index 84fedaa..c3fd647 100644 (file)
 /* 001001100 - Permute bytes as specified by GSR.MASK  */
 #define BSHUFFLE_OPF   0x04c
 
-#define VIS_OPCODE_MASK        ((0x3 << 30) | (0x3f << 19))
-#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
-
 #define VIS_OPF_SHIFT  5
 #define VIS_OPF_MASK   (0x1ff << VIS_OPF_SHIFT)
 
@@ -810,9 +807,6 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
        if (get_user(insn, (u32 __user *) pc))
                return -EFAULT;
 
-       if ((insn & VIS_OPCODE_MASK) != VIS_OPCODE_VAL)
-               return -EINVAL;
-
        opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT;
        switch (opf) {
        default:
index bd9de8c..4a6063f 100644 (file)
@@ -13,6 +13,7 @@ SECTIONS
   . = 0x4000;
   .text 0x0000000000404000 :
   {
+    _text = .;
     *(.text)
     SCHED_TEXT
     LOCK_TEXT
index 53b9b1f..33fd0b2 100644 (file)
@@ -235,6 +235,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+       return 0;
+}
+
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                     pte_t *ptep, pte_t entry)
 {
index 09cb7fc..a8e8802 100644 (file)
@@ -176,9 +176,9 @@ unsigned long sparc64_kern_sec_context __read_mostly;
 
 int bigkernel = 0;
 
-kmem_cache_t *pgtable_cache __read_mostly;
+struct kmem_cache *pgtable_cache __read_mostly;
 
-static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
 {
        clear_page(addr);
 }
index beaa028..236d02f 100644 (file)
@@ -239,7 +239,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
        }
 }
 
-static kmem_cache_t *tsb_caches[8] __read_mostly;
+static struct kmem_cache *tsb_caches[8] __read_mostly;
 
 static const char *tsb_cache_names[8] = {
        "tsb_8KB",
index d70b60a..737c269 100644 (file)
@@ -477,6 +477,10 @@ xcall_sync_tick:
        sethi           %hi(109f), %g7
        b,pt            %xcc, etrap_irq
 109:    or             %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call            smp_synchronize_tick_client
         nop
        clr             %l6
@@ -508,6 +512,10 @@ xcall_report_regs:
        sethi           %hi(109f), %g7
        b,pt            %xcc, etrap_irq
 109:    or             %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call            __show_regs
         add            %sp, PTREGS_OFF, %o0
        clr             %l6
index 12a940c..61be597 100644 (file)
@@ -449,7 +449,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
        error = -EBADF;
        file = fget(fd);
        if (file) {
-               error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf);
+               error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
                fput(file);
        }
 
@@ -481,7 +481,7 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
        file = fget(fd);
        if (file) {
                lock_kernel();
-               error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf);
+               error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
                unlock_kernel();
                fput(file);
        }
index be0a054..330743c 100644 (file)
@@ -299,8 +299,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
        rcu_read_lock();
        fdt = files_fdtable(current->files);
        if (! fdt->fd[fd] ||
-           ! fdt->fd[fd]->f_dentry ||
-           ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
+           ! fdt->fd[fd]->f_path.dentry ||
+           ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
            ! S_ISSOCK(ino->i_mode)) {
                rcu_read_unlock();
                return TBADF;
@@ -480,7 +480,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd
         struct sol_socket_struct *sock;
         struct module_info *mi;
 
-        ino = filp->f_dentry->d_inode;
+        ino = filp->f_path.dentry->d_inode;
         if (!S_ISSOCK(ino->i_mode))
                return -EBADF;
         sock = filp->private_data;
index 9ed9979..bca16e8 100644 (file)
@@ -77,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
                if (!file)
                        goto out;
                else {
-                       struct inode * inode = file->f_dentry->d_inode;
+                       struct inode * inode = file->f_path.dentry->d_inode;
                        if(imajor(inode) == MEM_MAJOR &&
                           iminor(inode) == 5) {
                                flags |= MAP_ANONYMOUS;
@@ -423,9 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
                           Solaris setpgrp and setsid? */
                        ret = sys_setpgid(0, 0);
                        if (ret) return ret;
-                       mutex_lock(&tty_mutex);
-                       current->signal->tty = NULL;
-                       mutex_unlock(&tty_mutex);
+                       proc_clear_tty(current);
                        return process_group(current);
                }
        case 2: /* getsid */
index 7c90e41..89a4757 100644 (file)
@@ -96,13 +96,13 @@ static int socksys_open(struct inode * inode, struct file * filp)
         * No shit.  WTF is it supposed to do, anyway?
         *
         * Try instead:
-        * d_delete(filp->f_dentry), then d_instantiate with sock inode
+        * d_delete(filp->f_path.dentry), then d_instantiate with sock inode
         */
-       dentry = filp->f_dentry;
-       filp->f_dentry = dget(fcheck(fd)->f_dentry);
-       filp->f_dentry->d_inode->i_rdev = inode->i_rdev;
-       filp->f_dentry->d_inode->i_flock = inode->i_flock;
-       SOCKET_I(filp->f_dentry->d_inode)->file = filp;
+       dentry = filp->f_path.dentry;
+       filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
+       filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
+       filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
+       SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
        filp->f_op = &socksys_file_ops;
         sock = (struct sol_socket_struct*) 
                mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
@@ -148,7 +148,7 @@ static unsigned int socksys_poll(struct file * filp, poll_table * wait)
        struct inode *ino;
        unsigned int mask = 0;
 
-       ino=filp->f_dentry->d_inode;
+       ino=filp->f_path.dentry->d_inode;
        if (ino && S_ISSOCK(ino->i_mode)) {
                struct sol_socket_struct *sock;
                sock = (struct sol_socket_struct*)filp->private_data;
index b84e545..a9d32ce 100644 (file)
@@ -147,7 +147,7 @@ static void timod_wake_socket(unsigned int fd)
 
        SOLD("wakeing socket");
        fdt = files_fdtable(current->files);
-       sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode);
+       sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
        wake_up_interruptible(&sock->wait);
        read_lock(&sock->sk->sk_callback_lock);
        if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -361,7 +361,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
 
        fdt = files_fdtable(current->files);
        filp = fdt->fd[fd];
-       ino = filp->f_dentry->d_inode;
+       ino = filp->f_path.dentry->d_inode;
        sock = (struct sol_socket_struct *)filp->private_data;
        SOLD("entry");
        if (get_user(ret, (int __user *)A(ctl_buf)))
@@ -644,7 +644,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
        SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
        fdt = files_fdtable(current->files);
        filp = fdt->fd[fd];
-       ino = filp->f_dentry->d_inode;
+       ino = filp->f_path.dentry->d_inode;
        sock = (struct sol_socket_struct *)filp->private_data;
        SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
        if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
@@ -865,7 +865,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
        filp = fdt->fd[fd];
        if(!filp) goto out;
 
-       ino = filp->f_dentry->d_inode;
+       ino = filp->f_path.dentry->d_inode;
        if (!ino || !S_ISSOCK(ino->i_mode))
                goto out;
 
@@ -933,7 +933,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
        filp = fdt->fd[fd];
        if(!filp) goto out;
 
-       ino = filp->f_dentry->d_inode;
+       ino = filp->f_path.dentry->d_inode;
        if (!ino) goto out;
 
        if (!S_ISSOCK(ino->i_mode) &&
index 5ac1f29..d32a80e 100644 (file)
@@ -47,6 +47,11 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
 # Used in kernel/irq/manage.c and include/linux/irq.h
 config IRQ_RELEASE_METHOD
        bool
index 3576b3c..7d4190e 100644 (file)
@@ -638,7 +638,7 @@ int chan_out_fd(struct list_head *chans)
        return -1;
 }
 
-void chan_interrupt(struct list_head *chans, struct work_struct *task,
+void chan_interrupt(struct list_head *chans, struct delayed_work *task,
                    struct tty_struct *tty, int irq)
 {
        struct list_head *ele, *next;
index 8243869..9c2e7a7 100644 (file)
@@ -98,4 +98,4 @@ static int register_daemon(void)
        return 0;
 }
 
-__initcall(register_daemon);
+late_initcall(register_daemon);
index 426633e..83301e1 100644 (file)
@@ -31,9 +31,9 @@ static irqreturn_t line_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static void line_timer_cb(void *arg)
+static void line_timer_cb(struct work_struct *work)
 {
-       struct line *line = arg;
+       struct line *line = container_of(work, struct line, task.work);
 
        if(!line->throttled)
                chan_interrupt(&line->chan_list, &line->task, line->tty,
@@ -246,7 +246,7 @@ out_up:
        return ret;
 }
 
-void line_set_termios(struct tty_struct *tty, struct termios * old)
+void line_set_termios(struct tty_struct *tty, struct ktermios * old)
 {
        /* nothing */
 }
@@ -443,7 +443,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
                 * is registered.
                 */
                enable_chan(line);
-               INIT_WORK(&line->task, line_timer_cb, line);
+               INIT_DELAYED_WORK(&line->task, line_timer_cb);
 
                if(!line->sigio){
                        chan_enable_winch(&line->chan_list, tty);
index c090fbd..52ccb7b 100644 (file)
@@ -127,4 +127,4 @@ static int register_mcast(void)
        return 0;
 }
 
-__initcall(register_mcast);
+late_initcall(register_mcast);
index 7b17216..96f0189 100644 (file)
@@ -56,7 +56,7 @@ static struct notifier_block reboot_notifier = {
 
 static LIST_HEAD(mc_requests);
 
-static void mc_work_proc(void *unused)
+static void mc_work_proc(struct work_struct *unused)
 {
        struct mconsole_entry *req;
        unsigned long flags;
@@ -72,7 +72,7 @@ static void mc_work_proc(void *unused)
        }
 }
 
-static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
+static DECLARE_WORK(mconsole_work, mc_work_proc);
 
 static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
 {
index ec9eb8b..286bc0b 100644 (file)
@@ -99,6 +99,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
                 * same device, since it tests for (dev->flags & IFF_UP). So
                 * there's no harm in delaying the device shutdown. */
                schedule_work(&close_work);
+#error this is not permitted - close_work will go out of scope
                goto out;
        }
        reactivate_fd(lp->fd, UM_ETH_IRQ);
index 6e1ef85..e67362a 100644 (file)
@@ -109,4 +109,4 @@ static int register_pcap(void)
        return 0;
 }
 
-__initcall(register_pcap);
+late_initcall(register_pcap);
index ce9f373..6dfe632 100644 (file)
@@ -132,7 +132,7 @@ static int port_accept(struct port_list *port)
 DECLARE_MUTEX(ports_sem);
 struct list_head ports = LIST_HEAD_INIT(ports);
 
-void port_work_proc(void *unused)
+void port_work_proc(struct work_struct *unused)
 {
        struct port_list *port;
        struct list_head *ele;
@@ -150,7 +150,7 @@ void port_work_proc(void *unused)
        local_irq_restore(flags);
 }
 
-DECLARE_WORK(port_work, port_work_proc, NULL);
+DECLARE_WORK(port_work, port_work_proc);
 
 static irqreturn_t port_interrupt(int irq, void *data)
 {
index 788da54..25634bd 100644 (file)
@@ -95,4 +95,4 @@ static int register_slip(void)
        return 0;
 }
 
-__initcall(register_slip);
+late_initcall(register_slip);
index ae322e1..b3ed8fb 100644 (file)
@@ -119,4 +119,4 @@ static int register_slirp(void)
        return 0;
 }
 
-__initcall(register_slirp);
+late_initcall(register_slirp);
index 572d286..9003a34 100644 (file)
@@ -27,7 +27,7 @@ struct chan {
        void *data;
 };
 
-extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
+extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
                           struct tty_struct *tty, int irq);
 extern int parse_chan_pair(char *str, struct line *line, int device,
                           const struct chan_opts *opts);
index 7be2481..5f232ae 100644 (file)
@@ -51,7 +51,7 @@ struct line {
        char *tail;
 
        int sigio;
-       struct work_struct task;
+       struct delayed_work task;
        const struct line_driver *driver;
        int have_irq;
 };
@@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines,
 extern int line_write(struct tty_struct *tty, const unsigned char *buf,
                      int len);
 extern void line_put_char(struct tty_struct *tty, unsigned char ch);
-extern void line_set_termios(struct tty_struct *tty, struct termios * old);
+extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
 extern int line_chars_in_buffer(struct tty_struct *tty);
 extern void line_flush_buffer(struct tty_struct *tty);
 extern void line_flush_chars(struct tty_struct *tty);
index 6670cc9..52b398b 100644 (file)
@@ -75,7 +75,7 @@ union uml_pt_regs {
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
        struct skas_regs {
-               unsigned long regs[HOST_FRAME_SIZE];
+               unsigned long regs[MAX_REG_NR];
                unsigned long fp[HOST_FP_SIZE];
                unsigned long xfp[HOST_XFP_SIZE];
                 struct faultinfo faultinfo;
index b492b12..4fffae7 100644 (file)
@@ -9,6 +9,7 @@
 #include <sys/mman.h>
 #include <asm/ptrace.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 #include "stub-data.h"
 #include "kern_constants.h"
 #include "uml-config.h"
index 617bb9e..66cb400 100644 (file)
@@ -108,7 +108,7 @@ union uml_pt_regs {
                 * 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 regs[MAX_REG_NR];
                unsigned long fp[HOST_FP_SIZE];
                 struct faultinfo faultinfo;
                long syscall;
index 0561c43..8d56ec6 100644 (file)
@@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv,
                    char __user *__user *env)
 {
         long error;
+       struct tty_struct *tty;
 
 #ifdef CONFIG_TTY_LOG
        mutex_lock(&tty_mutex);
-       task_lock(current);     /* FIXME:  is this needed ? */
-       log_exec(argv, current->signal->tty);
-       task_unlock(current);
+       tty = get_current_tty();
+       if (tty)
+               log_exec(argv, tty);
        mutex_unlock(&tty_mutex);
 #endif
         error = do_execve(file, argv, env, &current->thread.regs);
index 16385e2..7054182 100644 (file)
@@ -105,4 +105,4 @@ static int register_ethertap(void)
        return 0;
 }
 
-__initcall(register_ethertap);
+late_initcall(register_ethertap);
index 0edbac6..76570a2 100644 (file)
@@ -90,4 +90,4 @@ static int register_tuntap(void)
        return 0;
 }
 
-__initcall(register_tuntap);
+late_initcall(register_tuntap);
index 0e32adf..098720b 100644 (file)
@@ -1,4 +1,4 @@
-obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
+obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
        ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
        sys_call_table.o tls.o
 
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
new file mode 100644 (file)
index 0000000..200c8ba
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevent in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+       unsigned short ud2;
+
+       if (probe_kernel_address((unsigned short __user *)eip, ud2))
+               return 0;
+
+       return ud2 == 0x0b0f;
+}
index e299ee5..49057d8 100644 (file)
@@ -3,7 +3,6 @@
  * Licensed under the GPL
  */
 
-#include "linux/stddef.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/types.h"
index 5f3cc66..01212c8 100644 (file)
@@ -4,9 +4,9 @@
  */
 
 #include <stdio.h>
+#include <stddef.h>
 #include <errno.h>
 #include <unistd.h>
-#include <linux/stddef.h>
 #include "ptrace_user.h"
 /* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */
 #include <asm/user.h>
index 6f4ef2b..447306b 100644 (file)
@@ -2,7 +2,7 @@
 #include <signal.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
-#include <linux/stddef.h>
+#include <stddef.h>
 #include <sys/poll.h>
 
 #define DEFINE(sym, val) \
index f41768b..4d9e5ef 100644 (file)
@@ -4,7 +4,7 @@
 # Licensed under the GPL
 #
 
-obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
        setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
        ksyms.o tls.o
 
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
new file mode 100644 (file)
index 0000000..200c8ba
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevent in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+       unsigned short ud2;
+
+       if (probe_kernel_address((unsigned short __user *)eip, ud2))
+               return 0;
+
+       return ud2 == 0x0b0f;
+}
index 37ec644..bcf8258 100644 (file)
@@ -38,6 +38,14 @@ config TIME_LOW_RES
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 # Turn off some random 386 crap that can affect device config
 config ISA
        bool
index 88d087f..3a5fd07 100644 (file)
@@ -90,6 +90,7 @@
 
 /* Kernel text segment, and some constant data areas.  */
 #define TEXT_CONTENTS                                                        \
+               _text = .;                                                    \
                __stext = . ;                                                 \
                *(.text)                                                      \
                SCHED_TEXT                                                    \
index 010d226..d427553 100644 (file)
@@ -96,6 +96,19 @@ config AUDIT_ARCH
        bool
        default y
 
+config GENERIC_BUG
+       bool
+       default y
+       depends on BUG
+
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 source "init/Kconfig"
 
 
@@ -122,7 +135,7 @@ endchoice
 
 choice
        prompt "Processor family"
-       default MK8
+       default GENERIC_CPU
 
 config MK8
        bool "AMD-Opteron/Athlon64"
@@ -130,16 +143,31 @@ config MK8
          Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
 
 config MPSC
-       bool "Intel EM64T"
+       bool "Intel P4 / older Netburst based Xeon"
        help
-         Optimize for Intel Pentium 4 and Xeon CPUs with Intel
-         Extended Memory 64 Technology(EM64T). For details see
+         Optimize for Intel Pentium 4 and older Nocona/Dempsey Xeon CPUs
+         with Intel Extended Memory 64 Technology(EM64T). For details see
          <http://www.intel.com/technology/64bitextensions/>.
+         Note the the latest Xeons (Xeon 51xx and 53xx) are not based on the
+          Netburst core and shouldn't use this option. You can distingush them
+         using the cpu family field
+         in /proc/cpuinfo. Family 15 is a older Xeon, Family 6 a newer one
+         (this rule only applies to system that support EM64T)
+
+config MCORE2
+       bool "Intel Core2 / newer Xeon"
+       help
+         Optimize for Intel Core2 and newer Xeons (51xx)
+         You can distingush the newer Xeons from the older ones using
+         the cpu family field in /proc/cpuinfo. 15 is a older Xeon
+         (use CONFIG_MPSC then), 6 is a newer one. This rule only
+         applies to CPUs that support EM64T.
 
 config GENERIC_CPU
        bool "Generic-x86-64"
        help
          Generic x86-64 CPU.
+         Run equally well on all x86-64 CPUs.
 
 endchoice
 
@@ -149,12 +177,12 @@ endchoice
 config X86_L1_CACHE_BYTES
        int
        default "128" if GENERIC_CPU || MPSC
-       default "64" if MK8
+       default "64" if MK8 || MCORE2
 
 config X86_L1_CACHE_SHIFT
        int
        default "7" if GENERIC_CPU || MPSC
-       default "6" if MK8
+       default "6" if MK8 || MCORE2
 
 config X86_INTERNODE_CACHE_BYTES
        int
@@ -344,11 +372,6 @@ config ARCH_DISCONTIGMEM_ENABLE
        depends on NUMA
        default y
 
-
-config ARCH_DISCONTIGMEM_ENABLE
-       def_bool y
-       depends on NUMA
-
 config ARCH_DISCONTIGMEM_DEFAULT
        def_bool y
        depends on NUMA
@@ -455,6 +478,17 @@ config CALGARY_IOMMU
          Normally the kernel will make the right choice by itself.
          If unsure, say Y.
 
+config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+       bool "Should Calgary be enabled by default?"
+       default y
+       depends on CALGARY_IOMMU
+       help
+         Should Calgary be enabled by default? if you choose 'y', Calgary
+         will be used (if it exists). If you choose 'n', Calgary will not be
+         used even if it exists. If you choose 'n' and would like to use
+         Calgary anyway, pass 'iommu=calgary' on the kernel command line.
+         If unsure, say Y.
+
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
        bool
@@ -550,7 +584,7 @@ config SECCOMP
          If unsure, say Y. Only embedded should say N here.
 
 config CC_STACKPROTECTOR
-       bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)"
+       bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        help
          This option turns on the -fstack-protector GCC feature. This
index 6e38d4d..b471b85 100644 (file)
@@ -30,6 +30,10 @@ cflags-y     :=
 cflags-kernel-y        :=
 cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
 cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
+# gcc doesn't support -march=core2 yet as of gcc 4.3, but I hope it
+# will eventually. Use -mtune=generic as fallback
+cflags-$(CONFIG_MCORE2) += \
+       $(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
 cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
 
 cflags-y += -m64
index 0f5d44e..1a1c6a1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2-git4
-# Sat Oct 21 03:38:52 2006
+# Linux kernel version: 2.6.19-git14
+# Sat Dec  9 21:23:09 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -22,6 +22,9 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_DMI=y
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -47,13 +50,14 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -87,9 +91,7 @@ CONFIG_STOP_MACHINE=y
 # Block layer
 #
 CONFIG_BLOCK=y
-CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -111,10 +113,11 @@ CONFIG_X86_PC=y
 # CONFIG_X86_VSMP is not set
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
-CONFIG_GENERIC_CPU=y
-CONFIG_X86_L1_CACHE_BYTES=128
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_MCORE2=y
+# CONFIG_GENERIC_CPU is not set
+CONFIG_X86_L1_CACHE_BYTES=64
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTERNODE_CACHE_BYTES=64
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 # CONFIG_MICROCODE is not set
@@ -170,6 +173,7 @@ CONFIG_SECCOMP=y
 # CONFIG_CC_STACKPROTECTOR is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_REORDER is not set
@@ -322,6 +326,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
@@ -513,6 +518,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -533,6 +539,7 @@ CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -586,6 +593,7 @@ CONFIG_MEGARAID_SAS=y
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -624,6 +632,7 @@ CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -795,6 +804,7 @@ CONFIG_BNX2=y
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -927,10 +937,6 @@ CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
 CONFIG_AGP_INTEL=y
@@ -1107,10 +1113,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
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_TRIDENT is not set
@@ -1119,6 +1122,11 @@ CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+
 #
 # USB support
 #
@@ -1135,6 +1143,7 @@ CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1182,8 +1191,7 @@ CONFIG_USB_STORAGE=y
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_USB_HID_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
@@ -1212,6 +1220,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1473,6 +1482,11 @@ CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Instrumentation Support
 #
@@ -1503,6 +1517,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
@@ -1533,6 +1548,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
index 396d3c1..be87df5 100644 (file)
@@ -272,7 +272,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
             N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
            N_TRSIZE(ex) || N_DRSIZE(ex) ||
-           i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+           i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
                return -ENOEXEC;
        }
 
@@ -357,7 +357,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                {
                        printk(KERN_WARNING 
                               "fd_offset is not page aligned. Please convert program: %s\n",
-                              bprm->file->f_dentry->d_name.name);
+                              bprm->file->f_path.dentry->d_name.name);
                        error_time = jiffies;
                }
 #endif
@@ -440,7 +440,7 @@ static int load_aout_library(struct file *file)
        int retval;
        struct exec ex;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        retval = -ENOEXEC;
        error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
@@ -471,7 +471,7 @@ static int load_aout_library(struct file *file)
                {
                        printk(KERN_WARNING 
                               "N_TXTOFF is not page aligned. Please convert library: %s\n",
-                              file->f_dentry->d_name.name);
+                              file->f_path.dentry->d_name.name);
                        error_time = jiffies;
                }
 #endif
index 82ef182..543ef4f 100644 (file)
@@ -305,8 +305,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
 #undef MODULE_DESCRIPTION
 #undef MODULE_AUTHOR
 
-#define elf_addr_t __u32
-
 static void elf32_init(struct pt_regs *);
 
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
@@ -351,7 +349,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
                bprm->loader += stack_base;
        bprm->exec += stack_base;
 
-       mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!mpnt) 
                return -ENOMEM; 
 
index 0e0a266..ff499ef 100644 (file)
@@ -584,6 +584,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->rdx = (unsigned long) &frame->info;
        regs->rcx = (unsigned long) &frame->uc;
 
+       /* Make -mregparm=3 work */
+       regs->rax = sig;
+       regs->rdx = (unsigned long) &frame->info;
+       regs->rcx = (unsigned long) &frame->uc;
+
        asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
        asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
        
index 3a01329..3e5ed20 100644 (file)
@@ -49,7 +49,7 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
        struct mm_struct *mm = current->mm;
        int ret;
 
-       vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!vma)
                return -ENOMEM;
 
index 4d9d5ed..124b2d2 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>
@@ -45,6 +46,12 @@ int apic_calibrate_pmtmr __initdata;
 
 int disable_apic_timer __initdata;
 
+static struct resource *ioapic_resources;
+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
@@ -133,7 +140,6 @@ void clear_local_APIC(void)
                apic_write(APIC_LVTERR, APIC_LVT_MASKED);
        if (maxlvt >= 4)
                apic_write(APIC_LVTPC, APIC_LVT_MASKED);
-       v = GET_APIC_VERSION(apic_read(APIC_LVR));
        apic_write(APIC_ESR, 0);
        apic_read(APIC_ESR);
 }
@@ -452,23 +458,30 @@ static struct {
 static int lapic_suspend(struct sys_device *dev, pm_message_t state)
 {
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        apic_pm_state.apic_id = apic_read(APIC_ID);
        apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
        apic_pm_state.apic_ldr = apic_read(APIC_LDR);
        apic_pm_state.apic_dfr = apic_read(APIC_DFR);
        apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
        apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
-       apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+       if (maxlvt >= 4)
+               apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
        apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
        apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
        apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
        apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
        apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-       apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#ifdef CONFIG_X86_MCE_INTEL
+       if (maxlvt >= 5)
+               apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#endif
        local_irq_save(flags);
        disable_local_APIC();
        local_irq_restore(flags);
@@ -479,10 +492,13 @@ static int lapic_resume(struct sys_device *dev)
 {
        unsigned int l, h;
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        local_irq_save(flags);
        rdmsr(MSR_IA32_APICBASE, l, h);
        l &= ~MSR_IA32_APICBASE_BASE;
@@ -496,8 +512,12 @@ static int lapic_resume(struct sys_device *dev)
        apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
        apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
        apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
-       apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
-       apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+#ifdef CONFIG_X86_MCE_INTEL
+       if (maxlvt >= 5)
+               apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
+#endif
+       if (maxlvt >= 4)
+               apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
        apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
        apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
        apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
@@ -585,6 +605,64 @@ 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;
+
+       mem = alloc_bootmem(n);
+       res = (void *)mem;
+
+       if (mem != NULL) {
+               memset(mem, 0, n);
+               mem += sizeof(struct resource) * nr_ioapics;
+
+               for (i = 0; i < nr_ioapics; i++) {
+                       res[i].name = mem;
+                       res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+                       sprintf(mem,  "IOAPIC %u", i);
+                       mem += IOAPIC_RESOURCE_NAME_SIZE;
+               }
+       }
+
+       ioapic_resources = res;
+
+       return res;
+}
+
+static int __init ioapic_insert_resources(void)
+{
+       int i;
+       struct resource *r = ioapic_resources;
+
+       if (!r) {
+               printk("IO APIC resources could be not be allocated.\n");
+               return -1;
+       }
+
+       for (i = 0; i < nr_ioapics; i++) {
+               insert_resource(&iomem_resource, r);
+               r++;
+       }
+
+       return 0;
+}
+
+/* Insert the IO APIC resources after PCI initialization has occured to handle
+ * IO APICS that are mapped in on a BAR in PCI space. */
+late_initcall(ioapic_insert_resources);
+#endif
+
 void __init init_apic_mappings(void)
 {
        unsigned long apic_phys;
@@ -604,6 +682,11 @@ void __init init_apic_mappings(void)
        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).
@@ -613,7 +696,9 @@ void __init init_apic_mappings(void)
        {
                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;
@@ -625,6 +710,12 @@ 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 != NULL) {
+                               ioapic_res->start = ioapic_phys;
+                               ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+                               ioapic_res++;
+                       }
                }
        }
 }
@@ -644,10 +735,9 @@ void __init init_apic_mappings(void)
 
 static void __setup_APIC_LVTT(unsigned int clocks)
 {
-       unsigned int lvtt_value, tmp_value, ver;
+       unsigned int lvtt_value, tmp_value;
        int cpu = smp_processor_id();
 
-       ver = GET_APIC_VERSION(apic_read(APIC_LVR));
        lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
 
        if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask))
index 3525f88..95a7a2c 100644 (file)
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type,
-                                               void *data, size_t data_len)
-{
-       struct elf_note note;
-
-       note.n_namesz = strlen(name) + 1;
-       note.n_descsz = data_len;
-       note.n_type   = type;
-       memcpy(buf, &note, sizeof(note));
-       buf += (sizeof(note) +3)/4;
-       memcpy(buf, name, note.n_namesz);
-       buf += (note.n_namesz + 3)/4;
-       memcpy(buf, data, note.n_descsz);
-       buf += (note.n_descsz + 3)/4;
-
-       return buf;
-}
-
-static void final_note(u32 *buf)
-{
-       struct elf_note note;
-
-       note.n_namesz = 0;
-       note.n_descsz = 0;
-       note.n_type   = 0;
-       memcpy(buf, &note, sizeof(note));
-}
-
-static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
-{
-       struct elf_prstatus prstatus;
-       u32 *buf;
-
-       if ((cpu < 0) || (cpu >= NR_CPUS))
-               return;
-
-       /* Using ELF notes here is opportunistic.
-        * I need a well defined structure format
-        * 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, no need to invent something new.
-        */
-
-       buf = (u32*)per_cpu_ptr(crash_notes, cpu);
-
-       if (!buf)
-               return;
-
-       memset(&prstatus, 0, sizeof(prstatus));
-       prstatus.pr_pid = current->pid;
-       elf_core_copy_regs(&prstatus.pr_reg, regs);
-       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
-                                       sizeof(prstatus));
-       final_note(buf);
-}
-
-static void crash_save_self(struct pt_regs *regs)
-{
-       int cpu;
-
-       cpu = smp_processor_id();
-       crash_save_this_cpu(regs, cpu);
-}
-
 #ifdef CONFIG_SMP
 static atomic_t waiting_for_crash_ipi;
 
@@ -117,7 +52,7 @@ static int crash_nmi_callback(struct notifier_block *self,
                return NOTIFY_STOP;
        local_irq_disable();
 
-       crash_save_this_cpu(regs, cpu);
+       crash_save_cpu(regs, cpu);
        disable_local_APIC();
        atomic_dec(&waiting_for_crash_ipi);
        /* Assume hlt works */
@@ -196,5 +131,5 @@ void machine_crash_shutdown(struct pt_regs *regs)
 
        disable_IO_APIC();
 
-       crash_save_self(regs);
+       crash_save_cpu(regs, smp_processor_id());
 }
index 68273bf..829698f 100644 (file)
@@ -69,11 +69,18 @@ static void nvidia_bugs(void)
 
 static void ati_bugs(void)
 {
-       if (timer_over_8254 == 1) {
-               timer_over_8254 = 0;
-               printk(KERN_INFO
-               "ATI board detected. Disabling timer routing over 8254.\n");
-       }
+}
+
+static void intel_bugs(void)
+{
+       u16 device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
+
+#ifdef CONFIG_SMP
+       if (device == PCI_DEVICE_ID_INTEL_E7320_MCH ||
+           device == PCI_DEVICE_ID_INTEL_E7520_MCH ||
+           device == PCI_DEVICE_ID_INTEL_E7525_MCH)
+               quirk_intel_irqbalance();
+#endif
 }
 
 struct chipset {
@@ -85,6 +92,7 @@ static struct chipset early_qrk[] = {
        { PCI_VENDOR_ID_NVIDIA, nvidia_bugs },
        { PCI_VENDOR_ID_VIA, via_bugs },
        { PCI_VENDOR_ID_ATI, ati_bugs },
+       { PCI_VENDOR_ID_INTEL, intel_bugs},
        {}
 };
 
index 7d401b0..601d332 100644 (file)
@@ -230,7 +230,6 @@ ENTRY(system_call)
        CFI_REL_OFFSET rip,RIP-ARGOFFSET
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
-       CFI_REMEMBER_STATE
        jnz tracesys
        cmpq $__NR_syscall_max,%rax
        ja badsys
@@ -241,7 +240,6 @@ ENTRY(system_call)
  * Syscall return path ending with SYSRET (fast path)
  * Has incomplete stack frame and undefined top of stack. 
  */            
-       .globl ret_from_sys_call
 ret_from_sys_call:
        movl $_TIF_ALLWORK_MASK,%edi
        /* edi: flagmask */
@@ -251,8 +249,8 @@ sysret_check:
        TRACE_IRQS_OFF
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
-       CFI_REMEMBER_STATE
        jnz  sysret_careful 
+       CFI_REMEMBER_STATE
        /*
         * sysretq will re-enable interrupts:
         */
@@ -265,10 +263,10 @@ sysret_check:
        swapgs
        sysretq
 
+       CFI_RESTORE_STATE
        /* Handle reschedules */
        /* edx: work, edi: workmask */  
 sysret_careful:
-       CFI_RESTORE_STATE
        bt $TIF_NEED_RESCHED,%edx
        jnc sysret_signal
        TRACE_IRQS_ON
@@ -306,7 +304,6 @@ badsys:
 
        /* Do syscall tracing */
 tracesys:                       
-       CFI_RESTORE_STATE
        SAVE_REST
        movq $-ENOSYS,RAX(%rsp)
        FIXUP_TOP_OF_STACK %rdi
@@ -322,32 +319,13 @@ tracesys:
        call *sys_call_table(,%rax,8)
 1:     movq %rax,RAX-ARGOFFSET(%rsp)
        /* Use IRET because user could have changed frame */
-       jmp int_ret_from_sys_call
-       CFI_ENDPROC
-END(system_call)
                
 /* 
  * Syscall return path ending with IRET.
  * Has correct top of stack, but partial stack frame.
- */    
-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
-       /*CFI_REL_OFFSET        rflags,EFLAGS-ARGOFFSET*/
-       /*CFI_REL_OFFSET        cs,CS-ARGOFFSET*/
-       CFI_REL_OFFSET  rip,RIP-ARGOFFSET
-       CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
-       CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
-       CFI_REL_OFFSET  rax,RAX-ARGOFFSET
-       CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
-       CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
-       CFI_REL_OFFSET  r8,R8-ARGOFFSET
-       CFI_REL_OFFSET  r9,R9-ARGOFFSET
-       CFI_REL_OFFSET  r10,R10-ARGOFFSET
-       CFI_REL_OFFSET  r11,R11-ARGOFFSET
+ */
+       .globl int_ret_from_sys_call
+int_ret_from_sys_call:
        cli
        TRACE_IRQS_OFF
        testl $3,CS-ARGOFFSET(%rsp)
@@ -394,8 +372,6 @@ int_very_careful:
        popq %rdi
        CFI_ADJUST_CFA_OFFSET -8
        andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
-       cli
-       TRACE_IRQS_OFF
        jmp int_restore_rest
        
 int_signal:
@@ -411,7 +387,7 @@ int_restore_rest:
        TRACE_IRQS_OFF
        jmp int_with_check
        CFI_ENDPROC
-END(int_ret_from_sys_call)
+END(system_call)
                
 /* 
  * Certain special system calls that need to save a complete full stack frame.
index 8e78a75..b007433 100644 (file)
@@ -33,7 +33,7 @@ extern struct genapic apic_flat;
 extern struct genapic apic_physflat;
 
 struct genapic *genapic = &apic_flat;
-
+struct genapic *genapic_force;
 
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
@@ -46,6 +46,13 @@ void __init clustered_apic_check(void)
        u8 cluster_cnt[NUM_APIC_CLUSTERS];
        int max_apic = 0;
 
+       /* genapic selection can be forced because of certain quirks.
+        */
+       if (genapic_force) {
+               genapic = genapic_force;
+               goto print;
+       }
+
 #if defined(CONFIG_ACPI)
        /*
         * Some x86_64 machines use physical APIC mode regardless of how many
index 9561eb3..cc230b9 100644 (file)
@@ -57,10 +57,12 @@ void __init x86_64_start_kernel(char * real_mode_data)
 {
        int i;
 
-       for (i = 0; i < 256; i++)
+       /* clear bss before set_intr_gate with early_idt_handler */
+       clear_bss();
+
+       for (i = 0; i < IDT_ENTRIES; i++)
                set_intr_gate(i, early_idt_handler);
        asm volatile("lidt %0" :: "m" (idt_descr));
-       clear_bss();
 
        early_printk("Kernel alive\n");
 
index 3aa1e9b..1d58c13 100644 (file)
@@ -82,11 +82,8 @@ int save_i387(struct _fpstate __user *buf)
        struct task_struct *tsk = current;
        int err = 0;
 
-       { 
-               extern void bad_user_i387_struct(void); 
-               if (sizeof(struct user_i387_struct) != sizeof(tsk->thread.i387.fxsave))
-                       bad_user_i387_struct();
-       } 
+       BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
+                       sizeof(tsk->thread.i387.fxsave));
 
        if ((unsigned long)buf % 16) 
                printk("save_i387: bad fpstate %p\n",buf); 
index c4ef801..d73c79e 100644 (file)
@@ -76,7 +76,8 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xe) BUILD_16_IRQS(0xf)
        IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
        IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
 
-void (*interrupt[NR_IRQS])(void) = {
+/* for the irq vectors */
+static void (*interrupt[NR_VECTORS - FIRST_EXTERNAL_VECTOR])(void) = {
                                          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),
index c80081a..2a1dcd5 100644 (file)
@@ -55,10 +55,6 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
 
 static int no_timer_check;
 
-static int disable_timer_pin_1 __initdata;
-
-int timer_over_8254 __initdata = 1;
-
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
@@ -178,14 +174,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
  * the interrupt, and we need to make sure the entry is fully populated
  * before that happens.
  */
-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+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, 0x11 + 2*pin, eu.w2);
        io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       __ioapic_write_entry(apic, pin, e);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -348,29 +350,6 @@ static int __init disable_ioapic_setup(char *str)
 }
 early_param("noapic", disable_ioapic_setup);
 
-/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
-static int __init disable_timer_pin_setup(char *arg)
-{
-       disable_timer_pin_1 = 1;
-       return 1;
-}
-__setup("disable_timer_pin_1", disable_timer_pin_setup);
-
-static int __init setup_disable_8254_timer(char *s)
-{
-       timer_over_8254 = -1;
-       return 1;
-}
-static int __init setup_enable_8254_timer(char *s)
-{
-       timer_over_8254 = 2;
-       return 1;
-}
-
-__setup("disable_8254_timer", setup_disable_8254_timer);
-__setup("enable_8254_timer", setup_enable_8254_timer);
-
-
 /*
  * Find the IRQ entry number of a certain pin.
  */
@@ -750,6 +729,22 @@ static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
        return vector;
 }
 
+static void __clear_irq_vector(int irq)
+{
+       cpumask_t mask;
+       int cpu, vector;
+
+       BUG_ON(!irq_vector[irq]);
+
+       vector = irq_vector[irq];
+       cpus_and(mask, irq_domain[irq], cpu_online_map);
+       for_each_cpu_mask(cpu, mask)
+               per_cpu(vector_irq, cpu)[vector] = -1;
+
+       irq_vector[irq] = 0;
+       irq_domain[irq] = CPU_MASK_NONE;
+}
+
 void __setup_vector_irq(int cpu)
 {
        /* Initialize vector_irq on a new cpu */
@@ -794,27 +789,65 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
                                              handle_edge_irq, "edge");
        }
 }
-
-static void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
 {
        struct IO_APIC_route_entry entry;
-       int apic, pin, idx, irq, first_notcon = 1, vector;
+       int vector;
        unsigned long flags;
 
-       apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-       for (apic = 0; apic < nr_ioapics; apic++) {
-       for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+       /*
+        * add it to the IO-APIC irq-routing table:
+        */
+       memset(&entry,0,sizeof(entry));
 
-               /*
-                * add it to the IO-APIC irq-routing table:
-                */
-               memset(&entry,0,sizeof(entry));
+       entry.delivery_mode = INT_DELIVERY_MODE;
+       entry.dest_mode = INT_DEST_MODE;
+       entry.mask = 0;                         /* enable IRQ */
+       entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+
+       entry.trigger = irq_trigger(idx);
+       entry.polarity = irq_polarity(idx);
 
-               entry.delivery_mode = INT_DELIVERY_MODE;
-               entry.dest_mode = INT_DEST_MODE;
-               entry.mask = 0;                         /* enable IRQ */
+       if (irq_trigger(idx)) {
+               entry.trigger = 1;
+               entry.mask = 1;
                entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+       }
+
+       if (!apic && !IO_APIC_IRQ(irq))
+               return;
+
+       if (IO_APIC_IRQ(irq)) {
+               cpumask_t mask;
+               vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
+               if (vector < 0)
+                       return;
+
+               entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+               entry.vector = vector;
+
+               ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+               if (!apic && (irq < 16))
+                       disable_8259A_irq(irq);
+       }
+
+       ioapic_write_entry(apic, pin, entry);
+
+       spin_lock_irqsave(&ioapic_lock, flags);
+       set_native_irq_info(irq, TARGET_CPUS);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+
+}
+
+static void __init setup_IO_APIC_irqs(void)
+{
+       int apic, pin, idx, irq, first_notcon = 1;
+
+       apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+       for (apic = 0; apic < nr_ioapics; apic++) {
+       for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
 
                idx = find_irq_entry(apic,pin,mp_INT);
                if (idx == -1) {
@@ -826,39 +859,11 @@ static void __init setup_IO_APIC_irqs(void)
                        continue;
                }
 
-               entry.trigger = irq_trigger(idx);
-               entry.polarity = irq_polarity(idx);
-
-               if (irq_trigger(idx)) {
-                       entry.trigger = 1;
-                       entry.mask = 1;
-                       entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
-               }
-
                irq = pin_2_irq(idx, apic, pin);
                add_pin_to_irq(irq, apic, pin);
 
-               if (!apic && !IO_APIC_IRQ(irq))
-                       continue;
-
-               if (IO_APIC_IRQ(irq)) {
-                       cpumask_t mask;
-                       vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-                       if (vector < 0)
-                               continue;
-
-                       entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
-                       entry.vector = vector;
-
-                       ioapic_register_intr(irq, vector, IOAPIC_AUTO);
-                       if (!apic && (irq < 16))
-                               disable_8259A_irq(irq);
-               }
-               ioapic_write_entry(apic, pin, entry);
+               setup_IO_APIC_irq(apic, pin, idx, irq);
 
-               spin_lock_irqsave(&ioapic_lock, flags);
-               set_native_irq_info(irq, TARGET_CPUS);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
        }
        }
 
@@ -1563,10 +1568,33 @@ static inline void unlock_ExtINT_logic(void)
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  * fanatically on his truly buggy board.
- *
- * FIXME: really need to revamp this for modern platforms only.
  */
-static inline void check_timer(void)
+
+static int try_apic_pin(int apic, int pin, char *msg)
+{
+       apic_printk(APIC_VERBOSE, KERN_INFO
+                   "..TIMER: trying IO-APIC=%d PIN=%d %s",
+                   apic, pin, msg);
+
+       /*
+        * Ok, does IRQ0 through the IOAPIC work?
+        */
+       if (!no_timer_check && timer_irq_works()) {
+               nmi_watchdog_default();
+               if (nmi_watchdog == NMI_IO_APIC) {
+                       disable_8259A_irq(0);
+                       setup_nmi();
+                       enable_8259A_irq(0);
+               }
+               return 1;
+       }
+       clear_IO_APIC_pin(apic, pin);
+       apic_printk(APIC_QUIET, KERN_ERR " .. failed\n");
+       return 0;
+}
+
+/* The function from hell */
+static void check_timer(void)
 {
        int apic1, pin1, apic2, pin2;
        int vector;
@@ -1587,61 +1615,43 @@ static inline void check_timer(void)
         */
        apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
        init_8259A(1);
-       if (timer_over_8254 > 0)
-               enable_8259A_irq(0);
 
        pin1  = find_isa_irq_pin(0, mp_INT);
        apic1 = find_isa_irq_apic(0, mp_INT);
        pin2  = ioapic_i8259.pin;
        apic2 = ioapic_i8259.apic;
 
-       apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-               vector, apic1, pin1, apic2, pin2);
+       /* Do this first, otherwise we get double interrupts on ATI boards */
+       if ((pin1 != -1) && try_apic_pin(apic1, pin1,"with 8259 IRQ0 disabled"))
+               return;
 
-       if (pin1 != -1) {
-               /*
-                * Ok, does IRQ0 through the IOAPIC work?
-                */
-               unmask_IO_APIC_irq(0);
-               if (!no_timer_check && timer_irq_works()) {
-                       nmi_watchdog_default();
-                       if (nmi_watchdog == NMI_IO_APIC) {
-                               disable_8259A_irq(0);
-                               setup_nmi();
-                               enable_8259A_irq(0);
-                       }
-                       if (disable_timer_pin_1 > 0)
-                               clear_IO_APIC_pin(0, pin1);
-                       return;
-               }
-               clear_IO_APIC_pin(apic1, pin1);
-               apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
-                               "connected to IO-APIC\n");
-       }
+       /* Now try again with IRQ0 8259A enabled.
+          Assumes timer is on IO-APIC 0 ?!? */
+       enable_8259A_irq(0);
+       unmask_IO_APIC_irq(0);
+       if (try_apic_pin(apic1, pin1, "with 8259 IRQ0 enabled"))
+               return;
+       disable_8259A_irq(0);
+
+       /* Always try pin0 and pin2 on APIC 0 to handle buggy timer overrides
+          on Nvidia boards */
+       if (!(apic1 == 0 && pin1 == 0) &&
+           try_apic_pin(0, 0, "fallback with 8259 IRQ0 disabled"))
+               return;
+       if (!(apic1 == 0 && pin1 == 2) &&
+           try_apic_pin(0, 2, "fallback with 8259 IRQ0 disabled"))
+               return;
 
-       apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
-                               "through the 8259A ... ");
+       /* Then try pure 8259A routing on the 8259 as reported by BIOS*/
+       enable_8259A_irq(0);
        if (pin2 != -1) {
-               apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
-                       apic2, pin2);
-               /*
-                * legacy devices should be connected to IO APIC #0
-                */
                setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
-               if (timer_irq_works()) {
-                       apic_printk(APIC_VERBOSE," works.\n");
-                       nmi_watchdog_default();
-                       if (nmi_watchdog == NMI_IO_APIC) {
-                               setup_nmi();
-                       }
+               if (try_apic_pin(apic2,pin2,"8259A broadcast ExtINT from BIOS"))
                        return;
-               }
-               /*
-                * Cleanup, just in case ...
-                */
-               clear_IO_APIC_pin(apic2, pin2);
        }
-       apic_printk(APIC_VERBOSE," failed.\n");
+
+       /* Tried all possibilities to go through the IO-APIC. Now come the
+          really cheesy fallbacks. */
 
        if (nmi_watchdog == NMI_IO_APIC) {
                printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
@@ -1837,7 +1847,7 @@ void destroy_irq(unsigned int irq)
        dynamic_irq_cleanup(irq);
 
        spin_lock_irqsave(&vector_lock, flags);
-       irq_vector[irq] = 0;
+       __clear_irq_vector(irq);
        spin_unlock_irqrestore(&vector_lock, flags);
 }
 
@@ -2139,7 +2149,15 @@ void __init setup_ioapic_dest(void)
                        if (irq_entry == -1)
                                continue;
                        irq = pin_2_irq(irq_entry, ioapic, pin);
-                       set_ioapic_affinity_irq(irq, TARGET_CPUS);
+
+                       /* setup_IO_APIC_irqs could fail to get vector for some device
+                        * when you have too many devices, because at that time only boot
+                        * cpu is online.
+                        */
+                       if(!irq_vector[irq])
+                               setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
+                       else
+                               set_ioapic_affinity_irq(irq, TARGET_CPUS);
                }
 
        }
index e46c558..0c06af6 100644 (file)
@@ -120,7 +120,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
 
        if (likely(irq < NR_IRQS))
                generic_handle_irq(irq);
-       else
+       else if (printk_ratelimit())
                printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
                        __func__, smp_processor_id(), vector);
 
index ac24156..209c8c0 100644 (file)
@@ -224,7 +224,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, 0);
        mutex_unlock(&kprobe_mutex);
 }
 
index bbea888..ac08503 100644 (file)
@@ -306,8 +306,8 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status)
  */
 
 static int check_interval = 5 * 60; /* 5 minutes */
-static void mcheck_timer(void *data);
-static DECLARE_WORK(mcheck_work, mcheck_timer, NULL);
+static void mcheck_timer(struct work_struct *work);
+static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer);
 
 static void mcheck_check_cpu(void *info)
 {
@@ -315,7 +315,7 @@ static void mcheck_check_cpu(void *info)
                do_machine_check(NULL, 0);
 }
 
-static void mcheck_timer(void *data)
+static void mcheck_timer(struct work_struct *work)
 {
        on_each_cpu(mcheck_check_cpu, NULL, 1, 1);
        schedule_delayed_work(&mcheck_work, check_interval * HZ);
@@ -641,7 +641,6 @@ static __cpuinit int mce_create_device(unsigned int cpu)
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void mce_remove_device(unsigned int cpu)
 {
        int i;
@@ -652,6 +651,7 @@ static void mce_remove_device(unsigned int cpu)
        sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant);
        sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
        sysdev_unregister(&per_cpu(device_mce,cpu));
+       memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
 }
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
@@ -674,7 +674,6 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 static struct notifier_block mce_cpu_notifier = {
        .notifier_call = mce_cpu_callback,
 };
-#endif
 
 static __init int mce_init_device(void)
 {
index 883fe74..fa09deb 100644 (file)
@@ -551,7 +551,6 @@ out:
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 /*
  * let's be hotplug friendly.
  * in case of multiple core processors, the first core always takes ownership
@@ -594,12 +593,14 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 
        sprintf(name, "threshold_bank%i", bank);
 
+#ifdef CONFIG_SMP
        /* sibling symlink */
        if (shared_bank[bank] && b->blocks->cpu != cpu) {
                sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name);
                per_cpu(threshold_banks, cpu)[bank] = NULL;
                return;
        }
+#endif
 
        /* remove all sibling symlinks before unregistering */
        for_each_cpu_mask(i, b->cpus) {
@@ -656,7 +657,6 @@ static int threshold_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block threshold_cpu_notifier = {
        .notifier_call = threshold_cpu_callback,
 };
-#endif /* CONFIG_HOTPLUG_CPU */
 
 static __init int threshold_init_device(void)
 {
index 9d0958f..a888e67 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/bug.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
@@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr,
                                            lseg, lseg + locks->sh_size,
                                            tseg, tseg + text->sh_size);
        }
-       return 0;
+
+       return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
        alternatives_smp_module_del(mod);
+       module_bug_cleanup(mod);
 }
index b147ab1..0807256 100644 (file)
@@ -35,8 +35,6 @@
 int smp_found_config;
 unsigned int __initdata maxcpus = NR_CPUS;
 
-int acpi_found_madt;
-
 /*
  * Various Linux-internal data structures created from the
  * MP-table.
index 7af9cb3..186aebb 100644 (file)
  *  Mikael Pettersson  : PM converted to driver model. Disable/enable API.
  */
 
+#include <linux/nmi.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/sysdev.h>
-#include <linux/nmi.h>
 #include <linux/sysctl.h>
 #include <linux/kprobes.h>
+#include <linux/cpumask.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
@@ -41,6 +42,8 @@ int panic_on_unrecovered_nmi;
 static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner);
 static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[2]);
 
+static cpumask_t backtrace_mask = CPU_MASK_NONE;
+
 /* 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)
  */
@@ -190,6 +193,8 @@ void nmi_watchdog_default(void)
                nmi_watchdog = NMI_IO_APIC;
 }
 
+static int endflag __initdata = 0;
+
 #ifdef CONFIG_SMP
 /* The performance counters used by NMI_LOCAL_APIC don't trigger when
  * the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -197,7 +202,6 @@ void nmi_watchdog_default(void)
  */
 static __init void nmi_cpu_busy(void *data)
 {
-       volatile int *endflag = data;
        local_irq_enable_in_hardirq();
        /* Intentionally don't use cpu_relax here. This is
           to make sure that the performance counter really ticks,
@@ -205,14 +209,13 @@ static __init void nmi_cpu_busy(void *data)
           pause instruction. On a real HT machine this is fine because
           all other CPUs are busy with "useless" delay loops and don't
           care if they get somewhat less cycles. */
-       while (*endflag == 0)
-               barrier();
+       while (endflag == 0)
+               mb();
 }
 #endif
 
 int __init check_nmi_watchdog (void)
 {
-       volatile int endflag = 0;
        int *counts;
        int cpu;
 
@@ -253,6 +256,7 @@ int __init check_nmi_watchdog (void)
        if (!atomic_read(&nmi_active)) {
                kfree(counts);
                atomic_set(&nmi_active, -1);
+               endflag = 1;
                return -1;
        }
        endflag = 1;
@@ -782,6 +786,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
 {
        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;
@@ -799,6 +804,16 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
                touched = 1;
        }
 
+       if (cpu_isset(cpu, backtrace_mask)) {
+               static DEFINE_SPINLOCK(lock);   /* Serialise the printks */
+
+               spin_lock(&lock);
+               printk("NMI backtrace for cpu %d\n", cpu);
+               dump_stack();
+               spin_unlock(&lock);
+               cpu_clear(cpu, backtrace_mask);
+       }
+
 #ifdef CONFIG_X86_MCE
        /* Could check oops_in_progress here too, but it's safer
           not too */
@@ -931,6 +946,19 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
 
 #endif
 
+void __trigger_all_cpu_backtrace(void)
+{
+       int i;
+
+       backtrace_mask = cpu_online_map;
+       /* Wait for up to 10 seconds for all CPUs to do the backtrace */
+       for (i = 0; i < 10 * 1000; i++) {
+               if (cpus_empty(backtrace_mask))
+                       break;
+               mdelay(1);
+       }
+}
+
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
index 37a7708..3215675 100644 (file)
 #include <asm/pci-direct.h>
 #include <asm/system.h>
 #include <asm/dma.h>
+#include <asm/rio.h>
+
+#ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
+int use_calgary __read_mostly = 1;
+#else
+int use_calgary __read_mostly = 0;
+#endif /* CONFIG_CALGARY_DEFAULT_ENABLED */
 
 #define PCI_DEVICE_ID_IBM_CALGARY 0x02a1
 #define PCI_VENDOR_DEVICE_ID_CALGARY \
@@ -115,14 +122,35 @@ static const unsigned long phb_offsets[] = {
        0xB000 /* PHB3 */
 };
 
+/* PHB debug registers */
+
+static const unsigned long phb_debug_offsets[] = {
+       0x4000  /* PHB 0 DEBUG */,
+       0x5000  /* PHB 1 DEBUG */,
+       0x6000  /* PHB 2 DEBUG */,
+       0x7000  /* PHB 3 DEBUG */
+};
+
+/*
+ * STUFF register for each debug PHB,
+ * byte 1 = start bus number, byte 2 = end bus number
+ */
+
+#define PHB_DEBUG_STUFF_OFFSET 0x0020
+
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
 
+static struct rio_table_hdr    *rio_table_hdr __initdata;
+static struct scal_detail      *scal_devs[MAX_NUMNODES] __initdata;
+static struct rio_detail       *rio_devs[MAX_NUMNODES * 4] __initdata;
+
 struct calgary_bus_info {
        void *tce_space;
        unsigned char translation_disabled;
        signed char phbid;
+       void __iomem *bbar;
 };
 
 static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
@@ -475,6 +503,11 @@ static struct dma_mapping_ops calgary_dma_ops = {
        .unmap_sg = calgary_unmap_sg,
 };
 
+static inline void __iomem * busno_to_bbar(unsigned char num)
+{
+       return bus_info[num].bbar;
+}
+
 static inline int busno_to_phbid(unsigned char num)
 {
        return bus_info[num].phbid;
@@ -620,14 +653,9 @@ static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev)
 static void __init calgary_reserve_regions(struct pci_dev *dev)
 {
        unsigned int npages;
-       void __iomem *bbar;
-       unsigned char busnum;
        u64 start;
        struct iommu_table *tbl = dev->sysdata;
 
-       bbar = tbl->bbar;
-       busnum = dev->bus->number;
-
        /* reserve bad_dma_address in case it's a legal address */
        iommu_range_reserve(tbl, bad_dma_address, 1);
 
@@ -740,7 +768,7 @@ static void __init calgary_increase_split_completion_timeout(void __iomem *bbar,
 {
        u64 val64;
        void __iomem *target;
-       unsigned long phb_shift = -1;
+       unsigned int phb_shift = ~0; /* silence gcc */
        u64 mask;
 
        switch (busno_to_phbid(busnum)) {
@@ -828,33 +856,6 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
        del_timer_sync(&tbl->watchdog_timer);
 }
 
-static inline unsigned int __init locate_register_space(struct pci_dev *dev)
-{
-       int rionodeid;
-       u32 address;
-
-       /*
-        * Each Calgary has four busses. The first four busses (first Calgary)
-        * have RIO node ID 2, then the next four (second Calgary) have RIO
-        * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
-        * We use a gross hack - relying on the dev->bus->number ordering,
-        * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
-        * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
-        * second (id 3), and then it repeats modulo 14.
-        */
-       rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
-       /*
-        * register space address calculation as follows:
-        * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
-        * ChassisBase is always zero for x366/x260/x460
-        * RioNodeId is 2 for first Calgary, 3 for second Calgary
-        */
-       address = START_ADDRESS -
-               (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
-               (0x100000) * (rionodeid - CHASSIS_BASE);
-       return address;
-}
-
 static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
 {
        pci_dev_get(dev);
@@ -864,23 +865,15 @@ static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
 
 static int __init calgary_init_one(struct pci_dev *dev)
 {
-       u32 address;
        void __iomem *bbar;
        int ret;
 
        BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
 
-       address = locate_register_space(dev);
-       /* map entire 1MB of Calgary config space */
-       bbar = ioremap_nocache(address, 1024 * 1024);
-       if (!bbar) {
-               ret = -ENODATA;
-               goto done;
-       }
-
+       bbar = busno_to_bbar(dev->bus->number);
        ret = calgary_setup_tar(dev, bbar);
        if (ret)
-               goto iounmap;
+               goto done;
 
        pci_dev_get(dev);
        dev->bus->self = dev;
@@ -888,17 +881,66 @@ static int __init calgary_init_one(struct pci_dev *dev)
 
        return 0;
 
-iounmap:
-       iounmap(bbar);
 done:
        return ret;
 }
 
+static int __init calgary_locate_bbars(void)
+{
+       int ret;
+       int rioidx, phb, bus;
+       void __iomem *bbar;
+       void __iomem *target;
+       unsigned long offset;
+       u8 start_bus, end_bus;
+       u32 val;
+
+       ret = -ENODATA;
+       for (rioidx = 0; rioidx < rio_table_hdr->num_rio_dev; rioidx++) {
+               struct rio_detail *rio = rio_devs[rioidx];
+
+               if ((rio->type != COMPAT_CALGARY) && (rio->type != ALT_CALGARY))
+                       continue;
+
+               /* map entire 1MB of Calgary config space */
+               bbar = ioremap_nocache(rio->BBAR, 1024 * 1024);
+               if (!bbar)
+                       goto error;
+
+               for (phb = 0; phb < PHBS_PER_CALGARY; phb++) {
+                       offset = phb_debug_offsets[phb] | PHB_DEBUG_STUFF_OFFSET;
+                       target = calgary_reg(bbar, offset);
+
+                       val = be32_to_cpu(readl(target));
+                       start_bus = (u8)((val & 0x00FF0000) >> 16);
+                       end_bus = (u8)((val & 0x0000FF00) >> 8);
+                       for (bus = start_bus; bus <= end_bus; bus++) {
+                               bus_info[bus].bbar = bbar;
+                               bus_info[bus].phbid = phb;
+                       }
+               }
+       }
+
+       return 0;
+
+error:
+       /* scan bus_info and iounmap any bbars we previously ioremap'd */
+       for (bus = 0; bus < ARRAY_SIZE(bus_info); bus++)
+               if (bus_info[bus].bbar)
+                       iounmap(bus_info[bus].bbar);
+
+       return ret;
+}
+
 static int __init calgary_init(void)
 {
-       int ret = -ENODEV;
+       int ret;
        struct pci_dev *dev = NULL;
 
+       ret = calgary_locate_bbars();
+       if (ret)
+               return ret;
+
        do {
                dev = pci_get_device(PCI_VENDOR_ID_IBM,
                                     PCI_DEVICE_ID_IBM_CALGARY,
@@ -921,7 +963,7 @@ static int __init calgary_init(void)
 
 error:
        do {
-               dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
+               dev = pci_get_device_reverse(PCI_VENDOR_ID_IBM,
                                              PCI_DEVICE_ID_IBM_CALGARY,
                                              dev);
                if (!dev)
@@ -962,13 +1004,56 @@ static inline int __init determine_tce_table_size(u64 ram)
        return ret;
 }
 
+static int __init build_detail_arrays(void)
+{
+       unsigned long ptr;
+       int i, scal_detail_size, rio_detail_size;
+
+       if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
+               printk(KERN_WARNING
+                       "Calgary: MAX_NUMNODES too low! Defined as %d, "
+                       "but system has %d nodes.\n",
+                       MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+               return -ENODEV;
+       }
+
+       switch (rio_table_hdr->version){
+       case 2:
+               scal_detail_size = 11;
+               rio_detail_size = 13;
+               break;
+       case 3:
+               scal_detail_size = 12;
+               rio_detail_size = 15;
+               break;
+       default:
+               printk(KERN_WARNING
+                      "Calgary: Invalid Rio Grande Table Version: %d\n",
+                      rio_table_hdr->version);
+               return -EPROTO;
+       }
+
+       ptr = ((unsigned long)rio_table_hdr) + 3;
+       for (i = 0; i < rio_table_hdr->num_scal_dev;
+                   i++, ptr += scal_detail_size)
+               scal_devs[i] = (struct scal_detail *)ptr;
+
+       for (i = 0; i < rio_table_hdr->num_rio_dev;
+                   i++, ptr += rio_detail_size)
+               rio_devs[i] = (struct rio_detail *)ptr;
+
+       return 0;
+}
+
 void __init detect_calgary(void)
 {
        u32 val;
        int bus;
        void *tbl;
        int calgary_found = 0;
-       int phb = -1;
+       unsigned long ptr;
+       int offset;
+       int ret;
 
        /*
         * if the user specified iommu=off or iommu=soft or we found
@@ -977,25 +1062,47 @@ void __init detect_calgary(void)
        if (swiotlb || no_iommu || iommu_detected)
                return;
 
+       if (!use_calgary)
+               return;
+
        if (!early_pci_allowed())
                return;
 
+       ptr = (unsigned long)phys_to_virt(get_bios_ebda());
+
+       rio_table_hdr = NULL;
+       offset = 0x180;
+       while (offset) {
+               /* The block id is stored in the 2nd word */
+               if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
+                       /* set the pointer past the offset & block id */
+                       rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
+                       break;
+               }
+               /* The next offset is stored in the 1st word. 0 means no more */
+               offset = *((unsigned short *)(ptr + offset));
+       }
+       if (!rio_table_hdr) {
+               printk(KERN_ERR "Calgary: Unable to locate "
+                               "Rio Grande Table in EBDA - bailing!\n");
+               return;
+       }
+
+       ret = build_detail_arrays();
+       if (ret) {
+               printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret);
+               return;
+       }
+
        specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
 
        for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
                int dev;
                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;
 
-               /*
-                * There are 4 PHBs per Calgary chip.  Set phb to which phb (0-3)
-                * it is connected to releative to the clagary chip.
-                */
-               phb = (phb + 1) % PHBS_PER_CALGARY;
-
                if (info->translation_disabled)
                        continue;
 
@@ -1010,7 +1117,6 @@ void __init detect_calgary(void)
                                if (!tbl)
                                        goto cleanup;
                                info->tce_space = tbl;
-                               info->phbid = phb;
                                calgary_found = 1;
                                break;
                        }
index f8d8574..683b7a5 100644 (file)
@@ -296,6 +296,11 @@ __init int iommu_setup(char *p)
                gart_parse_options(p);
 #endif
 
+#ifdef CONFIG_CALGARY_IOMMU
+               if (!strncmp(p, "calgary", 7))
+                       use_calgary = 1;
+#endif /* CONFIG_CALGARY_IOMMU */
+
                p += strcspn(p, ",");
                if (*p == ',')
                        ++p;
index 16261a8..fc1960f 100644 (file)
@@ -601,10 +601,9 @@ void __init gart_iommu_init(void)
            (!force_iommu && end_pfn <= MAX_DMA32_PFN) ||
            !iommu_aperture ||
            (no_agp && init_k8_gatt(&info) < 0)) {
-               printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
                if (end_pfn > MAX_DMA32_PFN) {
                        printk(KERN_ERR "WARNING more than 4GB of memory "
-                                       "but IOMMU not available.\n"
+                                       "but GART IOMMU not available.\n"
                               KERN_ERR "WARNING 32bit PCI may malfunction.\n");
                }
                return;
index 7451a4c..a418ee4 100644 (file)
@@ -108,17 +108,15 @@ void exit_idle(void)
  */
 static void default_idle(void)
 {
-       local_irq_enable();
-
        current_thread_info()->status &= ~TS_POLLING;
        smp_mb__after_clear_bit();
-       while (!need_resched()) {
-               local_irq_disable();
-               if (!need_resched())
-                       safe_halt();
-               else
-                       local_irq_enable();
-       }
+       local_irq_disable();
+       if (!need_resched()) {
+               /* Enables interrupts one instruction before HLT.
+                  x86 special cases this so there is no race. */
+               safe_halt();
+       } else
+               local_irq_enable();
        current_thread_info()->status |= TS_POLLING;
 }
 
@@ -130,15 +128,7 @@ static void default_idle(void)
 static void poll_idle (void)
 {
        local_irq_enable();
-
-       asm volatile(
-               "2:"
-               "testl %0,%1;"
-               "rep; nop;"
-               "je 2b;"
-               : :
-               "i" (_TIF_NEED_RESCHED),
-               "m" (current_thread_info()->flags));
+       cpu_relax();
 }
 
 void cpu_idle_wait(void)
@@ -219,6 +209,12 @@ void cpu_idle (void)
                                idle = default_idle;
                        if (cpu_is_offline(smp_processor_id()))
                                play_dead();
+                       /*
+                        * Idle routines should keep interrupts disabled
+                        * from here on, until they go to idle.
+                        * Otherwise, idle callbacks can misfire.
+                        */
+                       local_irq_disable();
                        enter_idle();
                        idle();
                        /* In many cases the interrupt that ended idle
@@ -256,9 +252,16 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
 /* Default MONITOR/MWAIT with no hints, used for default C1 state */
 static void mwait_idle(void)
 {
-       local_irq_enable();
-       while (!need_resched())
-               mwait_idle_with_hints(0,0);
+       if (!need_resched()) {
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               smp_mb();
+               if (!need_resched())
+                       __sti_mwait(0, 0);
+               else
+                       local_irq_enable();
+       } else {
+               local_irq_enable();
+       }
 }
 
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
index fc944b5..af425a8 100644 (file)
@@ -471,8 +471,7 @@ void __init setup_arch(char **cmdline_p)
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
                        reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
-                       initrd_start =
-                               INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+                       initrd_start = INITRD_START + PAGE_OFFSET;
                        initrd_end = initrd_start+INITRD_SIZE;
                }
                else {
@@ -732,11 +731,8 @@ static void __cpuinit 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);
+       /* RDTSC can be speculated around */
+       clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
 }
 
 static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -835,6 +831,15 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
                        set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
        }
 
+       if (cpu_has_ds) {
+               unsigned int l1, l2;
+               rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+               if (!(l1 & (1<<11)))
+                       set_bit(X86_FEATURE_BTS, c->x86_capability);
+               if (!(l1 & (1<<12)))
+                       set_bit(X86_FEATURE_PEBS, c->x86_capability);
+       }
+
        n = c->extended_cpuid_level;
        if (n >= 0x80000008) {
                unsigned eax = cpuid_eax(0x80000008);
@@ -854,7 +859,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
                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);
+       if (c->x86 == 15)
+               set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+       else
+               clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
        c->x86_max_cores = intel_num_cpu_cores(c);
 
        srat_detect_node();
index 9f74c88..af1ec4d 100644 (file)
@@ -379,12 +379,17 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
                put_cpu();
                return 0;
        }
+
+       /* Can deadlock when called with interrupts disabled */
+       WARN_ON(irqs_disabled());
+
        spin_lock_bh(&call_lock);
        __smp_call_function_single(cpu, func, info, nonatomic, wait);
        spin_unlock_bh(&call_lock);
        put_cpu();
        return 0;
 }
+EXPORT_SYMBOL(smp_call_function_single);
 
 /*
  * this function sends a 'generic call function' IPI to all other CPUs
index 62c2e74..daf1933 100644 (file)
@@ -60,6 +60,7 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/numa.h>
+#include <asm/genapic.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -753,14 +754,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
 }
 
 struct create_idle {
+       struct work_struct work;
        struct task_struct *idle;
        struct completion done;
        int cpu;
 };
 
-void do_fork_idle(void *_c_idle)
+void do_fork_idle(struct work_struct *work)
 {
-       struct create_idle *c_idle = _c_idle;
+       struct create_idle *c_idle =
+               container_of(work, struct create_idle, work);
 
        c_idle->idle = fork_idle(c_idle->cpu);
        complete(&c_idle->done);
@@ -775,10 +778,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
        int timeout;
        unsigned long start_rip;
        struct create_idle c_idle = {
+               .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle),
                .cpu = cpu,
                .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
        };
-       DECLARE_WORK(work, do_fork_idle, &c_idle);
 
        /* allocate memory for gdts of secondary cpus. Hotplug is considered */
        if (!cpu_gdt_descr[cpu].address &&
@@ -825,9 +828,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
         * thread.
         */
        if (!keventd_up() || current_is_keventd())
-               work.func(work.data);
+               c_idle.work.func(&c_idle.work);
        else {
-               schedule_work(&work);
+               schedule_work(&c_idle.work);
                wait_for_completion(&c_idle.done);
        }
 
@@ -1167,6 +1170,13 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
+
+       if (num_online_cpus() > 8 && genapic == &apic_flat) {
+               printk(KERN_WARNING
+                      "flat APIC routing can't be used with > 8 cpus\n");
+               BUG();
+       }
+
        err = 0;
 
        return err;
index e3ef544..9f05bc9 100644 (file)
@@ -563,7 +563,7 @@ static unsigned int cpufreq_delayed_issched = 0;
 static unsigned int cpufreq_init = 0;
 static struct work_struct cpufreq_delayed_get_work;
 
-static void handle_cpufreq_delayed_get(void *v)
+static void handle_cpufreq_delayed_get(struct work_struct *v)
 {
        unsigned int cpu;
        for_each_online_cpu(cpu) {
@@ -639,7 +639,7 @@ static struct notifier_block time_cpufreq_notifier_block = {
 
 static int __init cpufreq_tsc(void)
 {
-       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
        if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
                                       CPUFREQ_TRANSITION_NOTIFIER))
                cpufreq_init = 1;
index 0d65b22..b54ccc0 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
 #include <linux/unwind.h>
+#include <linux/uaccess.h>
+#include <linux/bug.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/debugreg.h>
@@ -108,7 +109,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
        preempt_enable_no_resched();
 }
 
-static int kstack_depth_to_print = 12;
+int kstack_depth_to_print = 12;
 #ifdef CONFIG_STACK_UNWIND
 static int call_trace = 1;
 #else
@@ -225,16 +226,25 @@ 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;
+       unsigned long sp = UNW_SP(info);
 
+       if (arch_unw_user_mode(info))
+               return -1;
        while (unwind(info) == 0 && UNW_PC(info)) {
                n++;
                oad->ops->address(oad->data, UNW_PC(info));
                if (arch_unw_user_mode(info))
                        break;
+               if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
+                   && sp > UNW_SP(info))
+                       break;
+               sp = UNW_SP(info);
        }
        return n;
 }
 
+#define MSG(txt) ops->warning(data, txt)
+
 /*
  * x86-64 can have upto three kernel stacks: 
  * process stack
@@ -248,11 +258,12 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
         return p > t && p < t + THREAD_SIZE - 3;
 }
 
-void dump_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 = smp_processor_id();
-       unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
+       const unsigned cpu = get_cpu();
+       unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
        unsigned used = 0;
        struct thread_info *tinfo;
 
@@ -268,28 +279,30 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
                        if (unwind_init_frame_info(&info, tsk, regs) == 0)
                                unw_ret = dump_trace_unwind(&info, &oad);
                } else if (tsk == current)
-                       unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+                       unw_ret = unwind_init_running(&info, dump_trace_unwind,
+                                                     &oad);
                else {
                        if (unwind_init_blocked(&info, tsk) == 0)
                                unw_ret = dump_trace_unwind(&info, &oad);
                }
                if (unw_ret > 0) {
                        if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-                               ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+                               ops->warning_symbol(data,
+                                            "DWARF2 unwinder stuck at %s",
                                             UNW_PC(&info));
                                if ((long)UNW_SP(&info) < 0) {
-                                       ops->warning(data, "Leftover inexact backtrace:\n");
+                                       MSG("Leftover inexact backtrace:");
                                        stack = (unsigned long *)UNW_SP(&info);
                                        if (!stack)
-                                               return;
+                                               goto out;
                                } else
-                                       ops->warning(data, "Full inexact backtrace again:\n");
+                                       MSG("Full inexact backtrace again:");
                        } else if (call_trace >= 1)
-                               return;
+                               goto out;
                        else
-                               ops->warning(data, "Full inexact backtrace again:\n");
+                               MSG("Full inexact backtrace again:");
                } else
-                       ops->warning(data, "Inexact backtrace:\n");
+                       MSG("Inexact backtrace:");
        }
        if (!stack) {
                unsigned long dummy;
@@ -297,12 +310,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
                if (tsk && tsk != current)
                        stack = (unsigned long *)tsk->thread.rsp;
        }
-       /*
-        * Align the stack pointer on word boundary, later loops
-        * rely on that (and corruption / debug info bugs can cause
-        * unaligned values here):
-        */
-       stack = (unsigned long *)((unsigned long)stack & ~(sizeof(long)-1));
 
        /*
         * Print function call entries within a stack. 'cond' is the
@@ -312,9 +319,9 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
 #define HANDLE_STACK(cond) \
        do while (cond) { \
                unsigned long addr = *stack++; \
-               if (oops_in_progress ?          \
-                       __kernel_text_address(addr) : \
-                       kernel_text_address(addr)) { \
+               /* Use unlocked access here because except for NMIs     \
+                  we should be already protected against module unloads */ \
+               if (__kernel_text_address(addr)) { \
                        /* \
                         * If the address is either in the text segment of the \
                         * kernel, or in the region which contains vmalloc'ed \
@@ -380,6 +387,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
        tinfo = current_thread_info();
        HANDLE_STACK (valid_stack_ptr(tinfo, stack));
 #undef HANDLE_STACK
+out:
+       put_cpu();
 }
 EXPORT_SYMBOL(dump_trace);
 
@@ -516,30 +525,15 @@ bad:
        printk("\n");
 }      
 
-void handle_BUG(struct pt_regs *regs)
-{ 
-       struct bug_frame f;
-       long len;
-       const char *prefix = "";
+int is_valid_bugaddr(unsigned long rip)
+{
+       unsigned short ud2;
 
-       if (user_mode(regs))
-               return; 
-       if (__copy_from_user(&f, (const void __user *) regs->rip,
-                            sizeof(struct bug_frame)))
-               return; 
-       if (f.filename >= 0 ||
-           f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
-               return;
-       len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
-       if (len < 0 || len >= PATH_MAX)
-               f.filename = (int)(long)"unmapped filename";
-       else if (len > 50) {
-               f.filename += len - 50;
-               prefix = "...";
-       }
-       printk("----------- [cut here ] --------- [please bite here ] ---------\n");
-       printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
-} 
+       if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2)))
+               return 0;
+
+       return ud2 == 0x0b0f;
+}
 
 #ifdef CONFIG_BUG
 void out_of_line_bug(void)
@@ -619,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err)
 {
        unsigned long flags = oops_begin();
 
-       handle_BUG(regs);
+       if (!user_mode(regs))
+               report_bug(regs->rip);
+
        __die(str, regs, err);
        oops_end(flags);
        do_exit(SIGSEGV); 
@@ -786,8 +782,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
        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");
+       printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
 
        if (panic_on_unrecovered_nmi)
                panic("NMI: Not continuing");
index d9534e7..514be5d 100644 (file)
@@ -13,6 +13,7 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(phys_startup_64)
 jiffies_64 = jiffies;
+_proxy_pda = 0;
 PHDRS {
        text PT_LOAD FLAGS(5);  /* R_E */
        data PT_LOAD FLAGS(7);  /* RWE */
@@ -51,14 +52,7 @@ SECTIONS
 
   RODATA
 
-#ifdef CONFIG_STACK_UNWIND
-  . = ALIGN(8);
-  .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {
-       __start_unwind = .;
-       *(.eh_frame)
-       __end_unwind = .;
-  }
-#endif
+  BUG_TABLE
 
   . = ALIGN(PAGE_SIZE);        /* Align data segment to page size boundary */
                                /* Data */
index 92546c1..2433d6f 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/topology.h>
 
 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+#define __syscall_clobber "r11","rcx","memory"
 
 int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
 seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
@@ -224,8 +225,7 @@ out:
 
 static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
                                void __user *oldval, size_t __user *oldlenp,
-                               void __user *newval, size_t newlen,
-                               void **context)
+                               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
@@ -274,7 +274,6 @@ static void __cpuinit cpu_vsyscall_init(void *arg)
        vsyscall_set_cpu(raw_smp_processor_id());
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit
 cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
 {
@@ -283,13 +282,13 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
                smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
        return NOTIFY_DONE;
 }
-#endif
 
 static void __init map_vsyscall(void)
 {
        extern char __vsyscall_0;
        unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
 
+       /* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
        __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
 }
 
index 06ae630..bc503f5 100644 (file)
@@ -9,8 +9,6 @@
 #include <linux/module.h>
 #include <asm/checksum.h>
 
-#define __force_inline inline __attribute__((always_inline))
-
 static inline unsigned short from32to16(unsigned a) 
 {
        unsigned short b = a >> 16; 
@@ -33,7 +31,7 @@ static inline unsigned short from32to16(unsigned a)
  * Unrolling to an 128 bytes inner loop.
  * Using interleaving with more registers to break the carry chains.
  */
-static __force_inline unsigned do_csum(const unsigned char *buff, unsigned len)
+static unsigned do_csum(const unsigned char *buff, unsigned len)
 {
        unsigned odd, count;
        unsigned long result = 0;
index 50be909..2dbebd3 100644 (file)
@@ -40,13 +40,13 @@ EXPORT_SYMBOL(__delay);
 
 inline void __const_udelay(unsigned long xloops)
 {
-       __delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32);
+       __delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1);
 }
 EXPORT_SYMBOL(__const_udelay);
 
 void __udelay(unsigned long usecs)
 {
-       __const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
+       __const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
 }
 EXPORT_SYMBOL(__udelay);
 
index 3751b47..a65fc6f 100644 (file)
@@ -23,9 +23,9 @@
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
+#include <linux/uaccess.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
@@ -96,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 __user *instr;
+       unsigned char *instr;
        int scan_more = 1;
        int prefetch = 0; 
        unsigned char *max_instr;
@@ -116,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, (char __user *)instr))
+               if (probe_kernel_address(instr, opcode))
                        break; 
 
                instr_hi = opcode & 0xf0; 
@@ -154,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, (char __user *)instr))
+                       if (probe_kernel_address(instr, opcode))
                                break;
                        prefetch = (instr_lo == 0xF) &&
                                (opcode == 0x0D || opcode == 0x18);
@@ -170,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 __user *)p);
+       return probe_kernel_address((unsigned long *)p, dummy);
 } 
 
 void dump_pagetable(unsigned long address)
index 4c0c00e..2968b90 100644 (file)
@@ -730,14 +730,15 @@ static __init int x8664_sysctl_init(void)
 __initcall(x8664_sysctl_init);
 #endif
 
-/* A pseudo VMAs to allow ptrace access for the vsyscall page.   This only
+/* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
    covers the 64bit vsyscall page now. 32bit has a real VMA now and does
    not need special handling anymore. */
 
 static struct vm_area_struct gate_vma = {
        .vm_start = VSYSCALL_START,
-       .vm_end = VSYSCALL_END,
-       .vm_page_prot = PAGE_READONLY
+       .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES << PAGE_SHIFT),
+       .vm_page_prot = PAGE_READONLY_EXEC,
+       .vm_flags = VM_READ | VM_EXEC
 };
 
 struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
index 3e231d7..ccb91dd 100644 (file)
@@ -61,34 +61,40 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        return base;
 } 
 
-
-static void flush_kernel_map(void *address) 
+static void cache_flush_page(void *adr)
 {
-       if (0 && address && cpu_has_clflush) {
-               /* is this worth it? */ 
-               int i;
-               for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
-                       asm volatile("clflush (%0)" :: "r" (address + i)); 
-       } else
-               asm volatile("wbinvd":::"memory"); 
-       if (address)
-               __flush_tlb_one(address);
-       else
-               __flush_tlb_all();
+       int i;
+       for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+               asm volatile("clflush (%0)" :: "r" (adr + i));
 }
 
+static void flush_kernel_map(void *arg)
+{
+       struct list_head *l = (struct list_head *)arg;
+       struct page *pg;
+
+       /* When clflush is available always use it because it is
+          much cheaper than WBINVD */
+       if (!cpu_has_clflush)
+               asm volatile("wbinvd" ::: "memory");
+       list_for_each_entry(pg, l, lru) {
+               void *adr = page_address(pg);
+               if (cpu_has_clflush)
+                       cache_flush_page(adr);
+               __flush_tlb_one(adr);
+       }
+}
 
-static inline void flush_map(unsigned long address)
+static inline void flush_map(struct list_head *l)
 {      
-       on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
+       on_each_cpu(flush_kernel_map, l, 1, 1);
 }
 
-static struct page *deferred_pages; /* protected by init_mm.mmap_sem */
+static LIST_HEAD(deferred_pages); /* protected by init_mm.mmap_sem */
 
 static inline void save_page(struct page *fpage)
 {
-       fpage->lru.next = (struct list_head *)deferred_pages;
-       deferred_pages = fpage;
+       list_add(&fpage->lru, &deferred_pages);
 }
 
 /* 
@@ -207,18 +213,18 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot)
 
 void global_flush_tlb(void)
 { 
-       struct page *dpage;
+       struct page *pg, *next;
+       struct list_head l;
 
        down_read(&init_mm.mmap_sem);
-       dpage = xchg(&deferred_pages, NULL);
+       list_replace_init(&deferred_pages, &l);
        up_read(&init_mm.mmap_sem);
 
-       flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0);
-       while (dpage) {
-               struct page *tmp = dpage;
-               dpage = (struct page *)dpage->lru.next;
-               ClearPagePrivate(tmp);
-               __free_page(tmp);
+       flush_map(&l);
+
+       list_for_each_entry_safe(pg, next, &l, lru) {
+               ClearPagePrivate(pg);
+               __free_page(pg);
        } 
 } 
 
index c1e69a1..2e74cb0 100644 (file)
@@ -34,31 +34,24 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config ARCH_HAS_ILOG2_U32
+       bool
+       default n
+
+config ARCH_HAS_ILOG2_U64
+       bool
+       default n
+
 source "init/Kconfig"
 
 menu "Processor type and features"
 
 choice
        prompt "Xtensa Processor Configuration"
-       default XTENSA_CPU_LINUX_BE
+       default XTENSA_VARIANT_FSF
 
-config XTENSA_CPU_LINUX_BE
-       bool "linux_be"
-       ---help---
-         The linux_be processor configuration is the baseline Xtensa
-         configurations included in this kernel and also used by
-         binutils, gcc, and gdb. It contains no TIE, no coprocessors,
-         and the following configuration options:
-
-         Code Density Option                2 Misc Special Registers
-         NSA/NSAU Instructions              128-bit Data Bus Width
-         Processor ID                       8K, 2-way I and D Caches
-         Zero-Overhead Loops                2 Inst Address Break Registers
-         Big Endian                         2 Data Address Break Registers
-         64 General-Purpose Registers       JTAG Interface and Trace Port
-         17 Interrupts                      MMU w/ TLBs and Autorefill
-         3 Interrupt Levels                 8 Autorefill Ways (I/D TLBs)
-         3 Timers                           Unaligned Exceptions
+config XTENSA_VARIANT_FSF
+       bool "fsf"
 endchoice
 
 config MMU
index 3a3a4c6..95f836d 100644 (file)
 # this architecture
 
 # Core configuration.
-# (Use CPU=<xtensa_config> to use another default compiler.)
+# (Use VAR=<xtensa_config> to use another default compiler.)
 
-cpu-$(CONFIG_XTENSA_CPU_LINUX_BE)      := linux_be
-cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM)  := linux_custom
+variant-$(CONFIG_XTENSA_VARIANT_FSF)           := fsf
+variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM)  := custom
 
-CPU = $(cpu-y)
-export CPU
+VARIANT = $(variant-y)
+export VARIANT
 
 # Platform configuration
 
@@ -27,8 +27,6 @@ platform-$(CONFIG_XTENSA_PLATFORM_ISS)                := iss
 PLATFORM = $(platform-y)
 export PLATFORM
 
-CPPFLAGS       += $(if $(KBUILD_SRC),-I$(srctree)/include/asm-xtensa/)
-CPPFLAGS       += -Iinclude/asm
 CFLAGS         += -pipe -mlongcalls
 
 KBUILD_DEFCONFIG := iss_defconfig
@@ -41,12 +39,12 @@ core-$(CONFIG_EMBEDDED_RAMDISK)     += arch/xtensa/boot/ramdisk/
 
 # Test for cross compiling
 
-ifneq ($(CPU),)
+ifneq ($(VARIANT),)
   COMPILE_ARCH = $(shell uname -m)
 
   ifneq ($(COMPILE_ARCH), xtensa)
     ifndef CROSS_COMPILE
-      CROSS_COMPILE = xtensa_$(CPU)-
+      CROSS_COMPILE = xtensa_$(VARIANT)-
     endif
   endif
 endif
@@ -68,14 +66,13 @@ archinc             := include/asm-xtensa
 
 archprepare: $(archinc)/.platform
 
-# Update machine cpu and platform symlinks if something which affects
+# Update processor variant and platform symlinks if something which affects
 # them changed.
 
 $(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf
-       @echo '  SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)'
+       @echo '  SYMLINK $(archinc)/variant -> $(archinc)/variant-$(VARIANT)'
        $(Q)mkdir -p $(archinc)
-       $(Q)mkdir -p $(archinc)/xtensa
-       $(Q)ln -fsn $(srctree)/$(archinc)/xtensa/config-$(CPU) $(archinc)/xtensa/config
+       $(Q)ln -fsn $(srctree)/$(archinc)/variant-$(VARIANT) $(archinc)/variant
        @echo '  SYMLINK $(archinc)/platform -> $(archinc)/platform-$(PLATFORM)'
        $(Q)ln -fsn $(srctree)/$(archinc)/platform-$(PLATFORM) $(archinc)/platform
        @touch $@
@@ -89,7 +86,7 @@ zImage zImage.initrd: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $@
 
 CLEAN_FILES    += arch/xtensa/vmlinux.lds                      \
-                  $(archinc)/platform $(archinc)/xtensa/config \
+                  $(archinc)/platform $(archinc)/variant       \
                   $(archinc)/.platform
 
 define archhelp
index f857fc7..464298b 100644 (file)
@@ -1,7 +1,4 @@
 
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/core.h>
-
 #include <asm/bootparam.h>
 
 
index ee636b0..8484812 100644 (file)
@@ -1,9 +1,7 @@
-
-#define _ASMLANGUAGE
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/core.h>
-#include <xtensa/cacheasm.h>
-
+#include <asm/variant/core.h>
+#include <asm/regs.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
        /*
         * RB-Data: RedBoot data/bss
         * P:       Boot-Parameters
@@ -77,8 +75,14 @@ _start:
        /* Note: The assembler cannot relax "addi a0, a0, ..." to an
           l32r, so we load to a4 first. */
 
-       addi    a4, a0, __start - __start_a0
-       mov     a0, a4
+       # addi  a4, a0, __start - __start_a0
+       # mov   a0, a4
+
+       movi    a4, __start
+       movi    a5, __start_a0
+       add     a4, a0, a4
+       sub     a0, a4, a5
+
        movi    a4, __start
        movi    a5, __reloc_end
 
@@ -106,9 +110,13 @@ _start:
        /* We have to flush and invalidate the caches here before we jump. */
 
 #if XCHAL_DCACHE_IS_WRITEBACK
-       dcache_writeback_all  a5, a6
+
+       ___flush_dcache_all a5 a6
+
 #endif
-       icache_invalidate_all a5, a6
+
+       ___invalidate_icache_all a5 a6
+       isync
 
        movi    a11, _reloc
        jx      a11
@@ -209,9 +217,14 @@ _reloc:
        /* jump to the kernel */
 2:
 #if XCHAL_DCACHE_IS_WRITEBACK
-       dcache_writeback_all a5, a6
+
+       ___flush_dcache_all a5 a6
+
 #endif
-       icache_invalidate_all a5, a6
+
+       ___invalidate_icache_all a5 a6
+
+       isync
 
        movi    a5, __start
        movi    a3, boot_initrd_start
index 802621d..f198540 100644 (file)
@@ -53,11 +53,7 @@ CONFIG_CC_ALIGN_JUMPS=0
 #
 # Processor type and features
 #
-CONFIG_XTENSA_ARCH_LINUX_BE=y
-# CONFIG_XTENSA_ARCH_LINUX_LE is not set
-# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
-# CONFIG_XTENSA_ARCH_S5 is not set
-# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_XTENSA_VARIANT_FSF=y
 CONFIG_MMU=y
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 # CONFIG_PREEMPT is not set
index a495657..33d6e9d 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/ptrace.h>
-#include <asm/ptrace.h>
 #include <asm/current.h>
 #include <asm/asm-offsets.h>
-#include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/thread_info.h>
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 
@@ -216,7 +211,7 @@ ENTRY(fast_unaligned)
 
        extui   a5, a4, INSN_OP0, 4     # get insn.op0 nibble
 
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
        _beqi   a5, OP0_L32I_N, .Lload  # L32I.N, jump
        addi    a6, a5, -OP0_S32I_N
        _beqz   a6, .Lstore             # S32I.N, do a store
@@ -251,7 +246,7 @@ ENTRY(fast_unaligned)
 #endif
        __src_b a3, a5, a6              # a3 has the data word
 
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
        addi    a7, a7, 2               # increment PC (assume 16-bit insn)
 
        extui   a5, a4, INSN_OP0, 4
@@ -279,14 +274,14 @@ ENTRY(fast_unaligned)
 
 1:
 
-#if XCHAL_HAVE_LOOP
-       rsr     a3, LEND                # check if we reached LEND
-       bne     a7, a3, 1f
-       rsr     a3, LCOUNT              # and LCOUNT != 0
-       beqz    a3, 1f
-       addi    a3, a3, -1              # decrement LCOUNT and set
+#if XCHAL_HAVE_LOOPS
+       rsr     a5, LEND                # check if we reached LEND
+       bne     a7, a5, 1f
+       rsr     a5, LCOUNT              # and LCOUNT != 0
+       beqz    a5, 1f
+       addi    a5, a5, -1              # decrement LCOUNT and set
        rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a3, LCOUNT
+       wsr     a5, LCOUNT
 #endif
 
 1:     wsr     a7, EPC_1               # skip load instruction
@@ -336,7 +331,7 @@ ENTRY(fast_unaligned)
 
        movi    a6, 0                   # mask: ffffffff:00000000
 
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
        addi    a7, a7, 2               # incr. PC,assume 16-bit instruction
 
        extui   a5, a4, INSN_OP0, 4     # extract OP0
@@ -359,14 +354,14 @@ ENTRY(fast_unaligned)
        /* Get memory address */
 
 1:
-#if XCHAL_HAVE_LOOP
-       rsr     a3, LEND                # check if we reached LEND
-       bne     a7, a3, 1f
-       rsr     a3, LCOUNT              # and LCOUNT != 0
-       beqz    a3, 1f
-       addi    a3, a3, -1              # decrement LCOUNT and set
+#if XCHAL_HAVE_LOOPS
+       rsr     a4, LEND                # check if we reached LEND
+       bne     a7, a4, 1f
+       rsr     a4, LCOUNT              # and LCOUNT != 0
+       beqz    a4, 1f
+       addi    a4, a4, -1              # decrement LCOUNT and set
        rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a3, LCOUNT
+       wsr     a4, LCOUNT
 #endif
 
 1:     wsr     a7, EPC_1               # skip store instruction
@@ -416,6 +411,7 @@ ENTRY(fast_unaligned)
 
        /* Restore working register */
 
+       l32i    a8, a2, PT_AREG8
        l32i    a7, a2, PT_AREG7
        l32i    a6, a2, PT_AREG6
        l32i    a5, a2, PT_AREG5
@@ -446,7 +442,7 @@ ENTRY(fast_unaligned)
        mov     a1, a2
 
        rsr     a0, PS
-        bbsi.l  a2, PS_UM_SHIFT, 1f     # jump if user mode
+        bbsi.l  a2, PS_UM_BIT, 1f     # jump if user mode
 
        movi    a0, _kernel_exception
        jx      a0
index 7cd1d7f..b256cfb 100644 (file)
@@ -87,6 +87,11 @@ int main(void)
        DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
        BLANK();
        DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
+
+       /* constants */
+       DEFINE(_CLONE_VM, CLONE_VM);
+       DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
+
        return 0;
 }
 
index cf5a93f..01bcb9f 100644 (file)
@@ -90,7 +90,6 @@ ENTRY(enable_coprocessor)
        rsync
        retw
 
-#endif
 
 ENTRY(save_coprocessor_extra)
        entry   sp, 16
@@ -197,4 +196,5 @@ _xtensa_reginfo_tables:
        XCHAL_CP7_SA_CONTENTS_LIBDB
        .word   0xFC000000      /* invalid register number,marks end of table*/
 _xtensa_reginfo_table_end:
+#endif
 
index 89e409e..9e271ba 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/signal.h>
-#include <xtensa/coreasm.h>
+#include <asm/tlbflush.h>
 
 /* Unimplemented features. */
 
@@ -364,7 +364,7 @@ common_exception:
        movi    a2, 1
        extui   a3, a3, 0, 1            # a3 = PS.INTLEVEL[0]
        moveqz  a3, a2, a0              # a3 = 1 iff interrupt exception
-       movi    a2, PS_WOE_MASK
+       movi    a2, 1 << PS_WOE_BIT
        or      a3, a3, a2
        rsr     a0, EXCCAUSE
        xsr     a3, PS
@@ -399,7 +399,7 @@ common_exception_return:
        /* Jump if we are returning from kernel exceptions. */
 
 1:     l32i    a3, a1, PT_PS
-       _bbsi.l a3, PS_UM_SHIFT, 2f
+       _bbsi.l a3, PS_UM_BIT, 2f
        j       kernel_exception_exit
 
        /* Specific to a user exception exit:
@@ -422,7 +422,7 @@ common_exception_return:
         *       (Hint: There is only one user exception frame on stack)
         */
 
-       movi    a3, PS_WOE_MASK
+       movi    a3, 1 << PS_WOE_BIT
 
        _bbsi.l a4, TIF_NEED_RESCHED, 3f
        _bbci.l a4, TIF_SIGPENDING, 4f
@@ -694,7 +694,7 @@ common_exception_exit:
 ENTRY(debug_exception)
 
        rsr     a0, EPS + XCHAL_DEBUGLEVEL
-       bbsi.l  a0, PS_EXCM_SHIFT, 1f   # exception mode
+       bbsi.l  a0, PS_EXCM_BIT, 1f     # exception mode
 
        /* Set EPC_1 and EXCCAUSE */
 
@@ -707,7 +707,7 @@ ENTRY(debug_exception)
 
        /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
 
-       movi    a2, 1 << PS_EXCM_SHIFT
+       movi    a2, 1 << PS_EXCM_BIT
        or      a2, a0, a2
        movi    a0, debug_exception     # restore a3, debug jump vector
        wsr     a2, PS
@@ -715,7 +715,7 @@ ENTRY(debug_exception)
 
        /* Switch to kernel/user stack, restore jump vector, and save a0 */
 
-       bbsi.l  a2, PS_UM_SHIFT, 2f     # jump if user mode
+       bbsi.l  a2, PS_UM_BIT, 2f       # jump if user mode
 
        addi    a2, a1, -16-PT_SIZE     # assume kernel stack
        s32i    a0, a2, PT_AREG0
@@ -778,7 +778,7 @@ ENTRY(unrecoverable_exception)
        wsr     a1, WINDOWBASE
        rsync
 
-       movi    a1, PS_WOE_MASK | 1
+       movi    a1, (1 << PS_WOE_BIT) | 1
        wsr     a1, PS
        rsync
 
@@ -1004,13 +1004,10 @@ ENTRY(fast_syscall_kernel)
 
        rsr     a0, DEPC                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
-
-       addi    a0, a0, -__NR_sysxtensa
-       _beqz   a0, fast_syscall_sysxtensa
+       _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
        j       kernel_exception
 
-
 ENTRY(fast_syscall_user)
 
        /* Skip syscall. */
@@ -1024,9 +1021,7 @@ ENTRY(fast_syscall_user)
 
        rsr     a0, DEPC                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
-
-       addi    a0, a0, -__NR_sysxtensa
-       _beqz   a0, fast_syscall_sysxtensa
+       _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
        j       user_exception
 
@@ -1047,18 +1042,19 @@ ENTRY(fast_syscall_unrecoverable)
 /*
  * sysxtensa syscall handler
  *
- * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
- * a2                    a6              a3    a4      a5
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ *        a2            a6                   a3    a4      a5
  *
  * Entry condition:
  *
- *   a0:       trashed, original value saved on stack (PT_AREG0)
+ *   a0:       a2 (syscall-nr), original value saved on stack (PT_AREG0)
  *   a1:       a1
- *   a2:       new stack pointer, original in DEPC
- *   a3:       dispatch table
+ *   a2:       new stack pointer, original in a0 and DEPC
+ *   a3:       dispatch table, original in excsave_1
+ *   a4..a15:  unchanged
  *   depc:     a2, original value saved on stack (PT_DEPC)
  *   excsave_1:        a3
  *
@@ -1091,59 +1087,62 @@ ENTRY(fast_syscall_unrecoverable)
 #define CATCH                                                          \
 67:
 
-ENTRY(fast_syscall_sysxtensa)
-
-       _beqz   a6, 1f
-       _blti   a6, SYSXTENSA_COUNT, 2f
+ENTRY(fast_syscall_xtensa)
 
-1:     j       user_exception
-
-2:     xsr     a3, EXCSAVE_1           # restore a3, excsave1
-       s32i    a7, a2, PT_AREG7
+       xsr     a3, EXCSAVE_1           # restore a3, excsave1
 
+       s32i    a7, a2, PT_AREG7        # we need an additional register
        movi    a7, 4                   # sizeof(unsigned int)
-       access_ok a0, a3, a7, a2, .Leac
+       access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
 
-       _beqi   a6, SYSXTENSA_ATOMIC_SET, .Lset
-       _beqi   a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
-       _beqi   a6, SYSXTENSA_ATOMIC_ADD, .Ladd
+       addi    a6, a6, -1              # assuming SYS_XTENSA_ATOMIC_SET = 1
+       _bgeui  a6, SYS_XTENSA_COUNT - 1, .Lill
+       _bnei   a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
 
-       /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
+       /* Fall through for ATOMIC_CMP_SWP. */
 
 .Lswp: /* Atomic compare and swap */
 
-TRY    l32i    a7, a3, 0               # read old value
-       bne     a7, a4, 1f              # same as old value? jump
-       s32i    a5, a3, 0               # different, modify value
-       movi    a7, 1                   # and return 1
-       j       .Lret
-
-1:     movi    a7, 0                   # same values: return 0
-       j       .Lret
-
-.Ladd: /* Atomic add */
-.Lexg: /* Atomic (exchange) add */
+TRY    l32i    a0, a3, 0               # read old value
+       bne     a0, a4, 1f              # same as old value? jump
+TRY    s32i    a5, a3, 0               # different, modify value
+       l32i    a7, a2, PT_AREG7        # restore a7
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, 1                   # and return 1
+       addi    a6, a6, 1               # restore a6 (really necessary?)
+       rfe
 
-TRY    l32i    a7, a3, 0
-       add     a4, a4, a7
-       s32i    a4, a3, 0
-       j       .Lret
+1:     l32i    a7, a2, PT_AREG7        # restore a7
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, 0                   # return 0 (note that we cannot set
+       addi    a6, a6, 1               # restore a6 (really necessary?)
+       rfe
 
-.Lset: /* Atomic set */
+.Lnswp:        /* Atomic set, add, and exg_add. */
 
-TRY    l32i    a7, a3, 0               # read old value as return value
-       s32i    a4, a3, 0               # write new value
+TRY    l32i    a7, a3, 0               # orig
+       add     a0, a4, a7              # + arg
+       moveqz  a0, a4, a6              # set
+TRY    s32i    a0, a3, 0               # write new value
 
-.Lret: mov     a0, a2
+       mov     a0, a2
        mov     a2, a7
-       l32i    a7, a0, PT_AREG7
-       l32i    a3, a0, PT_AREG3
-       l32i    a0, a0, PT_AREG0
+       l32i    a7, a0, PT_AREG7        # restore a7
+       l32i    a0, a0, PT_AREG0        # restore a0
+       addi    a6, a6, 1               # restore a6 (really necessary?)
        rfe
 
 CATCH
-.Leac: movi    a7, -EFAULT
-       j       .Lret
+.Leac: l32i    a7, a2, PT_AREG7        # restore a7
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, -EFAULT
+       rfe
+
+.Lill: l32i    a7, a2, PT_AREG0        # restore a7
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, -EINVAL
+       rfe
+
 
 
 
@@ -1491,7 +1490,7 @@ ENTRY(_spill_registers)
         */
 
        rsr     a0, PS
-       _bbci.l a0, PS_UM_SHIFT, 1f
+       _bbci.l a0, PS_UM_BIT, 1f
 
        /* User space: Setup a dummy frame and kill application.
         * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
@@ -1510,7 +1509,7 @@ ENTRY(_spill_registers)
        l32i    a1, a3, EXC_TABLE_KSTK
        wsr     a3, EXCSAVE_1
 
-       movi    a4, PS_WOE_MASK | 1
+       movi    a4, (1 << PS_WOE_BIT) | 1
        wsr     a4, PS
        rsync
 
@@ -1612,7 +1611,7 @@ ENTRY(fast_second_level_miss)
        rsr     a1, PTEVADDR
        srli    a1, a1, PAGE_SHIFT
        slli    a1, a1, PAGE_SHIFT      # ptevaddr & PAGE_MASK
-       addi    a1, a1, DTLB_WAY_PGTABLE        # ... + way_number
+       addi    a1, a1, DTLB_WAY_PGD    # ... + way_number
 
        wdtlb   a0, a1
        dsync
@@ -1654,7 +1653,7 @@ ENTRY(fast_second_level_miss)
        mov     a1, a2
 
        rsr     a2, PS
-       bbsi.l  a2, PS_UM_SHIFT, 1f
+       bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
 
@@ -1753,7 +1752,7 @@ ENTRY(fast_store_prohibited)
        mov     a1, a2
 
        rsr     a2, PS
-       bbsi.l  a2, PS_UM_SHIFT, 1f
+       bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
 
@@ -1906,6 +1905,103 @@ ENTRY(fast_coprocessor)
 
 #endif /* XCHAL_EXTRA_SA_SIZE */
 
+/*
+ * System Calls.
+ *
+ * void system_call (struct pt_regs* regs, int exccause)
+ *                            a2                 a3
+ */
+
+ENTRY(system_call)
+       entry   a1, 32
+
+       /* regs->syscall = regs->areg[2] */
+
+       l32i    a3, a2, PT_AREG2
+       mov     a6, a2
+       movi    a4, do_syscall_trace_enter
+       s32i    a3, a2, PT_SYSCALL
+       callx4  a4
+
+       /* syscall = sys_call_table[syscall_nr] */
+
+       movi    a4, sys_call_table;
+       movi    a5, __NR_syscall_count
+       movi    a6, -ENOSYS
+       bgeu    a3, a5, 1f
+
+       addx4   a4, a3, a4
+       l32i    a4, a4, 0
+       movi    a5, sys_ni_syscall;
+       beq     a4, a5, 1f
+
+       /* Load args: arg0 - arg5 are passed via regs. */
+
+       l32i    a6, a2, PT_AREG6
+       l32i    a7, a2, PT_AREG3
+       l32i    a8, a2, PT_AREG4
+       l32i    a9, a2, PT_AREG5
+       l32i    a10, a2, PT_AREG8
+       l32i    a11, a2, PT_AREG9
+
+       /* Pass one additional argument to the syscall: pt_regs (on stack) */
+       s32i    a2, a1, 0
+
+       callx4  a4
+
+1:     /* regs->areg[2] = return_value */
+
+       s32i    a6, a2, PT_AREG2
+       movi    a4, do_syscall_trace_leave
+       mov     a6, a2
+       callx4  a4
+       retw
+
+
+/*
+ * Create a kernel thread
+ *
+ * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+ * a2                    a2                 a3             a4
+ */
+
+ENTRY(kernel_thread)
+       entry   a1, 16
+
+       mov     a5, a2                  # preserve fn over syscall
+       mov     a7, a3                  # preserve args over syscall
+
+       movi    a3, _CLONE_VM | _CLONE_UNTRACED
+       movi    a2, __NR_clone
+       or      a6, a4, a3              # arg0: flags
+       mov     a3, a1                  # arg1: sp
+       syscall
+
+       beq     a3, a1, 1f              # branch if parent
+       mov     a6, a7                  # args
+       callx4  a5                      # fn(args)
+
+       movi    a2, __NR_exit
+       syscall                         # return value of fn(args) still in a6
+
+1:     retw
+
+/*
+ * Do a system call from kernel instead of calling sys_execve, so we end up
+ * with proper pt_regs.
+ *
+ * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
+ * a2                        a2               a3                  a4
+ */
+
+ENTRY(kernel_execve)
+       entry   a1, 16
+       mov     a6, a2                  # arg0 is in a6
+       movi    a2, __NR_execve
+       syscall
+
+       retw
+
 /*
  * Task switch.
  *
@@ -1924,7 +2020,7 @@ ENTRY(_switch_to)
 
        /* Disable ints while we manipulate the stack pointer; spill regs. */
 
-       movi    a5, PS_EXCM_MASK | LOCKLEVEL
+       movi    a5, (1 << PS_EXCM_BIT) | LOCKLEVEL
        xsr     a5, PS
        rsr     a3, EXCSAVE_1
        rsync
@@ -1964,33 +2060,9 @@ ENTRY(ret_from_fork)
        movi    a4, schedule_tail
        callx4  a4
 
-       movi    a4, do_syscall_trace
+       movi    a4, do_syscall_trace_leave
+       mov     a6, a1
        callx4  a4
 
        j       common_exception_return
 
-
-
-/*
- * Table of syscalls
- */
-
-.data
-.align  4
-.global sys_call_table
-sys_call_table:
-
-#define SYSCALL(call, narg) .word call
-#include "syscalls.h"
-
-/*
- * Number of arguments of each syscall
- */
-
-.global sys_narg_table
-sys_narg_table:
-
-#undef SYSCALL
-#define SYSCALL(call, narg) .byte narg
-#include "syscalls.h"
-
index c07cb25..ea89910 100644 (file)
@@ -15,9 +15,9 @@
  * Kevin Chea
  */
 
-#include <xtensa/cacheasm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
+#include <asm/cacheasm.h>
 
 /*
  * This module contains the entry code for kernel images. It performs the
  *
  */
 
-       .macro  iterate from, to , cmd
-               .ifeq   ((\to - \from) & ~0xfff)
-                       \cmd    \from
-                       iterate "(\from+1)", \to, \cmd
-               .endif
-       .endm
-
 /*
  *  _start
  *
@@ -64,7 +57,7 @@ _startup:
 
        /* Disable interrupts and exceptions. */
 
-       movi    a0, XCHAL_PS_EXCM_MASK
+       movi    a0, LOCKLEVEL
        wsr     a0, PS
 
        /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
@@ -91,11 +84,11 @@ _startup:
        movi    a1, 15
        wsr     a0, ICOUNTLEVEL
 
-       .macro reset_dbreak num
-       wsr     a0, DBREAKC + \num
-       .endm
-
-        iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak
+       .set    _index, 0
+       .rept   XCHAL_NUM_DBREAK - 1
+       wsr     a0, DBREAKC + _index
+       .set    _index, _index + 1
+       .endr
 #endif
 
        /* Clear CCOUNT (not really necessary, but nice) */
@@ -110,10 +103,11 @@ _startup:
 
        /* Disable all timers. */
 
-       .macro  reset_timer     num
-       wsr     a0, CCOMPARE_0 + \num
-       .endm
-       iterate 0, XCHAL_NUM_TIMERS-1, reset_timer
+       .set    _index, 0
+       .rept   XCHAL_NUM_TIMERS - 1
+       wsr     a0, CCOMPARE + _index
+       .set    _index, _index + 1
+       .endr
 
        /* Interrupt initialization. */
 
@@ -139,12 +133,21 @@ _startup:
        rsync
 
        /*  Initialize the caches.
-        *  Does not include flushing writeback d-cache.
-        *  a6, a7 are just working registers (clobbered).
+        *  a2, a3 are just working registers (clobbered).
         */
 
-       icache_reset  a2, a3
-       dcache_reset  a2, a3
+#if XCHAL_DCACHE_LINE_LOCKABLE
+       ___unlock_dcache_all a2 a3
+#endif
+
+#if XCHAL_ICACHE_LINE_LOCKABLE
+       ___unlock_icache_all a2 a3
+#endif
+
+       ___invalidate_dcache_all a2 a3
+       ___invalidate_icache_all a2 a3
+
+       isync
 
        /* Unpack data sections
         *
@@ -181,9 +184,9 @@ _startup:
        movi    a2, _bss_start  # start of BSS
        movi    a3, _bss_end    # end of BSS
 
-1:     addi    a2, a2, 4
+       __loopt a2, a3, a4, 2
        s32i    a0, a2, 0
-       blt     a2, a3, 1b
+       __endla a2, a4, 4
 
 #if XCHAL_DCACHE_IS_WRITEBACK
 
@@ -191,7 +194,7 @@ _startup:
         * instructions/data are available.
         */
 
-       dcache_writeback_all    a2, a3
+       ___flush_dcache_all a2 a3
 #endif
 
        /* Setup stack and enable window exceptions (keep irqs disabled) */
index 1cf744e..c9ea73b 100644 (file)
@@ -4,7 +4,7 @@
  * Xtensa built-in interrupt controller and some generic functions copied
  * from i386.
  *
- * Copyright (C) 2002 - 2005 Tensilica, Inc.
+ * Copyright (C) 2002 - 2006 Tensilica, Inc.
  * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  *
  *
 #include <asm/uaccess.h>
 #include <asm/platform.h>
 
-static void enable_xtensa_irq(unsigned int irq);
-static void disable_xtensa_irq(unsigned int irq);
-static void mask_and_ack_xtensa(unsigned int irq);
-static void end_xtensa_irq(unsigned int irq);
-
 static unsigned int cached_irq_mask;
 
 atomic_t irq_err_count;
@@ -46,8 +41,16 @@ void ack_bad_irq(unsigned int irq)
  * handlers).
  */
 
-unsigned int  do_IRQ(int irq, struct pt_regs *regs)
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 {
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       struct irq_desc *desc = irq_desc + irq;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+                               __FUNCTION__, irq);
+       }
+
        irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
@@ -63,12 +66,10 @@ unsigned int  do_IRQ(int irq, struct pt_regs *regs)
                               sp - sizeof(struct thread_info));
        }
 #endif
-
-       __do_IRQ(irq, regs);
+       desc->handle_irq(irq, desc);
 
        irq_exit();
-
-       return 1;
+       set_irq_regs(old_regs);
 }
 
 /*
@@ -118,72 +119,68 @@ skip:
        }
        return 0;
 }
-/* shutdown is same as "disable" */
-#define shutdown_xtensa_irq disable_xtensa_irq
 
-static unsigned int startup_xtensa_irq(unsigned int irq)
-{
-       enable_xtensa_irq(irq);
-       return 0;               /* never anything pending */
-}
-
-static struct hw_interrupt_type xtensa_irq_type = {
-       "Xtensa-IRQ",
-       startup_xtensa_irq,
-       shutdown_xtensa_irq,
-       enable_xtensa_irq,
-       disable_xtensa_irq,
-       mask_and_ack_xtensa,
-       end_xtensa_irq
-};
-
-static inline void mask_irq(unsigned int irq)
+static void xtensa_irq_mask(unsigned int irq)
 {
        cached_irq_mask &= ~(1 << irq);
        set_sr (cached_irq_mask, INTENABLE);
 }
 
-static inline void unmask_irq(unsigned int irq)
+static void xtensa_irq_unmask(unsigned int irq)
 {
        cached_irq_mask |= 1 << irq;
        set_sr (cached_irq_mask, INTENABLE);
 }
 
-static void disable_xtensa_irq(unsigned int irq)
+static void xtensa_irq_ack(unsigned int irq)
 {
-       unsigned long flags;
-       local_save_flags(flags);
-       mask_irq(irq);
-       local_irq_restore(flags);
+       set_sr(1 << irq, INTCLEAR);
 }
 
-static void enable_xtensa_irq(unsigned int irq)
+static int xtensa_irq_retrigger(unsigned int irq)
 {
-       unsigned long flags;
-       local_save_flags(flags);
-       unmask_irq(irq);
-       local_irq_restore(flags);
-}
-
-static void mask_and_ack_xtensa(unsigned int irq)
-{
-        disable_xtensa_irq(irq);
+       set_sr (1 << irq, INTSET);
+       return 1;
 }
 
-static void end_xtensa_irq(unsigned int irq)
-{
-        enable_xtensa_irq(irq);
-}
 
+static struct irq_chip xtensa_irq_chip = {
+       .name           = "xtensa",
+       .mask           = xtensa_irq_mask,
+       .unmask         = xtensa_irq_unmask,
+       .ack            = xtensa_irq_ack,
+       .retrigger      = xtensa_irq_retrigger,
+};
 
 void __init init_IRQ(void)
 {
-       int i;
+       int index;
 
-       for (i=0; i < XTENSA_NR_IRQS; i++)
-               irq_desc[i].chip = &xtensa_irq_type;
+       for (index = 0; index < XTENSA_NR_IRQS; index++) {
+               int mask = 1 << index;
 
-       cached_irq_mask = 0;
+               if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
+                       set_irq_chip_and_handler(index, &xtensa_irq_chip,
+                                                handle_simple_irq);
 
-       platform_init_irq();
+               else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
+                       set_irq_chip_and_handler(index, &xtensa_irq_chip,
+                                                handle_edge_irq);
+
+               else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
+                       set_irq_chip_and_handler(index, &xtensa_irq_chip,
+                                                handle_level_irq);
+
+               else if (mask & XCHAL_INTTYPE_MASK_TIMER)
+                       set_irq_chip_and_handler(index, &xtensa_irq_chip,
+                                                handle_edge_irq);
+
+               else    /* XCHAL_INTTYPE_MASK_WRITE_ERROR */
+                       /* XCHAL_INTTYPE_MASK_NMI */
+
+                       set_irq_chip_and_handler(index, &xtensa_irq_chip,
+                                                handle_level_irq);
+       }
+
+       cached_irq_mask = 0;
 }
index 6648fa9..ca76f07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/xtensa/kernel/pci-dma.c
+ * arch/xtensa/pci-dma.c
  *
  * DMA coherent memory allocation.
  *
  */
 
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
 {
-       void *ret;
+       unsigned long ret;
+       unsigned long uncached = 0;
 
        /* ignore region speicifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
-       if (dev == NULL || (*dev->dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *)__get_free_pages(gfp, get_order(size));
+       flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *handle = virt_to_bus(ret);
+       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+               flag |= GFP_DMA;
+       ret = (unsigned long)__get_free_pages(flag, get_order(size));
+
+       if (ret == 0)
+               return NULL;
+
+       /* We currently don't support coherent memory outside KSEG */
+
+       if (ret < XCHAL_KSEG_CACHED_VADDR
+           || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
+               BUG();
+
+
+       if (ret != 0) {
+               memset((void*) ret, 0, size);
+               uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
+               *handle = virt_to_bus((void*)ret);
+               __flush_invalidate_dcache_range(ret, size);
        }
-       return (void*) BYPASS_ADDR((unsigned long)ret);
+
+       return (void*)uncached;
 }
 
 void dma_free_coherent(struct device *hwdev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+       long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+
+       if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
+               BUG();
+
+       free_pages(addr, get_order(size));
 }
 
 
index a7c4178..795bd5a 100644 (file)
@@ -1,4 +1,3 @@
-// TODO        verify coprocessor handling
 /*
  * arch/xtensa/kernel/process.c
  *
@@ -43,7 +42,7 @@
 #include <asm/irq.h>
 #include <asm/atomic.h>
 #include <asm/asm-offsets.h>
-#include <asm/coprocessor.h>
+#include <asm/regs.h>
 
 extern void ret_from_fork(void);
 
@@ -67,25 +66,6 @@ void (*pm_power_off)(void) = NULL;
 EXPORT_SYMBOL(pm_power_off);
 
 
-#if XCHAL_CP_NUM > 0
-
-/*
- * Coprocessor ownership.
- */
-
-coprocessor_info_t coprocessor_info[] = {
-       { 0, XTENSA_CPE_CP0_OFFSET },
-       { 0, XTENSA_CPE_CP1_OFFSET },
-       { 0, XTENSA_CPE_CP2_OFFSET },
-       { 0, XTENSA_CPE_CP3_OFFSET },
-       { 0, XTENSA_CPE_CP4_OFFSET },
-       { 0, XTENSA_CPE_CP5_OFFSET },
-       { 0, XTENSA_CPE_CP6_OFFSET },
-       { 0, XTENSA_CPE_CP7_OFFSET },
-};
-
-#endif
-
 /*
  * Powermanagement idle function, if any is provided by the platform.
  */
@@ -110,12 +90,10 @@ void cpu_idle(void)
 
 void exit_thread(void)
 {
-       release_coprocessors(current);  /* Empty macro if no CPs are defined */
 }
 
 void flush_thread(void)
 {
-       release_coprocessors(current);  /* Empty macro if no CPs are defined */
 }
 
 /*
@@ -182,36 +160,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 }
 
 
-/*
- * Create a kernel thread
- */
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       long retval;
-       __asm__ __volatile__
-               ("mov           a5, %4\n\t" /* preserve fn in a5 */
-                "mov           a6, %3\n\t" /* preserve and setup arg in a6 */
-                "movi          a2, %1\n\t" /* load __NR_clone for syscall*/
-                "mov           a3, sp\n\t" /* sp check and sys_clone */
-                "mov           a4, %5\n\t" /* load flags for syscall */
-                "syscall\n\t"
-                "beq           a3, sp, 1f\n\t" /* branch if parent */
-                "callx4        a5\n\t"     /* call fn */
-                "movi          a2, %2\n\t" /* load __NR_exit for syscall */
-                "mov           a3, a6\n\t" /* load fn return value */
-                "syscall\n"
-                "1:\n\t"
-                "mov           %0, a2\n\t" /* parent returns zero */
-                :"=r" (retval)
-                :"i" (__NR_clone), "i" (__NR_exit),
-                "r" (arg), "r" (fn),
-                "r" (flags | CLONE_VM)
-                : "a2", "a3", "a4", "a5", "a6" );
-       return retval;
-}
-
-
 /*
  * These bracket the sleeping functions..
  */
@@ -275,7 +223,7 @@ void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
         */
 
        elfregs->pc             = regs->pc;
-       elfregs->ps             = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+       elfregs->ps             = (regs->ps & ~(1 << PS_EXCM_BIT));
        elfregs->exccause       = regs->exccause;
        elfregs->excvaddr       = regs->excvaddr;
        elfregs->windowbase     = regs->windowbase;
@@ -325,7 +273,7 @@ void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
         */
 
        regs->pc                = elfregs->pc;
-       regs->ps                = (elfregs->ps | XCHAL_PS_EXCM_MASK);
+       regs->ps                = (elfregs->ps | (1 << PS_EXCM_BIT));
        regs->exccause          = elfregs->exccause;
        regs->excvaddr          = elfregs->excvaddr;
        regs->windowbase        = elfregs->windowbase;
@@ -459,16 +407,7 @@ int  do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
 int
 dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
 {
-/* see asm/coprocessor.h for this magic number 16 */
-#if XTENSA_CP_EXTRA_SIZE > 16
-       do_save_fpregs (r, regs, task);
-
-       /*  For now, bit 16 means some extra state may be present:  */
-// FIXME!! need to track to return more accurate mask
-       return 0x10000 | XCHAL_CP_MASK;
-#else
        return 0;       /* no coprocessors active on this processor */
-#endif
 }
 
 /*
@@ -483,3 +422,44 @@ int  dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
 {
        return dump_task_fpu(regs, current, r);
 }
+
+asmlinkage
+long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
+                  void __user *parent_tid, void *child_tls,
+                  void __user *child_tid, long a5,
+                  struct pt_regs *regs)
+{
+        if (!newsp)
+                newsp = regs->areg[1];
+        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+}
+
+/*
+ *  * xtensa_execve() executes a new program.
+ *   */
+
+asmlinkage
+long xtensa_execve(char __user *name, char __user * __user *argv,
+                   char __user * __user *envp,
+                   long a3, long a4, long a5,
+                   struct pt_regs *regs)
+{
+       long error;
+       char * filename;
+
+       filename = getname(name);
+       error = PTR_ERR(filename);
+       if (IS_ERR(filename))
+               goto out;
+       // FIXME: release coprocessor??
+       error = do_execve(filename, argv, envp, regs);
+       if (error == 0) {
+               task_lock(current);
+               current->ptrace &= ~PT_DTRACE;
+               task_unlock(current);
+       }
+       putname(filename);
+out:
+       return error;
+}
+
index 9aea23c..8b6d3d0 100644 (file)
@@ -96,7 +96,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        /* Note:  PS.EXCM is not set while user task is running;
                         * its being set in regs is for exception handling
                         * convenience.  */
-                       tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+                       tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
                        break;
                case REG_WB:
                        tmp = regs->windowbase;
@@ -332,12 +332,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
 void do_syscall_trace(void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-
        /*
         * The 0x80 provides a way for the tracing parent to distinguish
         * between a syscall stop and SIGTRAP delivery
@@ -354,3 +348,23 @@ void do_syscall_trace(void)
                current->exit_code = 0;
        }
 }
+
+void do_syscall_trace_enter(struct pt_regs *regs)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE)
+                       && (current->ptrace & PT_PTRACED))
+               do_syscall_trace();
+
+#if 0
+       if (unlikely(current->audit_context))
+               audit_syscall_entry(current, AUDIT_ARCH_XTENSA..);
+#endif
+}
+
+void do_syscall_trace_leave(struct pt_regs *regs)
+{
+       if ((test_thread_flag(TIF_SYSCALL_TRACE))
+                       && (current->ptrace & PT_PTRACED))
+               do_syscall_trace();
+}
+
index c99ab72..b6374c0 100644 (file)
@@ -42,8 +42,6 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 
-#include <xtensa/config/system.h>
-
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
 #endif
@@ -336,7 +334,7 @@ c_show(struct seq_file *f, void *slot)
        /* high-level stuff */
        seq_printf(f,"processor\t: 0\n"
                     "vendor_id\t: Tensilica\n"
-                    "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n"
+                    "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
                     "core ID\t\t: " XCHAL_CORE_ID "\n"
                     "build ID\t: 0x%x\n"
                     "byte order\t: %s\n"
@@ -420,25 +418,6 @@ c_show(struct seq_file *f, void *slot)
                     XCHAL_NUM_TIMERS,
                     XCHAL_DEBUGLEVEL);
 
-       /* Coprocessors */
-#if XCHAL_HAVE_CP
-       seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM);
-#else
-       seq_printf(f, "coprocessors\t: none\n");
-#endif
-
-       /* {I,D}{RAM,ROM} and XLMI */
-       seq_printf(f,"inst ROMs\t: %d\n"
-                    "inst RAMs\t: %d\n"
-                    "data ROMs\t: %d\n"
-                    "data RAMs\t: %d\n"
-                    "XLMI ports\t: %d\n",
-                    XCHAL_NUM_IROM,
-                    XCHAL_NUM_IRAM,
-                    XCHAL_NUM_DROM,
-                    XCHAL_NUM_DRAM,
-                    XCHAL_NUM_XLMI);
-
        /* Cache */
        seq_printf(f,"icache line size: %d\n"
                     "icache ways\t: %d\n"
@@ -466,24 +445,6 @@ c_show(struct seq_file *f, void *slot)
                     XCHAL_DCACHE_WAYS,
                     XCHAL_DCACHE_SIZE);
 
-       /* MMU */
-       seq_printf(f,"ASID bits\t: %d\n"
-                    "ASID invalid\t: %d\n"
-                    "ASID kernel\t: %d\n"
-                    "rings\t\t: %d\n"
-                    "itlb ways\t: %d\n"
-                    "itlb AR ways\t: %d\n"
-                    "dtlb ways\t: %d\n"
-                    "dtlb AR ways\t: %d\n",
-                    XCHAL_MMU_ASID_BITS,
-                    XCHAL_MMU_ASID_INVALID,
-                    XCHAL_MMU_ASID_KERNEL,
-                    XCHAL_MMU_RINGS,
-                    XCHAL_ITLB_WAYS,
-                    XCHAL_ITLB_ARF_WAYS,
-                    XCHAL_DTLB_WAYS,
-                    XCHAL_DTLB_ARF_WAYS);
-
        return 0;
 }
 
index c494f08..c6d9880 100644 (file)
@@ -12,8 +12,8 @@
  *
  */
 
-#include <xtensa/config/core.h>
-#include <xtensa/hal.h>
+#include <asm/variant/core.h>
+#include <asm/coprocessor.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -46,7 +46,7 @@ extern struct task_struct *coproc_owners[];
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 
-int sys_sigsuspend(struct pt_regs *regs)
+int xtensa_sigsuspend(struct pt_regs *regs)
 {
        old_sigset_t mask = (old_sigset_t) regs->areg[3];
        sigset_t saveset;
@@ -68,7 +68,7 @@ int sys_sigsuspend(struct pt_regs *regs)
 }
 
 asmlinkage int
-sys_rt_sigsuspend(struct pt_regs *regs)
+xtensa_rt_sigsuspend(struct pt_regs *regs)
 {
        sigset_t *unewset = (sigset_t *) regs->areg[4];
        size_t sigsetsize = (size_t) regs->areg[3];
@@ -96,7 +96,7 @@ sys_rt_sigsuspend(struct pt_regs *regs)
 }
 
 asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
+xtensa_sigaction(int sig, const struct old_sigaction *act,
              struct old_sigaction *oact)
 {
        struct k_sigaction new_ka, old_ka;
@@ -128,7 +128,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
 }
 
 asmlinkage int
-sys_sigaltstack(struct pt_regs *regs)
+xtensa_sigaltstack(struct pt_regs *regs)
 {
        const stack_t *uss = (stack_t *) regs->areg[4];
        stack_t *uoss = (stack_t *) regs->areg[3];
@@ -216,8 +216,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
         * handler, or the user mode value doesn't matter (e.g. PS.OWB).
         */
        err |= __get_user(ps, &sc->sc_ps);
-       regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK)
-               | (ps & XCHAL_PS_CALLINC_MASK);
+       regs->ps = (regs->ps & ~PS_CALLINC_MASK)
+               | (ps & PS_CALLINC_MASK);
 
        /* Additional corruption checks */
 
@@ -280,7 +280,7 @@ flush_my_cpstate(struct task_struct *tsk)
 static int
 save_cpextra (struct _cpstate *buf)
 {
-#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0)
+#if XCHAL_CP_NUM == 0
        return 0;
 #else
 
@@ -350,7 +350,7 @@ setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
        return err;
 }
 
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
+asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
 {
        struct sigframe *frame = (struct sigframe *)regs->areg[1];
        sigset_t set;
@@ -382,7 +382,7 @@ badframe:
        return 0;
 }
 
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
        sigset_t set;
@@ -497,8 +497,10 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
 
        /* Flush generated code out of the data cache */
 
-       if (err == 0)
-               __flush_invalidate_cache_range((unsigned long)codemem, 6UL);
+       if (err == 0) {
+               __invalidate_icache_range((unsigned long)codemem, 6UL);
+               __flush_invalidate_dcache_range((unsigned long)codemem, 6UL);
+       }
 
        return err;
 }
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
new file mode 100644 (file)
index 0000000..418268f
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * arch/xtensa/kernel/syscall.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.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+#include <asm/uaccess.h>
+#include <asm/syscalls.h>
+#include <asm/unistd.h>
+#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mman.h>
+#include <linux/shm.h>
+
+typedef void (*syscall_t)(void);
+
+syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
+       [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
+
+#undef __SYSCALL
+#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
+#undef _XTENSA_UNISTD_H
+#undef  __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
+};
+
+/*
+ * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
+ * the way unix traditional does this, though.
+ */
+
+asmlinkage long xtensa_pipe(int __user *userfds)
+{
+       int fd[2];
+       int error;
+
+       error = do_pipe(fd);
+       if (!error) {
+               if (copy_to_user(userfds, fd, 2 * sizeof(int)))
+                       error = -EFAULT;
+       }
+       return error;
+}
+
+
+asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len,
+                            unsigned long prot, unsigned long flags,
+                            unsigned long fd, unsigned long pgoff)
+{
+       int error = -EBADF;
+       struct file * file = NULL;
+
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       if (!(flags & MAP_ANONYMOUS)) {
+               file = fget(fd);
+               if (!file)
+                       goto out;
+       }
+
+       down_write(&current->mm->mmap_sem);
+       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up_write(&current->mm->mmap_sem);
+
+       if (file)
+               fput(file);
+out:
+       return error;
+}
+
+asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
+{
+       unsigned long ret;
+       long err;
+
+       err = do_shmat(shmid, shmaddr, shmflg, &ret);
+       if (err)
+               return err;
+       return (long)ret;
+}
+
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
deleted file mode 100644 (file)
index f49cb23..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * arch/xtensa/kernel/syscalls.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.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Copyright (C) 1995 - 2000 by Ralf Baechle
- *
- * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
- * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
- * Chris Zankel <chris@zankel.net>
- * Kevin Chea
- *
- */
-
-#define DEBUG  0
-
-#include <linux/linkage.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/mman.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/utsname.h>
-#include <linux/unistd.h>
-#include <linux/stringify.h>
-#include <linux/syscalls.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/errno.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
-#include <asm/mman.h>
-#include <asm/shmparam.h>
-#include <asm/page.h>
-
-extern void do_syscall_trace(void);
-typedef int (*syscall_t)(void *a0,...);
-extern syscall_t sys_call_table[];
-extern unsigned char sys_narg_table[];
-
-/*
- * sys_pipe() is the normal C calling standard for creating a pipe. It's not
- * the way unix traditional does this, though.
- */
-
-int sys_pipe(int __user *userfds)
-{
-       int fd[2];
-       int error;
-
-       error = do_pipe(fd);
-       if (!error) {
-               if (copy_to_user(userfds, fd, 2 * sizeof(int)))
-                       error = -EFAULT;
-       }
-       return error;
-}
-
-/*
- * Common code for old and new mmaps.
- */
-long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
-             unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
-       int error = -EBADF;
-       struct file * file = NULL;
-
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-       if (!(flags & MAP_ANONYMOUS)) {
-               file = fget(fd);
-               if (!file)
-                       goto out;
-       }
-
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-       up_write(&current->mm->mmap_sem);
-
-       if (file)
-               fput(file);
-out:
-       return error;
-}
-
-int sys_clone(struct pt_regs *regs)
-{
-       unsigned long clone_flags;
-       unsigned long newsp;
-       int __user *parent_tidptr, *child_tidptr;
-       clone_flags = regs->areg[4];
-       newsp = regs->areg[3];
-       parent_tidptr = (int __user *)regs->areg[5];
-       child_tidptr = (int __user *)regs->areg[6];
-       if (!newsp)
-               newsp = regs->areg[1];
-       return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-
-int sys_execve(struct pt_regs *regs)
-{
-       int error;
-       char * filename;
-
-       filename = getname((char *) (long)regs->areg[5]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename, (char **) (long)regs->areg[3],
-                         (char **) (long)regs->areg[4], regs);
-       putname(filename);
-
-out:
-       return error;
-}
-
-int sys_uname(struct old_utsname * name)
-{
-       if (name && !copy_to_user(name, utsname(), sizeof (*name)))
-               return 0;
-       return -EFAULT;
-}
-
-/*
- * Build the string table for the builtin "poor man's strace".
- */
-
-#if DEBUG
-#define SYSCALL(fun, narg) #fun,
-static char *sfnames[] = {
-#include "syscalls.h"
-};
-#undef SYS
-#endif
-
-void system_call (struct pt_regs *regs)
-{
-       syscall_t syscall;
-       unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
-       int nargs, res;
-       unsigned int syscallnr;
-       int ps;
-
-#if DEBUG
-       int i;
-       unsigned long parms[6];
-       char *sysname;
-#endif
-
-       regs->syscall = regs->areg[2];
-
-       do_syscall_trace();
-
-       /* Have to load after syscall_trace because strace
-        * sometimes changes regs->syscall.
-        */
-       syscallnr = regs->syscall;
-
-       parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
-
-       /* Restore interrupt level to syscall invoker's.
-        * If this were in assembly, we wouldn't disable
-        * interrupts in the first place:
-        */
-       local_save_flags (ps);
-       local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
-                         (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
-
-       if (syscallnr > __NR_Linux_syscalls) {
-               regs->areg[2] = -ENOSYS;
-               return;
-       }
-
-       syscall = sys_call_table[syscallnr];
-       nargs = sys_narg_table[syscallnr];
-
-       if (syscall == NULL) {
-               regs->areg[2] = -ENOSYS;
-               return;
-       }
-
-       /* There shouldn't be more than six arguments in the table! */
-
-       if (nargs > 6)
-               panic("Internal error - too many syscall arguments (%d)!\n",
-                     nargs);
-
-       /* Linux takes system-call arguments in registers.  The ABI
-         * and Xtensa software conventions require the system-call
-         * number in a2.  If an argument exists in a2, we move it to
-         * the next available register.  Note that for improved
-         * efficiency, we do NOT shift all parameters down one
-         * register to maintain the original order.
-        *
-         * At best case (zero arguments), we just write the syscall
-         * number to a2.  At worst case (1 to 6 arguments), we move
-         * the argument in a2 to the next available register, then
-         * write the syscall number to a2.
-        *
-         * For clarity, the following truth table enumerates all
-         * possibilities.
-        *
-         * arguments   syscall number  arg0, arg1, arg2, arg3, arg4, arg5
-         * ---------   --------------  ----------------------------------
-        *      0             a2
-        *      1             a2        a3
-        *      2             a2        a4,   a3
-        *      3             a2        a5,   a3,   a4
-        *      4             a2        a6,   a3,   a4,   a5
-        *      5             a2        a7,   a3,   a4,   a5,   a6
-        *      6             a2        a8,   a3,   a4,   a5,   a6,   a7
-        */
-       if (nargs) {
-               parm0 = regs->areg[nargs+2];
-               parm1 = regs->areg[3];
-               parm2 = regs->areg[4];
-               parm3 = regs->areg[5];
-               parm4 = regs->areg[6];
-               parm5 = regs->areg[7];
-       } else /* nargs == 0 */
-               parm0 = (unsigned long) regs;
-
-#if DEBUG
-       parms[0] = parm0;
-       parms[1] = parm1;
-       parms[2] = parm2;
-       parms[3] = parm3;
-       parms[4] = parm4;
-       parms[5] = parm5;
-
-       sysname = sfnames[syscallnr];
-       if (strncmp(sysname, "sys_", 4) == 0)
-               sysname = sysname + 4;
-
-       printk("\017SYSCALL:I:%x:%d:%s  %s(", regs->pc, current->pid,
-              current->comm, sysname);
-       for (i = 0; i < nargs; i++)
-               printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
-       printk(")\n");
-#endif
-
-       res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
-
-#if DEBUG
-       printk("\017SYSCALL:O:%d:%s  %s(",current->pid, current->comm, sysname);
-       for (i = 0; i < nargs; i++)
-               printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
-       if (res < 4096)
-               printk(") = %d\n", res);
-       else
-               printk(") = %#x\n", res);
-#endif /* DEBUG */
-
-       regs->areg[2] = res;
-       do_syscall_trace();
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
-       long __res;
-       asm volatile (
-               "  mov   a5, %2 \n"
-               "  mov   a4, %4 \n"
-               "  mov   a3, %3 \n"
-               "  movi  a2, %1 \n"
-               "  syscall      \n"
-               "  mov   %0, a2 \n"
-               : "=a" (__res)
-               : "i" (__NR_execve), "a" (filename), "a" (argv), "a" (envp)
-               : "a2", "a3", "a4", "a5");
-       return __res;
-}
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
deleted file mode 100644 (file)
index 216c10a..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * arch/xtensa/kernel/syscalls.h
- *
- * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- *
- * Changes by Joe Taylor <joe@tensilica.com>
- */
-
-/*
- * This file is being included twice - once to build a list of all
- * syscalls and once to build a table of how many arguments each syscall
- * accepts.  Syscalls that receive a pointer to the saved registers are
- * marked as having zero arguments.
- *
- * The binary compatibility calls are in a separate list.
- *
- * Entry '0' used to be system_call.  It's removed to disable indirect
- * system calls for now so user tasks can't recurse.  See mips'
- * sys_syscall for a comparable example.
- */
-
-SYSCALL(0, 0)                          /* 00 */
-SYSCALL(sys_exit, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_read, 3)
-SYSCALL(sys_write, 3)
-SYSCALL(sys_open, 3)                   /* 05 */
-SYSCALL(sys_close, 1)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_creat, 2)
-SYSCALL(sys_link, 2)
-SYSCALL(sys_unlink, 1)                 /* 10 */
-SYSCALL(sys_execve, 0)
-SYSCALL(sys_chdir, 1)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_mknod, 3)
-SYSCALL(sys_chmod, 2)                  /* 15 */
-SYSCALL(sys_lchown, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_newstat, 2)
-SYSCALL(sys_lseek, 3)
-SYSCALL(sys_getpid, 0)                 /* 20 */
-SYSCALL(sys_mount, 5)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_setuid, 1)
-SYSCALL(sys_getuid, 0)
-SYSCALL(sys_ni_syscall, 1)             /* 25 */
-SYSCALL(sys_ptrace, 4)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_newfstat, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_utime, 2)                  /* 30 */
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_access, 2)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_ni_syscall, 0)             /* 35 */
-SYSCALL(sys_sync, 0)
-SYSCALL(sys_kill, 2)
-SYSCALL(sys_rename, 2)
-SYSCALL(sys_mkdir, 2)
-SYSCALL(sys_rmdir, 1)                  /* 40 */
-SYSCALL(sys_dup, 1)
-SYSCALL(sys_pipe, 1)
-SYSCALL(sys_times, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_brk, 1)                    /* 45 */
-SYSCALL(sys_setgid, 1)
-SYSCALL(sys_getgid, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_geteuid, 0)
-SYSCALL(sys_getegid, 0)                        /* 50 */
-SYSCALL(sys_acct, 1)
-SYSCALL(sys_umount, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ioctl, 3)
-SYSCALL(sys_fcntl, 3)                  /* 55 */
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_setpgid, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_umask, 1)                  /* 60 */
-SYSCALL(sys_chroot, 1)
-SYSCALL(sys_ustat, 2)
-SYSCALL(sys_dup2, 2)
-SYSCALL(sys_getppid, 0)
-SYSCALL(sys_ni_syscall, 0)             /* 65 */
-SYSCALL(sys_setsid, 0)
-SYSCALL(sys_sigaction, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_setreuid, 2)               /* 70 */
-SYSCALL(sys_setregid, 2)
-SYSCALL(sys_sigsuspend, 0)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_sethostname, 2)
-SYSCALL(sys_setrlimit, 2)              /* 75 */
-SYSCALL(sys_getrlimit, 2)
-SYSCALL(sys_getrusage, 2)
-SYSCALL(sys_gettimeofday, 2)
-SYSCALL(sys_settimeofday, 2)
-SYSCALL(sys_getgroups, 2)              /* 80 */
-SYSCALL(sys_setgroups, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_symlink, 2)
-SYSCALL(sys_newlstat, 2)
-SYSCALL(sys_readlink, 3)               /* 85 */
-SYSCALL(sys_uselib, 1)
-SYSCALL(sys_swapon, 2)
-SYSCALL(sys_reboot, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 6)             /* 90 */
-SYSCALL(sys_munmap, 2)
-SYSCALL(sys_truncate, 2)
-SYSCALL(sys_ftruncate, 2)
-SYSCALL(sys_fchmod, 2)
-SYSCALL(sys_fchown, 3)                 /* 95 */
-SYSCALL(sys_getpriority, 2)
-SYSCALL(sys_setpriority, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_statfs, 2)
-SYSCALL(sys_fstatfs, 2)                        /* 100 */
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_syslog, 3)
-SYSCALL(sys_setitimer, 3)
-SYSCALL(sys_getitimer, 2)              /* 105 */
-SYSCALL(sys_newstat, 2)
-SYSCALL(sys_newlstat, 2)
-SYSCALL(sys_newfstat, 2)
-SYSCALL(sys_uname, 1)
-SYSCALL(sys_ni_syscall, 0)             /* 110 */
-SYSCALL(sys_vhangup, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_wait4, 4)
-SYSCALL(sys_swapoff, 1)                        /* 115 */
-SYSCALL(sys_sysinfo, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_fsync, 1)
-SYSCALL(sys_sigreturn, 0)
-SYSCALL(sys_clone, 0)                  /* 120 */
-SYSCALL(sys_setdomainname, 2)
-SYSCALL(sys_newuname, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_adjtimex, 1)
-SYSCALL(sys_mprotect, 3)               /* 125 */
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_init_module, 2)
-SYSCALL(sys_delete_module, 1)
-SYSCALL(sys_ni_syscall, 1)             /* 130 */
-SYSCALL(sys_quotactl, 0)
-SYSCALL(sys_getpgid, 1)
-SYSCALL(sys_fchdir, 1)
-SYSCALL(sys_bdflush, 2)
-SYSCALL(sys_sysfs, 3)                  /* 135 */
-SYSCALL(sys_personality, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_setfsuid, 1)
-SYSCALL(sys_setfsgid, 1)
-SYSCALL(sys_llseek, 5)                 /* 140 */
-SYSCALL(sys_getdents, 3)
-SYSCALL(sys_select, 5)
-SYSCALL(sys_flock, 2)
-SYSCALL(sys_msync, 3)
-SYSCALL(sys_readv, 3)                  /* 145 */
-SYSCALL(sys_writev, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 4)             /* handled in fast syscall handler. */
-SYSCALL(sys_ni_syscall, 0)             /* 150 */
-SYSCALL(sys_getsid, 1)
-SYSCALL(sys_fdatasync, 1)
-SYSCALL(sys_sysctl, 1)
-SYSCALL(sys_mlock, 2)
-SYSCALL(sys_munlock, 2)                        /* 155 */
-SYSCALL(sys_mlockall, 1)
-SYSCALL(sys_munlockall, 0)
-SYSCALL(sys_sched_setparam,2)
-SYSCALL(sys_sched_getparam,2)
-SYSCALL(sys_sched_setscheduler,3)      /* 160 */
-SYSCALL(sys_sched_getscheduler,1)
-SYSCALL(sys_sched_yield,0)
-SYSCALL(sys_sched_get_priority_max,1)
-SYSCALL(sys_sched_get_priority_min,1)
-SYSCALL(sys_sched_rr_get_interval,2)   /* 165 */
-SYSCALL(sys_nanosleep,2)
-SYSCALL(sys_mremap,4)
-SYSCALL(sys_accept, 3)
-SYSCALL(sys_bind, 3)
-SYSCALL(sys_connect, 3)                        /* 170 */
-SYSCALL(sys_getpeername, 3)
-SYSCALL(sys_getsockname, 3)
-SYSCALL(sys_getsockopt, 5)
-SYSCALL(sys_listen, 2)
-SYSCALL(sys_recv, 4)                   /* 175 */
-SYSCALL(sys_recvfrom, 6)
-SYSCALL(sys_recvmsg, 3)
-SYSCALL(sys_send, 4)
-SYSCALL(sys_sendmsg, 3)
-SYSCALL(sys_sendto, 6)                 /* 180 */
-SYSCALL(sys_setsockopt, 5)
-SYSCALL(sys_shutdown, 2)
-SYSCALL(sys_socket, 3)
-SYSCALL(sys_socketpair, 4)
-SYSCALL(sys_setresuid, 3)              /* 185 */
-SYSCALL(sys_getresuid, 3)
-SYSCALL(sys_ni_syscall, 5)
-SYSCALL(sys_poll, 3)
-SYSCALL(sys_nfsservctl, 3)
-SYSCALL(sys_setresgid, 3)              /* 190 */
-SYSCALL(sys_getresgid, 3)
-SYSCALL(sys_prctl, 5)
-SYSCALL(sys_rt_sigreturn, 0)
-SYSCALL(sys_rt_sigaction, 4)
-SYSCALL(sys_rt_sigprocmask, 4)         /* 195 */
-SYSCALL(sys_rt_sigpending, 2)
-SYSCALL(sys_rt_sigtimedwait, 4)
-SYSCALL(sys_rt_sigqueueinfo, 3)
-SYSCALL(sys_rt_sigsuspend, 0)
-SYSCALL(sys_pread64, 5)                        /* 200 */
-SYSCALL(sys_pwrite64, 5)
-SYSCALL(sys_chown, 3)
-SYSCALL(sys_getcwd, 2)
-SYSCALL(sys_capget, 2)
-SYSCALL(sys_capset, 2)                 /* 205 */
-SYSCALL(sys_sigaltstack, 0)
-SYSCALL(sys_sendfile, 4)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_mmap, 6)                   /* 210 */
-SYSCALL(sys_truncate64, 2)
-SYSCALL(sys_ftruncate64, 2)
-SYSCALL(sys_stat64, 2)
-SYSCALL(sys_lstat64, 2)
-SYSCALL(sys_fstat64, 2)                        /* 215 */
-SYSCALL(sys_pivot_root, 2)
-SYSCALL(sys_mincore, 3)
-SYSCALL(sys_madvise, 3)
-SYSCALL(sys_getdents64, 3)
-SYSCALL(sys_ni_syscall, 0)             /* 220 */
index 37347e3..a350431 100644 (file)
@@ -47,7 +47,7 @@ unsigned long long sched_clock(void)
        return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t timer_interrupt(int irq, void *dev_id);
 static struct irqaction timer_irqaction = {
        .handler =      timer_interrupt,
        .flags =        IRQF_DISABLED,
@@ -150,7 +150,7 @@ EXPORT_SYMBOL(do_gettimeofday);
  * The timer interrupt is called HZ times per second.
  */
 
-irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t timer_interrupt (int irq, void *dev_id)
 {
 
        unsigned long next;
@@ -160,9 +160,9 @@ irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 again:
        while ((signed long)(get_ccount() - next) > 0) {
 
-               profile_tick(CPU_PROFILING, regs);
+               profile_tick(CPU_PROFILING);
 #ifndef CONFIG_SMP
-               update_process_times(user_mode(regs));
+               update_process_times(user_mode(get_irq_regs()));
 #endif
 
                write_seqlock(&xtime_lock);
index ce077d6..693ab26 100644 (file)
@@ -75,7 +75,7 @@ extern void system_call (struct pt_regs*);
 #define USER           0x02
 
 #define COPROCESSOR(x)                                                 \
-{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
+{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
 
 typedef struct {
        int cause;
@@ -85,38 +85,38 @@ typedef struct {
 
 dispatch_init_table_t __init dispatch_init_table[] = {
 
-{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION,  0,         do_illegal_instruction},
-{ XCHAL_EXCCAUSE_SYSTEM_CALL,          KRNL,      fast_syscall_kernel },
-{ XCHAL_EXCCAUSE_SYSTEM_CALL,          USER,      fast_syscall_user },
-{ XCHAL_EXCCAUSE_SYSTEM_CALL,          0,         system_call },
-/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */
-/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/
-{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT,     0,         do_interrupt },
-{ XCHAL_EXCCAUSE_ALLOCA,               USER|KRNL, fast_alloca },
-/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
-/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */
+{ EXCCAUSE_ILLEGAL_INSTRUCTION,        0,         do_illegal_instruction},
+{ EXCCAUSE_SYSTEM_CALL,                KRNL,      fast_syscall_kernel },
+{ EXCCAUSE_SYSTEM_CALL,                USER,      fast_syscall_user },
+{ EXCCAUSE_SYSTEM_CALL,                0,         system_call },
+/* EXCCAUSE_INSTRUCTION_FETCH unhandled */
+/* EXCCAUSE_LOAD_STORE_ERROR unhandled*/
+{ EXCCAUSE_LEVEL1_INTERRUPT,   0,         do_interrupt },
+{ EXCCAUSE_ALLOCA,             USER|KRNL, fast_alloca },
+/* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
+/* EXCCAUSE_PRIVILEGED unhandled */
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 #ifdef CONFIG_UNALIGNED_USER
-{ XCHAL_EXCCAUSE_UNALIGNED,            USER,      fast_unaligned },
+{ EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
 #else
-{ XCHAL_EXCCAUSE_UNALIGNED,            0,         do_unaligned_user },
+{ EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
 #endif
-{ XCHAL_EXCCAUSE_UNALIGNED,            KRNL,      fast_unaligned },
+{ EXCCAUSE_UNALIGNED,          KRNL,      fast_unaligned },
 #endif
-{ XCHAL_EXCCAUSE_ITLB_MISS,            0,         do_page_fault },
-{ XCHAL_EXCCAUSE_ITLB_MISS,            USER|KRNL, fast_second_level_miss},
-{ XCHAL_EXCCAUSE_ITLB_MULTIHIT,                0,         do_multihit },
-{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE,       0,         do_page_fault },
-/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */
-{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE,        0,         do_page_fault },
-{ XCHAL_EXCCAUSE_DTLB_MISS,            USER|KRNL, fast_second_level_miss},
-{ XCHAL_EXCCAUSE_DTLB_MISS,            0,         do_page_fault },
-{ XCHAL_EXCCAUSE_DTLB_MULTIHIT,                0,         do_multihit },
-{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE,       0,         do_page_fault },
-/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
-{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE,        USER|KRNL, fast_store_prohibited },
-{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE,        0,         do_page_fault },
-{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0,         do_page_fault },
+{ EXCCAUSE_ITLB_MISS,          0,         do_page_fault },
+{ EXCCAUSE_ITLB_MISS,          USER|KRNL, fast_second_level_miss},
+{ EXCCAUSE_ITLB_MULTIHIT,              0,         do_multihit },
+{ EXCCAUSE_ITLB_PRIVILEGE,     0,         do_page_fault },
+/* EXCCAUSE_SIZE_RESTRICTION unhandled */
+{ EXCCAUSE_FETCH_CACHE_ATTRIBUTE,      0,         do_page_fault },
+{ EXCCAUSE_DTLB_MISS,          USER|KRNL, fast_second_level_miss},
+{ EXCCAUSE_DTLB_MISS,          0,         do_page_fault },
+{ EXCCAUSE_DTLB_MULTIHIT,              0,         do_multihit },
+{ EXCCAUSE_DTLB_PRIVILEGE,     0,         do_page_fault },
+/* EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
+{ EXCCAUSE_STORE_CACHE_ATTRIBUTE,      USER|KRNL, fast_store_prohibited },
+{ EXCCAUSE_STORE_CACHE_ATTRIBUTE,      0,         do_page_fault },
+{ EXCCAUSE_LOAD_CACHE_ATTRIBUTE,       0,         do_page_fault },
 /* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
 #if (XCHAL_CP_MASK & 1)
 COPROCESSOR(0),
index 0e74397..eb2d7bb 100644 (file)
@@ -53,6 +53,8 @@
 #include <asm/thread_info.h>
 #include <asm/processor.h>
 
+#define WINDOW_VECTORS_SIZE   0x180
+
 
 /*
  * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)
@@ -210,7 +212,7 @@ ENTRY(_DoubleExceptionVector)
        /* Check for kernel double exception (usually fatal). */
 
        rsr     a3, PS
-       _bbci.l a3, PS_UM_SHIFT, .Lksp
+       _bbci.l a3, PS_UM_BIT, .Lksp
 
        /* Check if we are currently handling a window exception. */
        /* Note: We don't need to indicate that we enter a critical section. */
@@ -219,7 +221,7 @@ ENTRY(_DoubleExceptionVector)
 
        movi    a3, XCHAL_WINDOW_VECTORS_VADDR
        _bltu   a0, a3, .Lfixup
-       addi    a3, a3, XSHAL_WINDOW_VECTORS_SIZE
+       addi    a3, a3, WINDOW_VECTORS_SIZE
        _bgeu   a0, a3, .Lfixup
 
        /* Window overflow/underflow exception. Get stack pointer. */
@@ -245,7 +247,7 @@ ENTRY(_DoubleExceptionVector)
 
        wsr     a2, DEPC                # save stack pointer temporarily
        rsr     a0, PS
-       extui   a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+       extui   a0, a0, PS_OWB_SHIFT, 4
        wsr     a0, WINDOWBASE
        rsync
 
@@ -312,8 +314,8 @@ ENTRY(_DoubleExceptionVector)
 .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
 
        rsr     a3, EXCCAUSE
-       beqi    a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f
-       addi    a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS
+       beqi    a3, EXCCAUSE_ITLB_MISS, 1f
+       addi    a3, a3, -EXCCAUSE_DTLB_MISS
        bnez    a3, .Lunrecoverable
 1:     movi    a3, fast_second_level_miss_double_kernel
        jx      a3
index cfe75f5..a36c104 100644 (file)
 
 #include <asm-generic/vmlinux.lds.h>
 
-#define _NOCLANGUAGE
-#include <xtensa/config/core.h>
-#include <xtensa/config/system.h>
+#include <asm/variant/core.h>
 OUTPUT_ARCH(xtensa)
 ENTRY(_start)
 
-#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN
+#ifdef __XTENSA_EB__
 jiffies = jiffies_64 + 4;
 #else
 jiffies = jiffies_64;
 #endif
 
-#define KERNELOFFSET 0x1000
+#define KERNELOFFSET 0xd0001000
 
 /* Note: In the following macros, it would be nice to specify only the
    vector name and section kind and construct "sym" and "section" using
@@ -75,7 +73,7 @@ jiffies = jiffies_64;
 
 SECTIONS
 {
-  . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET;
+  . = KERNELOFFSET;
   /* .text section */
 
   _text = .;
@@ -159,7 +157,7 @@ SECTIONS
 
   /* Initialization code and data: */
 
-  . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+  . = ALIGN(1 << 12);
   __init_begin = .;
   .init.text : {
        _sinittext = .;
@@ -223,32 +221,32 @@ SECTIONS
                  .dummy)
   SECTION_VECTOR (_DebugInterruptVector_literal,
                  .DebugInterruptVector.literal,
-                 XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) - 4,
+                 XCHAL_DEBUG_VECTOR_VADDR - 4,
                  SIZEOF(.WindowVectors.text),
                  .WindowVectors.text)
   SECTION_VECTOR (_DebugInterruptVector_text,
                  .DebugInterruptVector.text,
-                 XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL),
+                 XCHAL_DEBUG_VECTOR_VADDR,
                  4,
                  .DebugInterruptVector.literal)
   SECTION_VECTOR (_KernelExceptionVector_literal,
                  .KernelExceptionVector.literal,
-                 XCHAL_KERNELEXC_VECTOR_VADDR - 4,
+                 XCHAL_KERNEL_VECTOR_VADDR - 4,
                  SIZEOF(.DebugInterruptVector.text),
                  .DebugInterruptVector.text)
   SECTION_VECTOR (_KernelExceptionVector_text,
                  .KernelExceptionVector.text,
-                 XCHAL_KERNELEXC_VECTOR_VADDR,
+                 XCHAL_KERNEL_VECTOR_VADDR,
                  4,
                  .KernelExceptionVector.literal)
   SECTION_VECTOR (_UserExceptionVector_literal,
                  .UserExceptionVector.literal,
-                 XCHAL_USEREXC_VECTOR_VADDR - 4,
+                 XCHAL_USER_VECTOR_VADDR - 4,
                  SIZEOF(.KernelExceptionVector.text),
                  .KernelExceptionVector.text)
   SECTION_VECTOR (_UserExceptionVector_text,
                  .UserExceptionVector.text,
-                 XCHAL_USEREXC_VECTOR_VADDR,
+                 XCHAL_USER_VECTOR_VADDR,
                  4,
                  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
@@ -263,7 +261,7 @@ SECTIONS
                  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
-  . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+  . = ALIGN(1 << 12);
 
   __init_end = .;
 
index e2d64df..9d9cd99 100644 (file)
@@ -16,8 +16,7 @@
 
 #include <asm/errno.h>
 #include <linux/linkage.h>
-#define _ASMLANGUAGE
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
 /*
  * computes a partial checksum, e.g. for TCP/UDP fragments
index e8f6d7e..ddda8f4 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (C) 2002 - 2005 Tensilica Inc.
  */
 
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
 
        .macro  src_b   r, w0, w1
 #ifdef __XTENSA_EB__
index 4de2513..56a1749 100644 (file)
@@ -11,7 +11,7 @@
  *  Copyright (C) 2002 Tensilica Inc.
  */
 
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
 
 /*
  * void *memset(void *dst, int c, size_t length)
index 71d55df..a834057 100644 (file)
@@ -11,7 +11,7 @@
  *  Copyright (C) 2002 Tensilica Inc.
  */
 
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
 #include <linux/errno.h>
 
 /* Load or store instructions that may cause exceptions use the EX macro. */
index cdff4d6..5e9c1e7 100644 (file)
@@ -11,7 +11,7 @@
  *  Copyright (C) 2002 Tensilica Inc.
  */
 
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
 
 /* Load or store instructions that may cause exceptions use the EX macro. */
 
index 4641ef5..a8ab1d4 100644 (file)
@@ -53,7 +53,7 @@
  *     a11/ original length
  */
 
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
 
 #ifdef __XTENSA_EB__
 #define ALIGN(R, W0, W1) src   R, W0, W1
index dd0dbec..3dc6f2f 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/system.h>
 #include <asm/pgalloc.h>
 
-unsigned long asid_cache = ASID_FIRST_VERSION;
+unsigned long asid_cache = ASID_USER_FIRST;
 void bad_page_fault(struct pt_regs*, unsigned long, int);
 
 /*
@@ -58,10 +58,10 @@ void do_page_fault(struct pt_regs *regs)
                return;
        }
 
-       is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
-       is_exec =  (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE ||
-                   exccause == XCHAL_EXCCAUSE_ITLB_MISS ||
-                   exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
+       is_write = (exccause == EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
+       is_exec =  (exccause == EXCCAUSE_ITLB_PRIVILEGE ||
+                   exccause == EXCCAUSE_ITLB_MISS ||
+                   exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
 
 #if 0
        printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
index 660ef05..e1ec2d1 100644 (file)
@@ -141,8 +141,8 @@ void __init bootmem_init(void)
        if (min_low_pfn > max_pfn)
                panic("No memory found!\n");
 
-       max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ?
-               max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT;
+       max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ?
+               max_pfn : MAX_MEM_PFN >> PAGE_SHIFT;
 
        /* Find an area to use for the bootmem bitmap. */
 
@@ -215,7 +215,7 @@ void __init init_mmu (void)
 
        /* Set rasid register to a known value. */
 
-       set_rasid_register (ASID_ALL_RESERVED);
+       set_rasid_register (ASID_USER_FIRST);
 
        /* Set PTEVADDR special register to the start of the page
         * table, which is in kernel mappable space (ie. not
index 327c0f1..ae08533 100644 (file)
@@ -19,9 +19,8 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-
-#include <xtensa/cacheasm.h>
-#include <xtensa/cacheattrasm.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
 
 /* clear_page (page) */
 
@@ -74,104 +73,66 @@ ENTRY(copy_page)
 
        retw
 
-
 /*
- * void __flush_invalidate_cache_all(void)
+ * void __invalidate_icache_page(ulong start)
  */
 
-ENTRY(__flush_invalidate_cache_all)
+ENTRY(__invalidate_icache_page)
        entry   sp, 16
-       dcache_writeback_inv_all a2, a3
-       icache_invalidate_all a2, a3
-       retw
 
-/*
- * void __invalidate_icache_all(void)
- */
+       ___invalidate_icache_page a2 a3
+       isync
 
-ENTRY(__invalidate_icache_all)
-       entry   sp, 16
-       icache_invalidate_all a2, a3
        retw
 
 /*
- * void __flush_invalidate_dcache_all(void)
+ * void __invalidate_dcache_page(ulong start)
  */
 
-ENTRY(__flush_invalidate_dcache_all)
+ENTRY(__invalidate_dcache_page)
        entry   sp, 16
-       dcache_writeback_inv_all a2, a3
-       retw
-
 
-/*
- * void __flush_invalidate_cache_range(ulong start, ulong size)
- */
+       ___invalidate_dcache_page a2 a3
+       dsync
 
-ENTRY(__flush_invalidate_cache_range)
-       entry   sp, 16
-       mov     a4, a2
-       mov     a5, a3
-       dcache_writeback_inv_region a4, a5, a6
-       icache_invalidate_region a2, a3, a4
        retw
 
 /*
- * void __invalidate_icache_page(ulong start)
+ * void __flush_invalidate_dcache_page(ulong start)
  */
 
-ENTRY(__invalidate_icache_page)
+ENTRY(__flush_invalidate_dcache_page)
        entry   sp, 16
-       movi    a3, PAGE_SIZE
-       icache_invalidate_region a2, a3, a4
-       retw
 
-/*
- * void __invalidate_dcache_page(ulong start)
- */
+       ___flush_invalidate_dcache_page a2 a3
 
-ENTRY(__invalidate_dcache_page)
-       entry   sp, 16
-       movi    a3, PAGE_SIZE
-       dcache_invalidate_region a2, a3, a4
+       dsync
        retw
 
 /*
- * void __invalidate_icache_range(ulong start, ulong size)
+ * void __flush_dcache_page(ulong start)
  */
 
-ENTRY(__invalidate_icache_range)
+ENTRY(__flush_dcache_page)
        entry   sp, 16
-       icache_invalidate_region a2, a3, a4
-       retw
 
-/*
- * void __invalidate_dcache_range(ulong start, ulong size)
- */
+       ___flush_dcache_page a2 a3
 
-ENTRY(__invalidate_dcache_range)
-       entry   sp, 16
-       dcache_invalidate_region a2, a3, a4
+       dsync
        retw
 
-/*
- * void __flush_dcache_page(ulong start)
- */
 
-ENTRY(__flush_dcache_page)
-       entry   sp, 16
-       movi    a3, PAGE_SIZE
-       dcache_writeback_region a2, a3, a4
-       retw
 
 /*
- * void __flush_invalidate_dcache_page(ulong start)
+ * void __invalidate_icache_range(ulong start, ulong size)
  */
 
-ENTRY(__flush_invalidate_dcache_page)
+ENTRY(__invalidate_icache_range)
        entry   sp, 16
-       movi    a3, PAGE_SIZE
-       dcache_writeback_inv_region a2, a3, a4
+
+       ___invalidate_icache_range a2 a3 a4
+       isync
+
        retw
 
 /*
@@ -180,195 +141,69 @@ ENTRY(__flush_invalidate_dcache_page)
 
 ENTRY(__flush_invalidate_dcache_range)
        entry   sp, 16
-       dcache_writeback_inv_region a2, a3, a4
-       retw
 
-/*
- * void __invalidate_dcache_all(void)
- */
+       ___flush_invalidate_dcache_range a2 a3 a4
+       dsync
 
-ENTRY(__invalidate_dcache_all)
-       entry   sp, 16
-       dcache_invalidate_all a2, a3
        retw
 
 /*
- * void __flush_invalidate_dcache_page_phys(ulong start)
+ * void _flush_dcache_range(ulong start, ulong size)
  */
 
-ENTRY(__flush_invalidate_dcache_page_phys)
+ENTRY(__flush_dcache_range)
        entry   sp, 16
 
-       movi    a3, XCHAL_DCACHE_SIZE
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
-
-1:     addi    a3, a3, -XCHAL_DCACHE_LINESIZE
-
-       ldct    a6, a3
+       ___flush_dcache_range a2 a3 a4
        dsync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a3, 2, 1b
-       retw
 
-2:     diwbi   a3, 0
-       bgeui   a3, 2, 1b
        retw
 
-ENTRY(check_dcache_low0)
-       entry   sp, 16
-
-       movi    a3, XCHAL_DCACHE_SIZE / 4
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
-
-1:     addi    a3, a3, -XCHAL_DCACHE_LINESIZE
-
-       ldct    a6, a3
-       dsync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a3, 2, 1b
-       retw
-
-2:     j 2b
-
-ENTRY(check_dcache_high0)
-       entry   sp, 16
-
-       movi    a5, XCHAL_DCACHE_SIZE / 4
-       movi    a3, XCHAL_DCACHE_SIZE / 2
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
-
-1:     addi    a3, a3, -XCHAL_DCACHE_LINESIZE
-       addi    a5, a5, -XCHAL_DCACHE_LINESIZE
-
-       ldct    a6, a3
-       dsync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a5, 2, 1b
-       retw
-
-2:     j 2b
+/*
+ * void _invalidate_dcache_range(ulong start, ulong size)
+ */
 
-ENTRY(check_dcache_low1)
+ENTRY(__invalidate_dcache_range)
        entry   sp, 16
 
-       movi    a5, XCHAL_DCACHE_SIZE / 4
-       movi    a3, XCHAL_DCACHE_SIZE * 3 / 4
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
+       ___invalidate_dcache_range a2 a3 a4
 
-1:     addi    a3, a3, -XCHAL_DCACHE_LINESIZE
-       addi    a5, a5, -XCHAL_DCACHE_LINESIZE
 
-       ldct    a6, a3
-       dsync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a5, 2, 1b
        retw
 
-2:     j 2b
+/*
+ * void _invalidate_icache_all(void)
+ */
 
-ENTRY(check_dcache_high1)
+ENTRY(__invalidate_icache_all)
        entry   sp, 16
 
-       movi    a5, XCHAL_DCACHE_SIZE / 4
-       movi    a3, XCHAL_DCACHE_SIZE
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
-
-1:     addi    a3, a3, -XCHAL_DCACHE_LINESIZE
-       addi    a5, a5, -XCHAL_DCACHE_LINESIZE
+       ___invalidate_icache_all a2 a3
+       isync
 
-       ldct    a6, a3
-       dsync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a5, 2, 1b
        retw
 
-2:     j 2b
-
-
 /*
- * void __invalidate_icache_page_phys(ulong start)
+ * void _flush_invalidate_dcache_all(void)
  */
 
-ENTRY(__invalidate_icache_page_phys)
+ENTRY(__flush_invalidate_dcache_all)
        entry   sp, 16
 
-       movi    a3, XCHAL_ICACHE_SIZE
-       movi    a4, PAGE_MASK | 1
-       addi    a2, a2, 1
-
-1:     addi    a3, a3, -XCHAL_ICACHE_LINESIZE
-
-       lict    a6, a3
-       isync
-       and     a6, a6, a4
-       beq     a6, a2, 2f
-       bgeui   a3, 2, 1b
-       retw
+       ___flush_invalidate_dcache_all a2 a3
+       dsync
 
-2:     iii     a3, 0
-       bgeui   a3, 2, 1b
        retw
 
+/*
+ * void _invalidate_dcache_all(void)
+ */
 
-#if 0
-
-       movi    a3, XCHAL_DCACHE_WAYS - 1
-       movi    a4, PAGE_SIZE
-
-1:     mov     a5, a2
-       add     a6, a2, a4
-
-2:     diwbi   a5, 0
-       diwbi   a5, XCHAL_DCACHE_LINESIZE
-       diwbi   a5, XCHAL_DCACHE_LINESIZE * 2
-       diwbi   a5, XCHAL_DCACHE_LINESIZE * 3
-
-       addi    a5, a5, XCHAL_DCACHE_LINESIZE * 4
-       blt     a5, a6, 2b
-
-       addi    a3, a3, -1
-       addi    a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS
-       bgez    a3, 1b
-
-       retw
-
-ENTRY(__invalidate_icache_page_index)
+ENTRY(__invalidate_dcache_all)
        entry   sp, 16
 
-       movi    a3, XCHAL_ICACHE_WAYS - 1
-       movi    a4, PAGE_SIZE
-
-1:     mov     a5, a2
-       add     a6, a2, a4
-
-2:     iii     a5, 0
-       iii     a5, XCHAL_ICACHE_LINESIZE
-       iii     a5, XCHAL_ICACHE_LINESIZE * 2
-       iii     a5, XCHAL_ICACHE_LINESIZE * 3
-
-       addi    a5, a5, XCHAL_ICACHE_LINESIZE * 4
-       blt     a5, a6, 2b
-
-       addi    a3, a3, -1
-       addi    a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS
-       bgez    a3, 2b
+       ___invalidate_dcache_all a2 a3
+       dsync
 
        retw
 
-#endif
-
-
-
-
-
-
index 0fefb86..239461d 100644 (file)
 
 static inline void __flush_itlb_all (void)
 {
-       int way, index;
+       int w, i;
 
-       for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) {
-               for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) {
-                       int entry = way + (index << PAGE_SHIFT);
-                       invalidate_itlb_entry_no_isync (entry);
+       for (w = 0; w < ITLB_ARF_WAYS; w++) {
+               for (i = 0; i < (1 << XCHAL_ITLB_ARF_ENTRIES_LOG2); i++) {
+                       int e = w + (i << PAGE_SHIFT);
+                       invalidate_itlb_entry_no_isync(e);
                }
        }
        asm volatile ("isync\n");
@@ -37,12 +37,12 @@ static inline void __flush_itlb_all (void)
 
 static inline void __flush_dtlb_all (void)
 {
-       int way, index;
+       int w, i;
 
-       for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) {
-               for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) {
-                       int entry = way + (index << PAGE_SHIFT);
-                       invalidate_dtlb_entry_no_isync (entry);
+       for (w = 0; w < DTLB_ARF_WAYS; w++) {
+               for (i = 0; i < (1 << XCHAL_DTLB_ARF_ENTRIES_LOG2); i++) {
+                       int e = w + (i << PAGE_SHIFT);
+                       invalidate_dtlb_entry_no_isync(e);
                }
        }
        asm volatile ("isync\n");
@@ -63,21 +63,25 @@ void flush_tlb_all (void)
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
-#if 0
-       printk("[tlbmm<%lx>]\n", (unsigned long)mm->context);
-#endif
-
        if (mm == current->active_mm) {
                int flags;
                local_save_flags(flags);
-               get_new_mmu_context(mm, asid_cache);
-               set_rasid_register(ASID_INSERT(mm->context));
+               __get_new_mmu_context(mm);
+               __load_mmu_context(mm);
                local_irq_restore(flags);
        }
        else
                mm->context = 0;
 }
 
+#define _ITLB_ENTRIES (ITLB_ARF_WAYS << XCHAL_ITLB_ARF_ENTRIES_LOG2)
+#define _DTLB_ENTRIES (DTLB_ARF_WAYS << XCHAL_DTLB_ARF_ENTRIES_LOG2)
+#if _ITLB_ENTRIES > _DTLB_ENTRIES
+# define _TLB_ENTRIES _ITLB_ENTRIES
+#else
+# define _TLB_ENTRIES _DTLB_ENTRIES
+#endif
+
 void flush_tlb_range (struct vm_area_struct *vma,
                      unsigned long start, unsigned long end)
 {
@@ -93,7 +97,7 @@ void flush_tlb_range (struct vm_area_struct *vma,
 #endif
        local_save_flags(flags);
 
-       if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) {
+       if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) {
                int oldpid = get_rasid_register();
                set_rasid_register (ASID_INSERT(mm->context));
                start &= PAGE_MASK;
@@ -111,9 +115,7 @@ void flush_tlb_range (struct vm_area_struct *vma,
 
                set_rasid_register(oldpid);
        } else {
-               get_new_mmu_context(mm, asid_cache);
-               if (mm == current->active_mm)
-                       set_rasid_register(ASID_INSERT(mm->context));
+               flush_tlb_mm(mm);
        }
        local_irq_restore(flags);
 }
@@ -123,10 +125,6 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
        struct mm_struct* mm = vma->vm_mm;
        unsigned long flags;
        int oldpid;
-#if 0
-       printk("[tlbpage<%02lx,%08lx>]\n",
-                       (unsigned long)mm->context, page);
-#endif
 
        if(mm->context == NO_CONTEXT)
                return;
@@ -142,404 +140,5 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
        set_rasid_register(oldpid);
 
        local_irq_restore(flags);
-
-#if 0
-       flush_tlb_all();
-       return;
-#endif
-}
-
-
-#ifdef DEBUG_TLB
-
-#define USE_ITLB  0
-#define USE_DTLB  1
-
-struct way_config_t {
-       int indicies;
-       int indicies_log2;
-       int pgsz_log2;
-       int arf;
-};
-
-static struct way_config_t itlb[XCHAL_ITLB_WAYS] =
-{
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF)
-       },
-       { XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN),
-         XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF)
-       }
-};
-
-static struct way_config_t dtlb[XCHAL_DTLB_WAYS] =
-{
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF)
-       },
-       { XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN),
-         XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF)
-       }
-};
-
-/*  Total number of entries:  */
-#define ITLB_TOTAL_ENTRIES     \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \
-               XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES)
-#define DTLB_TOTAL_ENTRIES     \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \
-               XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES)
-
-
-typedef struct {
-    unsigned           va;
-    unsigned           pa;
-    unsigned char      asid;
-    unsigned char      ca;
-    unsigned char      way;
-    unsigned char      index;
-    unsigned char      pgsz_log2;      /* 0 .. 32 */
-    unsigned char      type;           /* 0=ITLB 1=DTLB */
-} tlb_dump_entry_t;
-
-/*  Return -1 if a precedes b, +1 if a follows b, 0 if same:  */
-int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b )
-{
-    if (a->asid < b->asid) return -1;
-    if (a->asid > b->asid) return  1;
-    if (a->va < b->va) return -1;
-    if (a->va > b->va) return  1;
-    if (a->pa < b->pa) return -1;
-    if (a->pa > b->pa) return  1;
-    if (a->ca < b->ca) return -1;
-    if (a->ca > b->ca) return  1;
-    if (a->way < b->way) return -1;
-    if (a->way > b->way) return  1;
-    if (a->index < b->index) return -1;
-    if (a->index > b->index) return  1;
-    return 0;
-}
-
-void sort_tlb_dump_info( tlb_dump_entry_t *t, int n )
-{
-    int i, j;
-    /*  Simple O(n*n) sort:  */
-    for (i = 0; i < n-1; i++)
-       for (j = i+1; j < n; j++)
-           if (cmp_tlb_dump_info(t+i, t+j) > 0) {
-               tlb_dump_entry_t tmp = t[i];
-               t[i] = t[j];
-               t[j] = tmp;
-           }
-}
-
-
-static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES];
-static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES];
-
-
-static inline char *way_type (int type)
-{
-       return type ? "autorefill" : "non-autorefill";
-}
-
-void print_entry (struct way_config_t *way_info,
-                 unsigned int way,
-                 unsigned int index,
-                 unsigned int virtual,
-                 unsigned int translation)
-{
-       char valid_chr;
-       unsigned int va, pa, asid, ca;
-
-       va = virtual &
-               ~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1);
-       asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1);
-       pa = translation & ~((1 << way_info->pgsz_log2) - 1);
-       ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1);
-       valid_chr = asid ? 'V' : 'I';
-
-       /* Compute and incorporate the effect of the index bits on the
-        * va.  It's more useful for kernel debugging, since we always
-        * want to know the effective va anyway. */
-
-       va += index << way_info->pgsz_log2;
-
-       printk ("\t[%d,%d] (%c) vpn 0x%.8x  ppn 0x%.8x  asid 0x%.2x  am 0x%x\n",
-               way, index, valid_chr, va, pa, asid, ca);
-}
-
-void print_itlb_entry (struct way_config_t *way_info, int way, int index)
-{
-       print_entry (way_info, way, index,
-                    read_itlb_virtual (way + (index << way_info->pgsz_log2)),
-                    read_itlb_translation (way + (index << way_info->pgsz_log2)));
-}
-
-void print_dtlb_entry (struct way_config_t *way_info, int way, int index)
-{
-       print_entry (way_info, way, index,
-                    read_dtlb_virtual (way + (index << way_info->pgsz_log2)),
-                    read_dtlb_translation (way + (index << way_info->pgsz_log2)));
-}
-
-void dump_itlb (void)
-{
-       int way, index;
-
-       printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS);
-
-       for (way = 0; way < XCHAL_ITLB_WAYS; way++) {
-               printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
-                       way, itlb[way].indicies,
-                       itlb[way].pgsz_log2, way_type(itlb[way].arf));
-               for (index = 0; index < itlb[way].indicies; index++) {
-                       print_itlb_entry(&itlb[way], way, index);
-               }
-       }
-}
-
-void dump_dtlb (void)
-{
-       int way, index;
-
-       printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS);
-
-       for (way = 0; way < XCHAL_DTLB_WAYS; way++) {
-               printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
-                       way, dtlb[way].indicies,
-                       dtlb[way].pgsz_log2, way_type(dtlb[way].arf));
-               for (index = 0; index < dtlb[way].indicies; index++) {
-                       print_dtlb_entry(&dtlb[way], way, index);
-               }
-       }
-}
-
-void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config,
-               int entries, int ways, int type, int show_invalid)
-{
-    tlb_dump_entry_t *e = tinfo;
-    int way, i;
-
-    /*  Gather all info:  */
-    for (way = 0; way < ways; way++) {
-       struct way_config_t *cfg = config + way;
-       for (i = 0; i < cfg->indicies; i++) {
-           unsigned wayindex = way + (i << cfg->pgsz_log2);
-           unsigned vv = (type ? read_dtlb_virtual (wayindex)
-                               : read_itlb_virtual (wayindex));
-           unsigned pp = (type ? read_dtlb_translation (wayindex)
-                               : read_itlb_translation (wayindex));
-
-           /* Compute and incorporate the effect of the index bits on the
-            * va.  It's more useful for kernel debugging, since we always
-            * want to know the effective va anyway. */
-
-           e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1));
-           e->va += (i << cfg->pgsz_log2);
-           e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1));
-           e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1));
-           e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1));
-           e->way = way;
-           e->index = i;
-           e->pgsz_log2 = cfg->pgsz_log2;
-           e->type = type;
-           e++;
-       }
-    }
-#if 1
-    /*  Sort by ASID and VADDR:  */
-    sort_tlb_dump_info (tinfo, entries);
-#endif
-
-    /*  Display all sorted info:  */
-    printk ("\n%cTLB dump:\n", (type ? 'D' : 'I'));
-    for (e = tinfo, i = 0; i < entries; i++, e++) {
-#if 0
-       if (e->asid == 0 && !show_invalid)
-           continue;
-#endif
-       printk ("%c way=%d i=%d  ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n",
-               (e->type ? 'D' : 'I'), e->way, e->index,
-               e->asid, e->va, e->pa, e->ca,
-               (1 << (e->pgsz_log2 % 10)),
-               " kMG"[e->pgsz_log2 / 10]
-               );
-    }
-}
-
-void dump_tlbs2 (int showinv)
-{
-    dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv);
-    dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv);
-}
-
-void dump_all_tlbs (void)
-{
-    dump_tlbs2 (1);
-}
-
-void dump_valid_tlbs (void)
-{
-    dump_tlbs2 (0);
 }
 
-
-void dump_tlbs (void)
-{
-       dump_itlb();
-       dump_dtlb();
-}
-
-void dump_cache_tag(int dcache, int idx)
-{
-       int w, i, s, e;
-       unsigned long tag, index;
-       unsigned long num_lines, num_ways, cache_size, line_size;
-
-       num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS;
-       cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE;
-       line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE;
-
-       num_lines = cache_size / num_ways;
-
-       s = 0; e = num_lines;
-
-       if (idx >= 0)
-               e = (s = idx * line_size) + 1;
-
-       for (i = s; i < e; i+= line_size) {
-               printk("\nline %#08x:", i);
-               for (w = 0; w < num_ways; w++) {
-                       index = w * num_lines + i;
-                       if (dcache)
-                               __asm__ __volatile__("ldct %0, %1\n\t"
-                                               : "=a"(tag) : "a"(index));
-                       else
-                               __asm__ __volatile__("lict %0, %1\n\t"
-                                               : "=a"(tag) : "a"(index));
-
-                       printk(" %#010lx", tag);
-               }
-       }
-       printk ("\n");
-}
-
-void dump_icache(int index)
-{
-       unsigned long data, addr;
-       int w, i;
-
-       const unsigned long num_ways = XCHAL_ICACHE_WAYS;
-       const unsigned long cache_size = XCHAL_ICACHE_SIZE;
-       const unsigned long line_size = XCHAL_ICACHE_LINESIZE;
-       const unsigned long num_lines = cache_size / num_ways / line_size;
-
-       for (w = 0; w < num_ways; w++) {
-               printk ("\nWay %d", w);
-
-               for (i = 0; i < line_size; i+= 4) {
-                       addr = w * num_lines + index * line_size + i;
-                       __asm__ __volatile__("licw %0, %1\n\t"
-                                       : "=a"(data) : "a"(addr));
-                       printk(" %#010lx", data);
-               }
-       }
-       printk ("\n");
-}
-
-void dump_cache_tags(void)
-{
-       printk("Instruction cache\n");
-       dump_cache_tag(0, -1);
-       printk("Data cache\n");
-       dump_cache_tag(1, -1);
-}
-
-#endif
index 5c947ca..2f4f20f 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 
-#include <xtensa/simcall.h>
+#include <asm/platform/simcall.h>
 
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
 #define SERIAL_MAX_NUM_LINES 1
 #define SERIAL_TIMER_VALUE (20 * HZ)
 
@@ -191,7 +195,7 @@ static int rs_read_proc(char *page, char **start, off_t off, int count,
 }
 
 
-static const struct tty_operations serial_ops = {
+static struct tty_operations serial_ops = {
        .open = rs_open,
        .close = rs_close,
        .write = rs_write,
index 15d6441..8ebfc87 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/timer.h>
 #include <linux/platform_device.h>
 
-#include <xtensa/simcall.h>
+#include <asm/platform/simcall.h>
 
 #define DRIVER_NAME "iss-netdev"
 #define ETH_MAX_PACKET 1500
index 0024211..5934c4b 100644 (file)
@@ -1274,9 +1274,10 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
  *
  * FIXME! dispatch queue is not a queue at all!
  */
-static void as_work_handler(void *data)
+static void as_work_handler(struct work_struct *work)
 {
-       struct request_queue *q = data;
+       struct as_data *ad = container_of(work, struct as_data, antic_work);
+       struct request_queue *q = ad->q;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
@@ -1332,7 +1333,7 @@ static void *as_init_queue(request_queue_t *q)
        ad->antic_timer.function = as_antic_timeout;
        ad->antic_timer.data = (unsigned long)q;
        init_timer(&ad->antic_timer);
-       INIT_WORK(&ad->antic_work, as_work_handler, q);
+       INIT_WORK(&ad->antic_work, as_work_handler);
 
        INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
        INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
index 74e02c0..d3679dd 100644 (file)
@@ -394,8 +394,7 @@ err:
        if (bt) {
                if (bt->dropped_file)
                        debugfs_remove(bt->dropped_file);
-               if (bt->sequence)
-                       free_percpu(bt->sequence);
+               free_percpu(bt->sequence);
                if (bt->rchan)
                        relay_close(bt->rchan);
                kfree(bt);
index e9019ed..78c6b31 100644 (file)
@@ -43,8 +43,8 @@ static int cfq_slice_idle = HZ / 125;
 #define RQ_CIC(rq)             ((struct cfq_io_context*)(rq)->elevator_private)
 #define RQ_CFQQ(rq)            ((rq)->elevator_private2)
 
-static kmem_cache_t *cfq_pool;
-static kmem_cache_t *cfq_ioc_pool;
+static struct kmem_cache *cfq_pool;
+static struct kmem_cache *cfq_ioc_pool;
 
 static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
@@ -1840,9 +1840,11 @@ queue_fail:
        return 1;
 }
 
-static void cfq_kick_queue(void *data)
+static void cfq_kick_queue(struct work_struct *work)
 {
-       request_queue_t *q = data;
+       struct cfq_data *cfqd =
+               container_of(work, struct cfq_data, unplug_work);
+       request_queue_t *q = cfqd->queue;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
@@ -1986,7 +1988,7 @@ static void *cfq_init_queue(request_queue_t *q)
        cfqd->idle_class_timer.function = cfq_idle_class_timer;
        cfqd->idle_class_timer.data = (unsigned long) cfqd;
 
-       INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
+       INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
 
        cfqd->cfq_quantum = cfq_quantum;
        cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
index 653919d..457fdac 100644 (file)
@@ -417,6 +417,34 @@ static struct disk_attribute disk_attr_stat = {
        .show   = disk_stats_read
 };
 
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static ssize_t disk_fail_store(struct gendisk * disk,
+                              const char *buf, size_t count)
+{
+       int i;
+
+       if (count > 0 && sscanf(buf, "%d", &i) > 0) {
+               if (i == 0)
+                       disk->flags &= ~GENHD_FL_FAIL;
+               else
+                       disk->flags |= GENHD_FL_FAIL;
+       }
+
+       return count;
+}
+static ssize_t disk_fail_read(struct gendisk * disk, char *page)
+{
+       return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
+}
+static struct disk_attribute disk_attr_fail = {
+       .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
+       .store  = disk_fail_store,
+       .show   = disk_fail_read
+};
+
+#endif
+
 static struct attribute * default_attrs[] = {
        &disk_attr_uevent.attr,
        &disk_attr_dev.attr,
@@ -424,6 +452,9 @@ static struct attribute * default_attrs[] = {
        &disk_attr_removable.attr,
        &disk_attr_size.attr,
        &disk_attr_stat.attr,
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+       &disk_attr_fail.attr,
+#endif
        NULL,
 };
 
index 58aab63..f6962b6 100644 (file)
@@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        bdevp = bdget_disk(disk, part);
                        if (!bdevp)
                                return -ENOMEM;
-                       mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION);
+                       mutex_lock(&bdevp->bd_mutex);
                        if (bdevp->bd_openers) {
                                mutex_unlock(&bdevp->bd_mutex);
                                bdput(bdevp);
@@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                        fsync_bdev(bdevp);
                        invalidate_bdev(bdevp, 0);
 
-                       mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE);
+                       mutex_lock(&bdev->bd_mutex);
                        delete_partition(disk, part);
                        mutex_unlock(&bdev->bd_mutex);
                        mutex_unlock(&bdevp->bd_mutex);
@@ -290,7 +290,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
    ENOIOCTLCMD for unknown ioctls. */
 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
-       struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+       struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
        struct gendisk *disk = bdev->bd_disk;
        int ret = -ENOIOCTLCMD;
        if (disk->fops->compat_ioctl) {
index 0f82e12..a541b42 100644 (file)
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
 #include <linux/blktrace_api.h>
+#include <linux/fault-inject.h>
 
 /*
  * for max sense size
  */
 #include <scsi/scsi_cmnd.h>
 
-static void blk_unplug_work(void *data);
+static void blk_unplug_work(struct work_struct *work);
 static void blk_unplug_timeout(unsigned long data);
 static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
 static void init_request_from_bio(struct request *req, struct bio *bio);
@@ -44,17 +46,17 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node);
 /*
  * For the allocated request tables
  */
-static kmem_cache_t *request_cachep;
+static struct kmem_cache *request_cachep;
 
 /*
  * For queue allocation
  */
-static kmem_cache_t *requestq_cachep;
+static struct kmem_cache *requestq_cachep;
 
 /*
  * For io context allocations
  */
-static kmem_cache_t *iocontext_cachep;
+static struct kmem_cache *iocontext_cachep;
 
 /*
  * Controlling structure to kblockd
@@ -127,13 +129,6 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
 }
 EXPORT_SYMBOL(blk_get_backing_dev_info);
 
-void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
-{
-       q->activity_fn = fn;
-       q->activity_data = data;
-}
-EXPORT_SYMBOL(blk_queue_activity_fn);
-
 /**
  * blk_queue_prep_rq - set a prepare_request function for queue
  * @q:         queue
@@ -227,7 +222,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
        if (q->unplug_delay == 0)
                q->unplug_delay = 1;
 
-       INIT_WORK(&q->unplug_work, blk_unplug_work, q);
+       INIT_WORK(&q->unplug_work, blk_unplug_work);
 
        q->unplug_timer.function = blk_unplug_timeout;
        q->unplug_timer.data = (unsigned long)q;
@@ -236,8 +231,6 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
         * by default assume old behaviour and bounce for any highmem page
         */
        blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-
-       blk_queue_activity_fn(q, NULL, NULL);
 }
 
 EXPORT_SYMBOL(blk_queue_make_request);
@@ -1631,9 +1624,9 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi,
        }
 }
 
-static void blk_unplug_work(void *data)
+static void blk_unplug_work(struct work_struct *work)
 {
-       request_queue_t *q = data;
+       request_queue_t *q = container_of(work, request_queue_t, unplug_work);
 
        blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL,
                                q->rq.count[READ] + q->rq.count[WRITE]);
@@ -2694,9 +2687,6 @@ static inline void add_request(request_queue_t * q, struct request * req)
 {
        drive_stat_acct(req, req->nr_sectors, 1);
 
-       if (q->activity_fn)
-               q->activity_fn(q->activity_data, rq_data_dir(req));
-
        /*
         * elevator indicated where it wants this request to be
         * inserted at elevator_merge time
@@ -3056,6 +3046,42 @@ static void handle_bad_sector(struct bio *bio)
        set_bit(BIO_EOF, &bio->bi_flags);
 }
 
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static DECLARE_FAULT_ATTR(fail_make_request);
+
+static int __init setup_fail_make_request(char *str)
+{
+       return setup_fault_attr(&fail_make_request, str);
+}
+__setup("fail_make_request=", setup_fail_make_request);
+
+static int should_fail_request(struct bio *bio)
+{
+       if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) ||
+           (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail))
+               return should_fail(&fail_make_request, bio->bi_size);
+
+       return 0;
+}
+
+static int __init fail_make_request_debugfs(void)
+{
+       return init_fault_attr_dentries(&fail_make_request,
+                                       "fail_make_request");
+}
+
+late_initcall(fail_make_request_debugfs);
+
+#else /* CONFIG_FAIL_MAKE_REQUEST */
+
+static inline int should_fail_request(struct bio *bio)
+{
+       return 0;
+}
+
+#endif /* CONFIG_FAIL_MAKE_REQUEST */
+
 /**
  * generic_make_request: hand a buffer to its device driver for I/O
  * @bio:  The bio describing the location in memory and on the device.
@@ -3141,6 +3167,9 @@ end_io:
                if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
                        goto end_io;
 
+               if (should_fail_request(bio))
+                       goto end_io;
+
                /*
                 * If this device has partitions, remap block n
                 * of partition p to block n+start(p) of the disk.
@@ -3195,10 +3224,12 @@ void submit_bio(int rw, struct bio *bio)
        BIO_BUG_ON(!bio->bi_size);
        BIO_BUG_ON(!bio->bi_io_vec);
        bio->bi_rw |= rw;
-       if (rw & WRITE)
+       if (rw & WRITE) {
                count_vm_events(PGPGOUT, count);
-       else
+       } else {
+               task_io_account_read(bio->bi_size);
                count_vm_events(PGPGIN, count);
+       }
 
        if (unlikely(block_dump)) {
                char b[BDEVNAME_SIZE];
@@ -3459,8 +3490,6 @@ static void blk_done_softirq(struct softirq_action *h)
        }
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
 static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
                          void *hcpu)
 {
@@ -3486,8 +3515,6 @@ static struct notifier_block __devinitdata blk_cpu_notifier = {
        .notifier_call  = blk_cpu_notify,
 };
 
-#endif /* CONFIG_HOTPLUG_CPU */
-
 /**
  * blk_complete_request - end I/O on a request
  * @req:      the request being processed
index b3e2107..f322b6a 100644 (file)
@@ -228,6 +228,7 @@ static int sg_io(struct file *file, request_queue_t *q,
        struct request *rq;
        char sense[SCSI_SENSE_BUFFERSIZE];
        unsigned char cmd[BLK_MAX_CDB];
+       struct bio *bio;
 
        if (hdr->interface_id != 'S')
                return -EINVAL;
@@ -270,13 +271,6 @@ static int sg_io(struct file *file, request_queue_t *q,
 
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
 
-       /*
-        * bounce this after holding a reference to the original bio, it's
-        * needed for proper unmapping
-        */
-       if (rq->bio)
-               blk_queue_bounce(q, &rq->bio);
-
        rq->timeout = jiffies_to_msecs(hdr->timeout);
        if (!rq->timeout)
                rq->timeout = q->sg_timeout;
@@ -308,6 +302,7 @@ static int sg_io(struct file *file, request_queue_t *q,
        if (ret)
                goto out;
 
+       bio = rq->bio;
        rq->retries = 0;
 
        start_time = jiffies;
@@ -338,6 +333,7 @@ static int sg_io(struct file *file, request_queue_t *q,
                        hdr->sb_len_wr = len;
        }
 
+       rq->bio = bio;
        if (blk_rq_unmap_user(rq))
                ret = -EFAULT;
 
index cbae839..92ba249 100644 (file)
@@ -39,6 +39,17 @@ config CRYPTO_HMAC
          HMAC: Keyed-Hashing for Message Authentication (RFC2104).
          This is required for IPSec.
 
+config CRYPTO_XCBC
+       tristate "XCBC support"
+       depends on EXPERIMENTAL
+       select CRYPTO_HASH
+       select CRYPTO_MANAGER
+       help
+         XCBC: Keyed-Hashing with encryption algorithm
+               http://www.ietf.org/rfc/rfc3566.txt
+               http://csrc.nist.gov/encryption/modes/proposedmodes/
+                xcbc-mac/xcbc-mac-spec.pdf
+
 config CRYPTO_NULL
        tristate "Null algorithms"
        select CRYPTO_ALGAPI
@@ -128,6 +139,16 @@ config CRYPTO_TGR192
          See also:
          <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
 
+config CRYPTO_GF128MUL
+       tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         Efficient table driven implementation of multiplications in the
+         field GF(2^128).  This is needed by some cypher modes. This
+         option will be selected automatically if you select such a
+         cipher mode.  Only select this option by hand if you expect to load
+         an external module that requires these functions.
+
 config CRYPTO_ECB
        tristate "ECB support"
        select CRYPTO_BLKCIPHER
@@ -147,6 +168,19 @@ config CRYPTO_CBC
          CBC: Cipher Block Chaining mode
          This block cipher algorithm is required for IPSec.
 
+config CRYPTO_LRW
+       tristate "LRW support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_MANAGER
+       select CRYPTO_GF128MUL
+       help
+         LRW: Liskov Rivest Wagner, a tweakable, non malleable, non movable
+         narrow block cipher mode for dm-crypt.  Use it with cipher
+         specification string aes-lrw-benbi, the key must be 256, 320 or 384.
+         The first 128, 192 or 256 bits in the key are used for AES and the
+         rest is used to tie each cipher block to its logical position.
+
 config CRYPTO_DES
        tristate "DES and Triple DES EDE cipher algorithms"
        select CRYPTO_ALGAPI
index 7236620..60e3d24 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
 
 obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
+obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
 obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
 obj-$(CONFIG_CRYPTO_MD4) += md4.o
 obj-$(CONFIG_CRYPTO_MD5) += md5.o
@@ -23,8 +24,10 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
 obj-$(CONFIG_CRYPTO_WP512) += wp512.o
 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
index 4fb7fa4..8c44687 100644 (file)
@@ -466,23 +466,8 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
        kfree(tfm);
 }
 
-int crypto_alg_available(const char *name, u32 flags)
-{
-       int ret = 0;
-       struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0,
-                                                      CRYPTO_ALG_ASYNC);
-       
-       if (!IS_ERR(alg)) {
-               crypto_mod_put(alg);
-               ret = 1;
-       }
-       
-       return ret;
-}
-
 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
-EXPORT_SYMBOL_GPL(crypto_alg_available);
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
index 9b5b156..2ebffb8 100644 (file)
@@ -40,9 +40,10 @@ struct cryptomgr_param {
        char template[CRYPTO_MAX_ALG_NAME];
 };
 
-static void cryptomgr_probe(void *data)
+static void cryptomgr_probe(struct work_struct *work)
 {
-       struct cryptomgr_param *param = data;
+       struct cryptomgr_param *param =
+               container_of(work, struct cryptomgr_param, work);
        struct crypto_template *tmpl;
        struct crypto_instance *inst;
        int err;
@@ -112,7 +113,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
        param->larval.type = larval->alg.cra_flags;
        param->larval.mask = larval->mask;
 
-       INIT_WORK(&param->work, cryptomgr_probe, param);
+       INIT_WORK(&param->work, cryptomgr_probe);
        schedule_work(&param->work);
 
        return NOTIFY_STOP;
index 0155a94..8f45932 100644 (file)
 #include "internal.h"
 #include "scatterwalk.h"
 
-void crypto_digest_init(struct crypto_tfm *tfm)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-
-       crypto_hash_init(&desc);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_init);
-
-void crypto_digest_update(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-       unsigned int nbytes = 0;
-       unsigned int i;
-
-       for (i = 0; i < nsg; i++)
-               nbytes += sg[i].length;
-
-       crypto_hash_update(&desc, sg, nbytes);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_update);
-
-void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-
-       crypto_hash_final(&desc, out);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_final);
-
-void crypto_digest_digest(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg, u8 *out)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-       unsigned int nbytes = 0;
-       unsigned int i;
-
-       for (i = 0; i < nsg; i++)
-               nbytes += sg[i].length;
-
-       crypto_hash_digest(&desc, sg, nbytes, out);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_digest);
-
 static int init(struct hash_desc *desc)
 {
        struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
new file mode 100644 (file)
index 0000000..0a2aadf
--- /dev/null
@@ -0,0 +1,466 @@
+/* gf128mul.c - GF(2^128) multiplication functions
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * 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.
+ */
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 31/01/2006
+
+ This file provides fast multiplication in GF(128) as required by several
+ cryptographic authentication modes
+*/
+
+#include <crypto/gf128mul.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define gf128mul_dat(q) { \
+       q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\
+       q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\
+       q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\
+       q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\
+       q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\
+       q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\
+       q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\
+       q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\
+       q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\
+       q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\
+       q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\
+       q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\
+       q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\
+       q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\
+       q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\
+       q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\
+       q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\
+       q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\
+       q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\
+       q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\
+       q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\
+       q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\
+       q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\
+       q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\
+       q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\
+       q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\
+       q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\
+       q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\
+       q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\
+       q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\
+       q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\
+       q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) \
+}
+
+/*     Given the value i in 0..255 as the byte overflow when a field element
+    in GHASH is multipled by x^8, this function will return the values that
+    are generated in the lo 16-bit word of the field value by applying the
+    modular polynomial. The values lo_byte and hi_byte are returned via the
+    macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into
+    memory as required by a suitable definition of this macro operating on
+    the table above
+*/
+
+#define xx(p, q)       0x##p##q
+
+#define xda_bbe(i) ( \
+       (i & 0x80 ? xx(43, 80) : 0) ^ (i & 0x40 ? xx(21, c0) : 0) ^ \
+       (i & 0x20 ? xx(10, e0) : 0) ^ (i & 0x10 ? xx(08, 70) : 0) ^ \
+       (i & 0x08 ? xx(04, 38) : 0) ^ (i & 0x04 ? xx(02, 1c) : 0) ^ \
+       (i & 0x02 ? xx(01, 0e) : 0) ^ (i & 0x01 ? xx(00, 87) : 0) \
+)
+
+#define xda_lle(i) ( \
+       (i & 0x80 ? xx(e1, 00) : 0) ^ (i & 0x40 ? xx(70, 80) : 0) ^ \
+       (i & 0x20 ? xx(38, 40) : 0) ^ (i & 0x10 ? xx(1c, 20) : 0) ^ \
+       (i & 0x08 ? xx(0e, 10) : 0) ^ (i & 0x04 ? xx(07, 08) : 0) ^ \
+       (i & 0x02 ? xx(03, 84) : 0) ^ (i & 0x01 ? xx(01, c2) : 0) \
+)
+
+static const u16 gf128mul_table_lle[256] = gf128mul_dat(xda_lle);
+static const u16 gf128mul_table_bbe[256] = gf128mul_dat(xda_bbe);
+
+/* These functions multiply a field element by x, by x^4 and by x^8
+ * in the polynomial field representation. It uses 32-bit word operations
+ * to gain speed but compensates for machine endianess and hence works
+ * correctly on both styles of machine.
+ */
+
+static void gf128mul_x_lle(be128 *r, const be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_lle[(b << 7) & 0xff];
+
+       r->b = cpu_to_be64((b >> 1) | (a << 63));
+       r->a = cpu_to_be64((a >> 1) ^ (_tt << 48));
+}
+
+static void gf128mul_x_bbe(be128 *r, const be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_bbe[a >> 63];
+
+       r->a = cpu_to_be64((a << 1) | (b >> 63));
+       r->b = cpu_to_be64((b << 1) ^ _tt);
+}
+
+static void gf128mul_x8_lle(be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_lle[b & 0xff];
+
+       x->b = cpu_to_be64((b >> 8) | (a << 56));
+       x->a = cpu_to_be64((a >> 8) ^ (_tt << 48));
+}
+
+static void gf128mul_x8_bbe(be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_bbe[a >> 56];
+
+       x->a = cpu_to_be64((a << 8) | (b >> 56));
+       x->b = cpu_to_be64((b << 8) ^ _tt);
+}
+
+void gf128mul_lle(be128 *r, const be128 *b)
+{
+       be128 p[8];
+       int i;
+
+       p[0] = *r;
+       for (i = 0; i < 7; ++i)
+               gf128mul_x_lle(&p[i + 1], &p[i]);
+
+       memset(r, 0, sizeof(r));
+       for (i = 0;;) {
+               u8 ch = ((u8 *)b)[15 - i];
+
+               if (ch & 0x80)
+                       be128_xor(r, r, &p[0]);
+               if (ch & 0x40)
+                       be128_xor(r, r, &p[1]);
+               if (ch & 0x20)
+                       be128_xor(r, r, &p[2]);
+               if (ch & 0x10)
+                       be128_xor(r, r, &p[3]);
+               if (ch & 0x08)
+                       be128_xor(r, r, &p[4]);
+               if (ch & 0x04)
+                       be128_xor(r, r, &p[5]);
+               if (ch & 0x02)
+                       be128_xor(r, r, &p[6]);
+               if (ch & 0x01)
+                       be128_xor(r, r, &p[7]);
+
+               if (++i >= 16)
+                       break;
+
+               gf128mul_x8_lle(r);
+       }
+}
+EXPORT_SYMBOL(gf128mul_lle);
+
+void gf128mul_bbe(be128 *r, const be128 *b)
+{
+       be128 p[8];
+       int i;
+
+       p[0] = *r;
+       for (i = 0; i < 7; ++i)
+               gf128mul_x_bbe(&p[i + 1], &p[i]);
+
+       memset(r, 0, sizeof(r));
+       for (i = 0;;) {
+               u8 ch = ((u8 *)b)[i];
+
+               if (ch & 0x80)
+                       be128_xor(r, r, &p[7]);
+               if (ch & 0x40)
+                       be128_xor(r, r, &p[6]);
+               if (ch & 0x20)
+                       be128_xor(r, r, &p[5]);
+               if (ch & 0x10)
+                       be128_xor(r, r, &p[4]);
+               if (ch & 0x08)
+                       be128_xor(r, r, &p[3]);
+               if (ch & 0x04)
+                       be128_xor(r, r, &p[2]);
+               if (ch & 0x02)
+                       be128_xor(r, r, &p[1]);
+               if (ch & 0x01)
+                       be128_xor(r, r, &p[0]);
+
+               if (++i >= 16)
+                       break;
+
+               gf128mul_x8_bbe(r);
+       }
+}
+EXPORT_SYMBOL(gf128mul_bbe);
+
+/*      This version uses 64k bytes of table space.
+    A 16 byte buffer has to be multiplied by a 16 byte key
+    value in GF(128).  If we consider a GF(128) value in
+    the buffer's lowest byte, we can construct a table of
+    the 256 16 byte values that result from the 256 values
+    of this byte.  This requires 4096 bytes. But we also
+    need tables for each of the 16 higher bytes in the
+    buffer as well, which makes 64 kbytes in total.
+*/
+/* additional explanation
+ * t[0][BYTE] contains g*BYTE
+ * t[1][BYTE] contains g*x^8*BYTE
+ *  ..
+ * t[15][BYTE] contains g*x^120*BYTE */
+struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g)
+{
+       struct gf128mul_64k *t;
+       int i, j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       for (i = 0; i < 16; i++) {
+               t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL);
+               if (!t->t[i]) {
+                       gf128mul_free_64k(t);
+                       t = NULL;
+                       goto out;
+               }
+       }
+
+       t->t[0]->t[128] = *g;
+       for (j = 64; j > 0; j >>= 1)
+               gf128mul_x_lle(&t->t[0]->t[j], &t->t[0]->t[j + j]);
+
+       for (i = 0;;) {
+               for (j = 2; j < 256; j += j)
+                       for (k = 1; k < j; ++k)
+                               be128_xor(&t->t[i]->t[j + k],
+                                         &t->t[i]->t[j], &t->t[i]->t[k]);
+
+               if (++i >= 16)
+                       break;
+
+               for (j = 128; j > 0; j >>= 1) {
+                       t->t[i]->t[j] = t->t[i - 1]->t[j];
+                       gf128mul_x8_lle(&t->t[i]->t[j]);
+               }
+       }
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_64k_lle);
+
+struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g)
+{
+       struct gf128mul_64k *t;
+       int i, j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       for (i = 0; i < 16; i++) {
+               t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL);
+               if (!t->t[i]) {
+                       gf128mul_free_64k(t);
+                       t = NULL;
+                       goto out;
+               }
+       }
+
+       t->t[0]->t[1] = *g;
+       for (j = 1; j <= 64; j <<= 1)
+               gf128mul_x_bbe(&t->t[0]->t[j + j], &t->t[0]->t[j]);
+
+       for (i = 0;;) {
+               for (j = 2; j < 256; j += j)
+                       for (k = 1; k < j; ++k)
+                               be128_xor(&t->t[i]->t[j + k],
+                                         &t->t[i]->t[j], &t->t[i]->t[k]);
+
+               if (++i >= 16)
+                       break;
+
+               for (j = 128; j > 0; j >>= 1) {
+                       t->t[i]->t[j] = t->t[i - 1]->t[j];
+                       gf128mul_x8_bbe(&t->t[i]->t[j]);
+               }
+       }
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_64k_bbe);
+
+void gf128mul_free_64k(struct gf128mul_64k *t)
+{
+       int i;
+
+       for (i = 0; i < 16; i++)
+               kfree(t->t[i]);
+       kfree(t);
+}
+EXPORT_SYMBOL(gf128mul_free_64k);
+
+void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i;
+
+       *r = t->t[0]->t[ap[0]];
+       for (i = 1; i < 16; ++i)
+               be128_xor(r, r, &t->t[i]->t[ap[i]]);
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_64k_lle);
+
+void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i;
+
+       *r = t->t[0]->t[ap[15]];
+       for (i = 1; i < 16; ++i)
+               be128_xor(r, r, &t->t[i]->t[ap[15 - i]]);
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_64k_bbe);
+
+/*      This version uses 4k bytes of table space.
+    A 16 byte buffer has to be multiplied by a 16 byte key
+    value in GF(128).  If we consider a GF(128) value in a
+    single byte, we can construct a table of the 256 16 byte
+    values that result from the 256 values of this byte.
+    This requires 4096 bytes. If we take the highest byte in
+    the buffer and use this table to get the result, we then
+    have to multiply by x^120 to get the final value. For the
+    next highest byte the result has to be multiplied by x^112
+    and so on. But we can do this by accumulating the result
+    in an accumulator starting with the result for the top
+    byte.  We repeatedly multiply the accumulator value by
+    x^8 and then add in (i.e. xor) the 16 bytes of the next
+    lower byte in the buffer, stopping when we reach the
+    lowest byte. This requires a 4096 byte table.
+*/
+struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g)
+{
+       struct gf128mul_4k *t;
+       int j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       t->t[128] = *g;
+       for (j = 64; j > 0; j >>= 1)
+               gf128mul_x_lle(&t->t[j], &t->t[j+j]);
+
+       for (j = 2; j < 256; j += j)
+               for (k = 1; k < j; ++k)
+                       be128_xor(&t->t[j + k], &t->t[j], &t->t[k]);
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_4k_lle);
+
+struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g)
+{
+       struct gf128mul_4k *t;
+       int j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       t->t[1] = *g;
+       for (j = 1; j <= 64; j <<= 1)
+               gf128mul_x_bbe(&t->t[j + j], &t->t[j]);
+
+       for (j = 2; j < 256; j += j)
+               for (k = 1; k < j; ++k)
+                       be128_xor(&t->t[j + k], &t->t[j], &t->t[k]);
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_4k_bbe);
+
+void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i = 15;
+
+       *r = t->t[ap[15]];
+       while (i--) {
+               gf128mul_x8_lle(r);
+               be128_xor(r, r, &t->t[ap[i]]);
+       }
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_4k_lle);
+
+void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i = 0;
+
+       *r = t->t[ap[0]];
+       while (++i < 16) {
+               gf128mul_x8_bbe(r);
+               be128_xor(r, r, &t->t[ap[i]]);
+       }
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_4k_bbe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Functions for multiplying elements of GF(2^128)");
diff --git a/crypto/lrw.c b/crypto/lrw.c
new file mode 100644 (file)
index 0000000..5664258
--- /dev/null
@@ -0,0 +1,301 @@
+/* LRW: as defined by Cyril Guyot in
+ *     http://grouper.ieee.org/groups/1619/email/pdf00017.pdf
+ *
+ * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based om ecb.c
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 implementation is checked against the test vectors in the above
+ * document and by a test vector provided by Ken Buchanan at
+ * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
+ *
+ * The test vectors are included in the testing module tcrypt.[ch] */
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <crypto/b128ops.h>
+#include <crypto/gf128mul.h>
+
+struct priv {
+       struct crypto_cipher *child;
+       /* optimizes multiplying a random (non incrementing, as at the
+        * start of a new sector) value with key2, we could also have
+        * used 4k optimization tables or no optimization at all. In the
+        * latter case we would have to store key2 here */
+       struct gf128mul_64k *table;
+       /* stores:
+        *  key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
+        *  key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
+        *  key2*{ 0,0,...1,1,1,1,1 }, etc
+        * needed for optimized multiplication of incrementing values
+        * with key2 */
+       be128 mulinc[128];
+};
+
+static inline void setbit128_bbe(void *b, int bit)
+{
+       __set_bit(bit ^ 0x78, b);
+}
+
+static int setkey(struct crypto_tfm *parent, const u8 *key,
+                 unsigned int keylen)
+{
+       struct priv *ctx = crypto_tfm_ctx(parent);
+       struct crypto_cipher *child = ctx->child;
+       int err, i;
+       be128 tmp = { 0 };
+       int bsize = crypto_cipher_blocksize(child);
+
+       crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+       crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+                                      CRYPTO_TFM_REQ_MASK);
+       if ((err = crypto_cipher_setkey(child, key, keylen - bsize)))
+               return err;
+       crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+                                    CRYPTO_TFM_RES_MASK);
+
+       if (ctx->table)
+               gf128mul_free_64k(ctx->table);
+
+       /* initialize multiplication table for Key2 */
+       ctx->table = gf128mul_init_64k_bbe((be128 *)(key + keylen - bsize));
+       if (!ctx->table)
+               return -ENOMEM;
+
+       /* initialize optimization table */
+       for (i = 0; i < 128; i++) {
+               setbit128_bbe(&tmp, i);
+               ctx->mulinc[i] = tmp;
+               gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table);
+       }
+
+       return 0;
+}
+
+struct sinfo {
+       be128 t;
+       struct crypto_tfm *tfm;
+       void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
+};
+
+static inline void inc(be128 *iv)
+{
+       if (!(iv->b = cpu_to_be64(be64_to_cpu(iv->b) + 1)))
+               iv->a = cpu_to_be64(be64_to_cpu(iv->a) + 1);
+}
+
+static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
+{
+       be128_xor(dst, &s->t, src);             /* PP <- T xor P */
+       s->fn(s->tfm, dst, dst);                /* CC <- E(Key2,PP) */
+       be128_xor(dst, dst, &s->t);             /* C <- T xor CC */
+}
+
+/* this returns the number of consequative 1 bits starting
+ * from the right, get_index128(00 00 00 00 00 00 ... 00 00 10 FB) = 2 */
+static inline int get_index128(be128 *block)
+{
+       int x;
+       __be32 *p = (__be32 *) block;
+
+       for (p += 3, x = 0; x < 128; p--, x += 32) {
+               u32 val = be32_to_cpup(p);
+
+               if (!~val)
+                       continue;
+
+               return x + ffz(val);
+       }
+
+       return x;
+}
+
+static int crypt(struct blkcipher_desc *d,
+                struct blkcipher_walk *w, struct priv *ctx,
+                void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+{
+       int err;
+       unsigned int avail;
+       const int bs = crypto_cipher_blocksize(ctx->child);
+       struct sinfo s = {
+               .tfm = crypto_cipher_tfm(ctx->child),
+               .fn = fn
+       };
+       be128 *iv;
+       u8 *wsrc;
+       u8 *wdst;
+
+       err = blkcipher_walk_virt(d, w);
+       if (!(avail = w->nbytes))
+               return err;
+
+       wsrc = w->src.virt.addr;
+       wdst = w->dst.virt.addr;
+
+       /* calculate first value of T */
+       iv = (be128 *)w->iv;
+       s.t = *iv;
+
+       /* T <- I*Key2 */
+       gf128mul_64k_bbe(&s.t, ctx->table);
+
+       goto first;
+
+       for (;;) {
+               do {
+                       /* T <- I*Key2, using the optimization
+                        * discussed in the specification */
+                       be128_xor(&s.t, &s.t, &ctx->mulinc[get_index128(iv)]);
+                       inc(iv);
+
+first:
+                       lrw_round(&s, wdst, wsrc);
+
+                       wsrc += bs;
+                       wdst += bs;
+               } while ((avail -= bs) >= bs);
+
+               err = blkcipher_walk_done(d, w, avail);
+               if (!(avail = w->nbytes))
+                       break;
+
+               wsrc = w->src.virt.addr;
+               wdst = w->dst.virt.addr;
+       }
+
+       return err;
+}
+
+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                  struct scatterlist *src, unsigned int nbytes)
+{
+       struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk w;
+
+       blkcipher_walk_init(&w, dst, src, nbytes);
+       return crypt(desc, &w, ctx,
+                    crypto_cipher_alg(ctx->child)->cia_encrypt);
+}
+
+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                  struct scatterlist *src, unsigned int nbytes)
+{
+       struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk w;
+
+       blkcipher_walk_init(&w, dst, src, nbytes);
+       return crypt(desc, &w, ctx,
+                    crypto_cipher_alg(ctx->child)->cia_decrypt);
+}
+
+static int init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+       struct priv *ctx = crypto_tfm_ctx(tfm);
+       u32 *flags = &tfm->crt_flags;
+
+       tfm = crypto_spawn_tfm(spawn);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       if (crypto_tfm_alg_blocksize(tfm) != 16) {
+               *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+               return -EINVAL;
+       }
+
+       ctx->child = crypto_cipher_cast(tfm);
+       return 0;
+}
+
+static void exit_tfm(struct crypto_tfm *tfm)
+{
+       struct priv *ctx = crypto_tfm_ctx(tfm);
+       if (ctx->table)
+               gf128mul_free_64k(ctx->table);
+       crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *alloc(void *param, unsigned int len)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+
+       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       inst = crypto_alloc_instance("lrw", alg);
+       if (IS_ERR(inst))
+               goto out_put_alg;
+
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+       inst->alg.cra_priority = alg->cra_priority;
+       inst->alg.cra_blocksize = alg->cra_blocksize;
+
+       if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7;
+       else inst->alg.cra_alignmask = alg->cra_alignmask;
+       inst->alg.cra_type = &crypto_blkcipher_type;
+
+       if (!(alg->cra_blocksize % 4))
+               inst->alg.cra_alignmask |= 3;
+       inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+       inst->alg.cra_blkcipher.min_keysize =
+               alg->cra_cipher.cia_min_keysize + alg->cra_blocksize;
+       inst->alg.cra_blkcipher.max_keysize =
+               alg->cra_cipher.cia_max_keysize + alg->cra_blocksize;
+
+       inst->alg.cra_ctxsize = sizeof(struct priv);
+
+       inst->alg.cra_init = init_tfm;
+       inst->alg.cra_exit = exit_tfm;
+
+       inst->alg.cra_blkcipher.setkey = setkey;
+       inst->alg.cra_blkcipher.encrypt = encrypt;
+       inst->alg.cra_blkcipher.decrypt = decrypt;
+
+out_put_alg:
+       crypto_mod_put(alg);
+       return inst;
+}
+
+static void free(struct crypto_instance *inst)
+{
+       crypto_drop_spawn(crypto_instance_ctx(inst));
+       kfree(inst);
+}
+
+static struct crypto_template crypto_tmpl = {
+       .name = "lrw",
+       .alloc = alloc,
+       .free = free,
+       .module = THIS_MODULE,
+};
+
+static int __init crypto_module_init(void)
+{
+       return crypto_register_template(&crypto_tmpl);
+}
+
+static void __exit crypto_module_exit(void)
+{
+       crypto_unregister_template(&crypto_tmpl);
+}
+
+module_init(crypto_module_init);
+module_exit(crypto_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LRW block cipher mode");
index 2dfe7f1..15eab9d 100644 (file)
@@ -24,7 +24,7 @@
 
 #define SHA384_DIGEST_SIZE 48
 #define SHA512_DIGEST_SIZE 64
-#define SHA384_HMAC_BLOCK_SIZE  96
+#define SHA384_HMAC_BLOCK_SIZE 128
 #define SHA512_HMAC_BLOCK_SIZE 128
 
 struct sha512_ctx {
index 8330742..d671e89 100644 (file)
@@ -906,6 +906,10 @@ static void do_test(void)
                            AES_CBC_ENC_TEST_VECTORS);
                test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
                            AES_CBC_DEC_TEST_VECTORS);
+               test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+                           AES_LRW_ENC_TEST_VECTORS);
+               test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+                           AES_LRW_DEC_TEST_VECTORS);
 
                //CAST5
                test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -977,6 +981,9 @@ static void do_test(void)
                test_hash("hmac(sha256)", hmac_sha256_tv_template,
                          HMAC_SHA256_TEST_VECTORS);
 
+               test_hash("xcbc(aes)", aes_xcbc128_tv_template,
+                         XCBC_AES_TEST_VECTORS);
+
                test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
                break;
 
@@ -1052,6 +1059,10 @@ static void do_test(void)
                            AES_CBC_ENC_TEST_VECTORS);
                test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
                            AES_CBC_DEC_TEST_VECTORS);
+               test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+                           AES_LRW_ENC_TEST_VECTORS);
+               test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+                           AES_LRW_DEC_TEST_VECTORS);
                break;
 
        case 11:
@@ -1191,6 +1202,10 @@ static void do_test(void)
                                  aes_speed_template);
                test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
                                  aes_speed_template);
+               test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
+                                 aes_lrw_speed_template);
+               test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
+                                 aes_lrw_speed_template);
                break;
 
        case 201:
index a40c441..48a8136 100644 (file)
@@ -39,15 +39,15 @@ struct hash_testvec {
 struct cipher_testvec {
        char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
        char iv[MAX_IVLEN];
-       char input[48];
-       char result[48];
+       char input[512];
+       char result[512];
        unsigned char tap[MAX_TAP];
        int np;
        unsigned char fail;
        unsigned char wk; /* weak key flag */
        unsigned char klen;
-       unsigned char ilen;
-       unsigned char rlen;
+       unsigned short ilen;
+       unsigned short rlen;
 };
 
 struct cipher_speed {
@@ -933,6 +933,74 @@ static struct hash_testvec hmac_sha256_tv_template[] = {
        },
 };
 
+#define XCBC_AES_TEST_VECTORS 6
+
+static struct hash_testvec aes_xcbc128_tv_template[] = {
+       {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { [0 ... 15] = 0 },
+               .digest = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+                           0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 },
+               .psize  = 0,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02 },
+               .digest = { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf,
+                           0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f },
+               .psize  = 3,
+               .ksize  = 16,
+       } , {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .digest = { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
+                           0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 },
+               .psize  = 16,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13 },
+               .digest = { 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
+                           0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 },
+               .tap    = { 10, 10 },
+               .psize  = 20,
+               .np     = 2,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                              0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+               .digest = { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3,
+                           0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 },
+               .psize  = 32,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                              0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                              0x20, 0x21 },
+               .digest = { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3,
+                           0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 },
+               .tap    = { 17, 17 },
+               .psize  = 34,
+               .np     = 2,
+               .ksize  = 16,
+       }
+};
+
 /*
  * DES test vectors.
  */
@@ -1831,6 +1899,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 #define AES_DEC_TEST_VECTORS 3
 #define AES_CBC_ENC_TEST_VECTORS 2
 #define AES_CBC_DEC_TEST_VECTORS 2
+#define AES_LRW_ENC_TEST_VECTORS 8
+#define AES_LRW_DEC_TEST_VECTORS 8
 
 static struct cipher_testvec aes_enc_tv_template[] = {
        { /* From FIPS-197 */
@@ -1968,6 +2038,509 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
        },
 };
 
+static struct cipher_testvec aes_lrw_enc_tv_template[] = {
+       /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+       { /* LRW-32-AES 1 */
+               .key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+                           0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+                           0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+                           0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+                           0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 2 */
+               .key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+                           0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+                           0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+                           0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+               },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+                           0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 3 */
+               .key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+                           0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+                           0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+                           0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+                           0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 4 */
+               .key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+                           0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+                           0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+                           0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+                           0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+                           0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 5 */
+               .key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+                           0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+                           0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+                           0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+                           0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+                           0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 6 */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+                           0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 7 */
+               .key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+                           0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+                           0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+                           0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+                           0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+                           0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+                           0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
+               .rlen   = 16,
+       }, {
+/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+                           0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+                           0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+                           0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+                           0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+                           0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+                           0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+                           0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+                           0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+                           0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+                           0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+                           0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+                           0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+                           0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+                           0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+                           0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+                           0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+                           0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+                           0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+                           0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+                           0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+                           0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+                           0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+                           0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+                           0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+                           0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+                           0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+                           0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+                           0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+                           0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+                           0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+                           0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+                           0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+                           0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+                           0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+                           0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+                           0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+                           0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+                           0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+                           0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+                           0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+                           0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+                           0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+                           0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+                           0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+                           0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+                           0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+                           0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+                           0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+                           0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+                           0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+                           0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+                           0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+                           0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+                           0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+                           0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+                           0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+                           0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+                           0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+                           0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+                           0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+                           0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+                           0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+                           0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
+               .ilen   = 512,
+               .result = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+                           0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+                           0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+                           0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+                           0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+                           0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+                           0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+                           0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+                           0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+                           0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+                           0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+                           0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+                           0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+                           0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+                           0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+                           0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+                           0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+                           0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+                           0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+                           0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+                           0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+                           0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+                           0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+                           0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+                           0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+                           0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+                           0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+                           0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+                           0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+                           0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+                           0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+                           0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+                           0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+                           0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+                           0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+                           0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+                           0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+                           0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+                           0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+                           0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+                           0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+                           0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+                           0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+                           0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+                           0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+                           0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+                           0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+                           0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+                           0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+                           0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+                           0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+                           0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+                           0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+                           0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+                           0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+                           0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+                           0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+                           0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+                           0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+                           0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+                           0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+                           0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+                           0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+                           0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
+               .rlen   = 512,
+       }
+};
+
+static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+       /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+       /* same as enc vectors with input and result reversed */
+       { /* LRW-32-AES 1 */
+               .key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+                           0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+                           0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+                           0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+                           0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 2 */
+               .key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+                           0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+                           0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+                           0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+               },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+               .input  = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+                           0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+               .ilen   = 16,
+               .result  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                            0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 3 */
+               .key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+                           0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+                           0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+                           0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+                           0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 4 */
+               .key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+                           0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+                           0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+                           0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+                           0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+                           0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 5 */
+               .key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+                           0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+                           0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+                           0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+                           0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+                           0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 6 */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+                           0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 7 */
+               .key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+                           0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+                           0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+                           0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+                           0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+                           0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+                           0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, {
+/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+                           0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+                           0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+                           0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+                           0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+                           0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+                           0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+                           0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+                           0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+                           0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+                           0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+                           0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+                           0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+                           0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+                           0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+                           0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+                           0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+                           0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+                           0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+                           0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+                           0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+                           0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+                           0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+                           0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+                           0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+                           0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+                           0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+                           0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+                           0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+                           0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+                           0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+                           0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+                           0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+                           0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+                           0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+                           0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+                           0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+                           0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+                           0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+                           0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+                           0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+                           0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+                           0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+                           0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+                           0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+                           0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+                           0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+                           0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+                           0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+                           0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+                           0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+                           0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+                           0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+                           0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+                           0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+                           0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+                           0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+                           0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+                           0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+                           0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+                           0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+                           0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+                           0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+                           0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
+               .ilen   = 512,
+               .result = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+                           0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+                           0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+                           0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+                           0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+                           0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+                           0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+                           0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+                           0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+                           0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+                           0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+                           0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+                           0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+                           0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+                           0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+                           0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+                           0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+                           0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+                           0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+                           0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+                           0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+                           0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+                           0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+                           0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+                           0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+                           0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+                           0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+                           0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+                           0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+                           0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+                           0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+                           0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+                           0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+                           0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+                           0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+                           0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+                           0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+                           0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+                           0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+                           0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+                           0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+                           0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+                           0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+                           0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+                           0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+                           0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+                           0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+                           0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+                           0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+                           0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+                           0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+                           0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+                           0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+                           0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+                           0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+                           0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+                           0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+                           0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+                           0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+                           0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+                           0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+                           0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+                           0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+                           0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
+               .rlen   = 512,
+       }
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS 3
 #define CAST5_DEC_TEST_VECTORS 3
@@ -3084,6 +3657,27 @@ static struct cipher_speed aes_speed_template[] = {
        {  .klen = 0, .blen = 0, }
 };
 
+static struct cipher_speed aes_lrw_speed_template[] = {
+       { .klen = 32, .blen = 16, },
+       { .klen = 32, .blen = 64, },
+       { .klen = 32, .blen = 256, },
+       { .klen = 32, .blen = 1024, },
+       { .klen = 32, .blen = 8192, },
+       { .klen = 40, .blen = 16, },
+       { .klen = 40, .blen = 64, },
+       { .klen = 40, .blen = 256, },
+       { .klen = 40, .blen = 1024, },
+       { .klen = 40, .blen = 8192, },
+       { .klen = 48, .blen = 16, },
+       { .klen = 48, .blen = 64, },
+       { .klen = 48, .blen = 256, },
+       { .klen = 48, .blen = 1024, },
+       { .klen = 48, .blen = 8192, },
+
+       /* End marker */
+       {  .klen = 0, .blen = 0, }
+};
+
 static struct cipher_speed des3_ede_speed_template[] = {
        { .klen = 24, .blen = 16, },
        { .klen = 24, .blen = 64, },
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
new file mode 100644 (file)
index 0000000..9347eb6
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * 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
+ *
+ * Author:
+ *     Kazunori Miyazawa <miyazawa@linux-ipv6.org>
+ */
+
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include "internal.h"
+
+static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
+                          0x02020202, 0x02020202, 0x02020202, 0x02020202,
+                          0x03030303, 0x03030303, 0x03030303, 0x03030303};
+/*
+ * +------------------------
+ * | <parent tfm>
+ * +------------------------
+ * | crypto_xcbc_ctx
+ * +------------------------
+ * | odds (block size)
+ * +------------------------
+ * | prev (block size)
+ * +------------------------
+ * | key (block size)
+ * +------------------------
+ * | consts (block size * 3)
+ * +------------------------
+ */
+struct crypto_xcbc_ctx {
+       struct crypto_tfm *child;
+       u8 *odds;
+       u8 *prev;
+       u8 *key;
+       u8 *consts;
+       void (*xor)(u8 *a, const u8 *b, unsigned int bs);
+       unsigned int keylen;
+       unsigned int len;
+};
+
+static void xor_128(u8 *a, const u8 *b, unsigned int bs)
+{
+       ((u32 *)a)[0] ^= ((u32 *)b)[0];
+       ((u32 *)a)[1] ^= ((u32 *)b)[1];
+       ((u32 *)a)[2] ^= ((u32 *)b)[2];
+       ((u32 *)a)[3] ^= ((u32 *)b)[3];
+}
+
+static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent,
+                                     struct crypto_xcbc_ctx *ctx)
+{
+       int bs = crypto_hash_blocksize(parent);
+       int err = 0;
+       u8 key1[bs];
+
+       if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
+           return err;
+
+       ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1,
+                       ctx->consts);
+
+       return crypto_cipher_setkey(ctx->child, key1, bs);
+}
+
+static int crypto_xcbc_digest_setkey(struct crypto_hash *parent,
+                                    const u8 *inkey, unsigned int keylen)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+
+       if (keylen != crypto_tfm_alg_blocksize(ctx->child))
+               return -EINVAL;
+
+       ctx->keylen = keylen;
+       memcpy(ctx->key, inkey, keylen);
+       ctx->consts = (u8*)ks;
+
+       return _crypto_xcbc_digest_setkey(parent, ctx);
+}
+
+static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(pdesc->tfm);
+       int bs = crypto_hash_blocksize(pdesc->tfm);
+
+       ctx->len = 0;
+       memset(ctx->odds, 0, bs);
+       memset(ctx->prev, 0, bs);
+
+       return 0;
+}
+
+static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
+                                    struct scatterlist *sg,
+                                    unsigned int nbytes)
+{
+       struct crypto_hash *parent = pdesc->tfm;
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+       struct crypto_tfm *tfm = ctx->child;
+       int bs = crypto_hash_blocksize(parent);
+       unsigned int i = 0;
+
+       do {
+
+               struct page *pg = sg[i].page;
+               unsigned int offset = sg[i].offset;
+               unsigned int slen = sg[i].length;
+
+               while (slen > 0) {
+                       unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
+                       char *p = crypto_kmap(pg, 0) + offset;
+
+                       /* checking the data can fill the block */
+                       if ((ctx->len + len) <= bs) {
+                               memcpy(ctx->odds + ctx->len, p, len);
+                               ctx->len += len;
+                               slen -= len;
+
+                               /* checking the rest of the page */
+                               if (len + offset >= PAGE_SIZE) {
+                                       offset = 0;
+                                       pg++;
+                               } else
+                                       offset += len;
+
+                               crypto_kunmap(p, 0);
+                               crypto_yield(tfm->crt_flags);
+                               continue;
+                       }
+
+                       /* filling odds with new data and encrypting it */
+                       memcpy(ctx->odds + ctx->len, p, bs - ctx->len);
+                       len -= bs - ctx->len;
+                       p += bs - ctx->len;
+
+                       ctx->xor(ctx->prev, ctx->odds, bs);
+                       tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+
+                       /* clearing the length */
+                       ctx->len = 0;
+
+                       /* encrypting the rest of data */
+                       while (len > bs) {
+                               ctx->xor(ctx->prev, p, bs);
+                               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+                               p += bs;
+                               len -= bs;
+                       }
+
+                       /* keeping the surplus of blocksize */
+                       if (len) {
+                               memcpy(ctx->odds, p, len);
+                               ctx->len = len;
+                       }
+                       crypto_kunmap(p, 0);
+                       crypto_yield(tfm->crt_flags);
+                       slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
+                       offset = 0;
+                       pg++;
+               }
+               nbytes-=sg[i].length;
+               i++;
+       } while (nbytes>0);
+
+       return 0;
+}
+
+static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
+{
+       struct crypto_hash *parent = pdesc->tfm;
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+       struct crypto_tfm *tfm = ctx->child;
+       int bs = crypto_hash_blocksize(parent);
+       int err = 0;
+
+       if (ctx->len == bs) {
+               u8 key2[bs];
+
+               if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
+                       return err;
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs));
+
+               ctx->xor(ctx->prev, ctx->odds, bs);
+               ctx->xor(ctx->prev, key2, bs);
+               _crypto_xcbc_digest_setkey(parent, ctx);
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+       } else {
+               u8 key3[bs];
+               unsigned int rlen;
+               u8 *p = ctx->odds + ctx->len;
+               *p = 0x80;
+               p++;
+
+               rlen = bs - ctx->len -1;
+               if (rlen)
+                       memset(p, 0, rlen);
+
+               if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
+                       return err;
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2));
+
+               ctx->xor(ctx->prev, ctx->odds, bs);
+               ctx->xor(ctx->prev, key3, bs);
+
+               _crypto_xcbc_digest_setkey(parent, ctx);
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+       }
+
+       return 0;
+}
+
+static int crypto_xcbc_digest(struct hash_desc *pdesc,
+                 struct scatterlist *sg, unsigned int nbytes, u8 *out)
+{
+       crypto_xcbc_digest_init(pdesc);
+       crypto_xcbc_digest_update(pdesc, sg, nbytes);
+       return crypto_xcbc_digest_final(pdesc, out);
+}
+
+static int xcbc_init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
+       int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm));
+
+       tfm = crypto_spawn_tfm(spawn);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       switch(bs) {
+       case 16:
+               ctx->xor = xor_128;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ctx->child = crypto_cipher_cast(tfm);
+       ctx->odds = (u8*)(ctx+1);
+       ctx->prev = ctx->odds + bs;
+       ctx->key = ctx->prev + bs;
+
+       return 0;
+};
+
+static void xcbc_exit_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
+       crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       switch(alg->cra_blocksize) {
+       case 16:
+               break;
+       default:
+               return ERR_PTR(PTR_ERR(alg));
+       }
+
+       inst = crypto_alloc_instance("xcbc", alg);
+       if (IS_ERR(inst))
+               goto out_put_alg;
+
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH;
+       inst->alg.cra_priority = alg->cra_priority;
+       inst->alg.cra_blocksize = alg->cra_blocksize;
+       inst->alg.cra_alignmask = alg->cra_alignmask;
+       inst->alg.cra_type = &crypto_hash_type;
+
+       inst->alg.cra_hash.digestsize =
+               (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+               CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
+                                      alg->cra_blocksize;
+       inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) +
+                               ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *));
+       inst->alg.cra_init = xcbc_init_tfm;
+       inst->alg.cra_exit = xcbc_exit_tfm;
+
+       inst->alg.cra_hash.init = crypto_xcbc_digest_init;
+       inst->alg.cra_hash.update = crypto_xcbc_digest_update;
+       inst->alg.cra_hash.final = crypto_xcbc_digest_final;
+       inst->alg.cra_hash.digest = crypto_xcbc_digest;
+       inst->alg.cra_hash.setkey = crypto_xcbc_digest_setkey;
+
+out_put_alg:
+       crypto_mod_put(alg);
+       return inst;
+}
+
+static void xcbc_free(struct crypto_instance *inst)
+{
+       crypto_drop_spawn(crypto_instance_ctx(inst));
+       kfree(inst);
+}
+
+static struct crypto_template crypto_xcbc_tmpl = {
+       .name = "xcbc",
+       .alloc = xcbc_alloc,
+       .free = xcbc_free,
+       .module = THIS_MODULE,
+};
+
+static int __init crypto_xcbc_module_init(void)
+{
+       return crypto_register_template(&crypto_xcbc_tmpl);
+}
+
+static void __exit crypto_xcbc_module_exit(void)
+{
+       crypto_unregister_template(&crypto_xcbc_tmpl);
+}
+
+module_init(crypto_xcbc_module_init);
+module_exit(crypto_xcbc_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XCBC keyed hash algorithm");
index f394634..e7da9fa 100644 (file)
@@ -64,6 +64,8 @@ source "drivers/video/Kconfig"
 
 source "sound/Kconfig"
 
+source "drivers/hid/Kconfig"
+
 source "drivers/usb/Kconfig"
 
 source "drivers/mmc/Kconfig"
@@ -78,4 +80,6 @@ source "drivers/rtc/Kconfig"
 
 source "drivers/dma/Kconfig"
 
+source "drivers/kvm/Kconfig"
+
 endmenu
index 6771177..0dd96d1 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_SPI)             += spi/
 obj-$(CONFIG_PCCARD)           += pcmcia/
 obj-$(CONFIG_DIO)              += dio/
 obj-$(CONFIG_SBUS)             += sbus/
+obj-$(CONFIG_KVM)              += kvm/
 obj-$(CONFIG_ZORRO)            += zorro/
 obj-$(CONFIG_MAC)              += macintosh/
 obj-$(CONFIG_ATA_OVER_ETH)     += block/aoe/
@@ -77,4 +78,5 @@ obj-$(CONFIG_CRYPTO)          += crypto/
 obj-$(CONFIG_SUPERH)           += sh/
 obj-$(CONFIG_GENERIC_TIME)     += clocksource/
 obj-$(CONFIG_DMA_ENGINE)       += dma/
+obj-$(CONFIG_HID)              += hid/
 obj-$(CONFIG_PPC_PS3)          += ps3/
index 068fe4f..02b30ae 100644 (file)
@@ -50,6 +50,7 @@ ACPI_MODULE_NAME("osl")
 struct acpi_os_dpc {
        acpi_osd_exec_callback function;
        void *context;
+       struct work_struct work;
 };
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -564,12 +565,9 @@ void acpi_os_derive_pci_id(acpi_handle rhandle,    /* upper bound  */
        acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
 }
 
-static void acpi_os_execute_deferred(void *context)
+static void acpi_os_execute_deferred(struct work_struct *work)
 {
-       struct acpi_os_dpc *dpc = NULL;
-
-
-       dpc = (struct acpi_os_dpc *)context;
+       struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
        if (!dpc) {
                printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
                return;
@@ -602,7 +600,6 @@ acpi_status acpi_os_execute(acpi_execute_type type,
 {
        acpi_status status = AE_OK;
        struct acpi_os_dpc *dpc;
-       struct work_struct *task;
 
        ACPI_FUNCTION_TRACE("os_queue_for_execution");
 
@@ -615,28 +612,22 @@ acpi_status acpi_os_execute(acpi_execute_type type,
 
        /*
         * Allocate/initialize DPC structure.  Note that this memory will be
-        * freed by the callee.  The kernel handles the tq_struct list  in a
+        * freed by the callee.  The kernel handles the work_struct list  in a
         * way that allows us to also free its memory inside the callee.
         * Because we may want to schedule several tasks with different
         * parameters we can't use the approach some kernel code uses of
-        * having a static tq_struct.
-        * We can save time and code by allocating the DPC and tq_structs
-        * from the same memory.
+        * having a static work_struct.
         */
 
-       dpc =
-           kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
-                   GFP_ATOMIC);
+       dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
        if (!dpc)
                return_ACPI_STATUS(AE_NO_MEMORY);
 
        dpc->function = function;
        dpc->context = context;
 
-       task = (void *)(dpc + 1);
-       INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
-
-       if (!queue_work(kacpid_wq, task)) {
+       INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+       if (!queue_work(kacpid_wq, &dpc->work)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Call to queue_work() failed.\n"));
                kfree(dpc);
index 9e3e2a6..fd54750 100644 (file)
@@ -80,12 +80,38 @@ static int amba_resume(struct device *dev)
        return ret;
 }
 
+#define amba_attr_func(name,fmt,arg...)                                        \
+static ssize_t name##_show(struct device *_dev,                                \
+                          struct device_attribute *attr, char *buf)    \
+{                                                                      \
+       struct amba_device *dev = to_amba_device(_dev);                 \
+       return sprintf(buf, fmt, arg);                                  \
+}
+
+#define amba_attr(name,fmt,arg...)     \
+amba_attr_func(name,fmt,arg)           \
+static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL)
+
+amba_attr_func(id, "%08x\n", dev->periphid);
+amba_attr(irq0, "%u\n", dev->irq[0]);
+amba_attr(irq1, "%u\n", dev->irq[1]);
+amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n",
+        (unsigned long long)dev->res.start, (unsigned long long)dev->res.end,
+        dev->res.flags);
+
+static struct device_attribute amba_dev_attrs[] = {
+       __ATTR_RO(id),
+       __ATTR_RO(resource),
+       __ATTR_NULL,
+};
+
 /*
  * Primecells are part of the Advanced Microcontroller Bus Architecture,
  * so we call the bus "amba".
  */
 static struct bus_type amba_bustype = {
        .name           = "amba",
+       .dev_attrs      = amba_dev_attrs,
        .match          = amba_match,
        .uevent         = amba_uevent,
        .suspend        = amba_suspend,
@@ -169,21 +195,6 @@ static void amba_device_release(struct device *dev)
        kfree(d);
 }
 
-#define amba_attr(name,fmt,arg...)                             \
-static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf)      \
-{                                                              \
-       struct amba_device *dev = to_amba_device(_dev);         \
-       return sprintf(buf, fmt, arg);                          \
-}                                                              \
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-amba_attr(id, "%08x\n", dev->periphid);
-amba_attr(irq0, "%u\n", dev->irq[0]);
-amba_attr(irq1, "%u\n", dev->irq[1]);
-amba_attr(resource, "\t%016llx\t%016llx\t%016lx\n",
-        (unsigned long long)dev->res.start, (unsigned long long)dev->res.end,
-        dev->res.flags);
-
 /**
  *     amba_device_register - register an AMBA device
  *     @dev: AMBA device to register
@@ -208,40 +219,46 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
                dev_warn(&dev->dev, "coherent dma mask is unset\n");
 
        ret = request_resource(parent, &dev->res);
-       if (ret == 0) {
-               tmp = ioremap(dev->res.start, SZ_4K);
-               if (!tmp) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               for (pid = 0, i = 0; i < 4; i++)
-                       pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8);
-               for (cid = 0, i = 0; i < 4; i++)
-                       cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8);
-
-               iounmap(tmp);
-
-               if (cid == 0xb105f00d)
-                       dev->periphid = pid;
-
-               if (dev->periphid)
-                       ret = device_register(&dev->dev);
-               else
-                       ret = -ENODEV;
-
-               if (ret == 0) {
-                       device_create_file(&dev->dev, &dev_attr_id);
-                       if (dev->irq[0] != NO_IRQ)
-                               device_create_file(&dev->dev, &dev_attr_irq0);
-                       if (dev->irq[1] != NO_IRQ)
-                               device_create_file(&dev->dev, &dev_attr_irq1);
-                       device_create_file(&dev->dev, &dev_attr_resource);
-               } else {
- out:
-                       release_resource(&dev->res);
-               }
+       if (ret)
+               goto err_out;
+
+       tmp = ioremap(dev->res.start, SZ_4K);
+       if (!tmp) {
+               ret = -ENOMEM;
+               goto err_release;
        }
+
+       for (pid = 0, i = 0; i < 4; i++)
+               pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8);
+       for (cid = 0, i = 0; i < 4; i++)
+               cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8);
+
+       iounmap(tmp);
+
+       if (cid == 0xb105f00d)
+               dev->periphid = pid;
+
+       if (!dev->periphid) {
+               ret = -ENODEV;
+               goto err_release;
+       }
+
+       ret = device_register(&dev->dev);
+       if (ret)
+               goto err_release;
+
+       if (dev->irq[0] != NO_IRQ)
+               ret = device_create_file(&dev->dev, &dev_attr_irq0);
+       if (ret == 0 && dev->irq[1] != NO_IRQ)
+               ret = device_create_file(&dev->dev, &dev_attr_irq1);
+       if (ret == 0)
+               return ret;
+
+       device_unregister(&dev->dev);
+
+ err_release:
+       release_resource(&dev->res);
+ err_out:
        return ret;
 }
 
index f8ec389..011c0a8 100644 (file)
@@ -1081,7 +1081,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
  *     ata_port_queue_task - Queue port_task
  *     @ap: The ata_port to queue port_task for
  *     @fn: workqueue function to be scheduled
- *     @data: data value to pass to workqueue function
+ *     @data: data for @fn to use
  *     @delay: delay time for workqueue function
  *
  *     Schedule @fn(@data) for execution after @delay jiffies using
@@ -1096,7 +1096,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
  *     LOCKING:
  *     Inherited from caller.
  */
-void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
+void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
                         unsigned long delay)
 {
        int rc;
@@ -1104,12 +1104,10 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
        if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
                return;
 
-       PREPARE_WORK(&ap->port_task, fn, data);
+       PREPARE_DELAYED_WORK(&ap->port_task, fn);
+       ap->port_task_data = data;
 
-       if (!delay)
-               rc = queue_work(ata_wq, &ap->port_task);
-       else
-               rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
+       rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
 
        /* rc == 0 means that another user is using port task */
        WARN_ON(rc == 0);
@@ -2305,7 +2303,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
         * DMA cycle timing is slower/equal than the fastest PIO timing.
         */
 
-       if (speed > XFER_PIO_4) {
+       if (speed > XFER_PIO_6) {
                ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
                ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
        }
@@ -4588,10 +4586,11 @@ fsm_start:
        return poll_next;
 }
 
-static void ata_pio_task(void *_data)
+static void ata_pio_task(struct work_struct *work)
 {
-       struct ata_queued_cmd *qc = _data;
-       struct ata_port *ap = qc->ap;
+       struct ata_port *ap =
+               container_of(work, struct ata_port, port_task.work);
+       struct ata_queued_cmd *qc = ap->port_task_data;
        u8 status;
        int poll_next;
 
@@ -4961,6 +4960,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
        if (ap->flags & ATA_FLAG_PIO_POLLING) {
                switch (qc->tf.protocol) {
                case ATA_PROT_PIO:
+               case ATA_PROT_NODATA:
                case ATA_PROT_ATAPI:
                case ATA_PROT_ATAPI_NODATA:
                        qc->tf.flags |= ATA_TFLAG_POLLING;
@@ -5635,9 +5635,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
        ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
 #endif
 
-       INIT_WORK(&ap->port_task, NULL, NULL);
-       INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
-       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
+       INIT_DELAYED_WORK(&ap->port_task, NULL);
+       INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
        INIT_LIST_HEAD(&ap->eh_done_q);
        init_waitqueue_head(&ap->eh_wait_q);
 
index 76a85df..08ad44b 100644 (file)
@@ -332,7 +332,7 @@ void ata_scsi_error(struct Scsi_Host *host)
        if (ap->pflags & ATA_PFLAG_LOADING)
                ap->pflags &= ~ATA_PFLAG_LOADING;
        else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
-               queue_work(ata_aux_wq, &ap->hotplug_task);
+               queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0);
 
        if (ap->pflags & ATA_PFLAG_RECOVERED)
                ata_port_printk(ap, KERN_INFO, "EH complete\n");
index 8eaace9..664e137 100644 (file)
@@ -2963,7 +2963,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
 
 /**
  *     ata_scsi_hotplug - SCSI part of hotplug
- *     @data: Pointer to ATA port to perform SCSI hotplug on
+ *     @work: Pointer to ATA port to perform SCSI hotplug on
  *
  *     Perform SCSI part of hotplug.  It's executed from a separate
  *     workqueue after EH completes.  This is necessary because SCSI
@@ -2973,9 +2973,10 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
  *     LOCKING:
  *     Kernel thread context (may sleep).
  */
-void ata_scsi_hotplug(void *data)
+void ata_scsi_hotplug(struct work_struct *work)
 {
-       struct ata_port *ap = data;
+       struct ata_port *ap =
+               container_of(work, struct ata_port, hotplug_task.work);
        int i;
 
        if (ap->pflags & ATA_PFLAG_UNLOADING) {
@@ -3076,7 +3077,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 
 /**
  *     ata_scsi_dev_rescan - initiate scsi_rescan_device()
- *     @data: Pointer to ATA port to perform scsi_rescan_device()
+ *     @work: Pointer to ATA port to perform scsi_rescan_device()
  *
  *     After ATA pass thru (SAT) commands are executed successfully,
  *     libata need to propagate the changes to SCSI layer.  This
@@ -3086,9 +3087,10 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
  *     LOCKING:
  *     Kernel thread context (may sleep).
  */
-void ata_scsi_dev_rescan(void *data)
+void ata_scsi_dev_rescan(struct work_struct *work)
 {
-       struct ata_port *ap = data;
+       struct ata_port *ap =
+               container_of(work, struct ata_port, scsi_rescan_task);
        unsigned long flags;
        unsigned int i;
 
index 107b2b5..81ae41d 100644 (file)
@@ -94,7 +94,7 @@ extern struct scsi_transport_template ata_scsi_transport_template;
 
 extern void ata_scsi_scan_host(struct ata_port *ap);
 extern int ata_scsi_offline_dev(struct ata_device *dev);
-extern void ata_scsi_hotplug(void *data);
+extern void ata_scsi_hotplug(struct work_struct *work);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
                               unsigned int buflen);
 
@@ -124,7 +124,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
-extern void ata_scsi_dev_rescan(void *data);
+extern void ata_scsi_dev_rescan(struct work_struct *work);
 extern int ata_bus_probe(struct ata_port *ap);
 
 /* libata-eh.c */
index a2778cf..f055874 100644 (file)
@@ -66,15 +66,17 @@ enum {
        board_2037x             = 0,    /* FastTrak S150 TX2plus */
        board_20319             = 1,    /* FastTrak S150 TX4 */
        board_20619             = 2,    /* FastTrak TX4000 */
-       board_20771             = 3,    /* FastTrak TX2300 */
-       board_2057x             = 4,    /* SATAII150 Tx2plus */
-       board_40518             = 5,    /* SATAII150 Tx4 */
+       board_2057x             = 3,    /* SATAII150 Tx2plus */
+       board_40518             = 4,    /* SATAII150 Tx4 */
 
        PDC_HAS_PATA            = (1 << 1), /* PDC20375/20575 has PATA */
 
+       /* PDC_CTLSTAT bit definitions */
+       PDC_DMA_ENABLE          = (1 << 7),
+       PDC_IRQ_DISABLE         = (1 << 10),
        PDC_RESET               = (1 << 11), /* HDMA reset */
 
-       PDC_COMMON_FLAGS        = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+       PDC_COMMON_FLAGS        = ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
                                  ATA_FLAG_PIO_POLLING,
 
@@ -90,7 +92,6 @@ struct pdc_port_priv {
 
 struct pdc_host_priv {
        unsigned long           flags;
-       int                     hotplug_offset;
 };
 
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -101,13 +102,16 @@ static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
 static void pdc_pata_phy_reset(struct ata_port *ap);
-static void pdc_sata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_irq_clear(struct ata_port *ap);
 static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 static void pdc_host_stop(struct ata_host *host);
+static void pdc_freeze(struct ata_port *ap);
+static void pdc_thaw(struct ata_port *ap);
+static void pdc_error_handler(struct ata_port *ap);
+static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
 
 
 static struct scsi_host_template pdc_ata_sht = {
@@ -136,11 +140,12 @@ static const struct ata_port_operations pdc_sata_ops = {
        .exec_command           = pdc_exec_command_mmio,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = pdc_sata_phy_reset,
-
        .qc_prep                = pdc_qc_prep,
        .qc_issue               = pdc_qc_issue_prot,
-       .eng_timeout            = pdc_eng_timeout,
+       .freeze                 = pdc_freeze,
+       .thaw                   = pdc_thaw,
+       .error_handler          = pdc_error_handler,
+       .post_internal_cmd      = pdc_post_internal_cmd,
        .data_xfer              = ata_mmio_data_xfer,
        .irq_handler            = pdc_interrupt,
        .irq_clear              = pdc_irq_clear,
@@ -198,23 +203,13 @@ static const struct ata_port_info pdc_port_info[] = {
        /* board_20619 */
        {
                .sht            = &pdc_ata_sht,
-               .flags          = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+               .flags          = PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &pdc_pata_ops,
        },
 
-       /* board_20771 */
-       {
-               .sht            = &pdc_ata_sht,
-               .flags          = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &pdc_sata_ops,
-       },
-
        /* board_2057x */
        {
                .sht            = &pdc_ata_sht,
@@ -244,6 +239,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
        { PCI_VDEVICE(PROMISE, 0x3570), board_2057x },
        { PCI_VDEVICE(PROMISE, 0x3571), board_2057x },
        { PCI_VDEVICE(PROMISE, 0x3574), board_2057x },
+       { PCI_VDEVICE(PROMISE, 0x3577), board_2057x },
        { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x },
        { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x },
 
@@ -256,15 +252,6 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
 
        { PCI_VDEVICE(PROMISE, 0x6629), board_20619 },
 
-/* TODO: remove all associated board_20771 code, as it completely
- * duplicates board_2037x code, unless reason for separation can be
- * divined.
- */
-#if 0
-       { PCI_VDEVICE(PROMISE, 0x3570), board_20771 },
-#endif
-       { PCI_VDEVICE(PROMISE, 0x3577), board_20771 },
-
        { }     /* terminate list */
 };
 
@@ -366,12 +353,6 @@ static void pdc_reset_port(struct ata_port *ap)
        readl(mmio);    /* flush */
 }
 
-static void pdc_sata_phy_reset(struct ata_port *ap)
-{
-       pdc_reset_port(ap);
-       sata_phy_reset(ap);
-}
-
 static void pdc_pata_cbl_detect(struct ata_port *ap)
 {
        u8 tmp;
@@ -439,6 +420,61 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
        }
 }
 
+static void pdc_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       tmp = readl(mmio + PDC_CTLSTAT);
+       tmp |= PDC_IRQ_DISABLE;
+       tmp &= ~PDC_DMA_ENABLE;
+       writel(tmp, mmio + PDC_CTLSTAT);
+       readl(mmio + PDC_CTLSTAT); /* flush */
+}
+
+static void pdc_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       /* clear IRQ */
+       readl(mmio + PDC_INT_SEQMASK);
+
+       /* turn IRQ back on */
+       tmp = readl(mmio + PDC_CTLSTAT);
+       tmp &= ~PDC_IRQ_DISABLE;
+       writel(tmp, mmio + PDC_CTLSTAT);
+       readl(mmio + PDC_CTLSTAT); /* flush */
+}
+
+static void pdc_error_handler(struct ata_port *ap)
+{
+       ata_reset_fn_t hardreset;
+
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               pdc_reset_port(ap);
+
+       hardreset = NULL;
+       if (sata_scr_valid(ap))
+               hardreset = sata_std_hardreset;
+
+       /* perform recovery */
+       ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+                 ata_std_postreset);
+}
+
+static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       if (qc->flags & ATA_QCFLAG_FAILED)
+               qc->err_mask |= AC_ERR_OTHER;
+
+       /* make DMA engine forget about the failed command */
+       if (qc->err_mask)
+               pdc_reset_port(ap);
+}
+
 static void pdc_eng_timeout(struct ata_port *ap)
 {
        struct ata_host *host = ap->host;
@@ -645,9 +681,14 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 {
        void __iomem *mmio = pe->mmio_base;
        struct pdc_host_priv *hp = pe->private_data;
-       int hotplug_offset = hp->hotplug_offset;
+       int hotplug_offset;
        u32 tmp;
 
+       if (hp->flags & PDC_FLAG_GEN_II)
+               hotplug_offset = PDC2_SATA_PLUG_CSR;
+       else
+               hotplug_offset = PDC_SATA_PLUG_CSR;
+
        /*
         * Except for the hotplug stuff, this is voodoo from the
         * Promise driver.  Label this entire section
@@ -742,8 +783,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                goto err_out_free_ent;
        }
 
-       /* Set default hotplug offset */
-       hp->hotplug_offset = PDC_SATA_PLUG_CSR;
        probe_ent->private_data = hp;
 
        probe_ent->sht          = pdc_port_info[board_idx].sht;
@@ -767,8 +806,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        switch (board_idx) {
        case board_40518:
                hp->flags |= PDC_FLAG_GEN_II;
-               /* Override hotplug offset for SATAII150 */
-               hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
                /* Fall through */
        case board_20319:
                        probe_ent->n_ports = 4;
@@ -780,10 +817,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                probe_ent->port[3].scr_addr = base + 0x700;
                break;
        case board_2057x:
-       case board_20771:
                hp->flags |= PDC_FLAG_GEN_II;
-               /* Override hotplug offset for SATAII150 */
-               hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
                /* Fall through */
        case board_2037x:
                probe_ent->n_ports = 2;
index a165b71..fc0ae5e 100644 (file)
@@ -2,4 +2,4 @@
 fore200e_mkfirm
 fore200e_pca_fw.c
 pca200e.bin
-
+pca200e_ecd.bin2
index cfa5af8..2ddd76f 100644 (file)
@@ -242,6 +242,7 @@ config ATM_IDT77252_USE_SUNI
 config ATM_AMBASSADOR
        tristate "Madge Ambassador (Collage PCI 155 Server)"
        depends on PCI && ATM
+       select BITREVERSE
        help
          This is a driver for ATMizer based ATM card produced by Madge
          Networks Ltd. Say Y (or M to compile as a module named ambassador)
index b5077ce..1b16f81 100644 (file)
@@ -41,7 +41,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
   # guess the target endianess to choose the right PCA-200E firmware image
   ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
     byteorder.h                        := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
-    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
+    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
   endif
 endif
 
index afa7d75..3c372e0 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/poison.h>
+#include <linux/bitrev.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -2068,18 +2069,6 @@ static void __devinit amb_ucode_version (amb_dev * dev) {
   PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor);
 }
   
-// swap bits within byte to get Ethernet ordering
-static u8 bit_swap (u8 byte)
-{
-    const u8 swap[] = {
-      0x0, 0x8, 0x4, 0xc,
-      0x2, 0xa, 0x6, 0xe,
-      0x1, 0x9, 0x5, 0xd,
-      0x3, 0xb, 0x7, 0xf
-    };
-    return ((swap[byte & 0xf]<<4) | swap[byte>>4]);
-}
-
 // get end station address
 static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
   u32 lower4;
@@ -2101,9 +2090,9 @@ static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
     PRINTDB (DBG_INIT, "ESI:");
     for (i = 0; i < ESI_LEN; ++i) {
       if (i < 4)
-         esi[i] = bit_swap (lower4>>(8*i));
+         esi[i] = bitrev8(lower4>>(8*i));
       else
-         esi[i] = bit_swap (upper2>>(8*(i-4)));
+         esi[i] = bitrev8(upper2>>(8*(i-4)));
       PRINTDM (DBG_INIT, " %02x", esi[i]);
     }
     
index c7314a7..7d9b4e5 100644 (file)
@@ -820,7 +820,7 @@ he_init_group(struct he_dev *he_dev, int group)
                void *cpuaddr;
 
 #ifdef USE_RBPS_POOL 
-               cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+               cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
                        return -ENOMEM;
 #else
@@ -884,7 +884,7 @@ he_init_group(struct he_dev *he_dev, int group)
                void *cpuaddr;
 
 #ifdef USE_RBPL_POOL
-               cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+               cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
                if (cpuaddr == NULL)
                        return -ENOMEM;
 #else
@@ -1724,7 +1724,7 @@ __alloc_tpd(struct he_dev *he_dev)
        struct he_tpd *tpd;
        dma_addr_t dma_handle; 
 
-       tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);              
+       tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle);
        if (tpd == NULL)
                return NULL;
                        
index 87b17c3..f407861 100644 (file)
@@ -135,7 +135,7 @@ static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
                               int flags);
 static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
                              char *page);
-static void idt77252_softint(void *dev_id);
+static void idt77252_softint(struct work_struct *work);
 
 
 static struct atmdev_ops idt77252_ops =
@@ -2866,9 +2866,10 @@ out:
 }
 
 static void
-idt77252_softint(void *dev_id)
+idt77252_softint(struct work_struct *work)
 {
-       struct idt77252_dev *card = dev_id;
+       struct idt77252_dev *card =
+               container_of(work, struct idt77252_dev, tqueue);
        u32 stat;
        int done;
 
@@ -3697,7 +3698,7 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
        card->pcidev = pcidev;
        sprintf(card->name, "idt77252-%d", card->index);
 
-       INIT_WORK(&card->tqueue, idt77252_softint, (void *)card);
+       INIT_WORK(&card->tqueue, idt77252_softint);
 
        membase = pci_resource_start(pcidev, 1);
        srambase = pci_resource_start(pcidev, 2);
index e4b530e..67b79a7 100644 (file)
@@ -386,6 +386,7 @@ void device_initialize(struct device *dev)
        INIT_LIST_HEAD(&dev->node);
        init_MUTEX(&dev->sem);
        device_init_wakeup(dev, 0);
+       set_dev_node(dev, -1);
 }
 
 #ifdef CONFIG_SYSFS_DEPRECATED
index 1f745f1..7fd095e 100644 (file)
@@ -104,8 +104,8 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
 
 /*
  * register_cpu - Setup a driverfs device for a CPU.
- * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
- *               generate a control file in sysfs for this CPU.
+ * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
+ *       sysfs for this CPU.
  * @num - CPU number to use when creating the device.
  *
  * Initialize and register the CPU device.
@@ -119,7 +119,7 @@ int __devinit register_cpu(struct cpu *cpu, int num)
 
        error = sysdev_register(&cpu->sysdev);
 
-       if (!error && !cpu->no_control)
+       if (!error && cpu->hotpluggable)
                register_cpu_control(cpu);
        if (!error)
                cpu_sys_devices[num] = &cpu->sysdev;
index b2efbd4..dbe0735 100644 (file)
@@ -126,7 +126,7 @@ dma_pool_create (const char *name, struct device *dev,
        } else if (allocation < size)
                return NULL;
 
-       if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL)))
+       if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL)))
                return retval;
 
        strlcpy (retval->name, name, sizeof retval->name);
@@ -297,7 +297,7 @@ restart:
                        }
                }
        }
-       if (!(page = pool_alloc_page (pool, SLAB_ATOMIC))) {
+       if (!(page = pool_alloc_page (pool, GFP_ATOMIC))) {
                if (mem_flags & __GFP_WAIT) {
                        DECLARE_WAITQUEUE (wait, current);
 
index c6b7d9c..74b9679 100644 (file)
@@ -290,9 +290,8 @@ static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
 
 static int block_size_init(void)
 {
-       sysfs_create_file(&memory_sysdev_class.kset.kobj,
-               &class_attr_block_size_bytes.attr);
-       return 0;
+       return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+                               &class_attr_block_size_bytes.attr);
 }
 
 /*
@@ -323,12 +322,14 @@ static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
 
 static int memory_probe_init(void)
 {
-       sysfs_create_file(&memory_sysdev_class.kset.kobj,
-               &class_attr_probe.attr);
-       return 0;
+       return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+                               &class_attr_probe.attr);
 }
 #else
-#define memory_probe_init(...) do {} while (0)
+static inline int memory_probe_init(void)
+{
+       return 0;
+}
 #endif
 
 /*
@@ -431,9 +432,12 @@ int __init memory_dev_init(void)
 {
        unsigned int i;
        int ret;
+       int err;
 
        memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
        ret = sysdev_class_register(&memory_sysdev_class);
+       if (ret)
+               goto out;
 
        /*
         * Create entries for memory sections that were found
@@ -442,11 +446,19 @@ int __init memory_dev_init(void)
        for (i = 0; i < NR_MEM_SECTIONS; i++) {
                if (!valid_section_nr(i))
                        continue;
-               add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+               err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+               if (!ret)
+                       ret = err;
        }
 
-       memory_probe_init();
-       block_size_init();
-
+       err = memory_probe_init();
+       if (!ret)
+               ret = err;
+       err = block_size_init();
+       if (!ret)
+               ret = err;
+out:
+       if (ret)
+               printk(KERN_ERR "%s() failed: %d\n", __FUNCTION__, ret);
        return ret;
 }
index 3d12b85..067a9e8 100644 (file)
@@ -108,7 +108,6 @@ static int __cpuinit topology_add_dev(unsigned int cpu)
        return rc;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void __cpuinit topology_remove_dev(unsigned int cpu)
 {
        struct sys_device *sys_dev = get_cpu_sysdev(cpu);
@@ -136,7 +135,6 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
        }
        return rc ? NOTIFY_BAD : NOTIFY_OK;
 }
-#endif
 
 static int __cpuinit topology_sysfs_init(void)
 {
index 742d074..8d81a3a 100644 (file)
@@ -324,13 +324,13 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
       Command->Next = Controller->FreeCommands;
       Controller->FreeCommands = Command;
       Controller->Commands[CommandIdentifier-1] = Command;
-      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC,
+      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, GFP_ATOMIC,
                                                        &ScatterGatherDMA);
       if (ScatterGatherCPU == NULL)
          return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
 
       if (RequestSensePool != NULL) {
-         RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC,
+         RequestSenseCPU = pci_pool_alloc(RequestSensePool, GFP_ATOMIC,
                                                &RequestSenseDMA);
          if (RequestSenseCPU == NULL) {
                 pci_pool_free(ScatterGatherPool, ScatterGatherCPU,
index 17dc222..ce9cfcb 100644 (file)
@@ -168,7 +168,8 @@ config BLK_CPQ_CISS_DA
 
 config CISS_SCSI_TAPE
        bool "SCSI tape drive support for Smart Array 5xxx"
-       depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS
+       depends on BLK_CPQ_CISS_DA && PROC_FS
+       depends on SCSI=y || SCSI=BLK_CPQ_CISS_DA
        help
          When enabled (Y), this option allows SCSI tape drives and SCSI medium
          changers (tape robots) to be accessed via a Compaq 5xxx array 
@@ -305,6 +306,7 @@ config BLK_DEV_LOOP
 config BLK_DEV_CRYPTOLOOP
        tristate "Cryptoloop Support"
        select CRYPTO
+       select CRYPTO_CBC
        depends on BLK_DEV_LOOP
        ---help---
          Say Y here if you want to be able to use the ciphers that are 
@@ -429,14 +431,18 @@ config CDROM_PKTCDVD
        tristate "Packet writing on CD/DVD media"
        depends on !UML
        help
-         If you have a CDROM drive that supports packet writing, say Y to
-         include preliminary support. It should work with any MMC/Mt Fuji
-         compliant ATAPI or SCSI drive, which is just about any newer CD
-         writer.
+         If you have a CDROM/DVD drive that supports packet writing, say
+         Y to include support. It should work with any MMC/Mt Fuji
+         compliant ATAPI or SCSI drive, which is just about any newer
+         DVD/CD writer.
 
-         Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible.
+         Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs
+         is possible.
          DVD-RW disks must be in restricted overwrite mode.
 
+         See the file <file:Documentation/cdrom/packet-writing.txt>
+         for further information on the use of this driver.
+
          To compile this driver as a module, choose M here: the
          module will be called pktcdvd.
 
index 8e41c87..e04be94 100644 (file)
@@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
                                                 loff_t *ppos )
 
 {
-       struct inode *node = file->f_dentry->d_inode;
+       struct inode *node = file->f_path.dentry->d_inode;
        unsigned long page;
        int length;
        int end;
@@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count,
                                                  loff_t *ppos )
 
 {
-       struct inode *node = file->f_dentry->d_inode;
+       struct inode *node = file->f_path.dentry->d_inode;
        int             device = iminor(node);
        int             n, filled, w, h;
 
index 6d11122..2308e83 100644 (file)
@@ -159,7 +159,7 @@ void aoecmd_work(struct aoedev *d);
 void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
 void aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
-void aoecmd_sleepwork(void *vp);
+void aoecmd_sleepwork(struct work_struct *);
 struct sk_buff *new_skb(ulong);
 
 int aoedev_init(void);
index aa25f8b..478489c 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/netdevice.h>
 #include "aoe.h"
 
-static kmem_cache_t *buf_pool_cache;
+static struct kmem_cache *buf_pool_cache;
 
 static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
 {
index 8a13b1a..97f7f53 100644 (file)
@@ -408,9 +408,9 @@ rexmit_timer(ulong vp)
 /* this function performs work that has been deferred until sleeping is OK
  */
 void
-aoecmd_sleepwork(void *vp)
+aoecmd_sleepwork(struct work_struct *work)
 {
-       struct aoedev *d = (struct aoedev *) vp;
+       struct aoedev *d = container_of(work, struct aoedev, work);
 
        if (d->flags & DEVFL_GDALLOC)
                aoeblk_gdalloc(d);
index 6125921..05a9719 100644 (file)
@@ -88,7 +88,7 @@ aoedev_newdev(ulong nframes)
                        kfree(d);
                return NULL;
        }
-       INIT_WORK(&d->work, aoecmd_sleepwork, d);
+       INIT_WORK(&d->work, aoecmd_sleepwork);
        spin_lock_init(&d->lock);
        init_timer(&d->timer);
        d->timer.data = (ulong) d;
index 4105c3b..ee159ed 100644 (file)
 #include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 3.6.10)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,10)
+#define DRIVER_NAME "HP CISS Driver (v 3.6.14)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.10");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14");
 MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
                        " SA6i P600 P800 P400 P400i E200 E200i E500");
+MODULE_VERSION("3.6.14");
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -81,7 +82,9 @@ static const struct pci_device_id cciss_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3213},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3214},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3215},
-       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3233},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3237},
+       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
 };
 
@@ -90,27 +93,29 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
 /*  board_id = Subsystem Device ID & Vendor ID
  *  product = Marketing Name for the board
  *  access = Address of the struct of function pointers
+ *  nr_cmds = Number of commands supported by controller
  */
 static struct board_type products[] = {
-       {0x40700E11, "Smart Array 5300", &SA5_access},
-       {0x40800E11, "Smart Array 5i", &SA5B_access},
-       {0x40820E11, "Smart Array 532", &SA5B_access},
-       {0x40830E11, "Smart Array 5312", &SA5B_access},
-       {0x409A0E11, "Smart Array 641", &SA5_access},
-       {0x409B0E11, "Smart Array 642", &SA5_access},
-       {0x409C0E11, "Smart Array 6400", &SA5_access},
-       {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
-       {0x40910E11, "Smart Array 6i", &SA5_access},
-       {0x3225103C, "Smart Array P600", &SA5_access},
-       {0x3223103C, "Smart Array P800", &SA5_access},
-       {0x3234103C, "Smart Array P400", &SA5_access},
-       {0x3235103C, "Smart Array P400i", &SA5_access},
-       {0x3211103C, "Smart Array E200i", &SA5_access},
-       {0x3212103C, "Smart Array E200", &SA5_access},
-       {0x3213103C, "Smart Array E200i", &SA5_access},
-       {0x3214103C, "Smart Array E200i", &SA5_access},
-       {0x3215103C, "Smart Array E200i", &SA5_access},
-       {0x3233103C, "Smart Array E500", &SA5_access},
+       {0x40700E11, "Smart Array 5300", &SA5_access, 512},
+       {0x40800E11, "Smart Array 5i", &SA5B_access, 512},
+       {0x40820E11, "Smart Array 532", &SA5B_access, 512},
+       {0x40830E11, "Smart Array 5312", &SA5B_access, 512},
+       {0x409A0E11, "Smart Array 641", &SA5_access, 512},
+       {0x409B0E11, "Smart Array 642", &SA5_access, 512},
+       {0x409C0E11, "Smart Array 6400", &SA5_access, 512},
+       {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512},
+       {0x40910E11, "Smart Array 6i", &SA5_access, 512},
+       {0x3225103C, "Smart Array P600", &SA5_access, 512},
+       {0x3223103C, "Smart Array P800", &SA5_access, 512},
+       {0x3234103C, "Smart Array P400", &SA5_access, 512},
+       {0x3235103C, "Smart Array P400i", &SA5_access, 512},
+       {0x3211103C, "Smart Array E200i", &SA5_access, 120},
+       {0x3212103C, "Smart Array E200", &SA5_access, 120},
+       {0x3213103C, "Smart Array E200i", &SA5_access, 120},
+       {0x3214103C, "Smart Array E200i", &SA5_access, 120},
+       {0x3215103C, "Smart Array E200i", &SA5_access, 120},
+       {0x3237103C, "Smart Array E500", &SA5_access, 512},
+       {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
 };
 
 /* How long to wait (in milliseconds) for board to go into simple mode */
@@ -121,7 +126,6 @@ static struct board_type products[] = {
 #define MAX_CMD_RETRIES 3
 
 #define READ_AHEAD      1024
-#define NR_CMDS                 384    /* #commands that can be outstanding */
 #define MAX_CTLR       32
 
 /* Originally cciss driver only supports 8 major numbers */
@@ -137,7 +141,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                       unsigned int cmd, unsigned long arg);
 static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
-static int revalidate_allvol(ctlr_info_t *host);
 static int cciss_revalidate(struct gendisk *disk);
 static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
 static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
@@ -265,6 +268,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
                       "Firmware Version: %c%c%c%c\n"
                       "IRQ: %d\n"
                       "Logical drives: %d\n"
+                      "Max sectors: %d\n"
                       "Current Q depth: %d\n"
                       "Current # commands on controller: %d\n"
                       "Max Q depth since init: %d\n"
@@ -275,7 +279,9 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
                       (unsigned long)h->board_id,
                       h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
                       h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT],
-                      h->num_luns, h->Qdepth, h->commands_outstanding,
+                      h->num_luns,
+                      h->cciss_max_sectors,
+                      h->Qdepth, h->commands_outstanding,
                       h->maxQsinceinit, h->max_outstanding, h->maxSG);
 
        pos += size;
@@ -400,8 +406,8 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
        } else {                /* get it out of the controllers pool */
 
                do {
-                       i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
-                       if (i == NR_CMDS)
+                       i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
+                       if (i == h->nr_cmds)
                                return NULL;
                } while (test_and_set_bit
                         (i & (BITS_PER_LONG - 1),
@@ -487,7 +493,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
         * but I'm already using way to many device nodes to claim another one
         * for "raw controller".
         */
-       if (drv->nr_blocks == 0) {
+       if (drv->heads == 0) {
                if (iminor(inode) != 0) {       /* not node 0? */
                        /* if not node 0 make sure it is a partition = 0 */
                        if (iminor(inode) & 0x0f) {
@@ -529,7 +535,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
 {
        int ret;
        lock_kernel();
-       ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+       ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
        unlock_kernel();
        return ret;
 }
@@ -850,9 +856,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                }
 
        case CCISS_REVALIDVOLS:
-               if (bdev != bdev->bd_contains || drv != host->drv)
-                       return -ENXIO;
-               return revalidate_allvol(host);
+               return rebuild_lun_table(host, NULL);
 
        case CCISS_GETLUNINFO:{
                        LogvolInfo_struct luninfo;
@@ -1152,75 +1156,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
        }
 }
 
-/*
- * revalidate_allvol is for online array config utilities.  After a
- * utility reconfigures the drives in the array, it can use this function
- * (through an ioctl) to make the driver zap any previous disk structs for
- * that controller and get new ones.
- *
- * Right now I'm using the getgeometry() function to do this, but this
- * function should probably be finer grained and allow you to revalidate one
- * particular logical volume (instead of all of them on a particular
- * controller).
- */
-static int revalidate_allvol(ctlr_info_t *host)
-{
-       int ctlr = host->ctlr, i;
-       unsigned long flags;
-
-       spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-       if (host->usage_count > 1) {
-               spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-               printk(KERN_WARNING "cciss: Device busy for volume"
-                      " revalidation (usage=%d)\n", host->usage_count);
-               return -EBUSY;
-       }
-       host->usage_count++;
-       spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-
-       for (i = 0; i < NWD; i++) {
-               struct gendisk *disk = host->gendisk[i];
-               if (disk) {
-                       request_queue_t *q = disk->queue;
-
-                       if (disk->flags & GENHD_FL_UP)
-                               del_gendisk(disk);
-                       if (q)
-                               blk_cleanup_queue(q);
-               }
-       }
-
-       /*
-        * Set the partition and block size structures for all volumes
-        * on this controller to zero.  We will reread all of this data
-        */
-       memset(host->drv, 0, sizeof(drive_info_struct)
-              * CISS_MAX_LUN);
-       /*
-        * Tell the array controller not to give us any interrupts while
-        * we check the new geometry.  Then turn interrupts back on when
-        * we're done.
-        */
-       host->access.set_intr_mask(host, CCISS_INTR_OFF);
-       cciss_getgeometry(ctlr);
-       host->access.set_intr_mask(host, CCISS_INTR_ON);
-
-       /* Loop through each real device */
-       for (i = 0; i < NWD; i++) {
-               struct gendisk *disk = host->gendisk[i];
-               drive_info_struct *drv = &(host->drv[i]);
-               /* we must register the controller even if no disks exist */
-               /* this is for the online array utilities */
-               if (!drv->heads && i)
-                       continue;
-               blk_queue_hardsect_size(drv->queue, drv->block_size);
-               set_capacity(disk, drv->nr_blocks);
-               add_disk(disk);
-       }
-       host->usage_count--;
-       return 0;
-}
-
 static inline void complete_buffers(struct bio *bio, int status)
 {
        while (bio) {
@@ -1243,7 +1178,7 @@ static void cciss_check_queues(ctlr_info_t *h)
         * in case the interrupt we serviced was from an ioctl and did not
         * free any new commands.
         */
-       if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+       if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds)
                return;
 
        /* We have room on the queue for more commands.  Now we need to queue
@@ -1262,7 +1197,7 @@ static void cciss_check_queues(ctlr_info_t *h)
                /* check to see if we have maxed out the number of commands
                 * that can be placed on the queue.
                 */
-               if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
+               if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) {
                        if (curr_queue == start_queue) {
                                h->next_to_run =
                                    (start_queue + 1) % (h->highest_lun + 1);
@@ -1380,6 +1315,11 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
        /* if it's the controller it's already added */
        if (drv_index) {
                disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+               sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index);
+               disk->major = h->major;
+               disk->first_minor = drv_index << NWD_SHIFT;
+               disk->fops = &cciss_fops;
+               disk->private_data = &h->drv[drv_index];
 
                /* Set up queue information */
                disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
@@ -1391,7 +1331,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
                /* This is a limit in the driver and could be eliminated. */
                blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
 
-               blk_queue_max_sectors(disk->queue, 512);
+               blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
 
                blk_queue_softirq_done(disk->queue, cciss_softirq_done);
 
@@ -1458,11 +1398,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
 
        /* Set busy_configuring flag for this operation */
        spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
-       if (h->num_luns >= CISS_MAX_LUN) {
-               spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
-               return -EINVAL;
-       }
-
        if (h->busy_configuring) {
                spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
                return -EBUSY;
@@ -1495,17 +1430,8 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
                                              0, 0, TYPE_CMD);
 
                if (return_code == IO_OK) {
-                       listlength |=
-                           (0xff & (unsigned int)(ld_buff->LUNListLength[0]))
-                           << 24;
-                       listlength |=
-                           (0xff & (unsigned int)(ld_buff->LUNListLength[1]))
-                           << 16;
-                       listlength |=
-                           (0xff & (unsigned int)(ld_buff->LUNListLength[2]))
-                           << 8;
-                       listlength |=
-                           0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+                       listlength =
+                               be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
                } else {        /* reading number of logical volumes failed */
                        printk(KERN_WARNING "cciss: report logical volume"
                               " command failed\n");
@@ -1556,6 +1482,14 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
                                if (drv_index == -1)
                                        goto freeret;
 
+                               /*Check if the gendisk needs to be allocated */
+                               if (!h->gendisk[drv_index]){
+                                       h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT);
+                                       if (!h->gendisk[drv_index]){
+                                               printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index);
+                                               goto mem_msg;
+                                       }
+                               }
                        }
                        h->drv[drv_index].LunID = lunid;
                        cciss_update_drive_info(ctlr, drv_index);
@@ -1593,6 +1527,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
 static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
                           int clear_all)
 {
+       int i;
        ctlr_info_t *h = get_host(disk);
 
        if (!capable(CAP_SYS_RAWIO))
@@ -1616,9 +1551,35 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
                                del_gendisk(disk);
                        if (q) {
                                blk_cleanup_queue(q);
+                               /* Set drv->queue to NULL so that we do not try
+                                * to call blk_start_queue on this queue in the
+                                * interrupt handler
+                                */
                                drv->queue = NULL;
                        }
+                       /* If clear_all is set then we are deleting the logical
+                        * drive, not just refreshing its info.  For drives
+                        * other than disk 0 we will call put_disk.  We do not
+                        * do this for disk 0 as we need it to be able to
+                        * configure the controller.
+                       */
+                       if (clear_all){
+                               /* This isn't pretty, but we need to find the
+                                * disk in our array and NULL our the pointer.
+                                * This is so that we will call alloc_disk if
+                                * this index is used again later.
+                               */
+                               for (i=0; i < CISS_MAX_LUN; i++){
+                                       if(h->gendisk[i] == disk){
+                                               h->gendisk[i] = NULL;
+                                               break;
+                                       }
+                               }
+                               put_disk(disk);
+                       }
                }
+       } else {
+               set_capacity(disk, 0);
        }
 
        --h->num_luns;
@@ -2136,7 +2097,7 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
 
        /* We've sent down an abort or reset, but something else
           has completed */
-       if (srl->ncompletions >= (NR_CMDS + 2)) {
+       if (srl->ncompletions >= (hba[ctlr]->nr_cmds + 2)) {
                /* Uh oh.  No room to save it for later... */
                printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
                       "reject list overflow, command lost!\n", ctlr);
@@ -2673,7 +2634,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
                        a1 = a;
                        if ((a & 0x04)) {
                                a2 = (a >> 3);
-                               if (a2 >= NR_CMDS) {
+                               if (a2 >= h->nr_cmds) {
                                        printk(KERN_WARNING
                                               "cciss: controller cciss%d failed, stopping.\n",
                                               h->ctlr);
@@ -2827,23 +2788,21 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c,
                if (err > 0) {
                        printk(KERN_WARNING "cciss: only %d MSI-X vectors "
                               "available\n", err);
+                       goto default_int_mode;
                } else {
                        printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
                               err);
+                       goto default_int_mode;
                }
        }
        if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
                if (!pci_enable_msi(pdev)) {
-                       c->intr[SIMPLE_MODE_INT] = pdev->irq;
                        c->msi_vector = 1;
-                       return;
                } else {
                        printk(KERN_WARNING "cciss: MSI init failed\n");
-                       c->intr[SIMPLE_MODE_INT] = pdev->irq;
-                       return;
                }
        }
-      default_int_mode:
+default_int_mode:
 #endif                         /* CONFIG_PCI_MSI */
        /* if we get here we're going to use the default interrupt mode */
        c->intr[SIMPLE_MODE_INT] = pdev->irq;
@@ -2956,16 +2915,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
                if (board_id == products[i].board_id) {
                        c->product_name = products[i].product_name;
                        c->access = *(products[i].access);
+                       c->nr_cmds = products[i].nr_cmds;
                        break;
                }
        }
-       if (i == ARRAY_SIZE(products)) {
-               printk(KERN_WARNING "cciss: Sorry, I don't know how"
-                      " to access the Smart Array controller %08lx\n",
-                      (unsigned long)board_id);
-               err = -ENODEV;
-               goto err_out_free_res;
-       }
        if ((readb(&c->cfgtable->Signature[0]) != 'C') ||
            (readb(&c->cfgtable->Signature[1]) != 'I') ||
            (readb(&c->cfgtable->Signature[2]) != 'S') ||
@@ -2974,6 +2927,27 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
                err = -ENODEV;
                goto err_out_free_res;
        }
+       /* We didn't find the controller in our list. We know the
+        * signature is valid. If it's an HP device let's try to
+        * bind to the device and fire it up. Otherwise we bail.
+        */
+       if (i == ARRAY_SIZE(products)) {
+               if (subsystem_vendor_id == PCI_VENDOR_ID_HP) {
+                       c->product_name = products[i-1].product_name;
+                       c->access = *(products[i-1].access);
+                       c->nr_cmds = products[i-1].nr_cmds;
+                       printk(KERN_WARNING "cciss: This is an unknown "
+                               "Smart Array controller.\n"
+                               "cciss: Please update to the latest driver "
+                               "available from www.hp.com.\n");
+               } else {
+                       printk(KERN_WARNING "cciss: Sorry, I don't know how"
+                               " to access the Smart Array controller %08lx\n"
+                                       , (unsigned long)board_id);
+                       err = -ENODEV;
+                       goto err_out_free_res;
+               }
+       }
 #ifdef CONFIG_X86
        {
                /* Need to enable prefetch in the SCSI core for 6400 in x86 */
@@ -2984,6 +2958,17 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
 #endif
 
+       /* Disabling DMA prefetch for the P600
+        * An ASIC bug may result in a prefetch beyond
+        * physical memory.
+        */
+       if(board_id == 0x3225103C) {
+               __u32 dma_prefetch;
+               dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG);
+               dma_prefetch |= 0x8000;
+               writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG);
+       }
+
 #ifdef CCISS_DEBUG
        printk("Trying to put board into Simple mode\n");
 #endif                         /* CCISS_DEBUG */
@@ -3158,13 +3143,7 @@ geo_inq:
 /* Returns -1 if no free entries are left.  */
 static int alloc_cciss_hba(void)
 {
-       struct gendisk *disk[NWD];
-       int i, n;
-       for (n = 0; n < NWD; n++) {
-               disk[n] = alloc_disk(1 << NWD_SHIFT);
-               if (!disk[n])
-                       goto out;
-       }
+       int i;
 
        for (i = 0; i < MAX_CTLR; i++) {
                if (!hba[i]) {
@@ -3172,20 +3151,18 @@ static int alloc_cciss_hba(void)
                        p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
                        if (!p)
                                goto Enomem;
-                       for (n = 0; n < NWD; n++)
-                               p->gendisk[n] = disk[n];
+                       p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
+                       if (!p->gendisk[0])
+                               goto Enomem;
                        hba[i] = p;
                        return i;
                }
        }
        printk(KERN_WARNING "cciss: This driver supports a maximum"
               " of %d controllers.\n", MAX_CTLR);
-       goto out;
-      Enomem:
+       return -1;
+Enomem:
        printk(KERN_ERR "cciss: out of memory.\n");
-      out:
-       while (n--)
-               put_disk(disk[n]);
        return -1;
 }
 
@@ -3195,7 +3172,7 @@ static void free_hba(int i)
        int n;
 
        hba[i] = NULL;
-       for (n = 0; n < NWD; n++)
+       for (n = 0; n < CISS_MAX_LUN; n++)
                put_disk(p->gendisk[n]);
        kfree(p);
 }
@@ -3208,9 +3185,8 @@ static void free_hba(int i)
 static int __devinit cciss_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
-       request_queue_t *q;
        int i;
-       int j;
+       int j = 0;
        int rc;
        int dac;
 
@@ -3269,15 +3245,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
               hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not");
 
        hba[i]->cmd_pool_bits =
-           kmalloc(((NR_CMDS + BITS_PER_LONG -
+           kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG -
                      1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
        hba[i]->cmd_pool = (CommandList_struct *)
            pci_alloc_consistent(hba[i]->pdev,
-                   NR_CMDS * sizeof(CommandList_struct),
+                   hba[i]->nr_cmds * sizeof(CommandList_struct),
                    &(hba[i]->cmd_pool_dhandle));
        hba[i]->errinfo_pool = (ErrorInfo_struct *)
            pci_alloc_consistent(hba[i]->pdev,
-                   NR_CMDS * sizeof(ErrorInfo_struct),
+                   hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
                    &(hba[i]->errinfo_pool_dhandle));
        if ((hba[i]->cmd_pool_bits == NULL)
            || (hba[i]->cmd_pool == NULL)
@@ -3288,7 +3264,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 #ifdef CONFIG_CISS_SCSI_TAPE
        hba[i]->scsi_rejects.complete =
            kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
-                   (NR_CMDS + 5), GFP_KERNEL);
+                   (hba[i]->nr_cmds + 5), GFP_KERNEL);
        if (hba[i]->scsi_rejects.complete == NULL) {
                printk(KERN_ERR "cciss: out of memory");
                goto clean4;
@@ -3302,7 +3278,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        /* command and error info recs zeroed out before
           they are used */
        memset(hba[i]->cmd_pool_bits, 0,
-              ((NR_CMDS + BITS_PER_LONG -
+              ((hba[i]->nr_cmds + BITS_PER_LONG -
                 1) / BITS_PER_LONG) * sizeof(unsigned long));
 
 #ifdef CCISS_DEBUG
@@ -3317,18 +3293,34 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
        cciss_procinit(i);
+
+       hba[i]->cciss_max_sectors = 2048;
+
        hba[i]->busy_initializing = 0;
 
-       for (j = 0; j < NWD; j++) {     /* mfm */
+       do {
                drive_info_struct *drv = &(hba[i]->drv[j]);
                struct gendisk *disk = hba[i]->gendisk[j];
+               request_queue_t *q;
+
+               /* Check if the disk was allocated already */
+               if (!disk){
+                       hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT);
+                       disk = hba[i]->gendisk[j];
+               }
+
+               /* Check that the disk was able to be allocated */
+               if (!disk) {
+                       printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j);
+                       goto clean4;
+               }
 
                q = blk_init_queue(do_cciss_request, &hba[i]->lock);
                if (!q) {
                        printk(KERN_ERR
                               "cciss:  unable to allocate queue for disk %d\n",
                               j);
-                       break;
+                       goto clean4;
                }
                drv->queue = q;
 
@@ -3341,7 +3333,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                /* This is a limit in the driver and could be eliminated. */
                blk_queue_max_phys_segments(q, MAXSGENTRIES);
 
-               blk_queue_max_sectors(q, 512);
+               blk_queue_max_sectors(q, hba[i]->cciss_max_sectors);
 
                blk_queue_softirq_done(q, cciss_softirq_done);
 
@@ -3360,7 +3352,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                blk_queue_hardsect_size(q, drv->block_size);
                set_capacity(disk, drv->nr_blocks);
                add_disk(disk);
-       }
+               j++;
+       } while (j <= hba[i]->highest_lun);
 
        return 1;
 
@@ -3371,11 +3364,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        kfree(hba[i]->cmd_pool_bits);
        if (hba[i]->cmd_pool)
                pci_free_consistent(hba[i]->pdev,
-                                   NR_CMDS * sizeof(CommandList_struct),
+                                   hba[i]->nr_cmds * sizeof(CommandList_struct),
                                    hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
        if (hba[i]->errinfo_pool)
                pci_free_consistent(hba[i]->pdev,
-                                   NR_CMDS * sizeof(ErrorInfo_struct),
+                                   hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
                                    hba[i]->errinfo_pool,
                                    hba[i]->errinfo_pool_dhandle);
        free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
@@ -3383,6 +3376,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        unregister_blkdev(hba[i]->major, hba[i]->devname);
       clean1:
        hba[i]->busy_initializing = 0;
+       /* cleanup any queues that may have been initialized */
+       for (j=0; j <= hba[i]->highest_lun; j++){
+               drive_info_struct *drv = &(hba[i]->drv[j]);
+               if (drv->queue)
+                       blk_cleanup_queue(drv->queue);
+       }
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
        free_hba(i);
        return -1;
 }
@@ -3430,7 +3432,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
        remove_proc_entry(hba[i]->devname, proc_cciss);
 
        /* remove it from the disk list */
-       for (j = 0; j < NWD; j++) {
+       for (j = 0; j < CISS_MAX_LUN; j++) {
                struct gendisk *disk = hba[i]->gendisk[j];
                if (disk) {
                        request_queue_t *q = disk->queue;
@@ -3442,9 +3444,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
                }
        }
 
-       pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
+       pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct),
                            hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
-       pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct),
+       pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
                            hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
        kfree(hba[i]->cmd_pool_bits);
 #ifdef CONFIG_CISS_SCSI_TAPE
index 562235c..b70988d 100644 (file)
@@ -6,7 +6,6 @@
 #include "cciss_cmd.h"
 
 
-#define NWD            16
 #define NWD_SHIFT      4
 #define MAX_PART       (1 << NWD_SHIFT)
 
@@ -60,6 +59,7 @@ struct ctlr_info
        __u32   board_id;
        void __iomem *vaddr;
        unsigned long paddr;
+       int     nr_cmds; /* Number of commands allowed on this controller */
        CfgTable_struct __iomem *cfgtable;
        int     interrupts_enabled;
        int     major;
@@ -76,6 +76,7 @@ struct ctlr_info
        unsigned int intr[4];
        unsigned int msix_vector;
        unsigned int msi_vector;
+       int     cciss_max_sectors;
        BYTE    cciss_read;
        BYTE    cciss_write;
        BYTE    cciss_read_capacity;
@@ -110,7 +111,7 @@ struct ctlr_info
        int                     next_to_run;
 
        // Disk structures we need to pass back
-       struct gendisk   *gendisk[NWD];
+       struct gendisk   *gendisk[CISS_MAX_LUN];
 #ifdef CONFIG_CISS_SCSI_TAPE
        void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
        /* list of block side commands the scsi error handling sucked up */
@@ -282,6 +283,7 @@ struct board_type {
        __u32   board_id;
        char    *product_name;
        struct access_method *access;
+       int nr_cmds; /* Max cmds this kind of ctlr can handle. */
 };
 
 #define CCISS_LOCK(i)  (&hba[i]->lock)
index 4af7c4c..43bf559 100644 (file)
@@ -55,6 +55,7 @@
 #define I2O_INT_MASK            0x34
 #define I2O_IBPOST_Q            0x40
 #define I2O_OBPOST_Q            0x44
+#define I2O_DMA1_CFG           0x214
 
 //Configuration Table
 #define CFGTBL_ChangeReq        0x00000001l
@@ -88,7 +89,7 @@ typedef union _u64bit
 //###########################################################################
 //STRUCTURES
 //###########################################################################
-#define CISS_MAX_LUN   16      
+#define CISS_MAX_LUN   1024
 #define CISS_MAX_PHYS_LUN      1024
 // SCSI-3 Cmmands 
 
index 9e6d3a8..3f1b382 100644 (file)
@@ -992,11 +992,11 @@ static void empty(void)
 {
 }
 
-static DECLARE_WORK(floppy_work, NULL, NULL);
+static DECLARE_WORK(floppy_work, NULL);
 
 static void schedule_bh(void (*handler) (void))
 {
-       PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL);
+       PREPARE_WORK(&floppy_work, (work_func_t)handler);
        schedule_work(&floppy_work);
 }
 
@@ -1008,7 +1008,7 @@ static void cancel_activity(void)
 
        spin_lock_irqsave(&floppy_lock, flags);
        do_floppy = NULL;
-       PREPARE_WORK(&floppy_work, (void *)empty, NULL);
+       PREPARE_WORK(&floppy_work, (work_func_t)empty);
        del_timer(&fd_timer);
        spin_unlock_irqrestore(&floppy_lock, flags);
 }
@@ -1868,7 +1868,7 @@ static void show_floppy(void)
        printk("fdc_busy=%lu\n", fdc_busy);
        if (do_floppy)
                printk("do_floppy=%p\n", do_floppy);
-       if (floppy_work.pending)
+       if (work_pending(&floppy_work))
                printk("floppy_work.func=%p\n", floppy_work.func);
        if (timer_pending(&fd_timer))
                printk("fd_timer.function=%p\n", fd_timer.function);
@@ -4498,7 +4498,7 @@ static void floppy_release_irq_and_dma(void)
                printk("floppy timer still active:%s\n", timeout_message);
        if (timer_pending(&fd_timer))
                printk("auxiliary floppy timer still active\n");
-       if (floppy_work.pending)
+       if (work_pending(&floppy_work))
                printk("work still pending\n");
 #endif
        old_fdc = fdc;
index beab6d2..6b5b642 100644 (file)
@@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
 
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
-       error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+       error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
        if (error)
                return error;
        memset(info, 0, sizeof(*info));
@@ -1287,7 +1287,7 @@ loop_get_status_compat(struct loop_device *lo,
 
 static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
        int err;
 
index 9d1035e..090796b 100644 (file)
@@ -355,14 +355,30 @@ harderror:
        return NULL;
 }
 
+static ssize_t pid_show(struct gendisk *disk, char *page)
+{
+       return sprintf(page, "%ld\n",
+               (long) ((struct nbd_device *)disk->private_data)->pid);
+}
+
+static struct disk_attribute pid_attr = {
+       .attr = { .name = "pid", .mode = S_IRUGO },
+       .show = pid_show,
+};
+
 static void nbd_do_it(struct nbd_device *lo)
 {
        struct request *req;
 
        BUG_ON(lo->magic != LO_MAGIC);
 
+       lo->pid = current->pid;
+       sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
+
        while ((req = nbd_read_stat(lo)) != NULL)
                nbd_end_request(req);
+
+       sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
        return;
 }
 
@@ -521,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                error = -EINVAL;
                file = fget(arg);
                if (file) {
-                       inode = file->f_dentry->d_inode;
+                       inode = file->f_path.dentry->d_inode;
                        if (S_ISSOCK(inode->i_mode)) {
                                lo->file = file;
                                lo->sock = SOCKET_I(inode);
index c4d696d..2695465 100644 (file)
@@ -149,12 +149,12 @@ static struct pi_protocol aten = {
 
 static int __init aten_init(void)
 {
-       return pi_register(&aten)-1;
+       return paride_register(&aten);
 }
 
 static void __exit aten_exit(void)
 {
-       pi_unregister( &aten );
+       paride_unregister( &aten );
 }
 
 MODULE_LICENSE("GPL");
index d462ff6..4f27e73 100644 (file)
@@ -464,12 +464,12 @@ static struct pi_protocol bpck = {
 
 static int __init bpck_init(void)
 {
-       return pi_register(&bpck)-1;
+       return paride_register(&bpck);
 }
 
 static void __exit bpck_exit(void)
 {
-       pi_unregister(&bpck);
+       paride_unregister(&bpck);
 }
 
 MODULE_LICENSE("GPL");
index 41a237c..ad12452 100644 (file)
@@ -31,10 +31,7 @@ static int verbose; /* set this to 1 to see debugging messages and whatnot */
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <asm/io.h>
-
-#if defined(CONFIG_PARPORT_MODULE)||defined(CONFIG_PARPORT)
 #include <linux/parport.h>
-#endif
 
 #include "ppc6lnx.c"
 #include "paride.h"
@@ -139,11 +136,6 @@ static int bpck6_test_port ( PIA *pi )   /* check for 8-bit port */
        PPCSTRUCT(pi)->ppc_id=pi->unit;
        PPCSTRUCT(pi)->lpt_addr=pi->port;
 
-#ifdef CONFIG_PARPORT_PC_MODULE
-#define CONFIG_PARPORT_PC
-#endif
-
-#ifdef CONFIG_PARPORT_PC
        /* look at the parport device to see if what modes we can use */
        if(((struct pardevice *)(pi->pardev))->port->modes & 
                (PARPORT_MODE_EPP)
@@ -161,11 +153,6 @@ static int bpck6_test_port ( PIA *pi )   /* check for 8-bit port */
        {
                return 1;
        }
-#else
-       /* there is no way of knowing what kind of port we have
-          default to the highest mode possible */
-       return 5;
-#endif
 }
 
 static int bpck6_probe_unit ( PIA *pi )
@@ -265,12 +252,12 @@ static int __init bpck6_init(void)
        printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n");
        if(verbose)
                printk(KERN_DEBUG "bpck6: verbose debug enabled.\n");
-       return pi_register(&bpck6) - 1;  
+       return paride_register(&bpck6);
 }
 
 static void __exit bpck6_exit(void)
 {
-       pi_unregister(&bpck6);
+       paride_unregister(&bpck6);
 }
 
 MODULE_LICENSE("GPL");
index 43d6135..9bcd354 100644 (file)
@@ -205,12 +205,12 @@ static struct pi_protocol comm = {
 
 static int __init comm_init(void)
 {
-       return pi_register(&comm)-1;
+       return paride_register(&comm);
 }
 
 static void __exit comm_exit(void)
 {
-       pi_unregister(&comm);
+       paride_unregister(&comm);
 }
 
 MODULE_LICENSE("GPL");
index 04d53bf..accc5c7 100644 (file)
@@ -220,12 +220,12 @@ static struct pi_protocol dstr = {
 
 static int __init dstr_init(void)
 {
-       return pi_register(&dstr)-1;
+       return paride_register(&dstr);
 }
 
 static void __exit dstr_exit(void)
 {
-       pi_unregister(&dstr);
+       paride_unregister(&dstr);
 }
 
 MODULE_LICENSE("GPL");
index 55d1c0a..1bcdff7 100644 (file)
@@ -327,12 +327,12 @@ static int __init epat_init(void)
 #ifdef CONFIG_PARIDE_EPATC8
        epatc8 = 1;
 #endif
-       return pi_register(&epat)-1;
+       return paride_register(&epat);
 }
 
 static void __exit epat_exit(void)
 {
-       pi_unregister(&epat);
+       paride_unregister(&epat);
 }
 
 MODULE_LICENSE("GPL");
index 0f2e0c2..fb0e782 100644 (file)
@@ -303,12 +303,12 @@ static struct pi_protocol epia = {
 
 static int __init epia_init(void)
 {
-       return pi_register(&epia)-1;
+       return paride_register(&epia);
 }
 
 static void __exit epia_exit(void)
 {
-       pi_unregister(&epia);
+       paride_unregister(&epia);
 }
 
 MODULE_LICENSE("GPL");
index e0f0691..3812837 100644 (file)
@@ -138,12 +138,12 @@ static struct pi_protocol fit2 = {
 
 static int __init fit2_init(void)
 {
-       return pi_register(&fit2)-1;
+       return paride_register(&fit2);
 }
 
 static void __exit fit2_exit(void)
 {
-       pi_unregister(&fit2);
+       paride_unregister(&fit2);
 }
 
 MODULE_LICENSE("GPL");
index 15400e7..275d269 100644 (file)
@@ -198,12 +198,12 @@ static struct pi_protocol fit3 = {
 
 static int __init fit3_init(void)
 {
-       return pi_register(&fit3)-1;
+       return paride_register(&fit3);
 }
 
 static void __exit fit3_exit(void)
 {
-       pi_unregister(&fit3);
+       paride_unregister(&fit3);
 }
 
 MODULE_LICENSE("GPL");
index 5ea2904..4f2ba24 100644 (file)
@@ -263,12 +263,12 @@ static struct pi_protocol friq = {
 
 static int __init friq_init(void)
 {
-       return pi_register(&friq)-1;
+       return paride_register(&friq);
 }
 
 static void __exit friq_exit(void)
 {
-       pi_unregister(&friq);
+       paride_unregister(&friq);
 }
 
 MODULE_LICENSE("GPL");
index 56b3824..c3cde36 100644 (file)
@@ -300,12 +300,12 @@ static struct pi_protocol frpw = {
 
 static int __init frpw_init(void)
 {
-       return pi_register(&frpw)-1;
+       return paride_register(&frpw);
 }
 
 static void __exit frpw_exit(void)
 {
-       pi_unregister(&frpw);
+       paride_unregister(&frpw);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo
deleted file mode 100644 (file)
index e793b9c..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-#
-# This script can be used to build "jumbo" modules that contain the
-# base PARIDE support, one protocol module and one high-level driver.
-#
-echo -n "High level driver [pcd] : "
-read X
-HLD=${X:-pcd}
-#
-echo -n "Protocol module [bpck] : "
-read X
-PROTO=${X:-bpck}
-#
-echo -n "Use MODVERSIONS [y] ? "
-read X
-UMODV=${X:-y}
-#
-echo -n "For SMP kernel [n] ? "
-read X
-USMP=${X:-n}
-#
-echo -n "Support PARPORT [n] ? "
-read X
-UPARP=${X:-n}
-#
-echo
-#
-case $USMP in
-       y* | Y* ) FSMP="-DCONFIG_SMP"
-                 ;;
-       *)        FSMP=""
-                 ;;
-esac
-#
-MODI="-include ../../../include/linux/modversions.h"
-#
-case $UMODV in
-       y* | Y* ) FMODV="-DMODVERSIONS $MODI"
-                 ;;
-       *)        FMODV=""
-                 ;;
-esac
-#
-case $UPARP in
-       y* | Y* ) FPARP="-DCONFIG_PARPORT"
-                 ;;
-       *)        FPARP=""
-                 ;;
-esac
-#
-TARG=$HLD-$PROTO.o
-FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
-FK="-D__KERNEL__ -I ../../../include"
-FLCH=-D_LINUX_CONFIG_H
-#
-echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
-cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
-#
-echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
-cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
-#
-echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
-cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
-#
-echo ld -r -o $TARG Jp.o Jb.o Jd.o
-ld -r -o $TARG Jp.o Jb.o Jd.o
-#
-#
-rm Jp.o Jb.o Jd.o
-#
index d983bce..35999c4 100644 (file)
@@ -283,13 +283,21 @@ static struct pi_protocol k971 = {
 
 static int __init kbic_init(void)
 {
-       return (pi_register(&k951)||pi_register(&k971))-1;
+       int rv;
+
+       rv = paride_register(&k951);
+       if (rv < 0)
+               return rv;
+       rv = paride_register(&k971);
+       if (rv < 0)
+               paride_unregister(&k951);
+       return rv;
 }
 
 static void __exit kbic_exit(void)
 {
-       pi_unregister(&k951);
-       pi_unregister(&k971);
+       paride_unregister(&k951);
+       paride_unregister(&k971);
 }
 
 MODULE_LICENSE("GPL");
index 6c7edbf..117ab0e 100644 (file)
@@ -115,12 +115,12 @@ static struct pi_protocol ktti = {
 
 static int __init ktti_init(void)
 {
-       return pi_register(&ktti)-1;
+       return paride_register(&ktti);
 }
 
 static void __exit ktti_exit(void)
 {
-       pi_unregister(&ktti);
+       paride_unregister(&ktti);
 }
 
 MODULE_LICENSE("GPL");
index 9f8e010..0173697 100644 (file)
@@ -140,12 +140,12 @@ static struct pi_protocol on20 = {
 
 static int __init on20_init(void)
 {
-       return pi_register(&on20)-1;
+       return paride_register(&on20);
 }
 
 static void __exit on20_exit(void)
 {
-       pi_unregister(&on20);
+       paride_unregister(&on20);
 }
 
 MODULE_LICENSE("GPL");
index 0f833ca..95ba256 100644 (file)
@@ -306,12 +306,12 @@ static struct pi_protocol on26 = {
 
 static int __init on26_init(void)
 {
-       return pi_register(&on26)-1;
+       return paride_register(&on26);
 }
 
 static void __exit on26_exit(void)
 {
-       pi_unregister(&on26);
+       paride_unregister(&on26);
 }
 
 MODULE_LICENSE("GPL");
index 4b258f7..48c50f1 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/sched.h>       /* TASK_* */
-
-#ifdef CONFIG_PARPORT_MODULE
-#define CONFIG_PARPORT
-#endif
-
-#ifdef CONFIG_PARPORT
 #include <linux/parport.h>
-#endif
 
 #include "paride.h"
 
@@ -76,8 +69,6 @@ void pi_read_block(PIA * pi, char *buf, int count)
 
 EXPORT_SYMBOL(pi_read_block);
 
-#ifdef CONFIG_PARPORT
-
 static void pi_wake_up(void *p)
 {
        PIA *pi = (PIA *) p;
@@ -100,11 +91,8 @@ static void pi_wake_up(void *p)
                cont();
 }
 
-#endif
-
 int pi_schedule_claimed(PIA * pi, void (*cont) (void))
 {
-#ifdef CONFIG_PARPORT
        unsigned long flags;
 
        spin_lock_irqsave(&pi_spinlock, flags);
@@ -115,7 +103,6 @@ int pi_schedule_claimed(PIA * pi, void (*cont) (void))
        }
        pi->claimed = 1;
        spin_unlock_irqrestore(&pi_spinlock, flags);
-#endif
        return 1;
 }
 EXPORT_SYMBOL(pi_schedule_claimed);
@@ -133,20 +120,16 @@ static void pi_claim(PIA * pi)
        if (pi->claimed)
                return;
        pi->claimed = 1;
-#ifdef CONFIG_PARPORT
        if (pi->pardev)
                wait_event(pi->parq,
                           !parport_claim((struct pardevice *) pi->pardev));
-#endif
 }
 
 static void pi_unclaim(PIA * pi)
 {
        pi->claimed = 0;
-#ifdef CONFIG_PARPORT
        if (pi->pardev)
                parport_release((struct pardevice *) (pi->pardev));
-#endif
 }
 
 void pi_connect(PIA * pi)
@@ -167,21 +150,15 @@ EXPORT_SYMBOL(pi_disconnect);
 
 static void pi_unregister_parport(PIA * pi)
 {
-#ifdef CONFIG_PARPORT
        if (pi->pardev) {
                parport_unregister_device((struct pardevice *) (pi->pardev));
                pi->pardev = NULL;
        }
-#endif
 }
 
 void pi_release(PIA * pi)
 {
        pi_unregister_parport(pi);
-#ifndef CONFIG_PARPORT
-       if (pi->reserved)
-               release_region(pi->port, pi->reserved);
-#endif                         /* !CONFIG_PARPORT */
        if (pi->proto->release_proto)
                pi->proto->release_proto(pi);
        module_put(pi->proto->owner);
@@ -229,7 +206,7 @@ static int pi_test_proto(PIA * pi, char *scratch, int verbose)
        return res;
 }
 
-int pi_register(PIP * pr)
+int paride_register(PIP * pr)
 {
        int k;
 
@@ -237,24 +214,24 @@ int pi_register(PIP * pr)
                if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) {
                        printk("paride: %s protocol already registered\n",
                               pr->name);
-                       return 0;
+                       return -1;
                }
        k = 0;
        while ((k < MAX_PROTOS) && (protocols[k]))
                k++;
        if (k == MAX_PROTOS) {
                printk("paride: protocol table full\n");
-               return 0;
+               return -1;
        }
        protocols[k] = pr;
        pr->index = k;
        printk("paride: %s registered as protocol %d\n", pr->name, k);
-       return 1;
+       return 0;
 }
 
-EXPORT_SYMBOL(pi_register);
+EXPORT_SYMBOL(paride_register);
 
-void pi_unregister(PIP * pr)
+void paride_unregister(PIP * pr)
 {
        if (!pr)
                return;
@@ -265,12 +242,10 @@ void pi_unregister(PIP * pr)
        protocols[pr->index] = NULL;
 }
 
-EXPORT_SYMBOL(pi_unregister);
+EXPORT_SYMBOL(paride_unregister);
 
 static int pi_register_parport(PIA * pi, int verbose)
 {
-#ifdef CONFIG_PARPORT
-
        struct parport *port;
 
        port = parport_find_base(pi->port);
@@ -290,7 +265,6 @@ static int pi_register_parport(PIA * pi, int verbose)
                printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name);
 
        pi->parname = (char *) port->name;
-#endif
 
        return 1;
 }
@@ -447,13 +421,6 @@ int pi_init(PIA * pi, int autoprobe, int port, int mode,
                        printk("%s: Adapter not found\n", device);
                return 0;
        }
-#ifndef CONFIG_PARPORT
-       if (!request_region(pi->port, pi->reserved, pi->device)) {
-               printk(KERN_WARNING "paride: Unable to request region 0x%x\n",
-                      pi->port);
-               return 0;
-       }
-#endif                         /* !CONFIG_PARPORT */
 
        if (pi->parname)
                printk("%s: Sharing %s at 0x%x\n", pi->device,
index c6d98ef..2bddbf4 100644 (file)
@@ -163,8 +163,8 @@ struct pi_protocol {
 
 typedef struct pi_protocol PIP;
 
-extern int pi_register( PIP * );
-extern void pi_unregister ( PIP * );
+extern int paride_register( PIP * );
+extern void paride_unregister ( PIP * );
 
 #endif /* __DRIVERS_PARIDE_H__ */
 /* end of paride.h */
index ac5ba46..c852eed 100644 (file)
@@ -912,12 +912,12 @@ static int __init pcd_init(void)
        int unit;
 
        if (disable)
-               return -1;
+               return -EINVAL;
 
        pcd_init_units();
 
        if (pcd_detect())
-               return -1;
+               return -ENODEV;
 
        /* get the atapi capabilities page */
        pcd_probe_capabilities();
@@ -925,7 +925,7 @@ static int __init pcd_init(void)
        if (register_blkdev(major, name)) {
                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
                        put_disk(cd->disk);
-               return -1;
+               return -EBUSY;
        }
 
        pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
@@ -933,7 +933,7 @@ static int __init pcd_init(void)
                unregister_blkdev(major, name);
                for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
                        put_disk(cd->disk);
-               return -1;
+               return -ENOMEM;
        }
 
        for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
index 40a11e5..9d9bff2 100644 (file)
@@ -352,19 +352,19 @@ static enum action (*phase)(void);
 
 static void run_fsm(void);
 
-static void ps_tq_int( void *data);
+static void ps_tq_int(struct work_struct *work);
 
-static DECLARE_WORK(fsm_tq, ps_tq_int, NULL);
+static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int);
 
 static void schedule_fsm(void)
 {
        if (!nice)
-               schedule_work(&fsm_tq);
+               schedule_delayed_work(&fsm_tq, 0);
        else
                schedule_delayed_work(&fsm_tq, nice-1);
 }
 
-static void ps_tq_int(void *data)
+static void ps_tq_int(struct work_struct *work)
 {
        run_fsm();
 }
index 1a9dee1..7cdaa19 100644 (file)
@@ -933,25 +933,25 @@ static int __init pf_init(void)
        int unit;
 
        if (disable)
-               return -1;
+               return -EINVAL;
 
        pf_init_units();
 
        if (pf_detect())
-               return -1;
+               return -ENODEV;
        pf_busy = 0;
 
        if (register_blkdev(major, name)) {
                for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
                        put_disk(pf->disk);
-               return -1;
+               return -EBUSY;
        }
        pf_queue = blk_init_queue(do_pf_request, &pf_spin_lock);
        if (!pf_queue) {
                unregister_blkdev(major, name);
                for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
                        put_disk(pf->disk);
-               return -1;
+               return -ENOMEM;
        }
 
        blk_queue_max_phys_segments(pf_queue, cluster);
index 13f998a..9970aed 100644 (file)
@@ -646,14 +646,14 @@ static int __init pg_init(void)
        int err;
 
        if (disable){
-               err = -1;
+               err = -EINVAL;
                goto out;
        }
 
        pg_init_units();
 
        if (pg_detect()) {
-               err = -1;
+               err = -ENODEV;
                goto out;
        }
 
index 932342d..bc37032 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 
-static void ps_tq_int( void *data);
+static void ps_tq_int(struct work_struct *work);
 
 static void (* ps_continuation)(void);
 static int (* ps_ready)(void);
@@ -45,7 +45,7 @@ static int ps_nice = 0;
 
 static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
 
-static DECLARE_WORK(ps_tq, ps_tq_int, NULL);
+static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
 
 static void ps_set_intr(void (*continuation)(void), 
                        int (*ready)(void),
@@ -63,14 +63,14 @@ static void ps_set_intr(void (*continuation)(void),
        if (!ps_tq_active) {
                ps_tq_active = 1;
                if (!ps_nice)
-                       schedule_work(&ps_tq);
+                       schedule_delayed_work(&ps_tq, 0);
                else
                        schedule_delayed_work(&ps_tq, ps_nice-1);
        }
        spin_unlock_irqrestore(&ps_spinlock,flags);
 }
 
-static void ps_tq_int(void *data)
+static void ps_tq_int(struct work_struct *work)
 {
        void (*con)(void);
        unsigned long flags;
@@ -92,7 +92,7 @@ static void ps_tq_int(void *data)
        }
        ps_tq_active = 1;
        if (!ps_nice)
-               schedule_work(&ps_tq);
+               schedule_delayed_work(&ps_tq, 0);
        else
                schedule_delayed_work(&ps_tq, ps_nice-1);
        spin_unlock_irqrestore(&ps_spinlock,flags);
index 35fb266..c902b25 100644 (file)
@@ -946,12 +946,12 @@ static int __init pt_init(void)
        int err;
 
        if (disable) {
-               err = -1;
+               err = -EINVAL;
                goto out;
        }
 
        if (pt_detect()) {
-               err = -1;
+               err = -ENODEV;
                goto out;
        }
 
index f2904f6..7c95c76 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2000 Jens Axboe <axboe@suse.de>
  * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com>
+ * Copyright (C) 2006 Thomas Maier <balagi@justmail.de>
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/mutex.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
 static struct proc_dir_entry *pkt_proc;
 static int pktdev_major;
+static int write_congestion_on  = PKT_WRITE_CONGESTION_ON;
+static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
 static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
 static mempool_t *psd_pool;
 
+static struct class    *class_pktcdvd = NULL;    /* /sys/class/pktcdvd */
+static struct dentry   *pkt_debugfs_root = NULL; /* /debug/pktcdvd */
+
+/* forward declaration */
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
+static int pkt_remove_dev(dev_t pkt_dev);
+static int pkt_seq_show(struct seq_file *m, void *p);
+
+
+
+/*
+ * create and register a pktcdvd kernel object.
+ */
+static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
+                                       const char* name,
+                                       struct kobject* parent,
+                                       struct kobj_type* ktype)
+{
+       struct pktcdvd_kobj *p;
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return NULL;
+       kobject_set_name(&p->kobj, "%s", name);
+       p->kobj.parent = parent;
+       p->kobj.ktype = ktype;
+       p->pd = pd;
+       if (kobject_register(&p->kobj) != 0)
+               return NULL;
+       return p;
+}
+/*
+ * remove a pktcdvd kernel object.
+ */
+static void pkt_kobj_remove(struct pktcdvd_kobj *p)
+{
+       if (p)
+               kobject_unregister(&p->kobj);
+}
+/*
+ * default release function for pktcdvd kernel objects.
+ */
+static void pkt_kobj_release(struct kobject *kobj)
+{
+       kfree(to_pktcdvdkobj(kobj));
+}
+
+
+/**********************************************************
+ *
+ * sysfs interface for pktcdvd
+ * by (C) 2006  Thomas Maier <balagi@justmail.de>
+ *
+ **********************************************************/
+
+#define DEF_ATTR(_obj,_name,_mode) \
+       static struct attribute _obj = { \
+               .name = _name, .owner = THIS_MODULE, .mode = _mode }
+
+/**********************************************************
+  /sys/class/pktcdvd/pktcdvd[0-7]/
+                     stat/reset
+                     stat/packets_started
+                     stat/packets_finished
+                     stat/kb_written
+                     stat/kb_read
+                     stat/kb_read_gather
+                     write_queue/size
+                     write_queue/congestion_off
+                     write_queue/congestion_on
+ **********************************************************/
+
+DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200);
+DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444);
+DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444);
+DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444);
+DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444);
+DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444);
+
+static struct attribute *kobj_pkt_attrs_stat[] = {
+       &kobj_pkt_attr_st1,
+       &kobj_pkt_attr_st2,
+       &kobj_pkt_attr_st3,
+       &kobj_pkt_attr_st4,
+       &kobj_pkt_attr_st5,
+       &kobj_pkt_attr_st6,
+       NULL
+};
+
+DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444);
+DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644);
+DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on",  0644);
+
+static struct attribute *kobj_pkt_attrs_wqueue[] = {
+       &kobj_pkt_attr_wq1,
+       &kobj_pkt_attr_wq2,
+       &kobj_pkt_attr_wq3,
+       NULL
+};
+
+/* declares a char buffer[64] _dbuf, copies data from
+ * _b with length _l into it and ensures that _dbuf ends
+ * with a \0 character.
+ */
+#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \
+       char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \
+       if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \
+       memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0
+
+static ssize_t kobj_pkt_show(struct kobject *kobj,
+                       struct attribute *attr, char *data)
+{
+       struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+       int n = 0;
+       int v;
+       if (strcmp(attr->name, "packets_started") == 0) {
+               n = sprintf(data, "%lu\n", pd->stats.pkt_started);
+
+       } else if (strcmp(attr->name, "packets_finished") == 0) {
+               n = sprintf(data, "%lu\n", pd->stats.pkt_ended);
+
+       } else if (strcmp(attr->name, "kb_written") == 0) {
+               n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1);
+
+       } else if (strcmp(attr->name, "kb_read") == 0) {
+               n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1);
+
+       } else if (strcmp(attr->name, "kb_read_gather") == 0) {
+               n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1);
+
+       } else if (strcmp(attr->name, "size") == 0) {
+               spin_lock(&pd->lock);
+               v = pd->bio_queue_size;
+               spin_unlock(&pd->lock);
+               n = sprintf(data, "%d\n", v);
+
+       } else if (strcmp(attr->name, "congestion_off") == 0) {
+               spin_lock(&pd->lock);
+               v = pd->write_congestion_off;
+               spin_unlock(&pd->lock);
+               n = sprintf(data, "%d\n", v);
+
+       } else if (strcmp(attr->name, "congestion_on") == 0) {
+               spin_lock(&pd->lock);
+               v = pd->write_congestion_on;
+               spin_unlock(&pd->lock);
+               n = sprintf(data, "%d\n", v);
+       }
+       return n;
+}
+
+static void init_write_congestion_marks(int* lo, int* hi)
+{
+       if (*hi > 0) {
+               *hi = max(*hi, 500);
+               *hi = min(*hi, 1000000);
+               if (*lo <= 0)
+                       *lo = *hi - 100;
+               else {
+                       *lo = min(*lo, *hi - 100);
+                       *lo = max(*lo, 100);
+               }
+       } else {
+               *hi = -1;
+               *lo = -1;
+       }
+}
+
+static ssize_t kobj_pkt_store(struct kobject *kobj,
+                       struct attribute *attr,
+                       const char *data, size_t len)
+{
+       struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+       int val;
+       DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */
+
+       if (strcmp(attr->name, "reset") == 0 && dlen > 0) {
+               pd->stats.pkt_started = 0;
+               pd->stats.pkt_ended = 0;
+               pd->stats.secs_w = 0;
+               pd->stats.secs_rg = 0;
+               pd->stats.secs_r = 0;
+
+       } else if (strcmp(attr->name, "congestion_off") == 0
+                  && sscanf(dbuf, "%d", &val) == 1) {
+               spin_lock(&pd->lock);
+               pd->write_congestion_off = val;
+               init_write_congestion_marks(&pd->write_congestion_off,
+                                       &pd->write_congestion_on);
+               spin_unlock(&pd->lock);
+
+       } else if (strcmp(attr->name, "congestion_on") == 0
+                  && sscanf(dbuf, "%d", &val) == 1) {
+               spin_lock(&pd->lock);
+               pd->write_congestion_on = val;
+               init_write_congestion_marks(&pd->write_congestion_off,
+                                       &pd->write_congestion_on);
+               spin_unlock(&pd->lock);
+       }
+       return len;
+}
+
+static struct sysfs_ops kobj_pkt_ops = {
+       .show = kobj_pkt_show,
+       .store = kobj_pkt_store
+};
+static struct kobj_type kobj_pkt_type_stat = {
+       .release = pkt_kobj_release,
+       .sysfs_ops = &kobj_pkt_ops,
+       .default_attrs = kobj_pkt_attrs_stat
+};
+static struct kobj_type kobj_pkt_type_wqueue = {
+       .release = pkt_kobj_release,
+       .sysfs_ops = &kobj_pkt_ops,
+       .default_attrs = kobj_pkt_attrs_wqueue
+};
+
+static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
+{
+       if (class_pktcdvd) {
+               pd->clsdev = class_device_create(class_pktcdvd,
+                                       NULL, pd->pkt_dev,
+                                       NULL, "%s", pd->name);
+               if (IS_ERR(pd->clsdev))
+                       pd->clsdev = NULL;
+       }
+       if (pd->clsdev) {
+               pd->kobj_stat = pkt_kobj_create(pd, "stat",
+                                       &pd->clsdev->kobj,
+                                       &kobj_pkt_type_stat);
+               pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
+                                       &pd->clsdev->kobj,
+                                       &kobj_pkt_type_wqueue);
+       }
+}
+
+static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
+{
+       pkt_kobj_remove(pd->kobj_stat);
+       pkt_kobj_remove(pd->kobj_wqueue);
+       if (class_pktcdvd)
+               class_device_destroy(class_pktcdvd, pd->pkt_dev);
+}
+
+
+/********************************************************************
+  /sys/class/pktcdvd/
+                     add            map block device
+                     remove         unmap packet dev
+                     device_map     show mappings
+ *******************************************************************/
+
+static void class_pktcdvd_release(struct class *cls)
+{
+       kfree(cls);
+}
+static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+{
+       int n = 0;
+       int idx;
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       for (idx = 0; idx < MAX_WRITERS; idx++) {
+               struct pktcdvd_device *pd = pkt_devs[idx];
+               if (!pd)
+                       continue;
+               n += sprintf(data+n, "%s %u:%u %u:%u\n",
+                       pd->name,
+                       MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
+                       MAJOR(pd->bdev->bd_dev),
+                       MINOR(pd->bdev->bd_dev));
+       }
+       mutex_unlock(&ctl_mutex);
+       return n;
+}
+
+static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+                                       size_t count)
+{
+       unsigned int major, minor;
+       DECLARE_BUF_AS_STRING(dbuf, buf, count);
+       if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+               pkt_setup_dev(MKDEV(major, minor), NULL);
+               return count;
+       }
+       return -EINVAL;
+}
+
+static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+                                       size_t count)
+{
+       unsigned int major, minor;
+       DECLARE_BUF_AS_STRING(dbuf, buf, count);
+       if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+               pkt_remove_dev(MKDEV(major, minor));
+               return count;
+       }
+       return -EINVAL;
+}
+
+static struct class_attribute class_pktcdvd_attrs[] = {
+ __ATTR(add,            0200, NULL, class_pktcdvd_store_add),
+ __ATTR(remove,         0200, NULL, class_pktcdvd_store_remove),
+ __ATTR(device_map,     0444, class_pktcdvd_show_map, NULL),
+ __ATTR_NULL
+};
+
+
+static int pkt_sysfs_init(void)
+{
+       int ret = 0;
+
+       /*
+        * create control files in sysfs
+        * /sys/class/pktcdvd/...
+        */
+       class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL);
+       if (!class_pktcdvd)
+               return -ENOMEM;
+       class_pktcdvd->name = DRIVER_NAME;
+       class_pktcdvd->owner = THIS_MODULE;
+       class_pktcdvd->class_release = class_pktcdvd_release;
+       class_pktcdvd->class_attrs = class_pktcdvd_attrs;
+       ret = class_register(class_pktcdvd);
+       if (ret) {
+               kfree(class_pktcdvd);
+               class_pktcdvd = NULL;
+               printk(DRIVER_NAME": failed to create class pktcdvd\n");
+               return ret;
+       }
+       return 0;
+}
+
+static void pkt_sysfs_cleanup(void)
+{
+       if (class_pktcdvd)
+               class_destroy(class_pktcdvd);
+       class_pktcdvd = NULL;
+}
+
+/********************************************************************
+  entries in debugfs
+
+  /debugfs/pktcdvd[0-7]/
+                       info
+
+ *******************************************************************/
+
+static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
+{
+       return pkt_seq_show(m, p);
+}
+
+static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pkt_debugfs_seq_show, inode->i_private);
+}
+
+static struct file_operations debug_fops = {
+       .open           = pkt_debugfs_fops_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .owner          = THIS_MODULE,
+};
+
+static void pkt_debugfs_dev_new(struct pktcdvd_device *pd)
+{
+       if (!pkt_debugfs_root)
+               return;
+       pd->dfs_f_info = NULL;
+       pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root);
+       if (IS_ERR(pd->dfs_d_root)) {
+               pd->dfs_d_root = NULL;
+               return;
+       }
+       pd->dfs_f_info = debugfs_create_file("info", S_IRUGO,
+                               pd->dfs_d_root, pd, &debug_fops);
+       if (IS_ERR(pd->dfs_f_info)) {
+               pd->dfs_f_info = NULL;
+               return;
+       }
+}
+
+static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
+{
+       if (!pkt_debugfs_root)
+               return;
+       if (pd->dfs_f_info)
+               debugfs_remove(pd->dfs_f_info);
+       pd->dfs_f_info = NULL;
+       if (pd->dfs_d_root)
+               debugfs_remove(pd->dfs_d_root);
+       pd->dfs_d_root = NULL;
+}
+
+static void pkt_debugfs_init(void)
+{
+       pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL);
+       if (IS_ERR(pkt_debugfs_root)) {
+               pkt_debugfs_root = NULL;
+               return;
+       }
+}
+
+static void pkt_debugfs_cleanup(void)
+{
+       if (!pkt_debugfs_root)
+               return;
+       debugfs_remove(pkt_debugfs_root);
+       pkt_debugfs_root = NULL;
+}
+
+/* ----------------------------------------------------------*/
+
 
 static void pkt_bio_finished(struct pktcdvd_device *pd)
 {
@@ -893,6 +1311,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
        sector_t zone = 0; /* Suppress gcc warning */
        struct pkt_rb_node *node, *first_node;
        struct rb_node *n;
+       int wakeup;
 
        VPRINTK("handle_queue\n");
 
@@ -965,7 +1384,13 @@ try_next_bio:
                pkt->write_size += bio->bi_size / CD_FRAMESIZE;
                spin_unlock(&pkt->lock);
        }
+       /* check write congestion marks, and if bio_queue_size is
+          below, wake up any waiters */
+       wakeup = (pd->write_congestion_on > 0
+                       && pd->bio_queue_size <= pd->write_congestion_off);
        spin_unlock(&pd->lock);
+       if (wakeup)
+               blk_clear_queue_congested(pd->disk->queue, WRITE);
 
        pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
        pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -2178,6 +2603,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
        }
        spin_unlock(&pd->cdrw.active_list_lock);
 
+       /*
+        * Test if there is enough room left in the bio work queue
+        * (queue size >= congestion on mark).
+        * If not, wait till the work queue size is below the congestion off mark.
+        */
+       spin_lock(&pd->lock);
+       if (pd->write_congestion_on > 0
+           && pd->bio_queue_size >= pd->write_congestion_on) {
+               blk_set_queue_congested(q, WRITE);
+               do {
+                       spin_unlock(&pd->lock);
+                       congestion_wait(WRITE, HZ);
+                       spin_lock(&pd->lock);
+               } while(pd->bio_queue_size > pd->write_congestion_off);
+       }
+       spin_unlock(&pd->lock);
+
        /*
         * No matching packet found. Store the bio in the work queue.
         */
@@ -2297,6 +2739,9 @@ static int pkt_seq_show(struct seq_file *m, void *p)
        seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
                   states[0], states[1], states[2], states[3], states[4], states[5]);
 
+       seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n",
+                       pd->write_congestion_off,
+                       pd->write_congestion_on);
        return 0;
 }
 
@@ -2436,36 +2881,33 @@ static struct block_device_operations pktcdvd_ops = {
 /*
  * Set up mapping from pktcdvd device to CD-ROM device.
  */
-static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
 {
        int idx;
        int ret = -ENOMEM;
        struct pktcdvd_device *pd;
        struct gendisk *disk;
-       dev_t dev = new_decode_dev(ctrl_cmd->dev);
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 
        for (idx = 0; idx < MAX_WRITERS; idx++)
                if (!pkt_devs[idx])
                        break;
        if (idx == MAX_WRITERS) {
                printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto out_mutex;
        }
 
        pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
        if (!pd)
-               return ret;
+               goto out_mutex;
 
        pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE,
                                                  sizeof(struct pkt_rb_node));
        if (!pd->rb_pool)
                goto out_mem;
 
-       disk = alloc_disk(1);
-       if (!disk)
-               goto out_mem;
-       pd->disk = disk;
-
        INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
        INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
        spin_lock_init(&pd->cdrw.active_list_lock);
@@ -2476,11 +2918,18 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
        init_waitqueue_head(&pd->wqueue);
        pd->bio_queue = RB_ROOT;
 
+       pd->write_congestion_on  = write_congestion_on;
+       pd->write_congestion_off = write_congestion_off;
+
+       disk = alloc_disk(1);
+       if (!disk)
+               goto out_mem;
+       pd->disk = disk;
        disk->major = pktdev_major;
        disk->first_minor = idx;
        disk->fops = &pktcdvd_ops;
        disk->flags = GENHD_FL_REMOVABLE;
-       sprintf(disk->disk_name, DRIVER_NAME"%d", idx);
+       strcpy(disk->disk_name, pd->name);
        disk->private_data = pd;
        disk->queue = blk_alloc_queue(GFP_KERNEL);
        if (!disk->queue)
@@ -2492,8 +2941,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
                goto out_new_dev;
 
        add_disk(disk);
+
+       pkt_sysfs_dev_new(pd);
+       pkt_debugfs_dev_new(pd);
+
        pkt_devs[idx] = pd;
-       ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
+       if (pkt_dev)
+               *pkt_dev = pd->pkt_dev;
+
+       mutex_unlock(&ctl_mutex);
        return 0;
 
 out_new_dev:
@@ -2504,17 +2960,22 @@ out_mem:
        if (pd->rb_pool)
                mempool_destroy(pd->rb_pool);
        kfree(pd);
+out_mutex:
+       mutex_unlock(&ctl_mutex);
+       printk(DRIVER_NAME": setup of pktcdvd device failed\n");
        return ret;
 }
 
 /*
  * Tear down mapping from pktcdvd device to CD-ROM device.
  */
-static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_remove_dev(dev_t pkt_dev)
 {
        struct pktcdvd_device *pd;
        int idx;
-       dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev);
+       int ret = 0;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 
        for (idx = 0; idx < MAX_WRITERS; idx++) {
                pd = pkt_devs[idx];
@@ -2523,15 +2984,22 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
        }
        if (idx == MAX_WRITERS) {
                DPRINTK(DRIVER_NAME": dev not setup\n");
-               return -ENXIO;
+               ret = -ENXIO;
+               goto out;
        }
 
-       if (pd->refcnt > 0)
-               return -EBUSY;
-
+       if (pd->refcnt > 0) {
+               ret = -EBUSY;
+               goto out;
+       }
        if (!IS_ERR(pd->cdrw.thread))
                kthread_stop(pd->cdrw.thread);
 
+       pkt_devs[idx] = NULL;
+
+       pkt_debugfs_dev_remove(pd);
+       pkt_sysfs_dev_remove(pd);
+
        blkdev_put(pd->bdev);
 
        remove_proc_entry(pd->name, pkt_proc);
@@ -2541,18 +3009,24 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
        blk_cleanup_queue(pd->disk->queue);
        put_disk(pd->disk);
 
-       pkt_devs[idx] = NULL;
        mempool_destroy(pd->rb_pool);
        kfree(pd);
 
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       return 0;
+
+out:
+       mutex_unlock(&ctl_mutex);
+       return ret;
 }
 
 static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
 {
-       struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
+       struct pktcdvd_device *pd;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
        if (pd) {
                ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev);
                ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
@@ -2561,6 +3035,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
                ctrl_cmd->pkt_dev = 0;
        }
        ctrl_cmd->num_devices = MAX_WRITERS;
+
+       mutex_unlock(&ctl_mutex);
 }
 
 static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2568,6 +3044,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
        void __user *argp = (void __user *)arg;
        struct pkt_ctrl_command ctrl_cmd;
        int ret = 0;
+       dev_t pkt_dev = 0;
 
        if (cmd != PACKET_CTRL_CMD)
                return -ENOTTY;
@@ -2579,21 +3056,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case PKT_CTRL_CMD_SETUP:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-               ret = pkt_setup_dev(&ctrl_cmd);
-               mutex_unlock(&ctl_mutex);
+               ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev);
+               ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev);
                break;
        case PKT_CTRL_CMD_TEARDOWN:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-               ret = pkt_remove_dev(&ctrl_cmd);
-               mutex_unlock(&ctl_mutex);
+               ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev));
                break;
        case PKT_CTRL_CMD_STATUS:
-               mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
                pkt_get_status(&ctrl_cmd);
-               mutex_unlock(&ctl_mutex);
                break;
        default:
                return -ENOTTY;
@@ -2620,6 +3092,8 @@ static int __init pkt_init(void)
 {
        int ret;
 
+       mutex_init(&ctl_mutex);
+
        psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
                                        sizeof(struct packet_stacked_data));
        if (!psd_pool)
@@ -2633,18 +3107,25 @@ static int __init pkt_init(void)
        if (!pktdev_major)
                pktdev_major = ret;
 
+       ret = pkt_sysfs_init();
+       if (ret)
+               goto out;
+
+       pkt_debugfs_init();
+
        ret = misc_register(&pkt_misc);
        if (ret) {
                printk(DRIVER_NAME": Unable to register misc device\n");
-               goto out;
+               goto out_misc;
        }
 
-       mutex_init(&ctl_mutex);
-
        pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
 
        return 0;
 
+out_misc:
+       pkt_debugfs_cleanup();
+       pkt_sysfs_cleanup();
 out:
        unregister_blkdev(pktdev_major, DRIVER_NAME);
 out2:
@@ -2656,6 +3137,10 @@ static void __exit pkt_exit(void)
 {
        remove_proc_entry(DRIVER_NAME, proc_root_driver);
        misc_deregister(&pkt_misc);
+
+       pkt_debugfs_cleanup();
+       pkt_sysfs_cleanup();
+
        unregister_blkdev(pktdev_major, DRIVER_NAME);
        mempool_destroy(psd_pool);
 }
index 47d6975..54509eb 100644 (file)
@@ -1244,9 +1244,10 @@ out:
        return IRQ_RETVAL(handled);
 }
 
-static void carm_fsm_task (void *_data)
+static void carm_fsm_task (struct work_struct *work)
 {
-       struct carm_host *host = _data;
+       struct carm_host *host =
+               container_of(work, struct carm_host, fsm_task);
        unsigned long flags;
        unsigned int state;
        int rc, i, next_dev;
@@ -1619,7 +1620,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        host->pdev = pdev;
        host->flags = pci_dac ? FL_DAC : 0;
        spin_lock_init(&host->lock);
-       INIT_WORK(&host->fsm_task, carm_fsm_task, host);
+       INIT_WORK(&host->fsm_task, carm_fsm_task);
        init_completion(&host->probe_comp);
 
        for (i = 0; i < ARRAY_SIZE(host->req); i++)
index 0d5c73f..2098eff 100644 (file)
@@ -376,7 +376,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
 static void ub_reset_enter(struct ub_dev *sc, int try);
-static void ub_reset_task(void *arg);
+static void ub_reset_task(struct work_struct *work);
 static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
 static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_capacity *ret);
@@ -1558,9 +1558,9 @@ static void ub_reset_enter(struct ub_dev *sc, int try)
        schedule_work(&sc->reset_work);
 }
 
-static void ub_reset_task(void *arg)
+static void ub_reset_task(struct work_struct *work)
 {
-       struct ub_dev *sc = arg;
+       struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
        unsigned long flags;
        struct list_head *p;
        struct ub_lun *lun;
@@ -2179,7 +2179,7 @@ static int ub_probe(struct usb_interface *intf,
        usb_init_urb(&sc->work_urb);
        tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
        atomic_set(&sc->poison, 0);
-       INIT_WORK(&sc->reset_work, ub_reset_task, sc);
+       INIT_WORK(&sc->reset_work, ub_reset_task);
        init_waitqueue_head(&sc->reset_wait);
 
        init_timer(&sc->work_timer);
index 5167517..9256985 100644 (file)
@@ -157,9 +157,10 @@ static void bcm203x_complete(struct urb *urb)
        }
 }
 
-static void bcm203x_work(void *user_data)
+static void bcm203x_work(struct work_struct *work)
 {
-       struct bcm203x_data *data = user_data;
+       struct bcm203x_data *data =
+               container_of(work, struct bcm203x_data, work);
 
        if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
                BT_ERR("Can't submit URB");
@@ -246,7 +247,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 
        release_firmware(firmware);
 
-       INIT_WORK(&data->work, bcm203x_work, (void *) data);
+       INIT_WORK(&data->work, bcm203x_work);
 
        usb_set_intfdata(intf, data);
 
index d0cface..5e2c318 100644 (file)
@@ -330,7 +330,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
           reliable packet if the number of packets sent but not yet ack'ed
           is < than the winsize */
 
-       spin_lock_irqsave(&bcsp->unack.lock, flags);
+       spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
 
        if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
                struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
@@ -696,7 +696,7 @@ static void bcsp_timed_event(unsigned long arg)
 
        BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen);
 
-       spin_lock_irqsave(&bcsp->unack.lock, flags);
+       spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
 
        while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) {
                bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07;
index 25032d7..3541690 100644 (file)
@@ -101,7 +101,7 @@ static void debug(int debug_this, const char* fmt, ...)
                return;
 
        va_start(args, fmt);
-       vsprintf(s, fmt, args);
+       vsnprintf(s, sizeof(s), fmt, args);
        printk(KERN_DEBUG "optcd: %s\n", s);
        va_end(args);
 }
index ba50e5a..a1283b1 100644 (file)
@@ -770,11 +770,10 @@ static void msg(int level, const char *fmt, ...)
        
        msgnum++;
        if (msgnum>99) msgnum=0;
-       sprintf(buf, MSG_LEVEL "%s-%d [%02d]:  ", major_name, current_drive - D_S, msgnum);
        va_start(args, fmt);
-       vsprintf(&buf[18], fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
-       printk(buf);
+       printk(MSG_LEVEL "%s-%d [%02d]:  %s", major_name, current_drive - D_S, msgnum, buf);
 #if KLOGD_PAUSE
        sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
 #endif /* KLOGD_PAUSE */ 
index 24f922f..b10f4d8 100644 (file)
@@ -201,6 +201,21 @@ config MOXA_SMARTIO
          The module will be called mxser. If you want to do that, say M
          here.
 
+config MOXA_SMARTIO_NEW
+       tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)"
+       depends on SERIAL_NONSTANDARD
+       help
+         Say Y here if you have a Moxa SmartIO multiport serial card and/or
+         want to help develop a new version of this driver.
+
+         This is upgraded (1.9.1) driver from original Moxa drivers with
+         changes finally resulting in PCI probing.
+
+         Use at your own risk.
+
+         This driver can also be built as a module. The module will be called
+         mxser_new. If you want to do that, say M here.
+
 config ISI
        tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
        depends on SERIAL_NONSTANDARD
index b1fcdab..fc11063 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_MOXA_INTELLIO)   += moxa.o
 obj-$(CONFIG_A2232)            += ser_a2232.o generic_serial.o
 obj-$(CONFIG_ATARI_DSP56K)     += dsp56k.o
 obj-$(CONFIG_MOXA_SMARTIO)     += mxser.o
+obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o
 obj-$(CONFIG_COMPUTONE)                += ip2/
 obj-$(CONFIG_RISCOM8)          += riscom8.o
 obj-$(CONFIG_ISI)              += isicom.o
index 00b17ae..2f2c4ef 100644 (file)
@@ -459,7 +459,7 @@ static const struct aper_size_info_32 nforce3_sizes[5] =
 
 /* Handle shadow device of the Nvidia NForce3 */
 /* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */
-static int __devinit nforce3_agp_init(struct pci_dev *pdev)
+static int nforce3_agp_init(struct pci_dev *pdev)
 {
        u32 tmp, apbase, apbar, aplimit;
        struct pci_dev *dev1;
index 66086fa..feb4ac8 100644 (file)
@@ -104,7 +104,7 @@ static struct async_struct *IRQ_ports;
 
 static unsigned char current_ctl_bits;
 
-static void change_speed(struct async_struct *info, struct termios *old);
+static void change_speed(struct async_struct *info, struct ktermios *old);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
 
@@ -694,7 +694,7 @@ static void shutdown(struct async_struct * info)
  * the specified baud rate for a serial port.
  */
 static void change_speed(struct async_struct *info,
-                        struct termios *old_termios)
+                        struct ktermios *old_termios)
 {
        int     quot = 0, baud_base, baud;
        unsigned cflag, cval = 0;
@@ -1365,7 +1365,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        return 0;
 }
 
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
        unsigned long flags;
index 8ce3f34..c02d9e9 100644 (file)
@@ -82,7 +82,7 @@ static inline u32 cs5535_lowhigh_base(int reg)
 static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
                                 size_t len, loff_t *ppos)
 {
-       u32     m = iminor(file->f_dentry->d_inode);
+       u32     m = iminor(file->f_path.dentry->d_inode);
        int     i, j;
        u32     base = gpio_base + cs5535_lowhigh_base(m);
        u32     m0, m1;
@@ -117,7 +117,7 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
 static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
                                size_t len, loff_t *ppos)
 {
-       u32     m = iminor(file->f_dentry->d_inode);
+       u32     m = iminor(file->f_path.dentry->d_inode);
        u32     base = gpio_base + cs5535_lowhigh_base(m);
        int     rd_bit = 1 << (m & 0x0f);
        int     i;
index e608dad..3ffa080 100644 (file)
@@ -1,8 +1,6 @@
 #undef BLOCKMOVE
 #define        Z_WAKE
 #undef Z_EXT_CHARS_IN_BUFFER
-static char rcsid[] =
-"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -593,18 +591,20 @@ static char rcsid[] =
  *
  */
 
+#define CY_VERSION     "2.4"
+
 /* If you need to install more boards than NR_CARDS, change the constant
    in the definition below. No other change is necessary to support up to
    eight boards. Beyond that you'll have to extend cy_isa_addresses. */
 
-#define NR_CARDS        4
+#define NR_CARDS       4
 
 /*
    If the total number of ports is larger than NR_PORTS, change this
    constant in the definition below. No other change is necessary to
    support more boards/ports. */
 
-#define NR_PORTS        256
+#define NR_PORTS       256
 
 #define ZE_V1_NPORTS   64
 #define ZO_V1  0
@@ -625,9 +625,9 @@ static char rcsid[] =
 #undef CY_PCI_DEBUG
 
 #if 0
-#define PAUSE __asm__("nop");
+#define PAUSE __asm__("nop")
 #else
-#define PAUSE ;
+#define PAUSE do {} while (0)
 #endif
 
 /*
@@ -663,7 +663,7 @@ static char rcsid[] =
                do {                                            \
                spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \
                } while (0)
-               
+
 #define        CY_UNLOCK(info,flags)                                   \
                do {                                            \
                spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \
@@ -676,14 +676,14 @@ static char rcsid[] =
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-static void cy_throttle (struct tty_struct *tty);
-static void cy_send_xchar (struct tty_struct *tty, char ch);
+static void cy_throttle(struct tty_struct *tty);
+static void cy_send_xchar(struct tty_struct *tty, char ch);
 
 #define IS_CYC_Z(card) ((card).num_chips == -1)
 
 #define Z_FPGA_CHECK(card) \
-    ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
-                ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
+       ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
+               ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
 
 #define ISZLOADED(card)        (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
                        ((card).ctl_addr))->mail_box_0)) || \
@@ -698,8 +698,6 @@ static void cy_send_xchar (struct tty_struct *tty, char ch);
 
 #define STD_COM_FLAGS (0)
 
-#define        JIFFIES_DIFF(n, j)      ((j) - (n))
-
 static struct tty_driver *cy_serial_driver;
 
 #ifdef CONFIG_ISA
@@ -713,27 +711,28 @@ static struct tty_driver *cy_serial_driver;
 */
 
 static unsigned int cy_isa_addresses[] = {
-        0xD0000,
-        0xD2000,
-        0xD4000,
-        0xD6000,
-        0xD8000,
-        0xDA000,
-        0xDC000,
-        0xDE000,
-        0,0,0,0,0,0,0,0
+       0xD0000,
+       0xD2000,
+       0xD4000,
+       0xD6000,
+       0xD8000,
+       0xDA000,
+       0xDC000,
+       0xDE000,
+       0, 0, 0, 0, 0, 0, 0, 0
 };
+
 #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
 
 #ifdef MODULE
 static long maddr[NR_CARDS] = { 0, };
-static int irq[NR_CARDS]  = { 0, };
+static int irq[NR_CARDS] = { 0, };
 
 module_param_array(maddr, long, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 #endif
 
-#endif /* CONFIG_ISA */
+#endif                         /* CONFIG_ISA */
 
 /* This is the per-card data structure containing address, irq, number of
    channels, etc. This driver supports a maximum of NR_CARDS cards.
@@ -745,7 +744,7 @@ static struct cyclades_card cy_card[NR_CARDS];
 */
 static struct cyclades_port cy_port[NR_PORTS];
 
-static int cy_next_channel; /* next minor available */
+static int cy_next_channel;    /* next minor available */
 
 /*
  * This is used to look up the divisor speeds and the timeouts
@@ -757,36 +756,42 @@ static int cy_next_channel; /* next minor available */
  *     20
  */
 static int baud_table[] = {
-       0,    50,    75,   110,   134,   150,   200,   300,   600,  1200,
-    1800,  2400,  4800,  9600, 19200, 38400, 57600, 76800,115200,150000,
-  230400,     0};
-
-static char baud_co_25[] = {  /* 25 MHz clock option table */
-    /* value =>    00    01   02    03    04 */
-    /* divide by    8    32   128   512  2048 */
-    0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x03,  0x03,  0x03,  0x02,
-    0x02,  0x02,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00};
-
-static char baud_bpr_25[] = {  /* 25 MHz baud rate period table */
-    0x00,  0xf5,  0xa3,  0x6f,  0x5c,  0x51,  0xf5,  0xa3,  0x51,  0xa3,
-    0x6d,  0x51,  0xa3,  0x51,  0xa3,  0x51,  0x36,  0x29,  0x1b,  0x15};
-
-static char baud_co_60[] = {  /* 60 MHz clock option table (CD1400 J) */
-    /* value =>    00    01   02    03    04 */
-    /* divide by    8    32   128   512  2048 */
-    0x00,  0x00,  0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x03,  0x03,
-    0x03,  0x02,  0x02,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,
-    0x00};
-
-static char baud_bpr_60[] = {  /* 60 MHz baud rate period table (CD1400 J) */
-    0x00,  0x82,  0x21,  0xff,  0xdb,  0xc3,  0x92,  0x62,  0xc3,  0x62,
-    0x41,  0xc3,  0x62,  0xc3,  0x62,  0xc3,  0x82,  0x62,  0x41,  0x32,
-    0x21};
-
-static char baud_cor3[] = {  /* receive threshold */
-    0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,
-    0x0a,  0x0a,  0x0a,  0x09,  0x09,  0x08,  0x08,  0x08,  0x08,  0x07,
-    0x07};
+       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+       1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
+       230400, 0
+};
+
+static char baud_co_25[] = {   /* 25 MHz clock option table */
+       /* value =>    00    01   02    03    04 */
+       /* divide by    8    32   128   512  2048 */
+       0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+       0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static char baud_bpr_25[] = {  /* 25 MHz baud rate period table */
+       0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+       0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
+};
+
+static char baud_co_60[] = {   /* 60 MHz clock option table (CD1400 J) */
+       /* value =>    00    01   02    03    04 */
+       /* divide by    8    32   128   512  2048 */
+       0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
+       0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00
+};
+
+static char baud_bpr_60[] = {  /* 60 MHz baud rate period table (CD1400 J) */
+       0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
+       0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
+       0x21
+};
+
+static char baud_cor3[] = {    /* receive threshold */
+       0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+       0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
+       0x07
+};
 
 /*
  * The Cyclades driver implements HW flow control as any serial driver.
@@ -799,42 +804,42 @@ static char baud_cor3[] = {  /* receive threshold */
  * cables.
  */
 
-static char rflow_thr[] = {  /* rflow threshold */
-    0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
-    0x00,  0x00,  0x00,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,
-    0x0a};
+static char rflow_thr[] = {    /* rflow threshold */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+       0x0a
+};
 
 /*  The Cyclom-Ye has placed the sequential chips in non-sequential
  *  address order.  This look-up table overcomes that problem.
  */
-static int cy_chip_offset [] =
-    { 0x0000,
-      0x0400,
-      0x0800,
-      0x0C00,
-      0x0200,
-      0x0600,
-      0x0A00,
-      0x0E00
-    };
+static int cy_chip_offset[] = { 0x0000,
+       0x0400,
+       0x0800,
+       0x0C00,
+       0x0200,
+       0x0600,
+       0x0A00,
+       0x0E00
+};
 
 /* PCI related definitions */
 
-static unsigned short  cy_pci_nboard;
-static unsigned short  cy_isa_nboard;
-static unsigned short  cy_nboard;
+static unsigned short cy_pci_nboard;
+static unsigned short cy_isa_nboard;
+static unsigned short cy_nboard;
 #ifdef CONFIG_PCI
-static unsigned short  cy_pci_dev_id[] = {
-                           PCI_DEVICE_ID_CYCLOM_Y_Lo,  /* PCI < 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_Y_Hi,  /* PCI > 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_Z_Lo,  /* Z PCI < 1Mb */
-                           PCI_DEVICE_ID_CYCLOM_Z_Hi,  /* Z PCI > 1Mb */
-                           0                           /* end of table */
-                       };
+static unsigned short cy_pci_dev_id[] = {
+       PCI_DEVICE_ID_CYCLOM_Y_Lo,      /* PCI < 1Mb */
+       PCI_DEVICE_ID_CYCLOM_Y_Hi,      /* PCI > 1Mb */
+       PCI_DEVICE_ID_CYCLOM_4Y_Lo,     /* 4Y PCI < 1Mb */
+       PCI_DEVICE_ID_CYCLOM_4Y_Hi,     /* 4Y PCI > 1Mb */
+       PCI_DEVICE_ID_CYCLOM_8Y_Lo,     /* 8Y PCI < 1Mb */
+       PCI_DEVICE_ID_CYCLOM_8Y_Hi,     /* 8Y PCI > 1Mb */
+       PCI_DEVICE_ID_CYCLOM_Z_Lo,      /* Z PCI < 1Mb */
+       PCI_DEVICE_ID_CYCLOM_Z_Hi,      /* Z PCI > 1Mb */
+       0                       /* end of table */
+};
 #endif
 
 static void cy_start(struct tty_struct *);
@@ -842,9 +847,9 @@ static void set_line_char(struct cyclades_port *);
 static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
 #ifdef CONFIG_ISA
 static unsigned detect_isa_irq(void __iomem *);
-#endif /* CONFIG_ISA */
+#endif                         /* CONFIG_ISA */
 
-static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
+static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *);
 
 #ifndef CONFIG_CYZ_INTR
 static void cyz_poll(unsigned long);
@@ -855,41 +860,36 @@ static long cyz_polling_cycle = CZ_DEF_POLL;
 static int cyz_timeron = 0;
 static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
 
-#else /* CONFIG_CYZ_INTR */
+#else                          /* CONFIG_CYZ_INTR */
 static void cyz_rx_restart(unsigned long);
 static struct timer_list cyz_rx_full_timer[NR_PORTS];
-#endif /* CONFIG_CYZ_INTR */
+#endif                         /* CONFIG_CYZ_INTR */
 
-static inline int
-serial_paranoia_check(struct cyclades_port *info,
-                        char *name, const char *routine)
+static inline int serial_paranoia_check(struct cyclades_port *info,
+               char *name, const char *routine)
 {
 #ifdef SERIAL_PARANOIA_CHECK
-    static const char *badmagic =
-        "cyc Warning: bad magic number for serial struct (%s) in %s\n";
-    static const char *badinfo =
-        "cyc Warning: null cyclades_port for (%s) in %s\n";
-    static const char *badrange =
-        "cyc Warning: cyclades_port out of range for (%s) in %s\n";
-
-    if (!info) {
-        printk(badinfo, name, routine);
-        return 1;
-    }
-
-    if( (long)info < (long)(&cy_port[0])
-    || (long)(&cy_port[NR_PORTS]) < (long)info ){
-        printk(badrange, name, routine);
-        return 1;
-    }
-
-    if (info->magic != CYCLADES_MAGIC) {
-        printk(badmagic, name, routine);
-        return 1;
-    }
+       if (!info) {
+               printk("cyc Warning: null cyclades_port for (%s) in %s\n",
+                               name, routine);
+               return 1;
+       }
+
+       if ((long)info < (long)(&cy_port[0]) ||
+                       (long)(&cy_port[NR_PORTS]) < (long)info) {
+               printk("cyc Warning: cyclades_port out of range for (%s) in "
+                               "%s\n", name, routine);
+               return 1;
+       }
+
+       if (info->magic != CYCLADES_MAGIC) {
+               printk("cyc Warning: bad magic number for serial struct (%s) "
+                               "in %s\n", name, routine);
+               return 1;
+       }
 #endif
-        return 0;
-} /* serial_paranoia_check */
+       return 0;
+}                              /* serial_paranoia_check */
 
 /*
  * This routine is used by the interrupt handler to schedule
@@ -897,13 +897,11 @@ serial_paranoia_check(struct cyclades_port *info,
  * (also known as the "bottom half").  This can be called any
  * number of times for any channel without harm.
  */
-static inline void
-cy_sched_event(struct cyclades_port *info, int event)
+static inline void cy_sched_event(struct cyclades_port *info, int event)
 {
-    info->event |= 1 << event; /* remember what kind of event and who */
-    schedule_work(&info->tqueue);
-} /* cy_sched_event */
-
+       info->event |= 1 << event; /* remember what kind of event and who */
+       schedule_work(&info->tqueue);
+}                              /* cy_sched_event */
 
 /*
  * This routine is used to handle the "bottom half" processing for the
@@ -926,44 +924,40 @@ cy_sched_event(struct cyclades_port *info, int event)
  * had to poll every port to see if that port needed servicing.
  */
 static void
-do_softint(void *private_)
+do_softint(struct work_struct *work)
 {
-  struct cyclades_port *info = (struct cyclades_port *) private_;
-  struct tty_struct    *tty;
-
-    tty = info->tty;
-    if (!tty)
-        return;
-
-    if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
-        tty_hangup(info->tty);
-        wake_up_interruptible(&info->open_wait);
-        info->flags &= ~ASYNC_NORMAL_ACTIVE;
-    }
-    if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
-        wake_up_interruptible(&info->open_wait);
-    }
+       struct cyclades_port *info =
+               container_of(work, struct cyclades_port, tqueue);
+       struct tty_struct    *tty;
+
+       tty = info->tty;
+       if (!tty)
+               return;
+
+       if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
+               tty_hangup(info->tty);
+               wake_up_interruptible(&info->open_wait);
+                       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+       }
+       if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event))
+               wake_up_interruptible(&info->open_wait);
 #ifdef CONFIG_CYZ_INTR
-    if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
-       if (cyz_rx_full_timer[info->line].function == NULL) {
-           cyz_rx_full_timer[info->line].expires = jiffies + 1;
-           cyz_rx_full_timer[info->line].function = cyz_rx_restart;
-           cyz_rx_full_timer[info->line].data = (unsigned long)info;
-           add_timer(&cyz_rx_full_timer[info->line]);
+       if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
+               if (cyz_rx_full_timer[info->line].function == NULL) {
+                       cyz_rx_full_timer[info->line].expires = jiffies + 1;
+                       cyz_rx_full_timer[info->line].function = cyz_rx_restart;
+                       cyz_rx_full_timer[info->line].data =
+                                               (unsigned long)info;
+                       add_timer(&cyz_rx_full_timer[info->line]);
+               }
        }
-    }
 #endif
-    if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) {
-       wake_up_interruptible(&info->delta_msr_wait);
-    }
-    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-        tty_wakeup(tty);
-        wake_up_interruptible(&tty->write_wait);
-    }
+       if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event))
+               wake_up_interruptible(&info->delta_msr_wait);
+       tty_wakeup(tty);
 #ifdef Z_WAKE
-    if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) {
-        wake_up_interruptible(&info->shutdown_wait);
-    }
+       if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event))
+               wake_up_interruptible(&info->shutdown_wait);
 #endif
 } /* do_softint */
 
@@ -978,341 +972,339 @@ do_softint(void *private_)
 
    This function is only called from inside spinlock-protected code.
  */
-static int
-cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
+static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
 {
-  volatile int  i;
+       volatile int i;
 
-    /* Check to see that the previous command has completed */
-    for(i = 0 ; i < 100 ; i++){
-       if (cy_readb(base_addr+(CyCCR<<index)) == 0){
-           break;
+       /* Check to see that the previous command has completed */
+       for (i = 0; i < 100; i++) {
+               if (cy_readb(base_addr + (CyCCR << index)) == 0) {
+                       break;
+               }
+               udelay(10L);
        }
-       udelay(10L);
-    }
-    /* if the CCR never cleared, the previous command
-       didn't finish within the "reasonable time" */
-    if (i == 100)      return (-1);
+       /* if the CCR never cleared, the previous command
+          didn't finish within the "reasonable time" */
+       if (i == 100)
+               return -1;
 
-    /* Issue the new command */
-    cy_writeb(base_addr+(CyCCR<<index), cmd);
+       /* Issue the new command */
+       cy_writeb(base_addr + (CyCCR << index), cmd);
 
-    return(0);
-} /* cyy_issue_cmd */
+       return 0;
+}                              /* cyy_issue_cmd */
 
 #ifdef CONFIG_ISA
 /* ISA interrupt detection code */
-static unsigned 
-detect_isa_irq(void __iomem *address)
+static unsigned detect_isa_irq(void __iomem * address)
 {
-  int irq;
-  unsigned long irqs, flags;
-  int save_xir, save_car;
-  int index = 0; /* IRQ probing is only for ISA */
-
-    /* forget possible initially masked and pending IRQ */
-    irq = probe_irq_off(probe_irq_on());
-
-    /* Clear interrupts on the board first */
-    cy_writeb(address + (Cy_ClrIntr<<index), 0);
-                             /* Cy_ClrIntr is 0x1800 */
-
-    irqs = probe_irq_on();
-    /* Wait ... */
-    udelay(5000L);
-
-    /* Enable the Tx interrupts on the CD1400 */
-    local_irq_save(flags);
-       cy_writeb(address + (CyCAR<<index), 0);
-       cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index);
-
-       cy_writeb(address + (CyCAR<<index), 0);
-       cy_writeb(address + (CySRER<<index), 
-               cy_readb(address + (CySRER<<index)) | CyTxRdy);
-    local_irq_restore(flags);
-
-    /* Wait ... */
-    udelay(5000L);
-
-    /* Check which interrupt is in use */
-    irq = probe_irq_off(irqs);
-
-    /* Clean up */
-    save_xir = (u_char) cy_readb(address + (CyTIR<<index));
-    save_car = cy_readb(address + (CyCAR<<index));
-    cy_writeb(address + (CyCAR<<index), (save_xir & 0x3));
-    cy_writeb(address + (CySRER<<index),
-       cy_readb(address + (CySRER<<index)) & ~CyTxRdy);
-    cy_writeb(address + (CyTIR<<index), (save_xir & 0x3f));
-    cy_writeb(address + (CyCAR<<index), (save_car));
-    cy_writeb(address + (Cy_ClrIntr<<index), 0);
-                             /* Cy_ClrIntr is 0x1800 */
-
-    return (irq > 0)? irq : 0;
+       int irq;
+       unsigned long irqs, flags;
+       int save_xir, save_car;
+       int index = 0;          /* IRQ probing is only for ISA */
+
+       /* forget possible initially masked and pending IRQ */
+       irq = probe_irq_off(probe_irq_on());
+
+       /* Clear interrupts on the board first */
+       cy_writeb(address + (Cy_ClrIntr << index), 0);
+       /* Cy_ClrIntr is 0x1800 */
+
+       irqs = probe_irq_on();
+       /* Wait ... */
+       udelay(5000L);
+
+       /* Enable the Tx interrupts on the CD1400 */
+       local_irq_save(flags);
+       cy_writeb(address + (CyCAR << index), 0);
+       cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
+
+       cy_writeb(address + (CyCAR << index), 0);
+       cy_writeb(address + (CySRER << index),
+                 cy_readb(address + (CySRER << index)) | CyTxRdy);
+       local_irq_restore(flags);
+
+       /* Wait ... */
+       udelay(5000L);
+
+       /* Check which interrupt is in use */
+       irq = probe_irq_off(irqs);
+
+       /* Clean up */
+       save_xir = (u_char) cy_readb(address + (CyTIR << index));
+       save_car = cy_readb(address + (CyCAR << index));
+       cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
+       cy_writeb(address + (CySRER << index),
+                 cy_readb(address + (CySRER << index)) & ~CyTxRdy);
+       cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
+       cy_writeb(address + (CyCAR << index), (save_car));
+       cy_writeb(address + (Cy_ClrIntr << index), 0);
+       /* Cy_ClrIntr is 0x1800 */
+
+       return (irq > 0) ? irq : 0;
 }
-#endif /* CONFIG_ISA */
+#endif                         /* CONFIG_ISA */
 
-/* The real interrupt service routine is called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t
-cyy_interrupt(int irq, void *dev_id)
+static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
+                       void __iomem * base_addr, int status, int index)
 {
-  struct tty_struct *tty;
-  int status;
-  struct cyclades_card *cinfo;
-  struct cyclades_port *info;
-  void __iomem *base_addr, *card_base_addr;
-  int chip;
-  int save_xir, channel, save_car;
-  char data;
-  volatile int char_count;
-  int outch;
-  int i,j,index;
-  int too_many;
-  int had_work;
-  int mdm_change;
-  int mdm_status;
-  int len;
-    if((cinfo = (struct cyclades_card *)dev_id) == 0){
-#ifdef CY_DEBUG_INTERRUPTS
-       printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
-#endif
-        return IRQ_NONE; /* spurious interrupt */
-    }
-
-    card_base_addr = cinfo->base_addr;
-    index = cinfo->bus_index;
-
-
-    /* This loop checks all chips in the card.  Make a note whenever
-       _any_ chip had some work to do, as this is considered an
-       indication that there will be more to do.  Only when no chip
-       has any work does this outermost loop exit.
-     */
-    do{
-        had_work = 0;
-        for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
-            base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
-            too_many = 0;
-            while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
-                had_work++;
-                /* The purpose of the following test is to ensure that
-                   no chip can monopolize the driver.  This forces the
-                   chips to be checked in a round-robin fashion (after
-                   draining each of a bunch (1000) of characters).
-                 */
-                if(1000<too_many++){
-                    break;
-                }
-                if (status & CySRReceive) { /* reception interrupt */
+       struct cyclades_port *info;
+       struct tty_struct *tty;
+       volatile int char_count;
+       int i, j, len, mdm_change, mdm_status, outch;
+       int save_xir, channel, save_car;
+       char data;
+
+       if (status & CySRReceive) {     /* reception interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-                   printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
+               printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
 #endif
-                    /* determine the channel & change to that context */
-                   spin_lock(&cinfo->card_lock);
-                    save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index));
-                    channel = (u_short ) (save_xir & CyIRChannel);
-                    i = channel + chip * 4 + cinfo->first_line;
-                    info = &cy_port[i];
-                    info->last_active = jiffies;
-                    save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
-                    /* if there is nowhere to put the data, discard it */
-                    if(info->tty == 0){
-                        j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask);
-                        if ( j == CyIVRRxEx ) { /* exception */
-                            data = cy_readb(base_addr+(CyRDSR<<index));
-                        } else { /* normal character reception */
-                            char_count = cy_readb(base_addr+(CyRDCR<<index));
-                            while(char_count--){
-                                data = cy_readb(base_addr+(CyRDSR<<index));
-                            }
-                        }
-                    }else{ /* there is an open port for this data */
-                        tty = info->tty;
-                        j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask);
-                        if ( j == CyIVRRxEx ) { /* exception */
-                            data = cy_readb(base_addr+(CyRDSR<<index));
-
-                           /* For statistics only */
-                           if (data & CyBREAK)
-                               info->icount.brk++;
-                           else if(data & CyFRAME)
-                               info->icount.frame++;
-                           else if(data & CyPARITY)
-                               info->icount.parity++;
-                           else if(data & CyOVERRUN)
-                               info->icount.overrun++;
-
-                            if(data & info->ignore_status_mask){
-                               info->icount.rx++;
-                                continue;
-                            }
-                            if (tty_buffer_request_room(tty, 1)) {
-                                if (data & info->read_status_mask){
-                                    if(data & CyBREAK){
-                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK);
-                                       info->icount.rx++;
-                                        if (info->flags & ASYNC_SAK){
-                                            do_SAK(tty);
-                                        }
-                                    }else if(data & CyFRAME){
-                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
-                                       info->icount.rx++;
-                                       info->idle_stats.frame_errs++;
-                                    }else if(data & CyPARITY){
-                                       /* Pieces of seven... */
-                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY);
-                                       info->icount.rx++;
-                                       info->idle_stats.parity_errs++;
-                                    }else if(data & CyOVERRUN){
-                                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+               /* determine the channel & change to that context */
+               spin_lock(&cinfo->card_lock);
+               save_xir = (u_char) cy_readb(base_addr + (CyRIR << index));
+               channel = (u_short) (save_xir & CyIRChannel);
+               i = channel + chip * 4 + cinfo->first_line;
+               info = &cy_port[i];
+               info->last_active = jiffies;
+               save_car = cy_readb(base_addr + (CyCAR << index));
+               cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+               /* if there is nowhere to put the data, discard it */
+               if (info->tty == 0) {
+                       j = (cy_readb(base_addr + (CyRIVR << index)) &
+                               CyIVRMask);
+                       if (j == CyIVRRxEx) {   /* exception */
+                               data = cy_readb(base_addr + (CyRDSR << index));
+                       } else {        /* normal character reception */
+                               char_count = cy_readb(base_addr +
+                                               (CyRDCR << index));
+                               while (char_count--) {
+                                       data = cy_readb(base_addr +
+                                               (CyRDSR << index));
+                               }
+                       }
+               } else {        /* there is an open port for this data */
+                       tty = info->tty;
+                       j = (cy_readb(base_addr + (CyRIVR << index)) &
+                                       CyIVRMask);
+                       if (j == CyIVRRxEx) {   /* exception */
+                               data = cy_readb(base_addr + (CyRDSR << index));
+
+                               /* For statistics only */
+                               if (data & CyBREAK)
+                                       info->icount.brk++;
+                               else if (data & CyFRAME)
+                                       info->icount.frame++;
+                               else if (data & CyPARITY)
+                                       info->icount.parity++;
+                               else if (data & CyOVERRUN)
+                                       info->icount.overrun++;
+
+                               if (data & info->ignore_status_mask) {
                                        info->icount.rx++;
-                                        /* If the flip buffer itself is
-                                           overflowing, we still lose
-                                           the next incoming character.
-                                         */
-                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
-                                       info->icount.rx++;
+                                       return;
+                               }
+                               if (tty_buffer_request_room(tty, 1)) {
+                                       if (data & info->read_status_mask) {
+                                               if (data & CyBREAK) {
+                                                       tty_insert_flip_char(
+                                                               tty,
+                                                               cy_readb(
+                                                               base_addr +
+                                                               (CyRDSR <<
+                                                                       index)),
+                                                               TTY_BREAK);
+                                                       info->icount.rx++;
+                                                       if (info->flags &
+                                                           ASYNC_SAK) {
+                                                               do_SAK(tty);
+                                                       }
+                                               } else if (data & CyFRAME) {
+                                                       tty_insert_flip_char(
+                                                               tty,
+                                                               cy_readb(
+                                                               base_addr +
+                                                               (CyRDSR <<
+                                                                       index)),
+                                                               TTY_FRAME);
+                                                       info->icount.rx++;
+                                                       info->idle_stats.
+                                                               frame_errs++;
+                                               } else if (data & CyPARITY) {
+                                                       /* Pieces of seven... */
+                                                       tty_insert_flip_char(
+                                                               tty,
+                                                               cy_readb(
+                                                               base_addr +
+                                                               (CyRDSR <<
+                                                                       index)),
+                                                               TTY_PARITY);
+                                                       info->icount.rx++;
+                                                       info->idle_stats.
+                                                               parity_errs++;
+                                               } else if (data & CyOVERRUN) {
+                                                       tty_insert_flip_char(
+                                                               tty, 0,
+                                                               TTY_OVERRUN);
+                                                       info->icount.rx++;
+                                               /* If the flip buffer itself is
+                                                  overflowing, we still lose
+                                                  the next incoming character.
+                                                */
+                                                       tty_insert_flip_char(
+                                                               tty,
+                                                               cy_readb(
+                                                               base_addr +
+                                                               (CyRDSR <<
+                                                                       index)),
+                                                               TTY_FRAME);
+                                                       info->icount.rx++;
+                                                       info->idle_stats.
+                                                               overruns++;
+                                       /* These two conditions may imply */
+                                       /* a normal read should be done. */
+                                       /* }else if(data & CyTIMEOUT){ */
+                                       /* }else if(data & CySPECHAR){ */
+                                               } else {
+                                                       tty_insert_flip_char(
+                                                               tty, 0,
+                                                               TTY_NORMAL);
+                                                       info->icount.rx++;
+                                               }
+                                       } else {
+                                               tty_insert_flip_char(tty, 0,
+                                                               TTY_NORMAL);
+                                               info->icount.rx++;
+                                       }
+                               } else {
+                                       /* there was a software buffer
+                                          overrun and nothing could be
+                                          done about it!!! */
+                                       info->icount.buf_overrun++;
                                        info->idle_stats.overruns++;
-                                    /* These two conditions may imply */
-                                    /* a normal read should be done. */
-                                    /* }else if(data & CyTIMEOUT){ */
-                                    /* }else if(data & CySPECHAR){ */
-                                    }else {
-                                       tty_insert_flip_char(tty, 0, TTY_NORMAL);
-                                       info->icount.rx++;
-                                    }
-                                }else{
-                                   tty_insert_flip_char(tty, 0, TTY_NORMAL);
-                                   info->icount.rx++;
-                                }
-                            }else{
-                                /* there was a software buffer
-                                  overrun and nothing could be
-                                  done about it!!! */
-                               info->icount.buf_overrun++;
-                               info->idle_stats.overruns++;
-                            }
-                        } else { /* normal character reception */
-                            /* load # chars available from the chip */
-                            char_count = cy_readb(base_addr+(CyRDCR<<index));
+                               }
+                       } else {        /* normal character reception */
+                               /* load # chars available from the chip */
+                               char_count = cy_readb(base_addr +
+                                               (CyRDCR << index));
 
 #ifdef CY_ENABLE_MONITORING
-                            ++info->mon.int_count;
-                            info->mon.char_count += char_count;
-                            if (char_count > info->mon.char_max)
-                               info->mon.char_max = char_count;
-                            info->mon.char_last = char_count;
+                               ++info->mon.int_count;
+                               info->mon.char_count += char_count;
+                               if (char_count > info->mon.char_max)
+                                       info->mon.char_max = char_count;
+                               info->mon.char_last = char_count;
 #endif
-                           len = tty_buffer_request_room(tty, char_count);
-                            while(len--){
-                                data = cy_readb(base_addr+(CyRDSR<<index));
-                               tty_insert_flip_char(tty, data, TTY_NORMAL);
-                               info->idle_stats.recv_bytes++;
-                               info->icount.rx++;
+                               len = tty_buffer_request_room(tty, char_count);
+                               while (len--) {
+                                       data = cy_readb(base_addr +
+                                                       (CyRDSR << index));
+                                       tty_insert_flip_char(tty, data,
+                                                       TTY_NORMAL);
+                                       info->idle_stats.recv_bytes++;
+                                       info->icount.rx++;
 #ifdef CY_16Y_HACK
-                                udelay(10L);
+                                       udelay(10L);
 #endif
-                            }
-                             info->idle_stats.recv_idle = jiffies;
-                        }
+                               }
+                               info->idle_stats.recv_idle = jiffies;
+                       }
                        tty_schedule_flip(tty);
-                    }
-                    /* end of service */
-                    cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
-                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
-                   spin_unlock(&cinfo->card_lock);
-                }
-
-
-                if (status & CySRTransmit) { /* transmission interrupt */
-                    /* Since we only get here when the transmit buffer
-                       is empty, we know we can always stuff a dozen
-                       characters. */
+               }
+               /* end of service */
+               cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f));
+               cy_writeb(base_addr + (CyCAR << index), (save_car));
+               spin_unlock(&cinfo->card_lock);
+       }
+
+       if (status & CySRTransmit) {    /* transmission interrupt */
+               /* Since we only get here when the transmit buffer
+                  is empty, we know we can always stuff a dozen
+                  characters. */
 #ifdef CY_DEBUG_INTERRUPTS
-                   printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
+               printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
 #endif
 
-                    /* determine the channel & change to that context */
-                   spin_lock(&cinfo->card_lock);
-                    save_xir = (u_char) cy_readb(base_addr+(CyTIR<<index));
-                    channel = (u_short ) (save_xir & CyIRChannel);
-                    i = channel + chip * 4 + cinfo->first_line;
-                    save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
-                    /* validate the port# (as configured and open) */
-                    if( (i < 0) || (NR_PORTS <= i) ){
-                        cy_writeb(base_addr+(CySRER<<index),
-                             cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
-                        goto txend;
-                    }
-                    info = &cy_port[i];
-                    info->last_active = jiffies;
-                    if(info->tty == 0){
-                        cy_writeb(base_addr+(CySRER<<index),
-                             cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
-                        goto txdone;
-                    }
-
-                    /* load the on-chip space for outbound data */
-                    char_count = info->xmit_fifo_size;
-
-                    if(info->x_char) { /* send special char */
-                        outch = info->x_char;
-                        cy_writeb(base_addr+(CyTDR<<index), outch);
-                        char_count--;
+               /* determine the channel & change to that context */
+               spin_lock(&cinfo->card_lock);
+               save_xir = (u_char) cy_readb(base_addr + (CyTIR << index));
+               channel = (u_short) (save_xir & CyIRChannel);
+               i = channel + chip * 4 + cinfo->first_line;
+               save_car = cy_readb(base_addr + (CyCAR << index));
+               cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+               /* validate the port# (as configured and open) */
+               if ((i < 0) || (NR_PORTS <= i)) {
+                       cy_writeb(base_addr + (CySRER << index),
+                                 cy_readb(base_addr + (CySRER << index)) &
+                                 ~CyTxRdy);
+                       goto txend;
+               }
+               info = &cy_port[i];
+               info->last_active = jiffies;
+               if (info->tty == 0) {
+                       cy_writeb(base_addr + (CySRER << index),
+                                 cy_readb(base_addr + (CySRER << index)) &
+                                 ~CyTxRdy);
+                       goto txdone;
+               }
+
+               /* load the on-chip space for outbound data */
+               char_count = info->xmit_fifo_size;
+
+               if (info->x_char) {     /* send special char */
+                       outch = info->x_char;
+                       cy_writeb(base_addr + (CyTDR << index), outch);
+                       char_count--;
                        info->icount.tx++;
-                        info->x_char = 0;
-                    }
+                       info->x_char = 0;
+               }
 
-                    if (info->breakon || info->breakoff) {
+               if (info->breakon || info->breakoff) {
                        if (info->breakon) {
-                           cy_writeb(base_addr + (CyTDR<<index), 0); 
-                           cy_writeb(base_addr + (CyTDR<<index), 0x81);
-                           info->breakon = 0;
-                            char_count -= 2;
+                               cy_writeb(base_addr + (CyTDR << index), 0);
+                               cy_writeb(base_addr + (CyTDR << index), 0x81);
+                               info->breakon = 0;
+                               char_count -= 2;
                        }
                        if (info->breakoff) {
-                           cy_writeb(base_addr + (CyTDR<<index), 0); 
-                           cy_writeb(base_addr + (CyTDR<<index), 0x83);
-                           info->breakoff = 0;
-                            char_count -= 2;
+                               cy_writeb(base_addr + (CyTDR << index), 0);
+                               cy_writeb(base_addr + (CyTDR << index), 0x83);
+                               info->breakoff = 0;
+                               char_count -= 2;
                        }
-                    }
-
-                    while (char_count-- > 0){
-                       if (!info->xmit_cnt){
-                           if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) {
-                               cy_writeb(base_addr+(CySRER<<index),
-                                         cy_readb(base_addr+(CySRER<<index)) &
-                                         ~CyTxMpty);
-                           } else {
-                               cy_writeb(base_addr+(CySRER<<index),
-                                         ((cy_readb(base_addr+(CySRER<<index))
-                                           & ~CyTxRdy)
-                                          | CyTxMpty));
-                           }
-                           goto txdone;
+               }
+
+               while (char_count-- > 0) {
+                       if (!info->xmit_cnt) {
+                               if (cy_readb(base_addr + (CySRER << index)) &
+                                               CyTxMpty) {
+                                       cy_writeb(base_addr + (CySRER << index),
+                                               cy_readb(base_addr +
+                                                       (CySRER << index)) &
+                                               ~CyTxMpty);
+                               } else {
+                                       cy_writeb(base_addr + (CySRER << index),
+                                               (cy_readb(base_addr +
+                                                       (CySRER << index)) &
+                                               ~CyTxRdy) | CyTxMpty);
+                               }
+                               goto txdone;
                        }
-                       if (info->xmit_buf == 0){
-                            cy_writeb(base_addr+(CySRER<<index),
-                               cy_readb(base_addr+(CySRER<<index)) & 
+                       if (info->xmit_buf == 0) {
+                               cy_writeb(base_addr + (CySRER << index),
+                                       cy_readb(base_addr + (CySRER << index))&
                                        ~CyTxRdy);
-                            goto txdone;
+                               goto txdone;
                        }
-                       if (info->tty->stopped || info->tty->hw_stopped){
-                            cy_writeb(base_addr+(CySRER<<index),
-                               cy_readb(base_addr+(CySRER<<index)) & 
+                       if (info->tty->stopped || info->tty->hw_stopped) {
+                               cy_writeb(base_addr + (CySRER << index),
+                                       cy_readb(base_addr + (CySRER << index))&
                                        ~CyTxRdy);
-                            goto txdone;
+                               goto txdone;
                        }
-                        /* Because the Embedded Transmit Commands have
-                           been enabled, we must check to see if the
+                       /* Because the Embedded Transmit Commands have
+                          been enabled, we must check to see if the
                           escape character, NULL, is being sent.  If it
                           is, we must ensure that there is room for it
                           to be doubled in the output stream.  Therefore
@@ -1321,125 +1313,182 @@ cyy_interrupt(int irq, void *dev_id)
                           after the check for a NULL output character.
                           This is necessary because there may not be
                           room for the two chars needed to send a NULL.)
-                         */
-                        outch = info->xmit_buf[info->xmit_tail];
-                        if( outch ){
-                            info->xmit_cnt--;
-                            info->xmit_tail = (info->xmit_tail + 1)
-                                                      & (SERIAL_XMIT_SIZE - 1);
-                            cy_writeb(base_addr+(CyTDR<<index), outch);
-                           info->icount.tx++;
-                        }else{
-                            if(char_count > 1){
-                                info->xmit_cnt--;
-                                info->xmit_tail = (info->xmit_tail + 1)
-                                                     & (SERIAL_XMIT_SIZE - 1);
-                                cy_writeb(base_addr+(CyTDR<<index), 
-                                         outch);
-                                cy_writeb(base_addr+(CyTDR<<index), 0);
+                        */
+                       outch = info->xmit_buf[info->xmit_tail];
+                       if (outch) {
+                               info->xmit_cnt--;
+                               info->xmit_tail = (info->xmit_tail + 1) &
+                                               (SERIAL_XMIT_SIZE - 1);
+                               cy_writeb(base_addr + (CyTDR << index), outch);
                                info->icount.tx++;
-                                char_count--;
-                            }else{
-                            }
-                        }
-                    }
-
-        txdone:
-                    if (info->xmit_cnt < WAKEUP_CHARS) {
-                        cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
-                    }
-        txend:
-                    /* end of service */
-                    cy_writeb(base_addr+(CyTIR<<index), 
-                             (save_xir & 0x3f));
-                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
-                   spin_unlock(&cinfo->card_lock);
-                }
-
-                if (status & CySRModem) {        /* modem interrupt */
-
-                    /* determine the channel & change to that context */
-                   spin_lock(&cinfo->card_lock);
-                    save_xir = (u_char) cy_readb(base_addr+(CyMIR<<index));
-                    channel = (u_short ) (save_xir & CyIRChannel);
-                    info = &cy_port[channel + chip * 4
-                                          + cinfo->first_line];
-                    info->last_active = jiffies;
-                    save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
-                    mdm_change = cy_readb(base_addr+(CyMISR<<index));
-                    mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
-
-                    if(info->tty == 0){/* no place for data, ignore it*/
-                        ;
-                    }else{
+                       } else {
+                               if (char_count > 1) {
+                                       info->xmit_cnt--;
+                                       info->xmit_tail = (info->xmit_tail + 1)&
+                                               (SERIAL_XMIT_SIZE - 1);
+                                       cy_writeb(base_addr + (CyTDR << index),
+                                               outch);
+                                       cy_writeb(base_addr + (CyTDR << index),
+                                               0);
+                                       info->icount.tx++;
+                                       char_count--;
+                               } else {
+                               }
+                       }
+               }
+
+txdone:
+               if (info->xmit_cnt < WAKEUP_CHARS) {
+                       cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+               }
+txend:
+               /* end of service */
+               cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f));
+               cy_writeb(base_addr + (CyCAR << index), (save_car));
+               spin_unlock(&cinfo->card_lock);
+       }
+
+       if (status & CySRModem) {       /* modem interrupt */
+
+               /* determine the channel & change to that context */
+               spin_lock(&cinfo->card_lock);
+               save_xir = (u_char) cy_readb(base_addr + (CyMIR << index));
+               channel = (u_short) (save_xir & CyIRChannel);
+               info = &cy_port[channel + chip * 4 + cinfo->first_line];
+               info->last_active = jiffies;
+               save_car = cy_readb(base_addr + (CyCAR << index));
+               cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+               mdm_change = cy_readb(base_addr + (CyMISR << index));
+               mdm_status = cy_readb(base_addr + (CyMSVR1 << index));
+
+               if (info->tty == 0) {   /* no place for data, ignore it */
+                       ;
+               } else {
                        if (mdm_change & CyANY_DELTA) {
-                           /* For statistics only */
-                           if (mdm_change & CyDCD)     info->icount.dcd++;
-                           if (mdm_change & CyCTS)     info->icount.cts++;
-                           if (mdm_change & CyDSR)     info->icount.dsr++;
-                           if (mdm_change & CyRI)      info->icount.rng++;
+                               /* For statistics only */
+                               if (mdm_change & CyDCD)
+                                       info->icount.dcd++;
+                               if (mdm_change & CyCTS)
+                                       info->icount.cts++;
+                               if (mdm_change & CyDSR)
+                                       info->icount.dsr++;
+                               if (mdm_change & CyRI)
+                                       info->icount.rng++;
+
+                               cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+                       }
+
+                       if ((mdm_change & CyDCD) &&
+                                       (info->flags & ASYNC_CHECK_CD)) {
+                               if (mdm_status & CyDCD) {
+                                       cy_sched_event(info,
+                                                       Cy_EVENT_OPEN_WAKEUP);
+                               } else {
+                                       cy_sched_event(info, Cy_EVENT_HANGUP);
+                               }
+                       }
+                       if ((mdm_change & CyCTS) &&
+                                       (info->flags & ASYNC_CTS_FLOW)) {
+                               if (info->tty->hw_stopped) {
+                                       if (mdm_status & CyCTS) {
+                                               /* cy_start isn't used
+                                                  because... !!! */
+                                               info->tty->hw_stopped = 0;
+                                               cy_writeb(base_addr +
+                                                       (CySRER << index),
+                                                       cy_readb(base_addr +
+                                                               (CySRER <<
+                                                                       index))|
+                                                       CyTxRdy);
+                                               cy_sched_event(info,
+                                                       Cy_EVENT_WRITE_WAKEUP);
+                                       }
+                               } else {
+                                       if (!(mdm_status & CyCTS)) {
+                                               /* cy_stop isn't used
+                                                  because ... !!! */
+                                               info->tty->hw_stopped = 1;
+                                               cy_writeb(base_addr +
+                                                       (CySRER << index),
+                                                       cy_readb(base_addr +
+                                                               (CySRER <<
+                                                               index)) &
+                                                       ~CyTxRdy);
+                                       }
+                               }
+                       }
+                       if (mdm_change & CyDSR) {
+                       }
+                       if (mdm_change & CyRI) {
+                       }
+               }
+               /* end of service */
+               cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
+               cy_writeb(base_addr + (CyCAR << index), save_car);
+               spin_unlock(&cinfo->card_lock);
+       }
+}
 
-                           cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+/* The real interrupt service routine is called
+   whenever the card wants its hand held--chars
+   received, out buffer empty, modem change, etc.
+ */
+static irqreturn_t cyy_interrupt(int irq, void *dev_id)
+{
+       int status;
+       struct cyclades_card *cinfo;
+       void __iomem *base_addr, *card_base_addr;
+       int chip;
+       int index;
+       int too_many;
+       int had_work;
+
+       if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+#ifdef CY_DEBUG_INTERRUPTS
+               printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
+#endif
+               return IRQ_NONE;        /* spurious interrupt */
+       }
+
+       card_base_addr = cinfo->base_addr;
+       index = cinfo->bus_index;
+
+       /* This loop checks all chips in the card.  Make a note whenever
+          _any_ chip had some work to do, as this is considered an
+          indication that there will be more to do.  Only when no chip
+          has any work does this outermost loop exit.
+        */
+       do {
+               had_work = 0;
+               for (chip = 0; chip < cinfo->num_chips; chip++) {
+                       base_addr = cinfo->base_addr +
+                                       (cy_chip_offset[chip] << index);
+                       too_many = 0;
+                       while ((status = cy_readb(base_addr +
+                                               (CySVRR << index))) != 0x00) {
+                               had_work++;
+                       /* The purpose of the following test is to ensure that
+                          no chip can monopolize the driver.  This forces the
+                          chips to be checked in a round-robin fashion (after
+                          draining each of a bunch (1000) of characters).
+                        */
+                               if (1000 < too_many++) {
+                                       break;
+                               }
+                               cyy_intr_chip(cinfo, chip, base_addr, status,
+                                               index);
                        }
+               }
+       } while (had_work);
 
-                        if((mdm_change & CyDCD)
-                        && (info->flags & ASYNC_CHECK_CD)){
-                            if(mdm_status & CyDCD){
-                                cy_sched_event(info,
-                                   Cy_EVENT_OPEN_WAKEUP);
-                            }else{
-                                cy_sched_event(info,
-                                   Cy_EVENT_HANGUP);
-                            }
-                        }
-                        if((mdm_change & CyCTS)
-                        && (info->flags & ASYNC_CTS_FLOW)){
-                            if(info->tty->hw_stopped){
-                                if(mdm_status & CyCTS){
-                                    /* cy_start isn't used
-                                        because... !!! */
-                                    info->tty->hw_stopped = 0;
-                                  cy_writeb(base_addr+(CySRER<<index),
-                                       cy_readb(base_addr+(CySRER<<index)) | 
-                                       CyTxRdy);
-                                    cy_sched_event(info,
-                                       Cy_EVENT_WRITE_WAKEUP);
-                                }
-                            }else{
-                                if(!(mdm_status & CyCTS)){
-                                    /* cy_stop isn't used
-                                        because ... !!! */
-                                    info->tty->hw_stopped = 1;
-                                  cy_writeb(base_addr+(CySRER<<index),
-                                       cy_readb(base_addr+(CySRER<<index)) & 
-                                       ~CyTxRdy);
-                                }
-                            }
-                        }
-                        if(mdm_change & CyDSR){
-                        }
-                        if(mdm_change & CyRI){
-                        }
-                    }
-                    /* end of service */
-                    cy_writeb(base_addr+(CyMIR<<index), 
-                             (save_xir & 0x3f));
-                    cy_writeb(base_addr+(CyCAR<<index), save_car);
-                   spin_unlock(&cinfo->card_lock);
-                }
-            }          /* end while status != 0 */
-        }            /* end loop for chips... */
-    } while(had_work);
-
-   /* clear interrupts */
-   spin_lock(&cinfo->card_lock);
-   cy_writeb(card_base_addr + (Cy_ClrIntr<<index), 0);
-                                /* Cy_ClrIntr is 0x1800 */
-   spin_unlock(&cinfo->card_lock);
-   return IRQ_HANDLED;
-} /* cyy_interrupt */
+       /* clear interrupts */
+       spin_lock(&cinfo->card_lock);
+       cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
+       /* Cy_ClrIntr is 0x1800 */
+       spin_unlock(&cinfo->card_lock);
+       return IRQ_HANDLED;
+}                              /* cyy_interrupt */
 
 /***********************************************************/
 /********* End of block of Cyclom-Y specific code **********/
@@ -1447,643 +1496,655 @@ cyy_interrupt(int irq, void *dev_id)
 /***********************************************************/
 
 static int
-cyz_fetch_msg( struct cyclades_card *cinfo,
-           uclong *channel, ucchar *cmd, uclong *param)
+cyz_fetch_msg(struct cyclades_card *cinfo,
+               uclong * channel, ucchar * cmd, uclong * param)
 {
-  struct FIRM_ID __iomem *firm_id;
-  struct ZFW_CTRL __iomem *zfw_ctrl;
-  struct BOARD_CTRL __iomem *board_ctrl;
-  unsigned long loc_doorbell;
-
-    firm_id = cinfo->base_addr + ID_ADDRESS;
-    if (!ISZLOADED(*cinfo)){
-       return (-1);
-    }
-    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-    board_ctrl = &zfw_ctrl->board_ctrl;
-
-    loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
-                     (cinfo->ctl_addr))->loc_doorbell);
-    if (loc_doorbell){
-       *cmd = (char)(0xff & loc_doorbell);
-       *channel = cy_readl(&board_ctrl->fwcmd_channel);
-       *param = (uclong)cy_readl(&board_ctrl->fwcmd_param);
-       cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, 
-                 0xffffffff);
-       return 1;
-    }
-    return 0;
-} /* cyz_fetch_msg */
+       struct FIRM_ID __iomem *firm_id;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct BOARD_CTRL __iomem *board_ctrl;
+       unsigned long loc_doorbell;
+
+       firm_id = cinfo->base_addr + ID_ADDRESS;
+       if (!ISZLOADED(*cinfo)) {
+               return -1;
+       }
+       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+                       0xfffff);
+       board_ctrl = &zfw_ctrl->board_ctrl;
+
+       loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
+                                 (cinfo->ctl_addr))->loc_doorbell);
+       if (loc_doorbell) {
+               *cmd = (char)(0xff & loc_doorbell);
+               *channel = cy_readl(&board_ctrl->fwcmd_channel);
+               *param = (uclong) cy_readl(&board_ctrl->fwcmd_param);
+               cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
+                         loc_doorbell, 0xffffffff);
+               return 1;
+       }
+       return 0;
+}                              /* cyz_fetch_msg */
 
 static int
-cyz_issue_cmd( struct cyclades_card *cinfo,
-           uclong channel, ucchar cmd, uclong param)
+cyz_issue_cmd(struct cyclades_card *cinfo,
+               uclong channel, ucchar cmd, uclong param)
 {
-  struct FIRM_ID __iomem *firm_id;
-  struct ZFW_CTRL __iomem *zfw_ctrl;
-  struct BOARD_CTRL __iomem *board_ctrl;
-  unsigned long __iomem *pci_doorbell;
-  int index;
-
-    firm_id = cinfo->base_addr + ID_ADDRESS;
-    if (!ISZLOADED(*cinfo)){
-       return (-1);
-    }
-    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-    board_ctrl = &zfw_ctrl->board_ctrl;
-
-    index = 0;
-    pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell;
-    while( (cy_readl(pci_doorbell) & 0xff) != 0){
-        if (index++ == 1000){
-           return((int)(cy_readl(pci_doorbell) & 0xff));
-        }
-       udelay(50L);
-    }
-    cy_writel(&board_ctrl->hcmd_channel, channel);
-    cy_writel(&board_ctrl->hcmd_param , param);
-    cy_writel(pci_doorbell, (long)cmd);
-
-    return(0);
-} /* cyz_issue_cmd */
+       struct FIRM_ID __iomem *firm_id;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct BOARD_CTRL __iomem *board_ctrl;
+       unsigned long __iomem *pci_doorbell;
+       int index;
+
+       firm_id = cinfo->base_addr + ID_ADDRESS;
+       if (!ISZLOADED(*cinfo)) {
+               return -1;
+       }
+       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+                       0xfffff);
+       board_ctrl = &zfw_ctrl->board_ctrl;
+
+       index = 0;
+       pci_doorbell =
+           &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+       while ((cy_readl(pci_doorbell) & 0xff) != 0) {
+               if (index++ == 1000) {
+                       return (int)(cy_readl(pci_doorbell) & 0xff);
+               }
+               udelay(50L);
+       }
+       cy_writel(&board_ctrl->hcmd_channel, channel);
+       cy_writel(&board_ctrl->hcmd_param, param);
+       cy_writel(pci_doorbell, (long)cmd);
+
+       return 0;
+}                              /* cyz_issue_cmd */
 
 static void
 cyz_handle_rx(struct cyclades_port *info,
-             volatile struct CH_CTRL __iomem *ch_ctrl,
-             volatile struct BUF_CTRL __iomem *buf_ctrl)
+               volatile struct CH_CTRL __iomem * ch_ctrl,
+               volatile struct BUF_CTRL __iomem * buf_ctrl)
 {
-  struct cyclades_card *cinfo = &cy_card[info->card];
-  struct tty_struct *tty = info->tty;
-  volatile int char_count;
-  int len;
+       struct cyclades_card *cinfo = &cy_card[info->card];
+       struct tty_struct *tty = info->tty;
+       volatile int char_count;
+       int len;
 #ifdef BLOCKMOVE
-  int small_count;
+       int small_count;
 #else
-  char data;
+       char data;
 #endif
-  volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
+       volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
 
-    rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
-    rx_put = cy_readl(&buf_ctrl->rx_put);
-    rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
-    rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
-    if (rx_put >= rx_get)
-       char_count = rx_put - rx_get;
-    else
-       char_count = rx_put - rx_get + rx_bufsize;
+       rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
+       rx_put = cy_readl(&buf_ctrl->rx_put);
+       rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+       rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
+       if (rx_put >= rx_get)
+               char_count = rx_put - rx_get;
+       else
+               char_count = rx_put - rx_get + rx_bufsize;
 
-    if ( char_count ) {
-       info->last_active = jiffies;
-       info->jiffies[1] = jiffies;
+       if (char_count) {
+               info->last_active = jiffies;
+               info->jiffies[1] = jiffies;
 
 #ifdef CY_ENABLE_MONITORING
-       info->mon.int_count++;
-       info->mon.char_count += char_count;
-       if (char_count > info->mon.char_max)
-           info->mon.char_max = char_count;
-       info->mon.char_last = char_count;
+               info->mon.int_count++;
+               info->mon.char_count += char_count;
+               if (char_count > info->mon.char_max)
+                       info->mon.char_max = char_count;
+               info->mon.char_last = char_count;
 #endif
-       if(tty == 0){
-           /* flush received characters */
-           new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1);
-           info->rflush_count++;
-       }else{
+               if (tty == 0) {
+                       /* flush received characters */
+                       new_rx_get = (new_rx_get + char_count) &
+                                       (rx_bufsize - 1);
+                       info->rflush_count++;
+               } else {
 #ifdef BLOCKMOVE
-           /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
-              for performance, but because of buffer boundaries, there
-              may be several steps to the operation */
-           while(0 < (small_count = 
-                      min_t(unsigned int, (rx_bufsize - new_rx_get),
-                      min_t(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count))
-                )) {
-               memcpy_fromio(tty->flip.char_buf_ptr,
-                             (char *)(cinfo->base_addr
-                                      + rx_bufaddr + new_rx_get),
-                             small_count);
-
-               tty->flip.char_buf_ptr += small_count;
-               memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count);
-               tty->flip.flag_buf_ptr += small_count;
-               new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1);
-               char_count -= small_count;
-               info->icount.rx += small_count;
-               info->idle_stats.recv_bytes += small_count;
-               tty->flip.count += small_count;
-           }
+               /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+                  for performance, but because of buffer boundaries, there
+                  may be several steps to the operation */
+                       while (0 < (small_count = min_t(unsigned int,
+                                       rx_bufsize - new_rx_get,
+                                       min_t(unsigned int, TTY_FLIPBUF_SIZE -
+                                               tty->flip.count, char_count)))){
+                               memcpy_fromio(tty->flip.char_buf_ptr,
+                                       (char *)(cinfo->base_addr + rx_bufaddr +
+                                               new_rx_get),
+                                       small_count);
+
+                               tty->flip.char_buf_ptr += small_count;
+                               memset(tty->flip.flag_buf_ptr, TTY_NORMAL,
+                                       small_count);
+                               tty->flip.flag_buf_ptr += small_count;
+                               new_rx_get = (new_rx_get + small_count) &
+                                               (rx_bufsize - 1);
+                               char_count -= small_count;
+                               info->icount.rx += small_count;
+                               info->idle_stats.recv_bytes += small_count;
+                               tty->flip.count += small_count;
+                       }
 #else
-           len = tty_buffer_request_room(tty, char_count);
-           while(len--){
-               data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
-               new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
-               tty_insert_flip_char(tty, data, TTY_NORMAL);
-               info->idle_stats.recv_bytes++;
-               info->icount.rx++;
-           }
+                       len = tty_buffer_request_room(tty, char_count);
+                       while (len--) {
+                               data = cy_readb(cinfo->base_addr + rx_bufaddr +
+                                               new_rx_get);
+                               new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1);
+                               tty_insert_flip_char(tty, data, TTY_NORMAL);
+                               info->idle_stats.recv_bytes++;
+                               info->icount.rx++;
+                       }
 #endif
 #ifdef CONFIG_CYZ_INTR
-           /* Recalculate the number of chars in the RX buffer and issue
-              a cmd in case it's higher than the RX high water mark */
-           rx_put = cy_readl(&buf_ctrl->rx_put);
-           if (rx_put >= rx_get)
-               char_count = rx_put - rx_get;
-           else
-               char_count = rx_put - rx_get + rx_bufsize;
-           if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) {
-               cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
-           }
+               /* Recalculate the number of chars in the RX buffer and issue
+                  a cmd in case it's higher than the RX high water mark */
+                       rx_put = cy_readl(&buf_ctrl->rx_put);
+                       if (rx_put >= rx_get)
+                               char_count = rx_put - rx_get;
+                       else
+                               char_count = rx_put - rx_get + rx_bufsize;
+                       if (char_count >= (int)cy_readl(&buf_ctrl->
+                                       rx_threshold)) {
+                               cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
+                       }
 #endif
-           info->idle_stats.recv_idle = jiffies;
-           tty_schedule_flip(tty);
+                       info->idle_stats.recv_idle = jiffies;
+                       tty_schedule_flip(tty);
+               }
+               /* Update rx_get */
+               cy_writel(&buf_ctrl->rx_get, new_rx_get);
        }
-       /* Update rx_get */
-       cy_writel(&buf_ctrl->rx_get, new_rx_get);
-    }
 }
 
 static void
 cyz_handle_tx(struct cyclades_port *info,
-             volatile struct CH_CTRL __iomem *ch_ctrl,
-             volatile struct BUF_CTRL __iomem *buf_ctrl)
+               volatile struct CH_CTRL __iomem * ch_ctrl,
+               volatile struct BUF_CTRL __iomem * buf_ctrl)
 {
-  struct cyclades_card *cinfo = &cy_card[info->card];
-  struct tty_struct *tty = info->tty;
-  char data;
-  volatile int char_count;
+       struct cyclades_card *cinfo = &cy_card[info->card];
+       struct tty_struct *tty = info->tty;
+       char data;
+       volatile int char_count;
 #ifdef BLOCKMOVE
-  int small_count;
+       int small_count;
 #endif
-  volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
+       volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
 
-    if (info->xmit_cnt <= 0)   /* Nothing to transmit */
-       return;
+       if (info->xmit_cnt <= 0)        /* Nothing to transmit */
+               return;
 
-    tx_get = cy_readl(&buf_ctrl->tx_get);
-    tx_put = cy_readl(&buf_ctrl->tx_put);
-    tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
-    tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
-    if (tx_put >= tx_get)
-       char_count = tx_get - tx_put - 1 + tx_bufsize;
-    else
-       char_count = tx_get - tx_put - 1;
+       tx_get = cy_readl(&buf_ctrl->tx_get);
+       tx_put = cy_readl(&buf_ctrl->tx_put);
+       tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+       tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
+       if (tx_put >= tx_get)
+               char_count = tx_get - tx_put - 1 + tx_bufsize;
+       else
+               char_count = tx_get - tx_put - 1;
 
-    if ( char_count ) {
+       if (char_count) {
 
-       if( tty == 0 ){
-           goto ztxdone;
-       }
+               if (tty == 0) {
+                       goto ztxdone;
+               }
 
-       if(info->x_char) { /* send special char */
-           data = info->x_char;
+               if (info->x_char) {     /* send special char */
+                       data = info->x_char;
 
-           cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data);
-           tx_put = (tx_put + 1) & (tx_bufsize - 1);
-           info->x_char = 0;
-           char_count--;
-           info->icount.tx++;
-           info->last_active = jiffies;
-           info->jiffies[2] = jiffies;
-       }
+                       cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+                       tx_put = (tx_put + 1) & (tx_bufsize - 1);
+                       info->x_char = 0;
+                       char_count--;
+                       info->icount.tx++;
+                       info->last_active = jiffies;
+                       info->jiffies[2] = jiffies;
+               }
 #ifdef BLOCKMOVE
-       while(0 < (small_count = 
-                  min_t(unsigned int, (tx_bufsize - tx_put),
-                      min_t(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail),
-                          min_t(unsigned int, info->xmit_cnt, char_count))))) {
-
-           memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
-                       &info->xmit_buf[info->xmit_tail],
-                       small_count);
-
-           tx_put = (tx_put + small_count) & (tx_bufsize - 1);
-           char_count -= small_count;
-           info->icount.tx += small_count;
-           info->xmit_cnt -= small_count;
-           info->xmit_tail = 
-               (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
-           info->last_active = jiffies;
-           info->jiffies[2] = jiffies;
-       }
+               while (0 < (small_count = min_t(unsigned int,
+                               tx_bufsize - tx_put, min_t(unsigned int,
+                                       (SERIAL_XMIT_SIZE - info->xmit_tail),
+                                       min_t(unsigned int, info->xmit_cnt,
+                                               char_count))))) {
+
+                       memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
+                                       tx_put),
+                                       &info->xmit_buf[info->xmit_tail],
+                                       small_count);
+
+                       tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+                       char_count -= small_count;
+                       info->icount.tx += small_count;
+                       info->xmit_cnt -= small_count;
+                       info->xmit_tail = (info->xmit_tail + small_count) &
+                                       (SERIAL_XMIT_SIZE - 1);
+                       info->last_active = jiffies;
+                       info->jiffies[2] = jiffies;
+               }
 #else
-       while (info->xmit_cnt && char_count){
-           data = info->xmit_buf[info->xmit_tail];
-           info->xmit_cnt--;
-           info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
-
-           cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
-           tx_put = (tx_put + 1) & (tx_bufsize - 1);
-           char_count--;
-           info->icount.tx++;
-           info->last_active = jiffies;
-           info->jiffies[2] = jiffies;
-       }
+               while (info->xmit_cnt && char_count) {
+                       data = info->xmit_buf[info->xmit_tail];
+                       info->xmit_cnt--;
+                       info->xmit_tail = (info->xmit_tail + 1) &
+                                       (SERIAL_XMIT_SIZE - 1);
+
+                       cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+                       tx_put = (tx_put + 1) & (tx_bufsize - 1);
+                       char_count--;
+                       info->icount.tx++;
+                       info->last_active = jiffies;
+                       info->jiffies[2] = jiffies;
+               }
 #endif
-    ztxdone:
-       if (info->xmit_cnt < WAKEUP_CHARS) {
-           cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+ztxdone:
+               if (info->xmit_cnt < WAKEUP_CHARS) {
+                       cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+               }
+               /* Update tx_put */
+               cy_writel(&buf_ctrl->tx_put, tx_put);
        }
-       /* Update tx_put */
-       cy_writel(&buf_ctrl->tx_put, tx_put);
-    }
 }
 
-static void
-cyz_handle_cmd(struct cyclades_card *cinfo)
+static void cyz_handle_cmd(struct cyclades_card *cinfo)
 {
-  struct tty_struct *tty;
-  struct cyclades_port *info;
-  static volatile struct FIRM_ID __iomem *firm_id;
-  static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
-  static volatile struct BOARD_CTRL __iomem *board_ctrl;
-  static volatile struct CH_CTRL __iomem *ch_ctrl;
-  static volatile struct BUF_CTRL __iomem *buf_ctrl;
-  uclong channel;
-  ucchar cmd;
-  uclong param;
-  uclong hw_ver, fw_ver;
-  int special_count;
-  int delta_count;
-
-    firm_id = cinfo->base_addr + ID_ADDRESS;
-    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-    board_ctrl = &zfw_ctrl->board_ctrl;
-    fw_ver = cy_readl(&board_ctrl->fw_version);
-    hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0);
-
-
-    while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
-       special_count = 0;
-       delta_count = 0;
-       info = &cy_port[channel + cinfo->first_line];
-       if((tty = info->tty) == 0) {
-           continue;
-       }
-       ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-       buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
-       switch(cmd) {
-           case C_CM_PR_ERROR:
-               tty_insert_flip_char(tty, 0, TTY_PARITY);
-               info->icount.rx++;
-               special_count++;
-               break;
-           case C_CM_FR_ERROR:
-               tty_insert_flip_char(tty, 0, TTY_FRAME);
-               info->icount.rx++;
-               special_count++;
-               break;
-           case C_CM_RXBRK:
-               tty_insert_flip_char(tty, 0, TTY_BREAK);
-               info->icount.rx++;
-               special_count++;
-               break;
-           case C_CM_MDCD:
-               info->icount.dcd++;
-               delta_count++;
-               if (info->flags & ASYNC_CHECK_CD){
-                   if ((fw_ver > 241 ? 
-                         ((u_long)param) : 
-                         cy_readl(&ch_ctrl->rs_status)) & C_RS_DCD) {
-                       cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
-                   }else{
-                       cy_sched_event(info, Cy_EVENT_HANGUP);
-                   }
+       struct tty_struct *tty;
+       struct cyclades_port *info;
+       static volatile struct FIRM_ID __iomem *firm_id;
+       static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
+       static volatile struct BOARD_CTRL __iomem *board_ctrl;
+       static volatile struct CH_CTRL __iomem *ch_ctrl;
+       static volatile struct BUF_CTRL __iomem *buf_ctrl;
+       uclong channel;
+       ucchar cmd;
+       uclong param;
+       uclong hw_ver, fw_ver;
+       int special_count;
+       int delta_count;
+
+       firm_id = cinfo->base_addr + ID_ADDRESS;
+       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+                       0xfffff);
+       board_ctrl = &zfw_ctrl->board_ctrl;
+       fw_ver = cy_readl(&board_ctrl->fw_version);
+       hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
+                       mail_box_0);
+
+       while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
+               special_count = 0;
+               delta_count = 0;
+               info = &cy_port[channel + cinfo->first_line];
+               if ((tty = info->tty) == 0) {
+                       continue;
                }
-               break;
-           case C_CM_MCTS:
-               info->icount.cts++;
-               delta_count++;
-               break;
-           case C_CM_MRI:
-               info->icount.rng++;
-               delta_count++;
-               break;
-           case C_CM_MDSR:
-               info->icount.dsr++;
-               delta_count++;
-               break;
+               ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+               buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+               switch (cmd) {
+               case C_CM_PR_ERROR:
+                       tty_insert_flip_char(tty, 0, TTY_PARITY);
+                       info->icount.rx++;
+                       special_count++;
+                       break;
+               case C_CM_FR_ERROR:
+                       tty_insert_flip_char(tty, 0, TTY_FRAME);
+                       info->icount.rx++;
+                       special_count++;
+                       break;
+               case C_CM_RXBRK:
+                       tty_insert_flip_char(tty, 0, TTY_BREAK);
+                       info->icount.rx++;
+                       special_count++;
+                       break;
+               case C_CM_MDCD:
+                       info->icount.dcd++;
+                       delta_count++;
+                       if (info->flags & ASYNC_CHECK_CD) {
+                               if ((fw_ver > 241 ? ((u_long) param) :
+                                               cy_readl(&ch_ctrl->rs_status)) &
+                                               C_RS_DCD) {
+                                       cy_sched_event(info,
+                                                       Cy_EVENT_OPEN_WAKEUP);
+                               } else {
+                                       cy_sched_event(info, Cy_EVENT_HANGUP);
+                               }
+                       }
+                       break;
+               case C_CM_MCTS:
+                       info->icount.cts++;
+                       delta_count++;
+                       break;
+               case C_CM_MRI:
+                       info->icount.rng++;
+                       delta_count++;
+                       break;
+               case C_CM_MDSR:
+                       info->icount.dsr++;
+                       delta_count++;
+                       break;
 #ifdef Z_WAKE
-           case C_CM_IOCTLW:
-               cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
-               break;
+               case C_CM_IOCTLW:
+                       cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+                       break;
 #endif
 #ifdef CONFIG_CYZ_INTR
-           case C_CM_RXHIWM:
-           case C_CM_RXNNDT:
-           case C_CM_INTBACK2:
-               /* Reception Interrupt */
+               case C_CM_RXHIWM:
+               case C_CM_RXNNDT:
+               case C_CM_INTBACK2:
+                       /* Reception Interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", 
-                       info->card, channel);
+                       printk("cyz_interrupt: rcvd intr, card %d, "
+                                       "port %ld\n\r", info->card, channel);
 #endif
-               cyz_handle_rx(info, ch_ctrl, buf_ctrl);
-               break;
-           case C_CM_TXBEMPTY:
-           case C_CM_TXLOWWM:
-           case C_CM_INTBACK:
-               /* Transmission Interrupt */
+                       cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+                       break;
+               case C_CM_TXBEMPTY:
+               case C_CM_TXLOWWM:
+               case C_CM_INTBACK:
+                       /* Transmission Interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-               printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", 
-                       info->card, channel);
+                       printk("cyz_interrupt: xmit intr, card %d, "
+                                       "port %ld\n\r", info->card, channel);
 #endif
-               cyz_handle_tx(info, ch_ctrl, buf_ctrl);
-               break;
-#endif /* CONFIG_CYZ_INTR */
-           case C_CM_FATAL:
-               /* should do something with this !!! */
-               break;
-           default:
-               break;
+                       cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+                       break;
+#endif                         /* CONFIG_CYZ_INTR */
+               case C_CM_FATAL:
+                       /* should do something with this !!! */
+                       break;
+               default:
+                       break;
+               }
+               if (delta_count)
+                       cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+               if (special_count)
+                       tty_schedule_flip(tty);
        }
-       if(delta_count)
-           cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
-       if(special_count)
-           tty_schedule_flip(tty);
-    }
 }
 
 #ifdef CONFIG_CYZ_INTR
-static irqreturn_t
-cyz_interrupt(int irq, void *dev_id)
+static irqreturn_t cyz_interrupt(int irq, void *dev_id)
 {
-  struct cyclades_card *cinfo;
+       struct cyclades_card *cinfo;
 
-    if((cinfo = (struct cyclades_card *)dev_id) == 0){
+       if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
 #ifdef CY_DEBUG_INTERRUPTS
-       printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+               printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
 #endif
-        return IRQ_NONE; /* spurious interrupt */
-    }
+               return IRQ_NONE;        /* spurious interrupt */
+       }
 
-    if (!ISZLOADED(*cinfo)) {
+       if (!ISZLOADED(*cinfo)) {
 #ifdef CY_DEBUG_INTERRUPTS
-       printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
+               printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
 #endif
-       return IRQ_NONE;
-    }
+               return IRQ_NONE;
+       }
 
-    /* Handle the interrupts */
-    cyz_handle_cmd(cinfo);
+       /* Handle the interrupts */
+       cyz_handle_cmd(cinfo);
 
-    return IRQ_HANDLED;
-} /* cyz_interrupt */
+       return IRQ_HANDLED;
+}                              /* cyz_interrupt */
 
-static void
-cyz_rx_restart(unsigned long arg)
+static void cyz_rx_restart(unsigned long arg)
 {
-    struct cyclades_port *info = (struct cyclades_port *)arg;
-    int retval;
-    int card = info->card;
-    uclong channel = (info->line) - (cy_card[card].first_line);
-    unsigned long flags;
-
-    CY_LOCK(info, flags);
-    retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
-    if (retval != 0){
-       printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", 
-              info->line, retval);
-    }
-    cyz_rx_full_timer[info->line].function = NULL;
-    CY_UNLOCK(info, flags);
+       struct cyclades_port *info = (struct cyclades_port *)arg;
+       int retval;
+       int card = info->card;
+       uclong channel = (info->line) - (cy_card[card].first_line);
+       unsigned long flags;
+
+       CY_LOCK(info, flags);
+       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
+       if (retval != 0) {
+               printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n",
+                       info->line, retval);
+       }
+       cyz_rx_full_timer[info->line].function = NULL;
+       CY_UNLOCK(info, flags);
 }
 
-#else /* CONFIG_CYZ_INTR */
+#else                          /* CONFIG_CYZ_INTR */
 
-static void
-cyz_poll(unsigned long arg)
+static void cyz_poll(unsigned long arg)
 {
-  struct cyclades_card *cinfo;
-  struct cyclades_port *info;
-  struct tty_struct *tty;
-  static volatile struct FIRM_ID *firm_id;
-  static volatile struct ZFW_CTRL *zfw_ctrl;
-  static volatile struct BOARD_CTRL *board_ctrl;
-  static volatile struct CH_CTRL *ch_ctrl;
-  static volatile struct BUF_CTRL *buf_ctrl;
-  int card, port;
-
-    cyz_timerlist.expires = jiffies + (HZ);
-    for (card = 0 ; card < NR_CARDS ; card++){
-       cinfo = &cy_card[card];
-
-       if (!IS_CYC_Z(*cinfo)) continue;
-       if (!ISZLOADED(*cinfo)) continue;
+       struct cyclades_card *cinfo;
+       struct cyclades_port *info;
+       struct tty_struct *tty;
+       static volatile struct FIRM_ID *firm_id;
+       static volatile struct ZFW_CTRL *zfw_ctrl;
+       static volatile struct BOARD_CTRL *board_ctrl;
+       static volatile struct CH_CTRL *ch_ctrl;
+       static volatile struct BUF_CTRL *buf_ctrl;
+       int card, port;
 
-       firm_id = cinfo->base_addr + ID_ADDRESS;
-       zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       board_ctrl = &(zfw_ctrl->board_ctrl);
+       cyz_timerlist.expires = jiffies + (HZ);
+       for (card = 0; card < NR_CARDS; card++) {
+               cinfo = &cy_card[card];
+
+               if (!IS_CYC_Z(*cinfo))
+                       continue;
+               if (!ISZLOADED(*cinfo))
+                       continue;
+
+               firm_id = cinfo->base_addr + ID_ADDRESS;
+               zfw_ctrl = cinfo->base_addr +
+                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               board_ctrl = &(zfw_ctrl->board_ctrl);
 
        /* Skip first polling cycle to avoid racing conditions with the FW */
-       if (!cinfo->intr_enabled) {
-           cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
-           cinfo->intr_enabled = 1;
-           continue;
-       }
+               if (!cinfo->intr_enabled) {
+                       cinfo->nports = (int)cy_readl(&board_ctrl->n_channel);
+                       cinfo->intr_enabled = 1;
+                       continue;
+               }
 
-       cyz_handle_cmd(cinfo);
+               cyz_handle_cmd(cinfo);
 
-       for (port = 0 ; port < cinfo->nports ; port++) {
-           info = &cy_port[ port + cinfo->first_line ];
-            tty = info->tty;
-           ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
-           buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
+               for (port = 0; port < cinfo->nports; port++) {
+                       info = &cy_port[port + cinfo->first_line];
+                       tty = info->tty;
+                       ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
+                       buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
 
-           if (!info->throttle)
-               cyz_handle_rx(info, ch_ctrl, buf_ctrl);
-           cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+                       if (!info->throttle)
+                               cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+                       cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+               }
+               /* poll every 'cyz_polling_cycle' period */
+               cyz_timerlist.expires = jiffies + cyz_polling_cycle;
        }
-       /* poll every 'cyz_polling_cycle' period */
-       cyz_timerlist.expires = jiffies + cyz_polling_cycle;
-    }
-    add_timer(&cyz_timerlist);
-
-    return;
-} /* cyz_poll */
+       add_timer(&cyz_timerlist);
+}                              /* cyz_poll */
 
-#endif /* CONFIG_CYZ_INTR */
+#endif                         /* CONFIG_CYZ_INTR */
 
 /********** End of block of Cyclades-Z specific code *********/
 /***********************************************************/
 
-
 /* This is called whenever a port becomes active;
    interrupts are enabled and DTR & RTS are turned on.
  */
-static int
-startup(struct cyclades_port * info)
+static int startup(struct cyclades_port *info)
 {
-  unsigned long flags;
-  int retval = 0;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
-  unsigned long page;
+       unsigned long flags;
+       int retval = 0;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
+       unsigned long page;
 
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
 
-    page = get_zeroed_page(GFP_KERNEL);
-    if (!page)
-       return -ENOMEM;
+       page = get_zeroed_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
 
-    CY_LOCK(info, flags);
+       CY_LOCK(info, flags);
 
-    if (info->flags & ASYNC_INITIALIZED){
-       free_page(page);
-       goto errout;
-    }
+       if (info->flags & ASYNC_INITIALIZED) {
+               free_page(page);
+               goto errout;
+       }
 
-    if (!info->type){
-        if (info->tty){
-            set_bit(TTY_IO_ERROR, &info->tty->flags);
-        }
-       free_page(page);
-       goto errout;
-    }
+       if (!info->type) {
+               if (info->tty) {
+                       set_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               free_page(page);
+               goto errout;
+       }
 
-    if (info->xmit_buf)
-       free_page(page);
-    else
-       info->xmit_buf = (unsigned char *) page;
+       if (info->xmit_buf)
+               free_page(page);
+       else
+               info->xmit_buf = (unsigned char *)page;
 
-    CY_UNLOCK(info, flags);
+       CY_UNLOCK(info, flags);
 
-    set_line_char(info);
+       set_line_char(info);
 
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr = cy_card[card].base_addr +
+                               (cy_chip_offset[chip] << index);
 
 #ifdef CY_DEBUG_OPEN
-       printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
-            card, chip, channel, (long)base_addr);/**/
+               printk("cyc startup card %d, chip %d, channel %d, "
+                               "base_addr %lx\n",
+                               card, chip, channel, (long)base_addr);
+               /**/
 #endif
+               CY_LOCK(info, flags);
 
-       CY_LOCK(info, flags);
-
-       cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
 
-       cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
-                ? info->default_timeout : 0x02)); /* 10ms rx timeout */
+               cy_writeb(base_addr + (CyRTPR << index),
+                       (info->default_timeout ? info->default_timeout : 0x02));
+               /* 10ms rx timeout */
 
-       cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
+               cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
+                               index);
 
-       cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-       cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-       cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+               cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
 
 #ifdef CY_DEBUG_DTR
-       printk("cyc:startup raising DTR\n");
-       printk("     status: 0x%x, 0x%x\n",
-               cy_readb(base_addr+(CyMSVR1<<index)), 
-                cy_readb(base_addr+(CyMSVR2<<index)));
+               printk("cyc:startup raising DTR\n");
+               printk("     status: 0x%x, 0x%x\n",
+                       cy_readb(base_addr + (CyMSVR1 << index)),
+                       cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
 
-       cy_writeb(base_addr+(CySRER<<index),
-               cy_readb(base_addr+(CySRER<<index)) | CyRxData);
-       info->flags |= ASYNC_INITIALIZED;
+               cy_writeb(base_addr + (CySRER << index),
+                       cy_readb(base_addr + (CySRER << index)) | CyRxData);
+               info->flags |= ASYNC_INITIALIZED;
 
-       if (info->tty){
-           clear_bit(TTY_IO_ERROR, &info->tty->flags);
-       }
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       info->breakon = info->breakoff = 0;
-       memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-       info->idle_stats.in_use    =
-       info->idle_stats.recv_idle =
-       info->idle_stats.xmit_idle = jiffies;
+               if (info->tty) {
+                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+               info->breakon = info->breakoff = 0;
+               memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+               info->idle_stats.in_use =
+               info->idle_stats.recv_idle =
+               info->idle_stats.xmit_idle = jiffies;
 
-       CY_UNLOCK(info, flags);
+               CY_UNLOCK(info, flags);
 
-    } else {
-      struct FIRM_ID __iomem *firm_id;
-      struct ZFW_CTRL __iomem *zfw_ctrl;
-      struct BOARD_CTRL __iomem *board_ctrl;
-      struct CH_CTRL __iomem *ch_ctrl;
-      int retval;
+       } else {
+               struct FIRM_ID __iomem *firm_id;
+               struct ZFW_CTRL __iomem *zfw_ctrl;
+               struct BOARD_CTRL __iomem *board_ctrl;
+               struct CH_CTRL __iomem *ch_ctrl;
+               int retval;
 
-       base_addr = cy_card[card].base_addr;
+               base_addr = cy_card[card].base_addr;
 
-        firm_id = base_addr + ID_ADDRESS;
-        if (!ISZLOADED(cy_card[card])){
-           return -ENODEV;
-       }
+               firm_id = base_addr + ID_ADDRESS;
+               if (!ISZLOADED(cy_card[card])) {
+                       return -ENODEV;
+               }
 
-       zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       board_ctrl = &zfw_ctrl->board_ctrl;
-       ch_ctrl = zfw_ctrl->ch_ctrl;
+               zfw_ctrl = cy_card[card].base_addr +
+                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               board_ctrl = &zfw_ctrl->board_ctrl;
+               ch_ctrl = zfw_ctrl->ch_ctrl;
 
 #ifdef CY_DEBUG_OPEN
-       printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
-            card, channel, (long)base_addr);/**/
+               printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
+                       card, channel, (long)base_addr);
+               /**/
 #endif
+               CY_LOCK(info, flags);
 
-       CY_LOCK(info, flags);
-
-       cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
+               cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
 #ifdef Z_WAKE
 #ifdef CONFIG_CYZ_INTR
-       cy_writel(&ch_ctrl[channel].intr_enable, 
-                 C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
-                 C_IN_IOCTLW|
-                 C_IN_MDCD);
+               cy_writel(&ch_ctrl[channel].intr_enable,
+                         C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+                         C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
 #else
-       cy_writel(&ch_ctrl[channel].intr_enable, 
-                 C_IN_IOCTLW|
-                 C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
+               cy_writel(&ch_ctrl[channel].intr_enable,
+                         C_IN_IOCTLW | C_IN_MDCD);
+#endif                         /* CONFIG_CYZ_INTR */
 #else
 #ifdef CONFIG_CYZ_INTR
-       cy_writel(&ch_ctrl[channel].intr_enable, 
-                 C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
-                 C_IN_MDCD);
+               cy_writel(&ch_ctrl[channel].intr_enable,
+                         C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+                         C_IN_RXNNDT | C_IN_MDCD);
 #else
-       cy_writel(&ch_ctrl[channel].intr_enable, 
-                 C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
-#endif /* Z_WAKE */
-
-       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
-       if (retval != 0){
-           printk("cyc:startup(1) retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+               cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD);
+#endif                         /* CONFIG_CYZ_INTR */
+#endif                         /* Z_WAKE */
+
+               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+               if (retval != 0) {
+                       printk("cyc:startup(1) retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
 
-       /* Flush RX buffers before raising DTR and RTS */
-       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L);
-       if (retval != 0){
-           printk("cyc:startup(2) retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+               /* Flush RX buffers before raising DTR and RTS */
+               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX,
+                               0L);
+               if (retval != 0) {
+                       printk("cyc:startup(2) retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
 
-       /* set timeout !!! */
-       /* set RTS and DTR !!! */
-       cy_writel(&ch_ctrl[channel].rs_control,
-             cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR) ;
-       retval = cyz_issue_cmd(&cy_card[info->card],
-           channel, C_CM_IOCTLM, 0L);
-       if (retval != 0){
-           printk("cyc:startup(3) retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+               /* set timeout !!! */
+               /* set RTS and DTR !!! */
+               cy_writel(&ch_ctrl[channel].rs_control,
+                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
+                       C_RS_DTR);
+               retval = cyz_issue_cmd(&cy_card[info->card], channel,
+                               C_CM_IOCTLM, 0L);
+               if (retval != 0) {
+                       printk("cyc:startup(3) retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
 #ifdef CY_DEBUG_DTR
-           printk("cyc:startup raising Z DTR\n");
+               printk("cyc:startup raising Z DTR\n");
 #endif
 
-       /* enable send, recv, modem !!! */
+               /* enable send, recv, modem !!! */
 
-       info->flags |= ASYNC_INITIALIZED;
-       if (info->tty){
-           clear_bit(TTY_IO_ERROR, &info->tty->flags);
-       }
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       info->breakon = info->breakoff = 0;
-       memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-       info->idle_stats.in_use    =
-       info->idle_stats.recv_idle =
-       info->idle_stats.xmit_idle = jiffies;
+               info->flags |= ASYNC_INITIALIZED;
+               if (info->tty) {
+                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+               info->breakon = info->breakoff = 0;
+               memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+               info->idle_stats.in_use =
+               info->idle_stats.recv_idle =
+               info->idle_stats.xmit_idle = jiffies;
 
-       CY_UNLOCK(info, flags);
-    }
+               CY_UNLOCK(info, flags);
+       }
 
 #ifdef CY_DEBUG_OPEN
        printk(" cyc startup done\n");
@@ -2093,165 +2154,165 @@ startup(struct cyclades_port * info)
 errout:
        CY_UNLOCK(info, flags);
        return retval;
-} /* startup */
-
+}                              /* startup */
 
-static void
-start_xmit( struct cyclades_port *info )
+static void start_xmit(struct cyclades_port *info)
 {
-  unsigned long flags;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       unsigned long flags;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
 
-       CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyCAR<<index), channel);
-           cy_writeb(base_addr+(CySRER<<index), 
-               cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
-       CY_UNLOCK(info, flags);
-    } else {
-#ifdef CONFIG_CYZ_INTR
-      int retval;
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr = cy_card[card].base_addr +
+                               (cy_chip_offset[chip] << index);
 
-       CY_LOCK(info, flags);
-           retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
-           if (retval != 0){
-               printk("cyc:start_xmit retval on ttyC%d was %x\n",
-                      info->line, retval);
-           }
-       CY_UNLOCK(info, flags);
-#else /* CONFIG_CYZ_INTR */
-       /* Don't have to do anything at this time */
-#endif /* CONFIG_CYZ_INTR */
-    }
-} /* start_xmit */
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCAR << index), channel);
+               cy_writeb(base_addr + (CySRER << index),
+                       cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
+               CY_UNLOCK(info, flags);
+       } else {
+#ifdef CONFIG_CYZ_INTR
+               int retval;
+
+               CY_LOCK(info, flags);
+               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK,
+                               0L);
+               if (retval != 0) {
+                       printk("cyc:start_xmit retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
+               CY_UNLOCK(info, flags);
+#else                          /* CONFIG_CYZ_INTR */
+               /* Don't have to do anything at this time */
+#endif                         /* CONFIG_CYZ_INTR */
+       }
+}                              /* start_xmit */
 
 /*
  * This routine shuts down a serial port; interrupts are disabled,
  * and DTR is dropped if the hangup on close termio flag is on.
  */
-static void
-shutdown(struct cyclades_port * info)
+static void shutdown(struct cyclades_port *info)
 {
-  unsigned long flags;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
-
-    if (!(info->flags & ASYNC_INITIALIZED)){
-        return;
-    }
-
-    card = info->card;
-    channel = info->line - cy_card[card].first_line;
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       unsigned long flags;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
+
+       if (!(info->flags & ASYNC_INITIALIZED)) {
+               return;
+       }
+
+       card = info->card;
+       channel = info->line - cy_card[card].first_line;
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr = cy_card[card].base_addr +
+                               (cy_chip_offset[chip] << index);
 
 #ifdef CY_DEBUG_OPEN
-    printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
-               card, chip, channel, (long)base_addr);
+               printk("cyc shutdown Y card %d, chip %d, channel %d, "
+                               "base_addr %lx\n",
+                               card, chip, channel, (long)base_addr);
 #endif
 
-       CY_LOCK(info, flags);
+               CY_LOCK(info, flags);
+
+               /* Clear delta_msr_wait queue to avoid mem leaks. */
+               wake_up_interruptible(&info->delta_msr_wait);
 
-           /* Clear delta_msr_wait queue to avoid mem leaks. */
-           wake_up_interruptible(&info->delta_msr_wait);
-
-           if (info->xmit_buf){
-               unsigned char * temp;
-               temp = info->xmit_buf;
-               info->xmit_buf = NULL;
-               free_page((unsigned long) temp);
-           }
-           cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-           if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-               cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
-               cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
+               if (info->xmit_buf) {
+                       unsigned char *temp;
+                       temp = info->xmit_buf;
+                       info->xmit_buf = NULL;
+                       free_page((unsigned long)temp);
+               }
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+                       cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+                       cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
-               printk("cyc shutdown dropping DTR\n");
-               printk("     status: 0x%x, 0x%x\n",
-                   cy_readb(base_addr+(CyMSVR1<<index)), 
-                    cy_readb(base_addr+(CyMSVR2<<index)));
+                       printk("cyc shutdown dropping DTR\n");
+                       printk("     status: 0x%x, 0x%x\n",
+                               cy_readb(base_addr + (CyMSVR1 << index)),
+                               cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
-           }
-           cyy_issue_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index);
-            /* it may be appropriate to clear _XMIT at
-              some later date (after testing)!!! */
-
-           if (info->tty){
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-           }
-           info->flags &= ~ASYNC_INITIALIZED;
-       CY_UNLOCK(info, flags);
-    } else {
-      struct FIRM_ID __iomem *firm_id;
-      struct ZFW_CTRL __iomem *zfw_ctrl;
-      struct BOARD_CTRL __iomem *board_ctrl;
-      struct CH_CTRL __iomem *ch_ctrl;
-      int retval;
-
-       base_addr = cy_card[card].base_addr;
+               }
+               cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
+               /* it may be appropriate to clear _XMIT at
+                  some later date (after testing)!!! */
+
+               if (info->tty) {
+                       set_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               info->flags &= ~ASYNC_INITIALIZED;
+               CY_UNLOCK(info, flags);
+       } else {
+               struct FIRM_ID __iomem *firm_id;
+               struct ZFW_CTRL __iomem *zfw_ctrl;
+               struct BOARD_CTRL __iomem *board_ctrl;
+               struct CH_CTRL __iomem *ch_ctrl;
+               int retval;
+
+               base_addr = cy_card[card].base_addr;
 #ifdef CY_DEBUG_OPEN
-    printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
-               card, channel, (long)base_addr);
+               printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
+                       card, channel, (long)base_addr);
 #endif
 
-        firm_id = base_addr + ID_ADDRESS;
-        if (!ISZLOADED(cy_card[card])) {
-           return;
-       }
+               firm_id = base_addr + ID_ADDRESS;
+               if (!ISZLOADED(cy_card[card])) {
+                       return;
+               }
 
-       zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       board_ctrl = &zfw_ctrl->board_ctrl;
-       ch_ctrl = zfw_ctrl->ch_ctrl;
+               zfw_ctrl = cy_card[card].base_addr +
+                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               board_ctrl = &zfw_ctrl->board_ctrl;
+               ch_ctrl = zfw_ctrl->ch_ctrl;
 
-       CY_LOCK(info, flags);
+               CY_LOCK(info, flags);
 
-           if (info->xmit_buf){
-               unsigned char * temp;
-               temp = info->xmit_buf;
-               info->xmit_buf = NULL;
-               free_page((unsigned long) temp);
-           }
-           
-           if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-               cy_writel(&ch_ctrl[channel].rs_control,
-                   (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & 
-                   ~(C_RS_RTS | C_RS_DTR)));
-               retval = cyz_issue_cmd(&cy_card[info->card],
-                       channel, C_CM_IOCTLM, 0L);
-               if (retval != 0){
-                   printk("cyc:shutdown retval on ttyC%d was %x\n",
-                          info->line, retval);
+               if (info->xmit_buf) {
+                       unsigned char *temp;
+                       temp = info->xmit_buf;
+                       info->xmit_buf = NULL;
+                       free_page((unsigned long)temp);
                }
+
+               if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+                       cy_writel(&ch_ctrl[channel].rs_control,
+                               (uclong)(cy_readl(&ch_ctrl[channel].rs_control)&
+                                       ~(C_RS_RTS | C_RS_DTR)));
+                       retval = cyz_issue_cmd(&cy_card[info->card], channel,
+                                       C_CM_IOCTLM, 0L);
+                       if (retval != 0) {
+                               printk("cyc:shutdown retval on ttyC%d was %x\n",
+                                       info->line, retval);
+                       }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:shutdown dropping Z DTR\n");
+                       printk("cyc:shutdown dropping Z DTR\n");
 #endif
-           }
-           
-           if (info->tty){
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-           }
-           info->flags &= ~ASYNC_INITIALIZED;
+               }
 
-       CY_UNLOCK(info, flags);
-    }
+               if (info->tty) {
+                       set_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               info->flags &= ~ASYNC_INITIALIZED;
+
+               CY_UNLOCK(info, flags);
+       }
 
 #ifdef CY_DEBUG_OPEN
-    printk(" cyc shutdown done\n");
+       printk(" cyc shutdown done\n");
 #endif
-    return;
-} /* shutdown */
-
+}                              /* shutdown */
 
 /*
  * ------------------------------------------------------------
@@ -2260,527 +2321,546 @@ shutdown(struct cyclades_port * info)
  */
 
 static int
-block_til_ready(struct tty_struct *tty, struct file * filp,
-                           struct cyclades_port *info)
+block_til_ready(struct tty_struct *tty, struct file *filp,
+               struct cyclades_port *info)
 {
-  DECLARE_WAITQUEUE(wait, current);
-  struct cyclades_card *cinfo;
-  unsigned long flags;
-  int chip, channel,index;
-  int retval;
-  void __iomem *base_addr;
-
-    cinfo = &cy_card[info->card];
-    channel = info->line - cinfo->first_line;
-
-    /*
-     * If the device is in the middle of being closed, then block
-     * until it's done, and then try again.
-     */
-    if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-       if (info->flags & ASYNC_CLOSING) {
-            interruptible_sleep_on(&info->close_wait);
+       DECLARE_WAITQUEUE(wait, current);
+       struct cyclades_card *cinfo;
+       unsigned long flags;
+       int chip, channel, index;
+       int retval;
+       void __iomem *base_addr;
+
+       cinfo = &cy_card[info->card];
+       channel = info->line - cinfo->first_line;
+
+       /*
+        * If the device is in the middle of being closed, then block
+        * until it's done, and then try again.
+        */
+       if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+               if (info->flags & ASYNC_CLOSING) {
+                       interruptible_sleep_on(&info->close_wait);
+               }
+               return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
        }
-        return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
-    }
-
-    /*
-     * If non-blocking mode is set, then make the check up front
-     * and then exit.
-     */
-    if ((filp->f_flags & O_NONBLOCK) ||
-       (tty->flags & (1 << TTY_IO_ERROR))) {
-        info->flags |= ASYNC_NORMAL_ACTIVE;
-        return 0;
-    }
-
-    /*
-     * Block waiting for the carrier detect and the line to become
-     * free (i.e., not in use by the callout).  While we are in
-     * this loop, info->count is dropped by one, so that
-     * cy_close() knows when to free things.  We restore it upon
-     * exit, either normal or abnormal.
-     */
-    retval = 0;
-    add_wait_queue(&info->open_wait, &wait);
+
+       /*
+        * If non-blocking mode is set, then make the check up front
+        * and then exit.
+        */
+       if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+               info->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;
+       }
+
+       /*
+        * Block waiting for the carrier detect and the line to become
+        * free (i.e., not in use by the callout).  While we are in
+        * this loop, info->count is dropped by one, so that
+        * cy_close() knows when to free things.  We restore it upon
+        * exit, either normal or abnormal.
+        */
+       retval = 0;
+       add_wait_queue(&info->open_wait, &wait);
 #ifdef CY_DEBUG_OPEN
-    printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
-           info->line, info->count);/**/
+       printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
+               info->line, info->count);
+       /**/
 #endif
-    CY_LOCK(info, flags);
-    if (!tty_hung_up_p(filp))
-       info->count--;
-    CY_UNLOCK(info, flags);
+       CY_LOCK(info, flags);
+       if (!tty_hung_up_p(filp))
+               info->count--;
+       CY_UNLOCK(info, flags);
 #ifdef CY_DEBUG_COUNT
-    printk("cyc block_til_ready: (%d): decrementing count to %d\n",
-        current->pid, info->count);
+       printk("cyc block_til_ready: (%d): decrementing count to %d\n",
+               current->pid, info->count);
 #endif
-    info->blocked_open++;
-
-    if (!IS_CYC_Z(*cinfo)) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cinfo->bus_index;
-       base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
-
-       while (1) {
-           CY_LOCK(info, flags);
-               if ((tty->termios->c_cflag & CBAUD)){
-                   cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-                   cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-                   cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
+       info->blocked_open++;
+
+       if (!IS_CYC_Z(*cinfo)) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cinfo->bus_index;
+               base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
+
+               while (1) {
+                       CY_LOCK(info, flags);
+                       if ((tty->termios->c_cflag & CBAUD)) {
+                               cy_writeb(base_addr + (CyCAR << index),
+                                         (u_char) channel);
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         CyRTS);
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         CyDTR);
 #ifdef CY_DEBUG_DTR
-                   printk("cyc:block_til_ready raising DTR\n");
-                   printk("     status: 0x%x, 0x%x\n",
-                       cy_readb(base_addr+(CyMSVR1<<index)), 
-                        cy_readb(base_addr+(CyMSVR2<<index)));
+                               printk("cyc:block_til_ready raising DTR\n");
+                               printk("     status: 0x%x, 0x%x\n",
+                                       cy_readb(base_addr +
+                                               (CyMSVR1 << index)),
+                                       cy_readb(base_addr +
+                                               (CyMSVR2 << index)));
 #endif
-               }
-           CY_UNLOCK(info, flags);
+                       }
+                       CY_UNLOCK(info, flags);
 
-           set_current_state(TASK_INTERRUPTIBLE);
-           if (tty_hung_up_p(filp)
-           || !(info->flags & ASYNC_INITIALIZED) ){
-               retval = ((info->flags & ASYNC_HUP_NOTIFY) ? 
-                   -EAGAIN : -ERESTARTSYS);
-               break;
-           }
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (tty_hung_up_p(filp) ||
+                                       !(info->flags & ASYNC_INITIALIZED)) {
+                               retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+                                         -EAGAIN : -ERESTARTSYS);
+                               break;
+                       }
 
-           CY_LOCK(info, flags);
-               cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-               if (!(info->flags & ASYNC_CLOSING)
-               && (C_CLOCAL(tty)
-                   || (cy_readb(base_addr+(CyMSVR1<<index)) & CyDCD))) {
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+                                       (cy_readb(base_addr +
+                                               (CyMSVR1 << index)) & CyDCD))) {
+                               CY_UNLOCK(info, flags);
+                               break;
+                       }
                        CY_UNLOCK(info, flags);
-                       break;
-               }
-           CY_UNLOCK(info, flags);
 
-           if (signal_pending(current)) {
-               retval = -ERESTARTSYS;
-               break;
-           }
+                       if (signal_pending(current)) {
+                               retval = -ERESTARTSYS;
+                               break;
+                       }
 #ifdef CY_DEBUG_OPEN
-           printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
-                  info->line, info->count);/**/
+                       printk("cyc block_til_ready blocking: ttyC%d, "
+                                       "count = %d\n",
+                                       info->line, info->count);
+                       /**/
 #endif
-           schedule();
-       }
-    } else {
-      struct FIRM_ID __iomem *firm_id;
-      struct ZFW_CTRL __iomem *zfw_ctrl;
-      struct BOARD_CTRL __iomem *board_ctrl;
-      struct CH_CTRL __iomem *ch_ctrl;
-      int retval;
-
-       base_addr = cinfo->base_addr;
-       firm_id = base_addr + ID_ADDRESS;
-        if (!ISZLOADED(*cinfo)){
-            current->state = TASK_RUNNING;
-           remove_wait_queue(&info->open_wait, &wait);
-           return -EINVAL;
-       }
-
-       zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       board_ctrl = &zfw_ctrl->board_ctrl;
-       ch_ctrl = zfw_ctrl->ch_ctrl;
-
-       while (1) {
-           if ((tty->termios->c_cflag & CBAUD)){
-               cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) |
-                       (C_RS_RTS | C_RS_DTR));
-               retval = cyz_issue_cmd(&cy_card[info->card],
-                                      channel, C_CM_IOCTLM, 0L);
-               if (retval != 0){
-                   printk("cyc:block_til_ready retval on ttyC%d was %x\n",
-                          info->line, retval);
+                       schedule();
+               }
+       } else {
+               struct FIRM_ID __iomem *firm_id;
+               struct ZFW_CTRL __iomem *zfw_ctrl;
+               struct BOARD_CTRL __iomem *board_ctrl;
+               struct CH_CTRL __iomem *ch_ctrl;
+               int retval;
+
+               base_addr = cinfo->base_addr;
+               firm_id = base_addr + ID_ADDRESS;
+               if (!ISZLOADED(*cinfo)) {
+                       current->state = TASK_RUNNING;
+                       remove_wait_queue(&info->open_wait, &wait);
+                       return -EINVAL;
                }
+
+               zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+                               0xfffff);
+               board_ctrl = &zfw_ctrl->board_ctrl;
+               ch_ctrl = zfw_ctrl->ch_ctrl;
+
+               while (1) {
+                       if ((tty->termios->c_cflag & CBAUD)) {
+                               cy_writel(&ch_ctrl[channel].rs_control,
+                                         cy_readl(&ch_ctrl[channel].
+                                                  rs_control) | (C_RS_RTS |
+                                                                 C_RS_DTR));
+                               retval = cyz_issue_cmd(&cy_card[info->card],
+                                               channel, C_CM_IOCTLM, 0L);
+                               if (retval != 0) {
+                                       printk("cyc:block_til_ready retval on "
+                                               "ttyC%d was %x\n",
+                                               info->line, retval);
+                               }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:block_til_ready raising Z DTR\n");
+                               printk("cyc:block_til_ready raising Z DTR\n");
 #endif
-           }
+                       }
 
-           set_current_state(TASK_INTERRUPTIBLE);
-           if (tty_hung_up_p(filp)
-           || !(info->flags & ASYNC_INITIALIZED) ){
-               retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
-                   -EAGAIN : -ERESTARTSYS);
-               break;
-           }
-           if (!(info->flags & ASYNC_CLOSING)
-           && (C_CLOCAL(tty)
-             || (cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) {
-               break;
-           }
-           if (signal_pending(current)) {
-               retval = -ERESTARTSYS;
-               break;
-           }
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (tty_hung_up_p(filp) ||
+                                       !(info->flags & ASYNC_INITIALIZED)) {
+                               retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+                                         -EAGAIN : -ERESTARTSYS);
+                               break;
+                       }
+                       if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+                                       (cy_readl(&ch_ctrl[channel].rs_status) &
+                                               C_RS_DCD))) {
+                               break;
+                       }
+                       if (signal_pending(current)) {
+                               retval = -ERESTARTSYS;
+                               break;
+                       }
 #ifdef CY_DEBUG_OPEN
-           printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
-                  info->line, info->count);/**/
+                       printk("cyc block_til_ready blocking: ttyC%d, "
+                                       "count = %d\n",
+                                       info->line, info->count);
+                       /**/
 #endif
-           schedule();
+                       schedule();
+               }
        }
-    }
-    current->state = TASK_RUNNING;
-    remove_wait_queue(&info->open_wait, &wait);
-    if (!tty_hung_up_p(filp)){
-       info->count++;
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&info->open_wait, &wait);
+       if (!tty_hung_up_p(filp)) {
+               info->count++;
 #ifdef CY_DEBUG_COUNT
-       printk("cyc:block_til_ready (%d): incrementing count to %d\n",
-           current->pid, info->count);
+               printk("cyc:block_til_ready (%d): incrementing count to %d\n",
+                       current->pid, info->count);
 #endif
-    }
-    info->blocked_open--;
+       }
+       info->blocked_open--;
 #ifdef CY_DEBUG_OPEN
-    printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
-          info->line, info->count);/**/
+       printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
+               info->line, info->count);
+       /**/
 #endif
-    if (retval)
-       return retval;
-    info->flags |= ASYNC_NORMAL_ACTIVE;
-    return 0;
-} /* block_til_ready */
-
+       if (retval)
+               return retval;
+       info->flags |= ASYNC_NORMAL_ACTIVE;
+       return 0;
+}                              /* block_til_ready */
 
 /*
  * This routine is called whenever a serial port is opened.  It
  * performs the serial-specific initialization for the tty structure.
  */
-static int
-cy_open(struct tty_struct *tty, struct file * filp)
+static int cy_open(struct tty_struct *tty, struct file *filp)
 {
-  struct cyclades_port  *info;
-  int retval, line;
-
-    line = tty->index;
-    if ((line < 0) || (NR_PORTS <= line)){
-        return -ENODEV;
-    }
-    info = &cy_port[line];
-    if (info->line < 0){
-        return -ENODEV;
-    }
-    
-    /* If the card's firmware hasn't been loaded,
-       treat it as absent from the system.  This
-       will make the user pay attention.
-    */
-    if (IS_CYC_Z(cy_card[info->card])) {
-       struct cyclades_card *cinfo = &cy_card[info->card];
-       struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
-
-        if (!ISZLOADED(*cinfo)) {
-           if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *)
-               (cinfo->ctl_addr))->mail_box_0)) &&
-               Z_FPGA_CHECK (*cinfo)) &&
-               (ZFIRM_HLT == cy_readl (&firm_id->signature)))
-           {
-               printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
-           } else {
-               printk("cyc:Cyclades-Z firmware not yet loaded\n");
-           }
-           return -ENODEV;
-       }
-#ifdef CONFIG_CYZ_INTR
-       else {
-           /* In case this Z board is operating in interrupt mode, its 
-              interrupts should be enabled as soon as the first open happens 
-              to one of its ports. */
-            if (!cinfo->intr_enabled) {
-               struct ZFW_CTRL __iomem *zfw_ctrl;
-               struct BOARD_CTRL __iomem *board_ctrl;
-
-               zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff);
+       struct cyclades_port *info;
+       int retval, line;
 
-               board_ctrl = &zfw_ctrl->board_ctrl;
+       line = tty->index;
+       if ((line < 0) || (NR_PORTS <= line)) {
+               return -ENODEV;
+       }
+       info = &cy_port[line];
+       if (info->line < 0) {
+               return -ENODEV;
+       }
 
-               /* Enable interrupts on the PLX chip */
-               cy_writew(cinfo->ctl_addr+0x68,
-                       cy_readw(cinfo->ctl_addr+0x68)|0x0900);
-               /* Enable interrupts on the FW */
-               retval = cyz_issue_cmd(cinfo,
-                                       0, C_CM_IRQ_ENBL, 0L);
-               if (retval != 0){
-                   printk("cyc:IRQ enable retval was %x\n", retval);
+       /* If the card's firmware hasn't been loaded,
+          treat it as absent from the system.  This
+          will make the user pay attention.
+        */
+       if (IS_CYC_Z(cy_card[info->card])) {
+               struct cyclades_card *cinfo = &cy_card[info->card];
+               struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
+
+               if (!ISZLOADED(*cinfo)) {
+                       if (((ZE_V1 == cy_readl(
+                                       &((struct RUNTIME_9060 __iomem *)
+                                        (cinfo->ctl_addr))->mail_box_0)) &&
+                                       Z_FPGA_CHECK(*cinfo)) &&
+                                       (ZFIRM_HLT == cy_readl(
+                                               &firm_id->signature))) {
+                               printk("cyc:Cyclades-Z Error: you need an "
+                                       "external power supply for this number "
+                                       "of ports.\n\rFirmware halted.\r\n");
+                       } else {
+                               printk("cyc:Cyclades-Z firmware not yet "
+                                       "loaded\n");
+                       }
+                       return -ENODEV;
                }
-               cinfo->nports = (int) cy_readl (&board_ctrl->n_channel);
-               cinfo->intr_enabled = 1;
-           }
+#ifdef CONFIG_CYZ_INTR
+               else {
+               /* In case this Z board is operating in interrupt mode, its
+                  interrupts should be enabled as soon as the first open
+                  happens to one of its ports. */
+                       if (!cinfo->intr_enabled) {
+                               struct ZFW_CTRL __iomem *zfw_ctrl;
+                               struct BOARD_CTRL __iomem *board_ctrl;
+
+                               zfw_ctrl = cinfo->base_addr +
+                                       (cy_readl(&firm_id->zfwctrl_addr) &
+                                               0xfffff);
+
+                               board_ctrl = &zfw_ctrl->board_ctrl;
+
+                               /* Enable interrupts on the PLX chip */
+                               cy_writew(cinfo->ctl_addr + 0x68,
+                                         cy_readw(cinfo->ctl_addr +
+                                                  0x68) | 0x0900);
+                               /* Enable interrupts on the FW */
+                               retval = cyz_issue_cmd(cinfo, 0,
+                                               C_CM_IRQ_ENBL, 0L);
+                               if (retval != 0) {
+                                       printk("cyc:IRQ enable retval was %x\n",
+                                               retval);
+                               }
+                               cinfo->nports =
+                                       (int)cy_readl(&board_ctrl->n_channel);
+                               cinfo->intr_enabled = 1;
+                       }
+               }
+#endif                         /* CONFIG_CYZ_INTR */
+               /* Make sure this Z port really exists in hardware */
+               if (info->line > (cinfo->first_line + cinfo->nports - 1))
+                       return -ENODEV;
        }
-#endif /* CONFIG_CYZ_INTR */
-       /* Make sure this Z port really exists in hardware */
-       if (info->line > (cinfo->first_line + cinfo->nports - 1))
-               return -ENODEV;
-    }
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_open ttyC%d\n", info->line); /* */
+       printk("cyc:cy_open ttyC%d\n", info->line);     /* */
 #endif
-    tty->driver_data = info;
-    info->tty = tty;
-    if (serial_paranoia_check(info, tty->name, "cy_open")){
-        return -ENODEV;
-    }
+       tty->driver_data = info;
+       info->tty = tty;
+       if (serial_paranoia_check(info, tty->name, "cy_open")) {
+               return -ENODEV;
+       }
 #ifdef CY_DEBUG_OPEN
-    printk("cyc:cy_open ttyC%d, count = %d\n",
-        info->line, info->count);/**/
+       printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count);
+       /**/
 #endif
-    info->count++;
+       info->count++;
 #ifdef CY_DEBUG_COUNT
-    printk("cyc:cy_open (%d): incrementing count to %d\n",
-        current->pid, info->count);
+       printk("cyc:cy_open (%d): incrementing count to %d\n",
+               current->pid, info->count);
 #endif
 
-    /*
-     * If the port is the middle of closing, bail out now
-     */
-    if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-       if (info->flags & ASYNC_CLOSING)
-           interruptible_sleep_on(&info->close_wait);
-       return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
-    }
-
-    /*
-     * Start up serial port
-     */
-    retval = startup(info);
-    if (retval){
-        return retval;
-    }
-
-    retval = block_til_ready(tty, filp, info);
-    if (retval) {
-#ifdef CY_DEBUG_OPEN
-        printk("cyc:cy_open returning after block_til_ready with %d\n",
-               retval);
-#endif
-        return retval;
-    }
+       /*
+        * If the port is the middle of closing, bail out now
+        */
+       if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+               if (info->flags & ASYNC_CLOSING)
+                       interruptible_sleep_on(&info->close_wait);
+               return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+       }
 
-    info->throttle = 0;
+       /*
+        * Start up serial port
+        */
+       retval = startup(info);
+       if (retval) {
+               return retval;
+       }
 
+       retval = block_til_ready(tty, filp, info);
+       if (retval) {
 #ifdef CY_DEBUG_OPEN
-    printk(" cyc:cy_open done\n");/**/
+               printk("cyc:cy_open returning after block_til_ready with %d\n",
+                       retval);
 #endif
+               return retval;
+       }
 
-    return 0;
-} /* cy_open */
+       info->throttle = 0;
 
+#ifdef CY_DEBUG_OPEN
+       printk(" cyc:cy_open done\n");
+       /**/
+#endif
+       return 0;
+}                              /* cy_open */
 
 /*
  * cy_wait_until_sent() --- wait until the transmitter is empty
  */
-static void 
-cy_wait_until_sent(struct tty_struct *tty, int timeout)
+static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
-  unsigned long orig_jiffies;
-  int char_time;
-       
-    if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
-       return;
-
-    if (info->xmit_fifo_size == 0)
-       return; /* Just in case.... */
-
-
-    orig_jiffies = jiffies;
-    /*
-     * Set the check interval to be 1/5 of the estimated time to
-     * send a single character, and make it at least 1.  The check
-     * interval should also be less than the timeout.
-     * 
-     * Note: we have to use pretty tight timings here to satisfy
-     * the NIST-PCTS.
-     */
-    char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
-    char_time = char_time / 5;
-    if (char_time <= 0)
-       char_time = 1;
-    if (timeout < 0)
-       timeout = 0;
-    if (timeout)
-       char_time = min(char_time, timeout);
-    /*
-     * If the transmitter hasn't cleared in twice the approximate
-     * amount of time to send the entire FIFO, it probably won't
-     * ever clear.  This assumes the UART isn't doing flow
-     * control, which is currently the case.  Hence, if it ever
-     * takes longer than info->timeout, this is probably due to a
-     * UART bug of some kind.  So, we clamp the timeout parameter at
-     * 2*info->timeout.
-     */
-    if (!timeout || timeout > 2*info->timeout)
-       timeout = 2*info->timeout;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
+       unsigned long orig_jiffies;
+       int char_time;
+
+       if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
+               return;
+
+       if (info->xmit_fifo_size == 0)
+               return;         /* Just in case.... */
+
+       orig_jiffies = jiffies;
+       /*
+        * Set the check interval to be 1/5 of the estimated time to
+        * send a single character, and make it at least 1.  The check
+        * interval should also be less than the timeout.
+        *
+        * Note: we have to use pretty tight timings here to satisfy
+        * the NIST-PCTS.
+        */
+       char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+       char_time = char_time / 5;
+       if (char_time <= 0)
+               char_time = 1;
+       if (timeout < 0)
+               timeout = 0;
+       if (timeout)
+               char_time = min(char_time, timeout);
+       /*
+        * If the transmitter hasn't cleared in twice the approximate
+        * amount of time to send the entire FIFO, it probably won't
+        * ever clear.  This assumes the UART isn't doing flow
+        * control, which is currently the case.  Hence, if it ever
+        * takes longer than info->timeout, this is probably due to a
+        * UART bug of some kind.  So, we clamp the timeout parameter at
+        * 2*info->timeout.
+        */
+       if (!timeout || timeout > 2 * info->timeout)
+               timeout = 2 * info->timeout;
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-    printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
-    printk("jiff=%lu...", jiffies);
+       printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
+       printk("jiff=%lu...", jiffies);
 #endif
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-       while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) {
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+               while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) {
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-           printk("Not clean (jiff=%lu)...", jiffies);
+                       printk("Not clean (jiff=%lu)...", jiffies);
 #endif
-           if (msleep_interruptible(jiffies_to_msecs(char_time)))
-               break;
-           if (timeout && time_after(jiffies, orig_jiffies + timeout))
-               break;
+                       if (msleep_interruptible(jiffies_to_msecs(char_time)))
+                               break;
+                       if (timeout && time_after(jiffies, orig_jiffies +
+                                       timeout))
+                               break;
+               }
+       } else {
+               /* Nothing to do! */
        }
-    } else {
-       // Nothing to do!
-    }
-    /* Run one more char cycle */
-    msleep_interruptible(jiffies_to_msecs(char_time * 5));
+       /* Run one more char cycle */
+       msleep_interruptible(jiffies_to_msecs(char_time * 5));
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
-    printk("Clean (jiff=%lu)...done\n", jiffies);
+       printk("Clean (jiff=%lu)...done\n", jiffies);
 #endif
 }
 
 /*
  * This routine is called when a particular tty device is closed.
  */
-static void
-cy_close(struct tty_struct *tty, struct file *filp)
+static void cy_close(struct tty_struct *tty, struct file *filp)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_close ttyC%d\n", info->line);
+       printk("cyc:cy_close ttyC%d\n", info->line);
 #endif
 
-    if (!info || serial_paranoia_check(info, tty->name, "cy_close")){
-        return;
-    }
+       if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
+               return;
+       }
 
-    CY_LOCK(info, flags);
-    /* If the TTY is being hung up, nothing to do */
-    if (tty_hung_up_p(filp)) {
-       CY_UNLOCK(info, flags);
-        return;
-    }
-        
+       CY_LOCK(info, flags);
+       /* If the TTY is being hung up, nothing to do */
+       if (tty_hung_up_p(filp)) {
+               CY_UNLOCK(info, flags);
+               return;
+       }
 #ifdef CY_DEBUG_OPEN
-    printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
+       printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
 #endif
-    if ((tty->count == 1) && (info->count != 1)) {
-        /*
-         * Uh, oh.  tty->count is 1, which means that the tty
-         * structure will be freed.  Info->count should always
-         * be one in these conditions.  If it's greater than
-         * one, we've got real problems, since it means the
-         * serial port won't be shutdown.
-         */
-        printk("cyc:cy_close: bad serial port count; tty->count is 1, "
-           "info->count is %d\n", info->count);
-        info->count = 1;
-    }
+       if ((tty->count == 1) && (info->count != 1)) {
+               /*
+                * Uh, oh.  tty->count is 1, which means that the tty
+                * structure will be freed.  Info->count should always
+                * be one in these conditions.  If it's greater than
+                * one, we've got real problems, since it means the
+                * serial port won't be shutdown.
+                */
+               printk("cyc:cy_close: bad serial port count; tty->count is 1, "
+                       "info->count is %d\n", info->count);
+               info->count = 1;
+       }
 #ifdef CY_DEBUG_COUNT
-    printk("cyc:cy_close at (%d): decrementing count to %d\n",
-        current->pid, info->count - 1);
+       printk("cyc:cy_close at (%d): decrementing count to %d\n",
+               current->pid, info->count - 1);
 #endif
-    if (--info->count < 0) {
+       if (--info->count < 0) {
 #ifdef CY_DEBUG_COUNT
-    printk("cyc:cyc_close setting count to 0\n");
+               printk("cyc:cyc_close setting count to 0\n");
 #endif
-        info->count = 0;
-    }
-    if (info->count) {
-       CY_UNLOCK(info, flags);
-        return;
-    }
-    info->flags |= ASYNC_CLOSING;
-
-    /*
-    * Now we wait for the transmit buffer to clear; and we notify
-    * the line discipline to only process XON/XOFF characters.
-    */
-    tty->closing = 1;
-    CY_UNLOCK(info, flags);
-    if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
-       tty_wait_until_sent(tty, info->closing_wait);
-    }
-    CY_LOCK(info, flags);
-
-    if (!IS_CYC_Z(cy_card[info->card])) {
-       int channel = info->line - cy_card[info->card].first_line;
-       int index = cy_card[info->card].bus_index;
-       void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index);
-       /* Stop accepting input */
-       channel &= 0x03;
-       cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-       cy_writeb(base_addr+(CySRER<<index),
-                       cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
-       if (info->flags & ASYNC_INITIALIZED) {
-           /* Waiting for on-board buffers to be empty before closing 
-              the port */
-           CY_UNLOCK(info, flags);
-           cy_wait_until_sent(tty, info->timeout);
-           CY_LOCK(info, flags);
+               info->count = 0;
        }
-    } else {
-#ifdef Z_WAKE
-       /* Waiting for on-board buffers to be empty before closing the port */
-       void __iomem *base_addr = cy_card[info->card].base_addr;
-       struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
-       struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
-       int channel = info->line - cy_card[info->card].first_line;
-       int retval;
+       if (info->count) {
+               CY_UNLOCK(info, flags);
+               return;
+       }
+       info->flags |= ASYNC_CLOSING;
 
-       if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
-           retval = cyz_issue_cmd(&cy_card[info->card], channel, 
-                                  C_CM_IOCTLW, 0L);
-           if (retval != 0){
-               printk("cyc:cy_close retval on ttyC%d was %x\n",
-                      info->line, retval);
-           }
-           CY_UNLOCK(info, flags);
-           interruptible_sleep_on(&info->shutdown_wait);
-           CY_LOCK(info, flags);
+       /*
+        * Now we wait for the transmit buffer to clear; and we notify
+        * the line discipline to only process XON/XOFF characters.
+        */
+       tty->closing = 1;
+       CY_UNLOCK(info, flags);
+       if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
+               tty_wait_until_sent(tty, info->closing_wait);
        }
+       CY_LOCK(info, flags);
+
+       if (!IS_CYC_Z(cy_card[info->card])) {
+               int channel = info->line - cy_card[info->card].first_line;
+               int index = cy_card[info->card].bus_index;
+               void __iomem *base_addr = cy_card[info->card].base_addr +
+                       (cy_chip_offset[channel >> 2] << index);
+               /* Stop accepting input */
+               channel &= 0x03;
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               cy_writeb(base_addr + (CySRER << index),
+                         cy_readb(base_addr + (CySRER << index)) & ~CyRxData);
+               if (info->flags & ASYNC_INITIALIZED) {
+                       /* Waiting for on-board buffers to be empty before closing
+                          the port */
+                       CY_UNLOCK(info, flags);
+                       cy_wait_until_sent(tty, info->timeout);
+                       CY_LOCK(info, flags);
+               }
+       } else {
+#ifdef Z_WAKE
+               /* Waiting for on-board buffers to be empty before closing the port */
+               void __iomem *base_addr = cy_card[info->card].base_addr;
+               struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
+               struct ZFW_CTRL __iomem *zfw_ctrl =
+                   base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
+               int channel = info->line - cy_card[info->card].first_line;
+               int retval;
+
+               if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
+                       retval = cyz_issue_cmd(&cy_card[info->card], channel,
+                                               C_CM_IOCTLW, 0L);
+                       if (retval != 0) {
+                               printk("cyc:cy_close retval on ttyC%d was %x\n",
+                                       info->line, retval);
+                       }
+                       CY_UNLOCK(info, flags);
+                       interruptible_sleep_on(&info->shutdown_wait);
+                       CY_LOCK(info, flags);
+               }
 #endif
-    }
-
-    CY_UNLOCK(info, flags);
-    shutdown(info);
-    if (tty->driver->flush_buffer)
-        tty->driver->flush_buffer(tty);
-    tty_ldisc_flush(tty);        
-    CY_LOCK(info, flags);
-
-    tty->closing = 0;
-    info->event = 0;
-    info->tty = NULL;
-    if (info->blocked_open) {
+       }
+
        CY_UNLOCK(info, flags);
-        if (info->close_delay) {
-            msleep_interruptible(jiffies_to_msecs(info->close_delay));
-        }
-        wake_up_interruptible(&info->open_wait);
+       shutdown(info);
+       if (tty->driver->flush_buffer)
+               tty->driver->flush_buffer(tty);
+       tty_ldisc_flush(tty);
        CY_LOCK(info, flags);
-    }
-    info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-    wake_up_interruptible(&info->close_wait);
+
+       tty->closing = 0;
+       info->event = 0;
+       info->tty = NULL;
+       if (info->blocked_open) {
+               CY_UNLOCK(info, flags);
+               if (info->close_delay) {
+                       msleep_interruptible(jiffies_to_msecs
+                                               (info->close_delay));
+               }
+               wake_up_interruptible(&info->open_wait);
+               CY_LOCK(info, flags);
+       }
+       info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+       wake_up_interruptible(&info->close_wait);
 
 #ifdef CY_DEBUG_OTHER
-    printk(" cyc:cy_close done\n");
+       printk(" cyc:cy_close done\n");
 #endif
 
-    CY_UNLOCK(info, flags);
-    return;
-} /* cy_close */
-
+       CY_UNLOCK(info, flags);
+}                              /* cy_close */
 
 /* This routine gets called when tty_write has put something into
  * the write_queue.  The characters may come from user space or
@@ -2795,50 +2875,49 @@ cy_close(struct tty_struct *tty, struct file *filp)
  * If the port is already active, there is no need to kick it.
  *
  */
-static int
-cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
+static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  int c, ret = 0;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
+       int c, ret = 0;
 
 #ifdef CY_DEBUG_IO
-    printk("cyc:cy_write ttyC%d\n", info->line); /* */
+       printk("cyc:cy_write ttyC%d\n", info->line);    /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_write")){
-        return 0;
-    }
-        
-    if (!info->xmit_buf)
-       return 0;
+       if (serial_paranoia_check(info, tty->name, "cy_write")) {
+               return 0;
+       }
+
+       if (!info->xmit_buf)
+               return 0;
+
+       CY_LOCK(info, flags);
+       while (1) {
+               c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+                                  (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
+
+               if (c <= 0)
+                       break;
+
+               memcpy(info->xmit_buf + info->xmit_head, buf, c);
+               info->xmit_head = (info->xmit_head + c) &
+                       (SERIAL_XMIT_SIZE - 1);
+               info->xmit_cnt += c;
+               buf += c;
+               count -= c;
+               ret += c;
+       }
+       CY_UNLOCK(info, flags);
 
-    CY_LOCK(info, flags);
-    while (1) {
-       c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
-                       (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
-               
-       if (c <= 0)
-           break;
-
-       memcpy(info->xmit_buf + info->xmit_head, buf, c);
-       info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-       info->xmit_cnt += c;
-       buf += c;
-       count -= c;
-       ret += c;
-    }
-    CY_UNLOCK(info, flags);
-
-    info->idle_stats.xmit_bytes += ret;
-    info->idle_stats.xmit_idle   = jiffies;
-
-    if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-        start_xmit(info);
-    }
-    return ret;
-} /* cy_write */
+       info->idle_stats.xmit_bytes += ret;
+       info->idle_stats.xmit_idle = jiffies;
 
+       if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+               start_xmit(info);
+       }
+       return ret;
+}                              /* cy_write */
 
 /*
  * This routine is called by the kernel to write a single
@@ -2847,60 +2926,56 @@ cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
  * done stuffing characters into the driver.  If there is no room
  * in the queue, the character is ignored.
  */
-static void
-cy_put_char(struct tty_struct *tty, unsigned char ch)
+static void cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
 
 #ifdef CY_DEBUG_IO
-    printk("cyc:cy_put_char ttyC%d\n", info->line);
+       printk("cyc:cy_put_char ttyC%d\n", info->line);
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-        return;
+       if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+               return;
 
-    if (!info->xmit_buf)
-        return;
+       if (!info->xmit_buf)
+               return;
 
-    CY_LOCK(info, flags);
-        if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-           CY_UNLOCK(info, flags);
-            return;
-        }
+       CY_LOCK(info, flags);
+       if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
+               CY_UNLOCK(info, flags);
+               return;
+       }
 
-        info->xmit_buf[info->xmit_head++] = ch;
-        info->xmit_head &= SERIAL_XMIT_SIZE - 1;
-        info->xmit_cnt++;
+       info->xmit_buf[info->xmit_head++] = ch;
+       info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+       info->xmit_cnt++;
        info->idle_stats.xmit_bytes++;
        info->idle_stats.xmit_idle = jiffies;
-    CY_UNLOCK(info, flags);
-} /* cy_put_char */
-
+       CY_UNLOCK(info, flags);
+}                              /* cy_put_char */
 
 /*
  * This routine is called by the kernel after it has written a
  * series of characters to the tty device using put_char().  
  */
-static void
-cy_flush_chars(struct tty_struct *tty)
+static void cy_flush_chars(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-                                
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
 #ifdef CY_DEBUG_IO
-    printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */
+       printk("cyc:cy_flush_chars ttyC%d\n", info->line);      /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-        return;
-
-    if (info->xmit_cnt <= 0 || tty->stopped
-    || tty->hw_stopped || !info->xmit_buf)
-        return;
+       if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
+               return;
 
-    start_xmit(info);
-} /* cy_flush_chars */
+       if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+                       !info->xmit_buf)
+               return;
 
+       start_xmit(info);
+}                              /* cy_flush_chars */
 
 /*
  * This routine returns the numbers of characters the tty driver
@@ -2908,75 +2983,70 @@ cy_flush_chars(struct tty_struct *tty)
  * to change as output buffers get emptied, or if the output flow
  * control is activated.
  */
-static int
-cy_write_room(struct tty_struct *tty)
+static int cy_write_room(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int   ret;
-                                
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       int ret;
+
 #ifdef CY_DEBUG_IO
-    printk("cyc:cy_write_room ttyC%d\n", info->line); /* */
+       printk("cyc:cy_write_room ttyC%d\n", info->line);       /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-        return 0;
-    ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-    if (ret < 0)
-        ret = 0;
-    return ret;
-} /* cy_write_room */
+       if (serial_paranoia_check(info, tty->name, "cy_write_room"))
+               return 0;
+       ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+       if (ret < 0)
+               ret = 0;
+       return ret;
+}                              /* cy_write_room */
 
-
-static int
-cy_chars_in_buffer(struct tty_struct *tty)
+static int cy_chars_in_buffer(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int card, channel;
-                                
-    if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-        return 0;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       int card, channel;
 
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
+       if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
+               return 0;
+
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
 
 #ifdef Z_EXT_CHARS_IN_BUFFER
-    if (!IS_CYC_Z(cy_card[card])) {
-#endif /* Z_EXT_CHARS_IN_BUFFER */
+       if (!IS_CYC_Z(cy_card[card])) {
+#endif                         /* Z_EXT_CHARS_IN_BUFFER */
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
-               info->line, info->xmit_cnt); /* */
+               printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt);       /* */
 #endif
-       return info->xmit_cnt;
+               return info->xmit_cnt;
 #ifdef Z_EXT_CHARS_IN_BUFFER
-    } else {
-       static volatile struct FIRM_ID *firm_id;
-       static volatile struct ZFW_CTRL *zfw_ctrl;
-       static volatile struct CH_CTRL *ch_ctrl;
-       static volatile struct BUF_CTRL *buf_ctrl;
-       int char_count;
-       volatile uclong tx_put, tx_get, tx_bufsize;
-
-       firm_id = cy_card[card].base_addr + ID_ADDRESS;
-       zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-       buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
-       tx_get = cy_readl(&buf_ctrl->tx_get);
-       tx_put = cy_readl(&buf_ctrl->tx_put);
-       tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
-       if (tx_put >= tx_get)
-           char_count = tx_put - tx_get;
-       else
-           char_count = tx_put - tx_get + tx_bufsize;
+       } else {
+               static volatile struct FIRM_ID *firm_id;
+               static volatile struct ZFW_CTRL *zfw_ctrl;
+               static volatile struct CH_CTRL *ch_ctrl;
+               static volatile struct BUF_CTRL *buf_ctrl;
+               int char_count;
+               volatile uclong tx_put, tx_get, tx_bufsize;
+
+               firm_id = cy_card[card].base_addr + ID_ADDRESS;
+               zfw_ctrl = cy_card[card].base_addr +
+                       (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+               buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+               tx_get = cy_readl(&buf_ctrl->tx_get);
+               tx_put = cy_readl(&buf_ctrl->tx_put);
+               tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+               if (tx_put >= tx_get)
+                       char_count = tx_put - tx_get;
+               else
+                       char_count = tx_put - tx_get + tx_bufsize;
 #ifdef CY_DEBUG_IO
-       printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
-               info->line, info->xmit_cnt + char_count); /* */
+               printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count);  /* */
 #endif
-       return (info->xmit_cnt + char_count);
-    }
-#endif /* Z_EXT_CHARS_IN_BUFFER */
-} /* cy_chars_in_buffer */
-
+               return info->xmit_cnt + char_count;
+       }
+#endif                         /* Z_EXT_CHARS_IN_BUFFER */
+}                              /* cy_chars_in_buffer */
 
 /*
  * ------------------------------------------------------------
@@ -2984,178 +3054,179 @@ cy_chars_in_buffer(struct tty_struct *tty)
  * ------------------------------------------------------------
  */
 
-static void
-cyy_baud_calc(struct cyclades_port *info, uclong baud)
+static void cyy_baud_calc(struct cyclades_port *info, uclong baud)
 {
-    int co, co_val, bpr;
-    uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000);
-
-    if (baud == 0) {
-       info->tbpr = info->tco = info->rbpr = info->rco = 0;
-       return;
-    }
-
-    /* determine which prescaler to use */
-    for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
-       if (cy_clock / co_val / baud > 63)
-           break;
-    }
-
-    bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
-    if (bpr > 255)
-       bpr = 255;
-
-    info->tbpr = info->rbpr = bpr;
-    info->tco = info->rco = co;
+       int co, co_val, bpr;
+       uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
+                       25000000);
+
+       if (baud == 0) {
+               info->tbpr = info->tco = info->rbpr = info->rco = 0;
+               return;
+       }
+
+       /* determine which prescaler to use */
+       for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
+               if (cy_clock / co_val / baud > 63)
+                       break;
+       }
+
+       bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
+       if (bpr > 255)
+               bpr = 255;
+
+       info->tbpr = info->rbpr = bpr;
+       info->tco = info->rco = co;
 }
 
 /*
  * This routine finds or computes the various line characteristics.
  * It used to be called config_setup
  */
-static void
-set_line_char(struct cyclades_port * info)
+static void set_line_char(struct cyclades_port *info)
 {
-  unsigned long flags;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
-  unsigned cflag, iflag;
-  unsigned short chip_number;
-  int baud, baud_rate = 0;
-  int   i;
-
-
-    if (!info->tty || !info->tty->termios){
-        return;
-    }
-    if (info->line == -1){
-        return;
-    }
-    cflag = info->tty->termios->c_cflag;
-    iflag = info->tty->termios->c_iflag;
-
-    /*
-     * Set up the tty->alt_speed kludge
-     */
-    if (info->tty) {
-       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-           info->tty->alt_speed = 57600;
-       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-           info->tty->alt_speed = 115200;
-       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-           info->tty->alt_speed = 230400;
-       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-           info->tty->alt_speed = 460800;
-    }
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    chip_number = channel / 4;
-
-    if (!IS_CYC_Z(cy_card[card])) {
-
-       index = cy_card[card].bus_index;
-
-       /* baud rate */
-       baud = tty_get_baud_rate(info->tty);
-       if ((baud == 38400) &&
-           ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
-           if (info->custom_divisor)
-               baud_rate = info->baud / info->custom_divisor;
-           else
-               baud_rate = info->baud;
-       } else if (baud > CD1400_MAX_SPEED) {
-           baud = CD1400_MAX_SPEED;
+       unsigned long flags;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
+       unsigned cflag, iflag;
+       unsigned short chip_number;
+       int baud, baud_rate = 0;
+       int i;
+
+       if (!info->tty || !info->tty->termios) {
+               return;
        }
-       /* find the baud index */
-       for (i = 0; i < 20; i++) {
-           if (baud == baud_table[i]) {
-               break;
-           }
+       if (info->line == -1) {
+               return;
        }
-       if (i == 20) {
-           i = 19; /* CD1400_MAX_SPEED */
-       } 
+       cflag = info->tty->termios->c_cflag;
+       iflag = info->tty->termios->c_iflag;
 
-       if ((baud == 38400) &&
-           ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
-           cyy_baud_calc(info, baud_rate);
-       } else {
-           if(info->chip_rev >= CD1400_REV_J) {
-               /* It is a CD1400 rev. J or later */
-               info->tbpr = baud_bpr_60[i]; /* Tx BPR */
-               info->tco = baud_co_60[i]; /* Tx CO */
-               info->rbpr = baud_bpr_60[i]; /* Rx BPR */
-               info->rco = baud_co_60[i]; /* Rx CO */
-           } else {
-               info->tbpr = baud_bpr_25[i]; /* Tx BPR */
-               info->tco = baud_co_25[i]; /* Tx CO */
-               info->rbpr = baud_bpr_25[i]; /* Rx BPR */
-               info->rco = baud_co_25[i]; /* Rx CO */
-           }
-       }
-       if (baud_table[i] == 134) {
-           /* get it right for 134.5 baud */
-           info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
-       } else if ((baud == 38400) &&
-                  ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
-           info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
-       } else if (baud_table[i]) {
-           info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
-           /* this needs to be propagated into the card info */
-       } else {
-           info->timeout = 0;
-       }
-       /* By tradition (is it a standard?) a baud rate of zero
-          implies the line should be/has been closed.  A bit
-          later in this routine such a test is performed. */
-
-       /* byte size and parity */
-       info->cor5 = 0;
-       info->cor4 = 0;
-       info->cor3 = (info->default_threshold
-                     ? info->default_threshold
-                     : baud_cor3[i]); /* receive threshold */
-       info->cor2 = CyETC;
-       switch(cflag & CSIZE){
-       case CS5:
-           info->cor1 = Cy_5_BITS;
-           break;
-       case CS6:
-           info->cor1 = Cy_6_BITS;
-           break;
-       case CS7:
-           info->cor1 = Cy_7_BITS;
-           break;
-       case CS8:
-           info->cor1 = Cy_8_BITS;
-           break;
-       }
-       if(cflag & CSTOPB){
-           info->cor1 |= Cy_2_STOP;
-       }
-       if (cflag & PARENB){
-           if (cflag & PARODD){
-               info->cor1 |= CyPARITY_O;
-           }else{
-               info->cor1 |= CyPARITY_E;
-           }
-       }else{
-           info->cor1 |= CyPARITY_NONE;
-       }
-           
-       /* CTS flow control flag */
-       if (cflag & CRTSCTS){
-           info->flags |= ASYNC_CTS_FLOW;
-           info->cor2 |= CyCtsAE;
-       }else{
-           info->flags &= ~ASYNC_CTS_FLOW;
-           info->cor2 &= ~CyCtsAE;
+       /*
+        * Set up the tty->alt_speed kludge
+        */
+       if (info->tty) {
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+                       info->tty->alt_speed = 57600;
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+                       info->tty->alt_speed = 115200;
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+                       info->tty->alt_speed = 230400;
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+                       info->tty->alt_speed = 460800;
        }
-       if (cflag & CLOCAL)
-           info->flags &= ~ASYNC_CHECK_CD;
-       else
-           info->flags |= ASYNC_CHECK_CD;
+
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       chip_number = channel / 4;
+
+       if (!IS_CYC_Z(cy_card[card])) {
+
+               index = cy_card[card].bus_index;
+
+               /* baud rate */
+               baud = tty_get_baud_rate(info->tty);
+               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+                               ASYNC_SPD_CUST) {
+                       if (info->custom_divisor)
+                               baud_rate = info->baud / info->custom_divisor;
+                       else
+                               baud_rate = info->baud;
+               } else if (baud > CD1400_MAX_SPEED) {
+                       baud = CD1400_MAX_SPEED;
+               }
+               /* find the baud index */
+               for (i = 0; i < 20; i++) {
+                       if (baud == baud_table[i]) {
+                               break;
+                       }
+               }
+               if (i == 20) {
+                       i = 19; /* CD1400_MAX_SPEED */
+               }
+
+               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+                               ASYNC_SPD_CUST) {
+                       cyy_baud_calc(info, baud_rate);
+               } else {
+                       if (info->chip_rev >= CD1400_REV_J) {
+                               /* It is a CD1400 rev. J or later */
+                               info->tbpr = baud_bpr_60[i];    /* Tx BPR */
+                               info->tco = baud_co_60[i];      /* Tx CO */
+                               info->rbpr = baud_bpr_60[i];    /* Rx BPR */
+                               info->rco = baud_co_60[i];      /* Rx CO */
+                       } else {
+                               info->tbpr = baud_bpr_25[i];    /* Tx BPR */
+                               info->tco = baud_co_25[i];      /* Tx CO */
+                               info->rbpr = baud_bpr_25[i];    /* Rx BPR */
+                               info->rco = baud_co_25[i];      /* Rx CO */
+                       }
+               }
+               if (baud_table[i] == 134) {
+                       /* get it right for 134.5 baud */
+                       info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+                                       2;
+               } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+                               ASYNC_SPD_CUST) {
+                       info->timeout = (info->xmit_fifo_size * HZ * 15 /
+                                       baud_rate) + 2;
+               } else if (baud_table[i]) {
+                       info->timeout = (info->xmit_fifo_size * HZ * 15 /
+                                       baud_table[i]) + 2;
+                       /* this needs to be propagated into the card info */
+               } else {
+                       info->timeout = 0;
+               }
+               /* By tradition (is it a standard?) a baud rate of zero
+                  implies the line should be/has been closed.  A bit
+                  later in this routine such a test is performed. */
+
+               /* byte size and parity */
+               info->cor5 = 0;
+               info->cor4 = 0;
+               /* receive threshold */
+               info->cor3 = (info->default_threshold ?
+                               info->default_threshold : baud_cor3[i]);
+               info->cor2 = CyETC;
+               switch (cflag & CSIZE) {
+               case CS5:
+                       info->cor1 = Cy_5_BITS;
+                       break;
+               case CS6:
+                       info->cor1 = Cy_6_BITS;
+                       break;
+               case CS7:
+                       info->cor1 = Cy_7_BITS;
+                       break;
+               case CS8:
+                       info->cor1 = Cy_8_BITS;
+                       break;
+               }
+               if (cflag & CSTOPB) {
+                       info->cor1 |= Cy_2_STOP;
+               }
+               if (cflag & PARENB) {
+                       if (cflag & PARODD) {
+                               info->cor1 |= CyPARITY_O;
+                       } else {
+                               info->cor1 |= CyPARITY_E;
+                       }
+               } else {
+                       info->cor1 |= CyPARITY_NONE;
+               }
+
+               /* CTS flow control flag */
+               if (cflag & CRTSCTS) {
+                       info->flags |= ASYNC_CTS_FLOW;
+                       info->cor2 |= CyCtsAE;
+               } else {
+                       info->flags &= ~ASYNC_CTS_FLOW;
+                       info->cor2 &= ~CyCtsAE;
+               }
+               if (cflag & CLOCAL)
+                       info->flags &= ~ASYNC_CHECK_CD;
+               else
+                       info->flags |= ASYNC_CHECK_CD;
 
         /***********************************************
            The hardware option, CyRtsAO, presents RTS when
@@ -3167,300 +3238,319 @@ set_line_char(struct cyclades_port * info)
            cable.  Contact Marcio Saito for details.
         ***********************************************/
 
-       chip = channel>>2;
-       channel &= 0x03;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+               chip = channel >> 2;
+               channel &= 0x03;
+               base_addr = cy_card[card].base_addr +
+                       (cy_chip_offset[chip] << index);
 
-       CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-
-          /* tx and rx baud rate */
-
-           cy_writeb(base_addr+(CyTCOR<<index), info->tco);
-           cy_writeb(base_addr+(CyTBPR<<index), info->tbpr);
-           cy_writeb(base_addr+(CyRCOR<<index), info->rco);
-           cy_writeb(base_addr+(CyRBPR<<index), info->rbpr);
-
-           /* set line characteristics  according configuration */
-
-           cy_writeb(base_addr+(CySCHR1<<index), 
-                     START_CHAR(info->tty));
-           cy_writeb(base_addr+(CySCHR2<<index), 
-                     STOP_CHAR(info->tty));
-           cy_writeb(base_addr+(CyCOR1<<index), info->cor1);
-           cy_writeb(base_addr+(CyCOR2<<index), info->cor2);
-           cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
-           cy_writeb(base_addr+(CyCOR4<<index), info->cor4);
-           cy_writeb(base_addr+(CyCOR5<<index), info->cor5);
-
-           cyy_issue_cmd(base_addr,
-                    CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
-
-           cy_writeb(base_addr+(CyCAR<<index), 
-                     (u_char)channel); /* !!! Is this needed? */
-           cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
-                                                ? info->default_timeout
-                                                : 0x02)); /* 10ms rx timeout */
-
-           if (C_CLOCAL(info->tty)) {
-               /* without modem intr */
-               cy_writeb(base_addr+(CySRER<<index),
-                   cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
-                                       /* act on 1->0 modem transitions */
-                if ((cflag & CRTSCTS) && info->rflow) {
-                        cy_writeb(base_addr+(CyMCOR1<<index), 
-                                  (CyCTS|rflow_thr[i]));
-                } else {
-                        cy_writeb(base_addr+(CyMCOR1<<index), CyCTS);
-                }
-                                       /* act on 0->1 modem transitions */
-               cy_writeb(base_addr+(CyMCOR2<<index), CyCTS);
-           } else {
-               /* without modem intr */
-               cy_writeb(base_addr+(CySRER<<index),
-                   cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
-                                       /* act on 1->0 modem transitions */
-                if ((cflag & CRTSCTS) && info->rflow) {
-                       cy_writeb(base_addr+(CyMCOR1<<index), 
-                                 (CyDSR|CyCTS|CyRI|CyDCD|rflow_thr[i]));
-                } else {
-                       cy_writeb(base_addr+(CyMCOR1<<index), 
-                                  CyDSR|CyCTS|CyRI|CyDCD);
-                }
-                                       /* act on 0->1 modem transitions */
-               cy_writeb(base_addr+(CyMCOR2<<index), 
-                         CyDSR|CyCTS|CyRI|CyDCD);
-           }
-
-           if(i == 0){ /* baud rate is zero, turn off line */
-               if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+
+               /* tx and rx baud rate */
+
+               cy_writeb(base_addr + (CyTCOR << index), info->tco);
+               cy_writeb(base_addr + (CyTBPR << index), info->tbpr);
+               cy_writeb(base_addr + (CyRCOR << index), info->rco);
+               cy_writeb(base_addr + (CyRBPR << index), info->rbpr);
+
+               /* set line characteristics  according configuration */
+
+               cy_writeb(base_addr + (CySCHR1 << index),
+                         START_CHAR(info->tty));
+               cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->tty));
+               cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
+               cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
+               cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
+               cy_writeb(base_addr + (CyCOR4 << index), info->cor4);
+               cy_writeb(base_addr + (CyCOR5 << index), info->cor5);
+
+               cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
+                               CyCOR3ch, index);
+
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);      /* !!! Is this needed? */
+               cy_writeb(base_addr + (CyRTPR << index),
+                       (info->default_timeout ? info->default_timeout : 0x02));
+               /* 10ms rx timeout */
+
+               if (C_CLOCAL(info->tty)) {
+                       /* without modem intr */
+                       cy_writeb(base_addr + (CySRER << index),
+                                 cy_readb(base_addr +
+                                          (CySRER << index)) | CyMdmCh);
+                       /* act on 1->0 modem transitions */
+                       if ((cflag & CRTSCTS) && info->rflow) {
+                               cy_writeb(base_addr + (CyMCOR1 << index),
+                                         (CyCTS | rflow_thr[i]));
+                       } else {
+                               cy_writeb(base_addr + (CyMCOR1 << index),
+                                         CyCTS);
+                       }
+                       /* act on 0->1 modem transitions */
+                       cy_writeb(base_addr + (CyMCOR2 << index), CyCTS);
                } else {
-                        cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
+                       /* without modem intr */
+                       cy_writeb(base_addr + (CySRER << index),
+                                 cy_readb(base_addr +
+                                          (CySRER << index)) | CyMdmCh);
+                       /* act on 1->0 modem transitions */
+                       if ((cflag & CRTSCTS) && info->rflow) {
+                               cy_writeb(base_addr + (CyMCOR1 << index),
+                                         (CyDSR | CyCTS | CyRI | CyDCD |
+                                          rflow_thr[i]));
+                       } else {
+                               cy_writeb(base_addr + (CyMCOR1 << index),
+                                         CyDSR | CyCTS | CyRI | CyDCD);
+                       }
+                       /* act on 0->1 modem transitions */
+                       cy_writeb(base_addr + (CyMCOR2 << index),
+                                 CyDSR | CyCTS | CyRI | CyDCD);
                }
+
+               if (i == 0) {   /* baud rate is zero, turn off line */
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         ~CyRTS);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         ~CyDTR);
+                       }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:set_line_char dropping DTR\n");
-               printk("     status: 0x%x, 0x%x\n", 
-                   cy_readb(base_addr+(CyMSVR1<<index)),
-                   cy_readb(base_addr+(CyMSVR2<<index)));
+                       printk("cyc:set_line_char dropping DTR\n");
+                       printk("     status: 0x%x, 0x%x\n",
+                               cy_readb(base_addr + (CyMSVR1 << index)),
+                               cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
-           }else{
-                if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-                } else {
-                       cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
-                }
+               } else {
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         CyRTS);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         CyDTR);
+                       }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:set_line_char raising DTR\n");
-               printk("     status: 0x%x, 0x%x\n",
-                   cy_readb(base_addr+(CyMSVR1<<index)),
-                   cy_readb(base_addr+(CyMSVR2<<index)));
+                       printk("cyc:set_line_char raising DTR\n");
+                       printk("     status: 0x%x, 0x%x\n",
+                               cy_readb(base_addr + (CyMSVR1 << index)),
+                               cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
-           }
-
-           if (info->tty){
-               clear_bit(TTY_IO_ERROR, &info->tty->flags);
-           }
-       CY_UNLOCK(info, flags);
+               }
 
-    } else {
-      struct FIRM_ID __iomem *firm_id;
-      struct ZFW_CTRL __iomem *zfw_ctrl;
-      struct BOARD_CTRL __iomem *board_ctrl;
-      struct CH_CTRL __iomem *ch_ctrl;
-      struct BUF_CTRL __iomem *buf_ctrl;
-      uclong sw_flow;
-      int retval;
-
-        firm_id = cy_card[card].base_addr + ID_ADDRESS;
-        if (!ISZLOADED(cy_card[card])) {
-           return;
-       }
+               if (info->tty) {
+                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
+               CY_UNLOCK(info, flags);
 
-       zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-       board_ctrl = &zfw_ctrl->board_ctrl;
-       ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-       buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
-
-       /* baud rate */
-       baud = tty_get_baud_rate(info->tty);
-       if ((baud == 38400) &&
-           ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
-           if (info->custom_divisor)
-               baud_rate = info->baud / info->custom_divisor;
-           else
-               baud_rate = info->baud;
-       } else if (baud > CYZ_MAX_SPEED) {
-           baud = CYZ_MAX_SPEED;
-       }
-       cy_writel(&ch_ctrl->comm_baud , baud);
-
-       if (baud == 134) {
-           /* get it right for 134.5 baud */
-           info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
-       } else if ((baud == 38400) &&
-                  ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
-           info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
-       } else if (baud) {
-           info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2;
-           /* this needs to be propagated into the card info */
        } else {
-           info->timeout = 0;
-       }
+               struct FIRM_ID __iomem *firm_id;
+               struct ZFW_CTRL __iomem *zfw_ctrl;
+               struct BOARD_CTRL __iomem *board_ctrl;
+               struct CH_CTRL __iomem *ch_ctrl;
+               struct BUF_CTRL __iomem *buf_ctrl;
+               uclong sw_flow;
+               int retval;
+
+               firm_id = cy_card[card].base_addr + ID_ADDRESS;
+               if (!ISZLOADED(cy_card[card])) {
+                       return;
+               }
 
-       /* byte size and parity */
-       switch(cflag & CSIZE){
-       case CS5: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS5); break;
-       case CS6: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS6); break;
-       case CS7: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS7); break;
-       case CS8: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS8); break;
-       }
-       if(cflag & CSTOPB){
-           cy_writel(&ch_ctrl->comm_data_l,
-               cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
-       }else{
-           cy_writel(&ch_ctrl->comm_data_l,
-               cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
-       }
-       if (cflag & PARENB){
-           if (cflag & PARODD){
-               cy_writel(&ch_ctrl->comm_parity , C_PR_ODD);
-           }else{
-               cy_writel(&ch_ctrl->comm_parity , C_PR_EVEN);
-           }
-       }else{
-           cy_writel(&ch_ctrl->comm_parity , C_PR_NONE);
-       }
+               zfw_ctrl = cy_card[card].base_addr +
+                       (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+               board_ctrl = &zfw_ctrl->board_ctrl;
+               ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+               buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
+
+               /* baud rate */
+               baud = tty_get_baud_rate(info->tty);
+               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+                               ASYNC_SPD_CUST) {
+                       if (info->custom_divisor)
+                               baud_rate = info->baud / info->custom_divisor;
+                       else
+                               baud_rate = info->baud;
+               } else if (baud > CYZ_MAX_SPEED) {
+                       baud = CYZ_MAX_SPEED;
+               }
+               cy_writel(&ch_ctrl->comm_baud, baud);
+
+               if (baud == 134) {
+                       /* get it right for 134.5 baud */
+                       info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+                                       2;
+               } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+                               ASYNC_SPD_CUST) {
+                       info->timeout = (info->xmit_fifo_size * HZ * 15 /
+                                       baud_rate) + 2;
+               } else if (baud) {
+                       info->timeout = (info->xmit_fifo_size * HZ * 15 /
+                                       baud) + 2;
+                       /* this needs to be propagated into the card info */
+               } else {
+                       info->timeout = 0;
+               }
 
-       /* CTS flow control flag */
-       if (cflag & CRTSCTS){
-           cy_writel(&ch_ctrl->hw_flow,
-               cy_readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
-       }else{
-           cy_writel(&ch_ctrl->hw_flow,
-               cy_readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS));
-       }
-       /* As the HW flow control is done in firmware, the driver doesn't
-          need to care about it */
-       info->flags &= ~ASYNC_CTS_FLOW;
-
-       /* XON/XOFF/XANY flow control flags */
-       sw_flow = 0;
-       if (iflag & IXON){
-           sw_flow |= C_FL_OXX;
-           if (iflag & IXANY)
-               sw_flow |= C_FL_OIXANY;
-       }
-       cy_writel(&ch_ctrl->sw_flow, sw_flow);
+               /* byte size and parity */
+               switch (cflag & CSIZE) {
+               case CS5:
+                       cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
+                       break;
+               case CS6:
+                       cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
+                       break;
+               case CS7:
+                       cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
+                       break;
+               case CS8:
+                       cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
+                       break;
+               }
+               if (cflag & CSTOPB) {
+                       cy_writel(&ch_ctrl->comm_data_l,
+                                 cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
+               } else {
+                       cy_writel(&ch_ctrl->comm_data_l,
+                                 cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
+               }
+               if (cflag & PARENB) {
+                       if (cflag & PARODD) {
+                               cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
+                       } else {
+                               cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
+                       }
+               } else {
+                       cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
+               }
 
-       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
-       if (retval != 0){
-           printk("cyc:set_line_char retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+               /* CTS flow control flag */
+               if (cflag & CRTSCTS) {
+                       cy_writel(&ch_ctrl->hw_flow,
+                                 cy_readl(&ch_ctrl->
+                                          hw_flow) | C_RS_CTS | C_RS_RTS);
+               } else {
+                       cy_writel(&ch_ctrl->hw_flow,
+                                 cy_readl(&ch_ctrl->
+                                          hw_flow) & ~(C_RS_CTS | C_RS_RTS));
+               }
+               /* As the HW flow control is done in firmware, the driver
+                  doesn't need to care about it */
+               info->flags &= ~ASYNC_CTS_FLOW;
+
+               /* XON/XOFF/XANY flow control flags */
+               sw_flow = 0;
+               if (iflag & IXON) {
+                       sw_flow |= C_FL_OXX;
+                       if (iflag & IXANY)
+                               sw_flow |= C_FL_OIXANY;
+               }
+               cy_writel(&ch_ctrl->sw_flow, sw_flow);
 
-       /* CD sensitivity */
-       if (cflag & CLOCAL){
-           info->flags &= ~ASYNC_CHECK_CD;
-       }else{
-           info->flags |= ASYNC_CHECK_CD;
-       }
+               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+               if (retval != 0) {
+                       printk("cyc:set_line_char retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
+
+               /* CD sensitivity */
+               if (cflag & CLOCAL) {
+                       info->flags &= ~ASYNC_CHECK_CD;
+               } else {
+                       info->flags |= ASYNC_CHECK_CD;
+               }
 
-       if(baud == 0){ /* baud rate is zero, turn off line */
-           cy_writel(&ch_ctrl->rs_control,
-               cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
+               if (baud == 0) {        /* baud rate is zero, turn off line */
+                       cy_writel(&ch_ctrl->rs_control,
+                                 cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-           printk("cyc:set_line_char dropping Z DTR\n");
+                       printk("cyc:set_line_char dropping Z DTR\n");
 #endif
-       }else{
-           cy_writel(&ch_ctrl->rs_control,
-               cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
+               } else {
+                       cy_writel(&ch_ctrl->rs_control,
+                                 cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-           printk("cyc:set_line_char raising Z DTR\n");
+                       printk("cyc:set_line_char raising Z DTR\n");
 #endif
-       }
+               }
 
-       retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L);
-       if (retval != 0){
-           printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+               retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L);
+               if (retval != 0) {
+                       printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
 
-       if (info->tty){
-           clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               if (info->tty) {
+                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               }
        }
-    }
-} /* set_line_char */
-
+}                              /* set_line_char */
 
 static int
-get_serial_info(struct cyclades_port * info,
-                           struct serial_struct __user * retinfo)
+get_serial_info(struct cyclades_port *info,
+               struct serial_struct __user * retinfo)
 {
-  struct serial_struct tmp;
-  struct cyclades_card *cinfo = &cy_card[info->card];
-
-    if (!retinfo)
-            return -EFAULT;
-    memset(&tmp, 0, sizeof(tmp));
-    tmp.type = info->type;
-    tmp.line = info->line;
-    tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
-    tmp.irq = cinfo->irq;
-    tmp.flags = info->flags;
-    tmp.close_delay = info->close_delay;
-    tmp.baud_base = info->baud;
-    tmp.custom_divisor = info->custom_divisor;
-    tmp.hub6 = 0;               /*!!!*/
-    return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0;
-} /* get_serial_info */
+       struct serial_struct tmp;
+       struct cyclades_card *cinfo = &cy_card[info->card];
 
+       if (!retinfo)
+               return -EFAULT;
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.type = info->type;
+       tmp.line = info->line;
+       tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
+       tmp.irq = cinfo->irq;
+       tmp.flags = info->flags;
+       tmp.close_delay = info->close_delay;
+       tmp.baud_base = info->baud;
+       tmp.custom_divisor = info->custom_divisor;
+       tmp.hub6 = 0;           /*!!! */
+       return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+}                              /* get_serial_info */
 
 static int
-set_serial_info(struct cyclades_port * info,
-                           struct serial_struct __user * new_info)
+set_serial_info(struct cyclades_port *info,
+               struct serial_struct __user * new_info)
 {
-  struct serial_struct new_serial;
-  struct cyclades_port old_info;
-
-    if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-       return -EFAULT;
-    old_info = *info;
-
-    if (!capable(CAP_SYS_ADMIN)) {
-            if ((new_serial.close_delay != info->close_delay) ||
-               (new_serial.baud_base != info->baud) ||
-               ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
-                (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
-                    return -EPERM;
-            info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-                           (new_serial.flags & ASYNC_USR_MASK));
-            info->baud = new_serial.baud_base;
-           info->custom_divisor = new_serial.custom_divisor;
-            goto check_and_exit;
-    }
-
-
-    /*
-     * OK, past this point, all the error checking has been done.
-     * At this point, we start making changes.....
-     */
-
-    info->baud = new_serial.baud_base;
-    info->custom_divisor = new_serial.custom_divisor;
-    info->flags = ((info->flags & ~ASYNC_FLAGS) |
-                    (new_serial.flags & ASYNC_FLAGS));
-    info->close_delay = new_serial.close_delay * HZ/100;
-    info->closing_wait = new_serial.closing_wait * HZ/100;
+       struct serial_struct new_serial;
+       struct cyclades_port old_info;
+
+       if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+               return -EFAULT;
+       old_info = *info;
+
+       if (!capable(CAP_SYS_ADMIN)) {
+               if (new_serial.close_delay != info->close_delay ||
+                               new_serial.baud_base != info->baud ||
+                               (new_serial.flags & ASYNC_FLAGS &
+                                       ~ASYNC_USR_MASK) !=
+                               (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
+                       return -EPERM;
+               info->flags = (info->flags & ~ASYNC_USR_MASK) |
+                               (new_serial.flags & ASYNC_USR_MASK);
+               info->baud = new_serial.baud_base;
+               info->custom_divisor = new_serial.custom_divisor;
+               goto check_and_exit;
+       }
+
+       /*
+        * OK, past this point, all the error checking has been done.
+        * At this point, we start making changes.....
+        */
+
+       info->baud = new_serial.baud_base;
+       info->custom_divisor = new_serial.custom_divisor;
+       info->flags = (info->flags & ~ASYNC_FLAGS) |
+                       (new_serial.flags & ASYNC_FLAGS);
+       info->close_delay = new_serial.close_delay * HZ / 100;
+       info->closing_wait = new_serial.closing_wait * HZ / 100;
 
 check_and_exit:
-    if (info->flags & ASYNC_INITIALIZED){
-        set_line_char(info);
-        return 0;
-    }else{
-        return startup(info);
-    }
-} /* set_serial_info */
+       if (info->flags & ASYNC_INITIALIZED) {
+               set_line_char(info);
+               return 0;
+       } else {
+               return startup(info);
+       }
+}                              /* set_serial_info */
 
 /*
  * get_lsr_info - get line status register info
@@ -3472,441 +3562,452 @@ check_and_exit:
  *         transmit holding register is empty.  This functionality
  *         allows an RS485 driver to be written in user space.
  */
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
+static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
 {
-    int card, chip, channel, index;
-    unsigned char status;
-    unsigned int result;
-    unsigned long flags;
-    void __iomem *base_addr;
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       int card, chip, channel, index;
+       unsigned char status;
+       unsigned int result;
+       unsigned long flags;
+       void __iomem *base_addr;
 
-       CY_LOCK(info, flags);
-       status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty);
-       CY_UNLOCK(info, flags);
-       result = (status ? 0 : TIOCSER_TEMT);
-    } else {
-       /* Not supported yet */
-       return -EINVAL;
-    }
-    return put_user(result, (unsigned long __user *) value);
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+               CY_LOCK(info, flags);
+               status = cy_readb(base_addr + (CySRER << index)) &
+                               (CyTxRdy | CyTxMpty);
+               CY_UNLOCK(info, flags);
+               result = (status ? 0 : TIOCSER_TEMT);
+       } else {
+               /* Not supported yet */
+               return -EINVAL;
+       }
+       return put_user(result, (unsigned long __user *)value);
 }
 
-static int
-cy_tiocmget(struct tty_struct *tty, struct file *file)
+static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  int card,chip,channel,index;
-  void __iomem *base_addr;
-  unsigned long flags;
-  unsigned char status;
-  unsigned long lstatus;
-  unsigned int result;
-  struct FIRM_ID __iomem *firm_id;
-  struct ZFW_CTRL __iomem *zfw_ctrl;
-  struct BOARD_CTRL __iomem *board_ctrl;
-  struct CH_CTRL __iomem *ch_ctrl;
-
-    if (serial_paranoia_check(info, tty->name, __FUNCTION__))
-       return -ENODEV;
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       int card, chip, channel, index;
+       void __iomem *base_addr;
+       unsigned long flags;
+       unsigned char status;
+       unsigned long lstatus;
+       unsigned int result;
+       struct FIRM_ID __iomem *firm_id;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct BOARD_CTRL __iomem *board_ctrl;
+       struct CH_CTRL __iomem *ch_ctrl;
+
+       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+               return -ENODEV;
 
-       CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-           status = cy_readb(base_addr+(CyMSVR1<<index));
-           status |= cy_readb(base_addr+(CyMSVR2<<index));
-       CY_UNLOCK(info, flags);
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
 
-        if (info->rtsdtr_inv) {
-           result =  ((status  & CyRTS) ? TIOCM_DTR : 0)
-                   | ((status  & CyDTR) ? TIOCM_RTS : 0);
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               status = cy_readb(base_addr + (CyMSVR1 << index));
+               status |= cy_readb(base_addr + (CyMSVR2 << index));
+               CY_UNLOCK(info, flags);
+
+               if (info->rtsdtr_inv) {
+                       result = ((status & CyRTS) ? TIOCM_DTR : 0) |
+                               ((status & CyDTR) ? TIOCM_RTS : 0);
+               } else {
+                       result = ((status & CyRTS) ? TIOCM_RTS : 0) |
+                               ((status & CyDTR) ? TIOCM_DTR : 0);
+               }
+               result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
+                       ((status & CyRI) ? TIOCM_RNG : 0) |
+                       ((status & CyDSR) ? TIOCM_DSR : 0) |
+                       ((status & CyCTS) ? TIOCM_CTS : 0);
        } else {
-           result =  ((status  & CyRTS) ? TIOCM_RTS : 0)
-                   | ((status  & CyDTR) ? TIOCM_DTR : 0);
-       }
-       result |=  ((status  & CyDCD) ? TIOCM_CAR : 0)
-                | ((status  & CyRI) ? TIOCM_RNG : 0)
-                | ((status  & CyDSR) ? TIOCM_DSR : 0)
-                | ((status  & CyCTS) ? TIOCM_CTS : 0);
-    } else {
-       base_addr = cy_card[card].base_addr;
-
-        if (cy_card[card].num_chips != -1){
-           return -EINVAL;
-       }
+               base_addr = cy_card[card].base_addr;
 
-       firm_id = cy_card[card].base_addr + ID_ADDRESS;
-        if (ISZLOADED(cy_card[card])) {
-           zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-           board_ctrl = &zfw_ctrl->board_ctrl;
-           ch_ctrl = zfw_ctrl->ch_ctrl;
-           lstatus = cy_readl(&ch_ctrl[channel].rs_status);
-           result =  ((lstatus  & C_RS_RTS) ? TIOCM_RTS : 0)
-                   | ((lstatus  & C_RS_DTR) ? TIOCM_DTR : 0)
-                   | ((lstatus  & C_RS_DCD) ? TIOCM_CAR : 0)
-                   | ((lstatus  & C_RS_RI) ? TIOCM_RNG : 0)
-                   | ((lstatus  & C_RS_DSR) ? TIOCM_DSR : 0)
-                   | ((lstatus  & C_RS_CTS) ? TIOCM_CTS : 0);
-       }else{
-           result = 0;
-           return -ENODEV;
-       }
+               if (cy_card[card].num_chips != -1) {
+                       return -EINVAL;
+               }
 
-    }
-    return result;
-} /* cy_tiomget */
+               firm_id = cy_card[card].base_addr + ID_ADDRESS;
+               if (ISZLOADED(cy_card[card])) {
+                       zfw_ctrl = cy_card[card].base_addr +
+                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+                       board_ctrl = &zfw_ctrl->board_ctrl;
+                       ch_ctrl = zfw_ctrl->ch_ctrl;
+                       lstatus = cy_readl(&ch_ctrl[channel].rs_status);
+                       result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
+                               ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
+                               ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
+                               ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
+                               ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
+                               ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
+               } else {
+                       result = 0;
+                       return -ENODEV;
+               }
 
+       }
+       return result;
+}                              /* cy_tiomget */
 
 static int
 cy_tiocmset(struct tty_struct *tty, struct file *file,
-            unsigned int set, unsigned int clear)
+               unsigned int set, unsigned int clear)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  int card,chip,channel,index;
-  void __iomem *base_addr;
-  unsigned long flags;
-  struct FIRM_ID __iomem *firm_id;
-  struct ZFW_CTRL __iomem *zfw_ctrl;
-  struct BOARD_CTRL __iomem *board_ctrl;
-  struct CH_CTRL __iomem *ch_ctrl;
-  int retval;
-
-    if (serial_paranoia_check(info, tty->name, __FUNCTION__))
-       return -ENODEV;
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-       if (set & TIOCM_RTS){
-               CY_LOCK(info, flags);
-               cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
-                } else {
-                       cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-                }
-               CY_UNLOCK(info, flags);
-       }
-       if (clear & TIOCM_RTS) {
-               CY_LOCK(info, flags);
-               cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
-                } else {
-                       cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
-                }
-               CY_UNLOCK(info, flags);
-       }
-       if (set & TIOCM_DTR){
-               CY_LOCK(info, flags);
-               cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-                } else {
-                       cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
-                }
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       int card, chip, channel, index;
+       void __iomem *base_addr;
+       unsigned long flags;
+       struct FIRM_ID __iomem *firm_id;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct BOARD_CTRL __iomem *board_ctrl;
+       struct CH_CTRL __iomem *ch_ctrl;
+       int retval;
+
+       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+               return -ENODEV;
+
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+               if (set & TIOCM_RTS) {
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         CyDTR);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         CyRTS);
+                       }
+                       CY_UNLOCK(info, flags);
+               }
+               if (clear & TIOCM_RTS) {
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         ~CyDTR);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         ~CyRTS);
+                       }
+                       CY_UNLOCK(info, flags);
+               }
+               if (set & TIOCM_DTR) {
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         CyRTS);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         CyDTR);
+                       }
 #ifdef CY_DEBUG_DTR
-               printk("cyc:set_modem_info raising DTR\n");
-               printk("     status: 0x%x, 0x%x\n",
-                   cy_readb(base_addr+(CyMSVR1<<index)), 
-                    cy_readb(base_addr+(CyMSVR2<<index)));
+                       printk("cyc:set_modem_info raising DTR\n");
+                       printk("     status: 0x%x, 0x%x\n",
+                               cy_readb(base_addr + (CyMSVR1 << index)),
+                               cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
-               CY_UNLOCK(info, flags);
-       }
-       if (clear & TIOCM_DTR) {
-               CY_LOCK(info, flags);
-               cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-                       cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
-                } else {
-                       cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
-                }
+                       CY_UNLOCK(info, flags);
+               }
+               if (clear & TIOCM_DTR) {
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         ~CyRTS);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         ~CyDTR);
+                       }
 
 #ifdef CY_DEBUG_DTR
-               printk("cyc:set_modem_info dropping DTR\n");
-               printk("     status: 0x%x, 0x%x\n",
-                   cy_readb(base_addr+(CyMSVR1<<index)), 
-                    cy_readb(base_addr+(CyMSVR2<<index)));
+                       printk("cyc:set_modem_info dropping DTR\n");
+                       printk("     status: 0x%x, 0x%x\n",
+                               cy_readb(base_addr + (CyMSVR1 << index)),
+                               cy_readb(base_addr + (CyMSVR2 << index)));
 #endif
-               CY_UNLOCK(info, flags);
-       }
-    } else {
-       base_addr = cy_card[card].base_addr;
-
-       firm_id = cy_card[card].base_addr + ID_ADDRESS;
-        if (ISZLOADED(cy_card[card])) {
-           zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
-           board_ctrl = &zfw_ctrl->board_ctrl;
-           ch_ctrl = zfw_ctrl->ch_ctrl;
-
-           if (set & TIOCM_RTS){
-                   CY_LOCK(info, flags);
-                   cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
-                   CY_UNLOCK(info, flags);
-           }
-           if (clear & TIOCM_RTS) {
-                   CY_LOCK(info, flags);
-                   cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
-                   CY_UNLOCK(info, flags);
-           }
-           if (set & TIOCM_DTR){
-                   CY_LOCK(info, flags);
-                   cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
+                       CY_UNLOCK(info, flags);
+               }
+       } else {
+               base_addr = cy_card[card].base_addr;
+
+               firm_id = cy_card[card].base_addr + ID_ADDRESS;
+               if (ISZLOADED(cy_card[card])) {
+                       zfw_ctrl = cy_card[card].base_addr +
+                               (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+                       board_ctrl = &zfw_ctrl->board_ctrl;
+                       ch_ctrl = zfw_ctrl->ch_ctrl;
+
+                       if (set & TIOCM_RTS) {
+                               CY_LOCK(info, flags);
+                               cy_writel(&ch_ctrl[channel].rs_control,
+                                         cy_readl(&ch_ctrl[channel].
+                                                  rs_control) | C_RS_RTS);
+                               CY_UNLOCK(info, flags);
+                       }
+                       if (clear & TIOCM_RTS) {
+                               CY_LOCK(info, flags);
+                               cy_writel(&ch_ctrl[channel].rs_control,
+                                         cy_readl(&ch_ctrl[channel].
+                                                  rs_control) & ~C_RS_RTS);
+                               CY_UNLOCK(info, flags);
+                       }
+                       if (set & TIOCM_DTR) {
+                               CY_LOCK(info, flags);
+                               cy_writel(&ch_ctrl[channel].rs_control,
+                                         cy_readl(&ch_ctrl[channel].
+                                                  rs_control) | C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                   printk("cyc:set_modem_info raising Z DTR\n");
+                               printk("cyc:set_modem_info raising Z DTR\n");
 #endif
-                   CY_UNLOCK(info, flags);
-           }
-           if (clear & TIOCM_DTR) {
-                   CY_LOCK(info, flags);
-                   cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
+                               CY_UNLOCK(info, flags);
+                       }
+                       if (clear & TIOCM_DTR) {
+                               CY_LOCK(info, flags);
+                               cy_writel(&ch_ctrl[channel].rs_control,
+                                         cy_readl(&ch_ctrl[channel].
+                                                  rs_control) & ~C_RS_DTR);
 #ifdef CY_DEBUG_DTR
-                   printk("cyc:set_modem_info clearing Z DTR\n");
+                               printk("cyc:set_modem_info clearing Z DTR\n");
 #endif
-                   CY_UNLOCK(info, flags);
-           }
-       }else{
-           return -ENODEV;
-       }
-       CY_LOCK(info, flags);
-        retval = cyz_issue_cmd(&cy_card[info->card],
-                                   channel, C_CM_IOCTLM,0L);
-       if (retval != 0){
-           printk("cyc:set_modem_info retval on ttyC%d was %x\n",
-                  info->line, retval);
+                               CY_UNLOCK(info, flags);
+                       }
+               } else {
+                       return -ENODEV;
+               }
+               CY_LOCK(info, flags);
+               retval = cyz_issue_cmd(&cy_card[info->card],
+                                       channel, C_CM_IOCTLM, 0L);
+               if (retval != 0) {
+                       printk("cyc:set_modem_info retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
+               CY_UNLOCK(info, flags);
        }
-       CY_UNLOCK(info, flags);
-    }
-    return 0;
-} /* cy_tiocmset */
+       return 0;
+}                              /* cy_tiocmset */
 
 /*
  * cy_break() --- routine which turns the break handling on or off
  */
-static void
-cy_break(struct tty_struct *tty, int break_state)
+static void cy_break(struct tty_struct *tty, int break_state)
 {
-    struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-    unsigned long flags;
-
-    if (serial_paranoia_check(info, tty->name, "cy_break"))
-       return;
-
-    CY_LOCK(info, flags);
-    if (!IS_CYC_Z(cy_card[info->card])) {
-        /* Let the transmit ISR take care of this (since it
-          requires stuffing characters into the output stream).
-        */
-       if (break_state == -1) {
-           if (!info->breakon) {
-               info->breakon = 1;
-               if (!info->xmit_cnt) {
-                   CY_UNLOCK(info, flags);
-                   start_xmit(info);
-                   CY_LOCK(info, flags);
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
+
+       if (serial_paranoia_check(info, tty->name, "cy_break"))
+               return;
+
+       CY_LOCK(info, flags);
+       if (!IS_CYC_Z(cy_card[info->card])) {
+               /* Let the transmit ISR take care of this (since it
+                  requires stuffing characters into the output stream).
+                */
+               if (break_state == -1) {
+                       if (!info->breakon) {
+                               info->breakon = 1;
+                               if (!info->xmit_cnt) {
+                                       CY_UNLOCK(info, flags);
+                                       start_xmit(info);
+                                       CY_LOCK(info, flags);
+                               }
+                       }
+               } else {
+                       if (!info->breakoff) {
+                               info->breakoff = 1;
+                               if (!info->xmit_cnt) {
+                                       CY_UNLOCK(info, flags);
+                                       start_xmit(info);
+                                       CY_LOCK(info, flags);
+                               }
+                       }
                }
-           }
        } else {
-           if (!info->breakoff) {
-               info->breakoff = 1;
-               if (!info->xmit_cnt) {
-                   CY_UNLOCK(info, flags);
-                   start_xmit(info);
-                   CY_LOCK(info, flags);
+               int retval;
+
+               if (break_state == -1) {
+                       retval = cyz_issue_cmd(&cy_card[info->card],
+                               info->line - cy_card[info->card].first_line,
+                               C_CM_SET_BREAK, 0L);
+                       if (retval != 0) {
+                               printk("cyc:cy_break (set) retval on ttyC%d "
+                                       "was %x\n", info->line, retval);
+                       }
+               } else {
+                       retval = cyz_issue_cmd(&cy_card[info->card],
+                               info->line - cy_card[info->card].first_line,
+                               C_CM_CLR_BREAK, 0L);
+                       if (retval != 0) {
+                               printk("cyc:cy_break (clr) retval on ttyC%d "
+                                       "was %x\n", info->line, retval);
+                       }
                }
-           }
        }
-    } else {
-       int retval;
-
-       if (break_state == -1) {
-           retval = cyz_issue_cmd(&cy_card[info->card],
-               (info->line) - (cy_card[info->card].first_line),
-               C_CM_SET_BREAK, 0L);
-           if (retval != 0) {
-               printk("cyc:cy_break (set) retval on ttyC%d was %x\n",
-                      info->line, retval);
-           }
-       } else {
-           retval = cyz_issue_cmd(&cy_card[info->card],
-               (info->line) - (cy_card[info->card].first_line),
-               C_CM_CLR_BREAK, 0L);
-           if (retval != 0) {
-               printk("cyc:cy_break (clr) retval on ttyC%d was %x\n",
-                      info->line, retval);
-           }
-       }
-    }
-    CY_UNLOCK(info, flags);
-} /* cy_break */
+       CY_UNLOCK(info, flags);
+}                              /* cy_break */
 
 static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
+get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
 {
 
-    if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-       return -EFAULT;
-    info->mon.int_count  = 0;
-    info->mon.char_count = 0;
-    info->mon.char_max   = 0;
-    info->mon.char_last  = 0;
-    return 0;
-}/* get_mon_info */
-
+       if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+               return -EFAULT;
+       info->mon.int_count = 0;
+       info->mon.char_count = 0;
+       info->mon.char_max = 0;
+       info->mon.char_last = 0;
+       return 0;
+}                              /* get_mon_info */
 
-static int
-set_threshold(struct cyclades_port * info, unsigned long value)
+static int set_threshold(struct cyclades_port *info, unsigned long value)
 {
-  void __iomem *base_addr;
-  int card,channel,chip,index;
-  unsigned long flags;
-   
-    card = info->card;
-    channel = info->line - cy_card[card].first_line;
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-       info->cor3 &= ~CyREC_FIFO;
-       info->cor3 |= value & CyREC_FIFO;
+       void __iomem *base_addr;
+       int card, channel, chip, index;
+       unsigned long flags;
 
-       CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
-           cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
-       CY_UNLOCK(info, flags);
-    } else {
-       // Nothing to do!
-    }
-    return 0;
-}/* set_threshold */
+       card = info->card;
+       channel = info->line - cy_card[card].first_line;
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
 
+               info->cor3 &= ~CyREC_FIFO;
+               info->cor3 |= value & CyREC_FIFO;
 
-static int
-get_threshold(struct cyclades_port * info, unsigned long __user *value)
-{
-  void __iomem *base_addr;
-  int card,channel,chip,index;
-  unsigned long tmp;
-   
-    card = info->card;
-    channel = info->line - cy_card[card].first_line;
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-       tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
-       return put_user(tmp,value);
-    } else {
-       // Nothing to do!
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
+               cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
+               CY_UNLOCK(info, flags);
+       } else {
+               /* Nothing to do! */
+       }
        return 0;
-    }
-}/* get_threshold */
-
+}                              /* set_threshold */
 
 static int
-set_default_threshold(struct cyclades_port * info, unsigned long value)
+get_threshold(struct cyclades_port *info, unsigned long __user * value)
 {
-    info->default_threshold = value & 0x0f;
-    return 0;
-}/* set_default_threshold */
+       void __iomem *base_addr;
+       int card, channel, chip, index;
+       unsigned long tmp;
 
+       card = info->card;
+       channel = info->line - cy_card[card].first_line;
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+               tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
+               return put_user(tmp, value);
+       } else {
+               /* Nothing to do! */
+               return 0;
+       }
+}                              /* get_threshold */
 
 static int
-get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
+set_default_threshold(struct cyclades_port *info, unsigned long value)
 {
-    return put_user(info->default_threshold,value);
-}/* get_default_threshold */
-
+       info->default_threshold = value & 0x0f;
+       return 0;
+}                              /* set_default_threshold */
 
 static int
-set_timeout(struct cyclades_port * info, unsigned long value)
+get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
 {
-  void __iomem *base_addr;
-  int card,channel,chip,index;
-  unsigned long flags;
-   
-    card = info->card;
-    channel = info->line - cy_card[card].first_line;
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+       return put_user(info->default_threshold, value);
+}                              /* get_default_threshold */
 
-       CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyRTPR<<index), value & 0xff);
-       CY_UNLOCK(info, flags);
-    } else {
-       // Nothing to do!
-    }
-    return 0;
-}/* set_timeout */
+static int set_timeout(struct cyclades_port *info, unsigned long value)
+{
+       void __iomem *base_addr;
+       int card, channel, chip, index;
+       unsigned long flags;
 
+       card = info->card;
+       channel = info->line - cy_card[card].first_line;
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
 
-static int
-get_timeout(struct cyclades_port * info, unsigned long __user *value)
-{
-  void __iomem *base_addr;
-  int card,channel,chip,index;
-  unsigned long tmp;
-   
-    card = info->card;
-    channel = info->line - cy_card[card].first_line;
-    if (!IS_CYC_Z(cy_card[card])) {
-       chip = channel>>2;
-       channel &= 0x03;
-       index = cy_card[card].bus_index;
-       base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-       tmp = cy_readb(base_addr+(CyRTPR<<index));
-       return put_user(tmp,value);
-    } else {
-       // Nothing to do!
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
+               CY_UNLOCK(info, flags);
+       } else {
+               /* Nothing to do! */
+       }
        return 0;
-    }
-}/* get_timeout */
+}                              /* set_timeout */
 
-
-static int
-set_default_timeout(struct cyclades_port * info, unsigned long value)
+static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
 {
-    info->default_timeout = value & 0xff;
-    return 0;
-}/* set_default_timeout */
+       void __iomem *base_addr;
+       int card, channel, chip, index;
+       unsigned long tmp;
+
+       card = info->card;
+       channel = info->line - cy_card[card].first_line;
+       if (!IS_CYC_Z(cy_card[card])) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               index = cy_card[card].bus_index;
+               base_addr =
+                   cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+               tmp = cy_readb(base_addr + (CyRTPR << index));
+               return put_user(tmp, value);
+       } else {
+               /* Nothing to do! */
+               return 0;
+       }
+}                              /* get_timeout */
 
+static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+{
+       info->default_timeout = value & 0xff;
+       return 0;
+}                              /* set_default_timeout */
 
 static int
-get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
+get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
 {
-    return put_user(info->default_timeout,value);
-}/* get_default_timeout */
+       return put_user(info->default_timeout, value);
+}                              /* get_default_timeout */
 
 /*
  * This routine allows the tty driver to implement device-
@@ -3914,184 +4015,193 @@ get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
  * not recognized by the driver, it should return ENOIOCTLCMD.
  */
 static int
-cy_ioctl(struct tty_struct *tty, struct file * file,
-            unsigned int cmd, unsigned long arg)
+cy_ioctl(struct tty_struct *tty, struct file *file,
+        unsigned int cmd, unsigned long arg)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  struct cyclades_icount cprev, cnow;          /* kernel counter temps */
-  struct serial_icounter_struct __user *p_cuser;       /* user space */
-  int ret_val = 0;
-  unsigned long flags;
-  void __user *argp = (void __user *)arg;
-
-    if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
-       return -ENODEV;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_icount cprev, cnow;     /* kernel counter temps */
+       struct serial_icounter_struct __user *p_cuser;  /* user space */
+       int ret_val = 0;
+       unsigned long flags;
+       void __user *argp = (void __user *)arg;
+
+       if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
+               return -ENODEV;
 
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
-        info->line, cmd, arg); /* */
+       printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg);      /* */
 #endif
 
-    switch (cmd) {
-        case CYGETMON:
-            ret_val = get_mon_info(info, argp);
-            break;
-        case CYGETTHRESH:
-            ret_val = get_threshold(info, argp);
-            break;
-        case CYSETTHRESH:
-            ret_val = set_threshold(info, arg);
-            break;
-        case CYGETDEFTHRESH:
-            ret_val = get_default_threshold(info, argp);
-            break;
-        case CYSETDEFTHRESH:
-            ret_val = set_default_threshold(info, arg);
-            break;
-        case CYGETTIMEOUT:
-            ret_val = get_timeout(info, argp);
-            break;
-        case CYSETTIMEOUT:
-            ret_val = set_timeout(info, arg);
-            break;
-        case CYGETDEFTIMEOUT:
-            ret_val = get_default_timeout(info, argp);
-            break;
-        case CYSETDEFTIMEOUT:
-            ret_val = set_default_timeout(info, arg);
-            break;
+       switch (cmd) {
+       case CYGETMON:
+               ret_val = get_mon_info(info, argp);
+               break;
+       case CYGETTHRESH:
+               ret_val = get_threshold(info, argp);
+               break;
+       case CYSETTHRESH:
+               ret_val = set_threshold(info, arg);
+               break;
+       case CYGETDEFTHRESH:
+               ret_val = get_default_threshold(info, argp);
+               break;
+       case CYSETDEFTHRESH:
+               ret_val = set_default_threshold(info, arg);
+               break;
+       case CYGETTIMEOUT:
+               ret_val = get_timeout(info, argp);
+               break;
+       case CYSETTIMEOUT:
+               ret_val = set_timeout(info, arg);
+               break;
+       case CYGETDEFTIMEOUT:
+               ret_val = get_default_timeout(info, argp);
+               break;
+       case CYSETDEFTIMEOUT:
+               ret_val = set_default_timeout(info, arg);
+               break;
        case CYSETRFLOW:
-           info->rflow = (int)arg;
-           ret_val = 0;
-           break;
+               info->rflow = (int)arg;
+               ret_val = 0;
+               break;
        case CYGETRFLOW:
-           ret_val = info->rflow;
-           break;
+               ret_val = info->rflow;
+               break;
        case CYSETRTSDTR_INV:
-           info->rtsdtr_inv = (int)arg;
-           ret_val = 0;
-           break;
+               info->rtsdtr_inv = (int)arg;
+               ret_val = 0;
+               break;
        case CYGETRTSDTR_INV:
-           ret_val = info->rtsdtr_inv;
-           break;
+               ret_val = info->rtsdtr_inv;
+               break;
        case CYGETCARDINFO:
-            if (copy_to_user(argp, &cy_card[info->card], 
-                       sizeof (struct cyclades_card))) {
-               ret_val = -EFAULT;
+               if (copy_to_user(argp, &cy_card[info->card],
+                                sizeof(struct cyclades_card))) {
+                       ret_val = -EFAULT;
+                       break;
+               }
+               ret_val = 0;
                break;
-           }
-           ret_val = 0;
-            break;
        case CYGETCD1400VER:
-           ret_val = info->chip_rev;
-           break;
+               ret_val = info->chip_rev;
+               break;
 #ifndef CONFIG_CYZ_INTR
        case CYZSETPOLLCYCLE:
-            cyz_polling_cycle = (arg * HZ) / 1000;
-           ret_val = 0;
-           break;
+               cyz_polling_cycle = (arg * HZ) / 1000;
+               ret_val = 0;
+               break;
        case CYZGETPOLLCYCLE:
-            ret_val = (cyz_polling_cycle * 1000) / HZ;
-           break;
-#endif /* CONFIG_CYZ_INTR */
+               ret_val = (cyz_polling_cycle * 1000) / HZ;
+               break;
+#endif                         /* CONFIG_CYZ_INTR */
        case CYSETWAIT:
-           info->closing_wait = (unsigned short)arg * HZ/100;
-           ret_val = 0;
-           break;
+               info->closing_wait = (unsigned short)arg *HZ / 100;
+               ret_val = 0;
+               break;
        case CYGETWAIT:
-           ret_val = info->closing_wait / (HZ/100);
-           break;
-        case TIOCGSERIAL:
-            ret_val = get_serial_info(info, argp);
-            break;
-        case TIOCSSERIAL:
-            ret_val = set_serial_info(info, argp);
-            break;
-       case TIOCSERGETLSR: /* Get line status register */
-           ret_val = get_lsr_info(info, argp);
-           break;
-       /*
-        * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change 
-        * - mask passed in arg for lines of interest
-        *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-        * Caller should use TIOCGICOUNT to see which one it was
-        */
+               ret_val = info->closing_wait / (HZ / 100);
+               break;
+       case TIOCGSERIAL:
+               ret_val = get_serial_info(info, argp);
+               break;
+       case TIOCSSERIAL:
+               ret_val = set_serial_info(info, argp);
+               break;
+       case TIOCSERGETLSR:     /* Get line status register */
+               ret_val = get_lsr_info(info, argp);
+               break;
+               /*
+                * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+                * - mask passed in arg for lines of interest
+                *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+                * Caller should use TIOCGICOUNT to see which one it was
+                */
        case TIOCMIWAIT:
-           CY_LOCK(info, flags);
-           /* note the counters on entry */
-           cprev = info->icount;
-           CY_UNLOCK(info, flags);
-           while (1) {
-               interruptible_sleep_on(&info->delta_msr_wait);
-               /* see if a signal did it */
-               if (signal_pending(current)) {
-                   return -ERESTARTSYS;
-               }
-
                CY_LOCK(info, flags);
-               cnow = info->icount; /* atomic copy */
+               /* note the counters on entry */
+               cprev = info->icount;
                CY_UNLOCK(info, flags);
+               while (1) {
+                       interruptible_sleep_on(&info->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current)) {
+                               return -ERESTARTSYS;
+                       }
 
-               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 */
+                       CY_LOCK(info, flags);
+                       cnow = info->icount;    /* atomic copy */
+                       CY_UNLOCK(info, flags);
 
-       /*
-        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-        * Return: write counters to the user passed counter struct
-        * NB: both 1->0 and 0->1 transitions are counted except for
-        *     RI where only 0->1 is counted.
-        */
+                       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 */
+
+               /*
+                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+                * Return: write counters to the user passed counter struct
+                * NB: both 1->0 and 0->1 transitions are counted except for
+                *     RI where only 0->1 is counted.
+                */
        case TIOCGICOUNT:
-           CY_LOCK(info, flags);
-           cnow = info->icount;
-           CY_UNLOCK(info, flags);
-           p_cuser = argp;
-           ret_val = put_user(cnow.cts, &p_cuser->cts);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.dsr, &p_cuser->dsr);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.rng, &p_cuser->rng);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.dcd, &p_cuser->dcd);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.rx, &p_cuser->rx);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.tx, &p_cuser->tx);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.frame, &p_cuser->frame);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.overrun, &p_cuser->overrun);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.parity, &p_cuser->parity);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.brk, &p_cuser->brk);
-           if (ret_val) return ret_val;
-           ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-           if (ret_val) return ret_val;
-           ret_val = 0;
-           break;
-        default:
-            ret_val = -ENOIOCTLCMD;
-    }
+               CY_LOCK(info, flags);
+               cnow = info->icount;
+               CY_UNLOCK(info, flags);
+               p_cuser = argp;
+               ret_val = put_user(cnow.cts, &p_cuser->cts);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.dsr, &p_cuser->dsr);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.rng, &p_cuser->rng);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.dcd, &p_cuser->dcd);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.rx, &p_cuser->rx);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.tx, &p_cuser->tx);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.frame, &p_cuser->frame);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.overrun, &p_cuser->overrun);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.parity, &p_cuser->parity);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.brk, &p_cuser->brk);
+               if (ret_val)
+                       return ret_val;
+               ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+               if (ret_val)
+                       return ret_val;
+               ret_val = 0;
+               break;
+       default:
+               ret_val = -ENOIOCTLCMD;
+       }
 
 #ifdef CY_DEBUG_OTHER
-    printk(" cyc:cy_ioctl done\n");
+       printk(" cyc:cy_ioctl done\n");
 #endif
 
-    return ret_val;
-} /* cy_ioctl */
-
+       return ret_val;
+}                              /* cy_ioctl */
 
 /*
  * This routine allows the tty driver to be notified when
@@ -4099,66 +4209,64 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
  * well-designed tty driver should be prepared to accept the case
  * where old == NULL, and try to do something rational.
  */
-static void
-cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
+static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_set_termios ttyC%d\n", info->line);
+       printk("cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
-    if ((tty->termios->c_cflag == old_termios->c_cflag) &&
-       ((tty->termios->c_iflag & (IXON|IXANY)) == 
-        (old_termios->c_iflag & (IXON|IXANY))))
-        return;
-    set_line_char(info);
-
-    if ((old_termios->c_cflag & CRTSCTS) &&
-        !(tty->termios->c_cflag & CRTSCTS)) {
-            tty->hw_stopped = 0;
-            cy_start(tty);
-    }
+       if (tty->termios->c_cflag == old_termios->c_cflag &&
+                       (tty->termios->c_iflag & (IXON | IXANY)) ==
+                       (old_termios->c_iflag & (IXON | IXANY)))
+               return;
+       set_line_char(info);
+
+       if ((old_termios->c_cflag & CRTSCTS) &&
+                       !(tty->termios->c_cflag & CRTSCTS)) {
+               tty->hw_stopped = 0;
+               cy_start(tty);
+       }
 #if 0
-    /*
-     * No need to wake up processes in open wait, since they
-     * sample the CLOCAL flag once, and don't recheck it.
-     * XXX  It's not clear whether the current behavior is correct
-     * or not.  Hence, this may change.....
-     */
-    if (!(old_termios->c_cflag & CLOCAL) &&
-        (tty->termios->c_cflag & CLOCAL))
-            wake_up_interruptible(&info->open_wait);
+       /*
+        * No need to wake up processes in open wait, since they
+        * sample the CLOCAL flag once, and don't recheck it.
+        * XXX  It's not clear whether the current behavior is correct
+        * or not.  Hence, this may change.....
+        */
+       if (!(old_termios->c_cflag & CLOCAL) &&
+           (tty->termios->c_cflag & CLOCAL))
+               wake_up_interruptible(&info->open_wait);
 #endif
-
-    return;
-} /* cy_set_termios */
+}                              /* cy_set_termios */
 
 /* This function is used to send a high-priority XON/XOFF character to
    the device.
 */
-static void
-cy_send_xchar (struct tty_struct *tty, char ch)
+static void cy_send_xchar(struct tty_struct *tty, char ch)
 {
-       struct cyclades_port *info = (struct cyclades_port *) tty->driver_data;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
        int card, channel;
 
-       if (serial_paranoia_check (info, tty->name, "cy_send_xchar"))
+       if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
                return;
 
-       info->x_char = ch;
+       info->x_char = ch;
 
        if (ch)
-               cy_start (tty);
+               cy_start(tty);
 
        card = info->card;
        channel = info->line - cy_card[card].first_line;
 
-       if (IS_CYC_Z (cy_card[card])) {
-               if (ch == STOP_CHAR (tty))
-                       cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXOFF, 0L);
-               else if (ch == START_CHAR (tty))
-                       cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXON, 0L);
+       if (IS_CYC_Z(cy_card[card])) {
+               if (ch == STOP_CHAR(tty))
+                       cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF,
+                                       0L);
+               else if (ch == START_CHAR(tty))
+                       cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON,
+                                       0L);
        }
 }
 
@@ -4166,260 +4274,248 @@ cy_send_xchar (struct tty_struct *tty, char ch)
    that incoming characters should be throttled because the input
    buffers are close to full.
  */
-static void
-cy_throttle(struct tty_struct * tty)
+static void cy_throttle(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
-  char buf[64];
+       char buf[64];
 
-    printk("cyc:throttle %s: %d....ttyC%d\n", 
-          tty_name(tty, buf),
-           tty->ldisc.chars_in_buffer(tty), info->line);
+       printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf),
+                       tty->ldisc.chars_in_buffer(tty), info->line);
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_throttle")){
-            return;
-    }
-
-    card = info->card;
-
-    if (I_IXOFF(tty)) {
-        if (!IS_CYC_Z (cy_card[card]))
-            cy_send_xchar (tty, STOP_CHAR (tty));
-        else
-            info->throttle = 1;
-    }
-
-    if (tty->termios->c_cflag & CRTSCTS) {
-        channel = info->line - cy_card[card].first_line;
-        if (!IS_CYC_Z(cy_card[card])) {
-            chip = channel>>2;
-            channel &= 0x03;
-            index = cy_card[card].bus_index;
-            base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-            CY_LOCK(info, flags);
-            cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-            if (info->rtsdtr_inv) {
-                cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
-             } else {
-                cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
-            }
-           CY_UNLOCK(info, flags);
-       } else {
-           info->throttle = 1;
-        }
-    }
+       if (serial_paranoia_check(info, tty->name, "cy_throttle")) {
+               return;
+       }
+
+       card = info->card;
 
-    return;
-} /* cy_throttle */
+       if (I_IXOFF(tty)) {
+               if (!IS_CYC_Z(cy_card[card]))
+                       cy_send_xchar(tty, STOP_CHAR(tty));
+               else
+                       info->throttle = 1;
+       }
 
+       if (tty->termios->c_cflag & CRTSCTS) {
+               channel = info->line - cy_card[card].first_line;
+               if (!IS_CYC_Z(cy_card[card])) {
+                       chip = channel >> 2;
+                       channel &= 0x03;
+                       index = cy_card[card].bus_index;
+                       base_addr = cy_card[card].base_addr +
+                               (cy_chip_offset[chip] << index);
+
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         ~CyDTR);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         ~CyRTS);
+                       }
+                       CY_UNLOCK(info, flags);
+               } else {
+                       info->throttle = 1;
+               }
+       }
+}                              /* cy_throttle */
 
 /*
  * This routine notifies the tty driver that it should signal
  * that characters can now be sent to the tty without fear of
  * overrunning the input buffers of the line disciplines.
  */
-static void
-cy_unthrottle(struct tty_struct * tty)
+static void cy_unthrottle(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  void __iomem *base_addr;
-  int card,chip,channel,index;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       unsigned long flags;
+       void __iomem *base_addr;
+       int card, chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
-  char buf[64];
-        
-    printk("cyc:unthrottle %s: %d....ttyC%d\n", 
-          tty_name(tty, buf),
-           tty->ldisc.chars_in_buffer(tty), info->line);
-#endif
+       char buf[64];
 
-    if (serial_paranoia_check(info, tty->name, "cy_unthrottle")){
-            return;
-    }
+       printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf),
+               tty->ldisc.chars_in_buffer(tty), info->line);
+#endif
 
-    if (I_IXOFF(tty)) {
-       if (info->x_char)
-           info->x_char = 0;
-       else
-           cy_send_xchar (tty, START_CHAR (tty));
-    }
-
-    if (tty->termios->c_cflag & CRTSCTS) {
-        card = info->card;
-        channel = info->line - cy_card[card].first_line;
-        if (!IS_CYC_Z(cy_card[card])) {
-           chip = channel>>2;
-           channel &= 0x03;
-           index = cy_card[card].bus_index;
-           base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
-           CY_LOCK(info, flags);
-           cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-           if (info->rtsdtr_inv) {
-                   cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
-           } else {
-                   cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
-           }
-           CY_UNLOCK(info, flags);
-        } else {
-           info->throttle = 0;
+       if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) {
+               return;
        }
-    }
 
-    return;
-} /* cy_unthrottle */
+       if (I_IXOFF(tty)) {
+               if (info->x_char)
+                       info->x_char = 0;
+               else
+                       cy_send_xchar(tty, START_CHAR(tty));
+       }
 
+       if (tty->termios->c_cflag & CRTSCTS) {
+               card = info->card;
+               channel = info->line - cy_card[card].first_line;
+               if (!IS_CYC_Z(cy_card[card])) {
+                       chip = channel >> 2;
+                       channel &= 0x03;
+                       index = cy_card[card].bus_index;
+                       base_addr = cy_card[card].base_addr +
+                               (cy_chip_offset[chip] << index);
+
+                       CY_LOCK(info, flags);
+                       cy_writeb(base_addr + (CyCAR << index),
+                                 (u_char) channel);
+                       if (info->rtsdtr_inv) {
+                               cy_writeb(base_addr + (CyMSVR2 << index),
+                                         CyDTR);
+                       } else {
+                               cy_writeb(base_addr + (CyMSVR1 << index),
+                                         CyRTS);
+                       }
+                       CY_UNLOCK(info, flags);
+               } else {
+                       info->throttle = 0;
+               }
+       }
+}                              /* cy_unthrottle */
 
 /* cy_start and cy_stop provide software output flow control as a
    function of XON/XOFF, software CTS, and other such stuff.
 */
-static void
-cy_stop(struct tty_struct *tty)
+static void cy_stop(struct tty_struct *tty)
 {
-  struct cyclades_card *cinfo;
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  void __iomem *base_addr;
-  int chip,channel,index;
-  unsigned long flags;
+       struct cyclades_card *cinfo;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       void __iomem *base_addr;
+       int chip, channel, index;
+       unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_stop ttyC%d\n", info->line); /* */
+       printk("cyc:cy_stop ttyC%d\n", info->line);     /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_stop"))
-        return;
-        
-    cinfo = &cy_card[info->card];
-    channel = info->line - cinfo->first_line;
-    if (!IS_CYC_Z(*cinfo)) {
-        index = cinfo->bus_index;
-        chip = channel>>2;
-        channel &= 0x03;
-        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
-
-       CY_LOCK(info, flags);
-            cy_writeb(base_addr+(CyCAR<<index),
-              (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb(base_addr+(CySRER<<index), 
-               cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
-       CY_UNLOCK(info, flags);
-    } else {
-       // Nothing to do!
-    }
+       if (serial_paranoia_check(info, tty->name, "cy_stop"))
+               return;
 
-    return;
-} /* cy_stop */
+       cinfo = &cy_card[info->card];
+       channel = info->line - cinfo->first_line;
+       if (!IS_CYC_Z(*cinfo)) {
+               index = cinfo->bus_index;
+               chip = channel >> 2;
+               channel &= 0x03;
+               base_addr = cy_card[info->card].base_addr +
+                       (cy_chip_offset[chip] << index);
 
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCAR << index),
+                       (u_char)(channel & 0x0003)); /* index channel */
+               cy_writeb(base_addr + (CySRER << index),
+                         cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+               CY_UNLOCK(info, flags);
+       } else {
+               /* Nothing to do! */
+       }
+}                              /* cy_stop */
 
-static void
-cy_start(struct tty_struct *tty)
+static void cy_start(struct tty_struct *tty)
 {
-  struct cyclades_card *cinfo;
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  void __iomem *base_addr;
-  int chip,channel,index;
-  unsigned long flags;
+       struct cyclades_card *cinfo;
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       void __iomem *base_addr;
+       int chip, channel, index;
+       unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_start ttyC%d\n", info->line); /* */
+       printk("cyc:cy_start ttyC%d\n", info->line);    /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_start"))
-        return;
-        
-    cinfo = &cy_card[info->card];
-    channel = info->line - cinfo->first_line;
-    index = cinfo->bus_index;
-    if (!IS_CYC_Z(*cinfo)) {
-        chip = channel>>2;
-        channel &= 0x03;
-        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
-
-       CY_LOCK(info, flags);
-            cy_writeb(base_addr+(CyCAR<<index),
-              (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb(base_addr+(CySRER<<index), 
-               cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
-       CY_UNLOCK(info, flags);
-    } else {
-       // Nothing to do!
-    }
+       if (serial_paranoia_check(info, tty->name, "cy_start"))
+               return;
 
-    return;
-} /* cy_start */
+       cinfo = &cy_card[info->card];
+       channel = info->line - cinfo->first_line;
+       index = cinfo->bus_index;
+       if (!IS_CYC_Z(*cinfo)) {
+               chip = channel >> 2;
+               channel &= 0x03;
+               base_addr = cy_card[info->card].base_addr +
+                       (cy_chip_offset[chip] << index);
 
+               CY_LOCK(info, flags);
+               cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003));   /* index channel */
+               cy_writeb(base_addr + (CySRER << index),
+                         cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
+               CY_UNLOCK(info, flags);
+       } else {
+               /* Nothing to do! */
+       }
+}                              /* cy_start */
 
-static void
-cy_flush_buffer(struct tty_struct *tty)
+static void cy_flush_buffer(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int card, channel, retval;
-  unsigned long flags;
-                                
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+       int card, channel, retval;
+       unsigned long flags;
+
 #ifdef CY_DEBUG_IO
-    printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */
+       printk("cyc:cy_flush_buffer ttyC%d\n", info->line);     /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-        return;
-
-    card = info->card;
-    channel = (info->line) - (cy_card[card].first_line);
+       if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+               return;
 
-    CY_LOCK(info, flags);
-    info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-    CY_UNLOCK(info, flags);
+       card = info->card;
+       channel = (info->line) - (cy_card[card].first_line);
 
-    if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board 
-                                     buffers as well */
        CY_LOCK(info, flags);
-       retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
-       if (retval != 0) {
-           printk("cyc: flush_buffer retval on ttyC%d was %x\n",
-                  info->line, retval);
-       }
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
        CY_UNLOCK(info, flags);
-    }
-    tty_wakeup(tty);
-    wake_up_interruptible(&tty->write_wait);
-} /* cy_flush_buffer */
 
+       if (IS_CYC_Z(cy_card[card])) {  /* If it is a Z card, flush the on-board
+                                          buffers as well */
+               CY_LOCK(info, flags);
+               retval =
+                   cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
+               if (retval != 0) {
+                       printk("cyc: flush_buffer retval on ttyC%d was %x\n",
+                               info->line, retval);
+               }
+               CY_UNLOCK(info, flags);
+       }
+       tty_wakeup(tty);
+       wake_up_interruptible(&tty->write_wait);
+}                              /* cy_flush_buffer */
 
 /*
  * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
-static void
-cy_hangup(struct tty_struct *tty)
+static void cy_hangup(struct tty_struct *tty)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-        
+       struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
 #ifdef CY_DEBUG_OTHER
-    printk("cyc:cy_hangup ttyC%d\n", info->line); /* */
+       printk("cyc:cy_hangup ttyC%d\n", info->line);   /* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-        return;
+       if (serial_paranoia_check(info, tty->name, "cy_hangup"))
+               return;
 
-    cy_flush_buffer(tty);
-    shutdown(info);
-    info->event = 0;
-    info->count = 0;
+       cy_flush_buffer(tty);
+       shutdown(info);
+       info->event = 0;
+       info->count = 0;
 #ifdef CY_DEBUG_COUNT
-    printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
+       printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
 #endif
-    info->tty = NULL;
-    info->flags &= ~ASYNC_NORMAL_ACTIVE;
-    wake_up_interruptible(&info->open_wait);
-} /* cy_hangup */
-
+       info->tty = NULL;
+       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+       wake_up_interruptible(&info->open_wait);
+}                              /* cy_hangup */
 
 /*
  * ---------------------------------------------------------------------
@@ -4432,82 +4528,84 @@ cy_hangup(struct tty_struct *tty)
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
 static unsigned short __init
-cyy_init_card(void __iomem *true_base_addr,int index)
+cyy_init_card(void __iomem * true_base_addr, int index)
 {
-  unsigned int chip_number;
-  void __iomem *base_addr;
-
-    cy_writeb(true_base_addr+(Cy_HwReset<<index), 0); 
-                                               /* Cy_HwReset is 0x1400 */
-    cy_writeb(true_base_addr+(Cy_ClrIntr<<index), 0); 
-                                               /* Cy_ClrIntr is 0x1800 */
-    udelay(500L);
-
-    for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){
-        base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
-        mdelay(1);
-        if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){
-            /*************
-            printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
-               chip_number, (unsigned long)base_addr);
-            *************/
-            return chip_number;
-        }
-
-        cy_writeb(base_addr+(CyGFRCR<<index), 0);
-        udelay(10L);
-
-        /* The Cyclom-16Y does not decode address bit 9 and therefore
-           cannot distinguish between references to chip 0 and a non-
-           existent chip 4.  If the preceding clearing of the supposed
-           chip 4 GFRCR register appears at chip 0, there is no chip 4
-           and this must be a Cyclom-16Y, not a Cyclom-32Ye.
-        */
-        if (chip_number == 4
-        && cy_readb(true_base_addr
-           + (cy_chip_offset[0]<<index)
-           + (CyGFRCR<<index)) == 0){
-            return chip_number;
-        }
-
-        cy_writeb(base_addr+(CyCCR<<index), CyCHIP_RESET);
-        mdelay(1);
-
-        if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){
-            /*
-            printk(" chip #%d at %#6lx is not responding ",
-               chip_number, (unsigned long)base_addr);
-            printk("(GFRCR stayed 0)\n",
-            */
-            return chip_number;
-        }
-        if((0xf0 & (cy_readb(base_addr+(CyGFRCR<<index)))) != 0x40){
-            /*
-            printk(" chip #%d at %#6lx is not valid (GFRCR == %#2x)\n",
-               chip_number, (unsigned long)base_addr,
-              base_addr[CyGFRCR<<index]);
-            */
-            return chip_number;
-        }
-        cy_writeb(base_addr+(CyGCR<<index), CyCH0_SERIAL);
-        if (cy_readb(base_addr+(CyGFRCR<<index)) >= CD1400_REV_J){
-           /* It is a CD1400 rev. J or later */
-           /* Impossible to reach 5ms with this chip. 
-              Changed to 2ms instead (f = 500 Hz). */
-           cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
-       } else {
-           /* f = 200 Hz */
-           cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
-       }
+       unsigned int chip_number;
+       void __iomem *base_addr;
+
+       cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
+       /* Cy_HwReset is 0x1400 */
+       cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
+       /* Cy_ClrIntr is 0x1800 */
+       udelay(500L);
+
+       for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) {
+               base_addr =
+                   true_base_addr + (cy_chip_offset[chip_number] << index);
+               mdelay(1);
+               if (cy_readb(base_addr + (CyCCR << index)) != 0x00) {
+                       /*************
+                       printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
+                       chip_number, (unsigned long)base_addr);
+                       *************/
+                       return chip_number;
+               }
+
+               cy_writeb(base_addr + (CyGFRCR << index), 0);
+               udelay(10L);
+
+               /* The Cyclom-16Y does not decode address bit 9 and therefore
+                  cannot distinguish between references to chip 0 and a non-
+                  existent chip 4.  If the preceding clearing of the supposed
+                  chip 4 GFRCR register appears at chip 0, there is no chip 4
+                  and this must be a Cyclom-16Y, not a Cyclom-32Ye.
+                */
+               if (chip_number == 4 && cy_readb(true_base_addr +
+                               (cy_chip_offset[0] << index) +
+                               (CyGFRCR << index)) == 0) {
+                       return chip_number;
+               }
+
+               cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
+               mdelay(1);
+
+               if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) {
+                       /*
+                          printk(" chip #%d at %#6lx is not responding ",
+                          chip_number, (unsigned long)base_addr);
+                          printk("(GFRCR stayed 0)\n",
+                        */
+                       return chip_number;
+               }
+               if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) !=
+                               0x40) {
+                       /*
+                       printk(" chip #%d at %#6lx is not valid (GFRCR == "
+                                       "%#2x)\n",
+                                       chip_number, (unsigned long)base_addr,
+                                       base_addr[CyGFRCR<<index]);
+                        */
+                       return chip_number;
+               }
+               cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
+               if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
+                       /* It is a CD1400 rev. J or later */
+                       /* Impossible to reach 5ms with this chip.
+                          Changed to 2ms instead (f = 500 Hz). */
+                       cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
+               } else {
+                       /* f = 200 Hz */
+                       cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
+               }
 
-    /*
-        printk(" chip #%d at %#6lx is rev 0x%2x\n",
-               chip_number, (unsigned long)base_addr,
-              cy_readb(base_addr+(CyGFRCR<<index)));
-    */
-    }
-    return chip_number;
-} /* cyy_init_card */
+               /*
+                  printk(" chip #%d at %#6lx is rev 0x%2x\n",
+                  chip_number, (unsigned long)base_addr,
+                  cy_readb(base_addr+(CyGFRCR<<index)));
+                */
+       }
+       return chip_number;
+}                              /* cyy_init_card */
 
 /*
  * ---------------------------------------------------------------------
@@ -4515,126 +4613,124 @@ cyy_init_card(void __iomem *true_base_addr,int index)
  * sets global variables and return the number of ISA boards found.
  * ---------------------------------------------------------------------
  */
-static int __init
-cy_detect_isa(void)
+static int __init cy_detect_isa(void)
 {
 #ifdef CONFIG_ISA
-  unsigned short       cy_isa_irq,nboard;
-  void __iomem         *cy_isa_address;
-  unsigned short       i,j,cy_isa_nchan;
+       unsigned short cy_isa_irq, nboard;
+       void __iomem *cy_isa_address;
+       unsigned short i, j, cy_isa_nchan;
 #ifdef MODULE
-  int isparam = 0;
+       int isparam = 0;
 #endif
 
-        nboard = 0;
+       nboard = 0;
 
 #ifdef MODULE
        /* Check for module parameters */
-       for(i = 0 ; i < NR_CARDS; i++) {
-           if (maddr[i] || i) {
-               isparam = 1;
-               cy_isa_addresses[i] = maddr[i];
-           }
-           if (!maddr[i])
-               break;
+       for (i = 0; i < NR_CARDS; i++) {
+               if (maddr[i] || i) {
+                       isparam = 1;
+                       cy_isa_addresses[i] = maddr[i];
+               }
+               if (!maddr[i])
+                       break;
        }
 #endif
 
-        /* scan the address table probing for Cyclom-Y/ISA boards */
-        for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
-               unsigned int isa_address = cy_isa_addresses[i];
-                if (isa_address  == 0x0000) {
-                        return(nboard);
-                }
+       /* scan the address table probing for Cyclom-Y/ISA boards */
+       for (i = 0; i < NR_ISA_ADDRS; i++) {
+               unsigned int isa_address = cy_isa_addresses[i];
+               if (isa_address == 0x0000) {
+                       return nboard;
+               }
 
-                /* probe for CD1400... */
+               /* probe for CD1400... */
                cy_isa_address = ioremap(isa_address, CyISA_Ywin);
-                cy_isa_nchan = CyPORTS_PER_CHIP * 
-                     cyy_init_card(cy_isa_address,0);
-                if (cy_isa_nchan == 0) {
-                        continue;
-                }
-
+               cy_isa_nchan = CyPORTS_PER_CHIP *
+                       cyy_init_card(cy_isa_address, 0);
+               if (cy_isa_nchan == 0) {
+                       continue;
+               }
 #ifdef MODULE
                if (isparam && irq[i])
-                   cy_isa_irq = irq[i];
+                       cy_isa_irq = irq[i];
                else
 #endif
-                /* find out the board's irq by probing */
-                cy_isa_irq = detect_isa_irq(cy_isa_address);
-                if (cy_isa_irq == 0) {
-                        printk("Cyclom-Y/ISA found at 0x%lx ",
-                                (unsigned long) cy_isa_address);
-                        printk("but the IRQ could not be detected.\n");
-                        continue;
-                }
-
-                if((cy_next_channel+cy_isa_nchan) > NR_PORTS) {
-                        printk("Cyclom-Y/ISA found at 0x%lx ",
-                                (unsigned long) cy_isa_address);
-                        printk("but no more channels are available.\n");
-                        printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
-                        return(nboard);
-                }
-                /* fill the next cy_card structure available */
-                for (j = 0 ; j < NR_CARDS ; j++) {
-                        if (cy_card[j].base_addr == 0)  break;
-                }
-                if (j == NR_CARDS) {    /* no more cy_cards available */
-                        printk("Cyclom-Y/ISA found at 0x%lx ",
-                                (unsigned long) cy_isa_address);
-                        printk("but no more cards can be used .\n");
-                        printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
-                        return(nboard);
-                }
-
-                /* allocate IRQ */
-                if(request_irq(cy_isa_irq, cyy_interrupt,
-                                  IRQF_DISABLED, "Cyclom-Y", &cy_card[j]))
-                {
-                        printk("Cyclom-Y/ISA found at 0x%lx ",
-                                (unsigned long) cy_isa_address);
-                        printk("but could not allocate IRQ#%d.\n",
-                                cy_isa_irq);
-                        return(nboard);
-                }
-
-                /* set cy_card */
-                cy_card[j].base_addr = cy_isa_address;
-                cy_card[j].ctl_addr = NULL;
-                cy_card[j].irq = (int) cy_isa_irq;
-                cy_card[j].bus_index = 0;
-                cy_card[j].first_line = cy_next_channel;
-                cy_card[j].num_chips = cy_isa_nchan/4;
-                nboard++;
-                        
-                /* print message */
-                printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ",
-                    j+1, (unsigned long) cy_isa_address,
-                    (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
-                   cy_isa_irq);
-                printk("%d channels starting from port %d.\n",
-                        cy_isa_nchan, cy_next_channel);
-                cy_next_channel += cy_isa_nchan;
-        }
-        return(nboard);
+                       /* find out the board's irq by probing */
+                       cy_isa_irq = detect_isa_irq(cy_isa_address);
+               if (cy_isa_irq == 0) {
+                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                               (unsigned long)cy_isa_address);
+                       printk("but the IRQ could not be detected.\n");
+                       continue;
+               }
+
+               if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
+                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                               (unsigned long)cy_isa_address);
+                       printk("but no more channels are available.\n");
+                       printk("Change NR_PORTS in cyclades.c and recompile "
+                                       "kernel.\n");
+                       return nboard;
+               }
+               /* fill the next cy_card structure available */
+               for (j = 0; j < NR_CARDS; j++) {
+                       if (cy_card[j].base_addr == 0)
+                               break;
+               }
+               if (j == NR_CARDS) {    /* no more cy_cards available */
+                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                               (unsigned long)cy_isa_address);
+                       printk("but no more cards can be used .\n");
+                       printk("Change NR_CARDS in cyclades.c and recompile "
+                                       "kernel.\n");
+                       return nboard;
+               }
+
+               /* allocate IRQ */
+               if (request_irq(cy_isa_irq, cyy_interrupt,
+                               IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
+                       printk("Cyclom-Y/ISA found at 0x%lx ",
+                               (unsigned long)cy_isa_address);
+                       printk("but could not allocate IRQ#%d.\n", cy_isa_irq);
+                       return nboard;
+               }
+
+               /* set cy_card */
+               cy_card[j].base_addr = cy_isa_address;
+               cy_card[j].ctl_addr = NULL;
+               cy_card[j].irq = (int)cy_isa_irq;
+               cy_card[j].bus_index = 0;
+               cy_card[j].first_line = cy_next_channel;
+               cy_card[j].num_chips = cy_isa_nchan / 4;
+               nboard++;
+
+               /* print message */
+               printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ",
+                       j + 1, (unsigned long)cy_isa_address,
+                       (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
+                       cy_isa_irq);
+               printk("%d channels starting from port %d.\n",
+                       cy_isa_nchan, cy_next_channel);
+               cy_next_channel += cy_isa_nchan;
+       }
+       return nboard;
 #else
-        return(0);
-#endif /* CONFIG_ISA */
-} /* cy_detect_isa */
+       return 0;
+#endif                         /* CONFIG_ISA */
+}                              /* cy_detect_isa */
 
-static void 
-plx_init(void __iomem *addr, uclong initctl)
+static void plx_init(void __iomem * addr, uclong initctl)
 {
-    /* Reset PLX */
-    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
-    udelay(100L);
-    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
-
-    /* Reload Config. Registers from EEPROM */
-    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
-    udelay(100L);
-    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
+       /* Reset PLX */
+       cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
+       udelay(100L);
+       cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
+
+       /* Reload Config. Registers from EEPROM */
+       cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
+       udelay(100L);
+       cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
 }
 
 /*
@@ -4643,43 +4739,42 @@ plx_init(void __iomem *addr, uclong initctl)
  * sets global variables and return the number of PCI boards found.
  * ---------------------------------------------------------------------
  */
-static int __init
-cy_detect_pci(void)
+static int __init cy_detect_pci(void)
 {
 #ifdef CONFIG_PCI
 
-  struct pci_dev       *pdev = NULL;
-  unsigned char                cyy_rev_id;
-  unsigned char                cy_pci_irq = 0;
-  uclong               cy_pci_phys0, cy_pci_phys2;
-  void __iomem         *cy_pci_addr0, *cy_pci_addr2;
-  unsigned short       i,j,cy_pci_nchan, plx_ver;
-  unsigned short       device_id,dev_index = 0;
-  uclong               mailbox;
-  uclong               ZeIndex = 0;
-  void __iomem         *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
-  uclong               Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
-  unsigned char                Ze_irq[NR_CARDS];
-  struct pci_dev       *Ze_pdev[NR_CARDS];
-
-        for (i = 0; i < NR_CARDS; i++) {
-                /* look for a Cyclades card by vendor and device id */
-                while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-                        if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
-                                        device_id, pdev)) == NULL) {
-                                dev_index++;    /* try next device id */
-                        } else {
-                                break;          /* found a board */
-                        }
-                }
+       struct pci_dev *pdev = NULL;
+       unsigned char cyy_rev_id;
+       unsigned char cy_pci_irq = 0;
+       uclong cy_pci_phys0, cy_pci_phys2;
+       void __iomem *cy_pci_addr0, *cy_pci_addr2;
+       unsigned short i, j, cy_pci_nchan, plx_ver;
+       unsigned short device_id, dev_index = 0;
+       uclong mailbox;
+       uclong ZeIndex = 0;
+       void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
+       uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
+       unsigned char Ze_irq[NR_CARDS];
+       struct pci_dev *Ze_pdev[NR_CARDS];
+
+       for (i = 0; i < NR_CARDS; i++) {
+               /* look for a Cyclades card by vendor and device id */
+               while ((device_id = cy_pci_dev_id[dev_index]) != 0) {
+                       if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
+                                                  device_id, pdev)) == NULL) {
+                               dev_index++;    /* try next device id */
+                       } else {
+                               break;  /* found a board */
+                       }
+               }
 
                if (device_id == 0)
-                   break;
+                       break;
 
                if (pci_enable_device(pdev))
-                   continue;
+                       continue;
 
-                /* read PCI configuration area */
+               /* read PCI configuration area */
                cy_pci_irq = pdev->irq;
                cy_pci_phys0 = pci_resource_start(pdev, 0);
                cy_pci_phys2 = pci_resource_start(pdev, 2);
@@ -4687,482 +4782,497 @@ cy_detect_pci(void)
 
                device_id &= ~PCI_DEVICE_ID_MASK;
 
-    if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
-          || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
+               if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+                               device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
 #ifdef CY_PCI_DEBUG
-            printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-               pdev->bus->number, pdev->devfn);
-            printk("rev_id=%d) IRQ%d\n",
-               cyy_rev_id, (int)cy_pci_irq);
-            printk("Cyclom-Y/PCI:found  winaddr=0x%lx ctladdr=0x%lx\n",
-               (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+                       printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
+                               pdev->bus->number, pdev->devfn);
+                       printk("rev_id=%d) IRQ%d\n",
+                               cyy_rev_id, (int)cy_pci_irq);
+                       printk("Cyclom-Y/PCI:found  winaddr=0x%lx "
+                               "ctladdr=0x%lx\n",
+                               (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
 #endif
 
-               if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-                   printk("  Warning: PCI I/O bit incorrectly set. "
-                          "Ignoring it...\n");
-                   pdev->resource[2].flags &= ~IORESOURCE_IO;
-               }
-
-               /* Although we don't use this I/O region, we should
-                  request it from the kernel anyway, to avoid problems
-                  with other drivers accessing it. */
-               if (pci_request_regions(pdev, "Cyclom-Y") != 0) {
-                       printk(KERN_ERR "cyclades: failed to reserve PCI resources\n");
-                       continue;
-               }
+                       if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+                               printk("  Warning: PCI I/O bit incorrectly "
+                                       "set. Ignoring it...\n");
+                               pdev->resource[2].flags &= ~IORESOURCE_IO;
+                       }
 
+                       /* Although we don't use this I/O region, we should
+                          request it from the kernel anyway, to avoid problems
+                          with other drivers accessing it. */
+                       if (pci_request_regions(pdev, "Cyclom-Y") != 0) {
+                               printk(KERN_ERR "cyclades: failed to reserve "
+                                               "PCI resources\n");
+                               continue;
+                       }
 #if defined(__alpha__)
-                if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
-                   printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-                       pdev->bus->number, pdev->devfn);
-                   printk("rev_id=%d) IRQ%d\n",
-                       cyy_rev_id, (int)cy_pci_irq);
-                    printk("Cyclom-Y/PCI:found  winaddr=0x%lx ctladdr=0x%lx\n",
-                       (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
-                   printk("Cyclom-Y/PCI not supported for low addresses in "
-                           "Alpha systems.\n");
-                   i--;
-                   continue;
-                }
+                       if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {   /* below 1M? */
+                               printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
+                                       pdev->bus->number, pdev->devfn);
+                               printk("rev_id=%d) IRQ%d\n",
+                                       cyy_rev_id, (int)cy_pci_irq);
+                               printk("Cyclom-Y/PCI:found  winaddr=0x%lx "
+                                       "ctladdr=0x%lx\n",
+                                       (ulong)cy_pci_phys2,
+                                       (ulong)cy_pci_phys0);
+                               printk("Cyclom-Y/PCI not supported for low "
+                                       "addresses in Alpha systems.\n");
+                               i--;
+                               continue;
+                       }
 #endif
-               cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
-               cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
+                       cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
+                       cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
 
 #ifdef CY_PCI_DEBUG
-            printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
-               (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
+                       printk("Cyclom-Y/PCI: relocate winaddr=0x%lx "
+                               "ctladdr=0x%lx\n",
+                               (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
 #endif
-                cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * 
-                       cyy_init_card(cy_pci_addr2, 1));
-                if(cy_pci_nchan == 0) {
-                        printk("Cyclom-Y PCI host card with ");
-                        printk("no Serial-Modules at 0x%lx.\n",
-                           (ulong) cy_pci_phys2);
-                        i--;
-                        continue;
-                }
-                if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
-                        printk("Cyclom-Y/PCI found at 0x%lx ",
-                           (ulong) cy_pci_phys2);
-                        printk("but no channels are available.\n");
-                        printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
-                        return(i);
-                }
-                /* fill the next cy_card structure available */
-                for (j = 0 ; j < NR_CARDS ; j++) {
-                        if (cy_card[j].base_addr == 0)  break;
-                }
-                if (j == NR_CARDS) {    /* no more cy_cards available */
-                        printk("Cyclom-Y/PCI found at 0x%lx ",
-                           (ulong) cy_pci_phys2);
-                        printk("but no more cards can be used.\n");
-                        printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
-                        return(i);
-                }
-
-                /* allocate IRQ */
-                if(request_irq(cy_pci_irq, cyy_interrupt,
-                       IRQF_SHARED, "Cyclom-Y", &cy_card[j]))
-                {
-                        printk("Cyclom-Y/PCI found at 0x%lx ",
-                           (ulong) cy_pci_phys2);
-                        printk("but could not allocate IRQ%d.\n",
-                           cy_pci_irq);
-                        return(i);
-                }
-
-                /* set cy_card */
-                cy_card[j].base_phys = (ulong)cy_pci_phys2;
-                cy_card[j].ctl_phys = (ulong)cy_pci_phys0;
-                cy_card[j].base_addr = cy_pci_addr2;
-                cy_card[j].ctl_addr = cy_pci_addr0;
-                cy_card[j].irq = (int) cy_pci_irq;
-                cy_card[j].bus_index = 1;
-                cy_card[j].first_line = cy_next_channel;
-                cy_card[j].num_chips = cy_pci_nchan/4;
-               cy_card[j].pdev = pdev;
-       
-                /* enable interrupts in the PCI interface */
-               plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
-               switch (plx_ver) {
-                   case PLX_9050:
-
-                   cy_writeb(cy_pci_addr0+0x4c, 0x43);
-                   break;
-
-                   case PLX_9060:
-                   case PLX_9080:
-                   default: /* Old boards, use PLX_9060 */
-
-                   plx_init(cy_pci_addr0, 0x6c);
-                   /* For some yet unknown reason, once the PLX9060 reloads
-                      the EEPROM, the IRQ is lost and, thus, we have to
-                      re-write it to the PCI config. registers.
-                      This will remain here until we find a permanent fix. */
-                   pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
-
-                   cy_writew(cy_pci_addr0+0x68, 
-                       cy_readw(cy_pci_addr0+0x68)|0x0900);
-                   break;
-               }
+                       cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP *
+                                       cyy_init_card(cy_pci_addr2, 1));
+                       if (cy_pci_nchan == 0) {
+                               printk("Cyclom-Y PCI host card with ");
+                               printk("no Serial-Modules at 0x%lx.\n",
+                                       (ulong) cy_pci_phys2);
+                               i--;
+                               continue;
+                       }
+                       if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+                               printk("Cyclom-Y/PCI found at 0x%lx ",
+                                       (ulong) cy_pci_phys2);
+                               printk("but no channels are available.\n");
+                               printk("Change NR_PORTS in cyclades.c and "
+                                               "recompile kernel.\n");
+                               return i;
+                       }
+                       /* fill the next cy_card structure available */
+                       for (j = 0; j < NR_CARDS; j++) {
+                               if (cy_card[j].base_addr == 0)
+                                       break;
+                       }
+                       if (j == NR_CARDS) {    /* no more cy_cards available */
+                               printk("Cyclom-Y/PCI found at 0x%lx ",
+                                       (ulong) cy_pci_phys2);
+                               printk("but no more cards can be used.\n");
+                               printk("Change NR_CARDS in cyclades.c and "
+                                               "recompile kernel.\n");
+                               return i;
+                       }
 
-                /* print message */
-                printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
-                      j+1, 
-                      (ulong)cy_pci_phys2, 
-                      (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1),
-                      (int)cy_pci_irq);
-                printk("%d channels starting from port %d.\n",
-                   cy_pci_nchan, cy_next_channel);
-
-                cy_next_channel += cy_pci_nchan;
-    }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
-           /* print message */
-               printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-                   pdev->bus->number, pdev->devfn);
-               printk("rev_id=%d) IRQ%d\n",
-                   cyy_rev_id, (int)cy_pci_irq);
-               printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
-                   (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
-           printk("Cyclades-Z/PCI not supported for low addresses\n");
-           break;
-    }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
+                       /* allocate IRQ */
+                       if (request_irq(cy_pci_irq, cyy_interrupt,
+                                       IRQF_SHARED, "Cyclom-Y", &cy_card[j])) {
+                               printk("Cyclom-Y/PCI found at 0x%lx ",
+                                       (ulong) cy_pci_phys2);
+                               printk("but could not allocate IRQ%d.\n",
+                                       cy_pci_irq);
+                               return i;
+                       }
+
+                       /* set cy_card */
+                       cy_card[j].base_phys = (ulong) cy_pci_phys2;
+                       cy_card[j].ctl_phys = (ulong) cy_pci_phys0;
+                       cy_card[j].base_addr = cy_pci_addr2;
+                       cy_card[j].ctl_addr = cy_pci_addr0;
+                       cy_card[j].irq = (int)cy_pci_irq;
+                       cy_card[j].bus_index = 1;
+                       cy_card[j].first_line = cy_next_channel;
+                       cy_card[j].num_chips = cy_pci_nchan / 4;
+                       cy_card[j].pdev = pdev;
+
+                       /* enable interrupts in the PCI interface */
+                       plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
+                       switch (plx_ver) {
+                       case PLX_9050:
+
+                               cy_writeb(cy_pci_addr0 + 0x4c, 0x43);
+                               break;
+
+                       case PLX_9060:
+                       case PLX_9080:
+                       default:        /* Old boards, use PLX_9060 */
+
+                               plx_init(cy_pci_addr0, 0x6c);
+                       /* For some yet unknown reason, once the PLX9060 reloads
+                          the EEPROM, the IRQ is lost and, thus, we have to
+                          re-write it to the PCI config. registers.
+                          This will remain here until we find a permanent
+                          fix. */
+                               pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+                                               cy_pci_irq);
+
+                               cy_writew(cy_pci_addr0 + 0x68,
+                                         cy_readw(cy_pci_addr0 +
+                                                  0x68) | 0x0900);
+                               break;
+                       }
+
+                       /* print message */
+                       printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
+                               j + 1, (ulong)cy_pci_phys2,
+                               (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1),
+                               (int)cy_pci_irq);
+                       printk("%d channels starting from port %d.\n",
+                               cy_pci_nchan, cy_next_channel);
+
+                       cy_next_channel += cy_pci_nchan;
+               } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
+                       /* print message */
+                       printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
+                               pdev->bus->number, pdev->devfn);
+                       printk("rev_id=%d) IRQ%d\n",
+                               cyy_rev_id, (int)cy_pci_irq);
+                       printk("Cyclades-Z/PCI: found winaddr=0x%lx "
+                               "ctladdr=0x%lx\n",
+                               (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+                       printk("Cyclades-Z/PCI not supported for low "
+                               "addresses\n");
+                       break;
+               } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
 #ifdef CY_PCI_DEBUG
-            printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-               pdev->bus->number, pdev->devfn);
-            printk("rev_id=%d) IRQ%d\n",
-               cyy_rev_id, (int)cy_pci_irq);
-            printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
-                (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+                       printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
+                               pdev->bus->number, pdev->devfn);
+                       printk("rev_id=%d) IRQ%d\n",
+                               cyy_rev_id, (int)cy_pci_irq);
+                       printk("Cyclades-Z/PCI: found winaddr=0x%lx "
+                               "ctladdr=0x%lx\n",
+                               (ulong) cy_pci_phys2, (ulong) cy_pci_phys0);
 #endif
-               cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
-
-               /* Disable interrupts on the PLX before resetting it */
-               cy_writew(cy_pci_addr0+0x68,
-                       cy_readw(cy_pci_addr0+0x68) & ~0x0900);
-
-               plx_init(cy_pci_addr0, 0x6c);
-               /* For some yet unknown reason, once the PLX9060 reloads
-                  the EEPROM, the IRQ is lost and, thus, we have to
-                  re-write it to the PCI config. registers.
-                  This will remain here until we find a permanent fix. */
-               pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
-
-               mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
-                          cy_pci_addr0)->mail_box_0);
-
-               if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-                   printk("  Warning: PCI I/O bit incorrectly set. "
-                          "Ignoring it...\n");
-                   pdev->resource[2].flags &= ~IORESOURCE_IO;
-               }
+                       cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
+
+                       /* Disable interrupts on the PLX before resetting it */
+                       cy_writew(cy_pci_addr0 + 0x68,
+                               cy_readw(cy_pci_addr0 + 0x68) & ~0x0900);
+
+                       plx_init(cy_pci_addr0, 0x6c);
+                       /* For some yet unknown reason, once the PLX9060 reloads
+                          the EEPROM, the IRQ is lost and, thus, we have to
+                          re-write it to the PCI config. registers.
+                          This will remain here until we find a permanent
+                          fix. */
+                       pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+                                               cy_pci_irq);
+
+                       mailbox =
+                           (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
+                                               cy_pci_addr0)->mail_box_0);
+
+                       if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+                               printk("  Warning: PCI I/O bit incorrectly "
+                                       "set. Ignoring it...\n");
+                               pdev->resource[2].flags &= ~IORESOURCE_IO;
+                       }
 
-               /* Although we don't use this I/O region, we should
-                  request it from the kernel anyway, to avoid problems
-                  with other drivers accessing it. */
-               if (pci_request_regions(pdev, "Cyclades-Z") != 0) {
-                       printk(KERN_ERR "cyclades: failed to reserve PCI resources\n");
-                       continue;
-               }
-       
-               if (mailbox == ZE_V1) {
-                   cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win);
-                   if (ZeIndex == NR_CARDS) {
-                       printk("Cyclades-Ze/PCI found at 0x%lx ",
-                               (ulong)cy_pci_phys2);
-                       printk("but no more cards can be used.\n");
-                        printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
-                   } else {
-                       Ze_phys0[ZeIndex] = cy_pci_phys0;
-                       Ze_phys2[ZeIndex] = cy_pci_phys2;
-                       Ze_addr0[ZeIndex] = cy_pci_addr0;
-                       Ze_addr2[ZeIndex] = cy_pci_addr2;
-                       Ze_irq[ZeIndex] = cy_pci_irq;
-                       Ze_pdev[ZeIndex] = pdev;
-                       ZeIndex++;
-                   }
-                   i--;
-                   continue;
-               } else {
-                   cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin);
-               }
+                       /* Although we don't use this I/O region, we should
+                          request it from the kernel anyway, to avoid problems
+                          with other drivers accessing it. */
+                       if (pci_request_regions(pdev, "Cyclades-Z") != 0) {
+                               printk(KERN_ERR "cyclades: failed to reserve "
+                                       "PCI resources\n");
+                               continue;
+                       }
+
+                       if (mailbox == ZE_V1) {
+                               cy_pci_addr2 = ioremap(cy_pci_phys2,
+                                               CyPCI_Ze_win);
+                               if (ZeIndex == NR_CARDS) {
+                                       printk("Cyclades-Ze/PCI found at "
+                                               "0x%lx but no more cards can "
+                                               "be used.\nChange NR_CARDS in "
+                                               "cyclades.c and recompile "
+                                               "kernel.\n",
+                                               (ulong)cy_pci_phys2);
+                               } else {
+                                       Ze_phys0[ZeIndex] = cy_pci_phys0;
+                                       Ze_phys2[ZeIndex] = cy_pci_phys2;
+                                       Ze_addr0[ZeIndex] = cy_pci_addr0;
+                                       Ze_addr2[ZeIndex] = cy_pci_addr2;
+                                       Ze_irq[ZeIndex] = cy_pci_irq;
+                                       Ze_pdev[ZeIndex] = pdev;
+                                       ZeIndex++;
+                               }
+                               i--;
+                               continue;
+                       } else {
+                               cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin);
+                       }
 
 #ifdef CY_PCI_DEBUG
-            printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
-                (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
-           if (mailbox == ZO_V1) {
-               cy_writel(&((struct RUNTIME_9060 *)
-                         (cy_pci_addr0))->loc_addr_base, WIN_CREG);
-               PAUSE
-               printk("Cyclades-8Zo/PCI: FPGA id %lx, ver %lx\n",
-                      (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *)
-                       (cy_pci_addr2))->fpga_id)),
-                      (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *)
-                       (cy_pci_addr2))->fpga_version)));
-               cy_writel(&((struct RUNTIME_9060 *)
-                         (cy_pci_addr0))->loc_addr_base, WIN_RAM);
-           } else {
-               printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not loaded\n");
-           }
+                       printk("Cyclades-Z/PCI: relocate winaddr=0x%lx "
+                               "ctladdr=0x%lx\n",
+                               (ulong) cy_pci_addr2, (ulong) cy_pci_addr0);
+                       if (mailbox == ZO_V1) {
+                               cy_writel(&((struct RUNTIME_9060 *)
+                                       (cy_pci_addr0))->loc_addr_base,
+                                       WIN_CREG);
+                               PAUSE;
+                               printk("Cyclades-8Zo/PCI: FPGA id %lx, ver "
+                                       "%lx\n", (ulong) (0xff &
+                                       cy_readl(&((struct CUSTOM_REG *)
+                                               (cy_pci_addr2))->fpga_id)),
+                                       (ulong)(0xff &
+                                       cy_readl(&((struct CUSTOM_REG *)
+                                               (cy_pci_addr2))->
+                                                       fpga_version)));
+                               cy_writel(&((struct RUNTIME_9060 *)
+                                       (cy_pci_addr0))->loc_addr_base,
+                                       WIN_RAM);
+                       } else {
+                               printk("Cyclades-Z/PCI: New Cyclades-Z board.  "
+                                               "FPGA not loaded\n");
+                       }
 #endif
-           /* The following clears the firmware id word.  This ensures
-              that the driver will not attempt to talk to the board
-              until it has been properly initialized.
-            */
-               PAUSE
-               if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-                   cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
-
-                /* This must be a Cyclades-8Zo/PCI.  The extendable
-                   version will have a different device_id and will
-                   be allocated its maximum number of ports. */
-                cy_pci_nchan = 8;
-
-                if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
-                        printk("Cyclades-8Zo/PCI found at 0x%lx ",
-                           (ulong)cy_pci_phys2);
-                        printk("but no channels are available.\n");
-                        printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
-                        return(i);
-                }
-
-                /* fill the next cy_card structure available */
-                for (j = 0 ; j < NR_CARDS ; j++) {
-                        if (cy_card[j].base_addr == 0)  break;
-                }
-                if (j == NR_CARDS) {    /* no more cy_cards available */
-                   printk("Cyclades-8Zo/PCI found at 0x%lx ",
-                       (ulong)cy_pci_phys2);
-                   printk("but no more cards can be used.\n");
-                    printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
-                   return(i);
-                }
+                       /* The following clears the firmware id word.  This
+                          ensures that the driver will not attempt to talk to
+                          the board until it has been properly initialized.
+                        */
+                       PAUSE;
+                       if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
+                               cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
+
+                       /* This must be a Cyclades-8Zo/PCI.  The extendable
+                          version will have a different device_id and will
+                          be allocated its maximum number of ports. */
+                       cy_pci_nchan = 8;
+
+                       if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+                               printk("Cyclades-8Zo/PCI found at 0x%lx but"
+                                       "no channels are available.\nChange "
+                                       "NR_PORTS in cyclades.c and recompile "
+                                       "kernel.\n", (ulong)cy_pci_phys2);
+                               return i;
+                       }
 
+                       /* fill the next cy_card structure available */
+                       for (j = 0; j < NR_CARDS; j++) {
+                               if (cy_card[j].base_addr == 0)
+                                       break;
+                       }
+                       if (j == NR_CARDS) {    /* no more cy_cards available */
+                               printk("Cyclades-8Zo/PCI found at 0x%lx but"
+                                       "no more cards can be used.\nChange "
+                                       "NR_CARDS in cyclades.c and recompile "
+                                       "kernel.\n", (ulong)cy_pci_phys2);
+                               return i;
+                       }
+#ifdef CONFIG_CYZ_INTR
+                       /* allocate IRQ only if board has an IRQ */
+                       if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
+                               if (request_irq(cy_pci_irq, cyz_interrupt,
+                                               IRQF_SHARED, "Cyclades-Z",
+                                               &cy_card[j])) {
+                                       printk("Cyclom-8Zo/PCI found at 0x%lx "
+                                               "but could not allocate "
+                                               "IRQ%d.\n", (ulong)cy_pci_phys2,
+                                               cy_pci_irq);
+                                       return i;
+                               }
+                       }
+#endif                         /* CONFIG_CYZ_INTR */
+
+                       /* set cy_card */
+                       cy_card[j].base_phys = cy_pci_phys2;
+                       cy_card[j].ctl_phys = cy_pci_phys0;
+                       cy_card[j].base_addr = cy_pci_addr2;
+                       cy_card[j].ctl_addr = cy_pci_addr0;
+                       cy_card[j].irq = (int)cy_pci_irq;
+                       cy_card[j].bus_index = 1;
+                       cy_card[j].first_line = cy_next_channel;
+                       cy_card[j].num_chips = -1;
+                       cy_card[j].pdev = pdev;
+
+                       /* print message */
 #ifdef CONFIG_CYZ_INTR
-                /* allocate IRQ only if board has an IRQ */
-               if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
-                   if(request_irq(cy_pci_irq, cyz_interrupt,
-                       IRQF_SHARED, "Cyclades-Z", &cy_card[j]))
-                   {
-                        printk("Cyclom-8Zo/PCI found at 0x%lx ",
-                           (ulong) cy_pci_phys2);
-                        printk("but could not allocate IRQ%d.\n",
-                           cy_pci_irq);
-                       return(i);
-                   }
+                       /* don't report IRQ if board is no IRQ */
+                       if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
+                               printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, "
+                                       "IRQ%d, ", j + 1, (ulong)cy_pci_phys2,
+                                       (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1),
+                                       (int)cy_pci_irq);
+                       else
+#endif                         /* CONFIG_CYZ_INTR */
+                               printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
+                                       j + 1, (ulong)cy_pci_phys2,
+                                       (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1));
+
+                       printk("%d channels starting from port %d.\n",
+                                       cy_pci_nchan, cy_next_channel);
+                       cy_next_channel += cy_pci_nchan;
                }
-#endif /* CONFIG_CYZ_INTR */
-
-
-                /* set cy_card */
-                cy_card[j].base_phys = cy_pci_phys2;
-                cy_card[j].ctl_phys = cy_pci_phys0;
-                cy_card[j].base_addr = cy_pci_addr2;
-                cy_card[j].ctl_addr = cy_pci_addr0;
-                cy_card[j].irq = (int) cy_pci_irq;
-                cy_card[j].bus_index = 1;
-                cy_card[j].first_line = cy_next_channel;
-                cy_card[j].num_chips = -1;
-               cy_card[j].pdev = pdev;
+       }
 
-                /* print message */
-#ifdef CONFIG_CYZ_INTR
-               /* don't report IRQ if board is no IRQ */
-               if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
-                   printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
-                       j+1,(ulong)cy_pci_phys2,
-                       (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1),
-                       (int)cy_pci_irq);
-               else
-#endif /* CONFIG_CYZ_INTR */
-                   printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
-                       j+1,(ulong)cy_pci_phys2,
-                       (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1));
-
-                printk("%d channels starting from port %d.\n",
-                   cy_pci_nchan,cy_next_channel);
-                cy_next_channel += cy_pci_nchan;
-           }
-        }
-
-        for (; ZeIndex != 0 && i < NR_CARDS; i++) {
-           cy_pci_phys0 = Ze_phys0[0];
-           cy_pci_phys2 = Ze_phys2[0];
-           cy_pci_addr0 = Ze_addr0[0];
-           cy_pci_addr2 = Ze_addr2[0];
-           cy_pci_irq = Ze_irq[0];
-           pdev = Ze_pdev[0];
-           for (j = 0 ; j < ZeIndex-1 ; j++) {
-               Ze_phys0[j] = Ze_phys0[j+1];
-               Ze_phys2[j] = Ze_phys2[j+1];
-               Ze_addr0[j] = Ze_addr0[j+1];
-               Ze_addr2[j] = Ze_addr2[j+1];
-               Ze_irq[j] = Ze_irq[j+1];
-               Ze_pdev[j] = Ze_pdev[j+1];
-           }
-           ZeIndex--;
-               mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
-                                          cy_pci_addr0)->mail_box_0);
+       for (; ZeIndex != 0 && i < NR_CARDS; i++) {
+               cy_pci_phys0 = Ze_phys0[0];
+               cy_pci_phys2 = Ze_phys2[0];
+               cy_pci_addr0 = Ze_addr0[0];
+               cy_pci_addr2 = Ze_addr2[0];
+               cy_pci_irq = Ze_irq[0];
+               pdev = Ze_pdev[0];
+               for (j = 0; j < ZeIndex - 1; j++) {
+                       Ze_phys0[j] = Ze_phys0[j + 1];
+                       Ze_phys2[j] = Ze_phys2[j + 1];
+                       Ze_addr0[j] = Ze_addr0[j + 1];
+                       Ze_addr2[j] = Ze_addr2[j + 1];
+                       Ze_irq[j] = Ze_irq[j + 1];
+                       Ze_pdev[j] = Ze_pdev[j + 1];
+               }
+               ZeIndex--;
+               mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
+                                               cy_pci_addr0)->mail_box_0);
 #ifdef CY_PCI_DEBUG
-            printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
-                (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
-           printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not loaded\n");
+               printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
+                       (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
+               printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not "
+                               "loaded\n");
 #endif
-               PAUSE
-                /* This must be the new Cyclades-Ze/PCI. */
-                cy_pci_nchan = ZE_V1_NPORTS;
-
-                if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
-                        printk("Cyclades-Ze/PCI found at 0x%lx ",
-                           (ulong)cy_pci_phys2);
-                        printk("but no channels are available.\n");
-                        printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
-                        return(i);
-                }
-
-                /* fill the next cy_card structure available */
-                for (j = 0 ; j < NR_CARDS ; j++) {
-                        if (cy_card[j].base_addr == 0)  break;
-                }
-                if (j == NR_CARDS) {    /* no more cy_cards available */
-                   printk("Cyclades-Ze/PCI found at 0x%lx ",
-                       (ulong)cy_pci_phys2);
-                   printk("but no more cards can be used.\n");
-                    printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
-                   return(i);
-                }
+               PAUSE;
+               /* This must be the new Cyclades-Ze/PCI. */
+               cy_pci_nchan = ZE_V1_NPORTS;
+
+               if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+                       printk("Cyclades-Ze/PCI found at 0x%lx but no channels "
+                               "are available.\nChange NR_PORTS in cyclades.c "
+                               "and recompile kernel.\n",
+                               (ulong) cy_pci_phys2);
+                       return i;
+               }
 
+               /* fill the next cy_card structure available */
+               for (j = 0; j < NR_CARDS; j++) {
+                       if (cy_card[j].base_addr == 0)
+                               break;
+               }
+               if (j == NR_CARDS) {    /* no more cy_cards available */
+                       printk("Cyclades-Ze/PCI found at 0x%lx but no more "
+                               "cards can be used.\nChange NR_CARDS in "
+                               "cyclades.c and recompile kernel.\n",
+                               (ulong) cy_pci_phys2);
+                       return i;
+               }
 #ifdef CONFIG_CYZ_INTR
-                /* allocate IRQ only if board has an IRQ */
-               if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
-                   if(request_irq(cy_pci_irq, cyz_interrupt,
-                       IRQF_SHARED, "Cyclades-Z", &cy_card[j]))
-                   {
-                        printk("Cyclom-Ze/PCI found at 0x%lx ",
-                           (ulong) cy_pci_phys2);
-                        printk("but could not allocate IRQ%d.\n",
-                           cy_pci_irq);
-                       return(i);
-                   }
+               /* allocate IRQ only if board has an IRQ */
+               if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
+                       if (request_irq(cy_pci_irq, cyz_interrupt,
+                                       IRQF_SHARED, "Cyclades-Z",
+                                       &cy_card[j])) {
+                               printk("Cyclom-Ze/PCI found at 0x%lx ",
+                                       (ulong) cy_pci_phys2);
+                               printk("but could not allocate IRQ%d.\n",
+                                       cy_pci_irq);
+                               return i;
+                       }
                }
-#endif /* CONFIG_CYZ_INTR */
-
-                /* set cy_card */
-                cy_card[j].base_phys = cy_pci_phys2;
-                cy_card[j].ctl_phys = cy_pci_phys0;
-                cy_card[j].base_addr = cy_pci_addr2;
-                cy_card[j].ctl_addr = cy_pci_addr0;
-                cy_card[j].irq = (int) cy_pci_irq;
-                cy_card[j].bus_index = 1;
-                cy_card[j].first_line = cy_next_channel;
-                cy_card[j].num_chips = -1;
+#endif                         /* CONFIG_CYZ_INTR */
+
+               /* set cy_card */
+               cy_card[j].base_phys = cy_pci_phys2;
+               cy_card[j].ctl_phys = cy_pci_phys0;
+               cy_card[j].base_addr = cy_pci_addr2;
+               cy_card[j].ctl_addr = cy_pci_addr0;
+               cy_card[j].irq = (int)cy_pci_irq;
+               cy_card[j].bus_index = 1;
+               cy_card[j].first_line = cy_next_channel;
+               cy_card[j].num_chips = -1;
                cy_card[j].pdev = pdev;
 
-                /* print message */
+               /* print message */
 #ifdef CONFIG_CYZ_INTR
                /* don't report IRQ if board is no IRQ */
-               if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
-                   printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
-                       j+1,(ulong)cy_pci_phys2,
-                       (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1),
-                       (int)cy_pci_irq);
+               if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
+                       printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
+                               j + 1, (ulong) cy_pci_phys2,
+                               (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1),
+                               (int)cy_pci_irq);
                else
-#endif /* CONFIG_CYZ_INTR */
-                   printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
-                       j+1,(ulong)cy_pci_phys2,
-                       (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1));
-
-                printk("%d channels starting from port %d.\n",
-                   cy_pci_nchan,cy_next_channel);
-                cy_next_channel += cy_pci_nchan;
-        }
+#endif                         /* CONFIG_CYZ_INTR */
+                       printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
+                               j + 1, (ulong) cy_pci_phys2,
+                               (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1));
+
+               printk("%d channels starting from port %d.\n",
+                       cy_pci_nchan, cy_next_channel);
+               cy_next_channel += cy_pci_nchan;
+       }
        if (ZeIndex != 0) {
-           printk("Cyclades-Ze/PCI found at 0x%x ",
-               (unsigned int) Ze_phys2[0]);
-           printk("but no more cards can be used.\n");
-            printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
+               printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be "
+                       "used.\nChange NR_CARDS in cyclades.c and recompile "
+                       "kernel.\n", (unsigned int)Ze_phys2[0]);
        }
-        return(i);
+       return i;
 #else
-        return(0);
-#endif /* ifdef CONFIG_PCI */
-} /* cy_detect_pci */
-
+       return 0;
+#endif                         /* ifdef CONFIG_PCI */
+}                              /* cy_detect_pci */
 
 /*
  * This routine prints out the appropriate serial driver version number
  * and identifies which options were configured into this driver.
  */
-static inline void
-show_version(void)
+static inline void show_version(void)
 {
-  char *rcsvers, *rcsdate, *tmp;
-    rcsvers = strchr(rcsid, ' '); rcsvers++;
-    tmp = strchr(rcsvers, ' '); *tmp++ = '\0';
-    rcsdate = strchr(tmp, ' '); rcsdate++;
-    tmp = strrchr(rcsdate, ' '); *tmp = '\0';
-    printk("Cyclades driver %s %s\n",
-        rcsvers, rcsdate);
-    printk("        built %s %s\n",
-       __DATE__, __TIME__);
-} /* show_version */
-
-static int 
+       printk("Cyclades driver " CY_VERSION "\n");
+       printk("        built %s %s\n", __DATE__, __TIME__);
+}                              /* show_version */
+
+static int
 cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
-                      int *eof, void *data)
+               int *eof, void *data)
 {
-    struct cyclades_port  *info;
-    int i;
-    int len=0;
-    off_t begin=0;
-    off_t pos=0;
-    int size;
-    __u32 cur_jifs = jiffies;
-
-    size = sprintf(buf, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   IdleIn  Overruns  Ldisc\n");
-
-    pos += size;
-    len += size;
-
-    /* Output one line for each known port */
-    for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
-       info = &cy_port[i];
-
-       if (info->count)
-           size = sprintf(buf+len,
-                       "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n",
-                       info->line,
-                       JIFFIES_DIFF(info->idle_stats.in_use, cur_jifs) / HZ,
-                       info->idle_stats.xmit_bytes,
-                       JIFFIES_DIFF(info->idle_stats.xmit_idle, cur_jifs) / HZ,
-                       info->idle_stats.recv_bytes,
-                       JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ,
-                       info->idle_stats.overruns,
-                       (long) info->tty->ldisc.num);
-       else
-           size = sprintf(buf+len,
-                       "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n",
-                       info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+       struct cyclades_port *info;
+       int i;
+       int len = 0;
+       off_t begin = 0;
+       off_t pos = 0;
+       int size;
+       __u32 cur_jifs = jiffies;
+
+       size = sprintf(buf, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
+                       "IdleIn  Overruns  Ldisc\n");
+
+       pos += size;
        len += size;
-       pos = begin + len;
 
-       if (pos < offset) {
-           len   = 0;
-           begin = pos;
+       /* Output one line for each known port */
+       for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
+               info = &cy_port[i];
+
+               if (info->count)
+                       size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
+                               "%8lu %9lu %6ld\n", info->line,
+                               (cur_jifs - info->idle_stats.in_use) / HZ,
+                               info->idle_stats.xmit_bytes,
+                               (cur_jifs - info->idle_stats.xmit_idle) / HZ,
+                               info->idle_stats.recv_bytes,
+                               (cur_jifs - info->idle_stats.recv_idle) / HZ,
+                               info->idle_stats.overruns,
+                               (long)info->tty->ldisc.num);
+               else
+                       size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
+                               "%8lu %9lu %6ld\n",
+                               info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+               len += size;
+               pos = begin + len;
+
+               if (pos < offset) {
+                       len = 0;
+                       begin = pos;
+               }
+               if (pos > offset + length)
+                       goto done;
        }
-       if (pos > offset + length)
-           goto done;
-    }
-    *eof = 1;
+       *eof = 1;
 done:
-    *start = buf + (offset - begin);   /* Start of wanted data */
-    len -= (offset - begin);           /* Start slop */
-    if (len > length)
-       len = length;                   /* Ending slop */
-    if (len < 0)
-       len = 0;
-    return len;
+       *start = buf + (offset - begin);        /* Start of wanted data */
+       len -= (offset - begin);        /* Start slop */
+       if (len > length)
+               len = length;   /* Ending slop */
+       if (len < 0)
+               len = 0;
+       return len;
 }
 
 /* The serial driver boot-time initialization code!
@@ -5184,290 +5294,288 @@ done:
  */
 
 static const struct tty_operations cy_ops = {
-    .open = cy_open,
-    .close = cy_close,
-    .write = cy_write,
-    .put_char = cy_put_char,
-    .flush_chars = cy_flush_chars,
-    .write_room = cy_write_room,
-    .chars_in_buffer = cy_chars_in_buffer,
-    .flush_buffer = cy_flush_buffer,
-    .ioctl = cy_ioctl,
-    .throttle = cy_throttle,
-    .unthrottle = cy_unthrottle,
-    .set_termios = cy_set_termios,
-    .stop = cy_stop,
-    .start = cy_start,
-    .hangup = cy_hangup,
-    .break_ctl = cy_break,
-    .wait_until_sent = cy_wait_until_sent,
-    .read_proc = cyclades_get_proc_info,
-    .tiocmget = cy_tiocmget,
-    .tiocmset = cy_tiocmset,
+       .open = cy_open,
+       .close = cy_close,
+       .write = cy_write,
+       .put_char = cy_put_char,
+       .flush_chars = cy_flush_chars,
+       .write_room = cy_write_room,
+       .chars_in_buffer = cy_chars_in_buffer,
+       .flush_buffer = cy_flush_buffer,
+       .ioctl = cy_ioctl,
+       .throttle = cy_throttle,
+       .unthrottle = cy_unthrottle,
+       .set_termios = cy_set_termios,
+       .stop = cy_stop,
+       .start = cy_start,
+       .hangup = cy_hangup,
+       .break_ctl = cy_break,
+       .wait_until_sent = cy_wait_until_sent,
+       .read_proc = cyclades_get_proc_info,
+       .tiocmget = cy_tiocmget,
+       .tiocmset = cy_tiocmset,
 };
 
-static int __init
-cy_init(void)
+static int __init cy_init(void)
 {
-  struct cyclades_port  *info;
-  struct cyclades_card *cinfo;
-  int number_z_boards = 0;
-  int board,port,i,index;
-  unsigned long mailbox;
-  unsigned short chip_number;
-  int nports;
-
-    cy_serial_driver = alloc_tty_driver(NR_PORTS);
-    if (!cy_serial_driver)
-       return -ENOMEM;
-    show_version();
-
-    /* Initialize the tty_driver structure */
-    
-    cy_serial_driver->owner = THIS_MODULE;
-    cy_serial_driver->driver_name = "cyclades";
-    cy_serial_driver->name = "ttyC";
-    cy_serial_driver->major = CYCLADES_MAJOR;
-    cy_serial_driver->minor_start = 0;
-    cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-    cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-    cy_serial_driver->init_termios = tty_std_termios;
-    cy_serial_driver->init_termios.c_cflag =
-            B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-    tty_set_operations(cy_serial_driver, &cy_ops);
-
-    if (tty_register_driver(cy_serial_driver))
-            panic("Couldn't register Cyclades serial driver\n");
-
-    for (i = 0; i < NR_CARDS; i++) {
-            /* base_addr=0 indicates board not found */
-            cy_card[i].base_addr = NULL;
-    }
-
-    /* the code below is responsible to find the boards. Each different
-       type of board has its own detection routine. If a board is found,
-       the next cy_card structure available is set by the detection
-       routine. These functions are responsible for checking the
-       availability of cy_card and cy_port data structures and updating
-       the cy_next_channel. */
-
-    /* look for isa boards */
-    cy_isa_nboard = cy_detect_isa();
-
-    /* look for pci boards */
-    cy_pci_nboard = cy_detect_pci();
-
-    cy_nboard = cy_isa_nboard + cy_pci_nboard;
-
-    /* invalidate remaining cy_card structures */
-    for (i = 0 ; i < NR_CARDS ; i++) {
-        if (cy_card[i].base_addr == 0) {
-                cy_card[i].first_line = -1;
-                cy_card[i].ctl_addr = NULL;
-                cy_card[i].irq = 0;
-                cy_card[i].bus_index = 0;
-                cy_card[i].first_line = 0;
-                cy_card[i].num_chips = 0;
-        }
-    }
-    /* invalidate remaining cy_port structures */
-    for (i = cy_next_channel ; i < NR_PORTS ; i++) {
-        cy_port[i].line = -1;
-        cy_port[i].magic = -1;
-    }
-
-    /* initialize per-port data structures for each valid board found */
-    for (board = 0 ; board < cy_nboard ; board++) {
-            cinfo = &cy_card[board];
-            if (cinfo->num_chips == -1) { /* Cyclades-Z */
-               number_z_boards++;
-               mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
-                            cy_card[board].ctl_addr)->mail_box_0);
-               nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
-               cinfo->intr_enabled = 0;
-               cinfo->nports = 0; /* Will be correctly set later, after 
-                                     Z FW is loaded */
-               spin_lock_init(&cinfo->card_lock);
-                for (port = cinfo->first_line ;
-                     port < cinfo->first_line + nports;
-                     port++)
-                {
-                    info = &cy_port[port];
-                    info->magic = CYCLADES_MAGIC;
-                    info->type = PORT_STARTECH;
-                    info->card = board;
-                    info->line = port;
-                   info->chip_rev = 0;
-                    info->flags = STD_COM_FLAGS;
-                    info->tty = NULL;
-                   if (mailbox == ZO_V1)
-                       info->xmit_fifo_size = CYZ_FIFO_SIZE;
-                   else
-                       info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
-                    info->cor1 = 0;
-                    info->cor2 = 0;
-                    info->cor3 = 0;
-                    info->cor4 = 0;
-                    info->cor5 = 0;
-                    info->tbpr = 0;
-                    info->tco = 0;
-                    info->rbpr = 0;
-                    info->rco = 0;
-                   info->custom_divisor = 0;
-                    info->close_delay = 5*HZ/10;
-                   info->closing_wait = CLOSING_WAIT_DELAY;
-                   info->icount.cts = info->icount.dsr = 
-                       info->icount.rng = info->icount.dcd = 0;
-                   info->icount.rx = info->icount.tx = 0;
-                   info->icount.frame = info->icount.parity = 0;
-                   info->icount.overrun = info->icount.brk = 0;
-                    info->x_char = 0;
-                    info->event = 0;
-                    info->count = 0;
-                    info->blocked_open = 0;
-                    info->default_threshold = 0;
-                    info->default_timeout = 0;
-                   INIT_WORK(&info->tqueue, do_softint, info);
-                   init_waitqueue_head(&info->open_wait);
-                   init_waitqueue_head(&info->close_wait);
-                   init_waitqueue_head(&info->shutdown_wait);
-                   init_waitqueue_head(&info->delta_msr_wait);
-                    /* info->session */
-                    /* info->pgrp */
-                    info->read_status_mask = 0;
-                    /* info->timeout */
-                   /* Bentson's vars */
-                    info->jiffies[0] = 0;
-                    info->jiffies[1] = 0;
-                    info->jiffies[2] = 0;
-                    info->rflush_count = 0;
+       struct cyclades_port *info;
+       struct cyclades_card *cinfo;
+       int number_z_boards = 0;
+       int board, port, i, index;
+       unsigned long mailbox;
+       unsigned short chip_number;
+       int nports;
+
+       cy_serial_driver = alloc_tty_driver(NR_PORTS);
+       if (!cy_serial_driver)
+               return -ENOMEM;
+       show_version();
+
+       /* Initialize the tty_driver structure */
+
+       cy_serial_driver->owner = THIS_MODULE;
+       cy_serial_driver->driver_name = "cyclades";
+       cy_serial_driver->name = "ttyC";
+       cy_serial_driver->major = CYCLADES_MAJOR;
+       cy_serial_driver->minor_start = 0;
+       cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+       cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+       cy_serial_driver->init_termios = tty_std_termios;
+       cy_serial_driver->init_termios.c_cflag =
+           B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+       tty_set_operations(cy_serial_driver, &cy_ops);
+
+       if (tty_register_driver(cy_serial_driver))
+               panic("Couldn't register Cyclades serial driver\n");
+
+       for (i = 0; i < NR_CARDS; i++) {
+               /* base_addr=0 indicates board not found */
+               cy_card[i].base_addr = NULL;
+       }
+
+       /* the code below is responsible to find the boards. Each different
+          type of board has its own detection routine. If a board is found,
+          the next cy_card structure available is set by the detection
+          routine. These functions are responsible for checking the
+          availability of cy_card and cy_port data structures and updating
+          the cy_next_channel. */
+
+       /* look for isa boards */
+       cy_isa_nboard = cy_detect_isa();
+
+       /* look for pci boards */
+       cy_pci_nboard = cy_detect_pci();
+
+       cy_nboard = cy_isa_nboard + cy_pci_nboard;
+
+       /* invalidate remaining cy_card structures */
+       for (i = 0; i < NR_CARDS; i++) {
+               if (cy_card[i].base_addr == 0) {
+                       cy_card[i].first_line = -1;
+                       cy_card[i].ctl_addr = NULL;
+                       cy_card[i].irq = 0;
+                       cy_card[i].bus_index = 0;
+                       cy_card[i].first_line = 0;
+                       cy_card[i].num_chips = 0;
+               }
+       }
+       /* invalidate remaining cy_port structures */
+       for (i = cy_next_channel; i < NR_PORTS; i++) {
+               cy_port[i].line = -1;
+               cy_port[i].magic = -1;
+       }
+
+       /* initialize per-port data structures for each valid board found */
+       for (board = 0; board < cy_nboard; board++) {
+               cinfo = &cy_card[board];
+               if (cinfo->num_chips == -1) {   /* Cyclades-Z */
+                       number_z_boards++;
+                       mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
+                                            cy_card[board].ctl_addr)->
+                                          mail_box_0);
+                       nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
+                       cinfo->intr_enabled = 0;
+                       cinfo->nports = 0;      /* Will be correctly set later, after 
+                                                  Z FW is loaded */
+                       spin_lock_init(&cinfo->card_lock);
+                       for (port = cinfo->first_line;
+                            port < cinfo->first_line + nports; port++) {
+                               info = &cy_port[port];
+                               info->magic = CYCLADES_MAGIC;
+                               info->type = PORT_STARTECH;
+                               info->card = board;
+                               info->line = port;
+                               info->chip_rev = 0;
+                               info->flags = STD_COM_FLAGS;
+                               info->tty = NULL;
+                               if (mailbox == ZO_V1)
+                                       info->xmit_fifo_size = CYZ_FIFO_SIZE;
+                               else
+                                       info->xmit_fifo_size =
+                                           4 * CYZ_FIFO_SIZE;
+                               info->cor1 = 0;
+                               info->cor2 = 0;
+                               info->cor3 = 0;
+                               info->cor4 = 0;
+                               info->cor5 = 0;
+                               info->tbpr = 0;
+                               info->tco = 0;
+                               info->rbpr = 0;
+                               info->rco = 0;
+                               info->custom_divisor = 0;
+                               info->close_delay = 5 * HZ / 10;
+                               info->closing_wait = CLOSING_WAIT_DELAY;
+                               info->icount.cts = info->icount.dsr =
+                                   info->icount.rng = info->icount.dcd = 0;
+                               info->icount.rx = info->icount.tx = 0;
+                               info->icount.frame = info->icount.parity = 0;
+                               info->icount.overrun = info->icount.brk = 0;
+                               info->x_char = 0;
+                               info->event = 0;
+                               info->count = 0;
+                               info->blocked_open = 0;
+                               info->default_threshold = 0;
+                               info->default_timeout = 0;
+                               INIT_WORK(&info->tqueue, do_softint);
+                               init_waitqueue_head(&info->open_wait);
+                               init_waitqueue_head(&info->close_wait);
+                               init_waitqueue_head(&info->shutdown_wait);
+                               init_waitqueue_head(&info->delta_msr_wait);
+                               /* info->session */
+                               /* info->pgrp */
+                               info->read_status_mask = 0;
+                               /* info->timeout */
+                               /* Bentson's vars */
+                               info->jiffies[0] = 0;
+                               info->jiffies[1] = 0;
+                               info->jiffies[2] = 0;
+                               info->rflush_count = 0;
 #ifdef CONFIG_CYZ_INTR
-                   init_timer(&cyz_rx_full_timer[port]);
-                   cyz_rx_full_timer[port].function = NULL;
+                               init_timer(&cyz_rx_full_timer[port]);
+                               cyz_rx_full_timer[port].function = NULL;
 #endif
-                }
-                continue;
-            }else{ /* Cyclom-Y of some kind*/
-                index = cinfo->bus_index;
-               spin_lock_init(&cinfo->card_lock);
-               cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
-                for (port = cinfo->first_line ;
-                     port < cinfo->first_line + cinfo->nports ;
-                     port++)
-                {
-                    info = &cy_port[port];
-                    info->magic = CYCLADES_MAGIC;
-                    info->type = PORT_CIRRUS;
-                    info->card = board;
-                    info->line = port;
-                    info->flags = STD_COM_FLAGS;
-                    info->tty = NULL;
-                    info->xmit_fifo_size = CyMAX_CHAR_FIFO;
-                    info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS;
-                    info->cor2 = CyETC;
-                    info->cor3 = 0x08; /* _very_ small rcv threshold */
-                    info->cor4 = 0;
-                    info->cor5 = 0;
-                   info->custom_divisor = 0;
-                    info->close_delay = 5*HZ/10;
-                   info->closing_wait = CLOSING_WAIT_DELAY;
-                   info->icount.cts = info->icount.dsr = 
-                       info->icount.rng = info->icount.dcd = 0;
-                   info->icount.rx = info->icount.tx = 0;
-                   info->icount.frame = info->icount.parity = 0;
-                   info->icount.overrun = info->icount.brk = 0;
-                   chip_number = (port - cinfo->first_line) / 4;
-                   if ((info->chip_rev =
-                        cy_readb(cinfo->base_addr +
-                                 (cy_chip_offset[chip_number]<<index) +
-                                 (CyGFRCR<<index))) >= CD1400_REV_J) {
-                        /* It is a CD1400 rev. J or later */
-                        info->tbpr = baud_bpr_60[13]; /* Tx BPR */
-                        info->tco = baud_co_60[13]; /* Tx CO */
-                        info->rbpr = baud_bpr_60[13]; /* Rx BPR */
-                        info->rco = baud_co_60[13]; /* Rx CO */
-                        info->rflow = 0;
-                        info->rtsdtr_inv = 1;
-                    } else {
-                        info->tbpr = baud_bpr_25[13]; /* Tx BPR */
-                        info->tco = baud_co_25[13]; /* Tx CO */
-                        info->rbpr = baud_bpr_25[13]; /* Rx BPR */
-                        info->rco = baud_co_25[13]; /* Rx CO */
-                        info->rflow = 0;
-                        info->rtsdtr_inv = 0;
-                    }
-                    info->x_char = 0;
-                    info->event = 0;
-                    info->count = 0;
-                    info->blocked_open = 0;
-                    info->default_threshold = 0;
-                    info->default_timeout = 0;
-                   INIT_WORK(&info->tqueue, do_softint, info);
-                   init_waitqueue_head(&info->open_wait);
-                   init_waitqueue_head(&info->close_wait);
-                   init_waitqueue_head(&info->shutdown_wait);
-                   init_waitqueue_head(&info->delta_msr_wait);
-                    /* info->session */
-                    /* info->pgrp */
-                    info->read_status_mask =
-                                 CyTIMEOUT| CySPECHAR| CyBREAK
-                                  | CyPARITY| CyFRAME| CyOVERRUN;
-                    /* info->timeout */
-                }
-            }
-    }
+                       }
+                       continue;
+               } else {        /* Cyclom-Y of some kind */
+                       index = cinfo->bus_index;
+                       spin_lock_init(&cinfo->card_lock);
+                       cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
+                       for (port = cinfo->first_line;
+                            port < cinfo->first_line + cinfo->nports; port++) {
+                               info = &cy_port[port];
+                               info->magic = CYCLADES_MAGIC;
+                               info->type = PORT_CIRRUS;
+                               info->card = board;
+                               info->line = port;
+                               info->flags = STD_COM_FLAGS;
+                               info->tty = NULL;
+                               info->xmit_fifo_size = CyMAX_CHAR_FIFO;
+                               info->cor1 =
+                                   CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
+                               info->cor2 = CyETC;
+                               info->cor3 = 0x08;      /* _very_ small rcv threshold */
+                               info->cor4 = 0;
+                               info->cor5 = 0;
+                               info->custom_divisor = 0;
+                               info->close_delay = 5 * HZ / 10;
+                               info->closing_wait = CLOSING_WAIT_DELAY;
+                               info->icount.cts = info->icount.dsr =
+                                   info->icount.rng = info->icount.dcd = 0;
+                               info->icount.rx = info->icount.tx = 0;
+                               info->icount.frame = info->icount.parity = 0;
+                               info->icount.overrun = info->icount.brk = 0;
+                               chip_number = (port - cinfo->first_line) / 4;
+                               if ((info->chip_rev =
+                                    cy_readb(cinfo->base_addr +
+                                             (cy_chip_offset[chip_number] <<
+                                              index) + (CyGFRCR << index))) >=
+                                   CD1400_REV_J) {
+                                       /* It is a CD1400 rev. J or later */
+                                       info->tbpr = baud_bpr_60[13];   /* Tx BPR */
+                                       info->tco = baud_co_60[13];     /* Tx CO */
+                                       info->rbpr = baud_bpr_60[13];   /* Rx BPR */
+                                       info->rco = baud_co_60[13];     /* Rx CO */
+                                       info->rflow = 0;
+                                       info->rtsdtr_inv = 1;
+                               } else {
+                                       info->tbpr = baud_bpr_25[13];   /* Tx BPR */
+                                       info->tco = baud_co_25[13];     /* Tx CO */
+                                       info->rbpr = baud_bpr_25[13];   /* Rx BPR */
+                                       info->rco = baud_co_25[13];     /* Rx CO */
+                                       info->rflow = 0;
+                                       info->rtsdtr_inv = 0;
+                               }
+                               info->x_char = 0;
+                               info->event = 0;
+                               info->count = 0;
+                               info->blocked_open = 0;
+                               info->default_threshold = 0;
+                               info->default_timeout = 0;
+                               INIT_WORK(&info->tqueue, do_softint);
+                               init_waitqueue_head(&info->open_wait);
+                               init_waitqueue_head(&info->close_wait);
+                               init_waitqueue_head(&info->shutdown_wait);
+                               init_waitqueue_head(&info->delta_msr_wait);
+                               /* info->session */
+                               /* info->pgrp */
+                               info->read_status_mask =
+                                   CyTIMEOUT | CySPECHAR | CyBREAK
+                                   | CyPARITY | CyFRAME | CyOVERRUN;
+                               /* info->timeout */
+                       }
+               }
+       }
 
 #ifndef CONFIG_CYZ_INTR
-    if (number_z_boards && !cyz_timeron){
-       cyz_timeron++;
-       cyz_timerlist.expires = jiffies + 1;
-       add_timer(&cyz_timerlist);
+       if (number_z_boards && !cyz_timeron) {
+               cyz_timeron++;
+               cyz_timerlist.expires = jiffies + 1;
+               add_timer(&cyz_timerlist);
 #ifdef CY_PCI_DEBUG
-       printk("Cyclades-Z polling initialized\n");
+               printk("Cyclades-Z polling initialized\n");
 #endif
-    }
-#endif /* CONFIG_CYZ_INTR */
+       }
+#endif                         /* CONFIG_CYZ_INTR */
+
+       return 0;
 
-    return 0;
-    
-} /* cy_init */
+}                              /* cy_init */
 
-static void __exit
-cy_cleanup_module(void)
+static void __exit cy_cleanup_module(void)
 {
-    int i, e1;
+       int i, e1;
 
 #ifndef CONFIG_CYZ_INTR
-    if (cyz_timeron){
-       cyz_timeron = 0;
-       del_timer(&cyz_timerlist);
-    }
+       if (cyz_timeron){
+               cyz_timeron = 0;
+               del_timer(&cyz_timerlist);
+       }
 #endif /* CONFIG_CYZ_INTR */
 
-    if ((e1 = tty_unregister_driver(cy_serial_driver)))
-            printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
-               e1);
+       if ((e1 = tty_unregister_driver(cy_serial_driver)))
+               printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
+                       e1);
 
-    put_tty_driver(cy_serial_driver);
+       put_tty_driver(cy_serial_driver);
 
-    for (i = 0; i < NR_CARDS; i++) {
-        if (cy_card[i].base_addr) {
-           iounmap(cy_card[i].base_addr);
-           if (cy_card[i].ctl_addr)
-               iounmap(cy_card[i].ctl_addr);
-           if (cy_card[i].irq
+       for (i = 0; i < NR_CARDS; i++) {
+               if (cy_card[i].base_addr) {
+                       iounmap(cy_card[i].base_addr);
+                       if (cy_card[i].ctl_addr)
+                               iounmap(cy_card[i].ctl_addr);
+                       if (cy_card[i].irq
 #ifndef CONFIG_CYZ_INTR
-               && cy_card[i].num_chips != -1 /* not a Z card */
+                               && cy_card[i].num_chips != -1 /* not a Z card */
 #endif /* CONFIG_CYZ_INTR */
-           )
-               free_irq(cy_card[i].irq, &cy_card[i]);
+                               )
+                               free_irq(cy_card[i].irq, &cy_card[i]);
 #ifdef CONFIG_PCI
-               if (cy_card[i].pdev)
-                       pci_release_regions(cy_card[i].pdev);
+                       if (cy_card[i].pdev)
+                               pci_release_regions(cy_card[i].pdev);
 #endif
-        }
-    }
+               }
+       }
 } /* cy_cleanup_module */
 
 module_init(cy_init);
index 85f404e..8ea2bea 100644 (file)
 extern int zs_init(void);
 #endif
 
-#ifdef CONFIG_DZ
-extern int dz_init(void);
-#endif
-
 #ifdef CONFIG_SERIAL_CONSOLE
 
 #ifdef CONFIG_ZS
 extern void zs_serial_console_init(void);
 #endif
 
-#ifdef CONFIG_DZ
-extern void dz_serial_console_init(void);
-#endif
-
 #endif
 
 /* rs_init - starts up the serial interface -
@@ -46,23 +38,11 @@ extern void dz_serial_console_init(void);
 
 int __init rs_init(void)
 {
-
-#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+#ifdef CONFIG_ZS
     if (IOASIC)
        return zs_init();
-    else
-       return dz_init();
-#else
-
-#ifdef CONFIG_ZS
-    return zs_init();
-#endif
-
-#ifdef CONFIG_DZ
-    return dz_init();
-#endif
-
 #endif
+    return -ENXIO;
 }
 
 __initcall(rs_init);
@@ -76,21 +56,9 @@ __initcall(rs_init);
  */
 static int __init decserial_console_init(void)
 {
-#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+#ifdef CONFIG_ZS
     if (IOASIC)
        zs_serial_console_init();
-    else
-       dz_serial_console_init();
-#else
-
-#ifdef CONFIG_ZS
-    zs_serial_console_init();
-#endif
-
-#ifdef CONFIG_DZ
-    dz_serial_console_init();
-#endif
-
 #endif
     return 0;
 }
index 5642ac4..8db9041 100644 (file)
@@ -116,6 +116,14 @@ typedef struct drm_clip_rect {
        unsigned short y2;
 } drm_clip_rect_t;
 
+/**
+ * Drawable information.
+ */
+typedef struct drm_drawable_info {
+       unsigned int num_rects;
+       drm_clip_rect_t *rects;
+} drm_drawable_info_t;
+
 /**
  * Texture region,
  */
@@ -348,7 +356,8 @@ typedef struct drm_buf_desc {
                _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
                _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
                _DRM_SG_BUFFER = 0x04,  /**< Scatter/gather memory buffer */
-               _DRM_FB_BUFFER = 0x08   /**< Buffer is in frame buffer */
+               _DRM_FB_BUFFER = 0x08,  /**< Buffer is in frame buffer */
+               _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
        } flags;
        unsigned long agp_start; /**<
                                  * Start address of where the AGP buffers are
@@ -443,6 +452,20 @@ typedef struct drm_draw {
        drm_drawable_t handle;
 } drm_draw_t;
 
+/**
+ * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
+ */
+typedef enum {
+       DRM_DRAWABLE_CLIPRECTS,
+} drm_drawable_info_type_t;
+
+typedef struct drm_update_draw {
+       drm_drawable_t handle;
+       unsigned int type;
+       unsigned int num;
+       unsigned long long data;
+} drm_update_draw_t;
+
 /**
  * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
  */
@@ -465,10 +488,14 @@ typedef struct drm_irq_busid {
 typedef enum {
        _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
        _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
+       _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
+       _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
        _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
 } drm_vblank_seq_type_t;
 
-#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
+#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
+                               _DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
        drm_vblank_seq_type_t type;
@@ -623,6 +650,8 @@ typedef struct drm_set_version {
 
 #define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, drm_wait_vblank_t)
 
+#define DRM_IOCTL_UPDATE_DRAW          DRM_IOW(0x3f, drm_update_draw_t)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x79.
index 7690a59..0bbb04f 100644 (file)
@@ -97,6 +97,7 @@
 #define DRIVER_IRQ_VBL     0x100
 #define DRIVER_DMA_QUEUE   0x200
 #define DRIVER_FB_DMA      0x400
+#define DRIVER_IRQ_VBL2    0x800
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -430,7 +431,8 @@ typedef struct drm_device_dma {
        enum {
                _DRM_DMA_USE_AGP = 0x01,
                _DRM_DMA_USE_SG = 0x02,
-               _DRM_DMA_USE_FB = 0x04
+               _DRM_DMA_USE_FB = 0x04,
+               _DRM_DMA_USE_PCI_RO = 0x08
        } flags;
 
 } drm_device_dma_t;
@@ -562,6 +564,7 @@ struct drm_driver {
        void (*kernel_context_switch_unlock) (struct drm_device * dev,
                                              drm_lock_t *lock);
        int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
+       int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
        int (*dri_library_name) (struct drm_device *dev, char *buf);
 
        /**
@@ -708,9 +711,13 @@ typedef struct drm_device {
 
        wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
        atomic_t vbl_received;
+       atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
        spinlock_t vbl_lock;
        drm_vbl_sig_t vbl_sigs;         /**< signal list to send on VBLANK */
+       drm_vbl_sig_t vbl_sigs2;        /**< signals to send on secondary VBLANK */
        unsigned int vbl_pending;
+       spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
+       void (*locked_tasklet_func)(struct drm_device *dev);
 
        /*@} */
        cycles_t ctx_start;
@@ -738,6 +745,15 @@ typedef struct drm_device {
        drm_local_map_t *agp_buffer_map;
        unsigned int agp_buffer_token;
        drm_head_t primary;             /**< primary screen head */
+
+       /** \name Drawable information */
+       /*@{ */
+       spinlock_t drw_lock;
+       unsigned int drw_bitfield_length;
+       u32 *drw_bitfield;
+       unsigned int drw_info_length;
+       drm_drawable_info_t **drw_info;
+       /*@} */
 } drm_device_t;
 
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
@@ -885,6 +901,10 @@ extern int drm_adddraw(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg);
 extern int drm_rmdraw(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg);
+extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
+                      unsigned int cmd, unsigned long arg);
+extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
+                                                 drm_drawable_t id);
 
                                /* Authentication IOCTL support (drm_auth.h) */
 extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -949,6 +969,7 @@ extern int drm_wait_vblank(struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg);
 extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
 extern void drm_vbl_send_signals(drm_device_t * dev);
+extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
 
                                /* AGP/GART support (drm_agpsupport.h) */
 extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
index 6eafff1..9f65f56 100644 (file)
@@ -887,6 +887,9 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
        request->count = entry->buf_count;
        request->size = size;
 
+       if (request->flags & _DRM_PCI_BUFFER_RO)
+               dma->flags = _DRM_DMA_USE_PCI_RO;
+
        atomic_dec(&dev->buf_alloc);
        return 0;
 
@@ -1471,9 +1474,10 @@ int drm_freebufs(struct inode *inode, struct file *filp,
  * \param arg pointer to a drm_buf_map structure.
  * \return zero on success or a negative number on failure.
  *
- * Maps the AGP or SG buffer region with do_mmap(), and copies information
- * about each buffer into user space. The PCI buffers are already mapped on the
- * addbufs_pci() call.
+ * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls do_mmap() with
+ * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
+ * drm_mmap_dma().
  */
 int drm_mapbufs(struct inode *inode, struct file *filp,
                unsigned int cmd, unsigned long arg)
index f4f9db6..3167390 100644 (file)
 
 #define CORE_NAME              "drm"
 #define CORE_DESC              "DRM shared core routines"
-#define CORE_DATE              "20051102"
+#define CORE_DATE              "20060810"
 
 #define DRM_IF_MAJOR   1
-#define DRM_IF_MINOR   2
+#define DRM_IF_MINOR   3
 
 #define CORE_MAJOR     1
-#define CORE_MINOR     0
-#define CORE_PATCHLEVEL 1
+#define CORE_MINOR     1
+#define CORE_PATCHLEVEL 0
index 7857453..de37d5f 100644 (file)
@@ -4,6 +4,7 @@
  *
  * \author Rickard E. (Rik) Faith <faith@valinux.com>
  * \author Gareth Hughes <gareth@valinux.com>
+ * \author Michel Dänzer <michel@tungstengraphics.com>
  */
 
 /*
@@ -11,6 +12,7 @@
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 
 #include "drmP.h"
 
-/** No-op. */
-int drm_adddraw(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+/**
+ * Allocate drawable ID and memory to store information about it.
+ */
+int drm_adddraw(DRM_IOCTL_ARGS)
 {
+       DRM_DEVICE;
+       unsigned long irqflags;
+       int i, j;
+       u32 *bitfield = dev->drw_bitfield;
+       unsigned int bitfield_length = dev->drw_bitfield_length;
+       drm_drawable_info_t **info = dev->drw_info;
+       unsigned int info_length = dev->drw_info_length;
        drm_draw_t draw;
 
-       draw.handle = 0;        /* NOOP */
+       for (i = 0, j = 0; i < bitfield_length; i++) {
+               if (bitfield[i] == ~0)
+                       continue;
+
+               for (; j < 8 * sizeof(*bitfield); j++)
+                       if (!(bitfield[i] & (1 << j)))
+                               goto done;
+       }
+done:
+
+       if (i == bitfield_length) {
+               bitfield_length++;
+
+               bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
+                                    DRM_MEM_BUFS);
+
+               if (!bitfield) {
+                       DRM_ERROR("Failed to allocate new drawable bitfield\n");
+                       return DRM_ERR(ENOMEM);
+               }
+
+               if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
+                       info_length += 8 * sizeof(*bitfield);
+
+                       info = drm_alloc(info_length * sizeof(*info),
+                                        DRM_MEM_BUFS);
+
+                       if (!info) {
+                               DRM_ERROR("Failed to allocate new drawable info"
+                                         " array\n");
+
+                               drm_free(bitfield,
+                                        bitfield_length * sizeof(*bitfield),
+                                        DRM_MEM_BUFS);
+                               return DRM_ERR(ENOMEM);
+                       }
+               }
+
+               bitfield[i] = 0;
+       }
+
+       draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
        DRM_DEBUG("%d\n", draw.handle);
-       if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw)))
-               return -EFAULT;
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+       bitfield[i] |= 1 << j;
+       info[draw.handle - 1] = NULL;
+
+       if (bitfield != dev->drw_bitfield) {
+               memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
+                      sizeof(*bitfield));
+               drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+                        dev->drw_bitfield_length, DRM_MEM_BUFS);
+               dev->drw_bitfield = bitfield;
+               dev->drw_bitfield_length = bitfield_length;
+       }
+
+       if (info != dev->drw_info) {
+               memcpy(info, dev->drw_info, dev->drw_info_length *
+                      sizeof(*info));
+               drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
+                        DRM_MEM_BUFS);
+               dev->drw_info = info;
+               dev->drw_info_length = info_length;
+       }
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+
        return 0;
 }
 
-/** No-op. */
-int drm_rmdraw(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+/**
+ * Free drawable ID and memory to store information about it.
+ */
+int drm_rmdraw(DRM_IOCTL_ARGS)
 {
-       return 0;               /* NOOP */
+       DRM_DEVICE;
+       drm_draw_t draw;
+       int id, idx;
+       unsigned int shift;
+       unsigned long irqflags;
+       u32 *bitfield = dev->drw_bitfield;
+       unsigned int bitfield_length = dev->drw_bitfield_length;
+       drm_drawable_info_t **info = dev->drw_info;
+       unsigned int info_length = dev->drw_info_length;
+
+       DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+                                sizeof(draw));
+
+       id = draw.handle - 1;
+       idx = id / (8 * sizeof(*bitfield));
+       shift = id % (8 * sizeof(*bitfield));
+
+       if (idx < 0 || idx >= bitfield_length ||
+           !(bitfield[idx] & (1 << shift))) {
+               DRM_DEBUG("No such drawable %d\n", draw.handle);
+               return 0;
+       }
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+       bitfield[idx] &= ~(1 << shift);
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       if (info[id]) {
+               drm_free(info[id]->rects, info[id]->num_rects *
+                        sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+               drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
+       }
+
+       /* Can we shrink the arrays? */
+       if (idx == bitfield_length - 1) {
+               while (idx >= 0 && !bitfield[idx])
+                       --idx;
+
+               bitfield_length = idx + 1;
+
+               if (idx != id / (8 * sizeof(*bitfield)))
+                       bitfield = drm_alloc(bitfield_length *
+                                            sizeof(*bitfield), DRM_MEM_BUFS);
+
+               if (!bitfield && bitfield_length) {
+                       bitfield = dev->drw_bitfield;
+                       bitfield_length = dev->drw_bitfield_length;
+               }
+       }
+
+       if (bitfield != dev->drw_bitfield) {
+               info_length = 8 * sizeof(*bitfield) * bitfield_length;
+
+               info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
+
+               if (!info && info_length) {
+                       info = dev->drw_info;
+                       info_length = dev->drw_info_length;
+               }
+
+               spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+               memcpy(bitfield, dev->drw_bitfield, bitfield_length *
+                      sizeof(*bitfield));
+               drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+                        dev->drw_bitfield_length, DRM_MEM_BUFS);
+               dev->drw_bitfield = bitfield;
+               dev->drw_bitfield_length = bitfield_length;
+
+               if (info != dev->drw_info) {
+                       memcpy(info, dev->drw_info, info_length *
+                              sizeof(*info));
+                       drm_free(dev->drw_info, sizeof(*info) *
+                                dev->drw_info_length, DRM_MEM_BUFS);
+                       dev->drw_info = info;
+                       dev->drw_info_length = info_length;
+               }
+
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       }
+
+       DRM_DEBUG("%d\n", draw.handle);
+       return 0;
+}
+
+int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+       DRM_DEVICE;
+       drm_update_draw_t update;
+       unsigned int id, idx, shift;
+       u32 *bitfield = dev->drw_bitfield;
+       unsigned long irqflags, bitfield_length = dev->drw_bitfield_length;
+       drm_drawable_info_t *info;
+       drm_clip_rect_t *rects;
+       int err;
+
+       DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+                                sizeof(update));
+
+       id = update.handle - 1;
+       idx = id / (8 * sizeof(*bitfield));
+       shift = id % (8 * sizeof(*bitfield));
+
+       if (idx < 0 || idx >= bitfield_length ||
+           !(bitfield[idx] & (1 << shift))) {
+               DRM_ERROR("No such drawable %d\n", update.handle);
+               return DRM_ERR(EINVAL);
+       }
+
+       info = dev->drw_info[id];
+
+       if (!info) {
+               info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
+
+               if (!info) {
+                       DRM_ERROR("Failed to allocate drawable info memory\n");
+                       return DRM_ERR(ENOMEM);
+               }
+       }
+
+       switch (update.type) {
+       case DRM_DRAWABLE_CLIPRECTS:
+               if (update.num != info->num_rects) {
+                       rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+                                        DRM_MEM_BUFS);
+               } else
+                       rects = info->rects;
+
+               if (update.num && !rects) {
+                       DRM_ERROR("Failed to allocate cliprect memory\n");
+                       err = DRM_ERR(ENOMEM);
+                       goto error;
+               }
+
+               if (update.num && DRM_COPY_FROM_USER(rects,
+                                                    (drm_clip_rect_t __user *)
+                                                    (unsigned long)update.data,
+                                                    update.num *
+                                                    sizeof(*rects))) {
+                       DRM_ERROR("Failed to copy cliprects from userspace\n");
+                       err = DRM_ERR(EFAULT);
+                       goto error;
+               }
+
+               spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+               if (rects != info->rects) {
+                       drm_free(info->rects, info->num_rects *
+                                sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+               }
+
+               info->rects = rects;
+               info->num_rects = update.num;
+               dev->drw_info[id] = info;
+
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+               DRM_DEBUG("Updated %d cliprects for drawable %d\n",
+                         info->num_rects, id);
+               break;
+       default:
+               DRM_ERROR("Invalid update type %d\n", update.type);
+               return DRM_ERR(EINVAL);
+       }
+
+       return 0;
+
+error:
+       if (!dev->drw_info[id])
+               drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+       else if (rects != dev->drw_info[id]->rects)
+               drm_free(rects, update.num *
+                        sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+
+       return err;
+}
+
+/**
+ * Caller must hold the drawable spinlock!
+ */
+drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
+       u32 *bitfield = dev->drw_bitfield;
+       unsigned int idx, shift;
+
+       id--;
+       idx = id / (8 * sizeof(*bitfield));
+       shift = id % (8 * sizeof(*bitfield));
+
+       if (idx < 0 || idx >= dev->drw_bitfield_length ||
+           !(bitfield[idx] & (1 << shift))) {
+               DRM_DEBUG("No such drawable %d\n", id);
+               return NULL;
+       }
+
+       return dev->drw_info[id];
 }
+EXPORT_SYMBOL(drm_get_drawable_info);
index b366c5b..a70af0d 100644 (file)
@@ -116,6 +116,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 
        [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
+
+       [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 };
 
 #define DRIVER_IOCTL_COUNT     ARRAY_SIZE( drm_ioctls )
@@ -151,6 +153,18 @@ int drm_lastclose(drm_device_t * dev)
        if (dev->irq_enabled)
                drm_irq_uninstall(dev);
 
+       /* Free drawable information memory */
+       for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
+            i++) {
+               drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
+
+               if (info) {
+                       drm_free(info->rects, info->num_rects *
+                                sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+                       drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+               }
+       }
+
        mutex_lock(&dev->struct_mutex);
        del_timer(&dev->timer);
 
index d4f8745..fafeb34 100644 (file)
@@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
                          &version->desc))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_VERSION, (unsigned long)version);
        if (err)
                return err;
@@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
                          &u->unique))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
        if (err)
                return err;
@@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
                          &u->unique))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
 }
 
@@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
        if (__put_user(idx, &map->offset))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_GET_MAP, (unsigned long)map);
        if (err)
                return err;
@@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
            || __put_user(m32.flags, &map->flags))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_ADD_MAP, (unsigned long)map);
        if (err)
                return err;
@@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
        if (__put_user((void *)(unsigned long)handle, &map->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RM_MAP, (unsigned long)map);
 }
 
@@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
        if (__put_user(idx, &client->idx))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_GET_CLIENT, (unsigned long)client);
        if (err)
                return err;
@@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
        if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_GET_STATS, (unsigned long)stats);
        if (err)
                return err;
@@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
            || __put_user(agp_start, &buf->agp_start))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
        if (err)
                return err;
@@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
            || __put_user(b32.high_mark, &buf->high_mark))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
 }
 
@@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
            || __put_user(list, &request->list))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_INFO_BUFS, (unsigned long)request);
        if (err)
                return err;
@@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
            || __put_user(list, &request->list))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_MAP_BUFS, (unsigned long)request);
        if (err)
                return err;
@@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
                          &request->list))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_FREE_BUFS, (unsigned long)request);
 }
 
@@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
                          &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
 }
 
@@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
        if (__put_user(ctx_id, &request->ctx_id))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
        if (err)
                return err;
@@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
                          &res->contexts))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_RES_CTX, (unsigned long)res);
        if (err)
                return err;
@@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
                          &d->request_sizes))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_DMA, (unsigned long)d);
        if (err)
                return err;
@@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
        if (put_user(m32.mode, &mode->mode))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
 }
 
@@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
        if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_AGP_INFO, (unsigned long)info);
        if (err)
                return err;
@@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
            || __put_user(req32.type, &request->type))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
        if (err)
                return err;
@@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
        if (__get_user(req32.handle, &request->handle)
            || __get_user(req32.physical, &request->physical)
            || copy_to_user(argp, &req32, sizeof(req32))) {
-               drm_ioctl(file->f_dentry->d_inode, file,
+               drm_ioctl(file->f_path.dentry->d_inode, file,
                          DRM_IOCTL_AGP_FREE, (unsigned long)request);
                return -EFAULT;
        }
@@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
            || __put_user(handle, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_AGP_FREE, (unsigned long)request);
 }
 
@@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
            || __put_user(req32.offset, &request->offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_AGP_BIND, (unsigned long)request);
 }
 
@@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
            || __put_user(handle, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
 }
 #endif                         /* __OS_HAS_AGP */
@@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
            || __put_user(x, &request->size))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_SG_ALLOC, (unsigned long)request);
        if (err)
                return err;
@@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
            || __put_user(x << PAGE_SHIFT, &request->handle))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_SG_FREE, (unsigned long)request);
 }
 
@@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
            || __put_user(req32.request.signal, &request->request.signal))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
        if (err)
                return err;
@@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return ret;
index 4553a3a..9d00c51 100644 (file)
@@ -121,6 +121,7 @@ static int drm_irq_install(drm_device_t * dev)
                spin_lock_init(&dev->vbl_lock);
 
                INIT_LIST_HEAD(&dev->vbl_sigs.head);
+               INIT_LIST_HEAD(&dev->vbl_sigs2.head);
 
                dev->vbl_pending = 0;
        }
@@ -175,6 +176,8 @@ int drm_irq_uninstall(drm_device_t * dev)
 
        free_irq(dev->irq, dev);
 
+       dev->locked_tasklet_func = NULL;
+
        return 0;
 }
 
@@ -247,10 +250,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        drm_wait_vblank_t vblwait;
        struct timeval now;
        int ret = 0;
-       unsigned int flags;
-
-       if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
-               return -EINVAL;
+       unsigned int flags, seq;
 
        if (!dev->irq)
                return -EINVAL;
@@ -258,9 +258,26 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
                return -EFAULT;
 
-       switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
+       if (vblwait.request.type &
+           ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
+               DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
+                         vblwait.request.type,
+                         (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
+               return -EINVAL;
+       }
+
+       flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+
+       if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
+                                   DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+               return -EINVAL;
+
+       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+                         : &dev->vbl_received);
+
+       switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
-               vblwait.request.sequence += atomic_read(&dev->vbl_received);
+               vblwait.request.sequence += seq;
                vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
        case _DRM_VBLANK_ABSOLUTE:
                break;
@@ -268,26 +285,30 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                return -EINVAL;
        }
 
-       flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+       if ((flags & _DRM_VBLANK_NEXTONMISS) &&
+           (seq - vblwait.request.sequence) <= (1<<23)) {
+               vblwait.request.sequence = seq + 1;
+       }
 
        if (flags & _DRM_VBLANK_SIGNAL) {
                unsigned long irqflags;
+               drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+                                     ? &dev->vbl_sigs2 : &dev->vbl_sigs;
                drm_vbl_sig_t *vbl_sig;
 
-               vblwait.reply.sequence = atomic_read(&dev->vbl_received);
-
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
                /* Check if this task has already scheduled the same signal
                 * for the same vblank sequence number; nothing to be done in
                 * that case
                 */
-               list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) {
+               list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
                        if (vbl_sig->sequence == vblwait.request.sequence
                            && vbl_sig->info.si_signo == vblwait.request.signal
                            && vbl_sig->task == current) {
                                spin_unlock_irqrestore(&dev->vbl_lock,
                                                       irqflags);
+                               vblwait.reply.sequence = seq;
                                goto done;
                        }
                }
@@ -315,11 +336,16 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
-               list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head);
+               list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
 
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+               vblwait.reply.sequence = seq;
        } else {
-               if (dev->driver->vblank_wait)
+               if (flags & _DRM_VBLANK_SECONDARY) {
+                       if (dev->driver->vblank_wait2)
+                               ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence);
+               } else if (dev->driver->vblank_wait)
                        ret =
                            dev->driver->vblank_wait(dev,
                                                     &vblwait.request.sequence);
@@ -347,25 +373,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
  */
 void drm_vbl_send_signals(drm_device_t * dev)
 {
-       struct list_head *list, *tmp;
-       drm_vbl_sig_t *vbl_sig;
-       unsigned int vbl_seq = atomic_read(&dev->vbl_received);
        unsigned long flags;
+       int i;
 
        spin_lock_irqsave(&dev->vbl_lock, flags);
 
-       list_for_each_safe(list, tmp, &dev->vbl_sigs.head) {
-               vbl_sig = list_entry(list, drm_vbl_sig_t, head);
-               if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-                       vbl_sig->info.si_code = vbl_seq;
-                       send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info,
-                                     vbl_sig->task);
+       for (i = 0; i < 2; i++) {
+               struct list_head *list, *tmp;
+               drm_vbl_sig_t *vbl_sig;
+               drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+               unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
+                                                  &dev->vbl_received);
+
+               list_for_each_safe(list, tmp, &vbl_sigs->head) {
+                       vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+                       if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+                               vbl_sig->info.si_code = vbl_seq;
+                               send_sig_info(vbl_sig->info.si_signo,
+                                             &vbl_sig->info, vbl_sig->task);
 
-                       list_del(list);
+                               list_del(list);
 
-                       drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER);
+                               drm_free(vbl_sig, sizeof(*vbl_sig),
+                                        DRM_MEM_DRIVER);
 
-                       dev->vbl_pending--;
+                               dev->vbl_pending--;
+                       }
                }
        }
 
@@ -373,3 +406,77 @@ void drm_vbl_send_signals(drm_device_t * dev)
 }
 
 EXPORT_SYMBOL(drm_vbl_send_signals);
+
+/**
+ * Tasklet wrapper function.
+ *
+ * \param data DRM device in disguise.
+ *
+ * Attempts to grab the HW lock and calls the driver callback on success. On
+ * failure, leave the lock marked as contended so the callback can be called
+ * from drm_unlock().
+ */
+static void drm_locked_tasklet_func(unsigned long data)
+{
+       drm_device_t *dev = (drm_device_t*)data;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (!dev->locked_tasklet_func ||
+           !drm_lock_take(&dev->lock.hw_lock->lock,
+                          DRM_KERNEL_CONTEXT)) {
+               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+               return;
+       }
+
+       dev->lock.lock_time = jiffies;
+       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+
+       dev->locked_tasklet_func(dev);
+
+       drm_lock_free(dev, &dev->lock.hw_lock->lock,
+                     DRM_KERNEL_CONTEXT);
+
+       dev->locked_tasklet_func = NULL;
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+}
+
+/**
+ * Schedule a tasklet to call back a driver hook with the HW lock held.
+ *
+ * \param dev DRM device.
+ * \param func Driver callback.
+ *
+ * This is intended for triggering actions that require the HW lock from an
+ * interrupt handler. The lock will be grabbed ASAP after the interrupt handler
+ * completes. Note that the callback may be called from interrupt or process
+ * context, it must not make any assumptions about this. Also, the HW lock will
+ * be held with the kernel context or any client context.
+ */
+void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+{
+       unsigned long irqflags;
+       static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) ||
+           test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state))
+               return;
+
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (dev->locked_tasklet_func) {
+               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+               return;
+       }
+
+       dev->locked_tasklet_func = func;
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
+       drm_tasklet.data = (unsigned long)dev;
+
+       tasklet_hi_schedule(&drm_tasklet);
+}
+EXPORT_SYMBOL(drm_locked_tasklet);
index f9e4530..116ed0f 100644 (file)
@@ -155,6 +155,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
        drm_lock_t lock;
+       unsigned long irqflags;
 
        if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
                return -EFAULT;
@@ -165,6 +166,16 @@ int drm_unlock(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (dev->locked_tasklet_func) {
+               dev->locked_tasklet_func(dev);
+
+               dev->locked_tasklet_func = NULL;
+       }
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
        atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
 
        /* kernel_context_switch isn't used by any of the x86 drm
index 425c823..19c81d2 100644 (file)
@@ -162,6 +162,7 @@ drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
 
        return 0;
 }
+EXPORT_SYMBOL(drm_sman_set_manager);
 
 static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
                                                 unsigned long owner)
index 7b1d4e8..5fd6dc0 100644 (file)
@@ -60,6 +60,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
        int retcode;
 
        spin_lock_init(&dev->count_lock);
+       spin_lock_init(&dev->drw_lock);
+       spin_lock_init(&dev->tasklet_lock);
        init_timer(&dev->timer);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
index b40ae43..b9cfc07 100644 (file)
@@ -147,14 +147,14 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
        if (address > vma->vm_end)
                return NOPAGE_SIGBUS;   /* Disallow mremap */
        if (!map)
-               return NOPAGE_OOM;      /* Nothing allocated */
+               return NOPAGE_SIGBUS;   /* Nothing allocated */
 
        offset = address - vma->vm_start;
        i = (unsigned long)map->handle + offset;
        page = (map->type == _DRM_CONSISTENT) ?
                virt_to_page((void *)i) : vmalloc_to_page((void *)i);
        if (!page)
-               return NOPAGE_OOM;
+               return NOPAGE_SIGBUS;
        get_page(page);
 
        DRM_DEBUG("shm_nopage 0x%lx\n", address);
@@ -272,7 +272,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
        if (address > vma->vm_end)
                return NOPAGE_SIGBUS;   /* Disallow mremap */
        if (!dma->pagelist)
-               return NOPAGE_OOM;      /* Nothing allocated */
+               return NOPAGE_SIGBUS;   /* Nothing allocated */
 
        offset = address - vma->vm_start;       /* vm_[pg]off[set] should be 0 */
        page_nr = offset >> PAGE_SHIFT;
@@ -310,7 +310,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
        if (address > vma->vm_end)
                return NOPAGE_SIGBUS;   /* Disallow mremap */
        if (!entry->pagelist)
-               return NOPAGE_OOM;      /* Nothing allocated */
+               return NOPAGE_SIGBUS;   /* Nothing allocated */
 
        offset = address - vma->vm_start;
        map_offset = map->offset - (unsigned long)dev->sg->virtual;
@@ -473,6 +473,22 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        }
        unlock_kernel();
 
+       if (!capable(CAP_SYS_ADMIN) &&
+           (dma->flags & _DRM_DMA_USE_PCI_RO)) {
+               vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+#if defined(__i386__) || defined(__x86_64__)
+               pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+               /* Ye gads this is ugly.  With more thought
+                  we could move this up higher and use
+                  `protection_map' instead.  */
+               vma->vm_page_prot =
+                   __pgprot(pte_val
+                            (pte_wrprotect
+                             (__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+       }
+
        vma->vm_ops = &drm_vm_dma_ops;
 
        vma->vm_flags |= VM_RESERVED;   /* Don't swap */
index fb7913f..9354ce3 100644 (file)
@@ -162,6 +162,7 @@ static int i915_initialize(drm_device_t * dev,
 
        dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
 
+       dev_priv->cpp = init->cpp;
        dev_priv->back_offset = init->back_offset;
        dev_priv->front_offset = init->front_offset;
        dev_priv->current_page = 0;
@@ -782,6 +783,7 @@ drm_ioctl_desc_t i915_ioctls[] = {
        [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
        [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
        [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
+       [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 6af83e6..96a4688 100644 (file)
@@ -104,6 +104,15 @@ typedef struct _drm_i915_sarea {
        unsigned int depth_tiled;
        unsigned int rotated_tiled;
        unsigned int rotated2_tiled;
+
+       int pipeA_x;
+       int pipeA_y;
+       int pipeA_w;
+       int pipeA_h;
+       int pipeB_x;
+       int pipeB_y;
+       int pipeB_w;
+       int pipeB_h;
 } drm_i915_sarea_t;
 
 /* Flags for perf_boxes
@@ -132,6 +141,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_DESTROY_HEAP  0x0c
 #define DRM_I915_SET_VBLANK_PIPE       0x0d
 #define DRM_I915_GET_VBLANK_PIPE       0x0e
+#define DRM_I915_VBLANK_SWAP   0x0f
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -148,6 +158,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_DESTROY_HEAP    DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
 #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+#define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -243,4 +254,12 @@ typedef struct drm_i915_vblank_pipe {
        int pipe;
 } drm_i915_vblank_pipe_t;
 
+/* Schedule buffer swap at given vertical blank:
+ */
+typedef struct drm_i915_vblank_swap {
+       drm_drawable_t drawable;
+       drm_vblank_seq_type_t seqtype;
+       unsigned int sequence;
+} drm_i915_vblank_swap_t;
+
 #endif                         /* _I915_DRM_H_ */
index 8e2e609..85bcc27 100644 (file)
@@ -44,12 +44,14 @@ static struct drm_driver driver = {
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+           DRIVER_IRQ_VBL2,
        .load = i915_driver_load,
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
        .device_is_agp = i915_driver_device_is_agp,
        .vblank_wait = i915_driver_vblank_wait,
+       .vblank_wait2 = i915_driver_vblank_wait2,
        .irq_preinstall = i915_driver_irq_preinstall,
        .irq_postinstall = i915_driver_irq_postinstall,
        .irq_uninstall = i915_driver_irq_uninstall,
index fdc2bf1..93cdcfe 100644 (file)
  * 1.3: Add vblank support
  * 1.4: Fix cmdbuffer path, add heap destroy
  * 1.5: Add vblank pipe configuration
+ * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
+ *      - Support vertical blank on secondary display pipe
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           5
+#define DRIVER_MINOR           6
 #define DRIVER_PATCHLEVEL      0
 
 typedef struct _drm_i915_ring_buffer {
@@ -71,6 +73,13 @@ struct mem_block {
        DRMFILE filp;           /* 0: free, -1: heap, other: real files */
 };
 
+typedef struct _drm_i915_vbl_swap {
+       struct list_head head;
+       drm_drawable_t drw_id;
+       unsigned int pipe;
+       unsigned int sequence;
+} drm_i915_vbl_swap_t;
+
 typedef struct drm_i915_private {
        drm_local_map_t *sarea;
        drm_local_map_t *mmio_map;
@@ -83,6 +92,7 @@ typedef struct drm_i915_private {
        dma_addr_t dma_status_page;
        unsigned long counter;
 
+       unsigned int cpp;
        int back_offset;
        int front_offset;
        int current_page;
@@ -98,6 +108,10 @@ typedef struct drm_i915_private {
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
+
+       spinlock_t swaps_lock;
+       drm_i915_vbl_swap_t vbl_swaps;
+       unsigned int swaps_pending;
 } drm_i915_private_t;
 
 extern drm_ioctl_desc_t i915_ioctls[];
@@ -117,12 +131,14 @@ extern int i915_irq_emit(DRM_IOCTL_ARGS);
 extern int i915_irq_wait(DRM_IOCTL_ARGS);
 
 extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(drm_device_t * dev);
 extern void i915_driver_irq_postinstall(drm_device_t * dev);
 extern void i915_driver_irq_uninstall(drm_device_t * dev);
 extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
 extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
+extern int i915_vblank_swap(DRM_IOCTL_ARGS);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(DRM_IOCTL_ARGS);
@@ -256,6 +272,10 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 
 #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
 
+#define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+
 #define MI_BATCH_BUFFER        ((0x30<<23)|1)
 #define MI_BATCH_BUFFER_START  (0x31<<23)
 #define MI_BATCH_BUFFER_END    (0xA<<23)
index 296248c..1fe68a2 100644 (file)
@@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
                          &batchbuffer->cliprects))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_I915_BATCHBUFFER,
                         (unsigned long)batchbuffer);
 }
@@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
                          &cmdbuffer->cliprects))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
 }
 
@@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
                          &request->irq_seq))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
 }
 typedef struct drm_i915_getparam32 {
@@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
                          &request->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
 }
 
@@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
                          &request->region_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_I915_ALLOC, (unsigned long)request);
 }
 
@@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return ret;
index 0d4a162..e5463b1 100644 (file)
 
 #define MAX_NOPID ((u32)~0)
 
+/**
+ * Emit blits for scheduled buffer swaps.
+ *
+ * This function will be called with the HW lock held.
+ */
+static void i915_vblank_tasklet(drm_device_t *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+       struct list_head *list, *tmp;
+
+       DRM_DEBUG("\n");
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+               drm_i915_vbl_swap_t *vbl_swap =
+                       list_entry(list, drm_i915_vbl_swap_t, head);
+               atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 :
+                       &dev->vbl_received;
+
+               if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) {
+                       drm_drawable_info_t *drw;
+
+                       spin_unlock(&dev_priv->swaps_lock);
+
+                       spin_lock(&dev->drw_lock);
+
+                       drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
+                               
+                       if (drw) {
+                               int i, num_rects = drw->num_rects;
+                               drm_clip_rect_t *rect = drw->rects;
+                               drm_i915_sarea_t *sarea_priv =
+                                   dev_priv->sarea_priv;
+                               u32 cpp = dev_priv->cpp;
+                               u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+                                                       XY_SRC_COPY_BLT_WRITE_ALPHA |
+                                                       XY_SRC_COPY_BLT_WRITE_RGB)
+                                                    : XY_SRC_COPY_BLT_CMD;
+                               u32 pitchropcpp = (sarea_priv->pitch * cpp) |
+                                                 (0xcc << 16) | (cpp << 23) |
+                                                 (1 << 24);
+                               RING_LOCALS;
+
+                               i915_kernel_lost_context(dev);
+
+                               BEGIN_LP_RING(6);
+
+                               OUT_RING(GFX_OP_DRAWRECT_INFO);
+                               OUT_RING(0);
+                               OUT_RING(0);
+                               OUT_RING(sarea_priv->width |
+                                        sarea_priv->height << 16);
+                               OUT_RING(sarea_priv->width |
+                                        sarea_priv->height << 16);
+                               OUT_RING(0);
+
+                               ADVANCE_LP_RING();
+
+                               sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+                               for (i = 0; i < num_rects; i++, rect++) {
+                                       BEGIN_LP_RING(8);
+
+                                       OUT_RING(cmd);
+                                       OUT_RING(pitchropcpp);
+                                       OUT_RING((rect->y1 << 16) | rect->x1);
+                                       OUT_RING((rect->y2 << 16) | rect->x2);
+                                       OUT_RING(sarea_priv->front_offset);
+                                       OUT_RING((rect->y1 << 16) | rect->x1);
+                                       OUT_RING(pitchropcpp & 0xffff);
+                                       OUT_RING(sarea_priv->back_offset);
+
+                                       ADVANCE_LP_RING();
+                               }
+                       }
+
+                       spin_unlock(&dev->drw_lock);
+
+                       spin_lock(&dev_priv->swaps_lock);
+
+                       list_del(list);
+
+                       drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+
+                       dev_priv->swaps_pending--;
+               }
+       }
+
+       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        drm_device_t *dev = (drm_device_t *) arg;
@@ -60,9 +153,26 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                DRM_WAKEUP(&dev_priv->irq_queue);
 
        if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-               atomic_inc(&dev->vbl_received);
+               int vblank_pipe = dev_priv->vblank_pipe;
+
+               if ((vblank_pipe &
+                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+                       if (temp & VSYNC_PIPEA_FLAG)
+                               atomic_inc(&dev->vbl_received);
+                       if (temp & VSYNC_PIPEB_FLAG)
+                               atomic_inc(&dev->vbl_received2);
+               } else if (((temp & VSYNC_PIPEA_FLAG) &&
+                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+                          ((temp & VSYNC_PIPEB_FLAG) &&
+                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+                       atomic_inc(&dev->vbl_received);
+
                DRM_WAKEUP(&dev->vbl_queue);
                drm_vbl_send_signals(dev);
+
+               if (dev_priv->swaps_pending > 0)
+                       drm_locked_tasklet(dev, i915_vblank_tasklet);
        }
 
        return IRQ_HANDLED;
@@ -120,7 +230,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
        return ret;
 }
 
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+                                     atomic_t *counter)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        unsigned int cur_vblank;
@@ -132,7 +243,7 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
        }
 
        DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
+                   (((cur_vblank = atomic_read(counter))
                        - *sequence) <= (1<<23)));
        
        *sequence = cur_vblank;
@@ -141,6 +252,16 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 }
 
 
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+}
+
+int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+}
+
 /* Needs the lock as it touches the ring.
  */
 int i915_irq_emit(DRM_IOCTL_ARGS)
@@ -189,7 +310,7 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
        return i915_wait_irq(dev, irqwait.irq_seq);
 }
 
-static int i915_enable_interrupt (drm_device_t *dev)
+static void i915_enable_interrupt (drm_device_t *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u16 flag;
@@ -199,13 +320,8 @@ static int i915_enable_interrupt (drm_device_t *dev)
                flag |= VSYNC_PIPEA_FLAG;
        if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
                flag |= VSYNC_PIPEB_FLAG;
-       if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
-               DRM_ERROR("%s called with invalid pipe 0x%x\n",
-                         __FUNCTION__, dev_priv->vblank_pipe);
-               return DRM_ERR(EINVAL);
-       }
+
        I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
-       return 0;
 }
 
 /* Set the vblank monitor pipe
@@ -224,8 +340,17 @@ int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
        DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
                                 sizeof(pipe));
 
+       if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+               DRM_ERROR("%s called with invalid pipe 0x%x\n", 
+                         __FUNCTION__, pipe.pipe);
+               return DRM_ERR(EINVAL);
+       }
+
        dev_priv->vblank_pipe = pipe.pipe;
-       return i915_enable_interrupt (dev);
+
+       i915_enable_interrupt (dev);
+
+       return 0;
 }
 
 int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
@@ -251,6 +376,118 @@ int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
        return 0;
 }
 
+/**
+ * Schedule buffer swap at given vertical blank.
+ */
+int i915_vblank_swap(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_vblank_swap_t swap;
+       drm_i915_vbl_swap_t *vbl_swap;
+       unsigned int pipe, seqtype, curseq;
+       unsigned long irqflags;
+       struct list_head *list;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return DRM_ERR(EINVAL);
+       }
+
+       if (dev_priv->sarea_priv->rotation) {
+               DRM_DEBUG("Rotation not supported\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
+                                sizeof(swap));
+
+       if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+               DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
+               return DRM_ERR(EINVAL);
+       }
+
+       pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+
+       seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+
+       if (!(dev_priv->vblank_pipe & (1 << pipe))) {
+               DRM_ERROR("Invalid pipe %d\n", pipe);
+               return DRM_ERR(EINVAL);
+       }
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+       if (!drm_get_drawable_info(dev, swap.drawable)) {
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+               DRM_ERROR("Invalid drawable ID %d\n", swap.drawable);
+               return DRM_ERR(EINVAL);
+       }
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+
+       if (seqtype == _DRM_VBLANK_RELATIVE)
+               swap.sequence += curseq;
+
+       if ((curseq - swap.sequence) <= (1<<23)) {
+               if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
+                       swap.sequence = curseq + 1;
+               } else {
+                       DRM_DEBUG("Missed target sequence\n");
+                       return DRM_ERR(EINVAL);
+               }
+       }
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       list_for_each(list, &dev_priv->vbl_swaps.head) {
+               vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+
+               if (vbl_swap->drw_id == swap.drawable &&
+                   vbl_swap->pipe == pipe &&
+                   vbl_swap->sequence == swap.sequence) {
+                       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+                       DRM_DEBUG("Already scheduled\n");
+                       return 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+       if (dev_priv->swaps_pending >= 100) {
+               DRM_DEBUG("Too many swaps queued\n");
+               return DRM_ERR(EBUSY);
+       }
+
+       vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER);
+
+       if (!vbl_swap) {
+               DRM_ERROR("Failed to allocate memory to queue swap\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       DRM_DEBUG("\n");
+
+       vbl_swap->drw_id = swap.drawable;
+       vbl_swap->pipe = pipe;
+       vbl_swap->sequence = swap.sequence;
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head);
+       dev_priv->swaps_pending++;
+
+       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+       DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
+                              sizeof(swap));
+
+       return 0;
+}
+
 /* drm_dma.h hooks
 */
 void i915_driver_irq_preinstall(drm_device_t * dev)
@@ -266,6 +503,12 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
+       dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+       INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+       dev_priv->swaps_pending = 0;
+
+       if (!dev_priv->vblank_pipe)
+               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
        i915_enable_interrupt(dev);
        DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 }
index 54a18eb..30d0047 100644 (file)
@@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
        if (err)
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_MGA_INIT, (unsigned long)init);
 }
 
@@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
                          &getparam->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
 }
 
@@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
            || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
                return -EFAULT;
 
-       err = drm_ioctl(file->f_dentry->d_inode, file,
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
                        DRM_IOCTL_MGA_DMA_BOOTSTRAP,
                        (unsigned long)dma_bootstrap);
        if (err)
@@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return ret;
index 9dd6d41..d3cb676 100644 (file)
@@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
                          &init->agp_textures_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_R128_INIT, (unsigned long)init);
 }
 
@@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
                          &depth->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
 
 }
@@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
                          &stipple->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
 }
 
@@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
                          &getparam->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
 }
 
@@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return ret;
index 0ccfd36..1f1f9cc 100644 (file)
@@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
                          &init->gart_textures_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
 }
 
@@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
                          &clr->depth_boxes))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
 }
 
@@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
                          &request->mask))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
 }
 
@@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
                          &image->data))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
 }
 
@@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
                          &request->prim))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
 }
 
@@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
                          &request->boxes))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
 }
 
@@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
                          &request->value))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
 }
 
@@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
                          &request->region_offset))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
 }
 
@@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
                          &request->irq_seq))
                return -EFAULT;
 
-       return drm_ioctl(file->f_dentry->d_inode, file,
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
                         DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
 }
 
@@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (fn != NULL)
                ret = (*fn) (filp, cmd, arg);
        else
-               ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return ret;
index 60c1695..806f9ce 100644 (file)
@@ -500,9 +500,9 @@ via_dmablit_timer(unsigned long data)
 
 
 static void 
-via_dmablit_workqueue(void *data)
+via_dmablit_workqueue(struct work_struct *work)
 {
-       drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+       drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
        drm_device_t *dev = blitq->dev;
        unsigned long irqsave;
        drm_via_sg_info_t *cur_sg;
@@ -571,7 +571,7 @@ via_init_dmablit(drm_device_t *dev)
                        DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
                }
                DRM_INIT_WAITQUEUE(&blitq->busy_queue);
-               INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq);
+               INIT_WORK(&blitq->wq, via_dmablit_workqueue);
                init_timer(&blitq->poll_timer);
                blitq->poll_timer.function = &via_dmablit_timer;
                blitq->poll_timer.data = (unsigned long) blitq;
index 9b1bf60..06f2dbf 100644 (file)
@@ -201,7 +201,7 @@ static int dsp56k_upload(u_char __user *bin, int len)
 static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
                           loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int dev = iminor(inode) & 0x0f;
 
        switch(dev)
@@ -264,7 +264,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
 static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
                            loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int dev = iminor(inode) & 0x0f;
 
        switch(dev)
@@ -420,7 +420,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
 #if 0
 static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
 {
-       int dev = iminor(file->f_dentry->d_inode) & 0x0f;
+       int dev = iminor(file->f_path.dentry->d_inode) & 0x0f;
 
        switch(dev)
        {
index 5e82c3b..d4005e9 100644 (file)
@@ -122,7 +122,7 @@ static void dtlk_timer_tick(unsigned long data);
 static ssize_t dtlk_read(struct file *file, char __user *buf,
                         size_t count, loff_t * ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        char ch;
        int i = 0, retries;
 
@@ -174,7 +174,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf,
        }
 #endif
 
-       if (iminor(file->f_dentry->d_inode) != DTLK_MINOR)
+       if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR)
                return -EINVAL;
 
        while (1) {
index 706733c..a0f822c 100644 (file)
@@ -199,8 +199,8 @@ static int pc_ioctl(struct tty_struct *, struct file *,
                     unsigned int, unsigned long);
 static int info_ioctl(struct tty_struct *, struct file *,
                     unsigned int, unsigned long);
-static void pc_set_termios(struct tty_struct *, struct termios *);
-static void do_softint(void *);
+static void pc_set_termios(struct tty_struct *, struct ktermios *);
+static void do_softint(struct work_struct *work);
 static void pc_stop(struct tty_struct *);
 static void pc_start(struct tty_struct *);
 static void pc_throttle(struct tty_struct * tty);
@@ -1236,6 +1236,8 @@ static int __init pc_init(void)
        pc_driver->init_termios.c_oflag = 0;
        pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
        pc_driver->init_termios.c_lflag = 0;
+       pc_driver->init_termios.c_ispeed = 9600;
+       pc_driver->init_termios.c_ospeed = 9600;
        pc_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(pc_driver, &pc_ops);
 
@@ -1250,6 +1252,8 @@ static int __init pc_init(void)
        pc_info->init_termios.c_oflag = 0;
        pc_info->init_termios.c_lflag = 0;
        pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+       pc_info->init_termios.c_ispeed = 9600;
+       pc_info->init_termios.c_ospeed = 9600;
        pc_info->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(pc_info, &info_ops);
 
@@ -1505,7 +1509,7 @@ static void post_fep_init(unsigned int crd)
 
                ch->brdchan        = bc;
                ch->mailbox        = gd; 
-               INIT_WORK(&ch->tqueue, do_softint, ch);
+               INIT_WORK(&ch->tqueue, do_softint);
                ch->board          = &boards[crd];
 
                spin_lock_irqsave(&epca_lock, flags);
@@ -1999,7 +2003,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
 { /* Begin epcaparam */
 
        unsigned int cmdHead;
-       struct termios *ts;
+       struct ktermios *ts;
        struct board_chan __iomem *bc;
        unsigned mval, hflow, cflag, iflag;
 
@@ -2114,7 +2118,7 @@ static void receive_data(struct channel *ch)
 { /* Begin receive_data */
 
        unchar *rptr;
-       struct termios *ts = NULL;
+       struct ktermios *ts = NULL;
        struct tty_struct *tty;
        struct board_chan __iomem *bc;
        int dataToRead, wrapgap, bytesAvailable;
@@ -2362,12 +2366,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
        switch (cmd) 
        { /* Begin switch cmd */
 
+#if 0  /* Handled by calling layer properly */
                case TCGETS:
-                       if (copy_to_user(argp, tty->termios, sizeof(struct termios)))
+                       if (copy_to_user(argp, tty->termios, sizeof(struct ktermios)))
                                return -EFAULT;
                        return 0;
                case TCGETA:
                        return get_termio(tty, argp);
+#endif
                case TCSBRK:    /* SVID version: non-zero arg --> no break */
                        retval = tty_check_change(tty);
                        if (retval)
@@ -2536,7 +2542,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
 
 /* --------------------- Begin pc_set_termios  ----------------------- */
 
-static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 { /* Begin pc_set_termios */
 
        struct channel *ch;
@@ -2566,9 +2572,9 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
 
 /* --------------------- Begin do_softint  ----------------------- */
 
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *work)
 { /* Begin do_softint */
-       struct channel *ch = (struct channel *) private_;
+       struct channel *ch = container_of(work, struct channel, tqueue);
        /* Called in response to a modem change event */
        if (ch && ch->magic == EPCA_MAGIC)  { /* Begin EPCA_MAGIC */
                struct tty_struct *tty = ch->tty;
index 15a4ea8..d1bfbaa 100644 (file)
@@ -723,9 +723,10 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
  * -------------------------------------------------------------------
  */
 
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *work)
 {
-       struct esp_struct       *info = (struct esp_struct *) private_;
+       struct esp_struct       *info =
+               container_of(work, struct esp_struct, tqueue);
        struct tty_struct       *tty;
        
        tty = info->tty;
@@ -746,9 +747,10 @@ static void do_softint(void *private_)
  *     do_serial_hangup() -> tty->hangup() -> esp_hangup()
  * 
  */
-static void do_serial_hangup(void *private_)
+static void do_serial_hangup(struct work_struct *work)
 {
-       struct esp_struct       *info = (struct esp_struct *) private_;
+       struct esp_struct       *info =
+               container_of(work, struct esp_struct, tqueue_hangup);
        struct tty_struct       *tty;
        
        tty = info->tty;
@@ -1913,7 +1915,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        return 0;
 }
 
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct esp_struct *info = (struct esp_struct *)tty->driver_data;
        unsigned long flags;
@@ -2501,8 +2503,8 @@ static int __init espserial_init(void)
                info->magic = ESP_MAGIC;
                info->close_delay = 5*HZ/10;
                info->closing_wait = 30*HZ;
-               INIT_WORK(&info->tqueue, do_softint, info);
-               INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
+               INIT_WORK(&info->tqueue, do_softint);
+               INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
                info->config.rx_timeout = rx_timeout;
                info->config.flow_on = flow_on;
                info->config.flow_off = flow_off;
index 87127e4..e769811 100644 (file)
@@ -718,11 +718,11 @@ static unsigned int     gs_baudrates[] = {
 
 
 void gs_set_termios (struct tty_struct * tty, 
-                     struct termios * old_termios)
+                     struct ktermios * old_termios)
 {
        struct gs_port *port;
        int baudrate, tmp, rv;
-       struct termios *tiosp;
+       struct ktermios *tiosp;
 
        func_enter();
 
index 817dc40..23b25ad 100644 (file)
@@ -102,7 +102,7 @@ static void gen_rtc_interrupt(unsigned long arg);
  * Routine to poll RTC seconds field for change as often as possible,
  * after first RTC_UIE use timer to reduce polling
  */
-static void genrtc_troutine(void *data)
+static void genrtc_troutine(struct work_struct *work)
 {
        unsigned int tmp = get_rtc_ss();
        
@@ -255,7 +255,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit)
                irq_active = 1;
                stop_rtc_timers = 0;
                lostint = 0;
-               INIT_WORK(&genrtc_task, genrtc_troutine, NULL);
+               INIT_WORK(&genrtc_task, genrtc_troutine);
                oldsecs = get_rtc_ss();
                init_timer(&timer_task);
 
index 9902ffa..cc2cd46 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 
index 8728255..207f734 100644 (file)
@@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
  * that will cause echoing or we'll go into recursive loop echoing chars back
  * and forth with the console drivers.
  */
-static struct termios hvcs_tty_termios = {
+static struct ktermios hvcs_tty_termios = {
        .c_iflag = IGNBRK | IGNPAR,
        .c_oflag = OPOST,
        .c_cflag = B38400 | CS8 | CREAD | HUPCL,
-       .c_cc = INIT_C_CC
+       .c_cc = INIT_C_CC,
+       .c_ispeed = 38400,
+       .c_ospeed = 38400
 };
 
 /*
@@ -337,11 +339,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
 static void hvcs_close(struct tty_struct *tty, struct file *filp);
 static void hvcs_hangup(struct tty_struct * tty);
 
-static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd);
-static void hvcs_remove_device_attrs(struct vio_dev *vdev);
-static void hvcs_create_driver_attrs(void);
-static void hvcs_remove_driver_attrs(void);
-
 static int __devinit hvcs_probe(struct vio_dev *dev,
                const struct vio_device_id *id);
 static int __devexit hvcs_remove(struct vio_dev *dev);
@@ -353,6 +350,172 @@ static void __exit hvcs_module_exit(void);
 #define HVCS_TRY_WRITE 0x00000004
 #define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ)
 
+static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
+{
+       return viod->dev.driver_data;
+}
+/* The sysfs interface for the driver and devices */
+
+static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
+
+static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
+
+static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
+               size_t count)
+{
+       /*
+        * Don't need this feature at the present time because firmware doesn't
+        * yet support multiple partners.
+        */
+       printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
+       return -EPERM;
+}
+
+static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+
+static DEVICE_ATTR(current_vty,
+       S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
+
+static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
+               size_t count)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+
+       /* writing a '0' to this sysfs entry will result in the disconnect. */
+       if (simple_strtol(buf, NULL, 0) != 0)
+               return -EINVAL;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+
+       if (hvcsd->open_count > 0) {
+               spin_unlock_irqrestore(&hvcsd->lock, flags);
+               printk(KERN_INFO "HVCS: vterm state unchanged.  "
+                               "The hvcs device node is still in use.\n");
+               return -EPERM;
+       }
+
+       if (hvcsd->connected == 0) {
+               spin_unlock_irqrestore(&hvcsd->lock, flags);
+               printk(KERN_INFO "HVCS: vterm state unchanged. The"
+                               " vty-server is not connected to a vty.\n");
+               return -EPERM;
+       }
+
+       hvcs_partner_free(hvcsd);
+       printk(KERN_INFO "HVCS: Closed vty-server@%X and"
+                       " partner vty@%X:%d connection.\n",
+                       hvcsd->vdev->unit_address,
+                       hvcsd->p_unit_address,
+                       (uint32_t)hvcsd->p_partition_ID);
+
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return count;
+}
+
+static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%d\n", hvcsd->connected);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
+               hvcs_vterm_state_show, hvcs_vterm_state_store);
+
+static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viod = to_vio_dev(dev);
+       struct hvcs_struct *hvcsd = from_vio_dev(viod);
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&hvcsd->lock, flags);
+       retval = sprintf(buf, "%d\n", hvcsd->index);
+       spin_unlock_irqrestore(&hvcsd->lock, flags);
+       return retval;
+}
+
+static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
+
+static struct attribute *hvcs_attrs[] = {
+       &dev_attr_partner_vtys.attr,
+       &dev_attr_partner_clcs.attr,
+       &dev_attr_current_vty.attr,
+       &dev_attr_vterm_state.attr,
+       &dev_attr_index.attr,
+       NULL,
+};
+
+static struct attribute_group hvcs_attr_group = {
+       .attrs = hvcs_attrs,
+};
+
+static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
+{
+       /* A 1 means it is updating, a 0 means it is done updating */
+       return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
+}
+
+static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
+               size_t count)
+{
+       if ((simple_strtol(buf, NULL, 0) != 1)
+               && (hvcs_rescan_status != 0))
+               return -EINVAL;
+
+       hvcs_rescan_status = 1;
+       printk(KERN_INFO "HVCS: rescanning partner info for all"
+               " vty-servers.\n");
+       hvcs_rescan_devices_list();
+       hvcs_rescan_status = 0;
+       return count;
+}
+
+static DRIVER_ATTR(rescan,
+       S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
+
 static void hvcs_kick(void)
 {
        hvcs_kicked = 1;
@@ -575,7 +738,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
        spin_unlock_irqrestore(&hvcsd->lock, flags);
        spin_unlock(&hvcs_structs_lock);
 
-       hvcs_remove_device_attrs(vdev);
+       sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
 
        kfree(hvcsd);
 }
@@ -608,6 +771,7 @@ static int __devinit hvcs_probe(
 {
        struct hvcs_struct *hvcsd;
        int index;
+       int retval;
 
        if (!dev || !id) {
                printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
@@ -658,14 +822,16 @@ static int __devinit hvcs_probe(
         * the hvcs_struct has been added to the devices list then the user app
         * will get -ENODEV.
         */
-
        spin_lock(&hvcs_structs_lock);
-
        list_add_tail(&(hvcsd->next), &hvcs_structs);
-
        spin_unlock(&hvcs_structs_lock);
 
-       hvcs_create_device_attrs(hvcsd);
+       retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
+       if (retval) {
+               printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
+                      hvcsd->vdev->unit_address);
+               return retval;
+       }
 
        printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
 
@@ -1354,8 +1520,10 @@ static int __init hvcs_module_init(void)
        if (!hvcs_tty_driver)
                return -ENOMEM;
 
-       if (hvcs_alloc_index_list(num_ttys_to_alloc))
-               return -ENOMEM;
+       if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
+               rc = -ENOMEM;
+               goto index_fail;
+       }
 
        hvcs_tty_driver->owner = THIS_MODULE;
 
@@ -1385,41 +1553,57 @@ static int __init hvcs_module_init(void)
         * dynamically assigned major and minor numbers for our devices.
         */
        if (tty_register_driver(hvcs_tty_driver)) {
-               printk(KERN_ERR "HVCS: registration "
-                       " as a tty driver failed.\n");
-               hvcs_free_index_list();
-               put_tty_driver(hvcs_tty_driver);
-               return -EIO;
+               printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
+               rc = -EIO;
+               goto register_fail;
        }
 
        hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
        if (!hvcs_pi_buff) {
-               tty_unregister_driver(hvcs_tty_driver);
-               hvcs_free_index_list();
-               put_tty_driver(hvcs_tty_driver);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto buff_alloc_fail;
        }
 
        hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
        if (IS_ERR(hvcs_task)) {
                printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
-               kfree(hvcs_pi_buff);
-               tty_unregister_driver(hvcs_tty_driver);
-               hvcs_free_index_list();
-               put_tty_driver(hvcs_tty_driver);
-               return -EIO;
+               rc = -EIO;
+               goto kthread_fail;
        }
 
        rc = vio_register_driver(&hvcs_vio_driver);
+       if (rc) {
+               printk(KERN_ERR "HVCS: can't register vio driver\n");
+               goto vio_fail;
+       }
 
        /*
         * This needs to be done AFTER the vio_register_driver() call or else
         * the kobjects won't be initialized properly.
         */
-       hvcs_create_driver_attrs();
+       rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
+       if (rc) {
+               printk(KERN_ERR "HVCS: sysfs attr create failed\n");
+               goto attr_fail;
+       }
 
        printk(KERN_INFO "HVCS: driver module inserted.\n");
 
+       return 0;
+
+attr_fail:
+       vio_unregister_driver(&hvcs_vio_driver);
+vio_fail:
+       kthread_stop(hvcs_task);
+kthread_fail:
+       kfree(hvcs_pi_buff);
+buff_alloc_fail:
+       tty_unregister_driver(hvcs_tty_driver);
+register_fail:
+       hvcs_free_index_list();
+index_fail:
+       put_tty_driver(hvcs_tty_driver);
+       hvcs_tty_driver = NULL;
        return rc;
 }
 
@@ -1441,7 +1625,7 @@ static void __exit hvcs_module_exit(void)
        hvcs_pi_buff = NULL;
        spin_unlock(&hvcs_pi_lock);
 
-       hvcs_remove_driver_attrs();
+       driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
 
        vio_unregister_driver(&hvcs_vio_driver);
 
@@ -1456,191 +1640,3 @@ static void __exit hvcs_module_exit(void)
 
 module_init(hvcs_module_init);
 module_exit(hvcs_module_exit);
-
-static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
-{
-       return viod->dev.driver_data;
-}
-/* The sysfs interface for the driver and devices */
-
-static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
-}
-static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
-
-static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
-}
-static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
-
-static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
-               size_t count)
-{
-       /*
-        * Don't need this feature at the present time because firmware doesn't
-        * yet support multiple partners.
-        */
-       printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
-       return -EPERM;
-}
-
-static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
-}
-
-static DEVICE_ATTR(current_vty,
-       S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
-
-static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
-               size_t count)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-
-       /* writing a '0' to this sysfs entry will result in the disconnect. */
-       if (simple_strtol(buf, NULL, 0) != 0)
-               return -EINVAL;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-
-       if (hvcsd->open_count > 0) {
-               spin_unlock_irqrestore(&hvcsd->lock, flags);
-               printk(KERN_INFO "HVCS: vterm state unchanged.  "
-                               "The hvcs device node is still in use.\n");
-               return -EPERM;
-       }
-
-       if (hvcsd->connected == 0) {
-               spin_unlock_irqrestore(&hvcsd->lock, flags);
-               printk(KERN_INFO "HVCS: vterm state unchanged. The"
-                               " vty-server is not connected to a vty.\n");
-               return -EPERM;
-       }
-
-       hvcs_partner_free(hvcsd);
-       printk(KERN_INFO "HVCS: Closed vty-server@%X and"
-                       " partner vty@%X:%d connection.\n",
-                       hvcsd->vdev->unit_address,
-                       hvcsd->p_unit_address,
-                       (uint32_t)hvcsd->p_partition_ID);
-
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return count;
-}
-
-static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = sprintf(buf, "%d\n", hvcsd->connected);
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
-}
-static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
-               hvcs_vterm_state_show, hvcs_vterm_state_store);
-
-static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct vio_dev *viod = to_vio_dev(dev);
-       struct hvcs_struct *hvcsd = from_vio_dev(viod);
-       unsigned long flags;
-       int retval;
-
-       spin_lock_irqsave(&hvcsd->lock, flags);
-       retval = sprintf(buf, "%d\n", hvcsd->index);
-       spin_unlock_irqrestore(&hvcsd->lock, flags);
-       return retval;
-}
-
-static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
-
-static struct attribute *hvcs_attrs[] = {
-       &dev_attr_partner_vtys.attr,
-       &dev_attr_partner_clcs.attr,
-       &dev_attr_current_vty.attr,
-       &dev_attr_vterm_state.attr,
-       &dev_attr_index.attr,
-       NULL,
-};
-
-static struct attribute_group hvcs_attr_group = {
-       .attrs = hvcs_attrs,
-};
-
-static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd)
-{
-       struct vio_dev *vdev = hvcsd->vdev;
-       sysfs_create_group(&vdev->dev.kobj, &hvcs_attr_group);
-}
-
-static void hvcs_remove_device_attrs(struct vio_dev *vdev)
-{
-       sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
-}
-
-static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
-{
-       /* A 1 means it is updating, a 0 means it is done updating */
-       return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
-}
-
-static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
-               size_t count)
-{
-       if ((simple_strtol(buf, NULL, 0) != 1)
-               && (hvcs_rescan_status != 0))
-               return -EINVAL;
-
-       hvcs_rescan_status = 1;
-       printk(KERN_INFO "HVCS: rescanning partner info for all"
-               " vty-servers.\n");
-       hvcs_rescan_devices_list();
-       hvcs_rescan_status = 0;
-       return count;
-}
-static DRIVER_ATTR(rescan,
-       S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
-
-static void hvcs_create_driver_attrs(void)
-{
-       struct device_driver *driverfs = &(hvcs_vio_driver.driver);
-       driver_create_file(driverfs, &driver_attr_rescan);
-}
-
-static void hvcs_remove_driver_attrs(void)
-{
-       struct device_driver *driverfs = &(hvcs_vio_driver.driver);
-       driver_remove_file(driverfs, &driver_attr_rescan);
-}
index 2cf63e7..d780683 100644 (file)
@@ -69,7 +69,7 @@
 #define __ALIGNED__    __attribute__((__aligned__(sizeof(long))))
 
 struct hvsi_struct {
-       struct work_struct writer;
+       struct delayed_work writer;
        struct work_struct handshaker;
        wait_queue_head_t emptyq; /* woken when outbuf is emptied */
        wait_queue_head_t stateq; /* woken when HVSI state changes */
@@ -744,9 +744,10 @@ static int hvsi_handshake(struct hvsi_struct *hp)
        return 0;
 }
 
-static void hvsi_handshaker(void *arg)
+static void hvsi_handshaker(struct work_struct *work)
 {
-       struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+       struct hvsi_struct *hp =
+               container_of(work, struct hvsi_struct, handshaker);
 
        if (hvsi_handshake(hp) >= 0)
                return;
@@ -951,9 +952,10 @@ static void hvsi_push(struct hvsi_struct *hp)
 }
 
 /* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
-static void hvsi_write_worker(void *arg)
+static void hvsi_write_worker(struct work_struct *work)
 {
-       struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+       struct hvsi_struct *hp =
+               container_of(work, struct hvsi_struct, writer.work);
        unsigned long flags;
 #ifdef DEBUG
        static long start_j = 0;
@@ -1159,6 +1161,8 @@ static int __init hvsi_init(void)
        hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
        hvsi_driver->init_termios = tty_std_termios;
        hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+       hvsi_driver->init_termios.c_ispeed = 9600;
+       hvsi_driver->init_termios.c_ospeed = 9600;
        hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(hvsi_driver, &hvsi_ops);
 
@@ -1287,8 +1291,8 @@ static int __init hvsi_console_init(void)
                }
 
                hp = &hvsi_ports[hvsi_count];
-               INIT_WORK(&hp->writer, hvsi_write_worker, hp);
-               INIT_WORK(&hp->handshaker, hvsi_handshaker, hp);
+               INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker);
+               INIT_WORK(&hp->handshaker, hvsi_handshaker);
                init_waitqueue_head(&hp->emptyq);
                init_waitqueue_head(&hp->stateq);
                spin_lock_init(&hp->lock);
index 9f7635f..5f3acd8 100644 (file)
@@ -3,17 +3,20 @@
 #
 
 config HW_RANDOM
-       bool "Hardware Random Number Generator Core support"
-       default y
+       tristate "Hardware Random Number Generator Core support"
+       default m
        ---help---
          Hardware Random Number Generator Core infrastructure.
 
+         To compile this driver as a module, choose M here: the
+         module will be called rng-core.
+
          If unsure, say Y.
 
 config HW_RANDOM_INTEL
        tristate "Intel HW Random Number Generator support"
        depends on HW_RANDOM && (X86 || IA64) && PCI
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random Number
          Generator hardware found on Intel i8xx-based motherboards.
@@ -26,7 +29,7 @@ config HW_RANDOM_INTEL
 config HW_RANDOM_AMD
        tristate "AMD HW Random Number Generator support"
        depends on HW_RANDOM && X86 && PCI
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random Number
          Generator hardware found on AMD 76x-based motherboards.
@@ -39,7 +42,7 @@ config HW_RANDOM_AMD
 config HW_RANDOM_GEODE
        tristate "AMD Geode HW Random Number Generator support"
        depends on HW_RANDOM && X86 && PCI
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random Number
          Generator hardware found on the AMD Geode LX.
@@ -52,7 +55,7 @@ config HW_RANDOM_GEODE
 config HW_RANDOM_VIA
        tristate "VIA HW Random Number Generator support"
        depends on HW_RANDOM && X86_32
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random Number
          Generator hardware found on VIA based motherboards.
@@ -65,7 +68,7 @@ config HW_RANDOM_VIA
 config HW_RANDOM_IXP4XX
        tristate "Intel IXP4xx NPU HW Random Number Generator support"
        depends on HW_RANDOM && ARCH_IXP4XX
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random
          Number Generator hardware found on the Intel IXP4xx NPU.
@@ -78,7 +81,7 @@ config HW_RANDOM_IXP4XX
 config HW_RANDOM_OMAP
        tristate "OMAP Random Number Generator support"
        depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX)
-       default y
+       default HW_RANDOM
        ---help---
          This driver provides kernel-side support for the Random Number
          Generator hardware found on OMAP16xx and OMAP24xx multimedia
index e263ae9..c41fa19 100644 (file)
@@ -2,7 +2,8 @@
 # Makefile for HW Random Number Generator (RNG) device drivers.
 #
 
-obj-$(CONFIG_HW_RANDOM) += core.o
+obj-$(CONFIG_HW_RANDOM) += rng-core.o
+rng-core-y := core.o
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
index baa4e72..29277ec 100644 (file)
@@ -367,11 +367,6 @@ static UCHAR cc02[];
 #define CSE_NULL  3  // Replace with a null
 #define CSE_MARK  4  // Replace with a 3-character sequence (as Unix)
 
-#define  CMD_SET_REPLACEMENT(arg,ch)   \
-                       (((cmdSyntaxPtr)(ct36a))->cmd[1] = (arg), \
-                       (((cmdSyntaxPtr)(ct36a))->cmd[2] = (ch),  \
-                       (cmdSyntaxPtr)(ct36a))
-
 #define CSE_REPLACE  0x8       // Replace the errored character with the
                                                        // replacement character defined here
 
index 54d93f0..7804576 100644 (file)
@@ -84,8 +84,8 @@ static void iiSendPendingMail(i2eBordStrPtr);
 static void serviceOutgoingFifo(i2eBordStrPtr);
 
 // Functions defined in ip2.c as part of interrupt handling
-static void do_input(void *);
-static void do_status(void *);
+static void do_input(struct work_struct *);
+static void do_status(struct work_struct *);
 
 //***************
 //* Debug  Data *
@@ -331,8 +331,8 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
                pCh->ClosingWaitTime  = 30*HZ;
 
                // Initialize task queue objects
-               INIT_WORK(&pCh->tqueue_input, do_input, pCh);
-               INIT_WORK(&pCh->tqueue_status, do_status, pCh);
+               INIT_WORK(&pCh->tqueue_input, do_input);
+               INIT_WORK(&pCh->tqueue_status, do_status);
 
 #ifdef IP2DEBUG_TRACE
                pCh->trace = ip2trace;
@@ -1016,7 +1016,6 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
        unsigned short channel;
        unsigned short stuffIndex;
        unsigned long flags;
-       int rc = 0;
 
        int bailout = 10;
 
@@ -1573,7 +1572,7 @@ i2StripFifo(i2eBordStrPtr pB)
 #ifdef USE_IQ
                        schedule_work(&pCh->tqueue_input);
 #else
-                       do_input(pCh);
+                       do_input(&pCh->tqueue_input);
 #endif
 
                        // Note we do not need to maintain any flow-control credits at this
@@ -1810,7 +1809,7 @@ i2StripFifo(i2eBordStrPtr pB)
 #ifdef USE_IQ
                                                schedule_work(&pCh->tqueue_status);
 #else
-                                               do_status(pCh);
+                                               do_status(&pCh->tqueue_status);
 #endif
                                        }
                                }
index a3f32d4..7c70310 100644 (file)
@@ -177,7 +177,7 @@ static int  ip2_write_room(PTTY);
 static int  ip2_chars_in_buf(PTTY);
 static void ip2_flush_buffer(PTTY);
 static int  ip2_ioctl(PTTY, struct file *, UINT, ULONG);
-static void ip2_set_termios(PTTY, struct termios *);
+static void ip2_set_termios(PTTY, struct ktermios *);
 static void ip2_set_line_discipline(PTTY);
 static void ip2_throttle(PTTY);
 static void ip2_unthrottle(PTTY);
@@ -189,16 +189,16 @@ static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
 
 static void set_irq(int, int);
-static void ip2_interrupt_bh(i2eBordStrPtr pB);
+static void ip2_interrupt_bh(struct work_struct *work);
 static irqreturn_t ip2_interrupt(int irq, void *dev_id);
 static void ip2_poll(unsigned long arg);
 static inline void service_all_boards(void);
-static void do_input(void *p);
-static void do_status(void *p);
+static void do_input(struct work_struct *);
+static void do_status(struct work_struct *);
 
 static void ip2_wait_until_sent(PTTY,int);
 
-static void set_params (i2ChanStrPtr, struct termios *);
+static void set_params (i2ChanStrPtr, struct ktermios *);
 static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 
@@ -918,7 +918,7 @@ ip2_init_board( int boardnum )
                pCh++;
        }
 ex_exit:
-       INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB);
+       INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
        return;
 
 err_release_region:
@@ -1125,8 +1125,8 @@ service_all_boards(void)
 
 
 /******************************************************************************/
-/* Function:   ip2_interrupt_bh(pB)                                           */
-/* Parameters: pB - pointer to the board structure                            */
+/* Function:   ip2_interrupt_bh(work)                                         */
+/* Parameters: work - pointer to the board structure                          */
 /* Returns:    Nothing                                                        */
 /*                                                                            */
 /* Description:                                                               */
@@ -1135,8 +1135,9 @@ service_all_boards(void)
 /*                                                                            */
 /******************************************************************************/
 static void
-ip2_interrupt_bh(i2eBordStrPtr pB)
+ip2_interrupt_bh(struct work_struct *work)
 {
+       i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
 //     pB better well be set or we have a problem!  We can only get
 //     here from the IMMEDIATE queue.  Here, we process the boards.
 //     Checking pB doesn't cost much and it saves us from the sanity checkers.
@@ -1245,9 +1246,9 @@ ip2_poll(unsigned long arg)
        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
 }
 
-static void do_input(void *p)
+static void do_input(struct work_struct *work)
 {
-       i2ChanStrPtr pCh = p;
+       i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
        unsigned long flags;
 
        ip2trace(CHANN, ITRC_INPUT, 21, 0 );
@@ -1279,9 +1280,9 @@ static inline void  isig(int sig, struct tty_struct *tty, int flush)
        }
 }
 
-static void do_status(void *p)
+static void do_status(struct work_struct *work)
 {
-       i2ChanStrPtr pCh = p;
+       i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
        int status;
 
        status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
@@ -2397,7 +2398,7 @@ set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
 /*                                                                            */
 /******************************************************************************/
 static void
-ip2_set_termios( PTTY tty, struct termios *old_termios )
+ip2_set_termios( PTTY tty, struct ktermios *old_termios )
 {
        i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
 
@@ -2439,11 +2440,11 @@ ip2_set_line_discipline ( PTTY tty )
 /* change.                                                                    */
 /******************************************************************************/
 static void
-set_params( i2ChanStrPtr pCh, struct termios *o_tios )
+set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
 {
        tcflag_t cflag, iflag, lflag;
        char stop_char, start_char;
-       struct termios dummy;
+       struct ktermios dummy;
 
        lflag = pCh->pTTY->termios->c_lflag;
        cflag = pCh->pTTY->termios->c_cflag;
@@ -2699,7 +2700,7 @@ static
 ssize_t
 ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
 {
-       unsigned int minor = iminor(pFile->f_dentry->d_inode);
+       unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
        int rc = 0;
 
 #ifdef IP2DEBUG_IPL
index 0030cd8..e736119 100644 (file)
 #include <linux/ipmi_msgdefs.h>                /* for completion codes */
 #include "ipmi_si_sm.h"
 
-static int bt_debug = 0x00;    /* Production value 0, see following flags */
+#define BT_DEBUG_OFF   0       /* Used in production */
+#define BT_DEBUG_ENABLE        1       /* Generic messages */
+#define BT_DEBUG_MSG   2       /* Prints all request/response buffers */
+#define BT_DEBUG_STATES        4       /* Verbose look at state changes */
+/* BT_DEBUG_OFF must be zero to correspond to the default uninitialized
+   value */
+
+static int bt_debug; /* 0 == BT_DEBUG_OFF */
 
-#define        BT_DEBUG_ENABLE 1
-#define BT_DEBUG_MSG   2
-#define BT_DEBUG_STATES        4
 module_param(bt_debug, int, 0644);
 MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
 
@@ -47,38 +51,54 @@ MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
    Since the Open IPMI architecture is single-message oriented at this
    stage, the queue depth of BT is of no concern. */
 
-#define BT_NORMAL_TIMEOUT      5000000 /* seconds in microseconds */
-#define BT_RETRY_LIMIT         2
-#define BT_RESET_DELAY         6000000 /* 6 seconds after warm reset */
+#define BT_NORMAL_TIMEOUT      5       /* seconds */
+#define BT_NORMAL_RETRY_LIMIT  2
+#define BT_RESET_DELAY         6       /* seconds after warm reset */
+
+/* States are written in chronological order and usually cover
+   multiple rows of the state table discussion in the IPMI spec. */
 
 enum bt_states {
-       BT_STATE_IDLE,
+       BT_STATE_IDLE = 0,      /* Order is critical in this list */
        BT_STATE_XACTION_START,
        BT_STATE_WRITE_BYTES,
-       BT_STATE_WRITE_END,
        BT_STATE_WRITE_CONSUME,
-       BT_STATE_B2H_WAIT,
-       BT_STATE_READ_END,
-       BT_STATE_RESET1,                /* These must come last */
+       BT_STATE_READ_WAIT,
+       BT_STATE_CLEAR_B2H,
+       BT_STATE_READ_BYTES,
+       BT_STATE_RESET1,        /* These must come last */
        BT_STATE_RESET2,
        BT_STATE_RESET3,
        BT_STATE_RESTART,
-       BT_STATE_HOSED
+       BT_STATE_PRINTME,
+       BT_STATE_CAPABILITIES_BEGIN,
+       BT_STATE_CAPABILITIES_END,
+       BT_STATE_LONG_BUSY      /* BT doesn't get hosed :-) */
 };
 
+/* Macros seen at the end of state "case" blocks.  They help with legibility
+   and debugging. */
+
+#define BT_STATE_CHANGE(X,Y) { bt->state = X; return Y; }
+
+#define BT_SI_SM_RETURN(Y)   { last_printed = BT_STATE_PRINTME; return Y; }
+
 struct si_sm_data {
        enum bt_states  state;
-       enum bt_states  last_state;     /* assist printing and resets */
        unsigned char   seq;            /* BT sequence number */
        struct si_sm_io *io;
-        unsigned char  write_data[IPMI_MAX_MSG_LENGTH];
-        int            write_count;
-        unsigned char  read_data[IPMI_MAX_MSG_LENGTH];
-        int            read_count;
-        int            truncated;
-        long           timeout;
-        unsigned int   error_retries;  /* end of "common" fields */
+       unsigned char   write_data[IPMI_MAX_MSG_LENGTH];
+       int             write_count;
+       unsigned char   read_data[IPMI_MAX_MSG_LENGTH];
+       int             read_count;
+       int             truncated;
+       long            timeout;        /* microseconds countdown */
+       int             error_retries;  /* end of "common" fields */
        int             nonzero_status; /* hung BMCs stay all 0 */
+       enum bt_states  complete;       /* to divert the state machine */
+       int             BT_CAP_outreqs;
+       long            BT_CAP_req2rsp;
+       int             BT_CAP_retries; /* Recommended retries */
 };
 
 #define BT_CLR_WR_PTR  0x01    /* See IPMI 1.5 table 11.6.4 */
@@ -111,86 +131,118 @@ struct si_sm_data {
 static char *state2txt(unsigned char state)
 {
        switch (state) {
-               case BT_STATE_IDLE:             return("IDLE");
-               case BT_STATE_XACTION_START:    return("XACTION");
-               case BT_STATE_WRITE_BYTES:      return("WR_BYTES");
-               case BT_STATE_WRITE_END:        return("WR_END");
-               case BT_STATE_WRITE_CONSUME:    return("WR_CONSUME");
-               case BT_STATE_B2H_WAIT:         return("B2H_WAIT");
-               case BT_STATE_READ_END:         return("RD_END");
-               case BT_STATE_RESET1:           return("RESET1");
-               case BT_STATE_RESET2:           return("RESET2");
-               case BT_STATE_RESET3:           return("RESET3");
-               case BT_STATE_RESTART:          return("RESTART");
-               case BT_STATE_HOSED:            return("HOSED");
+       case BT_STATE_IDLE:             return("IDLE");
+       case BT_STATE_XACTION_START:    return("XACTION");
+       case BT_STATE_WRITE_BYTES:      return("WR_BYTES");
+       case BT_STATE_WRITE_CONSUME:    return("WR_CONSUME");
+       case BT_STATE_READ_WAIT:        return("RD_WAIT");
+       case BT_STATE_CLEAR_B2H:        return("CLEAR_B2H");
+       case BT_STATE_READ_BYTES:       return("RD_BYTES");
+       case BT_STATE_RESET1:           return("RESET1");
+       case BT_STATE_RESET2:           return("RESET2");
+       case BT_STATE_RESET3:           return("RESET3");
+       case BT_STATE_RESTART:          return("RESTART");
+       case BT_STATE_LONG_BUSY:        return("LONG_BUSY");
+       case BT_STATE_CAPABILITIES_BEGIN: return("CAP_BEGIN");
+       case BT_STATE_CAPABILITIES_END: return("CAP_END");
        }
        return("BAD STATE");
 }
 #define STATE2TXT state2txt(bt->state)
 
-static char *status2txt(unsigned char status, char *buf)
+static char *status2txt(unsigned char status)
 {
+       /*
+        * This cannot be called by two threads at the same time and
+        * the buffer is always consumed immediately, so the static is
+        * safe to use.
+        */
+       static char buf[40];
+
        strcpy(buf, "[ ");
-       if (status & BT_B_BUSY) strcat(buf, "B_BUSY ");
-       if (status & BT_H_BUSY) strcat(buf, "H_BUSY ");
-       if (status & BT_OEM0) strcat(buf, "OEM0 ");
-       if (status & BT_SMS_ATN) strcat(buf, "SMS ");
-       if (status & BT_B2H_ATN) strcat(buf, "B2H ");
-       if (status & BT_H2B_ATN) strcat(buf, "H2B ");
+       if (status & BT_B_BUSY)
+               strcat(buf, "B_BUSY ");
+       if (status & BT_H_BUSY)
+               strcat(buf, "H_BUSY ");
+       if (status & BT_OEM0)
+               strcat(buf, "OEM0 ");
+       if (status & BT_SMS_ATN)
+               strcat(buf, "SMS ");
+       if (status & BT_B2H_ATN)
+               strcat(buf, "B2H ");
+       if (status & BT_H2B_ATN)
+               strcat(buf, "H2B ");
        strcat(buf, "]");
        return buf;
 }
-#define STATUS2TXT(buf) status2txt(status, buf)
+#define STATUS2TXT status2txt(status)
+
+/* called externally at insmod time, and internally on cleanup */
 
-/* This will be called from within this module on a hosed condition */
-#define FIRST_SEQ      0
 static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
 {
-       bt->state = BT_STATE_IDLE;
-       bt->last_state = BT_STATE_IDLE;
-       bt->seq = FIRST_SEQ;
-       bt->io = io;
-       bt->write_count = 0;
-       bt->read_count = 0;
-       bt->error_retries = 0;
-       bt->nonzero_status = 0;
-       bt->truncated = 0;
-       bt->timeout = BT_NORMAL_TIMEOUT;
+       memset(bt, 0, sizeof(struct si_sm_data));
+       if (bt->io != io) {             /* external: one-time only things */
+               bt->io = io;
+               bt->seq = 0;
+       }
+       bt->state = BT_STATE_IDLE;      /* start here */
+       bt->complete = BT_STATE_IDLE;   /* end here */
+       bt->BT_CAP_req2rsp = BT_NORMAL_TIMEOUT * 1000000;
+       bt->BT_CAP_retries = BT_NORMAL_RETRY_LIMIT;
+       /* BT_CAP_outreqs == zero is a flag to read BT Capabilities */
        return 3; /* We claim 3 bytes of space; ought to check SPMI table */
 }
 
+/* Jam a completion code (probably an error) into a response */
+
+static void force_result(struct si_sm_data *bt, unsigned char completion_code)
+{
+       bt->read_data[0] = 4;                           /* # following bytes */
+       bt->read_data[1] = bt->write_data[1] | 4;       /* Odd NetFn/LUN */
+       bt->read_data[2] = bt->write_data[2];           /* seq (ignored) */
+       bt->read_data[3] = bt->write_data[3];           /* Command */
+       bt->read_data[4] = completion_code;
+       bt->read_count = 5;
+}
+
+/* The upper state machine starts here */
+
 static int bt_start_transaction(struct si_sm_data *bt,
                                unsigned char *data,
                                unsigned int size)
 {
        unsigned int i;
 
-       if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
-              return -1;
+       if (size < 2)
+               return IPMI_REQ_LEN_INVALID_ERR;
+       if (size > IPMI_MAX_MSG_LENGTH)
+               return IPMI_REQ_LEN_EXCEEDED_ERR;
 
-       if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
-               return -2;
+       if (bt->state == BT_STATE_LONG_BUSY)
+               return IPMI_NODE_BUSY_ERR;
+
+       if (bt->state != BT_STATE_IDLE)
+               return IPMI_NOT_IN_MY_STATE_ERR;
 
        if (bt_debug & BT_DEBUG_MSG) {
-               printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
-               printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
+               printk(KERN_WARNING "BT: +++++++++++++++++ New command\n");
+               printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2);
                for (i = 0; i < size; i ++)
-                      printk (" %02x", data[i]);
+                       printk (" %02x", data[i]);
                printk("\n");
        }
        bt->write_data[0] = size + 1;   /* all data plus seq byte */
        bt->write_data[1] = *data;      /* NetFn/LUN */
-       bt->write_data[2] = bt->seq;
+       bt->write_data[2] = bt->seq++;
        memcpy(bt->write_data + 3, data + 1, size - 1);
        bt->write_count = size + 2;
-
        bt->error_retries = 0;
        bt->nonzero_status = 0;
-       bt->read_count = 0;
        bt->truncated = 0;
        bt->state = BT_STATE_XACTION_START;
-       bt->last_state = BT_STATE_IDLE;
-       bt->timeout = BT_NORMAL_TIMEOUT;
+       bt->timeout = bt->BT_CAP_req2rsp;
+       force_result(bt, IPMI_ERR_UNSPECIFIED);
        return 0;
 }
 
@@ -198,38 +250,30 @@ static int bt_start_transaction(struct si_sm_data *bt,
    it calls this.  Strip out the length and seq bytes. */
 
 static int bt_get_result(struct si_sm_data *bt,
-                          unsigned char *data,
-                          unsigned int length)
+                        unsigned char *data,
+                        unsigned int length)
 {
        int i, msg_len;
 
        msg_len = bt->read_count - 2;           /* account for length & seq */
-       /* Always NetFn, Cmd, cCode */
        if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) {
-               printk(KERN_DEBUG "BT results: bad msg_len = %d\n", msg_len);
-               data[0] = bt->write_data[1] | 0x4;      /* Kludge a response */
-               data[1] = bt->write_data[3];
-               data[2] = IPMI_ERR_UNSPECIFIED;
+               force_result(bt, IPMI_ERR_UNSPECIFIED);
                msg_len = 3;
-       } else {
-               data[0] = bt->read_data[1];
-               data[1] = bt->read_data[3];
-               if (length < msg_len)
-                      bt->truncated = 1;
-               if (bt->truncated) {    /* can be set in read_all_bytes() */
-                       data[2] = IPMI_ERR_MSG_TRUNCATED;
-                       msg_len = 3;
-               } else
-                      memcpy(data + 2, bt->read_data + 4, msg_len - 2);
+       }
+       data[0] = bt->read_data[1];
+       data[1] = bt->read_data[3];
+       if (length < msg_len || bt->truncated) {
+               data[2] = IPMI_ERR_MSG_TRUNCATED;
+               msg_len = 3;
+       } else
+               memcpy(data + 2, bt->read_data + 4, msg_len - 2);
 
-               if (bt_debug & BT_DEBUG_MSG) {
-                       printk (KERN_WARNING "BT: res (raw)");
-                       for (i = 0; i < msg_len; i++)
-                              printk(" %02x", data[i]);
-                       printk ("\n");
-               }
+       if (bt_debug & BT_DEBUG_MSG) {
+               printk (KERN_WARNING "BT: result %d bytes:", msg_len);
+               for (i = 0; i < msg_len; i++)
+                       printk(" %02x", data[i]);
+               printk ("\n");
        }
-       bt->read_count = 0;     /* paranoia */
        return msg_len;
 }
 
@@ -238,22 +282,40 @@ static int bt_get_result(struct si_sm_data *bt,
 
 static void reset_flags(struct si_sm_data *bt)
 {
+       if (bt_debug)
+               printk(KERN_WARNING "IPMI BT: flag reset %s\n",
+                                       status2txt(BT_STATUS));
        if (BT_STATUS & BT_H_BUSY)
-              BT_CONTROL(BT_H_BUSY);
-       if (BT_STATUS & BT_B_BUSY)
-              BT_CONTROL(BT_B_BUSY);
-       BT_CONTROL(BT_CLR_WR_PTR);
-       BT_CONTROL(BT_SMS_ATN);
-
-       if (BT_STATUS & BT_B2H_ATN) {
-               int i;
-               BT_CONTROL(BT_H_BUSY);
-               BT_CONTROL(BT_B2H_ATN);
-               BT_CONTROL(BT_CLR_RD_PTR);
-               for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++)
-                      BMC2HOST;
-               BT_CONTROL(BT_H_BUSY);
-       }
+               BT_CONTROL(BT_H_BUSY);  /* force clear */
+       BT_CONTROL(BT_CLR_WR_PTR);      /* always reset */
+       BT_CONTROL(BT_SMS_ATN);         /* always clear */
+       BT_INTMASK_W(BT_BMC_HWRST);
+}
+
+/* Get rid of an unwanted/stale response.  This should only be needed for
+   BMCs that support multiple outstanding requests. */
+
+static void drain_BMC2HOST(struct si_sm_data *bt)
+{
+       int i, size;
+
+       if (!(BT_STATUS & BT_B2H_ATN))  /* Not signalling a response */
+               return;
+
+       BT_CONTROL(BT_H_BUSY);          /* now set */
+       BT_CONTROL(BT_B2H_ATN);         /* always clear */
+       BT_STATUS;                      /* pause */
+       BT_CONTROL(BT_B2H_ATN);         /* some BMCs are stubborn */
+       BT_CONTROL(BT_CLR_RD_PTR);      /* always reset */
+       if (bt_debug)
+               printk(KERN_WARNING "IPMI BT: stale response %s; ",
+                       status2txt(BT_STATUS));
+       size = BMC2HOST;
+       for (i = 0; i < size ; i++)
+               BMC2HOST;
+       BT_CONTROL(BT_H_BUSY);          /* now clear */
+       if (bt_debug)
+               printk("drained %d bytes\n", size + 1);
 }
 
 static inline void write_all_bytes(struct si_sm_data *bt)
@@ -261,201 +323,256 @@ static inline void write_all_bytes(struct si_sm_data *bt)
        int i;
 
        if (bt_debug & BT_DEBUG_MSG) {
-               printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
+               printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
                        bt->write_count, bt->seq);
                for (i = 0; i < bt->write_count; i++)
                        printk (" %02x", bt->write_data[i]);
                printk ("\n");
        }
        for (i = 0; i < bt->write_count; i++)
-              HOST2BMC(bt->write_data[i]);
+               HOST2BMC(bt->write_data[i]);
 }
 
 static inline int read_all_bytes(struct si_sm_data *bt)
 {
        unsigned char i;
 
+       /* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
+          Keep layout of first four bytes aligned with write_data[] */
+
        bt->read_data[0] = BMC2HOST;
        bt->read_count = bt->read_data[0];
-       if (bt_debug & BT_DEBUG_MSG)
-               printk(KERN_WARNING "BT: read %d bytes:", bt->read_count);
 
-       /* minimum: length, NetFn, Seq, Cmd, cCode == 5 total, or 4 more
-          following the length byte. */
        if (bt->read_count < 4 || bt->read_count >= IPMI_MAX_MSG_LENGTH) {
                if (bt_debug & BT_DEBUG_MSG)
-                       printk("bad length %d\n", bt->read_count);
+                       printk(KERN_WARNING "BT: bad raw rsp len=%d\n",
+                               bt->read_count);
                bt->truncated = 1;
                return 1;       /* let next XACTION START clean it up */
        }
        for (i = 1; i <= bt->read_count; i++)
-              bt->read_data[i] = BMC2HOST;
-       bt->read_count++;       /* account for the length byte */
+               bt->read_data[i] = BMC2HOST;
+       bt->read_count++;       /* Account internally for length byte */
 
        if (bt_debug & BT_DEBUG_MSG) {
-               for (i = 0; i < bt->read_count; i++)
+               int max = bt->read_count;
+
+               printk(KERN_WARNING "BT: got %d bytes seq=0x%02X",
+                       max, bt->read_data[2]);
+               if (max > 16)
+                       max = 16;
+               for (i = 0; i < max; i++)
                        printk (" %02x", bt->read_data[i]);
-               printk ("\n");
+               printk ("%s\n", bt->read_count == max ? "" : " ...");
        }
-       if (bt->seq != bt->write_data[2])       /* idiot check */
-               printk(KERN_DEBUG "BT: internal error: sequence mismatch\n");
 
-       /* per the spec, the (NetFn, Seq, Cmd) tuples should match */
-       if ((bt->read_data[3] == bt->write_data[3]) &&          /* Cmd */
-               (bt->read_data[2] == bt->write_data[2]) &&      /* Sequence */
-               ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
+       /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */
+       if ((bt->read_data[3] == bt->write_data[3]) &&
+           (bt->read_data[2] == bt->write_data[2]) &&
+           ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
                        return 1;
 
        if (bt_debug & BT_DEBUG_MSG)
-              printk(KERN_WARNING "BT: bad packet: "
+               printk(KERN_WARNING "IPMI BT: bad packet: "
                "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
-               bt->write_data[1], bt->write_data[2], bt->write_data[3],
+               bt->write_data[1] | 0x04, bt->write_data[2], bt->write_data[3],
                bt->read_data[1],  bt->read_data[2],  bt->read_data[3]);
        return 0;
 }
 
-/* Modifies bt->state appropriately, need to get into the bt_event() switch */
+/* Restart if retries are left, or return an error completion code */
 
-static void error_recovery(struct si_sm_data *bt, char *reason)
+static enum si_sm_result error_recovery(struct si_sm_data *bt,
+                                       unsigned char status,
+                                       unsigned char cCode)
 {
-       unsigned char status;
-       char buf[40]; /* For getting status */
+       char *reason;
 
-       bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */
+       bt->timeout = bt->BT_CAP_req2rsp;
 
-       status = BT_STATUS;
-       printk(KERN_DEBUG "BT: %s in %s %s\n", reason, STATE2TXT,
-              STATUS2TXT(buf));
+       switch (cCode) {
+       case IPMI_TIMEOUT_ERR:
+               reason = "timeout";
+               break;
+       default:
+               reason = "internal error";
+               break;
+       }
+
+       printk(KERN_WARNING "IPMI BT: %s in %s %s ",    /* open-ended line */
+               reason, STATE2TXT, STATUS2TXT);
 
+       /* Per the IPMI spec, retries are based on the sequence number
+          known only to this module, so manage a restart here. */
        (bt->error_retries)++;
-       if (bt->error_retries > BT_RETRY_LIMIT) {
-               printk(KERN_DEBUG "retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
-               bt->state = BT_STATE_HOSED;
-               if (!bt->nonzero_status)
-                       printk(KERN_ERR "IPMI: BT stuck, try power cycle\n");
-               else if (bt->error_retries <= BT_RETRY_LIMIT + 1) {
-                       printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n");
-                       bt->state = BT_STATE_RESET1;
-               }
-       return;
+       if (bt->error_retries < bt->BT_CAP_retries) {
+               printk("%d retries left\n",
+                       bt->BT_CAP_retries - bt->error_retries);
+               bt->state = BT_STATE_RESTART;
+               return SI_SM_CALL_WITHOUT_DELAY;
        }
 
-       /* Sometimes the BMC queues get in an "off-by-one" state...*/
-       if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) {
-               printk(KERN_DEBUG "retry B2H_WAIT\n");
-               return;
+       printk("failed %d retries, sending error response\n",
+               bt->BT_CAP_retries);
+       if (!bt->nonzero_status)
+               printk(KERN_ERR "IPMI BT: stuck, try power cycle\n");
+
+       /* this is most likely during insmod */
+       else if (bt->seq <= (unsigned char)(bt->BT_CAP_retries & 0xFF)) {
+               printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n");
+               bt->state = BT_STATE_RESET1;
+               return SI_SM_CALL_WITHOUT_DELAY;
        }
 
-       printk(KERN_DEBUG "restart command\n");
-       bt->state = BT_STATE_RESTART;
+       /* Concoct a useful error message, set up the next state, and
+          be done with this sequence. */
+
+       bt->state = BT_STATE_IDLE;
+       switch (cCode) {
+       case IPMI_TIMEOUT_ERR:
+               if (status & BT_B_BUSY) {
+                       cCode = IPMI_NODE_BUSY_ERR;
+                       bt->state = BT_STATE_LONG_BUSY;
+               }
+               break;
+       default:
+               break;
+       }
+       force_result(bt, cCode);
+       return SI_SM_TRANSACTION_COMPLETE;
 }
 
-/* Check the status and (possibly) advance the BT state machine.  The
-   default return is SI_SM_CALL_WITH_DELAY. */
+/* Check status and (usually) take action and change this state machine. */
 
 static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
 {
-       unsigned char status;
-       char buf[40]; /* For getting status */
+       unsigned char status, BT_CAP[8];
+       static enum bt_states last_printed = BT_STATE_PRINTME;
        int i;
 
        status = BT_STATUS;
        bt->nonzero_status |= status;
-
-       if ((bt_debug & BT_DEBUG_STATES) && (bt->state != bt->last_state))
+       if ((bt_debug & BT_DEBUG_STATES) && (bt->state != last_printed)) {
                printk(KERN_WARNING "BT: %s %s TO=%ld - %ld \n",
                        STATE2TXT,
-                       STATUS2TXT(buf),
+                       STATUS2TXT,
                        bt->timeout,
                        time);
-       bt->last_state = bt->state;
+               last_printed = bt->state;
+       }
 
-       if (bt->state == BT_STATE_HOSED)
-              return SI_SM_HOSED;
+       /* Commands that time out may still (eventually) provide a response.
+          This stale response will get in the way of a new response so remove
+          it if possible (hopefully during IDLE).  Even if it comes up later
+          it will be rejected by its (now-forgotten) seq number. */
+
+       if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) {
+               drain_BMC2HOST(bt);
+               BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+       }
 
-       if (bt->state != BT_STATE_IDLE) {       /* do timeout test */
+       if ((bt->state != BT_STATE_IDLE) &&
+           (bt->state <  BT_STATE_PRINTME)) {          /* check timeout */
                bt->timeout -= time;
-               if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
-                       error_recovery(bt, "timed out");
-                       return SI_SM_CALL_WITHOUT_DELAY;
-               }
+               if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1))
+                       return error_recovery(bt,
+                                             status,
+                                             IPMI_TIMEOUT_ERR);
        }
 
        switch (bt->state) {
 
-       case BT_STATE_IDLE:     /* check for asynchronous messages */
+       /* Idle state first checks for asynchronous messages from another
+          channel, then does some opportunistic housekeeping. */
+
+       case BT_STATE_IDLE:
                if (status & BT_SMS_ATN) {
                        BT_CONTROL(BT_SMS_ATN); /* clear it */
                        return SI_SM_ATTN;
                }
-               return SI_SM_IDLE;
 
-       case BT_STATE_XACTION_START:
-               if (status & BT_H_BUSY) {
+               if (status & BT_H_BUSY)         /* clear a leftover H_BUSY */
                        BT_CONTROL(BT_H_BUSY);
-                       break;
-               }
-               if (status & BT_B2H_ATN)
-                      break;
-               bt->state = BT_STATE_WRITE_BYTES;
-               return SI_SM_CALL_WITHOUT_DELAY;        /* for logging */
 
-       case BT_STATE_WRITE_BYTES:
+               /* Read BT capabilities if it hasn't been done yet */
+               if (!bt->BT_CAP_outreqs)
+                       BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN,
+                                       SI_SM_CALL_WITHOUT_DELAY);
+               bt->timeout = bt->BT_CAP_req2rsp;
+               BT_SI_SM_RETURN(SI_SM_IDLE);
+
+       case BT_STATE_XACTION_START:
                if (status & (BT_B_BUSY | BT_H2B_ATN))
-                      break;
+                       BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+               if (BT_STATUS & BT_H_BUSY)
+                       BT_CONTROL(BT_H_BUSY);  /* force clear */
+               BT_STATE_CHANGE(BT_STATE_WRITE_BYTES,
+                               SI_SM_CALL_WITHOUT_DELAY);
+
+       case BT_STATE_WRITE_BYTES:
+               if (status & BT_H_BUSY)
+                       BT_CONTROL(BT_H_BUSY);  /* clear */
                BT_CONTROL(BT_CLR_WR_PTR);
                write_all_bytes(bt);
-               BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */
-               bt->state = BT_STATE_WRITE_CONSUME;
-               return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
-
-       case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
-               if (status & (BT_H2B_ATN | BT_B_BUSY))
-                      break;
-               bt->state = BT_STATE_B2H_WAIT;
-               /* fall through with status */
-
-       /* Stay in BT_STATE_B2H_WAIT until a packet matches.  However, spinning
-          hard here, constantly reading status, seems to hold off the
-          generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
-
-       case BT_STATE_B2H_WAIT:
-               if (!(status & BT_B2H_ATN))
-                      break;
-
-               /* Assume ordered, uncached writes: no need to wait */
-               if (!(status & BT_H_BUSY))
-                      BT_CONTROL(BT_H_BUSY); /* set */
-               BT_CONTROL(BT_B2H_ATN);         /* clear it, ACK to the BMC */
-               BT_CONTROL(BT_CLR_RD_PTR);      /* reset the queue */
-               i = read_all_bytes(bt);
-               BT_CONTROL(BT_H_BUSY);          /* clear */
-               if (!i)                         /* Try this state again */
-                      break;
-               bt->state = BT_STATE_READ_END;
-               return SI_SM_CALL_WITHOUT_DELAY;        /* for logging */
-
-       case BT_STATE_READ_END:
-
-               /* I could wait on BT_H_BUSY to go clear for a truly clean
-                  exit.  However, this is already done in XACTION_START
-                  and the (possible) extra loop/status/possible wait affects
-                  performance.  So, as long as it works, just ignore H_BUSY */
-
-#ifdef MAKE_THIS_TRUE_IF_NECESSARY
+               BT_CONTROL(BT_H2B_ATN); /* can clear too fast to catch */
+               BT_STATE_CHANGE(BT_STATE_WRITE_CONSUME,
+                               SI_SM_CALL_WITHOUT_DELAY);
 
-               if (status & BT_H_BUSY)
-                      break;
-#endif
-               bt->seq++;
-               bt->state = BT_STATE_IDLE;
-               return SI_SM_TRANSACTION_COMPLETE;
+       case BT_STATE_WRITE_CONSUME:
+               if (status & (BT_B_BUSY | BT_H2B_ATN))
+                       BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+               BT_STATE_CHANGE(BT_STATE_READ_WAIT,
+                               SI_SM_CALL_WITHOUT_DELAY);
+
+       /* Spinning hard can suppress B2H_ATN and force a timeout */
+
+       case BT_STATE_READ_WAIT:
+               if (!(status & BT_B2H_ATN))
+                       BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+               BT_CONTROL(BT_H_BUSY);          /* set */
+
+               /* Uncached, ordered writes should just proceeed serially but
+                  some BMCs don't clear B2H_ATN with one hit.  Fast-path a
+                  workaround without too much penalty to the general case. */
+
+               BT_CONTROL(BT_B2H_ATN);         /* clear it to ACK the BMC */
+               BT_STATE_CHANGE(BT_STATE_CLEAR_B2H,
+                               SI_SM_CALL_WITHOUT_DELAY);
+
+       case BT_STATE_CLEAR_B2H:
+               if (status & BT_B2H_ATN) {      /* keep hitting it */
+                       BT_CONTROL(BT_B2H_ATN);
+                       BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
+               }
+               BT_STATE_CHANGE(BT_STATE_READ_BYTES,
+                               SI_SM_CALL_WITHOUT_DELAY);
+
+       case BT_STATE_READ_BYTES:
+               if (!(status & BT_H_BUSY))      /* check in case of retry */
+                       BT_CONTROL(BT_H_BUSY);
+               BT_CONTROL(BT_CLR_RD_PTR);      /* start of BMC2HOST buffer */
+               i = read_all_bytes(bt);         /* true == packet seq match */
+               BT_CONTROL(BT_H_BUSY);          /* NOW clear */
+               if (!i)                         /* Not my message */
+                       BT_STATE_CHANGE(BT_STATE_READ_WAIT,
+                                       SI_SM_CALL_WITHOUT_DELAY);
+               bt->state = bt->complete;
+               return bt->state == BT_STATE_IDLE ?     /* where to next? */
+                       SI_SM_TRANSACTION_COMPLETE :    /* normal */
+                       SI_SM_CALL_WITHOUT_DELAY;       /* Startup magic */
+
+       case BT_STATE_LONG_BUSY:        /* For example: after FW update */
+               if (!(status & BT_B_BUSY)) {
+                       reset_flags(bt);        /* next state is now IDLE */
+                       bt_init_data(bt, bt->io);
+               }
+               return SI_SM_CALL_WITH_DELAY;   /* No repeat printing */
 
        case BT_STATE_RESET1:
-               reset_flags(bt);
-               bt->timeout = BT_RESET_DELAY;
-               bt->state = BT_STATE_RESET2;
-               break;
+               reset_flags(bt);
+               drain_BMC2HOST(bt);
+               BT_STATE_CHANGE(BT_STATE_RESET2,
+                               SI_SM_CALL_WITH_DELAY);
 
        case BT_STATE_RESET2:           /* Send a soft reset */
                BT_CONTROL(BT_CLR_WR_PTR);
@@ -464,29 +581,59 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                HOST2BMC(42);           /* Sequence number */
                HOST2BMC(3);            /* Cmd == Soft reset */
                BT_CONTROL(BT_H2B_ATN);
-               bt->state = BT_STATE_RESET3;
-               break;
+               bt->timeout = BT_RESET_DELAY * 1000000;
+               BT_STATE_CHANGE(BT_STATE_RESET3,
+                               SI_SM_CALL_WITH_DELAY);
 
-       case BT_STATE_RESET3:
+       case BT_STATE_RESET3:           /* Hold off everything for a bit */
                if (bt->timeout > 0)
-                      return SI_SM_CALL_WITH_DELAY;
-               bt->state = BT_STATE_RESTART;   /* printk in debug modes */
-               break;
+                       return SI_SM_CALL_WITH_DELAY;
+               drain_BMC2HOST(bt);
+               BT_STATE_CHANGE(BT_STATE_RESTART,
+                               SI_SM_CALL_WITH_DELAY);
 
-       case BT_STATE_RESTART:          /* don't reset retries! */
-               reset_flags(bt);
-               bt->write_data[2] = ++bt->seq;
+       case BT_STATE_RESTART:          /* don't reset retries or seq! */
                bt->read_count = 0;
                bt->nonzero_status = 0;
-               bt->timeout = BT_NORMAL_TIMEOUT;
-               bt->state = BT_STATE_XACTION_START;
-               break;
-
-       default:        /* HOSED is supposed to be caught much earlier */
-               error_recovery(bt, "internal logic error");
-               break;
-       }
-       return SI_SM_CALL_WITH_DELAY;
+               bt->timeout = bt->BT_CAP_req2rsp;
+               BT_STATE_CHANGE(BT_STATE_XACTION_START,
+                               SI_SM_CALL_WITH_DELAY);
+
+       /* Get BT Capabilities, using timing of upper level state machine.
+          Set outreqs to prevent infinite loop on timeout. */
+       case BT_STATE_CAPABILITIES_BEGIN:
+               bt->BT_CAP_outreqs = 1;
+               {
+                       unsigned char GetBT_CAP[] = { 0x18, 0x36 };
+                       bt->state = BT_STATE_IDLE;
+                       bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP));
+               }
+               bt->complete = BT_STATE_CAPABILITIES_END;
+               BT_STATE_CHANGE(BT_STATE_XACTION_START,
+                               SI_SM_CALL_WITH_DELAY);
+
+       case BT_STATE_CAPABILITIES_END:
+               i = bt_get_result(bt, BT_CAP, sizeof(BT_CAP));
+               bt_init_data(bt, bt->io);
+               if ((i == 8) && !BT_CAP[2]) {
+                       bt->BT_CAP_outreqs = BT_CAP[3];
+                       bt->BT_CAP_req2rsp = BT_CAP[6] * 1000000;
+                       bt->BT_CAP_retries = BT_CAP[7];
+               } else
+                       printk(KERN_WARNING "IPMI BT: using default values\n");
+               if (!bt->BT_CAP_outreqs)
+                       bt->BT_CAP_outreqs = 1;
+               printk(KERN_WARNING "IPMI BT: req2rsp=%ld secs retries=%d\n",
+                       bt->BT_CAP_req2rsp / 1000000L, bt->BT_CAP_retries);
+               bt->timeout = bt->BT_CAP_req2rsp;
+               return SI_SM_CALL_WITHOUT_DELAY;
+
+       default:        /* should never occur */
+               return error_recovery(bt,
+                                     status,
+                                     IPMI_ERR_UNSPECIFIED);
+       }
+       return SI_SM_CALL_WITH_DELAY;
 }
 
 static int bt_detect(struct si_sm_data *bt)
@@ -497,7 +644,7 @@ static int bt_detect(struct si_sm_data *bt)
           test that first.  The calling routine uses negative logic. */
 
        if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
-              return 1;
+               return 1;
        reset_flags(bt);
        return 0;
 }
@@ -513,11 +660,11 @@ static int bt_size(void)
 
 struct si_sm_handlers bt_smi_handlers =
 {
-       .init_data         = bt_init_data,
-       .start_transaction = bt_start_transaction,
-       .get_result        = bt_get_result,
-       .event             = bt_event,
-       .detect            = bt_detect,
-       .cleanup           = bt_cleanup,
-       .size              = bt_size,
+       .init_data              = bt_init_data,
+       .start_transaction      = bt_start_transaction,
+       .get_result             = bt_get_result,
+       .event                  = bt_event,
+       .detect                 = bt_detect,
+       .cleanup                = bt_cleanup,
+       .size                   = bt_size,
 };
index 81fcf0c..ff2d052 100644 (file)
@@ -596,6 +596,31 @@ static int ipmi_ioctl(struct inode  *inode,
                rv = 0;
                break;
        }
+
+       case IPMICTL_GET_MAINTENANCE_MODE_CMD:
+       {
+               int mode;
+
+               mode = ipmi_get_maintenance_mode(priv->user);
+               if (copy_to_user(arg, &mode, sizeof(mode))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               rv = 0;
+               break;
+       }
+
+       case IPMICTL_SET_MAINTENANCE_MODE_CMD:
+       {
+               int mode;
+
+               if (copy_from_user(&mode, arg, sizeof(mode))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               rv = ipmi_set_maintenance_mode(priv->user, mode);
+               break;
+       }
        }
   
        return rv;
@@ -773,7 +798,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                if (copy_to_user(precv64, &recv64, sizeof(recv64)))
                        return -EFAULT;
 
-               rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+               rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep,
                                ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
                                 ? IPMICTL_RECEIVE_MSG
                                 : IPMICTL_RECEIVE_MSG_TRUNC),
@@ -790,7 +815,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                return rc;
        }
        default:
-               return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+               return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg);
        }
 }
 #endif
@@ -809,7 +834,7 @@ static const struct file_operations ipmi_fops = {
 
 #define DEVICE_NAME     "ipmidev"
 
-static int ipmi_major = 0;
+static int ipmi_major;
 module_param(ipmi_major, int, 0);
 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
                 " default, or if you set it to zero, it will choose the next"
index 2062675..c1b8228 100644 (file)
@@ -93,8 +93,8 @@ enum kcs_states {
                                   state machine. */
 };
 
-#define MAX_KCS_READ_SIZE 80
-#define MAX_KCS_WRITE_SIZE 80
+#define MAX_KCS_READ_SIZE IPMI_MAX_MSG_LENGTH
+#define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH
 
 /* Timeouts in microseconds. */
 #define IBF_RETRY_TIMEOUT 1000000
@@ -261,12 +261,14 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
 {
        unsigned int i;
 
-       if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
-               return -1;
-       }
-       if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
-               return -2;
-       }
+       if (size < 2)
+               return IPMI_REQ_LEN_INVALID_ERR;
+       if (size > MAX_KCS_WRITE_SIZE)
+               return IPMI_REQ_LEN_EXCEEDED_ERR;
+
+       if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED))
+               return IPMI_NOT_IN_MY_STATE_ERR;
+
        if (kcs_debug & KCS_DEBUG_MSG) {
                printk(KERN_DEBUG "start_kcs_transaction -");
                for (i = 0; i < size; i ++) {
index c47add8..4e4691a 100644 (file)
 
 #define PFX "IPMI message handler: "
 
-#define IPMI_DRIVER_VERSION "39.0"
+#define IPMI_DRIVER_VERSION "39.1"
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
 
-static int initialized = 0;
+static int initialized;
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_ipmi_root = NULL;
+static struct proc_dir_entry *proc_ipmi_root;
 #endif /* CONFIG_PROC_FS */
 
+/* Remain in auto-maintenance mode for this amount of time (in ms). */
+#define IPMI_MAINTENANCE_MODE_TIMEOUT 30000
+
 #define MAX_EVENTS_IN_QUEUE    25
 
 /* Don't let a message sit in a queue forever, always time it with at lest
@@ -193,17 +196,28 @@ struct ipmi_smi
 
        struct kref refcount;
 
+       /* Used for a list of interfaces. */
+       struct list_head link;
+
        /* The list of upper layers that are using me.  seq_lock
         * protects this. */
        struct list_head users;
 
+       /* Information to supply to users. */
+       unsigned char ipmi_version_major;
+       unsigned char ipmi_version_minor;
+
        /* Used for wake ups at startup. */
        wait_queue_head_t waitq;
 
        struct bmc_device *bmc;
        char *my_dev_name;
+       char *sysfs_name;
 
-       /* This is the lower-layer's sender routine. */
+       /* This is the lower-layer's sender routine.  Note that you
+        * must either be holding the ipmi_interfaces_mutex or be in
+        * an umpreemptible region to use this.  You must fetch the
+        * value into a local variable and make sure it is not NULL. */
        struct ipmi_smi_handlers *handlers;
        void                     *send_info;
 
@@ -242,6 +256,7 @@ struct ipmi_smi
        spinlock_t       events_lock; /* For dealing with event stuff. */
        struct list_head waiting_events;
        unsigned int     waiting_events_count; /* How many events in queue? */
+       int              delivering_events;
 
        /* The event receiver for my BMC, only really used at panic
           shutdown as a place to store this. */
@@ -250,6 +265,12 @@ struct ipmi_smi
        unsigned char local_sel_device;
        unsigned char local_event_generator;
 
+       /* For handling of maintenance mode. */
+       int maintenance_mode;
+       int maintenance_mode_enable;
+       int auto_maintenance_timeout;
+       spinlock_t maintenance_mode_lock; /* Used in a timer... */
+
        /* A cheap hack, if this is non-null and a message to an
           interface comes in with a NULL user, call this routine with
           it.  Note that the message will still be freed by the
@@ -338,13 +359,6 @@ struct ipmi_smi
 };
 #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
 
-/* Used to mark an interface entry that cannot be used but is not a
- * free entry, either, primarily used at creation and deletion time so
- * a slot doesn't get reused too quickly. */
-#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1))
-#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \
-                                  || (i == IPMI_INVALID_INTERFACE_ENTRY))
-
 /**
  * The driver model view of the IPMI messaging driver.
  */
@@ -354,16 +368,13 @@ static struct device_driver ipmidriver = {
 };
 static DEFINE_MUTEX(ipmidriver_mutex);
 
-#define MAX_IPMI_INTERFACES 4
-static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
-
-/* Directly protects the ipmi_interfaces data structure. */
-static DEFINE_SPINLOCK(interfaces_lock);
+static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces);
+static DEFINE_MUTEX(ipmi_interfaces_mutex);
 
 /* List of watchers that want to know when smi's are added and
    deleted. */
 static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
-static DECLARE_RWSEM(smi_watchers_sem);
+static DEFINE_MUTEX(smi_watchers_mutex);
 
 
 static void free_recv_msg_list(struct list_head *q)
@@ -423,48 +434,84 @@ static void intf_free(struct kref *ref)
        kfree(intf);
 }
 
+struct watcher_entry {
+       int              intf_num;
+       ipmi_smi_t       intf;
+       struct list_head link;
+};
+
 int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
 {
-       int           i;
-       unsigned long flags;
+       ipmi_smi_t intf;
+       struct list_head to_deliver = LIST_HEAD_INIT(to_deliver);
+       struct watcher_entry *e, *e2;
+
+       mutex_lock(&smi_watchers_mutex);
 
-       down_write(&smi_watchers_sem);
-       list_add(&(watcher->link), &smi_watchers);
-       up_write(&smi_watchers_sem);
-       spin_lock_irqsave(&interfaces_lock, flags);
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               ipmi_smi_t intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
+       mutex_lock(&ipmi_interfaces_mutex);
+
+       /* Build a list of things to deliver. */
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+               if (intf->intf_num == -1)
                        continue;
-               spin_unlock_irqrestore(&interfaces_lock, flags);
-               watcher->new_smi(i, intf->si_dev);
-               spin_lock_irqsave(&interfaces_lock, flags);
+               e = kmalloc(sizeof(*e), GFP_KERNEL);
+               if (!e)
+                       goto out_err;
+               kref_get(&intf->refcount);
+               e->intf = intf;
+               e->intf_num = intf->intf_num;
+               list_add_tail(&e->link, &to_deliver);
        }
-       spin_unlock_irqrestore(&interfaces_lock, flags);
+
+       /* We will succeed, so add it to the list. */
+       list_add(&watcher->link, &smi_watchers);
+
+       mutex_unlock(&ipmi_interfaces_mutex);
+
+       list_for_each_entry_safe(e, e2, &to_deliver, link) {
+               list_del(&e->link);
+               watcher->new_smi(e->intf_num, e->intf->si_dev);
+               kref_put(&e->intf->refcount, intf_free);
+               kfree(e);
+       }
+
+       mutex_unlock(&smi_watchers_mutex);
+
        return 0;
+
+ out_err:
+       mutex_unlock(&ipmi_interfaces_mutex);
+       mutex_unlock(&smi_watchers_mutex);
+       list_for_each_entry_safe(e, e2, &to_deliver, link) {
+               list_del(&e->link);
+               kref_put(&e->intf->refcount, intf_free);
+               kfree(e);
+       }
+       return -ENOMEM;
 }
 
 int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
 {
-       down_write(&smi_watchers_sem);
+       mutex_lock(&smi_watchers_mutex);
        list_del(&(watcher->link));
-       up_write(&smi_watchers_sem);
+       mutex_unlock(&smi_watchers_mutex);
        return 0;
 }
 
+/*
+ * Must be called with smi_watchers_mutex held.
+ */
 static void
 call_smi_watchers(int i, struct device *dev)
 {
        struct ipmi_smi_watcher *w;
 
-       down_read(&smi_watchers_sem);
        list_for_each_entry(w, &smi_watchers, link) {
                if (try_module_get(w->owner)) {
                        w->new_smi(i, dev);
                        module_put(w->owner);
                }
        }
-       up_read(&smi_watchers_sem);
 }
 
 static int
@@ -590,6 +637,17 @@ static void deliver_response(struct ipmi_recv_msg *msg)
        }
 }
 
+static void
+deliver_err_response(struct ipmi_recv_msg *msg, int err)
+{
+       msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+       msg->msg_data[0] = err;
+       msg->msg.netfn |= 1; /* Convert to a response. */
+       msg->msg.data_len = 1;
+       msg->msg.data = msg->msg_data;
+       deliver_response(msg);
+}
+
 /* Find the next sequence number not being used and add the given
    message with the given timeout to the sequence table.  This must be
    called with the interface's seq_lock held. */
@@ -727,14 +785,8 @@ static int intf_err_seq(ipmi_smi_t   intf,
        }
        spin_unlock_irqrestore(&(intf->seq_lock), flags);
 
-       if (msg) {
-               msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
-               msg->msg_data[0] = err;
-               msg->msg.netfn |= 1; /* Convert to a response. */
-               msg->msg.data_len = 1;
-               msg->msg.data = msg->msg_data;
-               deliver_response(msg);
-       }
+       if (msg)
+               deliver_err_response(msg, err);
 
        return rv;
 }
@@ -776,17 +828,18 @@ int ipmi_create_user(unsigned int          if_num,
        if (!new_user)
                return -ENOMEM;
 
-       spin_lock_irqsave(&interfaces_lock, flags);
-       intf = ipmi_interfaces[if_num];
-       if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) {
-               spin_unlock_irqrestore(&interfaces_lock, flags);
-               rv = -EINVAL;
-               goto out_kfree;
+       mutex_lock(&ipmi_interfaces_mutex);
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+               if (intf->intf_num == if_num)
+                       goto found;
        }
+       /* Not found, return an error */
+       rv = -EINVAL;
+       goto out_kfree;
 
+ found:
        /* Note that each existing user holds a refcount to the interface. */
        kref_get(&intf->refcount);
-       spin_unlock_irqrestore(&interfaces_lock, flags);
 
        kref_init(&new_user->refcount);
        new_user->handler = handler;
@@ -807,6 +860,10 @@ int ipmi_create_user(unsigned int          if_num,
                }
        }
 
+       /* Hold the lock so intf->handlers is guaranteed to be good
+        * until now */
+       mutex_unlock(&ipmi_interfaces_mutex);
+
        new_user->valid = 1;
        spin_lock_irqsave(&intf->seq_lock, flags);
        list_add_rcu(&new_user->link, &intf->users);
@@ -817,6 +874,7 @@ int ipmi_create_user(unsigned int          if_num,
 out_kref:
        kref_put(&intf->refcount, intf_free);
 out_kfree:
+       mutex_unlock(&ipmi_interfaces_mutex);
        kfree(new_user);
        return rv;
 }
@@ -846,6 +904,7 @@ int ipmi_destroy_user(ipmi_user_t user)
                    && (intf->seq_table[i].recv_msg->user == user))
                {
                        intf->seq_table[i].inuse = 0;
+                       ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
                }
        }
        spin_unlock_irqrestore(&intf->seq_lock, flags);
@@ -872,9 +931,13 @@ int ipmi_destroy_user(ipmi_user_t user)
                kfree(rcvr);
        }
 
-       module_put(intf->handlers->owner);
-       if (intf->handlers->dec_usecount)
-               intf->handlers->dec_usecount(intf->send_info);
+       mutex_lock(&ipmi_interfaces_mutex);
+       if (intf->handlers) {
+               module_put(intf->handlers->owner);
+               if (intf->handlers->dec_usecount)
+                       intf->handlers->dec_usecount(intf->send_info);
+       }
+       mutex_unlock(&ipmi_interfaces_mutex);
 
        kref_put(&intf->refcount, intf_free);
 
@@ -887,8 +950,8 @@ void ipmi_get_version(ipmi_user_t   user,
                      unsigned char *major,
                      unsigned char *minor)
 {
-       *major = ipmi_version_major(&user->intf->bmc->id);
-       *minor = ipmi_version_minor(&user->intf->bmc->id);
+       *major = user->intf->ipmi_version_major;
+       *minor = user->intf->ipmi_version_minor;
 }
 
 int ipmi_set_my_address(ipmi_user_t   user,
@@ -931,6 +994,65 @@ int ipmi_get_my_LUN(ipmi_user_t   user,
        return 0;
 }
 
+int ipmi_get_maintenance_mode(ipmi_user_t user)
+{
+       int           mode;
+       unsigned long flags;
+
+       spin_lock_irqsave(&user->intf->maintenance_mode_lock, flags);
+       mode = user->intf->maintenance_mode;
+       spin_unlock_irqrestore(&user->intf->maintenance_mode_lock, flags);
+
+       return mode;
+}
+EXPORT_SYMBOL(ipmi_get_maintenance_mode);
+
+static void maintenance_mode_update(ipmi_smi_t intf)
+{
+       if (intf->handlers->set_maintenance_mode)
+               intf->handlers->set_maintenance_mode(
+                       intf->send_info, intf->maintenance_mode_enable);
+}
+
+int ipmi_set_maintenance_mode(ipmi_user_t user, int mode)
+{
+       int           rv = 0;
+       unsigned long flags;
+       ipmi_smi_t    intf = user->intf;
+
+       spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
+       if (intf->maintenance_mode != mode) {
+               switch (mode) {
+               case IPMI_MAINTENANCE_MODE_AUTO:
+                       intf->maintenance_mode = mode;
+                       intf->maintenance_mode_enable
+                               = (intf->auto_maintenance_timeout > 0);
+                       break;
+
+               case IPMI_MAINTENANCE_MODE_OFF:
+                       intf->maintenance_mode = mode;
+                       intf->maintenance_mode_enable = 0;
+                       break;
+
+               case IPMI_MAINTENANCE_MODE_ON:
+                       intf->maintenance_mode = mode;
+                       intf->maintenance_mode_enable = 1;
+                       break;
+
+               default:
+                       rv = -EINVAL;
+                       goto out_unlock;
+               }
+
+               maintenance_mode_update(intf);
+       }
+ out_unlock:
+       spin_unlock_irqrestore(&intf->maintenance_mode_lock, flags);
+
+       return rv;
+}
+EXPORT_SYMBOL(ipmi_set_maintenance_mode);
+
 int ipmi_set_gets_events(ipmi_user_t user, int val)
 {
        unsigned long        flags;
@@ -943,20 +1065,33 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
        spin_lock_irqsave(&intf->events_lock, flags);
        user->gets_events = val;
 
-       if (val) {
-               /* Deliver any queued events. */
+       if (intf->delivering_events)
+               /*
+                * Another thread is delivering events for this, so
+                * let it handle any new events.
+                */
+               goto out;
+
+       /* Deliver any queued events. */
+       while (user->gets_events && !list_empty(&intf->waiting_events)) {
                list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
                        list_move_tail(&msg->link, &msgs);
                intf->waiting_events_count = 0;
-       }
 
-       /* Hold the events lock while doing this to preserve order. */
-       list_for_each_entry_safe(msg, msg2, &msgs, link) {
-               msg->user = user;
-               kref_get(&user->refcount);
-               deliver_response(msg);
+               intf->delivering_events = 1;
+               spin_unlock_irqrestore(&intf->events_lock, flags);
+
+               list_for_each_entry_safe(msg, msg2, &msgs, link) {
+                       msg->user = user;
+                       kref_get(&user->refcount);
+                       deliver_response(msg);
+               }
+
+               spin_lock_irqsave(&intf->events_lock, flags);
+               intf->delivering_events = 0;
        }
 
+ out:
        spin_unlock_irqrestore(&intf->events_lock, flags);
 
        return 0;
@@ -1067,7 +1202,8 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
 void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
 {
        ipmi_smi_t intf = user->intf;
-       intf->handlers->set_run_to_completion(intf->send_info, val);
+       if (intf->handlers)
+               intf->handlers->set_run_to_completion(intf->send_info, val);
 }
 
 static unsigned char
@@ -1178,10 +1314,11 @@ static int i_ipmi_request(ipmi_user_t          user,
                          int                  retries,
                          unsigned int         retry_time_ms)
 {
-       int                  rv = 0;
-       struct ipmi_smi_msg  *smi_msg;
-       struct ipmi_recv_msg *recv_msg;
-       unsigned long        flags;
+       int                      rv = 0;
+       struct ipmi_smi_msg      *smi_msg;
+       struct ipmi_recv_msg     *recv_msg;
+       unsigned long            flags;
+       struct ipmi_smi_handlers *handlers;
 
 
        if (supplied_recv) {
@@ -1204,6 +1341,13 @@ static int i_ipmi_request(ipmi_user_t          user,
                }
        }
 
+       rcu_read_lock();
+       handlers = intf->handlers;
+       if (!handlers) {
+               rv = -ENODEV;
+               goto out_err;
+       }
+
        recv_msg->user = user;
        if (user)
                kref_get(&user->refcount);
@@ -1246,6 +1390,24 @@ static int i_ipmi_request(ipmi_user_t          user,
                        goto out_err;
                }
 
+               if (((msg->netfn == IPMI_NETFN_APP_REQUEST)
+                     && ((msg->cmd == IPMI_COLD_RESET_CMD)
+                         || (msg->cmd == IPMI_WARM_RESET_CMD)))
+                    || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST))
+               {
+                       spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
+                       intf->auto_maintenance_timeout
+                               = IPMI_MAINTENANCE_MODE_TIMEOUT;
+                       if (!intf->maintenance_mode
+                           && !intf->maintenance_mode_enable)
+                       {
+                               intf->maintenance_mode_enable = 1;
+                               maintenance_mode_update(intf);
+                       }
+                       spin_unlock_irqrestore(&intf->maintenance_mode_lock,
+                                              flags);
+               }
+
                if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
                        spin_lock_irqsave(&intf->counter_lock, flags);
                        intf->sent_invalid_commands++;
@@ -1520,11 +1682,14 @@ static int i_ipmi_request(ipmi_user_t          user,
                printk("\n");
        }
 #endif
-       intf->handlers->sender(intf->send_info, smi_msg, priority);
+
+       handlers->sender(intf->send_info, smi_msg, priority);
+       rcu_read_unlock();
 
        return 0;
 
  out_err:
+       rcu_read_unlock();
        ipmi_free_smi_msg(smi_msg);
        ipmi_free_recv_msg(recv_msg);
        return rv;
@@ -1604,6 +1769,7 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                              -1, 0);
 }
 
+#ifdef CONFIG_PROC_FS
 static int ipmb_file_read_proc(char *page, char **start, off_t off,
                               int count, int *eof, void *data)
 {
@@ -1692,6 +1858,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
 
        return (out - ((char *) page));
 }
+#endif /* CONFIG_PROC_FS */
 
 int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
                            read_proc_t *read_proc, write_proc_t *write_proc,
@@ -1817,13 +1984,12 @@ static int __find_bmc_prod_dev_id(struct device *dev, void *data)
        struct bmc_device *bmc = dev_get_drvdata(dev);
 
        return (bmc->id.product_id == id->product_id
-               && bmc->id.product_id == id->product_id
                && bmc->id.device_id == id->device_id);
 }
 
 static struct bmc_device *ipmi_find_bmc_prod_dev_id(
        struct device_driver *drv,
-       unsigned char product_id, unsigned char device_id)
+       unsigned int product_id, unsigned char device_id)
 {
        struct prod_dev_id id = {
                .product_id = product_id,
@@ -1940,6 +2106,9 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr,
 
 static void remove_files(struct bmc_device *bmc)
 {
+       if (!bmc->dev)
+               return;
+
        device_remove_file(&bmc->dev->dev,
                           &bmc->device_id_attr);
        device_remove_file(&bmc->dev->dev,
@@ -1981,7 +2150,11 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf)
 {
        struct bmc_device *bmc = intf->bmc;
 
-       sysfs_remove_link(&intf->si_dev->kobj, "bmc");
+       if (intf->sysfs_name) {
+               sysfs_remove_link(&intf->si_dev->kobj, intf->sysfs_name);
+               kfree(intf->sysfs_name);
+               intf->sysfs_name = NULL;
+       }
        if (intf->my_dev_name) {
                sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name);
                kfree(intf->my_dev_name);
@@ -1990,6 +2163,7 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf)
 
        mutex_lock(&ipmidriver_mutex);
        kref_put(&bmc->refcount, cleanup_bmc_device);
+       intf->bmc = NULL;
        mutex_unlock(&ipmidriver_mutex);
 }
 
@@ -1997,6 +2171,56 @@ static int create_files(struct bmc_device *bmc)
 {
        int err;
 
+       bmc->device_id_attr.attr.name = "device_id";
+       bmc->device_id_attr.attr.owner = THIS_MODULE;
+       bmc->device_id_attr.attr.mode = S_IRUGO;
+       bmc->device_id_attr.show = device_id_show;
+
+       bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
+       bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
+       bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
+       bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
+
+       bmc->revision_attr.attr.name = "revision";
+       bmc->revision_attr.attr.owner = THIS_MODULE;
+       bmc->revision_attr.attr.mode = S_IRUGO;
+       bmc->revision_attr.show = revision_show;
+
+       bmc->firmware_rev_attr.attr.name = "firmware_revision";
+       bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
+       bmc->firmware_rev_attr.attr.mode = S_IRUGO;
+       bmc->firmware_rev_attr.show = firmware_rev_show;
+
+       bmc->version_attr.attr.name = "ipmi_version";
+       bmc->version_attr.attr.owner = THIS_MODULE;
+       bmc->version_attr.attr.mode = S_IRUGO;
+       bmc->version_attr.show = ipmi_version_show;
+
+       bmc->add_dev_support_attr.attr.name = "additional_device_support";
+       bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
+       bmc->add_dev_support_attr.attr.mode = S_IRUGO;
+       bmc->add_dev_support_attr.show = add_dev_support_show;
+
+       bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
+       bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
+       bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
+       bmc->manufacturer_id_attr.show = manufacturer_id_show;
+
+       bmc->product_id_attr.attr.name = "product_id";
+       bmc->product_id_attr.attr.owner = THIS_MODULE;
+       bmc->product_id_attr.attr.mode = S_IRUGO;
+       bmc->product_id_attr.show = product_id_show;
+
+       bmc->guid_attr.attr.name = "guid";
+       bmc->guid_attr.attr.owner = THIS_MODULE;
+       bmc->guid_attr.attr.mode = S_IRUGO;
+       bmc->guid_attr.show = guid_show;
+
+       bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
+       bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
+       bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
+       bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
+
        err = device_create_file(&bmc->dev->dev,
                           &bmc->device_id_attr);
        if (err) goto out;
@@ -2066,7 +2290,8 @@ out:
        return err;
 }
 
-static int ipmi_bmc_register(ipmi_smi_t intf)
+static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
+                            const char *sysfs_name)
 {
        int               rv;
        struct bmc_device *bmc = intf->bmc;
@@ -2106,9 +2331,38 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
                       bmc->id.product_id,
                       bmc->id.device_id);
        } else {
-               bmc->dev = platform_device_alloc("ipmi_bmc",
-                                                bmc->id.device_id);
+               char name[14];
+               unsigned char orig_dev_id = bmc->id.device_id;
+               int warn_printed = 0;
+
+               snprintf(name, sizeof(name),
+                        "ipmi_bmc.%4.4x", bmc->id.product_id);
+
+               while (ipmi_find_bmc_prod_dev_id(&ipmidriver,
+                                                bmc->id.product_id,
+                                                bmc->id.device_id)) {
+                       if (!warn_printed) {
+                               printk(KERN_WARNING PFX
+                                      "This machine has two different BMCs"
+                                      " with the same product id and device"
+                                      " id.  This is an error in the"
+                                      " firmware, but incrementing the"
+                                      " device id to work around the problem."
+                                      " Prod ID = 0x%x, Dev ID = 0x%x\n",
+                                      bmc->id.product_id, bmc->id.device_id);
+                               warn_printed = 1;
+                       }
+                       bmc->id.device_id++; /* Wraps at 255 */
+                       if (bmc->id.device_id == orig_dev_id) {
+                               printk(KERN_ERR PFX
+                                      "Out of device ids!\n");
+                               break;
+                       }
+               }
+
+               bmc->dev = platform_device_alloc(name, bmc->id.device_id);
                if (!bmc->dev) {
+                       mutex_unlock(&ipmidriver_mutex);
                        printk(KERN_ERR
                               "ipmi_msghandler:"
                               " Unable to allocate platform device\n");
@@ -2121,6 +2375,8 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
                rv = platform_device_add(bmc->dev);
                mutex_unlock(&ipmidriver_mutex);
                if (rv) {
+                       platform_device_put(bmc->dev);
+                       bmc->dev = NULL;
                        printk(KERN_ERR
                               "ipmi_msghandler:"
                               " Unable to register bmc device: %d\n",
@@ -2130,57 +2386,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
                        return rv;
                }
 
-               bmc->device_id_attr.attr.name = "device_id";
-               bmc->device_id_attr.attr.owner = THIS_MODULE;
-               bmc->device_id_attr.attr.mode = S_IRUGO;
-               bmc->device_id_attr.show = device_id_show;
-
-               bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
-               bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
-               bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
-               bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
-
-               bmc->revision_attr.attr.name = "revision";
-               bmc->revision_attr.attr.owner = THIS_MODULE;
-               bmc->revision_attr.attr.mode = S_IRUGO;
-               bmc->revision_attr.show = revision_show;
-
-               bmc->firmware_rev_attr.attr.name = "firmware_revision";
-               bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
-               bmc->firmware_rev_attr.attr.mode = S_IRUGO;
-               bmc->firmware_rev_attr.show = firmware_rev_show;
-
-               bmc->version_attr.attr.name = "ipmi_version";
-               bmc->version_attr.attr.owner = THIS_MODULE;
-               bmc->version_attr.attr.mode = S_IRUGO;
-               bmc->version_attr.show = ipmi_version_show;
-
-               bmc->add_dev_support_attr.attr.name
-                       = "additional_device_support";
-               bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
-               bmc->add_dev_support_attr.attr.mode = S_IRUGO;
-               bmc->add_dev_support_attr.show = add_dev_support_show;
-
-               bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
-               bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
-               bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
-               bmc->manufacturer_id_attr.show = manufacturer_id_show;
-
-               bmc->product_id_attr.attr.name = "product_id";
-               bmc->product_id_attr.attr.owner = THIS_MODULE;
-               bmc->product_id_attr.attr.mode = S_IRUGO;
-               bmc->product_id_attr.show = product_id_show;
-
-               bmc->guid_attr.attr.name = "guid";
-               bmc->guid_attr.attr.owner = THIS_MODULE;
-               bmc->guid_attr.attr.mode = S_IRUGO;
-               bmc->guid_attr.show = guid_show;
-
-               bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
-               bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
-               bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
-               bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
-
                rv = create_files(bmc);
                if (rv) {
                        mutex_lock(&ipmidriver_mutex);
@@ -2202,29 +2407,44 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
         * create symlink from system interface device to bmc device
         * and back.
         */
+       intf->sysfs_name = kstrdup(sysfs_name, GFP_KERNEL);
+       if (!intf->sysfs_name) {
+               rv = -ENOMEM;
+               printk(KERN_ERR
+                      "ipmi_msghandler: allocate link to BMC: %d\n",
+                      rv);
+               goto out_err;
+       }
+
        rv = sysfs_create_link(&intf->si_dev->kobj,
-                              &bmc->dev->dev.kobj, "bmc");
+                              &bmc->dev->dev.kobj, intf->sysfs_name);
        if (rv) {
+               kfree(intf->sysfs_name);
+               intf->sysfs_name = NULL;
                printk(KERN_ERR
                       "ipmi_msghandler: Unable to create bmc symlink: %d\n",
                       rv);
                goto out_err;
        }
 
-       size = snprintf(dummy, 0, "ipmi%d", intf->intf_num);
+       size = snprintf(dummy, 0, "ipmi%d", ifnum);
        intf->my_dev_name = kmalloc(size+1, GFP_KERNEL);
        if (!intf->my_dev_name) {
+               kfree(intf->sysfs_name);
+               intf->sysfs_name = NULL;
                rv = -ENOMEM;
                printk(KERN_ERR
                       "ipmi_msghandler: allocate link from BMC: %d\n",
                       rv);
                goto out_err;
        }
-       snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num);
+       snprintf(intf->my_dev_name, size+1, "ipmi%d", ifnum);
 
        rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj,
                               intf->my_dev_name);
        if (rv) {
+               kfree(intf->sysfs_name);
+               intf->sysfs_name = NULL;
                kfree(intf->my_dev_name);
                intf->my_dev_name = NULL;
                printk(KERN_ERR
@@ -2409,17 +2629,14 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                      void                     *send_info,
                      struct ipmi_device_id    *device_id,
                      struct device            *si_dev,
+                     const char               *sysfs_name,
                      unsigned char            slave_addr)
 {
        int              i, j;
        int              rv;
        ipmi_smi_t       intf;
-       unsigned long    flags;
-       int              version_major;
-       int              version_minor;
-
-       version_major = ipmi_version_major(device_id);
-       version_minor = ipmi_version_minor(device_id);
+       ipmi_smi_t       tintf;
+       struct list_head *link;
 
        /* Make sure the driver is actually initialized, this handles
           problems with initialization order. */
@@ -2437,12 +2654,16 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        if (!intf)
                return -ENOMEM;
        memset(intf, 0, sizeof(*intf));
+
+       intf->ipmi_version_major = ipmi_version_major(device_id);
+       intf->ipmi_version_minor = ipmi_version_minor(device_id);
+
        intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL);
        if (!intf->bmc) {
                kfree(intf);
                return -ENOMEM;
        }
-       intf->intf_num = -1;
+       intf->intf_num = -1; /* Mark it invalid for now. */
        kref_init(&intf->refcount);
        intf->bmc->id = *device_id;
        intf->si_dev = si_dev;
@@ -2470,26 +2691,30 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        INIT_LIST_HEAD(&intf->waiting_events);
        intf->waiting_events_count = 0;
        mutex_init(&intf->cmd_rcvrs_mutex);
+       spin_lock_init(&intf->maintenance_mode_lock);
        INIT_LIST_HEAD(&intf->cmd_rcvrs);
        init_waitqueue_head(&intf->waitq);
 
        spin_lock_init(&intf->counter_lock);
        intf->proc_dir = NULL;
 
-       rv = -ENOMEM;
-       spin_lock_irqsave(&interfaces_lock, flags);
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               if (ipmi_interfaces[i] == NULL) {
-                       intf->intf_num = i;
-                       /* Reserve the entry till we are done. */
-                       ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY;
-                       rv = 0;
+       mutex_lock(&smi_watchers_mutex);
+       mutex_lock(&ipmi_interfaces_mutex);
+       /* Look for a hole in the numbers. */
+       i = 0;
+       link = &ipmi_interfaces;
+       list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) {
+               if (tintf->intf_num != i) {
+                       link = &tintf->link;
                        break;
                }
+               i++;
        }
-       spin_unlock_irqrestore(&interfaces_lock, flags);
-       if (rv)
-               goto out;
+       /* Add the new interface in numeric order. */
+       if (i == 0)
+               list_add_rcu(&intf->link, &ipmi_interfaces);
+       else
+               list_add_tail_rcu(&intf->link, link);
 
        rv = handlers->start_processing(send_info, intf);
        if (rv)
@@ -2497,8 +2722,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
 
        get_guid(intf);
 
-       if ((version_major > 1)
-           || ((version_major == 1) && (version_minor >= 5)))
+       if ((intf->ipmi_version_major > 1)
+           || ((intf->ipmi_version_major == 1)
+               && (intf->ipmi_version_minor >= 5)))
        {
                /* Start scanning the channels to see what is
                   available. */
@@ -2521,64 +2747,67 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        if (rv == 0)
                rv = add_proc_entries(intf, i);
 
-       rv = ipmi_bmc_register(intf);
+       rv = ipmi_bmc_register(intf, i, sysfs_name);
 
  out:
        if (rv) {
                if (intf->proc_dir)
                        remove_proc_entries(intf);
+               intf->handlers = NULL;
+               list_del_rcu(&intf->link);
+               mutex_unlock(&ipmi_interfaces_mutex);
+               mutex_unlock(&smi_watchers_mutex);
+               synchronize_rcu();
                kref_put(&intf->refcount, intf_free);
-               if (i < MAX_IPMI_INTERFACES) {
-                       spin_lock_irqsave(&interfaces_lock, flags);
-                       ipmi_interfaces[i] = NULL;
-                       spin_unlock_irqrestore(&interfaces_lock, flags);
-               }
        } else {
-               spin_lock_irqsave(&interfaces_lock, flags);
-               ipmi_interfaces[i] = intf;
-               spin_unlock_irqrestore(&interfaces_lock, flags);
+               /* After this point the interface is legal to use. */
+               intf->intf_num = i;
+               mutex_unlock(&ipmi_interfaces_mutex);
                call_smi_watchers(i, intf->si_dev);
+               mutex_unlock(&smi_watchers_mutex);
        }
 
        return rv;
 }
 
+static void cleanup_smi_msgs(ipmi_smi_t intf)
+{
+       int              i;
+       struct seq_table *ent;
+
+       /* No need for locks, the interface is down. */
+       for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
+               ent = &(intf->seq_table[i]);
+               if (!ent->inuse)
+                       continue;
+               deliver_err_response(ent->recv_msg, IPMI_ERR_UNSPECIFIED);
+       }
+}
+
 int ipmi_unregister_smi(ipmi_smi_t intf)
 {
-       int                     i;
        struct ipmi_smi_watcher *w;
-       unsigned long           flags;
+       int    intf_num = intf->intf_num;
 
        ipmi_bmc_unregister(intf);
 
-       spin_lock_irqsave(&interfaces_lock, flags);
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               if (ipmi_interfaces[i] == intf) {
-                       /* Set the interface number reserved until we
-                        * are done. */
-                       ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY;
-                       intf->intf_num = -1;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&interfaces_lock,flags);
+       mutex_lock(&smi_watchers_mutex);
+       mutex_lock(&ipmi_interfaces_mutex);
+       intf->intf_num = -1;
+       intf->handlers = NULL;
+       list_del_rcu(&intf->link);
+       mutex_unlock(&ipmi_interfaces_mutex);
+       synchronize_rcu();
 
-       if (i == MAX_IPMI_INTERFACES)
-               return -ENODEV;
+       cleanup_smi_msgs(intf);
 
        remove_proc_entries(intf);
 
        /* Call all the watcher interfaces to tell them that
           an interface is gone. */
-       down_read(&smi_watchers_sem);
        list_for_each_entry(w, &smi_watchers, link)
-               w->smi_gone(i);
-       up_read(&smi_watchers_sem);
-
-       /* Allow the entry to be reused now. */
-       spin_lock_irqsave(&interfaces_lock, flags);
-       ipmi_interfaces[i] = NULL;
-       spin_unlock_irqrestore(&interfaces_lock,flags);
+               w->smi_gone(intf_num);
+       mutex_unlock(&smi_watchers_mutex);
 
        kref_put(&intf->refcount, intf_free);
        return 0;
@@ -2660,6 +2889,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
        struct ipmi_ipmb_addr    *ipmb_addr;
        struct ipmi_recv_msg     *recv_msg;
        unsigned long            flags;
+       struct ipmi_smi_handlers *handlers;
 
        if (msg->rsp_size < 10) {
                /* Message not big enough, just ignore it. */
@@ -2716,10 +2946,16 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                printk("\n");
        }
 #endif
-               intf->handlers->sender(intf->send_info, msg, 0);
-
-               rv = -1; /* We used the message, so return the value that
-                           causes it to not be freed or queued. */
+               rcu_read_lock();
+               handlers = intf->handlers;
+               if (handlers) {
+                       handlers->sender(intf->send_info, msg, 0);
+                       /* We used the message, so return the value
+                          that causes it to not be freed or
+                          queued. */
+                       rv = -1;
+               }
+               rcu_read_unlock();
        } else {
                /* Deliver the message to the user. */
                spin_lock_irqsave(&intf->counter_lock, flags);
@@ -3309,16 +3545,6 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
        rcu_read_unlock();
 }
 
-static void
-handle_msg_timeout(struct ipmi_recv_msg *msg)
-{
-       msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
-       msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE;
-       msg->msg.netfn |= 1; /* Convert to a response. */
-       msg->msg.data_len = 1;
-       msg->msg.data = msg->msg_data;
-       deliver_response(msg);
-}
 
 static struct ipmi_smi_msg *
 smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
@@ -3350,7 +3576,11 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
                              struct list_head *timeouts, long timeout_period,
                              int slot, unsigned long *flags)
 {
-       struct ipmi_recv_msg *msg;
+       struct ipmi_recv_msg     *msg;
+       struct ipmi_smi_handlers *handlers;
+
+       if (intf->intf_num == -1)
+               return;
 
        if (!ent->inuse)
                return;
@@ -3393,13 +3623,19 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
                        return;
 
                spin_unlock_irqrestore(&intf->seq_lock, *flags);
+
                /* Send the new message.  We send with a zero
                 * priority.  It timed out, I doubt time is
                 * that critical now, and high priority
                 * messages are really only for messages to the
                 * local MC, which don't get resent. */
-               intf->handlers->sender(intf->send_info,
-                                      smi_msg, 0);
+               handlers = intf->handlers;
+               if (handlers)
+                       intf->handlers->sender(intf->send_info,
+                                              smi_msg, 0);
+               else
+                       ipmi_free_smi_msg(smi_msg);
+
                spin_lock_irqsave(&intf->seq_lock, *flags);
        }
 }
@@ -3411,18 +3647,12 @@ static void ipmi_timeout_handler(long timeout_period)
        struct ipmi_recv_msg *msg, *msg2;
        struct ipmi_smi_msg  *smi_msg, *smi_msg2;
        unsigned long        flags;
-       int                  i, j;
+       int                  i;
 
        INIT_LIST_HEAD(&timeouts);
 
-       spin_lock(&interfaces_lock);
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
-                       continue;
-               kref_get(&intf->refcount);
-               spin_unlock(&interfaces_lock);
-
+       rcu_read_lock();
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
                /* See if any waiting messages need to be processed. */
                spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
                list_for_each_entry_safe(smi_msg, smi_msg2,
@@ -3442,35 +3672,60 @@ static void ipmi_timeout_handler(long timeout_period)
                   have timed out, putting them in the timeouts
                   list. */
                spin_lock_irqsave(&intf->seq_lock, flags);
-               for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++)
-                       check_msg_timeout(intf, &(intf->seq_table[j]),
-                                         &timeouts, timeout_period, j,
+               for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
+                       check_msg_timeout(intf, &(intf->seq_table[i]),
+                                         &timeouts, timeout_period, i,
                                          &flags);
                spin_unlock_irqrestore(&intf->seq_lock, flags);
 
                list_for_each_entry_safe(msg, msg2, &timeouts, link)
-                       handle_msg_timeout(msg);
-
-               kref_put(&intf->refcount, intf_free);
-               spin_lock(&interfaces_lock);
+                       deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE);
+
+               /*
+                * Maintenance mode handling.  Check the timeout
+                * optimistically before we claim the lock.  It may
+                * mean a timeout gets missed occasionally, but that
+                * only means the timeout gets extended by one period
+                * in that case.  No big deal, and it avoids the lock
+                * most of the time.
+                */
+               if (intf->auto_maintenance_timeout > 0) {
+                       spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
+                       if (intf->auto_maintenance_timeout > 0) {
+                               intf->auto_maintenance_timeout
+                                       -= timeout_period;
+                               if (!intf->maintenance_mode
+                                   && (intf->auto_maintenance_timeout <= 0))
+                               {
+                                       intf->maintenance_mode_enable = 0;
+                                       maintenance_mode_update(intf);
+                               }
+                       }
+                       spin_unlock_irqrestore(&intf->maintenance_mode_lock,
+                                              flags);
+               }
        }
-       spin_unlock(&interfaces_lock);
+       rcu_read_unlock();
 }
 
 static void ipmi_request_event(void)
 {
-       ipmi_smi_t intf;
-       int        i;
+       ipmi_smi_t               intf;
+       struct ipmi_smi_handlers *handlers;
 
-       spin_lock(&interfaces_lock);
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
+       rcu_read_lock();
+       /* Called from the timer, no need to check if handlers is
+        * valid. */
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+               /* No event requests when in maintenance mode. */
+               if (intf->maintenance_mode_enable)
                        continue;
 
-               intf->handlers->request_events(intf->send_info);
+               handlers = intf->handlers;
+               if (handlers)
+                       handlers->request_events(intf->send_info);
        }
-       spin_unlock(&interfaces_lock);
+       rcu_read_unlock();
 }
 
 static struct timer_list ipmi_timer;
@@ -3599,7 +3854,6 @@ static void send_panic_events(char *str)
        struct kernel_ipmi_msg            msg;
        ipmi_smi_t                        intf;
        unsigned char                     data[16];
-       int                               i;
        struct ipmi_system_interface_addr *si;
        struct ipmi_addr                  addr;
        struct ipmi_smi_msg               smi_msg;
@@ -3633,9 +3887,9 @@ static void send_panic_events(char *str)
        recv_msg.done = dummy_recv_done_handler;
 
        /* For every registered interface, send the event. */
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+               if (!intf->handlers)
+                       /* Interface is not ready. */
                        continue;
 
                /* Send the event announcing the panic. */
@@ -3660,13 +3914,14 @@ static void send_panic_events(char *str)
        if (!str) 
                return;
 
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
+       /* For every registered interface, send the event. */
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
                char                  *p = str;
                struct ipmi_ipmb_addr *ipmb;
                int                   j;
 
-               intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
+               if (intf->intf_num == -1)
+                       /* Interface was not ready yet. */
                        continue;
 
                /* First job here is to figure out where to send the
@@ -3786,13 +4041,12 @@ static void send_panic_events(char *str)
 }
 #endif /* CONFIG_IPMI_PANIC_EVENT */
 
-static int has_panicked = 0;
+static int has_panicked;
 
 static int panic_event(struct notifier_block *this,
                       unsigned long         event,
                        void                  *ptr)
 {
-       int        i;
        ipmi_smi_t intf;
 
        if (has_panicked)
@@ -3800,9 +4054,9 @@ static int panic_event(struct notifier_block *this,
        has_panicked = 1;
 
        /* For every registered interface, set it to run to completion. */
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
-               intf = ipmi_interfaces[i];
-               if (IPMI_INVALID_INTERFACE(intf))
+       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+               if (!intf->handlers)
+                       /* Interface is not ready. */
                        continue;
 
                intf->handlers->set_run_to_completion(intf->send_info, 1);
@@ -3823,7 +4077,6 @@ static struct notifier_block panic_block = {
 
 static int ipmi_init_msghandler(void)
 {
-       int i;
        int rv;
 
        if (initialized)
@@ -3838,9 +4091,6 @@ static int ipmi_init_msghandler(void)
        printk(KERN_INFO "ipmi message handler version "
               IPMI_DRIVER_VERSION "\n");
 
-       for (i = 0; i < MAX_IPMI_INTERFACES; i++)
-               ipmi_interfaces[i] = NULL;
-
 #ifdef CONFIG_PROC_FS
        proc_ipmi_root = proc_mkdir("ipmi", NULL);
        if (!proc_ipmi_root) {
index 8d941db..9d23136 100644 (file)
@@ -43,6 +43,9 @@
 
 #define PFX "IPMI poweroff: "
 
+static void ipmi_po_smi_gone(int if_num);
+static void ipmi_po_new_smi(int if_num, struct device *device);
+
 /* Definitions for controlling power off (if the system supports it).  It
  * conveniently matches the IPMI chassis control values. */
 #define IPMI_CHASSIS_POWER_DOWN                0       /* power down, the default. */
 /* the IPMI data command */
 static int poweroff_powercycle;
 
+/* Which interface to use, -1 means the first we see. */
+static int ifnum_to_use = -1;
+
+/* Our local state. */
+static int ready;
+static ipmi_user_t ipmi_user;
+static int ipmi_ifnum;
+static void (*specific_poweroff_func)(ipmi_user_t user);
+
+/* Holds the old poweroff function so we can restore it on removal. */
+static void (*old_poweroff_func)(void);
+
+static int set_param_ifnum(const char *val, struct kernel_param *kp)
+{
+       int rv = param_set_int(val, kp);
+       if (rv)
+               return rv;
+       if ((ifnum_to_use < 0) || (ifnum_to_use == ipmi_ifnum))
+               return 0;
+
+       ipmi_po_smi_gone(ipmi_ifnum);
+       ipmi_po_new_smi(ifnum_to_use, NULL);
+       return 0;
+}
+
+module_param_call(ifnum_to_use, set_param_ifnum, param_get_int,
+                 &ifnum_to_use, 0644);
+MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
+                "timer.  Setting to -1 defaults to the first registered "
+                "interface");
+
 /* parameter definition to allow user to flag power cycle */
 module_param(poweroff_powercycle, int, 0644);
 MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
@@ -142,6 +176,42 @@ static int ipmi_request_in_rc_mode(ipmi_user_t            user,
 #define IPMI_ATCA_GET_ADDR_INFO_CMD    0x01
 #define IPMI_PICMG_ID                  0
 
+#define IPMI_NETFN_OEM                         0x2e
+#define IPMI_ATCA_PPS_GRACEFUL_RESTART         0x11
+#define IPMI_ATCA_PPS_IANA                     "\x00\x40\x0A"
+#define IPMI_MOTOROLA_MANUFACTURER_ID          0x0000A1
+#define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID      0x0051
+
+static void (*atca_oem_poweroff_hook)(ipmi_user_t user);
+
+static void pps_poweroff_atca (ipmi_user_t user)
+{
+        struct ipmi_system_interface_addr smi_addr;
+        struct kernel_ipmi_msg            send_msg;
+        int                               rv;
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+        printk(KERN_INFO PFX "PPS powerdown hook used");
+
+        send_msg.netfn = IPMI_NETFN_OEM;
+        send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
+        send_msg.data = IPMI_ATCA_PPS_IANA;
+        send_msg.data_len = 3;
+        rv = ipmi_request_in_rc_mode(user,
+                                  (struct ipmi_addr *) &smi_addr,
+                                   &send_msg);
+        if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
+                printk(KERN_ERR PFX "Unable to send ATCA ,"
+                       " IPMI error 0x%x\n", rv);
+        }
+       return;
+}
+
 static int ipmi_atca_detect (ipmi_user_t user)
 {
        struct ipmi_system_interface_addr smi_addr;
@@ -167,6 +237,13 @@ static int ipmi_atca_detect (ipmi_user_t user)
        rv = ipmi_request_wait_for_response(user,
                                            (struct ipmi_addr *) &smi_addr,
                                            &send_msg);
+
+        printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id);
+        if((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
+            && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
+               printk(KERN_INFO PFX "Installing Pigeon Point Systems Poweroff Hook\n");
+               atca_oem_poweroff_hook = pps_poweroff_atca;
+       }
        return !rv;
 }
 
@@ -200,12 +277,19 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
        rv = ipmi_request_in_rc_mode(user,
                                     (struct ipmi_addr *) &smi_addr,
                                     &send_msg);
-       if (rv) {
+        /** At this point, the system may be shutting down, and most
+         ** serial drivers (if used) will have interrupts turned off
+         ** it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
+         ** return code
+         **/
+        if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
                printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
                       " IPMI error 0x%x\n", rv);
                goto out;
        }
 
+       if(atca_oem_poweroff_hook)
+               return atca_oem_poweroff_hook(user);
  out:
        return;
 }
@@ -440,15 +524,6 @@ static struct poweroff_function poweroff_functions[] = {
                      / sizeof(struct poweroff_function))
 
 
-/* Our local state. */
-static int ready = 0;
-static ipmi_user_t ipmi_user;
-static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
-
-/* Holds the old poweroff function so we can restore it on removal. */
-static void (*old_poweroff_func)(void);
-
-
 /* Called on a powerdown request. */
 static void ipmi_poweroff_function (void)
 {
@@ -473,6 +548,9 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
        if (ready)
                return;
 
+       if ((ifnum_to_use >= 0) && (ifnum_to_use != if_num))
+               return;
+
        rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
                              &ipmi_user);
        if (rv) {
@@ -481,6 +559,8 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
                return;
        }
 
+       ipmi_ifnum = if_num;
+
         /*
          * Do a get device ide and store some results, since this is
         * used by several functions.
@@ -541,9 +621,15 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
 
 static void ipmi_po_smi_gone(int if_num)
 {
-       /* This can never be called, because once poweroff driver is
-          registered, the interface can't go away until the power
-          driver is unregistered. */
+       if (!ready)
+               return;
+
+       if (ipmi_ifnum != if_num)
+               return;
+
+       ready = 0;
+       ipmi_destroy_user(ipmi_user);
+       pm_power_off = old_poweroff_func;
 }
 
 static struct ipmi_smi_watcher smi_watcher =
@@ -616,9 +702,9 @@ static int ipmi_poweroff_init (void)
                printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
                goto out_err;
        }
-#endif
 
  out_err:
+#endif
        return rv;
 }
 
index bb1fac1..f1afd26 100644 (file)
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
 #include <linux/dmi.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#define PFX "ipmi_si: "
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -92,7 +96,7 @@ enum si_intf_state {
 enum si_type {
     SI_KCS, SI_SMIC, SI_BT
 };
-static char *si_to_str[] = { "KCS", "SMIC", "BT" };
+static char *si_to_str[] = { "kcs", "smic", "bt" };
 
 #define DEVICE_NAME "ipmi_si"
 
@@ -222,7 +226,10 @@ struct smi_info
 static int force_kipmid[SI_MAX_PARMS];
 static int num_force_kipmid;
 
+static int unload_when_empty = 1;
+
 static int try_smi_init(struct smi_info *smi);
+static void cleanup_one_si(struct smi_info *to_clean);
 
 static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
 static int register_xaction_notifier(struct notifier_block * nb)
@@ -240,14 +247,18 @@ static void deliver_recv_msg(struct smi_info *smi_info,
        spin_lock(&(smi_info->si_lock));
 }
 
-static void return_hosed_msg(struct smi_info *smi_info)
+static void return_hosed_msg(struct smi_info *smi_info, int cCode)
 {
        struct ipmi_smi_msg *msg = smi_info->curr_msg;
 
+       if (cCode < 0 || cCode > IPMI_ERR_UNSPECIFIED)
+               cCode = IPMI_ERR_UNSPECIFIED;
+       /* else use it as is */
+
        /* Make it a reponse */
        msg->rsp[0] = msg->data[0] | 4;
        msg->rsp[1] = msg->data[1];
-       msg->rsp[2] = 0xFF; /* Unknown error. */
+       msg->rsp[2] = cCode;
        msg->rsp_size = 3;
 
        smi_info->curr_msg = NULL;
@@ -298,7 +309,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
                        smi_info->curr_msg->data,
                        smi_info->curr_msg->data_size);
                if (err) {
-                       return_hosed_msg(smi_info);
+                       return_hosed_msg(smi_info, err);
                }
 
                rv = SI_SM_CALL_WITHOUT_DELAY;
@@ -640,7 +651,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
                        /* If we were handling a user message, format
                            a response to send to the upper layer to
                            tell it about the error. */
-                       return_hosed_msg(smi_info);
+                       return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED);
                }
                si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
        }
@@ -684,22 +695,24 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
        {
                /* We are idle and the upper layer requested that I fetch
                   events, so do so. */
-               unsigned char msg[2];
+               atomic_set(&smi_info->req_events, 0);
 
-               spin_lock(&smi_info->count_lock);
-               smi_info->flag_fetches++;
-               spin_unlock(&smi_info->count_lock);
+               smi_info->curr_msg = ipmi_alloc_smi_msg();
+               if (!smi_info->curr_msg)
+                       goto out;
 
-               atomic_set(&smi_info->req_events, 0);
-               msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
-               msg[1] = IPMI_GET_MSG_FLAGS_CMD;
+               smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
+               smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
+               smi_info->curr_msg->data_size = 2;
 
                smi_info->handlers->start_transaction(
-                       smi_info->si_sm, msg, 2);
-               smi_info->si_state = SI_GETTING_FLAGS;
+                       smi_info->si_sm,
+                       smi_info->curr_msg->data,
+                       smi_info->curr_msg->data_size);
+               smi_info->si_state = SI_GETTING_EVENTS;
                goto restart;
        }
-
+ out:
        return si_sm_result;
 }
 
@@ -714,6 +727,15 @@ static void sender(void                *send_info,
        struct timeval    t;
 #endif
 
+       if (atomic_read(&smi_info->stop_operation)) {
+               msg->rsp[0] = msg->data[0] | 4;
+               msg->rsp[1] = msg->data[1];
+               msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+               msg->rsp_size = 3;
+               deliver_recv_msg(smi_info, msg);
+               return;
+       }
+
        spin_lock_irqsave(&(smi_info->msg_lock), flags);
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
@@ -805,17 +827,25 @@ static void poll(void *send_info)
 {
        struct smi_info *smi_info = send_info;
 
-       smi_event_handler(smi_info, 0);
+       /*
+        * Make sure there is some delay in the poll loop so we can
+        * drive time forward and timeout things.
+        */
+       udelay(10);
+       smi_event_handler(smi_info, 10);
 }
 
 static void request_events(void *send_info)
 {
        struct smi_info *smi_info = send_info;
 
+       if (atomic_read(&smi_info->stop_operation))
+               return;
+
        atomic_set(&smi_info->req_events, 1);
 }
 
-static int initialized = 0;
+static int initialized;
 
 static void smi_timeout(unsigned long data)
 {
@@ -949,12 +979,21 @@ static int smi_start_processing(void       *send_info,
        return 0;
 }
 
+static void set_maintenance_mode(void *send_info, int enable)
+{
+       struct smi_info   *smi_info = send_info;
+
+       if (!enable)
+               atomic_set(&smi_info->req_events, 0);
+}
+
 static struct ipmi_smi_handlers handlers =
 {
        .owner                  = THIS_MODULE,
        .start_processing       = smi_start_processing,
        .sender                 = sender,
        .request_events         = request_events,
+       .set_maintenance_mode   = set_maintenance_mode,
        .set_run_to_completion  = set_run_to_completion,
        .poll                   = poll,
 };
@@ -979,14 +1018,24 @@ static int num_ports;
 static int           irqs[SI_MAX_PARMS];
 static int num_irqs;
 static int           regspacings[SI_MAX_PARMS];
-static int num_regspacings = 0;
+static int num_regspacings;
 static int           regsizes[SI_MAX_PARMS];
-static int num_regsizes = 0;
+static int num_regsizes;
 static int           regshifts[SI_MAX_PARMS];
-static int num_regshifts = 0;
+static int num_regshifts;
 static int slave_addrs[SI_MAX_PARMS];
-static int num_slave_addrs = 0;
+static int num_slave_addrs;
 
+#define IPMI_IO_ADDR_SPACE  0
+#define IPMI_MEM_ADDR_SPACE 1
+static char *addr_space_to_str[] = { "i/o", "mem" };
+
+static int hotmod_handler(const char *val, struct kernel_param *kp);
+
+module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200);
+MODULE_PARM_DESC(hotmod, "Add and remove interfaces.  See"
+                " Documentation/IPMI.txt in the kernel sources for the"
+                " gory details.");
 
 module_param_named(trydefaults, si_trydefaults, bool, 0);
 MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the"
@@ -1038,12 +1087,12 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0);
 MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or"
                 " disabled(0).  Normally the IPMI driver auto-detects"
                 " this, but the value may be overridden by this parm.");
+module_param(unload_when_empty, int, 0);
+MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are"
+                " specified or found, default is 1.  Setting to 0"
+                " is useful for hot add of devices using hotmod.");
 
 
-#define IPMI_IO_ADDR_SPACE  0
-#define IPMI_MEM_ADDR_SPACE 1
-static char *addr_space_to_str[] = { "I/O", "memory" };
-
 static void std_irq_cleanup(struct smi_info *info)
 {
        if (info->si_type == SI_BT)
@@ -1317,6 +1366,250 @@ static int mem_setup(struct smi_info *info)
        return 0;
 }
 
+/*
+ * Parms come in as <op1>[:op2[:op3...]].  ops are:
+ *   add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]
+ * Options are:
+ *   rsp=<regspacing>
+ *   rsi=<regsize>
+ *   rsh=<regshift>
+ *   irq=<irq>
+ *   ipmb=<ipmb addr>
+ */
+enum hotmod_op { HM_ADD, HM_REMOVE };
+struct hotmod_vals {
+       char *name;
+       int  val;
+};
+static struct hotmod_vals hotmod_ops[] = {
+       { "add",        HM_ADD },
+       { "remove",     HM_REMOVE },
+       { NULL }
+};
+static struct hotmod_vals hotmod_si[] = {
+       { "kcs",        SI_KCS },
+       { "smic",       SI_SMIC },
+       { "bt",         SI_BT },
+       { NULL }
+};
+static struct hotmod_vals hotmod_as[] = {
+       { "mem",        IPMI_MEM_ADDR_SPACE },
+       { "i/o",        IPMI_IO_ADDR_SPACE },
+       { NULL }
+};
+
+static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr)
+{
+       char *s;
+       int  i;
+
+       s = strchr(*curr, ',');
+       if (!s) {
+               printk(KERN_WARNING PFX "No hotmod %s given.\n", name);
+               return -EINVAL;
+       }
+       *s = '\0';
+       s++;
+       for (i = 0; hotmod_ops[i].name; i++) {
+               if (strcmp(*curr, v[i].name) == 0) {
+                       *val = v[i].val;
+                       *curr = s;
+                       return 0;
+               }
+       }
+
+       printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr);
+       return -EINVAL;
+}
+
+static int check_hotmod_int_op(const char *curr, const char *option,
+                              const char *name, int *val)
+{
+       char *n;
+
+       if (strcmp(curr, name) == 0) {
+               if (!option) {
+                       printk(KERN_WARNING PFX
+                              "No option given for '%s'\n",
+                              curr);
+                       return -EINVAL;
+               }
+               *val = simple_strtoul(option, &n, 0);
+               if ((*n != '\0') || (*option == '\0')) {
+                       printk(KERN_WARNING PFX
+                              "Bad option given for '%s'\n",
+                              curr);
+                       return -EINVAL;
+               }
+               return 1;
+       }
+       return 0;
+}
+
+static int hotmod_handler(const char *val, struct kernel_param *kp)
+{
+       char *str = kstrdup(val, GFP_KERNEL);
+       int  rv;
+       char *next, *curr, *s, *n, *o;
+       enum hotmod_op op;
+       enum si_type si_type;
+       int  addr_space;
+       unsigned long addr;
+       int regspacing;
+       int regsize;
+       int regshift;
+       int irq;
+       int ipmb;
+       int ival;
+       int len;
+       struct smi_info *info;
+
+       if (!str)
+               return -ENOMEM;
+
+       /* Kill any trailing spaces, as we can get a "\n" from echo. */
+       len = strlen(str);
+       ival = len - 1;
+       while ((ival >= 0) && isspace(str[ival])) {
+               str[ival] = '\0';
+               ival--;
+       }
+
+       for (curr = str; curr; curr = next) {
+               regspacing = 1;
+               regsize = 1;
+               regshift = 0;
+               irq = 0;
+               ipmb = 0x20;
+
+               next = strchr(curr, ':');
+               if (next) {
+                       *next = '\0';
+                       next++;
+               }
+
+               rv = parse_str(hotmod_ops, &ival, "operation", &curr);
+               if (rv)
+                       break;
+               op = ival;
+
+               rv = parse_str(hotmod_si, &ival, "interface type", &curr);
+               if (rv)
+                       break;
+               si_type = ival;
+
+               rv = parse_str(hotmod_as, &addr_space, "address space", &curr);
+               if (rv)
+                       break;
+
+               s = strchr(curr, ',');
+               if (s) {
+                       *s = '\0';
+                       s++;
+               }
+               addr = simple_strtoul(curr, &n, 0);
+               if ((*n != '\0') || (*curr == '\0')) {
+                       printk(KERN_WARNING PFX "Invalid hotmod address"
+                              " '%s'\n", curr);
+                       break;
+               }
+
+               while (s) {
+                       curr = s;
+                       s = strchr(curr, ',');
+                       if (s) {
+                               *s = '\0';
+                               s++;
+                       }
+                       o = strchr(curr, '=');
+                       if (o) {
+                               *o = '\0';
+                               o++;
+                       }
+                       rv = check_hotmod_int_op(curr, o, "rsp", &regspacing);
+                       if (rv < 0)
+                               goto out;
+                       else if (rv)
+                               continue;
+                       rv = check_hotmod_int_op(curr, o, "rsi", &regsize);
+                       if (rv < 0)
+                               goto out;
+                       else if (rv)
+                               continue;
+                       rv = check_hotmod_int_op(curr, o, "rsh", &regshift);
+                       if (rv < 0)
+                               goto out;
+                       else if (rv)
+                               continue;
+                       rv = check_hotmod_int_op(curr, o, "irq", &irq);
+                       if (rv < 0)
+                               goto out;
+                       else if (rv)
+                               continue;
+                       rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb);
+                       if (rv < 0)
+                               goto out;
+                       else if (rv)
+                               continue;
+
+                       rv = -EINVAL;
+                       printk(KERN_WARNING PFX
+                              "Invalid hotmod option '%s'\n",
+                              curr);
+                       goto out;
+               }
+
+               if (op == HM_ADD) {
+                       info = kzalloc(sizeof(*info), GFP_KERNEL);
+                       if (!info) {
+                               rv = -ENOMEM;
+                               goto out;
+                       }
+
+                       info->addr_source = "hotmod";
+                       info->si_type = si_type;
+                       info->io.addr_data = addr;
+                       info->io.addr_type = addr_space;
+                       if (addr_space == IPMI_MEM_ADDR_SPACE)
+                               info->io_setup = mem_setup;
+                       else
+                               info->io_setup = port_setup;
+
+                       info->io.addr = NULL;
+                       info->io.regspacing = regspacing;
+                       if (!info->io.regspacing)
+                               info->io.regspacing = DEFAULT_REGSPACING;
+                       info->io.regsize = regsize;
+                       if (!info->io.regsize)
+                               info->io.regsize = DEFAULT_REGSPACING;
+                       info->io.regshift = regshift;
+                       info->irq = irq;
+                       if (info->irq)
+                               info->irq_setup = std_irq_setup;
+                       info->slave_addr = ipmb;
+
+                       try_smi_init(info);
+               } else {
+                       /* remove */
+                       struct smi_info *e, *tmp_e;
+
+                       mutex_lock(&smi_infos_lock);
+                       list_for_each_entry_safe(e, tmp_e, &smi_infos, link) {
+                               if (e->io.addr_type != addr_space)
+                                       continue;
+                               if (e->si_type != si_type)
+                                       continue;
+                               if (e->io.addr_data == addr)
+                                       cleanup_one_si(e);
+                       }
+                       mutex_unlock(&smi_infos_lock);
+               }
+       }
+       rv = len;
+ out:
+       kfree(str);
+       return rv;
+}
 
 static __devinit void hardcode_find_bmc(void)
 {
@@ -1391,7 +1684,7 @@ static __devinit void hardcode_find_bmc(void)
 /* Once we get an ACPI failure, we don't try any more, because we go
    through the tables sequentially.  Once we don't find a table, there
    are no more. */
-static int acpi_failure = 0;
+static int acpi_failure;
 
 /* For GPE-type interrupts. */
 static u32 ipmi_acpi_gpe(void *context)
@@ -1502,7 +1795,6 @@ struct SPMITable {
 static __devinit int try_init_acpi(struct SPMITable *spmi)
 {
        struct smi_info  *info;
-       char             *io_type;
        u8               addr_space;
 
        if (spmi->IPMIlegacy != 1) {
@@ -1566,11 +1858,9 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
        info->io.regshift = spmi->addr.register_bit_offset;
 
        if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
-               io_type = "memory";
                info->io_setup = mem_setup;
                info->io.addr_type = IPMI_IO_ADDR_SPACE;
        } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-               io_type = "I/O";
                info->io_setup = port_setup;
                info->io.addr_type = IPMI_MEM_ADDR_SPACE;
        } else {
@@ -1952,19 +2242,9 @@ static int try_get_dev_id(struct smi_info *smi_info)
 static int type_file_read_proc(char *page, char **start, off_t off,
                               int count, int *eof, void *data)
 {
-       char            *out = (char *) page;
        struct smi_info *smi = data;
 
-       switch (smi->si_type) {
-           case SI_KCS:
-               return sprintf(out, "kcs\n");
-           case SI_SMIC:
-               return sprintf(out, "smic\n");
-           case SI_BT:
-               return sprintf(out, "bt\n");
-           default:
-               return 0;
-       }
+       return sprintf(page, "%s\n", si_to_str[smi->si_type]);
 }
 
 static int stat_file_read_proc(char *page, char **start, off_t off,
@@ -2000,7 +2280,24 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
        out += sprintf(out, "incoming_messages:     %ld\n",
                       smi->incoming_messages);
 
-       return (out - ((char *) page));
+       return out - page;
+}
+
+static int param_read_proc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+       struct smi_info *smi = data;
+
+       return sprintf(page,
+                      "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
+                      si_to_str[smi->si_type],
+                      addr_space_to_str[smi->io.addr_type],
+                      smi->io.addr_data,
+                      smi->io.regspacing,
+                      smi->io.regsize,
+                      smi->io.regshift,
+                      smi->irq,
+                      smi->slave_addr);
 }
 
 /*
@@ -2362,6 +2659,7 @@ static int try_smi_init(struct smi_info *new_smi)
                               new_smi,
                               &new_smi->device_id,
                               new_smi->dev,
+                              "bmc",
                               new_smi->slave_addr);
        if (rv) {
                printk(KERN_ERR
@@ -2390,6 +2688,16 @@ static int try_smi_init(struct smi_info *new_smi)
                goto out_err_stop_timer;
        }
 
+       rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
+                                    param_read_proc, NULL,
+                                    new_smi, THIS_MODULE);
+       if (rv) {
+               printk(KERN_ERR
+                      "ipmi_si: Unable to create proc entry: %d\n",
+                      rv);
+               goto out_err_stop_timer;
+       }
+
        list_add_tail(&new_smi->link, &smi_infos);
 
        mutex_unlock(&smi_infos_lock);
@@ -2478,12 +2786,16 @@ static __devinit int init_ipmi_si(void)
 #endif
 
 #ifdef CONFIG_ACPI
-       if (si_trydefaults)
-               acpi_find_bmc();
+       acpi_find_bmc();
 #endif
 
 #ifdef CONFIG_PCI
-       pci_module_init(&ipmi_pci_driver);
+       rv = pci_register_driver(&ipmi_pci_driver);
+       if (rv){
+               printk(KERN_ERR
+                      "init_ipmi_si: Unable to register PCI driver: %d\n",
+                      rv);
+       }
 #endif
 
        if (si_trydefaults) {
@@ -2498,7 +2810,7 @@ static __devinit int init_ipmi_si(void)
        }
 
        mutex_lock(&smi_infos_lock);
-       if (list_empty(&smi_infos)) {
+       if (unload_when_empty && list_empty(&smi_infos)) {
                mutex_unlock(&smi_infos_lock);
 #ifdef CONFIG_PCI
                pci_unregister_driver(&ipmi_pci_driver);
@@ -2513,7 +2825,7 @@ static __devinit int init_ipmi_si(void)
 }
 module_init(init_ipmi_si);
 
-static void __devexit cleanup_one_si(struct smi_info *to_clean)
+static void cleanup_one_si(struct smi_info *to_clean)
 {
        int           rv;
        unsigned long flags;
index 39d7e5e..e64ea7d 100644 (file)
@@ -141,12 +141,14 @@ static int start_smic_transaction(struct si_sm_data *smic,
 {
        unsigned int i;
 
-       if ((size < 2) || (size > MAX_SMIC_WRITE_SIZE)) {
-               return -1;
-       }
-       if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {
-               return -2;
-       }
+       if (size < 2)
+               return IPMI_REQ_LEN_INVALID_ERR;
+       if (size > MAX_SMIC_WRITE_SIZE)
+               return IPMI_REQ_LEN_EXCEEDED_ERR;
+
+       if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED))
+               return IPMI_NOT_IN_MY_STATE_ERR;
+
        if (smic_debug & SMIC_DEBUG_MSG) {
                printk(KERN_INFO "start_smic_transaction -");
                for (i = 0; i < size; i ++) {
index 73f759e..7828038 100644 (file)
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 
-static ipmi_user_t watchdog_user = NULL;
+static ipmi_user_t watchdog_user;
+static int watchdog_ifnum;
 
 /* Default the timeout to 10 seconds. */
 static int timeout = 10;
 
 /* The pre-timeout is disabled by default. */
-static int pretimeout = 0;
+static int pretimeout;
 
 /* Default action is to reset the board on a timeout. */
 static unsigned char action_val = WDOG_TIMEOUT_RESET;
@@ -155,12 +156,14 @@ static unsigned char preop_val = WDOG_PREOP_NONE;
 
 static char preop[16] = "preop_none";
 static DEFINE_SPINLOCK(ipmi_read_lock);
-static char data_to_read = 0;
+static char data_to_read;
 static DECLARE_WAIT_QUEUE_HEAD(read_q);
-static struct fasync_struct *fasync_q = NULL;
-static char pretimeout_since_last_heartbeat = 0;
+static struct fasync_struct *fasync_q;
+static char pretimeout_since_last_heartbeat;
 static char expect_close;
 
+static int ifnum_to_use = -1;
+
 static DECLARE_RWSEM(register_sem);
 
 /* Parameters to ipmi_set_timeout */
@@ -169,10 +172,12 @@ static DECLARE_RWSEM(register_sem);
 #define IPMI_SET_TIMEOUT_FORCE_HB              2
 
 static int ipmi_set_timeout(int do_heartbeat);
+static void ipmi_register_watchdog(int ipmi_intf);
+static void ipmi_unregister_watchdog(int ipmi_intf);
 
 /* If true, the driver will start running as soon as it is configured
    and ready. */
-static int start_now = 0;
+static int start_now;
 
 static int set_param_int(const char *val, struct kernel_param *kp)
 {
@@ -245,6 +250,26 @@ static int get_param_str(char *buffer, struct kernel_param *kp)
        return strlen(buffer);
 }
 
+
+static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp)
+{
+       int rv = param_set_int(val, kp);
+       if (rv)
+               return rv;
+       if ((ifnum_to_use < 0) || (ifnum_to_use == watchdog_ifnum))
+               return 0;
+
+       ipmi_unregister_watchdog(watchdog_ifnum);
+       ipmi_register_watchdog(ifnum_to_use);
+       return 0;
+}
+
+module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int,
+                 &ifnum_to_use, 0644);
+MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
+                "timer.  Setting to -1 defaults to the first registered "
+                "interface");
+
 module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644);
 MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
 
@@ -263,27 +288,28 @@ module_param_call(preop, set_param_str, get_param_str, preop_op, 0644);
 MODULE_PARM_DESC(preop, "Pretimeout driver operation.  One of: "
                 "preop_none, preop_panic, preop_give_data.");
 
-module_param(start_now, int, 0);
+module_param(start_now, int, 0444);
 MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
                 "soon as the driver is loaded.");
 
 module_param(nowayout, int, 0644);
-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=CONFIG_WATCHDOG_NOWAYOUT)");
 
 /* Default state of the timer. */
 static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 
 /* If shutting down via IPMI, we ignore the heartbeat. */
-static int ipmi_ignore_heartbeat = 0;
+static int ipmi_ignore_heartbeat;
 
 /* Is someone using the watchdog?  Only one user is allowed. */
-static unsigned long ipmi_wdog_open = 0;
+static unsigned long ipmi_wdog_open;
 
 /* If set to 1, the heartbeat command will set the state to reset and
    start the timer.  The timer doesn't normally run when the driver is
    first opened until the heartbeat is set the first time, this
    variable is used to accomplish this. */
-static int ipmi_start_timer_on_heartbeat = 0;
+static int ipmi_start_timer_on_heartbeat;
 
 /* IPMI version of the BMC. */
 static unsigned char ipmi_version_major;
@@ -872,6 +898,11 @@ static void ipmi_register_watchdog(int ipmi_intf)
        if (watchdog_user)
                goto out;
 
+       if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf))
+               goto out;
+
+       watchdog_ifnum = ipmi_intf;
+
        rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
        if (rv < 0) {
                printk(KERN_CRIT PFX "Unable to register with ipmi\n");
@@ -901,6 +932,39 @@ static void ipmi_register_watchdog(int ipmi_intf)
        }
 }
 
+static void ipmi_unregister_watchdog(int ipmi_intf)
+{
+       int rv;
+
+       down_write(&register_sem);
+
+       if (!watchdog_user)
+               goto out;
+
+       if (watchdog_ifnum != ipmi_intf)
+               goto out;
+
+       /* Make sure no one can call us any more. */
+       misc_deregister(&ipmi_wdog_miscdev);
+
+       /* Wait to make sure the message makes it out.  The lower layer has
+          pointers to our buffers, we want to make sure they are done before
+          we release our memory. */
+       while (atomic_read(&set_timeout_tofree))
+               schedule_timeout_uninterruptible(1);
+
+       /* Disconnect from IPMI. */
+       rv = ipmi_destroy_user(watchdog_user);
+       if (rv) {
+               printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",
+                      rv);
+       }
+       watchdog_user = NULL;
+
+ out:
+       up_write(&register_sem);
+}
+
 #ifdef HAVE_NMI_HANDLER
 static int
 ipmi_nmi(void *dev_id, int cpu, int handled)
@@ -1004,9 +1068,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
 
 static void ipmi_smi_gone(int if_num)
 {
-       /* This can never be called, because once the watchdog is
-          registered, the interface can't go away until the watchdog
-          is unregistered. */
+       ipmi_unregister_watchdog(if_num);
 }
 
 static struct ipmi_smi_watcher smi_watcher =
@@ -1148,30 +1210,32 @@ static int __init ipmi_wdog_init(void)
 
        check_parms();
 
+       register_reboot_notifier(&wdog_reboot_notifier);
+       atomic_notifier_chain_register(&panic_notifier_list,
+                       &wdog_panic_notifier);
+
        rv = ipmi_smi_watcher_register(&smi_watcher);
        if (rv) {
 #ifdef HAVE_NMI_HANDLER
                if (preaction_val == WDOG_PRETIMEOUT_NMI)
                        release_nmi(&ipmi_nmi_handler);
 #endif
+               atomic_notifier_chain_unregister(&panic_notifier_list,
+                                                &wdog_panic_notifier);
+               unregister_reboot_notifier(&wdog_reboot_notifier);
                printk(KERN_WARNING PFX "can't register smi watcher\n");
                return rv;
        }
 
-       register_reboot_notifier(&wdog_reboot_notifier);
-       atomic_notifier_chain_register(&panic_notifier_list,
-                       &wdog_panic_notifier);
-
        printk(KERN_INFO PFX "driver initialized\n");
 
        return 0;
 }
 
-static __exit void ipmi_unregister_watchdog(void)
+static void __exit ipmi_wdog_exit(void)
 {
-       int rv;
-
-       down_write(&register_sem);
+       ipmi_smi_watcher_unregister(&smi_watcher);
+       ipmi_unregister_watchdog(watchdog_ifnum);
 
 #ifdef HAVE_NMI_HANDLER
        if (nmi_handler_registered)
@@ -1179,37 +1243,8 @@ static __exit void ipmi_unregister_watchdog(void)
 #endif
 
        atomic_notifier_chain_unregister(&panic_notifier_list,
-                       &wdog_panic_notifier);
+                                        &wdog_panic_notifier);
        unregister_reboot_notifier(&wdog_reboot_notifier);
-
-       if (! watchdog_user)
-               goto out;
-
-       /* Make sure no one can call us any more. */
-       misc_deregister(&ipmi_wdog_miscdev);
-
-       /* Wait to make sure the message makes it out.  The lower layer has
-          pointers to our buffers, we want to make sure they are done before
-          we release our memory. */
-       while (atomic_read(&set_timeout_tofree))
-               schedule_timeout_uninterruptible(1);
-
-       /* Disconnect from IPMI. */
-       rv = ipmi_destroy_user(watchdog_user);
-       if (rv) {
-               printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",
-                      rv);
-       }
-       watchdog_user = NULL;
-
- out:
-       up_write(&register_sem);
-}
-
-static void __exit ipmi_wdog_exit(void)
-{
-       ipmi_smi_watcher_unregister(&smi_watcher);
-       ipmi_unregister_watchdog();
 }
 module_exit(ipmi_wdog_exit);
 module_init(ipmi_wdog_init);
index 58c955e..5a747e6 100644 (file)
@@ -172,12 +172,14 @@ static struct pci_driver isicom_driver = {
 static int prev_card = 3;      /*      start servicing isi_card[0]     */
 static struct tty_driver *isicom_normal;
 
-static struct timer_list tx;
+static DECLARE_COMPLETION(isi_timerdone);
 static char re_schedule = 1;
 
 static void isicom_tx(unsigned long _data);
 static void isicom_start(struct tty_struct *tty);
 
+static DEFINE_TIMER(tx, isicom_tx, 0, 0);
+
 /*   baud index mappings from linux defns to isi */
 
 static signed char linuxb_to_isib[] = {
@@ -193,9 +195,9 @@ struct      isi_board {
        unsigned short          shift_count;
        struct isi_port         * ports;
        signed char             count;
-       unsigned char           isa;
        spinlock_t              card_lock; /* Card wide lock 11/5/00 -sameer */
        unsigned long           flags;
+       unsigned int            index;
 };
 
 struct isi_port {
@@ -514,25 +516,19 @@ static void isicom_tx(unsigned long _data)
        /*      schedule another tx for hopefully in about 10ms */
 sched_again:
        if (!re_schedule) {
-               re_schedule = 2;
+               complete(&isi_timerdone);
                return;
        }
 
-       init_timer(&tx);
-       tx.expires = jiffies + HZ/100;
-       tx.data = 0;
-       tx.function = isicom_tx;
-       add_timer(&tx);
-
-       return;
+       mod_timer(&tx, jiffies + msecs_to_jiffies(10));
 }
 
 /*     Interrupt handlers      */
 
 
-static void isicom_bottomhalf(void *data)
+static void isicom_bottomhalf(struct work_struct *work)
 {
-       struct isi_port *port = (struct isi_port *) data;
+       struct isi_port *port = container_of(work, struct isi_port, bh_tqueue);
        struct tty_struct *tty = port->tty;
 
        if (!tty)
@@ -562,14 +558,12 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
        base = card->base;
        spin_lock(&card->card_lock);
 
-       if (card->isa == NO) {
-               /*
-                * disable any interrupts from the PCI card and lower the
-                * interrupt line
-                */
-               outw(0x8000, base+0x04);
-               ClearInterrupt(base);
-       }
+       /*
+        * disable any interrupts from the PCI card and lower the
+        * interrupt line
+        */
+       outw(0x8000, base+0x04);
+       ClearInterrupt(base);
 
        inw(base);              /* get the dummy word out */
        header = inw(base);
@@ -579,19 +573,13 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
        if (channel + 1 > card->port_count) {
                printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
                        "%d(channel) > port_count.\n", base, channel+1);
-               if (card->isa)
-                       ClearInterrupt(base);
-               else
-                       outw(0x0000, base+0x04); /* enable interrupts */
+               outw(0x0000, base+0x04); /* enable interrupts */
                spin_unlock(&card->card_lock);
                return IRQ_HANDLED;
        }
        port = card->ports + channel;
        if (!(port->flags & ASYNC_INITIALIZED)) {
-               if (card->isa)
-                       ClearInterrupt(base);
-               else
-                       outw(0x0000, base+0x04); /* enable interrupts */
+               outw(0x0000, base+0x04); /* enable interrupts */
                return IRQ_HANDLED;
        }
 
@@ -604,10 +592,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                }
                if (byte_count & 0x01)
                        inw(base);
-               if (card->isa == YES)
-                       ClearInterrupt(base);
-               else
-                       outw(0x0000, base+0x04); /* enable interrupts */
+               outw(0x0000, base+0x04); /* enable interrupts */
                spin_unlock(&card->card_lock);
                return IRQ_HANDLED;
        }
@@ -708,10 +693,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                }
                tty_flip_buffer_push(tty);
        }
-       if (card->isa == YES)
-               ClearInterrupt(base);
-       else
-               outw(0x0000, base+0x04); /* enable interrupts */
+       outw(0x0000, base+0x04); /* enable interrupts */
 
        return IRQ_HANDLED;
 }
@@ -964,8 +946,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
 {
        struct isi_port *port;
        struct isi_board *card;
-       unsigned int line, board;
-       int error;
+       unsigned int board;
+       int error, line;
 
        line = tty->index;
        if (line < 0 || line > PORT_COUNT-1)
@@ -1399,7 +1381,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
 
 /* set_termios et all */
 static void isicom_set_termios(struct tty_struct *tty,
-       struct termios *old_termios)
+       struct ktermios *old_termios)
 {
        struct isi_port *port = tty->driver_data;
 
@@ -1474,9 +1456,9 @@ static void isicom_start(struct tty_struct *tty)
 }
 
 /* hangup et all */
-static void do_isicom_hangup(void *data)
+static void do_isicom_hangup(struct work_struct *work)
 {
-       struct isi_port *port = data;
+       struct isi_port *port = container_of(work, struct isi_port, hangup_tq);
        struct tty_struct *tty;
 
        tty = port->tty;
@@ -1520,37 +1502,6 @@ static void isicom_flush_buffer(struct tty_struct *tty)
  * Driver init and deinit functions
  */
 
-static int __devinit isicom_register_ioregion(struct pci_dev *pdev,
-       const unsigned int index)
-{
-       struct isi_board *board = pci_get_drvdata(pdev);
-
-       if (!board->base)
-               return -EINVAL;
-
-       if (!request_region(board->base, 16, ISICOM_NAME)) {
-               dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
-                       "will be disabled.\n", board->base, board->base + 15,
-                       index + 1);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static void isicom_unregister_ioregion(struct pci_dev *pdev)
-{
-       struct isi_board *board = pci_get_drvdata(pdev);
-
-       if (!board->base)
-               return;
-
-       release_region(board->base, 16);
-       dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n",
-               board->base, board->base + 15);
-       board->base = 0;
-}
-
 static const struct tty_operations isicom_ops = {
        .open                   = isicom_open,
        .close                  = isicom_close,
@@ -1571,70 +1522,6 @@ static const struct tty_operations isicom_ops = {
        .tiocmset               = isicom_tiocmset,
 };
 
-static int __devinit isicom_register_tty_driver(void)
-{
-       int error = -ENOMEM;
-
-       /* tty driver structure initialization */
-       isicom_normal = alloc_tty_driver(PORT_COUNT);
-       if (!isicom_normal)
-               goto end;
-
-       isicom_normal->owner                    = THIS_MODULE;
-       isicom_normal->name                     = "ttyM";
-       isicom_normal->major                    = ISICOM_NMAJOR;
-       isicom_normal->minor_start              = 0;
-       isicom_normal->type                     = TTY_DRIVER_TYPE_SERIAL;
-       isicom_normal->subtype                  = SERIAL_TYPE_NORMAL;
-       isicom_normal->init_termios             = tty_std_termios;
-       isicom_normal->init_termios.c_cflag     = B9600 | CS8 | CREAD | HUPCL |
-               CLOCAL;
-       isicom_normal->flags                    = TTY_DRIVER_REAL_RAW;
-       tty_set_operations(isicom_normal, &isicom_ops);
-
-       if ((error = tty_register_driver(isicom_normal))) {
-               pr_dbg("Couldn't register the dialin driver, error=%d\n",
-                       error);
-               put_tty_driver(isicom_normal);
-       }
-end:
-       return error;
-}
-
-static void isicom_unregister_tty_driver(void)
-{
-       int error;
-
-       if ((error = tty_unregister_driver(isicom_normal)))
-               pr_dbg("couldn't unregister normal driver, error=%d.\n", error);
-
-       put_tty_driver(isicom_normal);
-}
-
-static int __devinit isicom_register_isr(struct pci_dev *pdev,
-       const unsigned int index)
-{
-       struct isi_board *board = pci_get_drvdata(pdev);
-       unsigned long irqflags = IRQF_DISABLED;
-       int retval = -EINVAL;
-
-       if (!board->base)
-               goto end;
-
-       if (board->isa == NO)
-               irqflags |= IRQF_SHARED;
-
-       retval = request_irq(board->irq, isicom_interrupt, irqflags,
-               ISICOM_NAME, board);
-       if (retval < 0)
-               dev_warn(&pdev->dev, "Could not install handler at Irq %d. "
-                       "Card%d will be disabled.\n", board->irq, index + 1);
-       else
-               retval = 0;
-end:
-       return retval;
-}
-
 static int __devinit reset_card(struct pci_dev *pdev,
        const unsigned int card, unsigned int *signature)
 {
@@ -1656,36 +1543,23 @@ static int __devinit reset_card(struct pci_dev *pdev,
 
        *signature = inw(base + 0x4) & 0xff;
 
-       if (board->isa == YES) {
-               if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) {
-                       dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
-                               inw(base + 0x2), inw(base + 0xe));
-                       dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure "
-                               "(Possible bad I/O Port Address 0x%lx).\n",
-                               card + 1, base);
-                       retval = -EIO;
-                       goto end;
-               }
-       } else {
-               portcount = inw(base + 0x2);
-               if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
-                               (portcount != 4) && (portcount != 8))) {
-                       dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
-                               inw(base + 0x2), inw(base + 0xe));
-                       dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
-                               "(Possible bad I/O Port Address 0x%lx).\n",
-                               card + 1, base);
-                       retval = -EIO;
-                       goto end;
-               }
+       portcount = inw(base + 0x2);
+       if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
+                       (portcount != 4) && (portcount != 8))) {
+               dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+                       inw(base + 0x2), inw(base + 0xe));
+               dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
+                       "(Possible bad I/O Port Address 0x%lx).\n",
+                       card + 1, base);
+               retval = -EIO;
+               goto end;
        }
 
        switch (*signature) {
        case 0xa5:
        case 0xbb:
        case 0xdd:
-               board->port_count = (board->isa == NO && portcount == 4) ? 4 :
-                       8;
+               board->port_count = (portcount == 4) ? 4 : 8;
                board->shift_count = 12;
                break;
        case 0xcc:
@@ -1831,6 +1705,11 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                }
 
                data = kmalloc(word_count * 2, GFP_KERNEL);
+               if (data == NULL) {
+                       dev_err(&pdev->dev, "Card%d, firmware upload "
+                               "failed, not enough memory\n", index + 1);
+                       goto errrelfw;
+               }
                inw(base);
                insw(base, data, word_count);
                InterruptTheCard(base);
@@ -1879,8 +1758,6 @@ end:
 /*
  *     Insmod can set static symbols so keep these static
  */
-static int io[4];
-static int irq[4];
 static int card;
 
 static int __devinit isicom_probe(struct pci_dev *pdev,
@@ -1906,20 +1783,29 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
                        break;
                }
 
+       board->index = index;
        board->base = ioaddr;
        board->irq = pciirq;
-       board->isa = NO;
        card++;
 
        pci_set_drvdata(pdev, board);
 
-       retval = isicom_register_ioregion(pdev, index);
-       if (retval < 0)
+       retval = pci_request_region(pdev, 3, ISICOM_NAME);
+       if (retval) {
+               dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+                       "will be disabled.\n", board->base, board->base + 15,
+                       index + 1);
+               retval = -EBUSY;
                goto err;
+       }
 
-       retval = isicom_register_isr(pdev, index);
-       if (retval < 0)
+       retval = request_irq(board->irq, isicom_interrupt,
+                       IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
+       if (retval < 0) {
+               dev_err(&pdev->dev, "Could not install handler at Irq %d. "
+                       "Card%d will be disabled.\n", board->irq, index + 1);
                goto errunrr;
+       }
 
        retval = reset_card(pdev, index, &signature);
        if (retval < 0)
@@ -1929,12 +1815,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
        if (retval < 0)
                goto errunri;
 
+       for (index = 0; index < board->port_count; index++)
+               tty_register_device(isicom_normal, board->index * 16 + index,
+                               &pdev->dev);
+
        return 0;
 
 errunri:
        free_irq(board->irq, board);
 errunrr:
-       isicom_unregister_ioregion(pdev);
+       pci_release_region(pdev, 3);
 err:
        board->base = 0;
        return retval;
@@ -1943,18 +1833,21 @@ err:
 static void __devexit isicom_remove(struct pci_dev *pdev)
 {
        struct isi_board *board = pci_get_drvdata(pdev);
+       unsigned int i;
+
+       for (i = 0; i < board->port_count; i++)
+               tty_unregister_device(isicom_normal, board->index * 16 + i);
 
        free_irq(board->irq, board);
-       isicom_unregister_ioregion(pdev);
+       pci_release_region(pdev, 3);
 }
 
-static int __devinit isicom_setup(void)
+static int __init isicom_init(void)
 {
        int retval, idx, channel;
        struct isi_port *port;
 
        card = 0;
-       memset(isi_ports, 0, sizeof(isi_ports));
 
        for(idx = 0; idx < BOARD_COUNT; idx++) {
                port = &isi_ports[idx * 16];
@@ -1966,8 +1859,8 @@ static int __devinit isicom_setup(void)
                        port->channel = channel;
                        port->close_delay = 50 * HZ/100;
                        port->closing_wait = 3000 * HZ/100;
-                       INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
-                       INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
+                       INIT_WORK(&port->hangup_tq, do_isicom_hangup);
+                       INIT_WORK(&port->bh_tqueue, isicom_bottomhalf);
                        port->status = 0;
                        init_waitqueue_head(&port->open_wait);
                        init_waitqueue_head(&port->close_wait);
@@ -1975,66 +1868,65 @@ static int __devinit isicom_setup(void)
                }
                isi_card[idx].base = 0;
                isi_card[idx].irq = 0;
-
-               if (!io[idx])
-                       continue;
-
-               if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4     ||
-                               irq[idx] == 5   || irq[idx] == 7        ||
-                               irq[idx] == 10  || irq[idx] == 11       ||
-                               irq[idx] == 12  || irq[idx] == 15) {
-                       printk(KERN_ERR "ISICOM: ISA not supported yet.\n");
-                       retval = -EINVAL;
-                       goto error;
-               } else
-                       printk(KERN_ERR "ISICOM: Irq %d unsupported. "
-                               "Disabling Card%d...\n", irq[idx], idx + 1);
        }
 
-       retval = isicom_register_tty_driver();
-       if (retval < 0)
+       /* tty driver structure initialization */
+       isicom_normal = alloc_tty_driver(PORT_COUNT);
+       if (!isicom_normal) {
+               retval = -ENOMEM;
                goto error;
+       }
+
+       isicom_normal->owner                    = THIS_MODULE;
+       isicom_normal->name                     = "ttyM";
+       isicom_normal->major                    = ISICOM_NMAJOR;
+       isicom_normal->minor_start              = 0;
+       isicom_normal->type                     = TTY_DRIVER_TYPE_SERIAL;
+       isicom_normal->subtype                  = SERIAL_TYPE_NORMAL;
+       isicom_normal->init_termios             = tty_std_termios;
+       isicom_normal->init_termios.c_cflag     = B9600 | CS8 | CREAD | HUPCL |
+               CLOCAL;
+       isicom_normal->flags                    = TTY_DRIVER_REAL_RAW |
+               TTY_DRIVER_DYNAMIC_DEV;
+       tty_set_operations(isicom_normal, &isicom_ops);
+
+       retval = tty_register_driver(isicom_normal);
+       if (retval) {
+               pr_dbg("Couldn't register the dialin driver\n");
+               goto err_puttty;
+       }
 
        retval = pci_register_driver(&isicom_driver);
        if (retval < 0) {
                printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
-               goto errtty;
+               goto err_unrtty;
        }
 
-       init_timer(&tx);
-       tx.expires = jiffies + 1;
-       tx.data = 0;
-       tx.function = isicom_tx;
-       re_schedule = 1;
-       add_timer(&tx);
+       mod_timer(&tx, jiffies + 1);
 
        return 0;
-errtty:
-       isicom_unregister_tty_driver();
+err_unrtty:
+       tty_unregister_driver(isicom_normal);
+err_puttty:
+       put_tty_driver(isicom_normal);
 error:
        return retval;
 }
 
 static void __exit isicom_exit(void)
 {
-       unsigned int index = 0;
-
        re_schedule = 0;
 
-       while (re_schedule != 2 && index++ < 100)
-               msleep(10);
+       wait_for_completion_timeout(&isi_timerdone, HZ);
 
        pci_unregister_driver(&isicom_driver);
-       isicom_unregister_tty_driver();
+       tty_unregister_driver(isicom_normal);
+       put_tty_driver(isicom_normal);
 }
 
-module_init(isicom_setup);
+module_init(isicom_init);
 module_exit(isicom_exit);
 
 MODULE_AUTHOR("MultiTech");
 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
 MODULE_LICENSE("GPL");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for the cards");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for the cards");
index ffdf9df..68645d3 100644 (file)
  *     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.
  */
 
 /*****************************************************************************/
@@ -41,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/eisa.h>
+#include <linux/ctype.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #define        BRD_BRUMBY4     2
 #define        BRD_ONBOARD2    3
 #define        BRD_ONBOARD     4
-#define        BRD_BRUMBY8     5
-#define        BRD_BRUMBY16    6
 #define        BRD_ONBOARDE    7
-#define        BRD_ONBOARD32   9
-#define        BRD_ONBOARD2_32 10
-#define        BRD_ONBOARDRS   11
-#define        BRD_EASYIO      20
-#define        BRD_ECH         21
-#define        BRD_ECHMC       22
 #define        BRD_ECP         23
 #define BRD_ECPE       24
 #define        BRD_ECPMC       25
-#define        BRD_ECHPCI      26
-#define        BRD_ECH64PCI    27
-#define        BRD_EASYIOPCI   28
 #define        BRD_ECPPCI      29
 
 #define        BRD_BRUMBY      BRD_BRUMBY4
  *     interrupt is required.
  */
 
-typedef struct {
+struct stlconf {
        int             brdtype;
        int             ioaddr1;
        int             ioaddr2;
        unsigned long   memaddr;
        int             irq;
        int             irqtype;
-} stlconf_t;
-
-static stlconf_t       stli_brdconf[] = {
-       /*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
 };
 
-static int     stli_nrbrds = ARRAY_SIZE(stli_brdconf);
+static unsigned int stli_nrbrds;
 
 /* stli_lock must NOT be taken holding brd_lock */
 static spinlock_t stli_lock;   /* TTY logic lock */
@@ -194,9 +172,11 @@ static struct tty_struct   *stli_txcooktty;
  *     with this termios initially. Basically all it defines is a raw port
  *     at 9600 baud, 8 data bits, no parity, 1 stop bit.
  */
-static struct termios          stli_deftermios = {
+static struct ktermios         stli_deftermios = {
        .c_cflag        = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
        .c_cc           = INIT_C_CC,
+       .c_ispeed       = 9600,
+       .c_ospeed       = 9600,
 };
 
 /*
@@ -205,13 +185,12 @@ static struct termios             stli_deftermios = {
  */
 static comstats_t      stli_comstats;
 static combrd_t                stli_brdstats;
-static asystats_t      stli_cdkstats;
-static stlibrd_t       stli_dummybrd;
-static stliport_t      stli_dummyport;
+static struct asystats stli_cdkstats;
 
 /*****************************************************************************/
 
-static stlibrd_t       *stli_brds[STL_MAXBRDS];
+static DEFINE_MUTEX(stli_brdslock);
+static struct stlibrd  *stli_brds[STL_MAXBRDS];
 
 static int             stli_shared;
 
@@ -223,6 +202,7 @@ static int          stli_shared;
  */
 #define        BST_FOUND       0x1
 #define        BST_STARTED     0x2
+#define        BST_PROBED      0x4
 
 /*
  *     Define the set of port state flags. These are marked for internal
@@ -255,18 +235,18 @@ static char       *stli_brdnames[] = {
        "Brumby",
        "Brumby",
        "ONboard-EI",
-       (char *) NULL,
+       NULL,
        "ONboard",
        "ONboard-MC",
        "ONboard-MC",
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
        "EasyIO",
        "EC8/32-AT",
        "EC8/32-MC",
@@ -304,12 +284,10 @@ static char       **stli_brdsp[] = {
  *     parse any module arguments.
  */
 
-typedef struct stlibrdtype {
+static struct stlibrdtype {
        char    *name;
        int     type;
-} stlibrdtype_t;
-
-static stlibrdtype_t   stli_brdstr[] = {
+} stli_brdstr[] = {
        { "stallion", BRD_STALLION },
        { "1", BRD_STALLION },
        { "brumby", BRD_BRUMBY },
@@ -379,6 +357,7 @@ MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
 module_param_array(board3, charp, NULL, 0);
 MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
 
+#if STLI_EISAPROBE != 0
 /*
  *     Set up a default memory address table for EISA board probing.
  *     The default addresses are all bellow 1Mbyte, which has to be the
@@ -396,14 +375,11 @@ static unsigned long      stli_eisamemprobeaddrs[] = {
 };
 
 static int     stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
+#endif
 
 /*
  *     Define the Stallion PCI vendor and device IDs.
  */
-#ifdef CONFIG_PCI
-#ifndef        PCI_VENDOR_ID_STALLION
-#define        PCI_VENDOR_ID_STALLION          0x124d
-#endif
 #ifndef PCI_DEVICE_ID_ECRA
 #define        PCI_DEVICE_ID_ECRA              0x0004
 #endif
@@ -414,7 +390,7 @@ static struct pci_device_id istallion_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
 
-#endif /* CONFIG_PCI */
+static struct pci_driver stli_pcidriver;
 
 /*****************************************************************************/
 
@@ -614,23 +590,11 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
 
 /*****************************************************************************/
 
-/*
- *     Define some handy local macros...
- */
-#undef MIN
-#define        MIN(a,b)        (((a) <= (b)) ? (a) : (b))
-
-#undef TOLOWER
-#define        TOLOWER(x)      ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
-
-/*****************************************************************************/
-
 /*
  *     Prototype all functions in this driver!
  */
 
-static int     stli_parsebrd(stlconf_t *confp, char **argp);
-static int     stli_init(void);
+static int     stli_parsebrd(struct stlconf *confp, char **argp);
 static int     stli_open(struct tty_struct *tty, struct file *filp);
 static void    stli_close(struct tty_struct *tty, struct file *filp);
 static int     stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
@@ -639,7 +603,7 @@ static void stli_flushchars(struct tty_struct *tty);
 static int     stli_writeroom(struct tty_struct *tty);
 static int     stli_charsinbuffer(struct tty_struct *tty);
 static int     stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void    stli_settermios(struct tty_struct *tty, struct termios *old);
+static void    stli_settermios(struct tty_struct *tty, struct ktermios *old);
 static void    stli_throttle(struct tty_struct *tty);
 static void    stli_unthrottle(struct tty_struct *tty);
 static void    stli_stop(struct tty_struct *tty);
@@ -649,86 +613,84 @@ static void       stli_breakctl(struct tty_struct *tty, int state);
 static void    stli_waituntilsent(struct tty_struct *tty, int timeout);
 static void    stli_sendxchar(struct tty_struct *tty, char ch);
 static void    stli_hangup(struct tty_struct *tty);
-static int     stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos);
+static int     stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos);
 
-static int     stli_brdinit(stlibrd_t *brdp);
-static int     stli_startbrd(stlibrd_t *brdp);
+static int     stli_brdinit(struct stlibrd *brdp);
+static int     stli_startbrd(struct stlibrd *brdp);
 static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
 static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
 static int     stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
-static void    stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp);
+static void    stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
 static void    stli_poll(unsigned long arg);
-static int     stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
-static int     stli_initopen(stlibrd_t *brdp, stliport_t *portp);
-static int     stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait);
-static int     stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait);
-static int     stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp);
-static void    stli_dohangup(void *arg);
-static int     stli_setport(stliport_t *portp);
-static int     stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void    stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void    __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void    stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp);
-static void    stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp);
+static int     stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
+static int     stli_initopen(struct stlibrd *brdp, struct stliport *portp);
+static int     stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int     stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int     stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
+static void    stli_dohangup(struct work_struct *);
+static int     stli_setport(struct stliport *portp);
+static int     stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void    stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void    __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void    stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
+static void    stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
 static void    stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
 static long    stli_mktiocm(unsigned long sigvalue);
-static void    stli_read(stlibrd_t *brdp, stliport_t *portp);
-static int     stli_getserial(stliport_t *portp, struct serial_struct __user *sp);
-static int     stli_setserial(stliport_t *portp, struct serial_struct __user *sp);
+static void    stli_read(struct stlibrd *brdp, struct stliport *portp);
+static int     stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
+static int     stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
 static int     stli_getbrdstats(combrd_t __user *bp);
-static int     stli_getportstats(stliport_t *portp, comstats_t __user *cp);
-static int     stli_portcmdstats(stliport_t *portp);
-static int     stli_clrportstats(stliport_t *portp, comstats_t __user *cp);
-static int     stli_getportstruct(stliport_t __user *arg);
-static int     stli_getbrdstruct(stlibrd_t __user *arg);
-static stlibrd_t *stli_allocbrd(void);
-
-static void    stli_ecpinit(stlibrd_t *brdp);
-static void    stli_ecpenable(stlibrd_t *brdp);
-static void    stli_ecpdisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_ecpreset(stlibrd_t *brdp);
-static void    stli_ecpintr(stlibrd_t *brdp);
-static void    stli_ecpeiinit(stlibrd_t *brdp);
-static void    stli_ecpeienable(stlibrd_t *brdp);
-static void    stli_ecpeidisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_ecpeireset(stlibrd_t *brdp);
-static void    stli_ecpmcenable(stlibrd_t *brdp);
-static void    stli_ecpmcdisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_ecpmcreset(stlibrd_t *brdp);
-static void    stli_ecppciinit(stlibrd_t *brdp);
-static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_ecppcireset(stlibrd_t *brdp);
-
-static void    stli_onbinit(stlibrd_t *brdp);
-static void    stli_onbenable(stlibrd_t *brdp);
-static void    stli_onbdisable(stlibrd_t *brdp);
-static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_onbreset(stlibrd_t *brdp);
-static void    stli_onbeinit(stlibrd_t *brdp);
-static void    stli_onbeenable(stlibrd_t *brdp);
-static void    stli_onbedisable(stlibrd_t *brdp);
-static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_onbereset(stlibrd_t *brdp);
-static void    stli_bbyinit(stlibrd_t *brdp);
-static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_bbyreset(stlibrd_t *brdp);
-static void    stli_stalinit(stlibrd_t *brdp);
-static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void    stli_stalreset(stlibrd_t *brdp);
-
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
-
-static int     stli_initecp(stlibrd_t *brdp);
-static int     stli_initonb(stlibrd_t *brdp);
-static int     stli_eisamemprobe(stlibrd_t *brdp);
-static int     stli_initports(stlibrd_t *brdp);
-
-#ifdef CONFIG_PCI
-static int     stli_initpcibrd(int brdtype, struct pci_dev *devp);
+static int     stli_getportstats(struct stliport *portp, comstats_t __user *cp);
+static int     stli_portcmdstats(struct stliport *portp);
+static int     stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
+static int     stli_getportstruct(struct stliport __user *arg);
+static int     stli_getbrdstruct(struct stlibrd __user *arg);
+static struct stlibrd *stli_allocbrd(void);
+
+static void    stli_ecpinit(struct stlibrd *brdp);
+static void    stli_ecpenable(struct stlibrd *brdp);
+static void    stli_ecpdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_ecpreset(struct stlibrd *brdp);
+static void    stli_ecpintr(struct stlibrd *brdp);
+static void    stli_ecpeiinit(struct stlibrd *brdp);
+static void    stli_ecpeienable(struct stlibrd *brdp);
+static void    stli_ecpeidisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_ecpeireset(struct stlibrd *brdp);
+static void    stli_ecpmcenable(struct stlibrd *brdp);
+static void    stli_ecpmcdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_ecpmcreset(struct stlibrd *brdp);
+static void    stli_ecppciinit(struct stlibrd *brdp);
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_ecppcireset(struct stlibrd *brdp);
+
+static void    stli_onbinit(struct stlibrd *brdp);
+static void    stli_onbenable(struct stlibrd *brdp);
+static void    stli_onbdisable(struct stlibrd *brdp);
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_onbreset(struct stlibrd *brdp);
+static void    stli_onbeinit(struct stlibrd *brdp);
+static void    stli_onbeenable(struct stlibrd *brdp);
+static void    stli_onbedisable(struct stlibrd *brdp);
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_onbereset(struct stlibrd *brdp);
+static void    stli_bbyinit(struct stlibrd *brdp);
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_bbyreset(struct stlibrd *brdp);
+static void    stli_stalinit(struct stlibrd *brdp);
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void    stli_stalreset(struct stlibrd *brdp);
+
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
+
+static int     stli_initecp(struct stlibrd *brdp);
+static int     stli_initonb(struct stlibrd *brdp);
+#if STLI_EISAPROBE != 0
+static int     stli_eisamemprobe(struct stlibrd *brdp);
 #endif
+static int     stli_initports(struct stlibrd *brdp);
 
 /*****************************************************************************/
 
@@ -766,136 +728,19 @@ static int       stli_timeron;
 
 static struct class *istallion_class;
 
-/*
- *     Loadable module initialization stuff.
- */
-
-static int __init istallion_module_init(void)
-{
-       stli_init();
-       return 0;
-}
-
-/*****************************************************************************/
-
-static void __exit istallion_module_exit(void)
-{
-       stlibrd_t       *brdp;
-       stliport_t      *portp;
-       int             i, j;
-
-       printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
-               stli_drvversion);
-
-       /*
-        *      Free up all allocated resources used by the ports. This includes
-        *      memory and interrupts.
-        */
-       if (stli_timeron) {
-               stli_timeron = 0;
-               del_timer_sync(&stli_timerlist);
-       }
-
-       i = tty_unregister_driver(stli_serial);
-       if (i) {
-               printk("STALLION: failed to un-register tty driver, "
-                       "errno=%d\n", -i);
-               return;
-       }
-       put_tty_driver(stli_serial);
-       for (i = 0; i < 4; i++)
-               class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-       class_destroy(istallion_class);
-       if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
-               printk("STALLION: failed to un-register serial memory device, "
-                       "errno=%d\n", -i);
-
-       kfree(stli_txcookbuf);
-
-       for (i = 0; (i < stli_nrbrds); i++) {
-               if ((brdp = stli_brds[i]) == NULL)
-                       continue;
-               for (j = 0; (j < STL_MAXPORTS); j++) {
-                       portp = brdp->ports[j];
-                       if (portp != NULL) {
-                               if (portp->tty != NULL)
-                                       tty_hangup(portp->tty);
-                               kfree(portp);
-                       }
-               }
-
-               iounmap(brdp->membase);
-               if (brdp->iosize > 0)
-                       release_region(brdp->iobase, brdp->iosize);
-               kfree(brdp);
-               stli_brds[i] = NULL;
-       }
-}
-
-module_init(istallion_module_init);
-module_exit(istallion_module_exit);
-
-/*****************************************************************************/
-
-/*
- *     Check for any arguments passed in on the module load command line.
- */
-
-static void stli_argbrds(void)
-{
-       stlconf_t conf;
-       stlibrd_t *brdp;
-       int i;
-
-       for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
-               memset(&conf, 0, sizeof(conf));
-               if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
-                       continue;
-               if ((brdp = stli_allocbrd()) == NULL)
-                       continue;
-               stli_nrbrds = i + 1;
-               brdp->brdnr = i;
-               brdp->brdtype = conf.brdtype;
-               brdp->iobase = conf.ioaddr1;
-               brdp->memaddr = conf.memaddr;
-               stli_brdinit(brdp);
-       }
-}
-
-/*****************************************************************************/
-
-/*
- *     Convert an ascii string number into an unsigned long.
- */
-
-static unsigned long stli_atol(char *str)
+static void stli_cleanup_ports(struct stlibrd *brdp)
 {
-       unsigned long val;
-       int base, c;
-       char *sp;
-
-       val = 0;
-       sp = str;
-       if ((*sp == '0') && (*(sp+1) == 'x')) {
-               base = 16;
-               sp += 2;
-       } else if (*sp == '0') {
-               base = 8;
-               sp++;
-       } else {
-               base = 10;
-       }
-
-       for (; (*sp != 0); sp++) {
-               c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
-               if ((c < 0) || (c >= base)) {
-                       printk("STALLION: invalid argument %s\n", str);
-                       val = 0;
-                       break;
+       struct stliport *portp;
+       unsigned int j;
+
+       for (j = 0; j < STL_MAXPORTS; j++) {
+               portp = brdp->ports[j];
+               if (portp != NULL) {
+                       if (portp->tty != NULL)
+                               tty_hangup(portp->tty);
+                       kfree(portp);
                }
-               val = (val * base) + c;
        }
-       return(val);
 }
 
 /*****************************************************************************/
@@ -904,16 +749,16 @@ static unsigned long stli_atol(char *str)
  *     Parse the supplied argument string, into the board conf struct.
  */
 
-static int stli_parsebrd(stlconf_t *confp, char **argp)
+static int stli_parsebrd(struct stlconf *confp, char **argp)
 {
+       unsigned int i;
        char *sp;
-       int i;
 
        if (argp[0] == NULL || *argp[0] == 0)
                return 0;
 
        for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
-               *sp = TOLOWER(*sp);
+               *sp = tolower(*sp);
 
        for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
                if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
@@ -926,9 +771,9 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
 
        confp->brdtype = stli_brdstr[i].type;
        if (argp[1] != NULL && *argp[1] != 0)
-               confp->ioaddr1 = stli_atol(argp[1]);
+               confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
        if (argp[2] !=  NULL && *argp[2] != 0)
-               confp->memaddr = stli_atol(argp[2]);
+               confp->memaddr = simple_strtoul(argp[2], NULL, 0);
        return(1);
 }
 
@@ -936,10 +781,10 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
 
 static int stli_open(struct tty_struct *tty, struct file *filp)
 {
-       stlibrd_t *brdp;
-       stliport_t *portp;
-       unsigned int minordev;
-       int brdnr, portnr, rc;
+       struct stlibrd *brdp;
+       struct stliport *portp;
+       unsigned int minordev, brdnr, portnr;
+       int rc;
 
        minordev = tty->index;
        brdnr = MINOR2BRD(minordev);
@@ -951,7 +796,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
        if ((brdp->state & BST_STARTED) == 0)
                return -ENODEV;
        portnr = MINOR2PORT(minordev);
-       if ((portnr < 0) || (portnr > brdp->nrports))
+       if (portnr > brdp->nrports)
                return -ENODEV;
 
        portp = brdp->ports[portnr];
@@ -1031,8 +876,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
 
 static void stli_close(struct tty_struct *tty, struct file *filp)
 {
-       stlibrd_t *brdp;
-       stliport_t *portp;
+       struct stlibrd *brdp;
+       struct stliport *portp;
        unsigned long flags;
 
        portp = tty->driver_data;
@@ -1109,7 +954,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
  *     this still all happens pretty quickly.
  */
 
-static int stli_initopen(stlibrd_t *brdp, stliport_t *portp)
+static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
 {
        struct tty_struct *tty;
        asynotify_t nt;
@@ -1157,7 +1002,7 @@ static int stli_initopen(stlibrd_t *brdp, stliport_t *portp)
  *     to overlap.
  */
 
-static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
+static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
 {
        cdkhdr_t __iomem *hdrp;
        cdkctrl_t __iomem *cp;
@@ -1228,7 +1073,7 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i
  *     wait is true then must have user context (to sleep).
  */
 
-static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
+static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
 {
        cdkhdr_t __iomem *hdrp;
        cdkctrl_t __iomem *cp;
@@ -1292,7 +1137,7 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg,
  *     to complete (as opposed to initiating the command then returning).
  */
 
-static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
 {
        wait_event_interruptible(portp->raw_wait,
                        !test_bit(ST_CMDING, &portp->state));
@@ -1318,16 +1163,16 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v
  *     waiting for the command to complete - so must have user context.
  */
 
-static int stli_setport(stliport_t *portp)
+static int stli_setport(struct stliport *portp)
 {
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
        asyport_t aport;
 
        if (portp == NULL)
                return -ENODEV;
        if (portp->tty == NULL)
                return -ENODEV;
-       if (portp->brdnr < 0 && portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return -ENODEV;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1344,7 +1189,7 @@ static int stli_setport(stliport_t *portp)
  *     maybe because if we are clocal then we don't need to wait...
  */
 
-static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp)
+static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
 {
        unsigned long flags;
        int rc, doclocal;
@@ -1409,8 +1254,8 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
        unsigned char __iomem *bits;
        unsigned char __iomem *shbuf;
        unsigned char *chbuf;
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned int len, stlen, head, tail, size;
        unsigned long flags;
 
@@ -1419,7 +1264,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
-       if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1445,12 +1290,12 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
                stlen = len;
        }
 
-       len = MIN(len, count);
+       len = min(len, (unsigned int)count);
        count = 0;
        shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
 
        while (len > 0) {
-               stlen = MIN(len, stlen);
+               stlen = min(len, stlen);
                memcpy_toio(shbuf + head, chbuf, stlen);
                chbuf += stlen;
                len -= stlen;
@@ -1516,8 +1361,8 @@ static void stli_flushchars(struct tty_struct *tty)
        unsigned char __iomem *bits;
        cdkasy_t __iomem *ap;
        struct tty_struct *cooktty;
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned int len, stlen, head, tail, size, count, cooksize;
        unsigned char *buf;
        unsigned char __iomem *shbuf;
@@ -1541,7 +1386,7 @@ static void stli_flushchars(struct tty_struct *tty)
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1564,13 +1409,13 @@ static void stli_flushchars(struct tty_struct *tty)
                stlen = len;
        }
 
-       len = MIN(len, cooksize);
+       len = min(len, cooksize);
        count = 0;
        shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
        buf = stli_txcookbuf;
 
        while (len > 0) {
-               stlen = MIN(len, stlen);
+               stlen = min(len, stlen);
                memcpy_toio(shbuf + head, buf, stlen);
                buf += stlen;
                len -= stlen;
@@ -1604,8 +1449,8 @@ static void stli_flushchars(struct tty_struct *tty)
 static int stli_writeroom(struct tty_struct *tty)
 {
        cdkasyrq_t __iomem *rp;
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned int head, tail, len;
        unsigned long flags;
 
@@ -1619,7 +1464,7 @@ static int stli_writeroom(struct tty_struct *tty)
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
-       if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1657,8 +1502,8 @@ static int stli_writeroom(struct tty_struct *tty)
 static int stli_charsinbuffer(struct tty_struct *tty)
 {
        cdkasyrq_t __iomem *rp;
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned int head, tail, len;
        unsigned long flags;
 
@@ -1667,7 +1512,7 @@ static int stli_charsinbuffer(struct tty_struct *tty)
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
-       if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1695,10 +1540,10 @@ static int stli_charsinbuffer(struct tty_struct *tty)
  *     Generate the serial struct info.
  */
 
-static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp)
+static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
 {
        struct serial_struct sio;
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
 
        memset(&sio, 0, sizeof(struct serial_struct));
        sio.type = PORT_UNKNOWN;
@@ -1728,7 +1573,7 @@ static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp)
  *     just quietly ignore any requests to change irq, etc.
  */
 
-static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp)
+static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
 {
        struct serial_struct sio;
        int rc;
@@ -1759,13 +1604,13 @@ static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp)
 
 static int stli_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       stliport_t *portp = tty->driver_data;
-       stlibrd_t *brdp;
+       struct stliport *portp = tty->driver_data;
+       struct stlibrd *brdp;
        int rc;
 
        if (portp == NULL)
                return -ENODEV;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1783,13 +1628,13 @@ static int stli_tiocmget(struct tty_struct *tty, struct file *file)
 static int stli_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear)
 {
-       stliport_t *portp = tty->driver_data;
-       stlibrd_t *brdp;
+       struct stliport *portp = tty->driver_data;
+       struct stlibrd *brdp;
        int rts = -1, dtr = -1;
 
        if (portp == NULL)
                return -ENODEV;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1814,8 +1659,8 @@ static int stli_tiocmset(struct tty_struct *tty, struct file *file,
 
 static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned int ival;
        int rc;
        void __user *argp = (void __user *)arg;
@@ -1823,7 +1668,7 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return 0;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1889,11 +1734,11 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
  *     Looks like it is true for the current ttys implementation..!!
  */
 
-static void stli_settermios(struct tty_struct *tty, struct termios *old)
+static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
 {
-       stliport_t *portp;
-       stlibrd_t *brdp;
-       struct termios *tiosp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
+       struct ktermios *tiosp;
        asyport_t aport;
 
        if (tty == NULL)
@@ -1901,7 +1746,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old)
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -1937,7 +1782,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old)
 
 static void stli_throttle(struct tty_struct *tty)
 {
-       stliport_t      *portp = tty->driver_data;
+       struct stliport *portp = tty->driver_data;
        if (portp == NULL)
                return;
        set_bit(ST_RXSTOP, &portp->state);
@@ -1953,7 +1798,7 @@ static void stli_throttle(struct tty_struct *tty)
 
 static void stli_unthrottle(struct tty_struct *tty)
 {
-       stliport_t      *portp = tty->driver_data;
+       struct stliport *portp = tty->driver_data;
        if (portp == NULL)
                return;
        clear_bit(ST_RXSTOP, &portp->state);
@@ -1990,9 +1835,9 @@ static void stli_start(struct tty_struct *tty)
  *     aren't that time critical).
  */
 
-static void stli_dohangup(void *arg)
+static void stli_dohangup(struct work_struct *ugly_api)
 {
-       stliport_t *portp = (stliport_t *) arg;
+       struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup);
        if (portp->tty != NULL) {
                tty_hangup(portp->tty);
        }
@@ -2009,14 +1854,14 @@ static void stli_dohangup(void *arg)
 
 static void stli_hangup(struct tty_struct *tty)
 {
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned long flags;
 
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -2062,14 +1907,14 @@ static void stli_hangup(struct tty_struct *tty)
 
 static void stli_flushbuffer(struct tty_struct *tty)
 {
-       stliport_t *portp;
-       stlibrd_t *brdp;
+       struct stliport *portp;
+       struct stlibrd *brdp;
        unsigned long ftype, flags;
 
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -2099,14 +1944,14 @@ static void stli_flushbuffer(struct tty_struct *tty)
 
 static void stli_breakctl(struct tty_struct *tty, int state)
 {
-       stlibrd_t       *brdp;
-       stliport_t      *portp;
+       struct stlibrd  *brdp;
+       struct stliport *portp;
        long            arg;
 
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -2120,7 +1965,7 @@ static void stli_breakctl(struct tty_struct *tty, int state)
 
 static void stli_waituntilsent(struct tty_struct *tty, int timeout)
 {
-       stliport_t *portp;
+       struct stliport *portp;
        unsigned long tend;
 
        if (tty == NULL)
@@ -2146,14 +1991,14 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
 
 static void stli_sendxchar(struct tty_struct *tty, char ch)
 {
-       stlibrd_t       *brdp;
-       stliport_t      *portp;
+       struct stlibrd  *brdp;
+       struct stliport *portp;
        asyctrl_t       actrl;
 
        portp = tty->driver_data;
        if (portp == NULL)
                return;
-       if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+       if (portp->brdnr >= stli_nrbrds)
                return;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
@@ -2181,7 +2026,7 @@ static void stli_sendxchar(struct tty_struct *tty, char ch)
  *     short then padded with spaces).
  */
 
-static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos)
+static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos)
 {
        char *sp, *uart;
        int rc, cnt;
@@ -2244,9 +2089,9 @@ static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *p
 
 static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       stlibrd_t *brdp;
-       stliport_t *portp;
-       int brdnr, portnr, totalport;
+       struct stlibrd *brdp;
+       struct stliport *portp;
+       unsigned int brdnr, portnr, totalport;
        int curoff, maxoff;
        char *pos;
 
@@ -2316,7 +2161,7 @@ stli_readdone:
  *     entry point)
  */
 
-static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
 {
        cdkhdr_t __iomem *hdrp;
        cdkctrl_t __iomem *cp;
@@ -2352,7 +2197,7 @@ static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd
        spin_unlock_irqrestore(&brd_lock, flags);
 }
 
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
 {
        unsigned long           flags;
 
@@ -2371,7 +2216,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd,
  *     more chars to unload.
  */
 
-static void stli_read(stlibrd_t *brdp, stliport_t *portp)
+static void stli_read(struct stlibrd *brdp, struct stliport *portp)
 {
        cdkasyrq_t __iomem *rp;
        char __iomem *shbuf;
@@ -2406,7 +2251,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
        while (len > 0) {
                unsigned char *cptr;
 
-               stlen = MIN(len, stlen);
+               stlen = min(len, stlen);
                tty_prepare_flip_string(tty, &cptr, stlen);
                memcpy_fromio(cptr, shbuf + tail, stlen);
                len -= stlen;
@@ -2433,7 +2278,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
  *     difficult to deal with them here.
  */
 
-static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp)
+static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
 {
        int cmd;
 
@@ -2481,7 +2326,7 @@ static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp)
  *     then port is still busy, otherwise no longer busy.
  */
 
-static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
+static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
 {
        cdkasy_t __iomem *ap;
        cdkctrl_t __iomem *cp;
@@ -2628,9 +2473,9 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
  *     at the cdk header structure.
  */
 
-static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp)
+static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
 {
-       stliport_t *portp;
+       struct stliport *portp;
        unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
        unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
        unsigned char __iomem *slavep;
@@ -2697,11 +2542,10 @@ static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp)
 static void stli_poll(unsigned long arg)
 {
        cdkhdr_t __iomem *hdrp;
-       stlibrd_t *brdp;
-       int brdnr;
+       struct stlibrd *brdp;
+       unsigned int brdnr;
 
-       stli_timerlist.expires = STLI_TIMEOUT;
-       add_timer(&stli_timerlist);
+       mod_timer(&stli_timerlist, STLI_TIMEOUT);
 
 /*
  *     Check each board and do any servicing required.
@@ -2730,7 +2574,7 @@ static void stli_poll(unsigned long arg)
  *     the slave.
  */
 
-static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
+static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
 {
        memset(pp, 0, sizeof(asyport_t));
 
@@ -2879,13 +2723,13 @@ static long stli_mktiocm(unsigned long sigvalue)
  *     we need to do here is set up the appropriate per port data structures.
  */
 
-static int stli_initports(stlibrd_t *brdp)
+static int stli_initports(struct stlibrd *brdp)
 {
-       stliport_t      *portp;
-       int             i, panelnr, panelport;
+       struct stliport *portp;
+       unsigned int i, panelnr, panelport;
 
        for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
-               portp = kzalloc(sizeof(stliport_t), GFP_KERNEL);
+               portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
                if (!portp) {
                        printk("STALLION: failed to allocate port structure\n");
                        continue;
@@ -2898,7 +2742,7 @@ static int stli_initports(stlibrd_t *brdp)
                portp->baud_base = STL_BAUDBASE;
                portp->close_delay = STL_CLOSEDELAY;
                portp->closing_wait = 30 * HZ;
-               INIT_WORK(&portp->tqhangup, stli_dohangup, portp);
+               INIT_WORK(&portp->tqhangup, stli_dohangup);
                init_waitqueue_head(&portp->open_wait);
                init_waitqueue_head(&portp->close_wait);
                init_waitqueue_head(&portp->raw_wait);
@@ -2919,7 +2763,7 @@ static int stli_initports(stlibrd_t *brdp)
  *     All the following routines are board specific hardware operations.
  */
 
-static void stli_ecpinit(stlibrd_t *brdp)
+static void stli_ecpinit(struct stlibrd *brdp)
 {
        unsigned long   memconf;
 
@@ -2934,21 +2778,21 @@ static void stli_ecpinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void stli_ecpenable(stlibrd_t *brdp)
+static void stli_ecpenable(struct stlibrd *brdp)
 {      
        outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
 }
 
 /*****************************************************************************/
 
-static void stli_ecpdisable(stlibrd_t *brdp)
+static void stli_ecpdisable(struct stlibrd *brdp)
 {      
        outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
 }
 
 /*****************************************************************************/
 
-static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char val;
@@ -2969,7 +2813,7 @@ static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, in
 
 /*****************************************************************************/
 
-static void stli_ecpreset(stlibrd_t *brdp)
+static void stli_ecpreset(struct stlibrd *brdp)
 {      
        outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
        udelay(10);
@@ -2979,7 +2823,7 @@ static void stli_ecpreset(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void stli_ecpintr(stlibrd_t *brdp)
+static void stli_ecpintr(struct stlibrd *brdp)
 {      
        outb(0x1, brdp->iobase);
 }
@@ -2990,7 +2834,7 @@ static void stli_ecpintr(stlibrd_t *brdp)
  *     The following set of functions act on ECP EISA boards.
  */
 
-static void stli_ecpeiinit(stlibrd_t *brdp)
+static void stli_ecpeiinit(struct stlibrd *brdp)
 {
        unsigned long   memconf;
 
@@ -3008,21 +2852,21 @@ static void stli_ecpeiinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void stli_ecpeienable(stlibrd_t *brdp)
+static void stli_ecpeienable(struct stlibrd *brdp)
 {      
        outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
 }
 
 /*****************************************************************************/
 
-static void stli_ecpeidisable(stlibrd_t *brdp)
+static void stli_ecpeidisable(struct stlibrd *brdp)
 {      
        outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
 }
 
 /*****************************************************************************/
 
-static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char   val;
@@ -3046,7 +2890,7 @@ static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset,
 
 /*****************************************************************************/
 
-static void stli_ecpeireset(stlibrd_t *brdp)
+static void stli_ecpeireset(struct stlibrd *brdp)
 {      
        outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
        udelay(10);
@@ -3060,21 +2904,21 @@ static void stli_ecpeireset(stlibrd_t *brdp)
  *     The following set of functions act on ECP MCA boards.
  */
 
-static void stli_ecpmcenable(stlibrd_t *brdp)
+static void stli_ecpmcenable(struct stlibrd *brdp)
 {      
        outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
 }
 
 /*****************************************************************************/
 
-static void stli_ecpmcdisable(stlibrd_t *brdp)
+static void stli_ecpmcdisable(struct stlibrd *brdp)
 {      
        outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
 }
 
 /*****************************************************************************/
 
-static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char val;
@@ -3095,7 +2939,7 @@ static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset,
 
 /*****************************************************************************/
 
-static void stli_ecpmcreset(stlibrd_t *brdp)
+static void stli_ecpmcreset(struct stlibrd *brdp)
 {      
        outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
        udelay(10);
@@ -3109,7 +2953,7 @@ static void stli_ecpmcreset(stlibrd_t *brdp)
  *     The following set of functions act on ECP PCI boards.
  */
 
-static void stli_ecppciinit(stlibrd_t *brdp)
+static void stli_ecppciinit(struct stlibrd *brdp)
 {
        outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
        udelay(10);
@@ -3119,7 +2963,7 @@ static void stli_ecppciinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char   val;
@@ -3140,7 +2984,7 @@ static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset,
 
 /*****************************************************************************/
 
-static void stli_ecppcireset(stlibrd_t *brdp)
+static void stli_ecppcireset(struct stlibrd *brdp)
 {      
        outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
        udelay(10);
@@ -3154,7 +2998,7 @@ static void stli_ecppcireset(stlibrd_t *brdp)
  *     The following routines act on ONboards.
  */
 
-static void stli_onbinit(stlibrd_t *brdp)
+static void stli_onbinit(struct stlibrd *brdp)
 {
        unsigned long   memconf;
 
@@ -3171,21 +3015,21 @@ static void stli_onbinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void stli_onbenable(stlibrd_t *brdp)
+static void stli_onbenable(struct stlibrd *brdp)
 {      
        outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
 }
 
 /*****************************************************************************/
 
-static void stli_onbdisable(stlibrd_t *brdp)
+static void stli_onbdisable(struct stlibrd *brdp)
 {      
        outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
 }
 
 /*****************************************************************************/
 
-static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
 
@@ -3202,7 +3046,7 @@ static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, in
 
 /*****************************************************************************/
 
-static void stli_onbreset(stlibrd_t *brdp)
+static void stli_onbreset(struct stlibrd *brdp)
 {      
        outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
        udelay(10);
@@ -3216,7 +3060,7 @@ static void stli_onbreset(stlibrd_t *brdp)
  *     The following routines act on ONboard EISA.
  */
 
-static void stli_onbeinit(stlibrd_t *brdp)
+static void stli_onbeinit(struct stlibrd *brdp)
 {
        unsigned long   memconf;
 
@@ -3236,21 +3080,21 @@ static void stli_onbeinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void stli_onbeenable(stlibrd_t *brdp)
+static void stli_onbeenable(struct stlibrd *brdp)
 {      
        outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
 }
 
 /*****************************************************************************/
 
-static void stli_onbedisable(stlibrd_t *brdp)
+static void stli_onbedisable(struct stlibrd *brdp)
 {      
        outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
 }
 
 /*****************************************************************************/
 
-static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char val;
@@ -3274,7 +3118,7 @@ static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, i
 
 /*****************************************************************************/
 
-static void stli_onbereset(stlibrd_t *brdp)
+static void stli_onbereset(struct stlibrd *brdp)
 {      
        outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
        udelay(10);
@@ -3288,7 +3132,7 @@ static void stli_onbereset(stlibrd_t *brdp)
  *     The following routines act on Brumby boards.
  */
 
-static void stli_bbyinit(stlibrd_t *brdp)
+static void stli_bbyinit(struct stlibrd *brdp)
 {
        outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
        udelay(10);
@@ -3300,7 +3144,7 @@ static void stli_bbyinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        void __iomem *ptr;
        unsigned char val;
@@ -3315,7 +3159,7 @@ static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, in
 
 /*****************************************************************************/
 
-static void stli_bbyreset(stlibrd_t *brdp)
+static void stli_bbyreset(struct stlibrd *brdp)
 {      
        outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
        udelay(10);
@@ -3329,7 +3173,7 @@ static void stli_bbyreset(stlibrd_t *brdp)
  *     The following routines act on original old Stallion boards.
  */
 
-static void stli_stalinit(stlibrd_t *brdp)
+static void stli_stalinit(struct stlibrd *brdp)
 {
        outb(0x1, brdp->iobase);
        mdelay(1000);
@@ -3337,7 +3181,7 @@ static void stli_stalinit(stlibrd_t *brdp)
 
 /*****************************************************************************/
 
-static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
 {      
        BUG_ON(offset > brdp->memsize);
        return brdp->membase + (offset % STAL_PAGESIZE);
@@ -3345,7 +3189,7 @@ static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, i
 
 /*****************************************************************************/
 
-static void stli_stalreset(stlibrd_t *brdp)
+static void stli_stalreset(struct stlibrd *brdp)
 {      
        u32 __iomem *vecp;
 
@@ -3362,21 +3206,22 @@ static void stli_stalreset(stlibrd_t *brdp)
  *     board types.
  */
 
-static int stli_initecp(stlibrd_t *brdp)
+static int stli_initecp(struct stlibrd *brdp)
 {
        cdkecpsig_t sig;
        cdkecpsig_t __iomem *sigsp;
        unsigned int status, nxtid;
        char *name;
-       int panelnr, nrports;
+       int retval, panelnr, nrports;
 
-       if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
-               return -EIO;
-       
-       if ((brdp->iobase == 0) || (brdp->memaddr == 0))
-       {
-               release_region(brdp->iobase, brdp->iosize);
-               return -ENODEV;
+       if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
+               retval = -ENODEV;
+               goto err;
+       }
+
+       if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+               retval = -EIO;
+               goto err;
        }
 
        brdp->iosize = ECP_IOSIZE;
@@ -3388,7 +3233,6 @@ static int stli_initecp(stlibrd_t *brdp)
  */
        switch (brdp->brdtype) {
        case BRD_ECP:
-               brdp->membase = (void *) brdp->memaddr;
                brdp->memsize = ECP_MEMSIZE;
                brdp->pagesize = ECP_ATPAGESIZE;
                brdp->init = stli_ecpinit;
@@ -3402,7 +3246,6 @@ static int stli_initecp(stlibrd_t *brdp)
                break;
 
        case BRD_ECPE:
-               brdp->membase = (void *) brdp->memaddr;
                brdp->memsize = ECP_MEMSIZE;
                brdp->pagesize = ECP_EIPAGESIZE;
                brdp->init = stli_ecpeiinit;
@@ -3416,7 +3259,6 @@ static int stli_initecp(stlibrd_t *brdp)
                break;
 
        case BRD_ECPMC:
-               brdp->membase = (void *) brdp->memaddr;
                brdp->memsize = ECP_MEMSIZE;
                brdp->pagesize = ECP_MCPAGESIZE;
                brdp->init = NULL;
@@ -3430,7 +3272,6 @@ static int stli_initecp(stlibrd_t *brdp)
                break;
 
        case BRD_ECPPCI:
-               brdp->membase = (void *) brdp->memaddr;
                brdp->memsize = ECP_PCIMEMSIZE;
                brdp->pagesize = ECP_PCIPAGESIZE;
                brdp->init = stli_ecppciinit;
@@ -3444,8 +3285,8 @@ static int stli_initecp(stlibrd_t *brdp)
                break;
 
        default:
-               release_region(brdp->iobase, brdp->iosize);
-               return -EINVAL;
+               retval = -EINVAL;
+               goto err_reg;
        }
 
 /*
@@ -3457,10 +3298,9 @@ static int stli_initecp(stlibrd_t *brdp)
        EBRDINIT(brdp);
 
        brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
-       if (brdp->membase == NULL)
-       {
-               release_region(brdp->iobase, brdp->iosize);
-               return -ENOMEM;
+       if (brdp->membase == NULL) {
+               retval = -ENOMEM;
+               goto err_reg;
        }
 
 /*
@@ -3473,10 +3313,9 @@ static int stli_initecp(stlibrd_t *brdp)
        memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
        EBRDDISABLE(brdp);
 
-       if (sig.magic != cpu_to_le32(ECP_MAGIC))
-       {
-               release_region(brdp->iobase, brdp->iosize);
-               return -ENODEV;
+       if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
+               retval = -ENODEV;
+               goto err_unmap;
        }
 
 /*
@@ -3501,6 +3340,13 @@ static int stli_initecp(stlibrd_t *brdp)
 
        brdp->state |= BST_FOUND;
        return 0;
+err_unmap:
+       iounmap(brdp->membase);
+       brdp->membase = NULL;
+err_reg:
+       release_region(brdp->iobase, brdp->iosize);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -3510,23 +3356,27 @@ static int stli_initecp(stlibrd_t *brdp)
  *     This handles only these board types.
  */
 
-static int stli_initonb(stlibrd_t *brdp)
+static int stli_initonb(struct stlibrd *brdp)
 {
        cdkonbsig_t sig;
        cdkonbsig_t __iomem *sigsp;
        char *name;
-       int i;
+       int i, retval;
 
 /*
  *     Do a basic sanity check on the IO and memory addresses.
  */
-       if (brdp->iobase == 0 || brdp->memaddr == 0)
-               return -ENODEV;
+       if (brdp->iobase == 0 || brdp->memaddr == 0) {
+               retval = -ENODEV;
+               goto err;
+       }
 
        brdp->iosize = ONB_IOSIZE;
        
-       if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
-               return -EIO;
+       if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+               retval = -EIO;
+               goto err;
+       }
 
 /*
  *     Based on the specific board type setup the common vars to access
@@ -3535,10 +3385,7 @@ static int stli_initonb(stlibrd_t *brdp)
  */
        switch (brdp->brdtype) {
        case BRD_ONBOARD:
-       case BRD_ONBOARD32:
        case BRD_ONBOARD2:
-       case BRD_ONBOARD2_32:
-       case BRD_ONBOARDRS:
                brdp->memsize = ONB_MEMSIZE;
                brdp->pagesize = ONB_ATPAGESIZE;
                brdp->init = stli_onbinit;
@@ -3569,8 +3416,6 @@ static int stli_initonb(stlibrd_t *brdp)
                break;
 
        case BRD_BRUMBY4:
-       case BRD_BRUMBY8:
-       case BRD_BRUMBY16:
                brdp->memsize = BBY_MEMSIZE;
                brdp->pagesize = BBY_PAGESIZE;
                brdp->init = stli_bbyinit;
@@ -3597,8 +3442,8 @@ static int stli_initonb(stlibrd_t *brdp)
                break;
 
        default:
-               release_region(brdp->iobase, brdp->iosize);
-               return -EINVAL;
+               retval = -EINVAL;
+               goto err_reg;
        }
 
 /*
@@ -3610,10 +3455,9 @@ static int stli_initonb(stlibrd_t *brdp)
        EBRDINIT(brdp);
 
        brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
-       if (brdp->membase == NULL)
-       {
-               release_region(brdp->iobase, brdp->iosize);
-               return -ENOMEM;
+       if (brdp->membase == NULL) {
+               retval = -ENOMEM;
+               goto err_reg;
        }
 
 /*
@@ -3629,10 +3473,9 @@ static int stli_initonb(stlibrd_t *brdp)
        if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
            sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
            sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
-           sig.magic3 != cpu_to_le16(ONB_MAGIC3))
-       {
-               release_region(brdp->iobase, brdp->iosize);
-               return -ENODEV;
+           sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
+               retval = -ENODEV;
+               goto err_unmap;
        }
 
 /*
@@ -3654,6 +3497,13 @@ static int stli_initonb(stlibrd_t *brdp)
 
        brdp->state |= BST_FOUND;
        return 0;
+err_unmap:
+       iounmap(brdp->membase);
+       brdp->membase = NULL;
+err_reg:
+       release_region(brdp->iobase, brdp->iosize);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -3664,14 +3514,15 @@ static int stli_initonb(stlibrd_t *brdp)
  *     read in the memory map, and get the show on the road...
  */
 
-static int stli_startbrd(stlibrd_t *brdp)
+static int stli_startbrd(struct stlibrd *brdp)
 {
        cdkhdr_t __iomem *hdrp;
        cdkmem_t __iomem *memp;
        cdkasy_t __iomem *ap;
        unsigned long flags;
-       stliport_t *portp;
-       int portnr, nrdevs, i, rc = 0;
+       unsigned int portnr, nrdevs, i;
+       struct stliport *portp;
+       int rc = 0;
        u32 memoff;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -3758,8 +3609,7 @@ stli_donestartup:
 
        if (! stli_timeron) {
                stli_timeron++;
-               stli_timerlist.expires = STLI_TIMEOUT;
-               add_timer(&stli_timerlist);
+               mod_timer(&stli_timerlist, STLI_TIMEOUT);
        }
 
        return rc;
@@ -3771,49 +3621,32 @@ stli_donestartup:
  *     Probe and initialize the specified board.
  */
 
-static int __init stli_brdinit(stlibrd_t *brdp)
+static int __devinit stli_brdinit(struct stlibrd *brdp)
 {
-       stli_brds[brdp->brdnr] = brdp;
+       int retval;
 
        switch (brdp->brdtype) {
        case BRD_ECP:
        case BRD_ECPE:
        case BRD_ECPMC:
        case BRD_ECPPCI:
-               stli_initecp(brdp);
+               retval = stli_initecp(brdp);
                break;
        case BRD_ONBOARD:
        case BRD_ONBOARDE:
        case BRD_ONBOARD2:
-       case BRD_ONBOARD32:
-       case BRD_ONBOARD2_32:
-       case BRD_ONBOARDRS:
        case BRD_BRUMBY4:
-       case BRD_BRUMBY8:
-       case BRD_BRUMBY16:
        case BRD_STALLION:
-               stli_initonb(brdp);
+               retval = stli_initonb(brdp);
                break;
-       case BRD_EASYIO:
-       case BRD_ECH:
-       case BRD_ECHMC:
-       case BRD_ECHPCI:
-               printk(KERN_ERR "STALLION: %s board type not supported in "
-                               "this driver\n", stli_brdnames[brdp->brdtype]);
-               return -ENODEV;
        default:
                printk(KERN_ERR "STALLION: board=%d is unknown board "
                                "type=%d\n", brdp->brdnr, brdp->brdtype);
-               return -ENODEV;
+               retval = -ENODEV;
        }
 
-       if ((brdp->state & BST_FOUND) == 0) {
-               printk(KERN_ERR "STALLION: %s board not found, board=%d "
-                               "io=%x mem=%x\n",
-                       stli_brdnames[brdp->brdtype], brdp->brdnr,
-                       brdp->iobase, (int) brdp->memaddr);
-               return -ENODEV;
-       }
+       if (retval)
+               return retval;
 
        stli_initports(brdp);
        printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x "
@@ -3823,6 +3656,7 @@ static int __init stli_brdinit(stlibrd_t *brdp)
        return 0;
 }
 
+#if STLI_EISAPROBE != 0
 /*****************************************************************************/
 
 /*
@@ -3830,7 +3664,7 @@ static int __init stli_brdinit(stlibrd_t *brdp)
  *     might be. This is a bit if hack, but it is the best we can do.
  */
 
-static int stli_eisamemprobe(stlibrd_t *brdp)
+static int stli_eisamemprobe(struct stlibrd *brdp)
 {
        cdkecpsig_t     ecpsig, __iomem *ecpsigp;
        cdkonbsig_t     onbsig, __iomem *onbsigp;
@@ -3916,10 +3750,11 @@ static int stli_eisamemprobe(stlibrd_t *brdp)
        }
        return 0;
 }
+#endif
 
 static int stli_getbrdnr(void)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < STL_MAXBRDS; i++) {
                if (!stli_brds[i]) {
@@ -3931,6 +3766,7 @@ static int stli_getbrdnr(void)
        return -1;
 }
 
+#if STLI_EISAPROBE != 0
 /*****************************************************************************/
 
 /*
@@ -3945,9 +3781,9 @@ static int stli_getbrdnr(void)
 
 static int stli_findeisabrds(void)
 {
-       stlibrd_t *brdp;
-       unsigned int iobase, eid;
-       int i;
+       struct stlibrd *brdp;
+       unsigned int iobase, eid, i;
+       int brdnr, found = 0;
 
 /*
  *     Firstly check if this is an EISA system.  If this is not an EISA system then
@@ -3985,9 +3821,11 @@ static int stli_findeisabrds(void)
  *             Allocate a board structure and initialize it.
  */
                if ((brdp = stli_allocbrd()) == NULL)
-                       return -ENOMEM;
-               if ((brdp->brdnr = stli_getbrdnr()) < 0)
-                       return -ENOMEM;
+                       return found ? : -ENOMEM;
+               brdnr = stli_getbrdnr();
+               if (brdnr < 0)
+                       return found ? : -ENOMEM;
+               brdp->brdnr = (unsigned int)brdnr;
                eid = inb(iobase + 0xc82);
                if (eid == ECP_EISAID)
                        brdp->brdtype = BRD_ECPE;
@@ -3999,11 +3837,24 @@ static int stli_findeisabrds(void)
                outb(0x1, (iobase + 0xc84));
                if (stli_eisamemprobe(brdp))
                        outb(0, (iobase + 0xc84));
-               stli_brdinit(brdp);
+               if (stli_brdinit(brdp) < 0) {
+                       kfree(brdp);
+                       continue;
+               }
+
+               stli_brds[brdp->brdnr] = brdp;
+               found++;
+
+               for (i = 0; i < brdp->nrports; i++)
+                       tty_register_device(stli_serial,
+                                       brdp->brdnr * STL_MAXPORTS + i, NULL);
        }
 
-       return 0;
+       return found;
 }
+#else
+static inline int stli_findeisabrds(void) { return 0; }
+#endif
 
 /*****************************************************************************/
 
@@ -4013,72 +3864,104 @@ static int stli_findeisabrds(void)
 
 /*****************************************************************************/
 
-#ifdef CONFIG_PCI
-
 /*
  *     We have a Stallion board. Allocate a board structure and
  *     initialize it. Read its IO and MEMORY resources from PCI
  *     configuration space.
  */
 
-static int stli_initpcibrd(int brdtype, struct pci_dev *devp)
+static int __devinit stli_pciprobe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
 {
-       stlibrd_t *brdp;
-
-       if (pci_enable_device(devp))
-               return -EIO;
-       if ((brdp = stli_allocbrd()) == NULL)
-               return -ENOMEM;
-       if ((brdp->brdnr = stli_getbrdnr()) < 0) {
+       struct stlibrd *brdp;
+       unsigned int i;
+       int brdnr, retval = -EIO;
+
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto err;
+       brdp = stli_allocbrd();
+       if (brdp == NULL) {
+               retval = -ENOMEM;
+               goto err;
+       }
+       mutex_lock(&stli_brdslock);
+       brdnr = stli_getbrdnr();
+       if (brdnr < 0) {
                printk(KERN_INFO "STALLION: too many boards found, "
                        "maximum supported %d\n", STL_MAXBRDS);
-               return 0;
+               mutex_unlock(&stli_brdslock);
+               retval = -EIO;
+               goto err_fr;
        }
-       brdp->brdtype = brdtype;
+       brdp->brdnr = (unsigned int)brdnr;
+       stli_brds[brdp->brdnr] = brdp;
+       mutex_unlock(&stli_brdslock);
+       brdp->brdtype = BRD_ECPPCI;
 /*
  *     We have all resources from the board, so lets setup the actual
  *     board structure now.
  */
-       brdp->iobase = pci_resource_start(devp, 3);
-       brdp->memaddr = pci_resource_start(devp, 2);
-       stli_brdinit(brdp);
+       brdp->iobase = pci_resource_start(pdev, 3);
+       brdp->memaddr = pci_resource_start(pdev, 2);
+       retval = stli_brdinit(brdp);
+       if (retval)
+               goto err_null;
+
+       brdp->state |= BST_PROBED;
+       pci_set_drvdata(pdev, brdp);
+
+       EBRDENABLE(brdp);
+       brdp->enable = NULL;
+       brdp->disable = NULL;
+
+       for (i = 0; i < brdp->nrports; i++)
+               tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
+                               &pdev->dev);
 
        return 0;
+err_null:
+       stli_brds[brdp->brdnr] = NULL;
+err_fr:
+       kfree(brdp);
+err:
+       return retval;
 }
 
-/*****************************************************************************/
+static void stli_pciremove(struct pci_dev *pdev)
+{
+       struct stlibrd *brdp = pci_get_drvdata(pdev);
 
-/*
- *     Find all Stallion PCI boards that might be installed. Initialize each
- *     one as it is found.
- */
+       stli_cleanup_ports(brdp);
 
-static int stli_findpcibrds(void)
-{
-       struct pci_dev *dev = NULL;
+       iounmap(brdp->membase);
+       if (brdp->iosize > 0)
+               release_region(brdp->iobase, brdp->iosize);
 
-       while ((dev = pci_get_device(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, dev))) {
-               stli_initpcibrd(BRD_ECPPCI, dev);
-       }
-       return 0;
+       stli_brds[brdp->brdnr] = NULL;
+       kfree(brdp);
 }
 
-#endif
-
+static struct pci_driver stli_pcidriver = {
+       .name = "istallion",
+       .id_table = istallion_pci_tbl,
+       .probe = stli_pciprobe,
+       .remove = __devexit_p(stli_pciremove)
+};
 /*****************************************************************************/
 
 /*
  *     Allocate a new board structure. Fill out the basic info in it.
  */
 
-static stlibrd_t *stli_allocbrd(void)
+static struct stlibrd *stli_allocbrd(void)
 {
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
 
-       brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL);
+       brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
        if (!brdp) {
                printk(KERN_ERR "STALLION: failed to allocate memory "
-                               "(size=%Zd)\n", sizeof(stlibrd_t));
+                               "(size=%Zd)\n", sizeof(struct stlibrd));
                return NULL;
        }
        brdp->magic = STLI_BOARDMAGIC;
@@ -4094,43 +3977,37 @@ static stlibrd_t *stli_allocbrd(void)
 
 static int stli_initbrds(void)
 {
-       stlibrd_t *brdp, *nxtbrdp;
-       stlconf_t *confp;
-       int i, j;
-
-       if (stli_nrbrds > STL_MAXBRDS) {
-               printk(KERN_INFO "STALLION: too many boards in configuration "
-                       "table, truncating to %d\n", STL_MAXBRDS);
-               stli_nrbrds = STL_MAXBRDS;
-       }
+       struct stlibrd *brdp, *nxtbrdp;
+       struct stlconf conf;
+       unsigned int i, j, found = 0;
+       int retval;
 
-/*
- *     Firstly scan the list of static boards configured. Allocate
- *     resources and initialize the boards as found. If this is a
- *     module then let the module args override static configuration.
- */
-       for (i = 0; (i < stli_nrbrds); i++) {
-               confp = &stli_brdconf[i];
-               stli_parsebrd(confp, stli_brdsp[i]);
+       for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
+                       stli_nrbrds++) {
+               memset(&conf, 0, sizeof(conf));
+               if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
+                       continue;
                if ((brdp = stli_allocbrd()) == NULL)
-                       return -ENOMEM;
-               brdp->brdnr = i;
-               brdp->brdtype = confp->brdtype;
-               brdp->iobase = confp->ioaddr1;
-               brdp->memaddr = confp->memaddr;
-               stli_brdinit(brdp);
+                       continue;
+               brdp->brdnr = stli_nrbrds;
+               brdp->brdtype = conf.brdtype;
+               brdp->iobase = conf.ioaddr1;
+               brdp->memaddr = conf.memaddr;
+               if (stli_brdinit(brdp) < 0) {
+                       kfree(brdp);
+                       continue;
+               }
+               stli_brds[brdp->brdnr] = brdp;
+               found++;
+
+               for (i = 0; i < brdp->nrports; i++)
+                       tty_register_device(stli_serial,
+                                       brdp->brdnr * STL_MAXPORTS + i, NULL);
        }
 
-/*
- *     Static configuration table done, so now use dynamic methods to
- *     see if any more boards should be configured.
- */
-       stli_argbrds();
-       if (STLI_EISAPROBE)
-               stli_findeisabrds();
-#ifdef CONFIG_PCI
-       stli_findpcibrds();
-#endif
+       retval = stli_findeisabrds();
+       if (retval > 0)
+               found += retval;
 
 /*
  *     All found boards are initialized. Now for a little optimization, if
@@ -4170,7 +4047,16 @@ static int stli_initbrds(void)
                }
        }
 
+       retval = pci_register_driver(&stli_pcidriver);
+       if (retval && found == 0) {
+               printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
+                               "driver can be registered!\n");
+               goto err;
+       }
+
        return 0;
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -4185,12 +4071,13 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
 {
        unsigned long flags;
        void __iomem *memptr;
-       stlibrd_t *brdp;
-       int brdnr, size, n;
+       struct stlibrd *brdp;
+       unsigned int brdnr;
+       int size, n;
        void *p;
        loff_t off = *offp;
 
-       brdnr = iminor(fp->f_dentry->d_inode);
+       brdnr = iminor(fp->f_path.dentry->d_inode);
        if (brdnr >= stli_nrbrds)
                return -ENODEV;
        brdp = stli_brds[brdnr];
@@ -4201,7 +4088,7 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
        if (off >= brdp->memsize || off + count < off)
                return 0;
 
-       size = MIN(count, (brdp->memsize - off));
+       size = min(count, (size_t)(brdp->memsize - off));
 
        /*
         *      Copy the data a page at a time
@@ -4215,8 +4102,8 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
                spin_lock_irqsave(&brd_lock, flags);
                EBRDENABLE(brdp);
                memptr = EBRDGETMEMPTR(brdp, off);
-               n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-               n = MIN(n, PAGE_SIZE);
+               n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+               n = min(n, (int)PAGE_SIZE);
                memcpy_fromio(p, memptr, n);
                EBRDDISABLE(brdp);
                spin_unlock_irqrestore(&brd_lock, flags);
@@ -4248,13 +4135,14 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
 {
        unsigned long flags;
        void __iomem *memptr;
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
        char __user *chbuf;
-       int brdnr, size, n;
+       unsigned int brdnr;
+       int size, n;
        void *p;
        loff_t off = *offp;
 
-       brdnr = iminor(fp->f_dentry->d_inode);
+       brdnr = iminor(fp->f_path.dentry->d_inode);
 
        if (brdnr >= stli_nrbrds)
                return -ENODEV;
@@ -4267,7 +4155,7 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
                return 0;
 
        chbuf = (char __user *) buf;
-       size = MIN(count, (brdp->memsize - off));
+       size = min(count, (size_t)(brdp->memsize - off));
 
        /*
         *      Copy the data a page at a time
@@ -4278,8 +4166,8 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
                return -ENOMEM;
 
        while (size > 0) {
-               n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-               n = MIN(n, PAGE_SIZE);
+               n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+               n = min(n, (int)PAGE_SIZE);
                if (copy_from_user(p, chbuf, n)) {
                        if (count == 0)
                                count = -EFAULT;
@@ -4309,8 +4197,8 @@ out:
 
 static int stli_getbrdstats(combrd_t __user *bp)
 {
-       stlibrd_t *brdp;
-       int i;
+       struct stlibrd *brdp;
+       unsigned int i;
 
        if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
                return -EFAULT;
@@ -4346,19 +4234,20 @@ static int stli_getbrdstats(combrd_t __user *bp)
  *     Resolve the referenced port number into a port struct pointer.
  */
 
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
+               unsigned int portnr)
 {
-       stlibrd_t *brdp;
-       int i;
+       struct stlibrd *brdp;
+       unsigned int i;
 
-       if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+       if (brdnr >= STL_MAXBRDS)
                return NULL;
        brdp = stli_brds[brdnr];
        if (brdp == NULL)
                return NULL;
        for (i = 0; (i < panelnr); i++)
                portnr += brdp->panels[i];
-       if ((portnr < 0) || (portnr >= brdp->nrports))
+       if (portnr >= brdp->nrports)
                return NULL;
        return brdp->ports[portnr];
 }
@@ -4371,10 +4260,10 @@ static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
  *     what port to get stats for (used through board control device).
  */
 
-static int stli_portcmdstats(stliport_t *portp)
+static int stli_portcmdstats(struct stliport *portp)
 {
        unsigned long   flags;
-       stlibrd_t       *brdp;
+       struct stlibrd  *brdp;
        int             rc;
 
        memset(&stli_comstats, 0, sizeof(comstats_t));
@@ -4445,9 +4334,9 @@ static int stli_portcmdstats(stliport_t *portp)
  *     what port to get stats for (used through board control device).
  */
 
-static int stli_getportstats(stliport_t *portp, comstats_t __user *cp)
+static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
 {
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
        int rc;
 
        if (!portp) {
@@ -4476,9 +4365,9 @@ static int stli_getportstats(stliport_t *portp, comstats_t __user *cp)
  *     Clear the port stats structure. We also return it zeroed out...
  */
 
-static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp)
+static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
 {
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
        int rc;
 
        if (!portp) {
@@ -4515,17 +4404,18 @@ static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp)
  *     Return the entire driver ports structure to a user app.
  */
 
-static int stli_getportstruct(stliport_t __user *arg)
+static int stli_getportstruct(struct stliport __user *arg)
 {
-       stliport_t *portp;
+       struct stliport stli_dummyport;
+       struct stliport *portp;
 
-       if (copy_from_user(&stli_dummyport, arg, sizeof(stliport_t)))
+       if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
                return -EFAULT;
        portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
                 stli_dummyport.portnr);
        if (!portp)
                return -ENODEV;
-       if (copy_to_user(arg, portp, sizeof(stliport_t)))
+       if (copy_to_user(arg, portp, sizeof(struct stliport)))
                return -EFAULT;
        return 0;
 }
@@ -4536,18 +4426,19 @@ static int stli_getportstruct(stliport_t __user *arg)
  *     Return the entire driver board structure to a user app.
  */
 
-static int stli_getbrdstruct(stlibrd_t __user *arg)
+static int stli_getbrdstruct(struct stlibrd __user *arg)
 {
-       stlibrd_t *brdp;
+       struct stlibrd stli_dummybrd;
+       struct stlibrd *brdp;
 
-       if (copy_from_user(&stli_dummybrd, arg, sizeof(stlibrd_t)))
+       if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
                return -EFAULT;
-       if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS))
+       if (stli_dummybrd.brdnr >= STL_MAXBRDS)
                return -ENODEV;
        brdp = stli_brds[stli_dummybrd.brdnr];
        if (!brdp)
                return -ENODEV;
-       if (copy_to_user(arg, brdp, sizeof(stlibrd_t)))
+       if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
                return -EFAULT;
        return 0;
 }
@@ -4562,7 +4453,7 @@ static int stli_getbrdstruct(stlibrd_t __user *arg)
 
 static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
 {
-       stlibrd_t *brdp;
+       struct stlibrd *brdp;
        int brdnr, rc, done;
        void __user *argp = (void __user *)arg;
 
@@ -4661,46 +4552,53 @@ static const struct tty_operations stli_ops = {
 };
 
 /*****************************************************************************/
+/*
+ *     Loadable module initialization stuff.
+ */
+
+static void istallion_cleanup_isa(void)
+{
+       struct stlibrd  *brdp;
+       unsigned int j;
+
+       for (j = 0; (j < stli_nrbrds); j++) {
+               if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
+                       continue;
 
-static int __init stli_init(void)
+               stli_cleanup_ports(brdp);
+
+               iounmap(brdp->membase);
+               if (brdp->iosize > 0)
+                       release_region(brdp->iobase, brdp->iosize);
+               kfree(brdp);
+               stli_brds[j] = NULL;
+       }
+}
+
+static int __init istallion_module_init(void)
 {
-       int i;
+       unsigned int i;
+       int retval;
+
        printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
 
        spin_lock_init(&stli_lock);
        spin_lock_init(&brd_lock);
 
-       stli_initbrds();
-
-       stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-       if (!stli_serial)
-               return -ENOMEM;
-
-/*
- *     Allocate a temporary write buffer.
- */
        stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
-       if (!stli_txcookbuf)
+       if (!stli_txcookbuf) {
                printk(KERN_ERR "STALLION: failed to allocate memory "
                                "(size=%d)\n", STLI_TXBUFSIZE);
+               retval = -ENOMEM;
+               goto err;
+       }
 
-/*
- *     Set up a character driver for the shared memory region. We need this
- *     to down load the slave code image. Also it is a useful debugging tool.
- */
-       if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
-               printk(KERN_ERR "STALLION: failed to register serial memory "
-                               "device\n");
-
-       istallion_class = class_create(THIS_MODULE, "staliomem");
-       for (i = 0; i < 4; i++)
-               class_device_create(istallion_class, NULL,
-                               MKDEV(STL_SIOMEMMAJOR, i),
-                               NULL, "staliomem%d", i);
+       stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+       if (!stli_serial) {
+               retval = -ENOMEM;
+               goto err_free;
+       }
 
-/*
- *     Set up the tty driver structure and register us as a driver.
- */
        stli_serial->owner = THIS_MODULE;
        stli_serial->driver_name = stli_drvname;
        stli_serial->name = stli_serialname;
@@ -4709,15 +4607,79 @@ static int __init stli_init(void)
        stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
        stli_serial->subtype = SERIAL_TYPE_NORMAL;
        stli_serial->init_termios = stli_deftermios;
-       stli_serial->flags = TTY_DRIVER_REAL_RAW;
+       stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        tty_set_operations(stli_serial, &stli_ops);
 
-       if (tty_register_driver(stli_serial)) {
-               put_tty_driver(stli_serial);
+       retval = tty_register_driver(stli_serial);
+       if (retval) {
                printk(KERN_ERR "STALLION: failed to register serial driver\n");
-               return -EBUSY;
+               goto err_ttyput;
        }
+
+       retval = stli_initbrds();
+       if (retval)
+               goto err_ttyunr;
+
+/*
+ *     Set up a character driver for the shared memory region. We need this
+ *     to down load the slave code image. Also it is a useful debugging tool.
+ */
+       retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
+       if (retval) {
+               printk(KERN_ERR "STALLION: failed to register serial memory "
+                               "device\n");
+               goto err_deinit;
+       }
+
+       istallion_class = class_create(THIS_MODULE, "staliomem");
+       for (i = 0; i < 4; i++)
+               class_device_create(istallion_class, NULL,
+                               MKDEV(STL_SIOMEMMAJOR, i),
+                               NULL, "staliomem%d", i);
+
        return 0;
+err_deinit:
+       pci_unregister_driver(&stli_pcidriver);
+       istallion_cleanup_isa();
+err_ttyunr:
+       tty_unregister_driver(stli_serial);
+err_ttyput:
+       put_tty_driver(stli_serial);
+err_free:
+       kfree(stli_txcookbuf);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
+
+static void __exit istallion_module_exit(void)
+{
+       unsigned int j;
+
+       printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
+               stli_drvversion);
+
+       if (stli_timeron) {
+               stli_timeron = 0;
+               del_timer_sync(&stli_timerlist);
+       }
+
+       unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+
+       for (j = 0; j < 4; j++)
+               class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR,
+                                       j));
+       class_destroy(istallion_class);
+
+       pci_unregister_driver(&stli_pcidriver);
+       istallion_cleanup_isa();
+
+       tty_unregister_driver(stli_serial);
+       put_tty_driver(stli_serial);
+
+       kfree(stli_txcookbuf);
+}
+
+module_init(istallion_module_init);
+module_exit(istallion_module_exit);
index 20b6c8b..7a6c1c0 100644 (file)
@@ -710,7 +710,7 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
 
 static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
 {
-       static const char *cur_chars = "BDCA";
+       static const char cur_chars[] = "BDCA";
 
        if (up_flag)
                return;
index 1ecea7d..b70b538 100644 (file)
@@ -296,7 +296,7 @@ static int lp_wait_ready(int minor, int nonblock)
 static ssize_t lp_write(struct file * file, const char __user * buf,
                        size_t count, loff_t *ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        struct parport *port = lp_table[minor].dev->port;
        char *kbuf = lp_table[minor].lp_buffer;
        ssize_t retv = 0;
@@ -415,7 +415,7 @@ static ssize_t lp_read(struct file * file, char __user * buf,
                       size_t count, loff_t *ppos)
 {
        DEFINE_WAIT(wait);
-       unsigned int minor=iminor(file->f_dentry->d_inode);
+       unsigned int minor=iminor(file->f_path.dentry->d_inode);
        struct parport *port = lp_table[minor].dev->port;
        ssize_t retval = 0;
        char *kbuf = lp_table[minor].lp_buffer;
index e67eef4..4f1813e 100644 (file)
@@ -646,7 +646,8 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size)
                        count = size;
 
                zap_page_range(vma, addr, count, NULL);
-               zeromap_page_range(vma, addr, count, PAGE_COPY);
+               if (zeromap_page_range(vma, addr, count, PAGE_COPY))
+                       break;
 
                size -= count;
                buf += count;
@@ -713,11 +714,14 @@ out:
 
 static int mmap_zero(struct file * file, struct vm_area_struct * vma)
 {
+       int err;
+
        if (vma->vm_flags & VM_SHARED)
                return shmem_zero_setup(vma);
-       if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
+       err = zeromap_page_range(vma, vma->vm_start,
+                       vma->vm_end - vma->vm_start, vma->vm_page_prot);
+       BUG_ON(err == -EEXIST);
+       return err;
 }
 #else /* CONFIG_MMU */
 static ssize_t read_zero(struct file * file, char * buf, 
@@ -774,7 +778,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
 {
        loff_t ret;
 
-       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+       mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
        switch (orig) {
                case 0:
                        file->f_pos = offset;
@@ -789,7 +793,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
                default:
                        ret = -EINVAL;
        }
-       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
        return ret;
 }
 
index 7a484fc..7e975f6 100644 (file)
@@ -199,6 +199,8 @@ int misc_register(struct miscdevice * misc)
        dev_t dev;
        int err = 0;
 
+       INIT_LIST_HEAD(&misc->list);
+
        down(&misc_sem);
        list_for_each_entry(c, &misc_list, list) {
                if (c->minor == misc->minor) {
index 22b9905..c091603 100644 (file)
@@ -680,7 +680,7 @@ static int __init mmtimer_init(void)
        if (sn_rtc_cycles_per_second < 100000) {
                printk(KERN_ERR "%s: unable to determine clock frequency\n",
                       MMTIMER_NAME);
-               return -1;
+               goto out1;
        }
 
        mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
@@ -689,13 +689,13 @@ static int __init mmtimer_init(void)
        if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) {
                printk(KERN_WARNING "%s: unable to allocate interrupt.",
                        MMTIMER_NAME);
-               return -1;
+               goto out1;
        }
 
        if (misc_register(&mmtimer_miscdev)) {
                printk(KERN_ERR "%s: failed to register device\n",
                       MMTIMER_NAME);
-               return -1;
+               goto out2;
        }
 
        /* Get max numbered node, calculate slots needed */
@@ -709,16 +709,18 @@ static int __init mmtimer_init(void)
        if (timers == NULL) {
                printk(KERN_ERR "%s: failed to allocate memory for device\n",
                                MMTIMER_NAME);
-               return -1;
+               goto out3;
        }
 
+       memset(timers,0,(sizeof(mmtimer_t *)*maxn));
+
        /* Allocate mmtimer_t's for each online node */
        for_each_online_node(node) {
                timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
                if (timers[node] == NULL) {
                        printk(KERN_ERR "%s: failed to allocate memory for device\n",
                                MMTIMER_NAME);
-                       return -1;
+                       goto out4;
                }
                for (i=0; i< NUM_COMPARATORS; i++) {
                        mmtimer_t * base = timers[node] + i;
@@ -739,6 +741,17 @@ static int __init mmtimer_init(void)
               sn_rtc_cycles_per_second/(unsigned long)1E6);
 
        return 0;
+
+out4:
+       for_each_online_node(node) {
+               kfree(timers[node]);
+       }
+out3:
+       misc_deregister(&mmtimer_miscdev);
+out2:
+       free_irq(SGI_MMTIMER_VECTOR, NULL);
+out1:
+       return -1;
 }
 
 module_init(mmtimer_init);
index 96cb1f0..f391a24 100644 (file)
@@ -222,7 +222,7 @@ static struct semaphore moxaBuffSem;
 /*
  * static functions:
  */
-static void do_moxa_softint(void *);
+static void do_moxa_softint(struct work_struct *);
 static int moxa_open(struct tty_struct *, struct file *);
 static void moxa_close(struct tty_struct *, struct file *);
 static int moxa_write(struct tty_struct *, const unsigned char *, int);
@@ -234,7 +234,7 @@ static void moxa_put_char(struct tty_struct *, unsigned char);
 static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
 static void moxa_throttle(struct tty_struct *);
 static void moxa_unthrottle(struct tty_struct *);
-static void moxa_set_termios(struct tty_struct *, struct termios *);
+static void moxa_set_termios(struct tty_struct *, struct ktermios *);
 static void moxa_stop(struct tty_struct *);
 static void moxa_start(struct tty_struct *);
 static void moxa_hangup(struct tty_struct *);
@@ -261,7 +261,7 @@ static void MoxaPortEnable(int);
 static void MoxaPortDisable(int);
 static long MoxaPortGetMaxBaud(int);
 static long MoxaPortSetBaud(int, long);
-static int MoxaPortSetTermio(int, struct termios *, speed_t);
+static int MoxaPortSetTermio(int, struct ktermios *, speed_t);
 static int MoxaPortGetLineOut(int, int *, int *);
 static void MoxaPortLineCtrl(int, int, int);
 static void MoxaPortFlowCtrl(int, int, int, int, int, int);
@@ -355,6 +355,8 @@ static int __init moxa_init(void)
        moxaDriver->init_termios.c_oflag = 0;
        moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
        moxaDriver->init_termios.c_lflag = 0;
+       moxaDriver->init_termios.c_ispeed = 9600;
+       moxaDriver->init_termios.c_ospeed = 9600;
        moxaDriver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(moxaDriver, &moxa_ops);
 
@@ -363,7 +365,7 @@ static int __init moxa_init(void)
        for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
                ch->type = PORT_16550A;
                ch->port = i;
-               INIT_WORK(&ch->tqueue, do_moxa_softint, ch);
+               INIT_WORK(&ch->tqueue, do_moxa_softint);
                ch->tty = NULL;
                ch->close_delay = 5 * HZ / 10;
                ch->closing_wait = 30 * HZ;
@@ -498,9 +500,12 @@ static void __exit moxa_exit(void)
                printk("Couldn't unregister MOXA Intellio family serial driver\n");
        put_tty_driver(moxaDriver);
 
-       for (i = 0; i < MAX_BOARDS; i++)
+       for (i = 0; i < MAX_BOARDS; i++) {
+               if (moxaBaseAddr[i])
+                       iounmap(moxaBaseAddr[i]);
                if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI)
                        pci_dev_put(moxa_boards[i].pciInfo.pdev);
+       }
 
        if (verbose)
                printk("Done\n");
@@ -509,9 +514,9 @@ static void __exit moxa_exit(void)
 module_init(moxa_init);
 module_exit(moxa_exit);
 
-static void do_moxa_softint(void *private_)
+static void do_moxa_softint(struct work_struct *work)
 {
-       struct moxa_str *ch = (struct moxa_str *) private_;
+       struct moxa_str *ch = container_of(work, struct moxa_str, tqueue);
        struct tty_struct *tty;
 
        if (ch && (tty = ch->tty)) {
@@ -861,7 +866,7 @@ static void moxa_unthrottle(struct tty_struct *tty)
 }
 
 static void moxa_set_termios(struct tty_struct *tty,
-                            struct termios *old_termios)
+                            struct ktermios *old_termios)
 {
        struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
 
@@ -975,7 +980,7 @@ static void moxa_poll(unsigned long ignored)
 
 static void set_tty_param(struct tty_struct *tty)
 {
-       register struct termios *ts;
+       register struct ktermios *ts;
        struct moxa_str *ch;
        int rts, cts, txflow, rxflow, xany;
 
@@ -1146,7 +1151,7 @@ static void shut_down(struct moxa_str *ch)
 static void receive_data(struct moxa_str *ch)
 {
        struct tty_struct *tp;
-       struct termios *ts;
+       struct ktermios *ts;
        unsigned long flags;
 
        ts = NULL;
@@ -1909,9 +1914,9 @@ int MoxaPortsOfCard(int cardno)
  *
  *      Function 12:    Configure the port.
  *      Syntax:
- *      int  MoxaPortSetTermio(int port, struct termios *termio, speed_t baud);
+ *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
  *           int port           : port number (0 - 127)
- *           struct termios * termio : termio structure pointer
+ *           struct ktermios * termio : termio structure pointer
  *          speed_t baud       : baud rate
  *
  *           return:    -1      : this port is invalid or termio == NULL
@@ -2192,7 +2197,7 @@ long MoxaPortSetBaud(int port, long baud)
        return (baud);
 }
 
-int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud)
+int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
 {
        void __iomem *ofsAddr;
        tcflag_t cflag;
index 048d911..c063359 100644 (file)
@@ -328,8 +328,8 @@ struct mxser_struct {
        int xmit_tail;
        int xmit_cnt;
        struct work_struct tqueue;
-       struct termios normal_termios;
-       struct termios callout_termios;
+       struct ktermios normal_termios;
+       struct ktermios callout_termios;
        wait_queue_head_t open_wait;
        wait_queue_head_t close_wait;
        wait_queue_head_t delta_msr_wait;
@@ -364,8 +364,8 @@ static int mxserBoardCAP[MXSER_BOARDS] = {
 static struct tty_driver *mxvar_sdriver;
 static struct mxser_struct mxvar_table[MXSER_PORTS];
 static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
-static struct termios *mxvar_termios[MXSER_PORTS + 1];
-static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
+static struct ktermios *mxvar_termios[MXSER_PORTS + 1];
+static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1];
 static struct mxser_log mxvar_log;
 static int mxvar_diagflag;
 static unsigned char mxser_msr[MXSER_PORTS + 1];
@@ -389,7 +389,7 @@ static int mxser_init(void);
 /* static void   mxser_poll(unsigned long); */
 static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
 static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *);
-static void mxser_do_softint(void *);
+static void mxser_do_softint(struct work_struct *);
 static int mxser_open(struct tty_struct *, struct file *);
 static void mxser_close(struct tty_struct *, struct file *);
 static int mxser_write(struct tty_struct *, const unsigned char *, int);
@@ -402,7 +402,7 @@ static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
 static int mxser_ioctl_special(unsigned int, void __user *);
 static void mxser_throttle(struct tty_struct *);
 static void mxser_unthrottle(struct tty_struct *);
-static void mxser_set_termios(struct tty_struct *, struct termios *);
+static void mxser_set_termios(struct tty_struct *, struct ktermios *);
 static void mxser_stop(struct tty_struct *);
 static void mxser_start(struct tty_struct *);
 static void mxser_hangup(struct tty_struct *);
@@ -414,7 +414,7 @@ static void mxser_check_modem_status(struct mxser_struct *, int);
 static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
 static int mxser_startup(struct mxser_struct *);
 static void mxser_shutdown(struct mxser_struct *);
-static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
+static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios);
 static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *);
 static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *);
 static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *);
@@ -515,6 +515,7 @@ static void __exit mxser_module_exit(void)
                        if (pdev != NULL) {     /* PCI */
                                release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
                                release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
+                               pci_dev_put(pdev);
                        } else {
                                release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports);
                                release_region(mxsercfg[i].vector, 1);
@@ -556,7 +557,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
        n = board * MXSER_PORTS_PER_BOARD;
        info = &mxvar_table[n];
        /*if (verbose) */  {
-               printk(KERN_DEBUG "        ttyM%d - ttyM%d ",
+               printk(KERN_DEBUG "        ttyMI%d - ttyMI%d ",
                        n, n + hwconf->ports - 1);
                printk(" max. baud rate = %d bps.\n",
                        hwconf->MaxCanSetBaudRate[0]);
@@ -590,7 +591,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
                info->custom_divisor = hwconf->baud_base[i] * 16;
                info->close_delay = 5 * HZ / 10;
                info->closing_wait = 30 * HZ;
-               INIT_WORK(&info->tqueue, mxser_do_softint, info);
+               INIT_WORK(&info->tqueue, mxser_do_softint);
                info->normal_termios = mxvar_sdriver->init_termios;
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
@@ -717,7 +718,7 @@ static int mxser_init(void)
        /* Initialize the tty_driver structure */
        memset(mxvar_sdriver, 0, sizeof(struct tty_driver));
        mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
-       mxvar_sdriver->name = "ttyM";
+       mxvar_sdriver->name = "ttyMI";
        mxvar_sdriver->major = ttymajor;
        mxvar_sdriver->minor_start = 0;
        mxvar_sdriver->num = MXSER_PORTS + 1;
@@ -725,6 +726,8 @@ static int mxser_init(void)
        mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
        mxvar_sdriver->init_termios = tty_std_termios;
        mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+       mxvar_sdriver->init_termios.c_ispeed = 9600;
+       mxvar_sdriver->init_termios.c_ospeed = 9600;
        mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(mxvar_sdriver, &mxser_ops);
        mxvar_sdriver->ttys = mxvar_tty;
@@ -839,9 +842,9 @@ static int mxser_init(void)
        index = 0;
        b = 0;
        while (b < n) {
-               pdev = pci_find_device(mxser_pcibrds[b].vendor,
+               pdev = pci_get_device(mxser_pcibrds[b].vendor,
                                mxser_pcibrds[b].device, pdev);
-                       if (pdev == NULL) {
+               if (pdev == NULL) {
                        b++;
                        continue;
                }
@@ -893,6 +896,9 @@ static int mxser_init(void)
                        if (mxser_initbrd(m, &hwconf) < 0)
                                continue;
                        m++;
+                       /* Keep an extra reference if we succeeded. It will
+                          be returned at unload time */
+                       pci_dev_get(pdev);
                }
        }
 #endif
@@ -917,9 +923,10 @@ static int mxser_init(void)
        return 0;
 }
 
-static void mxser_do_softint(void *private_)
+static void mxser_do_softint(struct work_struct *work)
 {
-       struct mxser_struct *info = private_;
+       struct mxser_struct *info =
+               container_of(work, struct mxser_struct, tqueue);
        struct tty_struct *tty;
 
        tty = info->tty;
@@ -993,7 +1000,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
                mxser_change_speed(info, NULL);
        }
 
-       info->session = current->signal->session;
+       info->session = process_session(current);
        info->pgrp = process_group(current);
 
        /*
@@ -1744,7 +1751,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
        /* MX_UNLOCK(&info->slock); */
 }
 
-static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct mxser_struct *info = tty->driver_data;
        unsigned long flags;
@@ -2536,7 +2543,7 @@ static void mxser_shutdown(struct mxser_struct *info)
  * This routine is called to set the UART divisor registers to match
  * the specified baud rate for a serial port.
  */
-static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios)
+static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios)
 {
        unsigned cflag, cval, fcr;
        int ret = 0;
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
new file mode 100644 (file)
index 0000000..efa8076
--- /dev/null
@@ -0,0 +1,2804 @@
+/*
+ *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
+ *
+ *      Copyright (C) 1999-2006  Moxa Technologies (support@moxa.com.tw).
+ *     Copyright (C) 2006       Jiri Slaby <jirislaby@gmail.com>
+ *
+ *      This code is loosely based on the 1.8 moxa driver which is based on
+ *     Linux serial driver, written by Linus Torvalds, Theodore T'so and
+ *     others.
+ *
+ *      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.
+ *
+ *     Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
+ *     <alan@redhat.com>. The original 1.8 code is available on www.moxa.com.
+ *     - Fixed x86_64 cleanness
+ *     - Fixed sleep with spinlock held in mxser_send_break
+ */
+
+#include <linux/module.h>
+#include <linux/autoconf.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/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/gfp.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#include "mxser_new.h"
+
+#define        MXSER_VERSION   "2.0"
+#define        MXSERMAJOR       174
+#define        MXSERCUMAJOR     175
+
+#define        MXSER_EVENT_TXLOW       1
+
+#define MXSER_BOARDS           4       /* Max. boards */
+#define MXSER_PORTS_PER_BOARD  8       /* Max. ports per board */
+#define MXSER_PORTS            (MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
+#define MXSER_ISR_PASS_LIMIT   99999L
+
+#define        MXSER_ERR_IOADDR        -1
+#define        MXSER_ERR_IRQ           -2
+#define        MXSER_ERR_IRQ_CONFLIT   -3
+#define        MXSER_ERR_VECTOR        -4
+
+#define WAKEUP_CHARS           256
+
+#define UART_MCR_AFE           0x20
+#define UART_LSR_SPECIAL       0x1E
+
+#define RELEVANT_IFLAG(iflag)  (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
+                                         IXON|IXOFF))
+
+#define C168_ASIC_ID    1
+#define C104_ASIC_ID    2
+#define C102_ASIC_ID   0xB
+#define CI132_ASIC_ID  4
+#define CI134_ASIC_ID  3
+#define CI104J_ASIC_ID  5
+
+#define MXSER_HIGHBAUD 1
+#define MXSER_HAS2     2
+
+/* This is only for PCI */
+static const struct {
+       int type;
+       int tx_fifo;
+       int rx_fifo;
+       int xmit_fifo_size;
+       int rx_high_water;
+       int rx_trigger;
+       int rx_low_water;
+       long max_baud;
+} Gpci_uart_info[] = {
+       {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
+       {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
+       {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
+};
+#define UART_INFO_NUM  ARRAY_SIZE(Gpci_uart_info)
+
+struct mxser_cardinfo {
+       unsigned int nports;
+       char *name;
+       unsigned int flags;
+};
+
+static const struct mxser_cardinfo mxser_cards[] = {
+       { 8, "C168 series", },                  /* C168-ISA */
+       { 4, "C104 series", },                  /* C104-ISA */
+       { 4, "CI-104J series", },               /* CI104J */
+       { 8, "C168H/PCI series", },             /* C168-PCI */
+       { 4, "C104H/PCI series", },             /* C104-PCI */
+       { 4, "C102 series", MXSER_HAS2 },       /* C102-ISA */
+       { 4, "CI-132 series", MXSER_HAS2 },     /* CI132 */
+       { 4, "CI-134 series", },                /* CI134 */
+       { 2, "CP-132 series", },                /* CP132 */
+       { 4, "CP-114 series", },                /* CP114 */
+       { 4, "CT-114 series", },                /* CT114 */
+       { 2, "CP-102 series", MXSER_HIGHBAUD }, /* CP102 */
+       { 4, "CP-104U series", },               /* CP104U */
+       { 8, "CP-168U series", },               /* CP168U */
+       { 2, "CP-132U series", },               /* CP132U */
+       { 4, "CP-134U series", },               /* CP134U */
+       { 4, "CP-104JU series", },              /* CP104JU */
+       { 8, "Moxa UC7000 Serial", },           /* RC7000 */
+       { 8, "CP-118U series", },               /* CP118U */
+       { 2, "CP-102UL series", },              /* CP102UL */
+       { 2, "CP-102U series", },               /* CP102U */
+       { 8, "CP-118EL series", },              /* CP118EL */
+       { 8, "CP-168EL series", },              /* CP168EL */
+       { 4, "CP-104EL series", }               /* CP104EL */
+};
+
+/* driver_data correspond to the lines in the structure above
+   see also ISA probe function before you change something */
+static struct pci_device_id mxser_pcibrds[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168),
+               .driver_data = 3 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104),
+               .driver_data = 4 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132),
+               .driver_data = 8 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114),
+               .driver_data = 9 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114),
+               .driver_data = 10 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102),
+               .driver_data = 11 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U),
+               .driver_data = 12 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U),
+               .driver_data = 13 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U),
+               .driver_data = 14 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U),
+               .driver_data = 15 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU),
+               .driver_data = 16 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000),
+               .driver_data = 17 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U),
+               .driver_data = 18 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
+               .driver_data = 19 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U),
+               .driver_data = 20 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL),
+               .driver_data = 21 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL),
+               .driver_data = 22 },
+       { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL),
+               .driver_data = 23 },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
+
+static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
+static int ttymajor = MXSERMAJOR;
+static int calloutmajor = MXSERCUMAJOR;
+
+/* Variables for insmod */
+
+MODULE_AUTHOR("Casper Yang");
+MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
+module_param_array(ioaddr, int, NULL, 0);
+module_param(ttymajor, int, 0);
+MODULE_LICENSE("GPL");
+
+struct mxser_log {
+       int tick;
+       unsigned long rxcnt[MXSER_PORTS];
+       unsigned long txcnt[MXSER_PORTS];
+};
+
+
+struct mxser_mon {
+       unsigned long rxcnt;
+       unsigned long txcnt;
+       unsigned long up_rxcnt;
+       unsigned long up_txcnt;
+       int modem_status;
+       unsigned char hold_reason;
+};
+
+struct mxser_mon_ext {
+       unsigned long rx_cnt[32];
+       unsigned long tx_cnt[32];
+       unsigned long up_rxcnt[32];
+       unsigned long up_txcnt[32];
+       int modem_status[32];
+
+       long baudrate[32];
+       int databits[32];
+       int stopbits[32];
+       int parity[32];
+       int flowctrl[32];
+       int fifo[32];
+       int iftype[32];
+};
+
+struct mxser_board;
+
+struct mxser_port {
+       struct mxser_board *board;
+       struct tty_struct *tty;
+
+       unsigned long ioaddr;
+       unsigned long opmode_ioaddr;
+       int max_baud;
+
+       int rx_high_water;
+       int rx_trigger;         /* Rx fifo trigger level */
+       int rx_low_water;
+       int baud_base;          /* max. speed */
+       long realbaud;
+       int type;               /* UART type */
+       int flags;              /* defined in tty.h */
+       long session;           /* Session of opening process */
+       long pgrp;              /* pgrp of opening process */
+
+       int x_char;             /* xon/xoff character */
+       int IER;                /* Interrupt Enable Register */
+       int MCR;                /* Modem control register */
+
+       unsigned char stop_rx;
+       unsigned char ldisc_stop_rx;
+
+       int custom_divisor;
+       int close_delay;
+       unsigned short closing_wait;
+       unsigned char err_shadow;
+       unsigned long event;
+
+       int count;              /* # of fd on device */
+       int blocked_open;       /* # of blocked opens */
+       struct async_icount icount; /* kernel counters for 4 input interrupts */
+       int timeout;
+
+       int read_status_mask;
+       int ignore_status_mask;
+       int xmit_fifo_size;
+       unsigned char *xmit_buf;
+       int xmit_head;
+       int xmit_tail;
+       int xmit_cnt;
+
+       struct ktermios normal_termios;
+       struct ktermios callout_termios;
+
+       struct mxser_mon mon_data;
+
+       spinlock_t slock;
+       struct work_struct tqueue;
+       wait_queue_head_t open_wait;
+       wait_queue_head_t close_wait;
+       wait_queue_head_t delta_msr_wait;
+};
+
+struct mxser_board {
+       unsigned int idx;
+       int irq;
+       const struct mxser_cardinfo *info;
+       unsigned long vector;
+       unsigned long vector_mask;
+
+       int chip_flag;
+       int uart_type;
+
+       struct mxser_port ports[MXSER_PORTS_PER_BOARD];
+};
+
+struct mxser_mstatus {
+       tcflag_t cflag;
+       int cts;
+       int dsr;
+       int ri;
+       int dcd;
+};
+
+static struct mxser_mstatus GMStatus[MXSER_PORTS];
+
+static int mxserBoardCAP[MXSER_BOARDS] = {
+       0, 0, 0, 0
+       /*  0x180, 0x280, 0x200, 0x320 */
+};
+
+static struct mxser_board mxser_boards[MXSER_BOARDS];
+static struct tty_driver *mxvar_sdriver;
+static struct mxser_log mxvar_log;
+static int mxvar_diagflag;
+static unsigned char mxser_msr[MXSER_PORTS + 1];
+static struct mxser_mon_ext mon_data_ext;
+static int mxser_set_baud_method[MXSER_PORTS + 1];
+static spinlock_t gm_lock;
+
+static int CheckIsMoxaMust(int io)
+{
+       u8 oldmcr, hwid;
+       int i;
+
+       outb(0, io + UART_LCR);
+       DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
+       oldmcr = inb(io + UART_MCR);
+       outb(0, io + UART_MCR);
+       SET_MOXA_MUST_XON1_VALUE(io, 0x11);
+       if ((hwid = inb(io + UART_MCR)) != 0) {
+               outb(oldmcr, io + UART_MCR);
+               return MOXA_OTHER_UART;
+       }
+
+       GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
+       for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
+               if (hwid == Gpci_uart_info[i].type)
+                       return (int)hwid;
+       }
+       return MOXA_OTHER_UART;
+}
+
+static void process_txrx_fifo(struct mxser_port *info)
+{
+       int i;
+
+       if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
+               info->rx_trigger = 1;
+               info->rx_high_water = 1;
+               info->rx_low_water = 1;
+               info->xmit_fifo_size = 1;
+       } else
+               for (i = 0; i < UART_INFO_NUM; i++)
+                       if (info->board->chip_flag == Gpci_uart_info[i].type) {
+                               info->rx_trigger = Gpci_uart_info[i].rx_trigger;
+                               info->rx_low_water = Gpci_uart_info[i].rx_low_water;
+                               info->rx_high_water = Gpci_uart_info[i].rx_high_water;
+                               info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
+                               break;
+                       }
+}
+
+static void mxser_do_softint(struct work_struct *work)
+{
+       struct mxser_port *info = container_of(work, struct mxser_port, tqueue);
+       struct tty_struct *tty = info->tty;
+
+       if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event))
+               tty_wakeup(tty);
+}
+
+static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
+{
+       unsigned char status = 0;
+
+       status = inb(baseaddr + UART_MSR);
+
+       mxser_msr[port] &= 0x0F;
+       mxser_msr[port] |= status;
+       status = mxser_msr[port];
+       if (mode)
+               mxser_msr[port] = 0;
+
+       return status;
+}
+
+static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
+               struct mxser_port *port)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       int retval;
+       int do_clocal = 0;
+       unsigned long flags;
+
+       /*
+        * If non-blocking mode is set, or the port is not enabled,
+        * then make the check up front and then exit.
+        */
+       if ((filp->f_flags & O_NONBLOCK) ||
+                       test_bit(TTY_IO_ERROR, &tty->flags)) {
+               port->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;
+       }
+
+       if (tty->termios->c_cflag & CLOCAL)
+               do_clocal = 1;
+
+       /*
+        * Block waiting for the carrier detect and the line to become
+        * free (i.e., not in use by the callout).  While we are in
+        * this loop, port->count is dropped by one, so that
+        * mxser_close() knows when to free things.  We restore it upon
+        * exit, either normal or abnormal.
+        */
+       retval = 0;
+       add_wait_queue(&port->open_wait, &wait);
+
+       spin_lock_irqsave(&port->slock, flags);
+       if (!tty_hung_up_p(filp))
+               port->count--;
+       spin_unlock_irqrestore(&port->slock, flags);
+       port->blocked_open++;
+       while (1) {
+               spin_lock_irqsave(&port->slock, flags);
+               outb(inb(port->ioaddr + UART_MCR) |
+                       UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
+               spin_unlock_irqrestore(&port->slock, flags);
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+                       if (port->flags & ASYNC_HUP_NOTIFY)
+                               retval = -EAGAIN;
+                       else
+                               retval = -ERESTARTSYS;
+                       break;
+               }
+               if (!(port->flags & ASYNC_CLOSING) &&
+                               (do_clocal ||
+                               (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
+                       break;
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       break;
+               }
+               schedule();
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&port->open_wait, &wait);
+       if (!tty_hung_up_p(filp))
+               port->count++;
+       port->blocked_open--;
+       if (retval)
+               return retval;
+       port->flags |= ASYNC_NORMAL_ACTIVE;
+       return 0;
+}
+
+static int mxser_set_baud(struct mxser_port *info, long newspd)
+{
+       int quot = 0;
+       unsigned char cval;
+       int ret = 0;
+       unsigned long flags;
+
+       if (!info->tty || !info->tty->termios)
+               return ret;
+
+       if (!(info->ioaddr))
+               return ret;
+
+       if (newspd > info->max_baud)
+               return 0;
+
+       info->realbaud = newspd;
+       if (newspd == 134) {
+               quot = (2 * info->baud_base / 269);
+       } else if (newspd) {
+               quot = info->baud_base / newspd;
+               if (quot == 0)
+                       quot = 1;
+       } else {
+               quot = 0;
+       }
+
+       info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
+       info->timeout += HZ / 50;       /* Add .02 seconds of slop */
+
+       if (quot) {
+               spin_lock_irqsave(&info->slock, flags);
+               info->MCR |= UART_MCR_DTR;
+               outb(info->MCR, info->ioaddr + UART_MCR);
+               spin_unlock_irqrestore(&info->slock, flags);
+       } else {
+               spin_lock_irqsave(&info->slock, flags);
+               info->MCR &= ~UART_MCR_DTR;
+               outb(info->MCR, info->ioaddr + UART_MCR);
+               spin_unlock_irqrestore(&info->slock, flags);
+               return ret;
+       }
+
+       cval = inb(info->ioaddr + UART_LCR);
+
+       outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR);    /* set DLAB */
+
+       outb(quot & 0xff, info->ioaddr + UART_DLL);     /* LS of divisor */
+       outb(quot >> 8, info->ioaddr + UART_DLM);       /* MS of divisor */
+       outb(cval, info->ioaddr + UART_LCR);    /* reset DLAB */
+
+
+       return ret;
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static int mxser_change_speed(struct mxser_port *info,
+               struct ktermios *old_termios)
+{
+       unsigned cflag, cval, fcr;
+       int ret = 0;
+       unsigned char status;
+       long baud;
+       unsigned long flags;
+
+       if (!info->tty || !info->tty->termios)
+               return ret;
+       cflag = info->tty->termios->c_cflag;
+       if (!(info->ioaddr))
+               return ret;
+
+       if (mxser_set_baud_method[info->tty->index] == 0) {
+               baud = tty_get_baud_rate(info->tty);
+               mxser_set_baud(info, baud);
+       }
+
+       /* byte size and parity */
+       switch (cflag & CSIZE) {
+       case CS5:
+               cval = 0x00;
+               break;
+       case CS6:
+               cval = 0x01;
+               break;
+       case CS7:
+               cval = 0x02;
+               break;
+       case CS8:
+               cval = 0x03;
+               break;
+       default:
+               cval = 0x00;
+               break;          /* too keep GCC shut... */
+       }
+       if (cflag & CSTOPB)
+               cval |= 0x04;
+       if (cflag & PARENB)
+               cval |= UART_LCR_PARITY;
+       if (!(cflag & PARODD))
+               cval |= UART_LCR_EPAR;
+       if (cflag & CMSPAR)
+               cval |= UART_LCR_SPAR;
+
+       if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
+               if (info->board->chip_flag) {
+                       fcr = UART_FCR_ENABLE_FIFO;
+                       fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+                       SET_MOXA_MUST_FIFO_VALUE(info);
+               } else
+                       fcr = 0;
+       } else {
+               fcr = UART_FCR_ENABLE_FIFO;
+               if (info->board->chip_flag) {
+                       fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+                       SET_MOXA_MUST_FIFO_VALUE(info);
+               } else {
+                       switch (info->rx_trigger) {
+                       case 1:
+                               fcr |= UART_FCR_TRIGGER_1;
+                               break;
+                       case 4:
+                               fcr |= UART_FCR_TRIGGER_4;
+                               break;
+                       case 8:
+                               fcr |= UART_FCR_TRIGGER_8;
+                               break;
+                       default:
+                               fcr |= UART_FCR_TRIGGER_14;
+                               break;
+                       }
+               }
+       }
+
+       /* CTS flow control flag and modem status interrupts */
+       info->IER &= ~UART_IER_MSI;
+       info->MCR &= ~UART_MCR_AFE;
+       if (cflag & CRTSCTS) {
+               info->flags |= ASYNC_CTS_FLOW;
+               info->IER |= UART_IER_MSI;
+               if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
+                       info->MCR |= UART_MCR_AFE;
+               } else {
+                       status = inb(info->ioaddr + UART_MSR);
+                       if (info->tty->hw_stopped) {
+                               if (status & UART_MSR_CTS) {
+                                       info->tty->hw_stopped = 0;
+                                       if (info->type != PORT_16550A &&
+                                                       !info->board->chip_flag) {
+                                               outb(info->IER & ~UART_IER_THRI,
+                                                       info->ioaddr +
+                                                       UART_IER);
+                                               info->IER |= UART_IER_THRI;
+                                               outb(info->IER, info->ioaddr +
+                                                               UART_IER);
+                                       }
+                                       set_bit(MXSER_EVENT_TXLOW, &info->event);
+                                       schedule_work(&info->tqueue);                           }
+                       } else {
+                               if (!(status & UART_MSR_CTS)) {
+                                       info->tty->hw_stopped = 1;
+                                       if ((info->type != PORT_16550A) &&
+                                                       (!info->board->chip_flag)) {
+                                               info->IER &= ~UART_IER_THRI;
+                                               outb(info->IER, info->ioaddr +
+                                                               UART_IER);
+                                       }
+                               }
+                       }
+               }
+       } else {
+               info->flags &= ~ASYNC_CTS_FLOW;
+       }
+       outb(info->MCR, info->ioaddr + UART_MCR);
+       if (cflag & CLOCAL) {
+               info->flags &= ~ASYNC_CHECK_CD;
+       } else {
+               info->flags |= ASYNC_CHECK_CD;
+               info->IER |= UART_IER_MSI;
+       }
+       outb(info->IER, info->ioaddr + UART_IER);
+
+       /*
+        * Set up parity check flag
+        */
+       info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+       if (I_INPCK(info->tty))
+               info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+       if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+               info->read_status_mask |= UART_LSR_BI;
+
+       info->ignore_status_mask = 0;
+
+       if (I_IGNBRK(info->tty)) {
+               info->ignore_status_mask |= UART_LSR_BI;
+               info->read_status_mask |= UART_LSR_BI;
+               /*
+                * If we're ignore parity and break indicators, ignore
+                * overruns too.  (For real raw support).
+                */
+               if (I_IGNPAR(info->tty)) {
+                       info->ignore_status_mask |=
+                                               UART_LSR_OE |
+                                               UART_LSR_PE |
+                                               UART_LSR_FE;
+                       info->read_status_mask |=
+                                               UART_LSR_OE |
+                                               UART_LSR_PE |
+                                               UART_LSR_FE;
+               }
+       }
+       if (info->board->chip_flag) {
+               spin_lock_irqsave(&info->slock, flags);
+               SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
+               SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
+               if (I_IXON(info->tty)) {
+                       ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+               } else {
+                       DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+               }
+               if (I_IXOFF(info->tty)) {
+                       ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+               } else {
+                       DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+               }
+               spin_unlock_irqrestore(&info->slock, flags);
+       }
+
+
+       outb(fcr, info->ioaddr + UART_FCR);     /* set fcr */
+       outb(cval, info->ioaddr + UART_LCR);
+
+       return ret;
+}
+
+static void mxser_check_modem_status(struct mxser_port *port, int status)
+{
+       /* update input line counters */
+       if (status & UART_MSR_TERI)
+               port->icount.rng++;
+       if (status & UART_MSR_DDSR)
+               port->icount.dsr++;
+       if (status & UART_MSR_DDCD)
+               port->icount.dcd++;
+       if (status & UART_MSR_DCTS)
+               port->icount.cts++;
+       port->mon_data.modem_status = status;
+       wake_up_interruptible(&port->delta_msr_wait);
+
+       if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+               if (status & UART_MSR_DCD)
+                       wake_up_interruptible(&port->open_wait);
+               schedule_work(&port->tqueue);
+       }
+
+       if (port->flags & ASYNC_CTS_FLOW) {
+               if (port->tty->hw_stopped) {
+                       if (status & UART_MSR_CTS) {
+                               port->tty->hw_stopped = 0;
+
+                               if ((port->type != PORT_16550A) &&
+                                               (!port->board->chip_flag)) {
+                                       outb(port->IER & ~UART_IER_THRI,
+                                               port->ioaddr + UART_IER);
+                                       port->IER |= UART_IER_THRI;
+                                       outb(port->IER, port->ioaddr +
+                                                       UART_IER);
+                               }
+                               set_bit(MXSER_EVENT_TXLOW, &port->event);
+                               schedule_work(&port->tqueue);
+                       }
+               } else {
+                       if (!(status & UART_MSR_CTS)) {
+                               port->tty->hw_stopped = 1;
+                               if (port->type != PORT_16550A &&
+                                               !port->board->chip_flag) {
+                                       port->IER &= ~UART_IER_THRI;
+                                       outb(port->IER, port->ioaddr +
+                                                       UART_IER);
+                               }
+                       }
+               }
+       }
+}
+
+static int mxser_startup(struct mxser_port *info)
+{
+       unsigned long page;
+       unsigned long flags;
+
+       page = __get_free_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
+
+       spin_lock_irqsave(&info->slock, flags);
+
+       if (info->flags & ASYNC_INITIALIZED) {
+               free_page(page);
+               spin_unlock_irqrestore(&info->slock, flags);
+               return 0;
+       }
+
+       if (!info->ioaddr || !info->type) {
+               if (info->tty)
+                       set_bit(TTY_IO_ERROR, &info->tty->flags);
+               free_page(page);
+               spin_unlock_irqrestore(&info->slock, flags);
+               return 0;
+       }
+       if (info->xmit_buf)
+               free_page(page);
+       else
+               info->xmit_buf = (unsigned char *) page;
+
+       /*
+        * Clear the FIFO buffers and disable them
+        * (they will be reenabled in mxser_change_speed())
+        */
+       if (info->board->chip_flag)
+               outb((UART_FCR_CLEAR_RCVR |
+                       UART_FCR_CLEAR_XMIT |
+                       MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
+       else
+               outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+                       info->ioaddr + UART_FCR);
+
+       /*
+        * At this point there's no way the LSR could still be 0xFF;
+        * if it is, then bail out, because there's likely no UART
+        * here.
+        */
+       if (inb(info->ioaddr + UART_LSR) == 0xff) {
+               spin_unlock_irqrestore(&info->slock, flags);
+               if (capable(CAP_SYS_ADMIN)) {
+                       if (info->tty)
+                               set_bit(TTY_IO_ERROR, &info->tty->flags);
+                       return 0;
+               } else
+                       return -ENODEV;
+       }
+
+       /*
+        * Clear the interrupt registers.
+        */
+       (void) inb(info->ioaddr + UART_LSR);
+       (void) inb(info->ioaddr + UART_RX);
+       (void) inb(info->ioaddr + UART_IIR);
+       (void) inb(info->ioaddr + UART_MSR);
+
+       /*
+        * Now, initialize the UART
+        */
+       outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR);  /* reset DLAB */
+       info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+       outb(info->MCR, info->ioaddr + UART_MCR);
+
+       /*
+        * Finally, enable interrupts
+        */
+       info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+
+       if (info->board->chip_flag)
+               info->IER |= MOXA_MUST_IER_EGDAI;
+       outb(info->IER, info->ioaddr + UART_IER);       /* enable interrupts */
+
+       /*
+        * And clear the interrupt registers again for luck.
+        */
+       (void) inb(info->ioaddr + UART_LSR);
+       (void) inb(info->ioaddr + UART_RX);
+       (void) inb(info->ioaddr + UART_IIR);
+       (void) inb(info->ioaddr + UART_MSR);
+
+       if (info->tty)
+               clear_bit(TTY_IO_ERROR, &info->tty->flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+       /*
+        * and set the speed of the serial port
+        */
+       spin_unlock_irqrestore(&info->slock, flags);
+       mxser_change_speed(info, NULL);
+
+       info->flags |= ASYNC_INITIALIZED;
+       return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts maybe disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void mxser_shutdown(struct mxser_port *info)
+{
+       unsigned long flags;
+
+       if (!(info->flags & ASYNC_INITIALIZED))
+               return;
+
+       spin_lock_irqsave(&info->slock, flags);
+
+       /*
+        * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+        * here so the queue might never be waken up
+        */
+       wake_up_interruptible(&info->delta_msr_wait);
+
+       /*
+        * Free the IRQ, if necessary
+        */
+       if (info->xmit_buf) {
+               free_page((unsigned long) info->xmit_buf);
+               info->xmit_buf = NULL;
+       }
+
+       info->IER = 0;
+       outb(0x00, info->ioaddr + UART_IER);
+
+       if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+               info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
+       outb(info->MCR, info->ioaddr + UART_MCR);
+
+       /* clear Rx/Tx FIFO's */
+       if (info->board->chip_flag)
+               outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
+                               MOXA_MUST_FCR_GDA_MODE_ENABLE,
+                               info->ioaddr + UART_FCR);
+       else
+               outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+                       info->ioaddr + UART_FCR);
+
+       /* read data port to reset things */
+       (void) inb(info->ioaddr + UART_RX);
+
+       if (info->tty)
+               set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+       info->flags &= ~ASYNC_INITIALIZED;
+
+       if (info->board->chip_flag)
+               SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int mxser_open(struct tty_struct *tty, struct file *filp)
+{
+       struct mxser_port *info;
+       int retval, line;
+
+       /* initialize driver_data in case something fails */
+       tty->driver_data = NULL;
+
+       line = tty->index;
+       if (line == MXSER_PORTS)
+               return 0;
+       if (line < 0 || line > MXSER_PORTS)
+               return -ENODEV;
+       info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
+       if (!info->ioaddr)
+               return -ENODEV;
+
+       tty->driver_data = info;
+       info->tty = tty;
+       /*
+        * Start up serial port
+        */
+       info->count++;
+       retval = mxser_startup(info);
+       if (retval)
+               return retval;
+
+       retval = mxser_block_til_ready(tty, filp, info);
+       if (retval)
+               return retval;
+
+       if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+               if (tty->driver->subtype == SERIAL_TYPE_NORMAL)
+                       *tty->termios = info->normal_termios;
+               else
+                       *tty->termios = info->callout_termios;
+               mxser_change_speed(info, NULL);
+       }
+
+       info->session = process_session(current);
+       info->pgrp = process_group(current);
+
+       /* unmark here for very high baud rate (ex. 921600 bps) used */
+       tty->low_latency = 1;
+       return 0;
+}
+
+/*
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+static void mxser_close(struct tty_struct *tty, struct file *filp)
+{
+       struct mxser_port *info = tty->driver_data;
+
+       unsigned long timeout;
+       unsigned long flags;
+
+       if (tty->index == MXSER_PORTS)
+               return;
+       if (!info)
+               return;
+
+       spin_lock_irqsave(&info->slock, flags);
+
+       if (tty_hung_up_p(filp)) {
+               spin_unlock_irqrestore(&info->slock, flags);
+               return;
+       }
+       if ((tty->count == 1) && (info->count != 1)) {
+               /*
+                * Uh, oh.  tty->count is 1, which means that the tty
+                * structure will be freed.  Info->count should always
+                * be one in these conditions.  If it's greater than
+                * one, we've got real problems, since it means the
+                * serial port won't be shutdown.
+                */
+               printk(KERN_ERR "mxser_close: bad serial port count; "
+                       "tty->count is 1, info->count is %d\n", info->count);
+               info->count = 1;
+       }
+       if (--info->count < 0) {
+               printk(KERN_ERR "mxser_close: bad serial port count for "
+                       "ttys%d: %d\n", tty->index, info->count);
+               info->count = 0;
+       }
+       if (info->count) {
+               spin_unlock_irqrestore(&info->slock, flags);
+               return;
+       }
+       info->flags |= ASYNC_CLOSING;
+       spin_unlock_irqrestore(&info->slock, flags);
+       /*
+        * Save the termios structure, since this port may have
+        * separate termios for callout and dialin.
+        */
+       if (info->flags & ASYNC_NORMAL_ACTIVE)
+               info->normal_termios = *tty->termios;
+       /*
+        * Now we wait for the transmit buffer to clear; and we notify
+        * the line discipline to only process XON/XOFF characters.
+        */
+       tty->closing = 1;
+       if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+               tty_wait_until_sent(tty, info->closing_wait);
+       /*
+        * At this point we stop accepting input.  To do this, we
+        * disable the receive line status interrupts, and tell the
+        * interrupt driver to stop checking the data ready bit in the
+        * line status register.
+        */
+       info->IER &= ~UART_IER_RLSI;
+       if (info->board->chip_flag)
+               info->IER &= ~MOXA_MUST_RECV_ISR;
+
+       if (info->flags & ASYNC_INITIALIZED) {
+               outb(info->IER, info->ioaddr + UART_IER);
+               /*
+                * Before we drop DTR, make sure the UART transmitter
+                * has completely drained; this is especially
+                * important if there is a transmit FIFO!
+                */
+               timeout = jiffies + HZ;
+               while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
+                       schedule_timeout_interruptible(5);
+                       if (time_after(jiffies, timeout))
+                               break;
+               }
+       }
+       mxser_shutdown(info);
+
+       if (tty->driver->flush_buffer)
+               tty->driver->flush_buffer(tty);
+
+       tty_ldisc_flush(tty);
+
+       tty->closing = 0;
+       info->event = 0;
+       info->tty = NULL;
+       if (info->blocked_open) {
+               if (info->close_delay)
+                       schedule_timeout_interruptible(info->close_delay);
+               wake_up_interruptible(&info->open_wait);
+       }
+
+       info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+       wake_up_interruptible(&info->close_wait);
+
+}
+
+static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+       int c, total = 0;
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       if (!info->xmit_buf)
+               return 0;
+
+       while (1) {
+               c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                         SERIAL_XMIT_SIZE - info->xmit_head));
+               if (c <= 0)
+                       break;
+
+               memcpy(info->xmit_buf + info->xmit_head, buf, c);
+               spin_lock_irqsave(&info->slock, flags);
+               info->xmit_head = (info->xmit_head + c) &
+                                 (SERIAL_XMIT_SIZE - 1);
+               info->xmit_cnt += c;
+               spin_unlock_irqrestore(&info->slock, flags);
+
+               buf += c;
+               count -= c;
+               total += c;
+       }
+
+       if (info->xmit_cnt && !tty->stopped) {
+               if (!tty->hw_stopped ||
+                               (info->type == PORT_16550A) ||
+                               (info->board->chip_flag)) {
+                       spin_lock_irqsave(&info->slock, flags);
+                       outb(info->IER & ~UART_IER_THRI, info->ioaddr +
+                                       UART_IER);
+                       info->IER |= UART_IER_THRI;
+                       outb(info->IER, info->ioaddr + UART_IER);
+                       spin_unlock_irqrestore(&info->slock, flags);
+               }
+       }
+       return total;
+}
+
+static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       if (!info->xmit_buf)
+               return;
+
+       if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+               return;
+
+       spin_lock_irqsave(&info->slock, flags);
+       info->xmit_buf[info->xmit_head++] = ch;
+       info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+       info->xmit_cnt++;
+       spin_unlock_irqrestore(&info->slock, flags);
+       if (!tty->stopped) {
+               if (!tty->hw_stopped ||
+                               (info->type == PORT_16550A) ||
+                               info->board->chip_flag) {
+                       spin_lock_irqsave(&info->slock, flags);
+                       outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+                       info->IER |= UART_IER_THRI;
+                       outb(info->IER, info->ioaddr + UART_IER);
+                       spin_unlock_irqrestore(&info->slock, flags);
+               }
+       }
+}
+
+
+static void mxser_flush_chars(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       if (info->xmit_cnt <= 0 ||
+                       tty->stopped ||
+                       !info->xmit_buf ||
+                       (tty->hw_stopped &&
+                        (info->type != PORT_16550A) &&
+                        (!info->board->chip_flag)
+                       ))
+               return;
+
+       spin_lock_irqsave(&info->slock, flags);
+
+       outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+       info->IER |= UART_IER_THRI;
+       outb(info->IER, info->ioaddr + UART_IER);
+
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static int mxser_write_room(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       int ret;
+
+       ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+       if (ret < 0)
+               ret = 0;
+       return ret;
+}
+
+static int mxser_chars_in_buffer(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       return info->xmit_cnt;
+}
+
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       char fcr;
+       unsigned long flags;
+
+
+       spin_lock_irqsave(&info->slock, flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+       fcr = inb(info->ioaddr + UART_FCR);
+       outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+               info->ioaddr + UART_FCR);
+       outb(fcr, info->ioaddr + UART_FCR);
+
+       spin_unlock_irqrestore(&info->slock, flags);
+
+       tty_wakeup(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * friends of mxser_ioctl()
+ * ------------------------------------------------------------
+ */
+static int mxser_get_serial_info(struct mxser_port *info,
+               struct serial_struct __user *retinfo)
+{
+       struct serial_struct tmp;
+
+       if (!retinfo)
+               return -EFAULT;
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.type = info->type;
+       tmp.line = info->tty->index;
+       tmp.port = info->ioaddr;
+       tmp.irq = info->board->irq;
+       tmp.flags = info->flags;
+       tmp.baud_base = info->baud_base;
+       tmp.close_delay = info->close_delay;
+       tmp.closing_wait = info->closing_wait;
+       tmp.custom_divisor = info->custom_divisor;
+       tmp.hub6 = 0;
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+       return 0;
+}
+
+static int mxser_set_serial_info(struct mxser_port *info,
+               struct serial_struct __user *new_info)
+{
+       struct serial_struct new_serial;
+       unsigned int flags;
+       int retval = 0;
+
+       if (!new_info || !info->ioaddr)
+               return -EFAULT;
+       if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+               return -EFAULT;
+
+       if ((new_serial.irq != info->board->irq) ||
+                       (new_serial.port != info->ioaddr) ||
+                       (new_serial.custom_divisor != info->custom_divisor) ||
+                       (new_serial.baud_base != info->baud_base))
+               return -EPERM;
+
+       flags = info->flags & ASYNC_SPD_MASK;
+
+       if (!capable(CAP_SYS_ADMIN)) {
+               if ((new_serial.baud_base != info->baud_base) ||
+                               (new_serial.close_delay != info->close_delay) ||
+                               ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
+                       return -EPERM;
+               info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+                               (new_serial.flags & ASYNC_USR_MASK));
+       } else {
+               /*
+                * OK, past this point, all the error checking has been done.
+                * At this point, we start making changes.....
+                */
+               info->flags = ((info->flags & ~ASYNC_FLAGS) |
+                               (new_serial.flags & ASYNC_FLAGS));
+               info->close_delay = new_serial.close_delay * HZ / 100;
+               info->closing_wait = new_serial.closing_wait * HZ / 100;
+               info->tty->low_latency =
+                               (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+               info->tty->low_latency = 0;
+       }
+
+       info->type = new_serial.type;
+
+       process_txrx_fifo(info);
+
+       if (info->flags & ASYNC_INITIALIZED) {
+               if (flags != (info->flags & ASYNC_SPD_MASK))
+                       mxser_change_speed(info, NULL);
+       } else
+               retval = mxser_startup(info);
+
+       return retval;
+}
+
+/*
+ * mxser_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 mxser_get_lsr_info(struct mxser_port *info,
+               unsigned int __user *value)
+{
+       unsigned char status;
+       unsigned int result;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->slock, flags);
+       status = inb(info->ioaddr + UART_LSR);
+       spin_unlock_irqrestore(&info->slock, flags);
+       result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+       return put_user(result, value);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void mxser_send_break(struct mxser_port *info, int duration)
+{
+       unsigned long flags;
+
+       if (!info->ioaddr)
+               return;
+       set_current_state(TASK_INTERRUPTIBLE);
+       spin_lock_irqsave(&info->slock, flags);
+       outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
+               info->ioaddr + UART_LCR);
+       spin_unlock_irqrestore(&info->slock, flags);
+       schedule_timeout(duration);
+       spin_lock_irqsave(&info->slock, flags);
+       outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
+               info->ioaddr + UART_LCR);
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned char control, status;
+       unsigned long flags;
+
+
+       if (tty->index == MXSER_PORTS)
+               return -ENOIOCTLCMD;
+       if (test_bit(TTY_IO_ERROR, &tty->flags))
+               return -EIO;
+
+       control = info->MCR;
+
+       spin_lock_irqsave(&info->slock, flags);
+       status = inb(info->ioaddr + UART_MSR);
+       if (status & UART_MSR_ANY_DELTA)
+               mxser_check_modem_status(info, status);
+       spin_unlock_irqrestore(&info->slock, flags);
+       return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+                   ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+                   ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+                   ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+                   ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+                   ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+}
+
+static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
+               unsigned int set, unsigned int clear)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+
+       if (tty->index == MXSER_PORTS)
+               return -ENOIOCTLCMD;
+       if (test_bit(TTY_IO_ERROR, &tty->flags))
+               return -EIO;
+
+       spin_lock_irqsave(&info->slock, flags);
+
+       if (set & TIOCM_RTS)
+               info->MCR |= UART_MCR_RTS;
+       if (set & TIOCM_DTR)
+               info->MCR |= UART_MCR_DTR;
+
+       if (clear & TIOCM_RTS)
+               info->MCR &= ~UART_MCR_RTS;
+       if (clear & TIOCM_DTR)
+               info->MCR &= ~UART_MCR_DTR;
+
+       outb(info->MCR, info->ioaddr + UART_MCR);
+       spin_unlock_irqrestore(&info->slock, flags);
+       return 0;
+}
+
+static int mxser_program_mode(int port)
+{
+       int id, i, j, n;
+
+       spin_lock(&gm_lock);
+       outb(0, port);
+       outb(0, port);
+       outb(0, port);
+       (void)inb(port);
+       (void)inb(port);
+       outb(0, port);
+       (void)inb(port);
+       spin_unlock(&gm_lock);
+
+       id = inb(port + 1) & 0x1F;
+       if ((id != C168_ASIC_ID) &&
+                       (id != C104_ASIC_ID) &&
+                       (id != C102_ASIC_ID) &&
+                       (id != CI132_ASIC_ID) &&
+                       (id != CI134_ASIC_ID) &&
+                       (id != CI104J_ASIC_ID))
+               return -1;
+       for (i = 0, j = 0; i < 4; i++) {
+               n = inb(port + 2);
+               if (n == 'M') {
+                       j = 1;
+               } else if ((j == 1) && (n == 1)) {
+                       j = 2;
+                       break;
+               } else
+                       j = 0;
+       }
+       if (j != 2)
+               id = -2;
+       return id;
+}
+
+static void mxser_normal_mode(int port)
+{
+       int i, n;
+
+       outb(0xA5, port + 1);
+       outb(0x80, port + 3);
+       outb(12, port + 0);     /* 9600 bps */
+       outb(0, port + 1);
+       outb(0x03, port + 3);   /* 8 data bits */
+       outb(0x13, port + 4);   /* loop back mode */
+       for (i = 0; i < 16; i++) {
+               n = inb(port + 5);
+               if ((n & 0x61) == 0x60)
+                       break;
+               if ((n & 1) == 1)
+                       (void)inb(port);
+       }
+       outb(0x00, port + 4);
+}
+
+#define CHIP_SK        0x01    /* Serial Data Clock  in Eprom */
+#define CHIP_DO        0x02    /* Serial Data Output in Eprom */
+#define CHIP_CS        0x04    /* Serial Chip Select in Eprom */
+#define CHIP_DI        0x08    /* Serial Data Input  in Eprom */
+#define EN_CCMD        0x000   /* Chip's command register     */
+#define EN0_RSARLO     0x008   /* Remote start address reg 0  */
+#define EN0_RSARHI     0x009   /* Remote start address reg 1  */
+#define EN0_RCNTLO     0x00A   /* Remote byte count reg WR    */
+#define EN0_RCNTHI     0x00B   /* Remote byte count reg WR    */
+#define EN0_DCFG       0x00E   /* Data configuration reg WR   */
+#define EN0_PORT       0x010   /* Rcv missed frame error counter RD */
+#define ENC_PAGE0      0x000   /* Select page 0 of chip registers   */
+#define ENC_PAGE3      0x0C0   /* Select page 3 of chip registers   */
+static int mxser_read_register(int port, unsigned short *regs)
+{
+       int i, k, value, id;
+       unsigned int j;
+
+       id = mxser_program_mode(port);
+       if (id < 0)
+               return id;
+       for (i = 0; i < 14; i++) {
+               k = (i & 0x3F) | 0x180;
+               for (j = 0x100; j > 0; j >>= 1) {
+                       outb(CHIP_CS, port);
+                       if (k & j) {
+                               outb(CHIP_CS | CHIP_DO, port);
+                               outb(CHIP_CS | CHIP_DO | CHIP_SK, port);        /* A? bit of read */
+                       } else {
+                               outb(CHIP_CS, port);
+                               outb(CHIP_CS | CHIP_SK, port);  /* A? bit of read */
+                       }
+               }
+               (void)inb(port);
+               value = 0;
+               for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
+                       outb(CHIP_CS, port);
+                       outb(CHIP_CS | CHIP_SK, port);
+                       if (inb(port) & CHIP_DI)
+                               value |= j;
+               }
+               regs[i] = value;
+               outb(0, port);
+       }
+       mxser_normal_mode(port);
+       return id;
+}
+
+static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+{
+       struct mxser_port *port;
+       int result, status;
+       unsigned int i, j;
+
+       switch (cmd) {
+       case MOXA_GET_CONF:
+/*             if (copy_to_user(argp, mxsercfg,
+                               sizeof(struct mxser_hwconf) * 4))
+                       return -EFAULT;
+               return 0;*/
+               return -ENXIO;
+       case MOXA_GET_MAJOR:
+               if (copy_to_user(argp, &ttymajor, sizeof(int)))
+                       return -EFAULT;
+               return 0;
+
+       case MOXA_GET_CUMAJOR:
+               if (copy_to_user(argp, &calloutmajor, sizeof(int)))
+                       return -EFAULT;
+               return 0;
+
+       case MOXA_CHKPORTENABLE:
+               result = 0;
+
+               for (i = 0; i < MXSER_BOARDS; i++)
+                       for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
+                               if (mxser_boards[i].ports[j].ioaddr)
+                                       result |= (1 << i);
+
+               return put_user(result, (unsigned long __user *)argp);
+       case MOXA_GETDATACOUNT:
+               if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
+                       return -EFAULT;
+               return 0;
+       case MOXA_GETMSTATUS:
+               for (i = 0; i < MXSER_BOARDS; i++)
+                       for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+                               port = &mxser_boards[i].ports[j];
+
+                               GMStatus[i].ri = 0;
+                               if (!port->ioaddr) {
+                                       GMStatus[i].dcd = 0;
+                                       GMStatus[i].dsr = 0;
+                                       GMStatus[i].cts = 0;
+                                       continue;
+                               }
+
+                               if (!port->tty || !port->tty->termios)
+                                       GMStatus[i].cflag =
+                                               port->normal_termios.c_cflag;
+                               else
+                                       GMStatus[i].cflag =
+                                               port->tty->termios->c_cflag;
+
+                               status = inb(port->ioaddr + UART_MSR);
+                               if (status & 0x80 /*UART_MSR_DCD */ )
+                                       GMStatus[i].dcd = 1;
+                               else
+                                       GMStatus[i].dcd = 0;
+
+                               if (status & 0x20 /*UART_MSR_DSR */ )
+                                       GMStatus[i].dsr = 1;
+                               else
+                                       GMStatus[i].dsr = 0;
+
+
+                               if (status & 0x10 /*UART_MSR_CTS */ )
+                                       GMStatus[i].cts = 1;
+                               else
+                                       GMStatus[i].cts = 0;
+                       }
+               if (copy_to_user(argp, GMStatus,
+                               sizeof(struct mxser_mstatus) * MXSER_PORTS))
+                       return -EFAULT;
+               return 0;
+       case MOXA_ASPP_MON_EXT: {
+               int status, p, shiftbit;
+               unsigned long opmode;
+               unsigned cflag, iflag;
+
+               for (i = 0; i < MXSER_BOARDS; i++)
+                       for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+                               port = &mxser_boards[i].ports[j];
+                               if (!port->ioaddr)
+                                       continue;
+
+                               status = mxser_get_msr(port->ioaddr, 0, i);
+
+                               if (status & UART_MSR_TERI)
+                                       port->icount.rng++;
+                               if (status & UART_MSR_DDSR)
+                                       port->icount.dsr++;
+                               if (status & UART_MSR_DDCD)
+                                       port->icount.dcd++;
+                               if (status & UART_MSR_DCTS)
+                                       port->icount.cts++;
+
+                               port->mon_data.modem_status = status;
+                               mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt;
+                               mon_data_ext.tx_cnt[i] = port->mon_data.txcnt;
+                               mon_data_ext.up_rxcnt[i] =
+                                       port->mon_data.up_rxcnt;
+                               mon_data_ext.up_txcnt[i] =
+                                       port->mon_data.up_txcnt;
+                               mon_data_ext.modem_status[i] =
+                                       port->mon_data.modem_status;
+                               mon_data_ext.baudrate[i] = port->realbaud;
+
+                               if (!port->tty || !port->tty->termios) {
+                                       cflag = port->normal_termios.c_cflag;
+                                       iflag = port->normal_termios.c_iflag;
+                               } else {
+                                       cflag = port->tty->termios->c_cflag;
+                                       iflag = port->tty->termios->c_iflag;
+                               }
+
+                               mon_data_ext.databits[i] = cflag & CSIZE;
+
+                               mon_data_ext.stopbits[i] = cflag & CSTOPB;
+
+                               mon_data_ext.parity[i] =
+                                       cflag & (PARENB | PARODD | CMSPAR);
+
+                               mon_data_ext.flowctrl[i] = 0x00;
+
+                               if (cflag & CRTSCTS)
+                                       mon_data_ext.flowctrl[i] |= 0x03;
+
+                               if (iflag & (IXON | IXOFF))
+                                       mon_data_ext.flowctrl[i] |= 0x0C;
+
+                               if (port->type == PORT_16550A)
+                                       mon_data_ext.fifo[i] = 1;
+                               else
+                                       mon_data_ext.fifo[i] = 0;
+
+                               p = i % 4;
+                               shiftbit = p * 2;
+                               opmode = inb(port->opmode_ioaddr) >> shiftbit;
+                               opmode &= OP_MODE_MASK;
+
+                               mon_data_ext.iftype[i] = opmode;
+
+                       }
+                       if (copy_to_user(argp, &mon_data_ext,
+                                               sizeof(mon_data_ext)))
+                               return -EFAULT;
+
+                       return 0;
+
+       } default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       struct mxser_port *info = tty->driver_data;
+       struct async_icount cprev, cnow;        /* kernel counter temps */
+       struct serial_icounter_struct __user *p_cuser;
+       unsigned long templ;
+       unsigned long flags;
+       void __user *argp = (void __user *)arg;
+       int retval;
+
+       if (tty->index == MXSER_PORTS)
+               return mxser_ioctl_special(cmd, argp);
+
+       if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
+               int p;
+               unsigned long opmode;
+               static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
+               int shiftbit;
+               unsigned char val, mask;
+
+               p = tty->index % 4;
+               if (cmd == MOXA_SET_OP_MODE) {
+                       if (get_user(opmode, (int __user *) argp))
+                               return -EFAULT;
+                       if (opmode != RS232_MODE &&
+                                       opmode != RS485_2WIRE_MODE &&
+                                       opmode != RS422_MODE &&
+                                       opmode != RS485_4WIRE_MODE)
+                               return -EFAULT;
+                       mask = ModeMask[p];
+                       shiftbit = p * 2;
+                       val = inb(info->opmode_ioaddr);
+                       val &= mask;
+                       val |= (opmode << shiftbit);
+                       outb(val, info->opmode_ioaddr);
+               } else {
+                       shiftbit = p * 2;
+                       opmode = inb(info->opmode_ioaddr) >> shiftbit;
+                       opmode &= OP_MODE_MASK;
+                       if (copy_to_user(argp, &opmode, sizeof(int)))
+                               return -EFAULT;
+               }
+               return 0;
+       }
+
+       if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+                       test_bit(TTY_IO_ERROR, &tty->flags))
+               return -EIO;
+
+       switch (cmd) {
+       case TCSBRK:            /* SVID version: non-zero arg --> no break */
+               retval = tty_check_change(tty);
+               if (retval)
+                       return retval;
+               tty_wait_until_sent(tty, 0);
+               if (!arg)
+                       mxser_send_break(info, HZ / 4); /* 1/4 second */
+               return 0;
+       case TCSBRKP:           /* support for POSIX tcsendbreak() */
+               retval = tty_check_change(tty);
+               if (retval)
+                       return retval;
+               tty_wait_until_sent(tty, 0);
+               mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+               return 0;
+       case TIOCGSOFTCAR:
+               return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
+       case TIOCSSOFTCAR:
+               if (get_user(templ, (unsigned long __user *) argp))
+                       return -EFAULT;
+               arg = templ;
+               tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+               return 0;
+       case TIOCGSERIAL:
+               return mxser_get_serial_info(info, argp);
+       case TIOCSSERIAL:
+               return mxser_set_serial_info(info, argp);
+       case TIOCSERGETLSR:     /* Get line status register */
+               return mxser_get_lsr_info(info, argp);
+               /*
+                * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+                * - mask passed in arg for lines of interest
+                *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+                * Caller should use TIOCGICOUNT to see which one it was
+                */
+       case TIOCMIWAIT: {
+               DECLARE_WAITQUEUE(wait, current);
+               int ret;
+               spin_lock_irqsave(&info->slock, flags);
+               cprev = info->icount;   /* note the counters on entry */
+               spin_unlock_irqrestore(&info->slock, flags);
+
+               add_wait_queue(&info->delta_msr_wait, &wait);
+               while (1) {
+                       spin_lock_irqsave(&info->slock, flags);
+                       cnow = info->icount;    /* atomic copy */
+                       spin_unlock_irqrestore(&info->slock, flags);
+
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       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))) {
+                               ret = 0;
+                               break;
+                       }
+                       /* see if a signal did it */
+                       if (signal_pending(current)) {
+                               ret = -ERESTARTSYS;
+                               break;
+                       }
+                       cprev = cnow;
+               }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&info->delta_msr_wait, &wait);
+               break;
+       }
+       /* NOTREACHED */
+       /*
+        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+        * Return: write counters to the user passed counter struct
+        * NB: both 1->0 and 0->1 transitions are counted except for
+        *     RI where only 0->1 is counted.
+        */
+       case TIOCGICOUNT:
+               spin_lock_irqsave(&info->slock, flags);
+               cnow = info->icount;
+               spin_unlock_irqrestore(&info->slock, flags);
+               p_cuser = argp;
+               if (put_user(cnow.frame, &p_cuser->frame))
+                       return -EFAULT;
+               if (put_user(cnow.brk, &p_cuser->brk))
+                       return -EFAULT;
+               if (put_user(cnow.overrun, &p_cuser->overrun))
+                       return -EFAULT;
+               if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+                       return -EFAULT;
+               if (put_user(cnow.parity, &p_cuser->parity))
+                       return -EFAULT;
+               if (put_user(cnow.rx, &p_cuser->rx))
+                       return -EFAULT;
+               if (put_user(cnow.tx, &p_cuser->tx))
+                       return -EFAULT;
+               put_user(cnow.cts, &p_cuser->cts);
+               put_user(cnow.dsr, &p_cuser->dsr);
+               put_user(cnow.rng, &p_cuser->rng);
+               put_user(cnow.dcd, &p_cuser->dcd);
+               return 0;
+       case MOXA_HighSpeedOn:
+               return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+       case MOXA_SDS_RSTICOUNTER:
+               info->mon_data.rxcnt = 0;
+               info->mon_data.txcnt = 0;
+               return 0;
+       case MOXA_ASPP_SETBAUD:{
+               long baud;
+               if (get_user(baud, (long __user *)argp))
+                       return -EFAULT;
+               mxser_set_baud(info, baud);
+               return 0;
+       }
+       case MOXA_ASPP_GETBAUD:
+               if (copy_to_user(argp, &info->realbaud, sizeof(long)))
+                       return -EFAULT;
+
+               return 0;
+
+       case MOXA_ASPP_OQUEUE:{
+               int len, lsr;
+
+               len = mxser_chars_in_buffer(tty);
+
+               lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
+
+               len += (lsr ? 0 : 1);
+
+               if (copy_to_user(argp, &len, sizeof(int)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case MOXA_ASPP_MON: {
+               int mcr, status;
+
+               status = mxser_get_msr(info->ioaddr, 1, tty->index);
+               mxser_check_modem_status(info, status);
+
+               mcr = inb(info->ioaddr + UART_MCR);
+               if (mcr & MOXA_MUST_MCR_XON_FLAG)
+                       info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
+               else
+                       info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
+
+               if (mcr & MOXA_MUST_MCR_TX_XON)
+                       info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
+               else
+                       info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
+
+               if (info->tty->hw_stopped)
+                       info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
+               else
+                       info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
+
+               if (copy_to_user(argp, &info->mon_data,
+                               sizeof(struct mxser_mon)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case MOXA_ASPP_LSTATUS: {
+               if (copy_to_user(argp, &info->err_shadow,
+                               sizeof(unsigned char)))
+                       return -EFAULT;
+
+               info->err_shadow = 0;
+               return 0;
+       }
+       case MOXA_SET_BAUD_METHOD: {
+               int method;
+
+               if (get_user(method, (int __user *)argp))
+                       return -EFAULT;
+               mxser_set_baud_method[tty->index] = method;
+               if (copy_to_user(argp, &method, sizeof(int)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static void mxser_stoprx(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+
+       info->ldisc_stop_rx = 1;
+       if (I_IXOFF(tty)) {
+               if (info->board->chip_flag) {
+                       info->IER &= ~MOXA_MUST_RECV_ISR;
+                       outb(info->IER, info->ioaddr + UART_IER);
+               } else {
+                       info->x_char = STOP_CHAR(tty);
+                       outb(0, info->ioaddr + UART_IER);
+                       info->IER |= UART_IER_THRI;
+                       outb(info->IER, info->ioaddr + UART_IER);
+               }
+       }
+
+       if (info->tty->termios->c_cflag & CRTSCTS) {
+               info->MCR &= ~UART_MCR_RTS;
+               outb(info->MCR, info->ioaddr + UART_MCR);
+       }
+}
+
+/*
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ */
+static void mxser_throttle(struct tty_struct *tty)
+{
+       mxser_stoprx(tty);
+}
+
+static void mxser_unthrottle(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+
+       /* startrx */
+       info->ldisc_stop_rx = 0;
+       if (I_IXOFF(tty)) {
+               if (info->x_char)
+                       info->x_char = 0;
+               else {
+                       if (info->board->chip_flag) {
+                               info->IER |= MOXA_MUST_RECV_ISR;
+                               outb(info->IER, info->ioaddr + UART_IER);
+                       } else {
+                               info->x_char = START_CHAR(tty);
+                               outb(0, info->ioaddr + UART_IER);
+                               info->IER |= UART_IER_THRI;
+                               outb(info->IER, info->ioaddr + UART_IER);
+                       }
+               }
+       }
+
+       if (info->tty->termios->c_cflag & CRTSCTS) {
+               info->MCR |= UART_MCR_RTS;
+               outb(info->MCR, info->ioaddr + UART_MCR);
+       }
+}
+
+/*
+ * mxser_stop() and mxser_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ */
+static void mxser_stop(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->slock, flags);
+       if (info->IER & UART_IER_THRI) {
+               info->IER &= ~UART_IER_THRI;
+               outb(info->IER, info->ioaddr + UART_IER);
+       }
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_start(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->slock, flags);
+       if (info->xmit_cnt && info->xmit_buf) {
+               outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+               info->IER |= UART_IER_THRI;
+               outb(info->IER, info->ioaddr + UART_IER);
+       }
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       if ((tty->termios->c_cflag != old_termios->c_cflag) ||
+                       (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+
+               mxser_change_speed(info, old_termios);
+
+               if ((old_termios->c_cflag & CRTSCTS) &&
+                               !(tty->termios->c_cflag & CRTSCTS)) {
+                       tty->hw_stopped = 0;
+                       mxser_start(tty);
+               }
+       }
+
+       /* Handle sw stopped */
+       if ((old_termios->c_iflag & IXON) &&
+                       !(tty->termios->c_iflag & IXON)) {
+               tty->stopped = 0;
+
+               if (info->board->chip_flag) {
+                       spin_lock_irqsave(&info->slock, flags);
+                       DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       spin_unlock_irqrestore(&info->slock, flags);
+               }
+
+               mxser_start(tty);
+       }
+}
+
+/*
+ * mxser_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long orig_jiffies, char_time;
+       int lsr;
+
+       if (info->type == PORT_UNKNOWN)
+               return;
+
+       if (info->xmit_fifo_size == 0)
+               return;         /* Just in case.... */
+
+       orig_jiffies = jiffies;
+       /*
+        * Set the check interval to be 1/5 of the estimated time to
+        * send a single character, and make it at least 1.  The check
+        * interval should also be less than the timeout.
+        *
+        * Note: we have to use pretty tight timings here to satisfy
+        * the NIST-PCTS.
+        */
+       char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+       char_time = char_time / 5;
+       if (char_time == 0)
+               char_time = 1;
+       if (timeout && timeout < char_time)
+               char_time = timeout;
+       /*
+        * If the transmitter hasn't cleared in twice the approximate
+        * amount of time to send the entire FIFO, it probably won't
+        * ever clear.  This assumes the UART isn't doing flow
+        * control, which is currently the case.  Hence, if it ever
+        * takes longer than info->timeout, this is probably due to a
+        * UART bug of some kind.  So, we clamp the timeout parameter at
+        * 2*info->timeout.
+        */
+       if (!timeout || timeout > 2 * info->timeout)
+               timeout = 2 * info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+       printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
+               timeout, char_time);
+       printk("jiff=%lu...", jiffies);
+#endif
+       while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+               printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+               schedule_timeout_interruptible(char_time);
+               if (signal_pending(current))
+                       break;
+               if (timeout && time_after(jiffies, orig_jiffies + timeout))
+                       break;
+       }
+       set_current_state(TASK_RUNNING);
+
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+       printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * This routine is called by tty_hangup() when a hangup is signaled.
+ */
+void mxser_hangup(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+
+       mxser_flush_buffer(tty);
+       mxser_shutdown(info);
+       info->event = 0;
+       info->count = 0;
+       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+       info->tty = NULL;
+       wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * mxser_rs_break() --- routine which turns the break handling on or off
+ */
+static void mxser_rs_break(struct tty_struct *tty, int break_state)
+{
+       struct mxser_port *info = tty->driver_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->slock, flags);
+       if (break_state == -1)
+               outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
+                       info->ioaddr + UART_LCR);
+       else
+               outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
+                       info->ioaddr + UART_LCR);
+       spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_receive_chars(struct mxser_port *port, int *status)
+{
+       struct tty_struct *tty = port->tty;
+       unsigned char ch, gdl;
+       int ignored = 0;
+       int cnt = 0;
+       int recv_room;
+       int max = 256;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->slock, flags);
+
+       recv_room = tty->receive_room;
+       if ((recv_room == 0) && (!port->ldisc_stop_rx))
+               mxser_stoprx(tty);
+
+       if (port->board->chip_flag != MOXA_OTHER_UART) {
+
+               if (*status & UART_LSR_SPECIAL)
+                       goto intr_old;
+               if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
+                               (*status & MOXA_MUST_LSR_RERR))
+                       goto intr_old;
+               if (*status & MOXA_MUST_LSR_RERR)
+                       goto intr_old;
+
+               gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
+
+               if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
+                       gdl &= MOXA_MUST_GDL_MASK;
+               if (gdl >= recv_room) {
+                       if (!port->ldisc_stop_rx)
+                               mxser_stoprx(tty);
+               }
+               while (gdl--) {
+                       ch = inb(port->ioaddr + UART_RX);
+                       tty_insert_flip_char(tty, ch, 0);
+                       cnt++;
+               }
+               goto end_intr;
+       }
+intr_old:
+
+       do {
+               if (max-- < 0)
+                       break;
+
+               ch = inb(port->ioaddr + UART_RX);
+               if (port->board->chip_flag && (*status & UART_LSR_OE))
+                       outb(0x23, port->ioaddr + UART_FCR);
+               *status &= port->read_status_mask;
+               if (*status & port->ignore_status_mask) {
+                       if (++ignored > 100)
+                               break;
+               } else {
+                       char flag = 0;
+                       if (*status & UART_LSR_SPECIAL) {
+                               if (*status & UART_LSR_BI) {
+                                       flag = TTY_BREAK;
+                                       port->icount.brk++;
+
+                                       if (port->flags & ASYNC_SAK)
+                                               do_SAK(tty);
+                               } else if (*status & UART_LSR_PE) {
+                                       flag = TTY_PARITY;
+                                       port->icount.parity++;
+                               } else if (*status & UART_LSR_FE) {
+                                       flag = TTY_FRAME;
+                                       port->icount.frame++;
+                               } else if (*status & UART_LSR_OE) {
+                                       flag = TTY_OVERRUN;
+                                       port->icount.overrun++;
+                               }
+                       }
+                       tty_insert_flip_char(tty, ch, flag);
+                       cnt++;
+                       if (cnt >= recv_room) {
+                               if (!port->ldisc_stop_rx)
+                                       mxser_stoprx(tty);
+                               break;
+                       }
+
+               }
+
+               if (port->board->chip_flag)
+                       break;
+
+               *status = inb(port->ioaddr + UART_LSR);
+       } while (*status & UART_LSR_DR);
+
+end_intr:
+       mxvar_log.rxcnt[port->tty->index] += cnt;
+       port->mon_data.rxcnt += cnt;
+       port->mon_data.up_rxcnt += cnt;
+       spin_unlock_irqrestore(&port->slock, flags);
+
+       tty_flip_buffer_push(tty);
+}
+
+static void mxser_transmit_chars(struct mxser_port *port)
+{
+       int count, cnt;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->slock, flags);
+
+       if (port->x_char) {
+               outb(port->x_char, port->ioaddr + UART_TX);
+               port->x_char = 0;
+               mxvar_log.txcnt[port->tty->index]++;
+               port->mon_data.txcnt++;
+               port->mon_data.up_txcnt++;
+               port->icount.tx++;
+               goto unlock;
+       }
+
+       if (port->xmit_buf == 0)
+               goto unlock;
+
+       if ((port->xmit_cnt <= 0) || port->tty->stopped ||
+                       (port->tty->hw_stopped &&
+                       (port->type != PORT_16550A) &&
+                       (!port->board->chip_flag))) {
+               port->IER &= ~UART_IER_THRI;
+               outb(port->IER, port->ioaddr + UART_IER);
+               goto unlock;
+       }
+
+       cnt = port->xmit_cnt;
+       count = port->xmit_fifo_size;
+       do {
+               outb(port->xmit_buf[port->xmit_tail++],
+                       port->ioaddr + UART_TX);
+               port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+               if (--port->xmit_cnt <= 0)
+                       break;
+       } while (--count > 0);
+       mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt);
+
+       port->mon_data.txcnt += (cnt - port->xmit_cnt);
+       port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
+       port->icount.tx += (cnt - port->xmit_cnt);
+
+       if (port->xmit_cnt < WAKEUP_CHARS) {
+               set_bit(MXSER_EVENT_TXLOW, &port->event);
+               schedule_work(&port->tqueue);
+       }
+       if (port->xmit_cnt <= 0) {
+               port->IER &= ~UART_IER_THRI;
+               outb(port->IER, port->ioaddr + UART_IER);
+       }
+unlock:
+       spin_unlock_irqrestore(&port->slock, flags);
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id)
+{
+       int status, iir, i;
+       struct mxser_board *brd = NULL;
+       struct mxser_port *port;
+       int max, irqbits, bits, msr;
+       int pass_counter = 0;
+       unsigned int int_cnt;
+       int handled = IRQ_NONE;
+
+       for (i = 0; i < MXSER_BOARDS; i++)
+               if (dev_id == &mxser_boards[i]) {
+                       brd = dev_id;
+                       break;
+               }
+
+       if (i == MXSER_BOARDS)
+               goto irq_stop;
+       if (brd == NULL)
+               goto irq_stop;
+       max = brd->info->nports;
+       while (1) {
+               irqbits = inb(brd->vector) & brd->vector_mask;
+               if (irqbits == brd->vector_mask)
+                       break;
+
+               handled = IRQ_HANDLED;
+               for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+                       if (irqbits == brd->vector_mask)
+                               break;
+                       if (bits & irqbits)
+                               continue;
+                       port = &brd->ports[i];
+
+                       int_cnt = 0;
+                       do {
+                               iir = inb(port->ioaddr + UART_IIR);
+                               if (iir & UART_IIR_NO_INT)
+                                       break;
+                               iir &= MOXA_MUST_IIR_MASK;
+                               if (!port->tty) {
+                                       status = inb(port->ioaddr + UART_LSR);
+                                       outb(0x27, port->ioaddr + UART_FCR);
+                                       inb(port->ioaddr + UART_MSR);
+                                       break;
+                               }
+
+                               status = inb(port->ioaddr + UART_LSR);
+
+                               if (status & UART_LSR_PE)
+                                       port->err_shadow |= NPPI_NOTIFY_PARITY;
+                               if (status & UART_LSR_FE)
+                                       port->err_shadow |= NPPI_NOTIFY_FRAMING;
+                               if (status & UART_LSR_OE)
+                                       port->err_shadow |=
+                                               NPPI_NOTIFY_HW_OVERRUN;
+                               if (status & UART_LSR_BI)
+                                       port->err_shadow |= NPPI_NOTIFY_BREAK;
+
+                               if (port->board->chip_flag) {
+                                       if (iir == MOXA_MUST_IIR_GDA ||
+                                           iir == MOXA_MUST_IIR_RDA ||
+                                           iir == MOXA_MUST_IIR_RTO ||
+                                           iir == MOXA_MUST_IIR_LSR)
+                                               mxser_receive_chars(port,
+                                                               &status);
+
+                               } else {
+                                       status &= port->read_status_mask;
+                                       if (status & UART_LSR_DR)
+                                               mxser_receive_chars(port,
+                                                               &status);
+                               }
+                               msr = inb(port->ioaddr + UART_MSR);
+                               if (msr & UART_MSR_ANY_DELTA)
+                                       mxser_check_modem_status(port, msr);
+
+                               if (port->board->chip_flag) {
+                                       if (iir == 0x02 && (status &
+                                                               UART_LSR_THRE))
+                                               mxser_transmit_chars(port);
+                               } else {
+                                       if (status & UART_LSR_THRE)
+                                               mxser_transmit_chars(port);
+                               }
+                       } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
+               }
+               if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
+                       break;  /* Prevent infinite loops */
+       }
+
+irq_stop:
+       return handled;
+}
+
+static const struct tty_operations mxser_ops = {
+       .open = mxser_open,
+       .close = mxser_close,
+       .write = mxser_write,
+       .put_char = mxser_put_char,
+       .flush_chars = mxser_flush_chars,
+       .write_room = mxser_write_room,
+       .chars_in_buffer = mxser_chars_in_buffer,
+       .flush_buffer = mxser_flush_buffer,
+       .ioctl = mxser_ioctl,
+       .throttle = mxser_throttle,
+       .unthrottle = mxser_unthrottle,
+       .set_termios = mxser_set_termios,
+       .stop = mxser_stop,
+       .start = mxser_start,
+       .hangup = mxser_hangup,
+       .break_ctl = mxser_rs_break,
+       .wait_until_sent = mxser_wait_until_sent,
+       .tiocmget = mxser_tiocmget,
+       .tiocmset = mxser_tiocmset,
+};
+
+/*
+ * The MOXA Smartio/Industio serial driver boot-time initialization code!
+ */
+
+static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
+               unsigned int irq)
+{
+       if (irq)
+               free_irq(brd->irq, brd);
+       if (pdev != NULL) {     /* PCI */
+               pci_release_region(pdev, 2);
+               pci_release_region(pdev, 3);
+               pci_dev_put(pdev);
+       } else {
+               release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+               release_region(brd->vector, 1);
+       }
+}
+
+static int __devinit mxser_initbrd(struct mxser_board *brd,
+               struct pci_dev *pdev)
+{
+       struct mxser_port *info;
+       unsigned int i;
+       int retval;
+
+       printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud);
+
+       for (i = 0; i < brd->info->nports; i++) {
+               info = &brd->ports[i];
+               info->board = brd;
+               info->stop_rx = 0;
+               info->ldisc_stop_rx = 0;
+
+               /* Enhance mode enabled here */
+               if (brd->chip_flag != MOXA_OTHER_UART)
+                       ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr);
+
+               info->flags = ASYNC_SHARE_IRQ;
+               info->type = brd->uart_type;
+
+               process_txrx_fifo(info);
+
+               info->custom_divisor = info->baud_base * 16;
+               info->close_delay = 5 * HZ / 10;
+               info->closing_wait = 30 * HZ;
+               INIT_WORK(&info->tqueue, mxser_do_softint);
+               info->normal_termios = mxvar_sdriver->init_termios;
+               init_waitqueue_head(&info->open_wait);
+               init_waitqueue_head(&info->close_wait);
+               init_waitqueue_head(&info->delta_msr_wait);
+               memset(&info->mon_data, 0, sizeof(struct mxser_mon));
+               info->err_shadow = 0;
+               spin_lock_init(&info->slock);
+
+               /* before set INT ISR, disable all int */
+               outb(inb(info->ioaddr + UART_IER) & 0xf0,
+                       info->ioaddr + UART_IER);
+       }
+       /*
+        * Allocate the IRQ if necessary
+        */
+
+       retval = request_irq(brd->irq, mxser_interrupt,
+                       (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED :
+                       IRQF_DISABLED, "mxser", brd);
+       if (retval) {
+               printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
+                       "conflict with another device.\n",
+                       brd->info->name, brd->irq);
+               /* We hold resources, we need to release them. */
+               mxser_release_res(brd, pdev, 0);
+               return retval;
+       }
+       return 0;
+}
+
+static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
+{
+       int id, i, bits;
+       unsigned short regs[16], irq;
+       unsigned char scratch, scratch2;
+
+       brd->chip_flag = MOXA_OTHER_UART;
+
+       id = mxser_read_register(cap, regs);
+       switch (id) {
+       case C168_ASIC_ID:
+               brd->info = &mxser_cards[0];
+               break;
+       case C104_ASIC_ID:
+               brd->info = &mxser_cards[1];
+               break;
+       case CI104J_ASIC_ID:
+               brd->info = &mxser_cards[2];
+               break;
+       case C102_ASIC_ID:
+               brd->info = &mxser_cards[5];
+               break;
+       case CI132_ASIC_ID:
+               brd->info = &mxser_cards[6];
+               break;
+       case CI134_ASIC_ID:
+               brd->info = &mxser_cards[7];
+               break;
+       default:
+               return 0;
+       }
+
+       irq = 0;
+       /* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
+          Flag-hack checks if configuration should be read as 2-port here. */
+       if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
+               irq = regs[9] & 0xF000;
+               irq = irq | (irq >> 4);
+               if (irq != (regs[9] & 0xFF00))
+                       return MXSER_ERR_IRQ_CONFLIT;
+       } else if (brd->info->nports == 4) {
+               irq = regs[9] & 0xF000;
+               irq = irq | (irq >> 4);
+               irq = irq | (irq >> 8);
+               if (irq != regs[9])
+                       return MXSER_ERR_IRQ_CONFLIT;
+       } else if (brd->info->nports == 8) {
+               irq = regs[9] & 0xF000;
+               irq = irq | (irq >> 4);
+               irq = irq | (irq >> 8);
+               if ((irq != regs[9]) || (irq != regs[10]))
+                       return MXSER_ERR_IRQ_CONFLIT;
+       }
+
+       if (!irq)
+               return MXSER_ERR_IRQ;
+       brd->irq = ((int)(irq & 0xF000) >> 12);
+       for (i = 0; i < 8; i++)
+               brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
+       if ((regs[12] & 0x80) == 0)
+               return MXSER_ERR_VECTOR;
+       brd->vector = (int)regs[11];    /* interrupt vector */
+       if (id == 1)
+               brd->vector_mask = 0x00FF;
+       else
+               brd->vector_mask = 0x000F;
+       for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
+               if (regs[12] & bits) {
+                       brd->ports[i].baud_base = 921600;
+                       brd->ports[i].max_baud = 921600;
+               } else {
+                       brd->ports[i].baud_base = 115200;
+                       brd->ports[i].max_baud = 115200;
+               }
+       }
+       scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
+       outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
+       outb(0, cap + UART_EFR);        /* EFR is the same as FCR */
+       outb(scratch2, cap + UART_LCR);
+       outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
+       scratch = inb(cap + UART_IIR);
+
+       if (scratch & 0xC0)
+               brd->uart_type = PORT_16550A;
+       else
+               brd->uart_type = PORT_16450;
+       if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
+                       "mxser(IO)"))
+               return MXSER_ERR_IOADDR;
+       if (!request_region(brd->vector, 1, "mxser(vector)")) {
+               release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+               return MXSER_ERR_VECTOR;
+       }
+       return brd->info->nports;
+}
+
+static int __devinit mxser_probe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       struct mxser_board *brd;
+       unsigned int i, j;
+       unsigned long ioaddress;
+       int retval = -EINVAL;
+
+       for (i = 0; i < MXSER_BOARDS; i++)
+               if (mxser_boards[i].info == NULL)
+                       break;
+
+       if (i >= MXSER_BOARDS) {
+               printk(KERN_ERR "Too many Smartio/Industio family boards found "
+                       "(maximum %d), board not configured\n", MXSER_BOARDS);
+               goto err;
+       }
+
+       brd = &mxser_boards[i];
+       brd->idx = i * MXSER_PORTS_PER_BOARD;
+       printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n",
+               mxser_cards[ent->driver_data].name,
+               pdev->bus->number, PCI_SLOT(pdev->devfn));
+
+       retval = pci_enable_device(pdev);
+       if (retval) {
+               printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+               goto err;
+       }
+
+       /* io address */
+       ioaddress = pci_resource_start(pdev, 2);
+       retval = pci_request_region(pdev, 2, "mxser(IO)");
+       if (retval)
+               goto err;
+
+       brd->info = &mxser_cards[ent->driver_data];
+       for (i = 0; i < brd->info->nports; i++)
+               brd->ports[i].ioaddr = ioaddress + 8 * i;
+
+       /* vector */
+       ioaddress = pci_resource_start(pdev, 3);
+       retval = pci_request_region(pdev, 3, "mxser(vector)");
+       if (retval)
+               goto err_relio;
+       brd->vector = ioaddress;
+
+       /* irq */
+       brd->irq = pdev->irq;
+
+       brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
+       brd->uart_type = PORT_16550A;
+       brd->vector_mask = 0;
+
+       for (i = 0; i < brd->info->nports; i++) {
+               for (j = 0; j < UART_INFO_NUM; j++) {
+                       if (Gpci_uart_info[j].type == brd->chip_flag) {
+                               brd->ports[i].max_baud =
+                                       Gpci_uart_info[j].max_baud;
+
+                               /* exception....CP-102 */
+                               if (brd->info->flags & MXSER_HIGHBAUD)
+                                       brd->ports[i].max_baud = 921600;
+                               break;
+                       }
+               }
+       }
+
+       if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
+               for (i = 0; i < brd->info->nports; i++) {
+                       if (i < 4)
+                               brd->ports[i].opmode_ioaddr = ioaddress + 4;
+                       else
+                               brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
+               }
+               outb(0, ioaddress + 4); /* default set to RS232 mode */
+               outb(0, ioaddress + 0x0c);      /* default set to RS232 mode */
+       }
+
+       for (i = 0; i < brd->info->nports; i++) {
+               brd->vector_mask |= (1 << i);
+               brd->ports[i].baud_base = 921600;
+       }
+
+       /* mxser_initbrd will hook ISR. */
+       if (mxser_initbrd(brd, pdev) < 0)
+               goto err_relvec;
+
+       for (i = 0; i < brd->info->nports; i++)
+               tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+
+       pci_set_drvdata(pdev, brd);
+
+       return 0;
+err_relvec:
+       pci_release_region(pdev, 3);
+err_relio:
+       pci_release_region(pdev, 2);
+       brd->info = NULL;
+err:
+       return retval;
+}
+
+static void __devexit mxser_remove(struct pci_dev *pdev)
+{
+       struct mxser_board *brd = pci_get_drvdata(pdev);
+       unsigned int i;
+
+       for (i = 0; i < brd->info->nports; i++)
+               tty_unregister_device(mxvar_sdriver, brd->idx + i);
+
+       mxser_release_res(brd, pdev, 1);
+}
+
+static struct pci_driver mxser_driver = {
+       .name = "mxser",
+       .id_table = mxser_pcibrds,
+       .probe = mxser_probe,
+       .remove = __devexit_p(mxser_remove)
+};
+
+static int __init mxser_module_init(void)
+{
+       struct mxser_board *brd;
+       unsigned long cap;
+       unsigned int i, m, isaloop;
+       int retval, b;
+
+       pr_debug("Loading module mxser ...\n");
+
+       mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
+       if (!mxvar_sdriver)
+               return -ENOMEM;
+       spin_lock_init(&gm_lock);
+
+       printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
+               MXSER_VERSION);
+
+       /* Initialize the tty_driver structure */
+       mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
+       mxvar_sdriver->name = "ttyMI";
+       mxvar_sdriver->major = ttymajor;
+       mxvar_sdriver->minor_start = 0;
+       mxvar_sdriver->num = MXSER_PORTS + 1;
+       mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
+       mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
+       mxvar_sdriver->init_termios = tty_std_termios;
+       mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+       mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
+       tty_set_operations(mxvar_sdriver, &mxser_ops);
+
+       retval = tty_register_driver(mxvar_sdriver);
+       if (retval) {
+               printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
+                               "tty driver !\n");
+               goto err_put;
+       }
+
+       mxvar_diagflag = 0;
+
+       m = 0;
+       /* Start finding ISA boards here */
+       for (isaloop = 0; isaloop < 2; isaloop++)
+               for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
+                       if (!isaloop)
+                               cap = mxserBoardCAP[b]; /* predefined */
+                       else
+                               cap = ioaddr[b]; /* module param */
+
+                       if (!cap)
+                               continue;
+
+                       brd = &mxser_boards[m];
+                       retval = mxser_get_ISA_conf(cap, brd);
+
+                       if (retval != 0)
+                               printk(KERN_INFO "Found MOXA %s board "
+                                       "(CAP=0x%x)\n",
+                                       brd->info->name, ioaddr[b]);
+
+                       if (retval <= 0) {
+                               if (retval == MXSER_ERR_IRQ)
+                                       printk(KERN_ERR "Invalid interrupt "
+                                               "number, board not "
+                                               "configured\n");
+                               else if (retval == MXSER_ERR_IRQ_CONFLIT)
+                                       printk(KERN_ERR "Invalid interrupt "
+                                               "number, board not "
+                                               "configured\n");
+                               else if (retval == MXSER_ERR_VECTOR)
+                                       printk(KERN_ERR "Invalid interrupt "
+                                               "vector, board not "
+                                               "configured\n");
+                               else if (retval == MXSER_ERR_IOADDR)
+                                       printk(KERN_ERR "Invalid I/O address, "
+                                               "board not configured\n");
+
+                               brd->info = NULL;
+                               continue;
+                       }
+
+                       /* mxser_initbrd will hook ISR. */
+                       if (mxser_initbrd(brd, NULL) < 0) {
+                               brd->info = NULL;
+                               continue;
+                       }
+
+                       brd->idx = m * MXSER_PORTS_PER_BOARD;
+                       for (i = 0; i < brd->info->nports; i++)
+                               tty_register_device(mxvar_sdriver, brd->idx + i,
+                                               NULL);
+
+                       m++;
+               }
+
+       retval = pci_register_driver(&mxser_driver);
+       if (retval) {
+               printk(KERN_ERR "Can't register pci driver\n");
+               if (!m) {
+                       retval = -ENODEV;
+                       goto err_unr;
+               } /* else: we have some ISA cards under control */
+       }
+
+       pr_debug("Done.\n");
+
+       return 0;
+err_unr:
+       tty_unregister_driver(mxvar_sdriver);
+err_put:
+       put_tty_driver(mxvar_sdriver);
+       return retval;
+}
+
+static void __exit mxser_module_exit(void)
+{
+       unsigned int i, j;
+
+       pr_debug("Unloading module mxser ...\n");
+
+       pci_unregister_driver(&mxser_driver);
+
+       for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
+               if (mxser_boards[i].info != NULL)
+                       for (j = 0; j < mxser_boards[i].info->nports; j++)
+                               tty_unregister_device(mxvar_sdriver,
+                                               mxser_boards[i].idx + j);
+       tty_unregister_driver(mxvar_sdriver);
+       put_tty_driver(mxvar_sdriver);
+
+       for (i = 0; i < MXSER_BOARDS; i++)
+               if (mxser_boards[i].info != NULL)
+                       mxser_release_res(&mxser_boards[i], NULL, 1);
+
+       pr_debug("Done.\n");
+}
+
+module_init(mxser_module_init);
+module_exit(mxser_module_exit);
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h
new file mode 100644 (file)
index 0000000..a08f0ec
--- /dev/null
@@ -0,0 +1,450 @@
+#ifndef _MXSER_H
+#define _MXSER_H
+
+/*
+ *     Semi-public control interfaces
+ */
+
+/*
+ *     MOXA ioctls
+ */
+
+#define MOXA                   0x400
+#define MOXA_GETDATACOUNT      (MOXA + 23)
+#define        MOXA_GET_CONF           (MOXA + 35)
+#define MOXA_DIAGNOSE          (MOXA + 50)
+#define MOXA_CHKPORTENABLE     (MOXA + 60)
+#define MOXA_HighSpeedOn       (MOXA + 61)
+#define MOXA_GET_MAJOR         (MOXA + 63)
+#define MOXA_GET_CUMAJOR       (MOXA + 64)
+#define MOXA_GETMSTATUS                (MOXA + 65)
+#define MOXA_SET_OP_MODE       (MOXA + 66)
+#define MOXA_GET_OP_MODE       (MOXA + 67)
+
+#define RS232_MODE             0
+#define RS485_2WIRE_MODE       1
+#define RS422_MODE             2
+#define RS485_4WIRE_MODE       3
+#define OP_MODE_MASK           3
+// above add by Victor Yu. 01-05-2004
+
+#define TTY_THRESHOLD_THROTTLE  128
+
+#define LO_WATER               (TTY_FLIPBUF_SIZE)
+#define HI_WATER               (TTY_FLIPBUF_SIZE*2*3/4)
+
+// added by James. 03-11-2004.
+#define MOXA_SDS_GETICOUNTER   (MOXA + 68)
+#define MOXA_SDS_RSTICOUNTER   (MOXA + 69)
+// (above) added by James.
+
+#define MOXA_ASPP_OQUEUE       (MOXA + 70)
+#define MOXA_ASPP_SETBAUD      (MOXA + 71)
+#define MOXA_ASPP_GETBAUD      (MOXA + 72)
+#define MOXA_ASPP_MON          (MOXA + 73)
+#define MOXA_ASPP_LSTATUS      (MOXA + 74)
+#define MOXA_ASPP_MON_EXT      (MOXA + 75)
+#define MOXA_SET_BAUD_METHOD   (MOXA + 76)
+
+
+/* --------------------------------------------------- */
+
+#define NPPI_NOTIFY_PARITY     0x01
+#define NPPI_NOTIFY_FRAMING    0x02
+#define NPPI_NOTIFY_HW_OVERRUN 0x04
+#define NPPI_NOTIFY_SW_OVERRUN 0x08
+#define NPPI_NOTIFY_BREAK      0x10
+
+#define NPPI_NOTIFY_CTSHOLD         0x01       // Tx hold by CTS low
+#define NPPI_NOTIFY_DSRHOLD         0x02       // Tx hold by DSR low
+#define NPPI_NOTIFY_XOFFHOLD        0x08       // Tx hold by Xoff received
+#define NPPI_NOTIFY_XOFFXENT        0x10       // Xoff Sent
+
+//CheckIsMoxaMust return value
+#define MOXA_OTHER_UART                        0x00
+#define MOXA_MUST_MU150_HWID           0x01
+#define MOXA_MUST_MU860_HWID           0x02
+
+// follow just for Moxa Must chip define.
+//
+// when LCR register (offset 0x03) write following value,
+// the Must chip will enter enchance mode. And write value
+// on EFR (offset 0x02) bit 6,7 to change bank.
+#define MOXA_MUST_ENTER_ENCHANCE       0xBF
+
+// when enhance mode enable, access on general bank register
+#define MOXA_MUST_GDL_REGISTER         0x07
+#define MOXA_MUST_GDL_MASK             0x7F
+#define MOXA_MUST_GDL_HAS_BAD_DATA     0x80
+
+#define MOXA_MUST_LSR_RERR             0x80    // error in receive FIFO
+// enchance register bank select and enchance mode setting register
+// when LCR register equal to 0xBF
+#define MOXA_MUST_EFR_REGISTER         0x02
+// enchance mode enable
+#define MOXA_MUST_EFR_EFRB_ENABLE      0x10
+// enchance reister bank set 0, 1, 2
+#define MOXA_MUST_EFR_BANK0            0x00
+#define MOXA_MUST_EFR_BANK1            0x40
+#define MOXA_MUST_EFR_BANK2            0x80
+#define MOXA_MUST_EFR_BANK3            0xC0
+#define MOXA_MUST_EFR_BANK_MASK                0xC0
+
+// set XON1 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XON1_REGISTER                0x04
+
+// set XON2 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XON2_REGISTER                0x05
+
+// set XOFF1 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XOFF1_REGISTER       0x06
+
+// set XOFF2 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XOFF2_REGISTER       0x07
+
+#define MOXA_MUST_RBRTL_REGISTER       0x04
+#define MOXA_MUST_RBRTH_REGISTER       0x05
+#define MOXA_MUST_RBRTI_REGISTER       0x06
+#define MOXA_MUST_THRTL_REGISTER       0x07
+#define MOXA_MUST_ENUM_REGISTER                0x04
+#define MOXA_MUST_HWID_REGISTER                0x05
+#define MOXA_MUST_ECR_REGISTER         0x06
+#define MOXA_MUST_CSR_REGISTER         0x07
+
+// good data mode enable
+#define MOXA_MUST_FCR_GDA_MODE_ENABLE  0x20
+// only good data put into RxFIFO
+#define MOXA_MUST_FCR_GDA_ONLY_ENABLE  0x10
+
+// enable CTS interrupt
+#define MOXA_MUST_IER_ECTSI            0x80
+// enable RTS interrupt
+#define MOXA_MUST_IER_ERTSI            0x40
+// enable Xon/Xoff interrupt
+#define MOXA_MUST_IER_XINT             0x20
+// enable GDA interrupt
+#define MOXA_MUST_IER_EGDAI            0x10
+
+#define MOXA_MUST_RECV_ISR             (UART_IER_RDI | MOXA_MUST_IER_EGDAI)
+
+// GDA interrupt pending
+#define MOXA_MUST_IIR_GDA              0x1C
+#define MOXA_MUST_IIR_RDA              0x04
+#define MOXA_MUST_IIR_RTO              0x0C
+#define MOXA_MUST_IIR_LSR              0x06
+
+// recieved Xon/Xoff or specical interrupt pending
+#define MOXA_MUST_IIR_XSC              0x10
+
+// RTS/CTS change state interrupt pending
+#define MOXA_MUST_IIR_RTSCTS           0x20
+#define MOXA_MUST_IIR_MASK             0x3E
+
+#define MOXA_MUST_MCR_XON_FLAG         0x40
+#define MOXA_MUST_MCR_XON_ANY          0x80
+#define MOXA_MUST_MCR_TX_XON           0x08
+
+
+// software flow control on chip mask value
+#define MOXA_MUST_EFR_SF_MASK          0x0F
+// send Xon1/Xoff1
+#define MOXA_MUST_EFR_SF_TX1           0x08
+// send Xon2/Xoff2
+#define MOXA_MUST_EFR_SF_TX2           0x04
+// send Xon1,Xon2/Xoff1,Xoff2
+#define MOXA_MUST_EFR_SF_TX12          0x0C
+// don't send Xon/Xoff
+#define MOXA_MUST_EFR_SF_TX_NO         0x00
+// Tx software flow control mask
+#define MOXA_MUST_EFR_SF_TX_MASK       0x0C
+// don't receive Xon/Xoff
+#define MOXA_MUST_EFR_SF_RX_NO         0x00
+// receive Xon1/Xoff1
+#define MOXA_MUST_EFR_SF_RX1           0x02
+// receive Xon2/Xoff2
+#define MOXA_MUST_EFR_SF_RX2           0x01
+// receive Xon1,Xon2/Xoff1,Xoff2
+#define MOXA_MUST_EFR_SF_RX12          0x03
+// Rx software flow control mask
+#define MOXA_MUST_EFR_SF_RX_MASK       0x03
+
+//#define MOXA_MUST_MIN_XOFFLIMIT               66
+//#define MOXA_MUST_MIN_XONLIMIT                20
+//#define ID1_RX_TRIG                   120
+
+
+#define CHECK_MOXA_MUST_XOFFLIMIT(info) {      \
+       if ( (info)->IsMoxaMustChipFlag &&      \
+        (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) {       \
+               (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT;   \
+               (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT;     \
+       }       \
+}
+
+#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr |= MOXA_MUST_EFR_EFRB_ENABLE;     \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) {      \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;    \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) {      \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK0;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER);    \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) {      \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK0;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER);    \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK0;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK0;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK1;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK1;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK1;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) {     \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK1;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+//#define MOXA_MUST_RBRL_VALUE  4
+#define SET_MOXA_MUST_FIFO_VALUE(info) {       \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((info)->ioaddr+UART_LCR);        \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);        \
+       __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER);     \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK1;   \
+       outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER);     \
+       outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER);     \
+       outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER);        \
+       outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER);      \
+       outb(__oldlcr, (info)->ioaddr+UART_LCR);        \
+}
+
+
+
+#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) {      \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK2;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER);    \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) {       \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
+       __efr |= MOXA_MUST_EFR_BANK2;   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) {       \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {  \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
+       __efr |= MOXA_MUST_EFR_SF_TX1;  \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {    \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;     \
+       __efr |= MOXA_MUST_EFR_SF_TX1;  \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {   \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;     \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {  \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
+       __efr |= MOXA_MUST_EFR_SF_RX1;  \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {    \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;     \
+       __efr |= MOXA_MUST_EFR_SF_RX1;  \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {   \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;     \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
+       u8      __oldlcr, __efr;        \
+       __oldlcr = inb((baseio)+UART_LCR);      \
+       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
+       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
+       __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
+       __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1);   \
+       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
+       outb(__oldlcr, (baseio)+UART_LCR);      \
+}
+
+#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) {        \
+       u8      __oldmcr;       \
+       __oldmcr = inb((baseio)+UART_MCR);      \
+       __oldmcr |= MOXA_MUST_MCR_XON_ANY;      \
+       outb(__oldmcr, (baseio)+UART_MCR);      \
+}
+
+#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) {       \
+       u8      __oldmcr;       \
+       __oldmcr = inb((baseio)+UART_MCR);      \
+       __oldmcr &= ~MOXA_MUST_MCR_XON_ANY;     \
+       outb(__oldmcr, (baseio)+UART_MCR);      \
+}
+
+#define READ_MOXA_MUST_GDL(baseio)     inb((baseio)+MOXA_MUST_GDL_REGISTER)
+
+
+#ifndef INIT_WORK
+#define INIT_WORK(_work, _func, _data){        \
+       _data->tqueue.routine = _func;\
+       _data->tqueue.data = _data;\
+       }
+#endif
+
+#endif
index 203dc2b..103d338 100644 (file)
@@ -142,7 +142,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
                       const unsigned char * buf, size_t nr);
 static int r3964_ioctl(struct tty_struct * tty, struct file * file,
                        unsigned int cmd, unsigned long arg);
-static void r3964_set_termios(struct tty_struct *tty, struct termios * old);
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old);
 static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
                      struct poll_table_struct  *wait);
 static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
@@ -1347,7 +1347,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file,
    }
 }
 
-static void r3964_set_termios(struct tty_struct *tty, struct termios * old)
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old)
 {
    TRACE_L("set_termios");
 }
index 603b9ad..e96a00f 100644 (file)
@@ -994,7 +994,7 @@ int is_ignored(int sig)
  *     when the ldisc is closed.
  */
  
-static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
 {
        if (!tty)
                return;
index 4d47d79..808d44e 100644 (file)
@@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
 ssize_t nsc_gpio_write(struct file *file, const char __user *data,
                       size_t len, loff_t *ppos)
 {
-       unsigned m = iminor(file->f_dentry->d_inode);
+       unsigned m = iminor(file->f_path.dentry->d_inode);
        struct nsc_gpio_ops *amp = file->private_data;
        struct device *dev = amp->dev;
        size_t i;
@@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data,
 ssize_t nsc_gpio_read(struct file *file, char __user * buf,
                      size_t len, loff_t * ppos)
 {
-       unsigned m = iminor(file->f_dentry->d_inode);
+       unsigned m = iminor(file->f_path.dentry->d_inode);
        int value;
        struct nsc_gpio_ops *amp = file->private_data;
 
index f9f7250..5152ced 100644 (file)
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_CS_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -235,7 +237,7 @@ typedef struct _mgslpc_info {
        int dosyncppp;
        spinlock_t netlock;
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 
@@ -392,7 +394,7 @@ static void tx_timeout(unsigned long context);
 
 static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(MGSLPC_INFO *info);
 static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);
@@ -421,7 +423,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id);
 /*
  * Bottom half interrupt handlers
  */
-static void bh_handler(void* Context);
+static void bh_handler(struct work_struct *work);
 static void bh_transmit(MGSLPC_INFO *info);
 static void bh_status(MGSLPC_INFO *info);
 
@@ -547,7 +549,7 @@ static int mgslpc_probe(struct pcmcia_device *link)
 
     memset(info, 0, sizeof(MGSLPC_INFO));
     info->magic = MGSLPC_MAGIC;
-    INIT_WORK(&info->task, bh_handler, info);
+    INIT_WORK(&info->task, bh_handler);
     info->max_frame_size = 4096;
     info->close_delay = 5*HZ/10;
     info->closing_wait = 30*HZ;
@@ -835,9 +837,9 @@ static int bh_action(MGSLPC_INFO *info)
        return rc;
 }
 
-static void bh_handler(void* Context)
+static void bh_handler(struct work_struct *work)
 {
-       MGSLPC_INFO *info = (MGSLPC_INFO*)Context;
+       MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task);
        int action;
 
        if (!info)
@@ -1053,7 +1055,7 @@ static void tx_done(MGSLPC_INFO *info)
                info->drop_rts_on_tx_done = 0;
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else 
@@ -1164,7 +1166,7 @@ static void dcd_change(MGSLPC_INFO *info)
        }
        else
                info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount) {
                if (info->serial_signals & SerialSignal_DCD)
                        netif_carrier_on(info->netdev);
@@ -2373,7 +2375,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
  *     tty             pointer to tty structure
  *     termios         pointer to buffer to hold returned old termios
  */
-static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
        unsigned long flags;
@@ -2953,7 +2955,7 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
        printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",
                info->device_name, info->io_base, info->irq_level);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 }
@@ -2969,7 +2971,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
                                last->next_device = info->next_device;
                        else
                                mgslpc_device_list = info->next_device;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        hdlcdev_exit(info);
 #endif
                        release_resources(info);
@@ -3901,7 +3903,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
                                return_frame = 1;
                }
                framesize = 0;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                {
                        struct net_device_stats *stats = hdlc_stats(info->netdev);
                        stats->rx_errors++;
@@ -3935,7 +3937,7 @@ static int rx_get_frame(MGSLPC_INFO *info)
                                ++framesize;
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info, buf->data, framesize);
                        else
@@ -4091,7 +4093,7 @@ static void tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->lock,flags);
        
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
@@ -4099,7 +4101,7 @@ static void tx_timeout(unsigned long context)
                bh_transmit(info);
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
index c1e3dd8..4abd1ef 100644 (file)
@@ -106,7 +106,7 @@ static inline void pp_enable_irq (struct pp_struct *pp)
 static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
                        loff_t * ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        struct pp_struct *pp = file->private_data;
        char * kbuffer;
        ssize_t bytes_read = 0;
@@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
 static ssize_t pp_write (struct file * file, const char __user * buf,
                         size_t count, loff_t * ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        struct pp_struct *pp = file->private_data;
        char * kbuffer;
        ssize_t bytes_written = 0;
index 80d3eed..c07a1b5 100644 (file)
@@ -218,7 +218,7 @@ out:
        return retval;
 }
 
-static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
         tty->termios->c_cflag &= ~(CSIZE | PARENB);
         tty->termios->c_cflag |= (CS8 | CREAD);
@@ -272,6 +272,8 @@ static void __init legacy_pty_init(void)
        pty_driver->init_termios.c_oflag = 0;
        pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
        pty_driver->init_termios.c_lflag = 0;
+       pty_driver->init_termios.c_ispeed = 38400;
+       pty_driver->init_termios.c_ospeed = 38400;
        pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
        pty_driver->other = pty_slave_driver;
        tty_set_operations(pty_driver, &pty_ops);
@@ -286,6 +288,8 @@ static void __init legacy_pty_init(void)
        pty_slave_driver->subtype = PTY_TYPE_SLAVE;
        pty_slave_driver->init_termios = tty_std_termios;
        pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+       pty_slave_driver->init_termios.c_ispeed = 38400;
+       pty_slave_driver->init_termios.c_ospeed = 38400;
        pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
                                        TTY_DRIVER_REAL_RAW;
        pty_slave_driver->other = pty_driver;
@@ -366,6 +370,8 @@ static void __init unix98_pty_init(void)
        ptm_driver->init_termios.c_oflag = 0;
        ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
        ptm_driver->init_termios.c_lflag = 0;
+       ptm_driver->init_termios.c_ispeed = 38400;
+       ptm_driver->init_termios.c_ospeed = 38400;
        ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
        ptm_driver->other = pts_driver;
@@ -381,6 +387,8 @@ static void __init unix98_pty_init(void)
        pts_driver->subtype = PTY_TYPE_SLAVE;
        pts_driver->init_termios = tty_std_termios;
        pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+       pts_driver->init_termios.c_ispeed = 38400;
+       pts_driver->init_termios.c_ospeed = 38400;
        pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
        pts_driver->other = ptm_driver;
index d40df30..13d0b13 100644 (file)
@@ -1048,7 +1048,7 @@ random_write(struct file * file, const char __user * buffer,
        if (p == buffer) {
                return (ssize_t)ret;
        } else {
-               struct inode *inode = file->f_dentry->d_inode;
+               struct inode *inode = file->f_path.dentry->d_inode;
                inode->i_mtime = current_fs_time(inode->i_sb);
                mark_inode_dirty(inode);
                return (ssize_t)(p - buffer);
@@ -1203,7 +1203,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
 
 static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
                         void __user *oldval, size_t __user *oldlenp,
-                        void __user *newval, size_t newlen, void **context)
+                        void __user *newval, size_t newlen)
 {
        unsigned char tmp_uuid[16], *uuid;
        unsigned int len;
@@ -1422,9 +1422,9 @@ static struct keydata {
 
 static unsigned int ip_cnt;
 
-static void rekey_seq_generator(void *private_);
+static void rekey_seq_generator(struct work_struct *work);
 
-static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
+static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
 
 /*
  * Lock avoidance:
@@ -1438,7 +1438,7 @@ static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
  * happen, and even if that happens only a not perfectly compliant
  * ISN is generated, nothing fatal.
  */
-static void rekey_seq_generator(void *private_)
+static void rekey_seq_generator(struct work_struct *work)
 {
        struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
 
index 3b32313..645e20a 100644 (file)
@@ -75,7 +75,7 @@ static int raw_open(struct inode *inode, struct file *filp)
        filp->f_flags |= O_DIRECT;
        filp->f_mapping = bdev->bd_inode->i_mapping;
        if (++raw_devices[minor].inuse == 1)
-               filp->f_dentry->d_inode->i_mapping =
+               filp->f_path.dentry->d_inode->i_mapping =
                        bdev->bd_inode->i_mapping;
        filp->private_data = bdev;
        mutex_unlock(&raw_mutex);
index 7ac68cb..e79b2ed 100644 (file)
@@ -1026,6 +1026,7 @@ static int __init rio_init(void)
                        found++;
                } else {
                        iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
+                       p->RIOHosts[p->RIONumHosts].Caddr = NULL;
                }
        }
 
@@ -1078,6 +1079,7 @@ static int __init rio_init(void)
                        found++;
                } else {
                        iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
+                       p->RIOHosts[p->RIONumHosts].Caddr = NULL;
                }
 #else
                printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
@@ -1117,8 +1119,10 @@ static int __init rio_init(void)
                                }
                        }
 
-                       if (!okboard)
+                       if (!okboard) {
                                iounmap(hp->Caddr);
+                               hp->Caddr = NULL;
+                       }
                }
        }
 
@@ -1188,6 +1192,8 @@ static void __exit rio_exit(void)
                }
                /* It is safe/allowed to del_timer a non-active timer */
                del_timer(&hp->timer);
+               if (hp->Caddr)
+                       iounmap(hp->Caddr);
                if (hp->Type == RIO_PCI)
                        pci_dev_put(hp->pdev);
        }
index 5ab32b3..e2a94bf 100644 (file)
 static struct riscom_board * IRQ_to_board[16];
 static struct tty_driver *riscom_driver;
 
-static unsigned long baud_table[] =  {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 76800, 0, 
-};
-
 static struct riscom_board rc_board[RC_NBOARD] =  {
        {
                .base   = RC_IOBASE1,
@@ -1516,9 +1511,9 @@ static void rc_start(struct tty_struct * tty)
  *     do_rc_hangup() -> tty->hangup() -> rc_hangup()
  * 
  */
-static void do_rc_hangup(void *private_)
+static void do_rc_hangup(struct work_struct *ugly_api)
 {
-       struct riscom_port      *port = (struct riscom_port *) private_;
+       struct riscom_port      *port = container_of(ugly_api, struct riscom_port, tqueue_hangup);
        struct tty_struct       *tty;
        
        tty = port->tty;
@@ -1544,7 +1539,7 @@ static void rc_hangup(struct tty_struct * tty)
        wake_up_interruptible(&port->open_wait);
 }
 
-static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        unsigned long flags;
@@ -1567,9 +1562,9 @@ static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios
        }
 }
 
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *ugly_api)
 {
-       struct riscom_port      *port = (struct riscom_port *) private_;
+       struct riscom_port      *port = container_of(ugly_api, struct riscom_port, tqueue);
        struct tty_struct       *tty;
        
        if(!(tty = port->tty)) 
@@ -1619,6 +1614,8 @@ static inline int rc_init_drivers(void)
        riscom_driver->init_termios = tty_std_termios;
        riscom_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       riscom_driver->init_termios.c_ispeed = 9600;
+       riscom_driver->init_termios.c_ospeed = 9600;
        riscom_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(riscom_driver, &riscom_ops);
        if ((error = tty_register_driver(riscom_driver)))  {
@@ -1632,8 +1629,8 @@ static inline int rc_init_drivers(void)
        memset(rc_port, 0, sizeof(rc_port));
        for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
                rc_port[i].magic = RISCOM8_MAGIC;
-               INIT_WORK(&rc_port[i].tqueue, do_softint, &rc_port[i]);
-               INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup, &rc_port[i]);
+               INIT_WORK(&rc_port[i].tqueue, do_softint);
+               INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup);
                rc_port[i].close_delay = 50 * HZ/100;
                rc_port[i].closing_wait = 3000 * HZ/100;
                init_waitqueue_head(&rc_port[i].open_wait);
index bac8005..e94a62e 100644 (file)
@@ -712,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
  *  user mode into the driver (exception handler).  *info CD manipulation is spinlock protected.
  */
 static void configure_r_port(struct r_port *info,
-                            struct termios *old_termios)
+                            struct ktermios *old_termios)
 {
        unsigned cflag;
        unsigned long flags;
@@ -1017,7 +1017,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
        /*
         * Info->count is now 1; so it's safe to sleep now.
         */
-       info->session = current->signal->session;
+       info->session = process_session(current);
        info->pgrp = process_group(current);
 
        if ((info->flags & ROCKET_INITIALIZED) == 0) {
@@ -1194,7 +1194,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
 }
 
 static void rp_set_termios(struct tty_struct *tty,
-                          struct termios *old_termios)
+                          struct ktermios *old_termios)
 {
        struct r_port *info = (struct r_port *) tty->driver_data;
        CHANNEL_t *cp;
@@ -2214,7 +2214,7 @@ static int __init init_PCI(int boards_found)
        int count = 0;
 
        /*  Work through the PCI device list, pulling out ours */
-       while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
+       while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
                if (register_PCI(count + boards_found, dev))
                        count++;
        }
@@ -2436,6 +2436,8 @@ static int __init rp_init(void)
        rocket_driver->init_termios = tty_std_termios;
        rocket_driver->init_termios.c_cflag =
            B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       rocket_driver->init_termios.c_ispeed = 9600;
+       rocket_driver->init_termios.c_ospeed = 9600;
 #ifdef ROCKET_SOFT_FLOW
        rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 #endif
index 4217d38..75de5f6 100644 (file)
@@ -695,6 +695,8 @@ static int a2232_init_drivers(void)
        a2232_driver->init_termios = tty_std_termios;
        a2232_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       a2232_driver->init_termios.c_ispeed = 9600;
+       a2232_driver->init_termios.c_ospeed = 9600;
        a2232_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(a2232_driver, &a2232_ops);
        if ((error = tty_register_driver(a2232_driver))) {
index 3af7f09..af50d32 100644 (file)
@@ -706,9 +706,9 @@ cd2401_rx_interrupt(int irq, void *dev_id)
  * had to poll every port to see if that port needed servicing.
  */
 static void
-do_softint(void *private_)
+do_softint(struct work_struct *ugly_api)
 {
-  struct cyclades_port *info = (struct cyclades_port *) private_;
+  struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue);
   struct tty_struct    *tty;
 
     tty = info->tty;
@@ -1695,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
 
 
 static void
-cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
+cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
@@ -2273,7 +2273,7 @@ scrn[1] = '\0';
                info->blocked_open = 0;
                info->default_threshold = 0;
                info->default_timeout = 0;
-               INIT_WORK(&info->tqueue, do_softint, info);
+               INIT_WORK(&info->tqueue, do_softint);
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
                /* info->session */
index c084149..17d54e1 100644 (file)
@@ -765,7 +765,7 @@ static void sonypi_setbluetoothpower(u8 state)
        sonypi_device.bluetooth_power = state;
 }
 
-static void input_keyrelease(void *data)
+static void input_keyrelease(struct work_struct *work)
 {
        struct sonypi_keypress kp;
 
@@ -979,7 +979,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
        }
 
        if (ret > 0) {
-               struct inode *inode = file->f_dentry->d_inode;
+               struct inode *inode = file->f_path.dentry->d_inode;
                inode->i_atime = current_fs_time(inode->i_sb);
        }
 
@@ -1412,7 +1412,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
                        goto err_inpdev_unregister;
                }
 
-               INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
+               INIT_WORK(&sonypi_device.input_work, input_keyrelease);
        }
 
        sonypi_enable(0);
index 7e1bd95..20946f5 100644 (file)
@@ -2261,9 +2261,10 @@ static void sx_start(struct tty_struct * tty)
  *     do_sx_hangup() -> tty->hangup() -> sx_hangup()
  *
  */
-static void do_sx_hangup(void *private_)
+static void do_sx_hangup(struct work_struct *work)
 {
-       struct specialix_port   *port = (struct specialix_port *) private_;
+       struct specialix_port   *port =
+               container_of(work, struct specialix_port, tqueue_hangup);
        struct tty_struct       *tty;
 
        func_enter();
@@ -2310,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty)
 }
 
 
-static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
 {
        struct specialix_port *port = (struct specialix_port *)tty->driver_data;
        unsigned long flags;
@@ -2336,9 +2337,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios
 }
 
 
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *work)
 {
-       struct specialix_port   *port = (struct specialix_port *) private_;
+       struct specialix_port   *port =
+               container_of(work, struct specialix_port, tqueue);
        struct tty_struct       *tty;
 
        func_enter();
@@ -2398,6 +2400,8 @@ static int sx_init_drivers(void)
        specialix_driver->init_termios = tty_std_termios;
        specialix_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       specialix_driver->init_termios.c_ispeed = 9600;
+       specialix_driver->init_termios.c_ospeed = 9600;
        specialix_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(specialix_driver, &sx_ops);
 
@@ -2411,8 +2415,8 @@ static int sx_init_drivers(void)
        memset(sx_port, 0, sizeof(sx_port));
        for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
                sx_port[i].magic = SPECIALIX_MAGIC;
-               INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]);
-               INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]);
+               INIT_WORK(&sx_port[i].tqueue, do_softint);
+               INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup);
                sx_port[i].close_delay = 50 * HZ/100;
                sx_port[i].closing_wait = 3000 * HZ/100;
                init_waitqueue_head(&sx_port[i].open_wait);
@@ -2473,7 +2477,7 @@ static int __init specialix_init(void)
                                i++;
                                continue;
                        }
-                       pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+                       pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
                                                PCI_DEVICE_ID_SPECIALIX_IO8,
                                                pdev);
                        if (!pdev) break;
@@ -2489,6 +2493,9 @@ static int __init specialix_init(void)
                        if (!sx_probe(&sx_board[i]))
                                found ++;
                }
+               /* May exit pci_get sequence early with lots of boards */
+               if (pdev != NULL)
+                       pci_dev_put(pdev);
        }
 #endif
 
index 522e88e..e45113a 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <linux/ctype.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PCI
 #include <linux/pci.h>
-#endif
 
 /*****************************************************************************/
 
 #define        BRD_ECH64PCI    27
 #define        BRD_EASYIOPCI   28
 
-/*
- *     Define a configuration structure to hold the board configuration.
- *     Need to set this up in the code (for now) with the boards that are
- *     to be configured into the system. This is what needs to be modified
- *     when adding/removing/modifying boards. Each line entry in the
- *     stl_brdconf[] array is a board. Each line contains io/irq/memory
- *     ranges for that board (as well as what type of board it is).
- *     Some examples:
- *             { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
- *     This line would configure an EasyIO board (4 or 8, no difference),
- *     at io address 2a0 and irq 10.
- *     Another example:
- *             { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 },
- *     This line will configure an EasyConnection 8/32 board at primary io
- *     address 2a8, secondary io address 280 and irq 12.
- *     Enter as many lines into this array as you want (only the first 4
- *     will actually be used!). Any combination of EasyIO and EasyConnection
- *     boards can be specified. EasyConnection 8/32 boards can share their
- *     secondary io addresses between each other.
- *
- *     NOTE: there is no need to put any entries in this table for PCI
- *     boards. They will be found automatically by the driver - provided
- *     PCI BIOS32 support is compiled into the kernel.
- */
-
-typedef struct {
-       int             brdtype;
+struct stlconf {
+       unsigned int    brdtype;
        int             ioaddr1;
        int             ioaddr2;
        unsigned long   memaddr;
        int             irq;
        int             irqtype;
-} stlconf_t;
-
-static stlconf_t       stl_brdconf[] = {
-       /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
 };
 
-static int     stl_nrbrds = ARRAY_SIZE(stl_brdconf);
+static unsigned int stl_nrbrds;
 
 /*****************************************************************************/
 
@@ -143,20 +113,13 @@ static struct tty_driver  *stl_serial;
  *     with this termios initially. Basically all it defines is a raw port
  *     at 9600, 8 data bits, 1 stop bit.
  */
-static struct termios          stl_deftermios = {
+static struct ktermios         stl_deftermios = {
        .c_cflag        = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
        .c_cc           = INIT_C_CC,
+       .c_ispeed       = 9600,
+       .c_ospeed       = 9600,
 };
 
-/*
- *     Define global stats structures. Not used often, and can be
- *     re-used for each stats call.
- */
-static comstats_t      stl_comstats;
-static combrd_t                stl_brdstats;
-static stlbrd_t                stl_dummybrd;
-static stlport_t       stl_dummyport;
-
 /*
  *     Define global place to put buffer overflow characters.
  */
@@ -164,13 +127,16 @@ static char               stl_unwanted[SC26198_RXFIFOSIZE];
 
 /*****************************************************************************/
 
-static stlbrd_t                *stl_brds[STL_MAXBRDS];
+static DEFINE_MUTEX(stl_brdslock);
+static struct stlbrd           *stl_brds[STL_MAXBRDS];
 
 /*
  *     Per board state flags. Used with the state field of the board struct.
  *     Not really much here!
  */
 #define        BRD_FOUND       0x1
+#define STL_PROBED     0x2
+
 
 /*
  *     Define the port structure istate flags. These set of flags are
@@ -187,32 +153,32 @@ static stlbrd_t           *stl_brds[STL_MAXBRDS];
  *     referencing boards when printing trace and stuff.
  */
 static char    *stl_brdnames[] = {
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
        "EasyIO",
        "EC8/32-AT",
        "EC8/32-MC",
-       (char *) NULL,
-       (char *) NULL,
-       (char *) NULL,
+       NULL,
+       NULL,
+       NULL,
        "EC8/32-PCI",
        "EC8/64-PCI",
        "EasyIO-PCI",
@@ -225,7 +191,7 @@ static char *stl_brdnames[] = {
  *     load line. These allow for easy board definitions, and easy
  *     modification of the io, memory and irq resoucres.
  */
-static int     stl_nargs = 0;
+static unsigned int stl_nargs;
 static char    *board0[4];
 static char    *board1[4];
 static char    *board2[4];
@@ -243,12 +209,10 @@ static char       **stl_brdsp[] = {
  *     parse any module arguments.
  */
 
-typedef struct stlbrdtype {
+static struct {
        char    *name;
        int     type;
-} stlbrdtype_t;
-
-static stlbrdtype_t    stl_brdstr[] = {
+} stl_brdstr[] = {
        { "easyio", BRD_EASYIO },
        { "eio", BRD_EASYIO },
        { "20", BRD_EASYIO },
@@ -282,9 +246,6 @@ static stlbrdtype_t stl_brdstr[] = {
 /*
  *     Define the module agruments.
  */
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
-MODULE_LICENSE("GPL");
 
 module_param_array(board0, charp, &stl_nargs, 0);
 MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
@@ -386,8 +347,6 @@ static spinlock_t stallion_lock;    /* Guard the tty driver */
 
 /*****************************************************************************/
 
-#ifdef CONFIG_PCI
-
 /*
  *     Define the Stallion PCI vendor and device IDs.
  */
@@ -407,22 +366,19 @@ static spinlock_t stallion_lock;  /* Guard the tty driver */
 /*
  *     Define structure to hold all Stallion PCI boards.
  */
-typedef struct stlpcibrd {
-       unsigned short          vendid;
-       unsigned short          devid;
-       int                     brdtype;
-} stlpcibrd_t;
-
-static stlpcibrd_t     stl_pcibrds[] = {
-       { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI },
-       { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI },
-       { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI },
-       { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
-};
 
-static int     stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
-
-#endif
+static struct pci_device_id stl_pcibrds[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
+               .driver_data = BRD_ECH64PCI },
+       { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
+               .driver_data = BRD_EASYIOPCI },
+       { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
+               .driver_data = BRD_ECHPCI },
+       { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
+               .driver_data = BRD_ECHPCI },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, stl_pcibrds);
 
 /*****************************************************************************/
 
@@ -442,134 +398,74 @@ static unsigned int      stl_baudrates[] = {
        9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
 };
 
-/*
- *     Define some handy local macros...
- */
-#undef MIN
-#define        MIN(a,b)        (((a) <= (b)) ? (a) : (b))
-
-#undef TOLOWER
-#define        TOLOWER(x)      ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
-
 /*****************************************************************************/
 
 /*
  *     Declare all those functions in this driver!
  */
 
-static void    stl_argbrds(void);
-static int     stl_parsebrd(stlconf_t *confp, char **argp);
-
-static unsigned long stl_atol(char *str);
-
-static int     stl_init(void);
-static int     stl_open(struct tty_struct *tty, struct file *filp);
-static void    stl_close(struct tty_struct *tty, struct file *filp);
-static int     stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void    stl_putchar(struct tty_struct *tty, unsigned char ch);
-static void    stl_flushchars(struct tty_struct *tty);
-static int     stl_writeroom(struct tty_struct *tty);
-static int     stl_charsinbuffer(struct tty_struct *tty);
-static int     stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void    stl_settermios(struct tty_struct *tty, struct termios *old);
-static void    stl_throttle(struct tty_struct *tty);
-static void    stl_unthrottle(struct tty_struct *tty);
-static void    stl_stop(struct tty_struct *tty);
-static void    stl_start(struct tty_struct *tty);
-static void    stl_flushbuffer(struct tty_struct *tty);
-static void    stl_breakctl(struct tty_struct *tty, int state);
-static void    stl_waituntilsent(struct tty_struct *tty, int timeout);
-static void    stl_sendxchar(struct tty_struct *tty, char ch);
-static void    stl_hangup(struct tty_struct *tty);
 static int     stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
-static int     stl_portinfo(stlport_t *portp, int portnr, char *pos);
-static int     stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);
-
-static int     stl_brdinit(stlbrd_t *brdp);
-static int     stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static int     stl_getserial(stlport_t *portp, struct serial_struct __user *sp);
-static int     stl_setserial(stlport_t *portp, struct serial_struct __user *sp);
-static int     stl_getbrdstats(combrd_t __user *bp);
-static int     stl_getportstats(stlport_t *portp, comstats_t __user *cp);
-static int     stl_clrportstats(stlport_t *portp, comstats_t __user *cp);
-static int     stl_getportstruct(stlport_t __user *arg);
-static int     stl_getbrdstruct(stlbrd_t __user *arg);
-static int     stl_waitcarrier(stlport_t *portp, struct file *filp);
-static int     stl_eiointr(stlbrd_t *brdp);
-static int     stl_echatintr(stlbrd_t *brdp);
-static int     stl_echmcaintr(stlbrd_t *brdp);
-static int     stl_echpciintr(stlbrd_t *brdp);
-static int     stl_echpci64intr(stlbrd_t *brdp);
-static void    stl_offintr(void *private);
-static stlbrd_t *stl_allocbrd(void);
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
-
-static inline int      stl_initbrds(void);
-static inline int      stl_initeio(stlbrd_t *brdp);
-static inline int      stl_initech(stlbrd_t *brdp);
-static inline int      stl_getbrdnr(void);
-
-#ifdef CONFIG_PCI
-static inline int      stl_findpcibrds(void);
-static inline int      stl_initpcibrd(int brdtype, struct pci_dev *devp);
-#endif
+static int     stl_brdinit(struct stlbrd *brdp);
+static int     stl_getportstats(struct stlport *portp, comstats_t __user *cp);
+static int     stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
+static int     stl_waitcarrier(struct stlport *portp, struct file *filp);
 
 /*
  *     CD1400 uart specific handling functions.
  */
-static void    stl_cd1400setreg(stlport_t *portp, int regnr, int value);
-static int     stl_cd1400getreg(stlport_t *portp, int regnr);
-static int     stl_cd1400updatereg(stlport_t *portp, int regnr, int value);
-static int     stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void    stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static void    stl_cd1400setport(stlport_t *portp, struct termios *tiosp);
-static int     stl_cd1400getsignals(stlport_t *portp);
-static void    stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);
-static void    stl_cd1400ccrwait(stlport_t *portp);
-static void    stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);
-static void    stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);
-static void    stl_cd1400disableintrs(stlport_t *portp);
-static void    stl_cd1400sendbreak(stlport_t *portp, int len);
-static void    stl_cd1400flowctrl(stlport_t *portp, int state);
-static void    stl_cd1400sendflow(stlport_t *portp, int state);
-static void    stl_cd1400flush(stlport_t *portp);
-static int     stl_cd1400datastate(stlport_t *portp);
-static void    stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);
-static void    stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);
-static void    stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);
-static void    stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);
-static void    stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);
-
-static inline int      stl_cd1400breakisr(stlport_t *portp, int ioaddr);
+static void    stl_cd1400setreg(struct stlport *portp, int regnr, int value);
+static int     stl_cd1400getreg(struct stlport *portp, int regnr);
+static int     stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
+static int     stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void    stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void    stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
+static int     stl_cd1400getsignals(struct stlport *portp);
+static void    stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
+static void    stl_cd1400ccrwait(struct stlport *portp);
+static void    stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
+static void    stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
+static void    stl_cd1400disableintrs(struct stlport *portp);
+static void    stl_cd1400sendbreak(struct stlport *portp, int len);
+static void    stl_cd1400flowctrl(struct stlport *portp, int state);
+static void    stl_cd1400sendflow(struct stlport *portp, int state);
+static void    stl_cd1400flush(struct stlport *portp);
+static int     stl_cd1400datastate(struct stlport *portp);
+static void    stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
+static void    stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
+static void    stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
+static void    stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
+static void    stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
+
+static inline int      stl_cd1400breakisr(struct stlport *portp, int ioaddr);
 
 /*
  *     SC26198 uart specific handling functions.
  */
-static void    stl_sc26198setreg(stlport_t *portp, int regnr, int value);
-static int     stl_sc26198getreg(stlport_t *portp, int regnr);
-static int     stl_sc26198updatereg(stlport_t *portp, int regnr, int value);
-static int     stl_sc26198getglobreg(stlport_t *portp, int regnr);
-static int     stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void    stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static void    stl_sc26198setport(stlport_t *portp, struct termios *tiosp);
-static int     stl_sc26198getsignals(stlport_t *portp);
-static void    stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);
-static void    stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);
-static void    stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);
-static void    stl_sc26198disableintrs(stlport_t *portp);
-static void    stl_sc26198sendbreak(stlport_t *portp, int len);
-static void    stl_sc26198flowctrl(stlport_t *portp, int state);
-static void    stl_sc26198sendflow(stlport_t *portp, int state);
-static void    stl_sc26198flush(stlport_t *portp);
-static int     stl_sc26198datastate(stlport_t *portp);
-static void    stl_sc26198wait(stlport_t *portp);
-static void    stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty);
-static void    stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);
-static void    stl_sc26198txisr(stlport_t *port);
-static void    stl_sc26198rxisr(stlport_t *port, unsigned int iack);
-static void    stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch);
-static void    stl_sc26198rxbadchars(stlport_t *portp);
-static void    stl_sc26198otherisr(stlport_t *port, unsigned int iack);
+static void    stl_sc26198setreg(struct stlport *portp, int regnr, int value);
+static int     stl_sc26198getreg(struct stlport *portp, int regnr);
+static int     stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
+static int     stl_sc26198getglobreg(struct stlport *portp, int regnr);
+static int     stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void    stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void    stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
+static int     stl_sc26198getsignals(struct stlport *portp);
+static void    stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
+static void    stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
+static void    stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
+static void    stl_sc26198disableintrs(struct stlport *portp);
+static void    stl_sc26198sendbreak(struct stlport *portp, int len);
+static void    stl_sc26198flowctrl(struct stlport *portp, int state);
+static void    stl_sc26198sendflow(struct stlport *portp, int state);
+static void    stl_sc26198flush(struct stlport *portp);
+static int     stl_sc26198datastate(struct stlport *portp);
+static void    stl_sc26198wait(struct stlport *portp);
+static void    stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
+static void    stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
+static void    stl_sc26198txisr(struct stlport *port);
+static void    stl_sc26198rxisr(struct stlport *port, unsigned int iack);
+static void    stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
+static void    stl_sc26198rxbadchars(struct stlport *portp);
+static void    stl_sc26198otherisr(struct stlport *port, unsigned int iack);
 
 /*****************************************************************************/
 
@@ -577,20 +473,20 @@ static void       stl_sc26198otherisr(stlport_t *port, unsigned int iack);
  *     Generic UART support structure.
  */
 typedef struct uart {
-       int     (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp);
-       void    (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-       void    (*setport)(stlport_t *portp, struct termios *tiosp);
-       int     (*getsignals)(stlport_t *portp);
-       void    (*setsignals)(stlport_t *portp, int dtr, int rts);
-       void    (*enablerxtx)(stlport_t *portp, int rx, int tx);
-       void    (*startrxtx)(stlport_t *portp, int rx, int tx);
-       void    (*disableintrs)(stlport_t *portp);
-       void    (*sendbreak)(stlport_t *portp, int len);
-       void    (*flowctrl)(stlport_t *portp, int state);
-       void    (*sendflow)(stlport_t *portp, int state);
-       void    (*flush)(stlport_t *portp);
-       int     (*datastate)(stlport_t *portp);
-       void    (*intr)(stlpanel_t *panelp, unsigned int iobase);
+       int     (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
+       void    (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+       void    (*setport)(struct stlport *portp, struct ktermios *tiosp);
+       int     (*getsignals)(struct stlport *portp);
+       void    (*setsignals)(struct stlport *portp, int dtr, int rts);
+       void    (*enablerxtx)(struct stlport *portp, int rx, int tx);
+       void    (*startrxtx)(struct stlport *portp, int rx, int tx);
+       void    (*disableintrs)(struct stlport *portp);
+       void    (*sendbreak)(struct stlport *portp, int len);
+       void    (*flowctrl)(struct stlport *portp, int state);
+       void    (*sendflow)(struct stlport *portp, int state);
+       void    (*flush)(struct stlport *portp);
+       int     (*datastate)(struct stlport *portp);
+       void    (*intr)(struct stlpanel *panelp, unsigned int iobase);
 } uart_t;
 
 /*
@@ -712,184 +608,35 @@ static const struct file_operations      stl_fsiomem = {
        .ioctl          = stl_memioctl,
 };
 
-/*****************************************************************************/
-
 static struct class *stallion_class;
 
-/*
- *     Loadable module initialization stuff.
- */
-
-static int __init stallion_module_init(void)
-{
-       stl_init();
-       return 0;
-}
-
-/*****************************************************************************/
-
-static void __exit stallion_module_exit(void)
-{
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
-       stlport_t       *portp;
-       int             i, j, k;
-
-#ifdef DEBUG
-       printk("cleanup_module()\n");
-#endif
-
-       printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
-               stl_drvversion);
-
-/*
- *     Free up all allocated resources used by the ports. This includes
- *     memory and interrupts. As part of this process we will also do
- *     a hangup on every open port - to try to flush out any processes
- *     hanging onto ports.
- */
-       i = tty_unregister_driver(stl_serial);
-       put_tty_driver(stl_serial);
-       if (i) {
-               printk("STALLION: failed to un-register tty driver, "
-                       "errno=%d\n", -i);
-               return;
-       }
-       for (i = 0; i < 4; i++)
-               class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-       if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
-               printk("STALLION: failed to un-register serial memory device, "
-                       "errno=%d\n", -i);
-       class_destroy(stallion_class);
-
-       for (i = 0; (i < stl_nrbrds); i++) {
-               if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
-                       continue;
-
-               free_irq(brdp->irq, brdp);
-
-               for (j = 0; (j < STL_MAXPANELS); j++) {
-                       panelp = brdp->panels[j];
-                       if (panelp == (stlpanel_t *) NULL)
-                               continue;
-                       for (k = 0; (k < STL_PORTSPERPANEL); k++) {
-                               portp = panelp->ports[k];
-                               if (portp == (stlport_t *) NULL)
-                                       continue;
-                               if (portp->tty != (struct tty_struct *) NULL)
-                                       stl_hangup(portp->tty);
-                               kfree(portp->tx.buf);
-                               kfree(portp);
-                       }
-                       kfree(panelp);
-               }
-
-               release_region(brdp->ioaddr1, brdp->iosize1);
-               if (brdp->iosize2 > 0)
-                       release_region(brdp->ioaddr2, brdp->iosize2);
-
-               kfree(brdp);
-               stl_brds[i] = (stlbrd_t *) NULL;
-       }
-}
-
-module_init(stallion_module_init);
-module_exit(stallion_module_exit);
-
-/*****************************************************************************/
-
 /*
  *     Check for any arguments passed in on the module load command line.
  */
 
-static void stl_argbrds(void)
-{
-       stlconf_t       conf;
-       stlbrd_t        *brdp;
-       int             i;
-
-#ifdef DEBUG
-       printk("stl_argbrds()\n");
-#endif
-
-       for (i = stl_nrbrds; (i < stl_nargs); i++) {
-               memset(&conf, 0, sizeof(conf));
-               if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
-                       continue;
-               if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
-                       continue;
-               stl_nrbrds = i + 1;
-               brdp->brdnr = i;
-               brdp->brdtype = conf.brdtype;
-               brdp->ioaddr1 = conf.ioaddr1;
-               brdp->ioaddr2 = conf.ioaddr2;
-               brdp->irq = conf.irq;
-               brdp->irqtype = conf.irqtype;
-               stl_brdinit(brdp);
-       }
-}
-
-/*****************************************************************************/
-
-/*
- *     Convert an ascii string number into an unsigned long.
- */
-
-static unsigned long stl_atol(char *str)
-{
-       unsigned long   val;
-       int             base, c;
-       char            *sp;
-
-       val = 0;
-       sp = str;
-       if ((*sp == '0') && (*(sp+1) == 'x')) {
-               base = 16;
-               sp += 2;
-       } else if (*sp == '0') {
-               base = 8;
-               sp++;
-       } else {
-               base = 10;
-       }
-
-       for (; (*sp != 0); sp++) {
-               c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
-               if ((c < 0) || (c >= base)) {
-                       printk("STALLION: invalid argument %s\n", str);
-                       val = 0;
-                       break;
-               }
-               val = (val * base) + c;
-       }
-       return val;
-}
-
 /*****************************************************************************/
 
 /*
  *     Parse the supplied argument string, into the board conf struct.
  */
 
-static int stl_parsebrd(stlconf_t *confp, char **argp)
+static int __init stl_parsebrd(struct stlconf *confp, char **argp)
 {
        char    *sp;
-       int     i;
+       unsigned int i;
 
-#ifdef DEBUG
-       printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
-#endif
+       pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
 
-       if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
+       if ((argp[0] == NULL) || (*argp[0] == 0))
                return 0;
 
-       for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
-               *sp = TOLOWER(*sp);
+       for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
+               *sp = tolower(*sp);
 
-       for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
+       for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
                if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
                        break;
-       }
+
        if (i == ARRAY_SIZE(stl_brdstr)) {
                printk("STALLION: unknown board name, %s?\n", argp[0]);
                return 0;
@@ -898,16 +645,16 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
        confp->brdtype = stl_brdstr[i].type;
 
        i = 1;
-       if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
-               confp->ioaddr1 = stl_atol(argp[i]);
+       if ((argp[i] != NULL) && (*argp[i] != 0))
+               confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
        i++;
        if (confp->brdtype == BRD_ECH) {
-               if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
-                       confp->ioaddr2 = stl_atol(argp[i]);
+               if ((argp[i] != NULL) && (*argp[i] != 0))
+                       confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
                i++;
        }
-       if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
-               confp->irq = stl_atol(argp[i]);
+       if ((argp[i] != NULL) && (*argp[i] != 0))
+               confp->irq = simple_strtoul(argp[i], NULL, 0);
        return 1;
 }
 
@@ -917,14 +664,14 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
  *     Allocate a new board structure. Fill out the basic info in it.
  */
 
-static stlbrd_t *stl_allocbrd(void)
+static struct stlbrd *stl_allocbrd(void)
 {
-       stlbrd_t        *brdp;
+       struct stlbrd   *brdp;
 
-       brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
+       brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
        if (!brdp) {
                printk("STALLION: failed to allocate memory (size=%Zd)\n",
-                       sizeof(stlbrd_t));
+                       sizeof(struct stlbrd));
                return NULL;
        }
 
@@ -936,26 +683,23 @@ static stlbrd_t *stl_allocbrd(void)
 
 static int stl_open(struct tty_struct *tty, struct file *filp)
 {
-       stlport_t       *portp;
-       stlbrd_t        *brdp;
-       unsigned int    minordev;
-       int             brdnr, panelnr, portnr, rc;
-
-#ifdef DEBUG
-       printk("stl_open(tty=%x,filp=%x): device=%s\n", (int) tty,
-               (int) filp, tty->name);
-#endif
+       struct stlport  *portp;
+       struct stlbrd   *brdp;
+       unsigned int    minordev, brdnr, panelnr;
+       int             portnr, rc;
+
+       pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
 
        minordev = tty->index;
        brdnr = MINOR2BRD(minordev);
        if (brdnr >= stl_nrbrds)
                return -ENODEV;
        brdp = stl_brds[brdnr];
-       if (brdp == (stlbrd_t *) NULL)
+       if (brdp == NULL)
                return -ENODEV;
        minordev = MINOR2PORT(minordev);
-       for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
-               if (brdp->panels[panelnr] == (stlpanel_t *) NULL)
+       for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
+               if (brdp->panels[panelnr] == NULL)
                        break;
                if (minordev < brdp->panels[panelnr]->nrports) {
                        portnr = minordev;
@@ -967,7 +711,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
                return -ENODEV;
 
        portp = brdp->panels[panelnr]->ports[portnr];
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return -ENODEV;
 
 /*
@@ -1013,10 +757,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  *     previous opens still in effect. If we are a normal serial device
  *     then also we might have to wait for carrier.
  */
-       if (!(filp->f_flags & O_NONBLOCK)) {
+       if (!(filp->f_flags & O_NONBLOCK))
                if ((rc = stl_waitcarrier(portp, filp)) != 0)
                        return rc;
-       }
+
        portp->flags |= ASYNC_NORMAL_ACTIVE;
 
        return 0;
@@ -1029,14 +773,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  *     maybe because if we are clocal then we don't need to wait...
  */
 
-static int stl_waitcarrier(stlport_t *portp, struct file *filp)
+static int stl_waitcarrier(struct stlport *portp, struct file *filp)
 {
        unsigned long   flags;
        int             rc, doclocal;
 
-#ifdef DEBUG
-       printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp);
-#endif
+       pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
 
        rc = 0;
        doclocal = 0;
@@ -1062,9 +804,8 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
                        break;
                }
                if (((portp->flags & ASYNC_CLOSING) == 0) &&
-                   (doclocal || (portp->sigs & TIOCM_CD))) {
+                   (doclocal || (portp->sigs & TIOCM_CD)))
                        break;
-               }
                if (signal_pending(current)) {
                        rc = -ERESTARTSYS;
                        break;
@@ -1083,17 +824,61 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
 
 /*****************************************************************************/
 
+static void stl_flushbuffer(struct tty_struct *tty)
+{
+       struct stlport  *portp;
+
+       pr_debug("stl_flushbuffer(tty=%p)\n", tty);
+
+       if (tty == NULL)
+               return;
+       portp = tty->driver_data;
+       if (portp == NULL)
+               return;
+
+       stl_flush(portp);
+       tty_wakeup(tty);
+}
+
+/*****************************************************************************/
+
+static void stl_waituntilsent(struct tty_struct *tty, int timeout)
+{
+       struct stlport  *portp;
+       unsigned long   tend;
+
+       pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
+
+       if (tty == NULL)
+               return;
+       portp = tty->driver_data;
+       if (portp == NULL)
+               return;
+
+       if (timeout == 0)
+               timeout = HZ;
+       tend = jiffies + timeout;
+
+       while (stl_datastate(portp)) {
+               if (signal_pending(current))
+                       break;
+               msleep_interruptible(20);
+               if (time_after_eq(jiffies, tend))
+                       break;
+       }
+}
+
+/*****************************************************************************/
+
 static void stl_close(struct tty_struct *tty, struct file *filp)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_close(tty=%x,filp=%x)\n", (int) tty, (int) filp);
-#endif
+       pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
 
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        spin_lock_irqsave(&stallion_lock, flags);
@@ -1136,17 +921,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
        stl_enablerxtx(portp, 0, 0);
        stl_flushbuffer(tty);
        portp->istate = 0;
-       if (portp->tx.buf != (char *) NULL) {
+       if (portp->tx.buf != NULL) {
                kfree(portp->tx.buf);
-               portp->tx.buf = (char *) NULL;
-               portp->tx.head = (char *) NULL;
-               portp->tx.tail = (char *) NULL;
+               portp->tx.buf = NULL;
+               portp->tx.head = NULL;
+               portp->tx.tail = NULL;
        }
        set_bit(TTY_IO_ERROR, &tty->flags);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
-       portp->tty = (struct tty_struct *) NULL;
+       portp->tty = NULL;
 
        if (portp->openwaitcnt) {
                if (portp->close_delay)
@@ -1167,20 +952,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
 
 static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    len, stlen;
        unsigned char   *chbuf;
        char            *head, *tail;
 
-#ifdef DEBUG
-       printk("stl_write(tty=%x,buf=%x,count=%d)\n",
-               (int) tty, (int) buf, count);
-#endif
+       pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
 
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return 0;
-       if (portp->tx.buf == (char *) NULL)
+       if (portp->tx.buf == NULL)
                return 0;
 
 /*
@@ -1201,10 +983,10 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
                stlen = len;
        }
 
-       len = MIN(len, count);
+       len = min(len, (unsigned int)count);
        count = 0;
        while (len > 0) {
-               stlen = MIN(len, stlen);
+               stlen = min(len, stlen);
                memcpy(head, chbuf, stlen);
                len -= stlen;
                chbuf += stlen;
@@ -1227,20 +1009,18 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
 
 static void stl_putchar(struct tty_struct *tty, unsigned char ch)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    len;
        char            *head, *tail;
 
-#ifdef DEBUG
-       printk("stl_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch);
-#endif
+       pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
-       if (portp->tx.buf == (char *) NULL)
+       if (portp->tx.buf == NULL)
                return;
 
        head = portp->tx.head;
@@ -1267,18 +1047,16 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
 
 static void stl_flushchars(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_flushchars(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_flushchars(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
-       if (portp->tx.buf == (char *) NULL)
+       if (portp->tx.buf == NULL)
                return;
 
        stl_startrxtx(portp, -1, 1);
@@ -1288,24 +1066,22 @@ static void stl_flushchars(struct tty_struct *tty)
 
 static int stl_writeroom(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        char            *head, *tail;
 
-#ifdef DEBUG
-       printk("stl_writeroom(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_writeroom(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return 0;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return 0;
-       if (portp->tx.buf == (char *) NULL)
+       if (portp->tx.buf == NULL)
                return 0;
 
        head = portp->tx.head;
        tail = portp->tx.tail;
-       return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
+       return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
 }
 
 /*****************************************************************************/
@@ -1321,20 +1097,18 @@ static int stl_writeroom(struct tty_struct *tty)
 
 static int stl_charsinbuffer(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    size;
        char            *head, *tail;
 
-#ifdef DEBUG
-       printk("stl_charsinbuffer(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return 0;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return 0;
-       if (portp->tx.buf == (char *) NULL)
+       if (portp->tx.buf == NULL)
                return 0;
 
        head = portp->tx.head;
@@ -1351,14 +1125,12 @@ static int stl_charsinbuffer(struct tty_struct *tty)
  *     Generate the serial struct info.
  */
 
-static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
+static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
 {
        struct serial_struct    sio;
-       stlbrd_t                *brdp;
+       struct stlbrd           *brdp;
 
-#ifdef DEBUG
-       printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
-#endif
+       pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
 
        memset(&sio, 0, sizeof(struct serial_struct));
        sio.line = portp->portnr;
@@ -1378,7 +1150,7 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
        }
 
        brdp = stl_brds[portp->brdnr];
-       if (brdp != (stlbrd_t *) NULL)
+       if (brdp != NULL)
                sio.irq = brdp->irq;
 
        return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
@@ -1392,13 +1164,11 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
  *     just quietly ignore any requests to change irq, etc.
  */
 
-static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
+static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
 {
        struct serial_struct    sio;
 
-#ifdef DEBUG
-       printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
-#endif
+       pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
 
        if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
                return -EFAULT;
@@ -1424,12 +1194,12 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
 
 static int stl_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return -ENODEV;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
@@ -1440,13 +1210,13 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
 static int stl_tiocmset(struct tty_struct *tty, struct file *file,
                        unsigned int set, unsigned int clear)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        int rts = -1, dtr = -1;
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return -ENODEV;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
@@ -1466,27 +1236,24 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
 
 static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    ival;
        int             rc;
        void __user *argp = (void __user *)arg;
 
-#ifdef DEBUG
-       printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n",
-               (int) tty, (int) file, cmd, (int) arg);
-#endif
+       pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
+                       arg);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return -ENODEV;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
+           (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
                if (tty->flags & (1 << TTY_IO_ERROR))
                        return -EIO;
-       }
 
        rc = 0;
 
@@ -1531,19 +1298,37 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
 
 /*****************************************************************************/
 
-static void stl_settermios(struct tty_struct *tty, struct termios *old)
+/*
+ *     Start the transmitter again. Just turn TX interrupts back on.
+ */
+
+static void stl_start(struct tty_struct *tty)
 {
-       stlport_t       *portp;
-       struct termios  *tiosp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old);
-#endif
+       pr_debug("stl_start(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
+               return;
+       stl_startrxtx(portp, -1, 1);
+}
+
+/*****************************************************************************/
+
+static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
+{
+       struct stlport  *portp;
+       struct ktermios *tiosp;
+
+       pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
+
+       if (tty == NULL)
+               return;
+       portp = tty->driver_data;
+       if (portp == NULL)
                return;
 
        tiosp = tty->termios;
@@ -1571,16 +1356,14 @@ static void stl_settermios(struct tty_struct *tty, struct termios *old)
 
 static void stl_throttle(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_throttle(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_throttle(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        stl_flowctrl(portp, 0);
 }
@@ -1593,16 +1376,14 @@ static void stl_throttle(struct tty_struct *tty)
 
 static void stl_unthrottle(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_unthrottle(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_unthrottle(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        stl_flowctrl(portp, 1);
 }
@@ -1616,44 +1397,20 @@ static void stl_unthrottle(struct tty_struct *tty)
 
 static void stl_stop(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_stop(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_stop(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        stl_startrxtx(portp, -1, 0);
 }
 
 /*****************************************************************************/
 
-/*
- *     Start the transmitter again. Just turn TX interrupts back on.
- */
-
-static void stl_start(struct tty_struct *tty)
-{
-       stlport_t       *portp;
-
-#ifdef DEBUG
-       printk("stl_start(tty=%x)\n", (int) tty);
-#endif
-
-       if (tty == (struct tty_struct *) NULL)
-               return;
-       portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
-               return;
-       stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
 /*
  *     Hangup this port. This is pretty much like closing the port, only
  *     a little more brutal. No waiting for data to drain. Shutdown the
@@ -1662,16 +1419,14 @@ static void stl_start(struct tty_struct *tty)
 
 static void stl_hangup(struct tty_struct *tty)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_hangup(tty=%x)\n", (int) tty);
-#endif
+       pr_debug("stl_hangup(tty=%p)\n", tty);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        portp->flags &= ~ASYNC_INITIALIZED;
@@ -1682,13 +1437,13 @@ static void stl_hangup(struct tty_struct *tty)
        stl_flushbuffer(tty);
        portp->istate = 0;
        set_bit(TTY_IO_ERROR, &tty->flags);
-       if (portp->tx.buf != (char *) NULL) {
+       if (portp->tx.buf != NULL) {
                kfree(portp->tx.buf);
-               portp->tx.buf = (char *) NULL;
-               portp->tx.head = (char *) NULL;
-               portp->tx.tail = (char *) NULL;
+               portp->tx.buf = NULL;
+               portp->tx.head = NULL;
+               portp->tx.tail = NULL;
        }
-       portp->tty = (struct tty_struct *) NULL;
+       portp->tty = NULL;
        portp->flags &= ~ASYNC_NORMAL_ACTIVE;
        portp->refcount = 0;
        wake_up_interruptible(&portp->open_wait);
@@ -1696,38 +1451,16 @@ static void stl_hangup(struct tty_struct *tty)
 
 /*****************************************************************************/
 
-static void stl_flushbuffer(struct tty_struct *tty)
-{
-       stlport_t       *portp;
-
-#ifdef DEBUG
-       printk("stl_flushbuffer(tty=%x)\n", (int) tty);
-#endif
-
-       if (tty == (struct tty_struct *) NULL)
-               return;
-       portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
-               return;
-
-       stl_flush(portp);
-       tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
 static void stl_breakctl(struct tty_struct *tty, int state)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state);
-#endif
+       pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        stl_sendbreak(portp, ((state == -1) ? 1 : 2));
@@ -1735,48 +1468,16 @@ static void stl_breakctl(struct tty_struct *tty, int state)
 
 /*****************************************************************************/
 
-static void stl_waituntilsent(struct tty_struct *tty, int timeout)
-{
-       stlport_t       *portp;
-       unsigned long   tend;
-
-#ifdef DEBUG
-       printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout);
-#endif
-
-       if (tty == (struct tty_struct *) NULL)
-               return;
-       portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
-               return;
-
-       if (timeout == 0)
-               timeout = HZ;
-       tend = jiffies + timeout;
-
-       while (stl_datastate(portp)) {
-               if (signal_pending(current))
-                       break;
-               msleep_interruptible(20);
-               if (time_after_eq(jiffies, tend))
-                       break;
-       }
-}
-
-/*****************************************************************************/
-
 static void stl_sendxchar(struct tty_struct *tty, char ch)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
 
-#ifdef DEBUG
-       printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);
-#endif
+       pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
        portp = tty->driver_data;
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        if (ch == STOP_CHAR(tty))
@@ -1797,7 +1498,7 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
  *     short then padded with spaces).
  */
 
-static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
+static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
 {
        char    *sp;
        int     sigs, cnt;
@@ -1826,7 +1527,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
        *sp = ' ';
        sp += cnt;
 
-       for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
+       for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
                *sp++ = ' ';
        if (cnt >= MAXLINE)
                pos[(MAXLINE - 2)] = '+';
@@ -1843,18 +1544,15 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
 
 static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
-       stlport_t       *portp;
-       int             brdnr, panelnr, portnr, totalport;
-       int             curoff, maxoff;
+       struct stlbrd   *brdp;
+       struct stlpanel *panelp;
+       struct stlport  *portp;
+       unsigned int    brdnr, panelnr, portnr;
+       int             totalport, curoff, maxoff;
        char            *pos;
 
-#ifdef DEBUG
-       printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"
-               "data=%x\n", (int) page, (int) start, (int) off, count,
-               (int) eof, (int) data);
-#endif
+       pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
+               "data=%p\n", page, start, off, count, eof, data);
 
        pos = page;
        totalport = 0;
@@ -1873,9 +1571,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
  *     We scan through for each board, panel and port. The offset is
  *     calculated on the fly, and irrelevant ports are skipped.
  */
-       for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
+       for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
                brdp = stl_brds[brdnr];
-               if (brdp == (stlbrd_t *) NULL)
+               if (brdp == NULL)
                        continue;
                if (brdp->state == 0)
                        continue;
@@ -1887,9 +1585,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
                }
 
                totalport = brdnr * STL_MAXPORTS;
-               for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
+               for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
                        panelp = brdp->panels[panelnr];
-                       if (panelp == (stlpanel_t *) NULL)
+                       if (panelp == NULL)
                                continue;
 
                        maxoff = curoff + (panelp->nrports * MAXLINE);
@@ -1899,10 +1597,10 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
                                continue;
                        }
 
-                       for (portnr = 0; (portnr < panelp->nrports); portnr++,
+                       for (portnr = 0; portnr < panelp->nrports; portnr++,
                            totalport++) {
                                portp = panelp->ports[portnr];
-                               if (portp == (stlport_t *) NULL)
+                               if (portp == NULL)
                                        continue;
                                if (off >= (curoff += MAXLINE))
                                        continue;
@@ -1917,7 +1615,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
 
 stl_readdone:
        *start = page;
-       return (pos - page);
+       return pos - page;
 }
 
 /*****************************************************************************/
@@ -1929,11 +1627,9 @@ stl_readdone:
 
 static irqreturn_t stl_intr(int irq, void *dev_id)
 {
-       stlbrd_t        *brdp = (stlbrd_t *) dev_id;
+       struct stlbrd *brdp = dev_id;
 
-#ifdef DEBUG
-       printk("stl_intr(brdp=%x,irq=%d)\n", (int) brdp, irq);
-#endif
+       pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
 
        return IRQ_RETVAL((* brdp->isr)(brdp));
 }
@@ -1944,9 +1640,9 @@ static irqreturn_t stl_intr(int irq, void *dev_id)
  *     Interrupt service routine for EasyIO board types.
  */
 
-static int stl_eiointr(stlbrd_t *brdp)
+static int stl_eiointr(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
+       struct stlpanel *panelp;
        unsigned int    iobase;
        int             handled = 0;
 
@@ -1967,18 +1663,17 @@ static int stl_eiointr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-AT board types.
  */
 
-static int stl_echatintr(stlbrd_t *brdp)
+static int stl_echatintr(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
-       unsigned int    ioaddr;
-       int             bnknr;
+       struct stlpanel *panelp;
+       unsigned int    ioaddr, bnknr;
        int             handled = 0;
 
        outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
 
        while (inb(brdp->iostatus) & ECH_INTRPEND) {
                handled = 1;
-               for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+               for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
                                panelp = brdp->bnk2panel[bnknr];
@@ -1998,16 +1693,15 @@ static int stl_echatintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-MCA board types.
  */
 
-static int stl_echmcaintr(stlbrd_t *brdp)
+static int stl_echmcaintr(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
-       unsigned int    ioaddr;
-       int             bnknr;
+       struct stlpanel *panelp;
+       unsigned int    ioaddr, bnknr;
        int             handled = 0;
 
        while (inb(brdp->iostatus) & ECH_INTRPEND) {
                handled = 1;
-               for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+               for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
                                panelp = brdp->bnk2panel[bnknr];
@@ -2024,16 +1718,15 @@ static int stl_echmcaintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-PCI board types.
  */
 
-static int stl_echpciintr(stlbrd_t *brdp)
+static int stl_echpciintr(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
-       unsigned int    ioaddr;
-       int             bnknr, recheck;
+       struct stlpanel *panelp;
+       unsigned int    ioaddr, bnknr, recheck;
        int             handled = 0;
 
        while (1) {
                recheck = 0;
-               for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+               for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
                        outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2055,16 +1748,15 @@ static int stl_echpciintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-8/64-PCI board types.
  */
 
-static int stl_echpci64intr(stlbrd_t *brdp)
+static int stl_echpci64intr(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
-       unsigned int    ioaddr;
-       int             bnknr;
+       struct stlpanel *panelp;
+       unsigned int    ioaddr, bnknr;
        int             handled = 0;
 
        while (inb(brdp->ioctrl) & 0x1) {
                handled = 1;
-               for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+               for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
                                panelp = brdp->bnk2panel[bnknr];
@@ -2081,39 +1773,34 @@ static int stl_echpci64intr(stlbrd_t *brdp)
 /*
  *     Service an off-level request for some channel.
  */
-static void stl_offintr(void *private)
+static void stl_offintr(struct work_struct *work)
 {
-       stlport_t               *portp;
+       struct stlport          *portp = container_of(work, struct stlport, tqueue);
        struct tty_struct       *tty;
        unsigned int            oldsigs;
 
-       portp = private;
-
-#ifdef DEBUG
-       printk("stl_offintr(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_offintr(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        tty = portp->tty;
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
 
        lock_kernel();
-       if (test_bit(ASYI_TXLOW, &portp->istate)) {
+       if (test_bit(ASYI_TXLOW, &portp->istate))
                tty_wakeup(tty);
-       }
+
        if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
                clear_bit(ASYI_DCDCHANGE, &portp->istate);
                oldsigs = portp->sigs;
                portp->sigs = stl_getsignals(portp);
                if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
                        wake_up_interruptible(&portp->open_wait);
-               if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
+               if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
                        if (portp->flags & ASYNC_CHECK_CD)
                                tty_hangup(tty);        /* FIXME: module removal race here - AKPM */
-               }
        }
        unlock_kernel();
 }
@@ -2124,14 +1811,13 @@ static void stl_offintr(void *private)
  *     Initialize all the ports on a panel.
  */
 
-static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
+static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
 {
-       stlport_t       *portp;
-       int             chipmask, i;
+       struct stlport *portp;
+       unsigned int i;
+       int chipmask;
 
-#ifdef DEBUG
-       printk("stl_initports(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
-#endif
+       pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
 
        chipmask = stl_panelinit(brdp, panelp);
 
@@ -2139,11 +1825,11 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
  *     All UART's are initialized (if found!). Now go through and setup
  *     each ports data structures.
  */
-       for (i = 0; (i < panelp->nrports); i++) {
-               portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
+       for (i = 0; i < panelp->nrports; i++) {
+               portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
                if (!portp) {
                        printk("STALLION: failed to allocate memory "
-                               "(size=%Zd)\n", sizeof(stlport_t));
+                               "(size=%Zd)\n", sizeof(struct stlport));
                        break;
                }
 
@@ -2156,7 +1842,7 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
                portp->baud_base = STL_BAUDBASE;
                portp->close_delay = STL_CLOSEDELAY;
                portp->closing_wait = 30 * HZ;
-               INIT_WORK(&portp->tqueue, stl_offintr, portp);
+               INIT_WORK(&portp->tqueue, stl_offintr);
                init_waitqueue_head(&portp->open_wait);
                init_waitqueue_head(&portp->close_wait);
                portp->stats.brd = portp->brdnr;
@@ -2166,7 +1852,30 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
                stl_portinit(brdp, panelp, portp);
        }
 
-       return(0);
+       return 0;
+}
+
+static void stl_cleanup_panels(struct stlbrd *brdp)
+{
+       struct stlpanel *panelp;
+       struct stlport *portp;
+       unsigned int j, k;
+
+       for (j = 0; j < STL_MAXPANELS; j++) {
+               panelp = brdp->panels[j];
+               if (panelp == NULL)
+                       continue;
+               for (k = 0; k < STL_PORTSPERPANEL; k++) {
+                       portp = panelp->ports[k];
+                       if (portp == NULL)
+                               continue;
+                       if (portp->tty != NULL)
+                               stl_hangup(portp->tty);
+                       kfree(portp->tx.buf);
+                       kfree(portp);
+               }
+               kfree(panelp);
+       }
 }
 
 /*****************************************************************************/
@@ -2175,16 +1884,14 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
  *     Try to find and initialize an EasyIO board.
  */
 
-static inline int stl_initeio(stlbrd_t *brdp)
+static int __devinit stl_initeio(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
+       struct stlpanel *panelp;
        unsigned int    status;
        char            *name;
-       int             rc;
+       int             retval;
 
-#ifdef DEBUG
-       printk("stl_initeio(brdp=%x)\n", (int) brdp);
-#endif
+       pr_debug("stl_initeio(brdp=%p)\n", brdp);
 
        brdp->ioctrl = brdp->ioaddr1 + 1;
        brdp->iostatus = brdp->ioaddr1 + 2;
@@ -2209,18 +1916,20 @@ static inline int stl_initeio(stlbrd_t *brdp)
                    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
                        printk("STALLION: invalid irq=%d for brd=%d\n",
                                brdp->irq, brdp->brdnr);
-                       return(-EINVAL);
+                       retval = -EINVAL;
+                       goto err;
                }
                outb((stl_vecmap[brdp->irq] | EIO_0WS |
                        ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
                        brdp->ioctrl);
        }
 
+       retval = -EBUSY;
        if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
                printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
                        "%x conflicts with another device\n", brdp->brdnr, 
                        brdp->ioaddr1);
-               return(-EBUSY);
+               goto err;
        }
        
        if (brdp->iosize2 > 0)
@@ -2231,8 +1940,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
                        printk(KERN_WARNING "STALLION: Warning, also "
                                "releasing board %d I/O address %x \n", 
                                brdp->brdnr, brdp->ioaddr1);
-                       release_region(brdp->ioaddr1, brdp->iosize1);
-                       return(-EBUSY);
+                       goto err_rel1;
                }
 
 /*
@@ -2241,6 +1949,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
        brdp->clk = CD1400_CLK;
        brdp->isr = stl_eiointr;
 
+       retval = -ENODEV;
        switch (status & EIO_IDBITMASK) {
        case EIO_8PORTM:
                brdp->clk = CD1400_CLK8M;
@@ -2264,11 +1973,11 @@ static inline int stl_initeio(stlbrd_t *brdp)
                        brdp->nrports = 16;
                        break;
                default:
-                       return(-ENODEV);
+                       goto err_rel2;
                }
                break;
        default:
-               return(-ENODEV);
+               goto err_rel2;
        }
 
 /*
@@ -2276,11 +1985,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
  *     can complete the setup.
  */
 
-       panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+       panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
        if (!panelp) {
                printk(KERN_WARNING "STALLION: failed to allocate memory "
-                       "(size=%Zd)\n", sizeof(stlpanel_t));
-               return -ENOMEM;
+                       "(size=%Zd)\n", sizeof(struct stlpanel));
+               retval = -ENOMEM;
+               goto err_rel2;
        }
 
        panelp->magic = STL_PANELMAGIC;
@@ -2290,10 +2000,10 @@ static inline int stl_initeio(stlbrd_t *brdp)
        panelp->iobase = brdp->ioaddr1;
        panelp->hwid = status;
        if ((status & EIO_IDBITMASK) == EIO_MK3) {
-               panelp->uartp = (void *) &stl_sc26198uart;
+               panelp->uartp = &stl_sc26198uart;
                panelp->isr = stl_sc26198intr;
        } else {
-               panelp->uartp = (void *) &stl_cd1400uart;
+               panelp->uartp = &stl_cd1400uart;
                panelp->isr = stl_cd1400eiointr;
        }
 
@@ -2304,11 +2014,20 @@ static inline int stl_initeio(stlbrd_t *brdp)
        if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
                printk("STALLION: failed to register interrupt "
                    "routine for %s irq=%d\n", name, brdp->irq);
-               rc = -ENODEV;
-       } else {
-               rc = 0;
+               retval = -ENODEV;
+               goto err_fr;
        }
-       return rc;
+
+       return 0;
+err_fr:
+       stl_cleanup_panels(brdp);
+err_rel2:
+       if (brdp->iosize2 > 0)
+               release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+       release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -2318,16 +2037,14 @@ static inline int stl_initeio(stlbrd_t *brdp)
  *     dealing with all types of ECH board.
  */
 
-static inline int stl_initech(stlbrd_t *brdp)
+static int __devinit stl_initech(struct stlbrd *brdp)
 {
-       stlpanel_t      *panelp;
-       unsigned int    status, nxtid, ioaddr, conflict;
-       int             panelnr, banknr, i;
+       struct stlpanel *panelp;
+       unsigned int    status, nxtid, ioaddr, conflict, panelnr, banknr, i;
+       int             retval;
        char            *name;
 
-#ifdef DEBUG
-       printk("stl_initech(brdp=%x)\n", (int) brdp);
-#endif
+       pr_debug("stl_initech(brdp=%p)\n", brdp);
 
        status = 0;
        conflict = 0;
@@ -2344,20 +2061,23 @@ static inline int stl_initech(stlbrd_t *brdp)
                brdp->ioctrl = brdp->ioaddr1 + 1;
                brdp->iostatus = brdp->ioaddr1 + 1;
                status = inb(brdp->iostatus);
-               if ((status & ECH_IDBITMASK) != ECH_ID)
-                       return(-ENODEV);
+               if ((status & ECH_IDBITMASK) != ECH_ID) {
+                       retval = -ENODEV;
+                       goto err;
+               }
                if ((brdp->irq < 0) || (brdp->irq > 15) ||
                    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
                        printk("STALLION: invalid irq=%d for brd=%d\n",
                                brdp->irq, brdp->brdnr);
-                       return(-EINVAL);
+                       retval = -EINVAL;
+                       goto err;
                }
                status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
                status |= (stl_vecmap[brdp->irq] << 1);
                outb((status | ECH_BRDRESET), brdp->ioaddr1);
                brdp->ioctrlval = ECH_INTENABLE |
                        ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
-               for (i = 0; (i < 10); i++)
+               for (i = 0; i < 10; i++)
                        outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
                brdp->iosize1 = 2;
                brdp->iosize2 = 32;
@@ -2370,13 +2090,16 @@ static inline int stl_initech(stlbrd_t *brdp)
                brdp->ioctrl = brdp->ioaddr1 + 0x20;
                brdp->iostatus = brdp->ioctrl;
                status = inb(brdp->iostatus);
-               if ((status & ECH_IDBITMASK) != ECH_ID)
-                       return(-ENODEV);
+               if ((status & ECH_IDBITMASK) != ECH_ID) {
+                       retval = -ENODEV;
+                       goto err;
+               }
                if ((brdp->irq < 0) || (brdp->irq > 15) ||
                    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
                        printk("STALLION: invalid irq=%d for brd=%d\n",
                                brdp->irq, brdp->brdnr);
-                       return(-EINVAL);
+                       retval = -EINVAL;
+                       goto err;
                }
                outb(ECHMC_BRDRESET, brdp->ioctrl);
                outb(ECHMC_INTENABLE, brdp->ioctrl);
@@ -2403,19 +2126,20 @@ static inline int stl_initech(stlbrd_t *brdp)
 
        default:
                printk("STALLION: unknown board type=%d\n", brdp->brdtype);
-               return(-EINVAL);
-               break;
+               retval = -EINVAL;
+               goto err;
        }
 
 /*
  *     Check boards for possible IO address conflicts and return fail status 
  *     if an IO conflict found.
  */
+       retval = -EBUSY;
        if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
                printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
                        "%x conflicts with another device\n", brdp->brdnr, 
                        brdp->ioaddr1);
-               return(-EBUSY);
+               goto err;
        }
        
        if (brdp->iosize2 > 0)
@@ -2426,8 +2150,7 @@ static inline int stl_initech(stlbrd_t *brdp)
                        printk(KERN_WARNING "STALLION: Warning, also "
                                "releasing board %d I/O address %x \n", 
                                brdp->brdnr, brdp->ioaddr1);
-                       release_region(brdp->ioaddr1, brdp->iosize1);
-                       return(-EBUSY);
+                       goto err_rel1;
                }
 
 /*
@@ -2442,19 +2165,19 @@ static inline int stl_initech(stlbrd_t *brdp)
        panelnr = 0;
        nxtid = 0;
 
-       for (i = 0; (i < STL_MAXPANELS); i++) {
+       for (i = 0; i < STL_MAXPANELS; i++) {
                if (brdp->brdtype == BRD_ECHPCI) {
                        outb(nxtid, brdp->ioctrl);
                        ioaddr = brdp->ioaddr2;
                }
                status = inb(ioaddr + ECH_PNLSTATUS);
                if ((status & ECH_PNLIDMASK) != nxtid)
-                       break;
-               panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+                       goto err_fr;
+               panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
                if (!panelp) {
                        printk("STALLION: failed to allocate memory "
-                               "(size=%Zd)\n", sizeof(stlpanel_t));
-                       break;
+                               "(size=%Zd)\n", sizeof(struct stlpanel));
+                       goto err_fr;
                }
                panelp->magic = STL_PANELMAGIC;
                panelp->brdnr = brdp->brdnr;
@@ -2467,7 +2190,7 @@ static inline int stl_initech(stlbrd_t *brdp)
                brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
 
                if (status & ECH_PNLXPID) {
-                       panelp->uartp = (void *) &stl_sc26198uart;
+                       panelp->uartp = &stl_sc26198uart;
                        panelp->isr = stl_sc26198intr;
                        if (status & ECH_PNL16PORT) {
                                panelp->nrports = 16;
@@ -2475,11 +2198,10 @@ static inline int stl_initech(stlbrd_t *brdp)
                                brdp->bnkpageaddr[banknr] = nxtid;
                                brdp->bnkstataddr[banknr++] = ioaddr + 4 +
                                        ECH_PNLSTATUS;
-                       } else {
+                       } else
                                panelp->nrports = 8;
-                       }
                } else {
-                       panelp->uartp = (void *) &stl_cd1400uart;
+                       panelp->uartp = &stl_cd1400uart;
                        panelp->isr = stl_cd1400echintr;
                        if (status & ECH_PNL16PORT) {
                                panelp->nrports = 16;
@@ -2502,7 +2224,7 @@ static inline int stl_initech(stlbrd_t *brdp)
                brdp->panels[panelnr++] = panelp;
                if ((brdp->brdtype != BRD_ECHPCI) &&
                    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
-                       break;
+                       goto err_fr;
        }
 
        brdp->nrpanels = panelnr;
@@ -2514,12 +2236,19 @@ static inline int stl_initech(stlbrd_t *brdp)
        if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
                printk("STALLION: failed to register interrupt "
                    "routine for %s irq=%d\n", name, brdp->irq);
-               i = -ENODEV;
-       } else {
-               i = 0;
+               retval = -ENODEV;
+               goto err_fr;
        }
 
-       return(i);
+       return 0;
+err_fr:
+       stl_cleanup_panels(brdp);
+       if (brdp->iosize2 > 0)
+               release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+       release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -2531,48 +2260,61 @@ static inline int stl_initech(stlbrd_t *brdp)
  *     since the initial search and setup is very different.
  */
 
-static int __init stl_brdinit(stlbrd_t *brdp)
+static int __devinit stl_brdinit(struct stlbrd *brdp)
 {
-       int     i;
+       int i, retval;
 
-#ifdef DEBUG
-       printk("stl_brdinit(brdp=%x)\n", (int) brdp);
-#endif
+       pr_debug("stl_brdinit(brdp=%p)\n", brdp);
 
        switch (brdp->brdtype) {
        case BRD_EASYIO:
        case BRD_EASYIOPCI:
-               stl_initeio(brdp);
+               retval = stl_initeio(brdp);
+               if (retval)
+                       goto err;
                break;
        case BRD_ECH:
        case BRD_ECHMC:
        case BRD_ECHPCI:
        case BRD_ECH64PCI:
-               stl_initech(brdp);
+               retval = stl_initech(brdp);
+               if (retval)
+                       goto err;
                break;
        default:
                printk("STALLION: board=%d is unknown board type=%d\n",
                        brdp->brdnr, brdp->brdtype);
-               return(ENODEV);
+               retval = -ENODEV;
+               goto err;
        }
 
-       stl_brds[brdp->brdnr] = brdp;
        if ((brdp->state & BRD_FOUND) == 0) {
                printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
                        stl_brdnames[brdp->brdtype], brdp->brdnr,
                        brdp->ioaddr1, brdp->irq);
-               return(ENODEV);
+               goto err_free;
        }
 
-       for (i = 0; (i < STL_MAXPANELS); i++)
-               if (brdp->panels[i] != (stlpanel_t *) NULL)
+       for (i = 0; i < STL_MAXPANELS; i++)
+               if (brdp->panels[i] != NULL)
                        stl_initports(brdp, brdp->panels[i]);
 
        printk("STALLION: %s found, board=%d io=%x irq=%d "
                "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
                brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
                brdp->nrports);
-       return(0);
+
+       return 0;
+err_free:
+       free_irq(brdp->irq, brdp);
+
+       stl_cleanup_panels(brdp);
+
+       release_region(brdp->ioaddr1, brdp->iosize1);
+       if (brdp->iosize2 > 0)
+               release_region(brdp->ioaddr2, brdp->iosize2);
+err:
+       return retval;
 }
 
 /*****************************************************************************/
@@ -2581,59 +2323,62 @@ static int __init stl_brdinit(stlbrd_t *brdp)
  *     Find the next available board number that is free.
  */
 
-static inline int stl_getbrdnr(void)
+static int __devinit stl_getbrdnr(void)
 {
-       int     i;
+       unsigned int i;
 
-       for (i = 0; (i < STL_MAXBRDS); i++) {
-               if (stl_brds[i] == (stlbrd_t *) NULL) {
+       for (i = 0; i < STL_MAXBRDS; i++)
+               if (stl_brds[i] == NULL) {
                        if (i >= stl_nrbrds)
                                stl_nrbrds = i + 1;
-                       return(i);
+                       return i;
                }
-       }
-       return(-1);
+
+       return -1;
 }
 
 /*****************************************************************************/
-
-#ifdef CONFIG_PCI
-
 /*
  *     We have a Stallion board. Allocate a board structure and
  *     initialize it. Read its IO and IRQ resources from PCI
  *     configuration space.
  */
 
-static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
+static int __devinit stl_pciprobe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
 {
-       stlbrd_t        *brdp;
-
-#ifdef DEBUG
-       printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
-               devp->bus->number, devp->devfn);
-#endif
-
-       if (pci_enable_device(devp))
-               return(-EIO);
-       if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
-               return(-ENOMEM);
-       if ((brdp->brdnr = stl_getbrdnr()) < 0) {
-               printk("STALLION: too many boards found, "
+       struct stlbrd *brdp;
+       unsigned int i, brdtype = ent->driver_data;
+       int brdnr, retval = -ENODEV;
+
+       if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+               goto err;
+
+       dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
+                       pdev->vendor, pdev->device, pdev->class);
+
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto err;
+       brdp = stl_allocbrd();
+       if (brdp == NULL) {
+               retval = -ENOMEM;
+               goto err;
+       }
+       mutex_lock(&stl_brdslock);
+       brdnr = stl_getbrdnr();
+       if (brdnr < 0) {
+               dev_err(&pdev->dev, "too many boards found, "
                        "maximum supported %d\n", STL_MAXBRDS);
-               return(0);
+               mutex_unlock(&stl_brdslock);
+               goto err_fr;
        }
-       brdp->brdtype = brdtype;
+       brdp->brdnr = (unsigned int)brdnr;
+       stl_brds[brdp->brdnr] = brdp;
+       mutex_unlock(&stl_brdslock);
 
-/*
- *     Different Stallion boards use the BAR registers in different ways,
- *     so set up io addresses based on board type.
- */
-#ifdef DEBUG
-       printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
-               pci_resource_start(devp, 0), pci_resource_start(devp, 1),
-               pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
-#endif
+       brdp->brdtype = brdtype;
+       brdp->state |= STL_PROBED;
 
 /*
  *     We have all resources from the board, so let's setup the actual
@@ -2641,120 +2386,70 @@ static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
  */
        switch (brdtype) {
        case BRD_ECHPCI:
-               brdp->ioaddr2 = pci_resource_start(devp, 0);
-               brdp->ioaddr1 = pci_resource_start(devp, 1);
+               brdp->ioaddr2 = pci_resource_start(pdev, 0);
+               brdp->ioaddr1 = pci_resource_start(pdev, 1);
                break;
        case BRD_ECH64PCI:
-               brdp->ioaddr2 = pci_resource_start(devp, 2);
-               brdp->ioaddr1 = pci_resource_start(devp, 1);
+               brdp->ioaddr2 = pci_resource_start(pdev, 2);
+               brdp->ioaddr1 = pci_resource_start(pdev, 1);
                break;
        case BRD_EASYIOPCI:
-               brdp->ioaddr1 = pci_resource_start(devp, 2);
-               brdp->ioaddr2 = pci_resource_start(devp, 1);
-               break;
-       default:
-               printk("STALLION: unknown PCI board type=%d\n", brdtype);
+               brdp->ioaddr1 = pci_resource_start(pdev, 2);
+               brdp->ioaddr2 = pci_resource_start(pdev, 1);
                break;
-       }
-
-       brdp->irq = devp->irq;
-       stl_brdinit(brdp);
-
-       return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *     Find all Stallion PCI boards that might be installed. Initialize each
- *     one as it is found.
- */
-
-
-static inline int stl_findpcibrds(void)
-{
-       struct pci_dev  *dev = NULL;
-       int             i, rc;
-
-#ifdef DEBUG
-       printk("stl_findpcibrds()\n");
-#endif
-
-       for (i = 0; (i < stl_nrpcibrds); i++)
-               while ((dev = pci_find_device(stl_pcibrds[i].vendid,
-                   stl_pcibrds[i].devid, dev))) {
-
-/*
- *                     Found a device on the PCI bus that has our vendor and
- *                     device ID. Need to check now that it is really us.
- */
-                       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-                               continue;
-
-                       rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
-                       if (rc)
-                               return(rc);
-               }
+       default:
+               dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
+               break;
+       }
 
-       return(0);
-}
+       brdp->irq = pdev->irq;
+       retval = stl_brdinit(brdp);
+       if (retval)
+               goto err_null;
 
-#endif
+       pci_set_drvdata(pdev, brdp);
 
-/*****************************************************************************/
+       for (i = 0; i < brdp->nrports; i++)
+               tty_register_device(stl_serial,
+                               brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
 
-/*
- *     Scan through all the boards in the configuration and see what we
- *     can find. Handle EIO and the ECH boards a little differently here
- *     since the initial search and setup is too different.
- */
+       return 0;
+err_null:
+       stl_brds[brdp->brdnr] = NULL;
+err_fr:
+       kfree(brdp);
+err:
+       return retval;
+}
 
-static inline int stl_initbrds(void)
+static void __devexit stl_pciremove(struct pci_dev *pdev)
 {
-       stlbrd_t        *brdp;
-       stlconf_t       *confp;
-       int             i;
+       struct stlbrd *brdp = pci_get_drvdata(pdev);
+       unsigned int i;
 
-#ifdef DEBUG
-       printk("stl_initbrds()\n");
-#endif
+       free_irq(brdp->irq, brdp);
 
-       if (stl_nrbrds > STL_MAXBRDS) {
-               printk("STALLION: too many boards in configuration table, "
-                       "truncating to %d\n", STL_MAXBRDS);
-               stl_nrbrds = STL_MAXBRDS;
-       }
+       stl_cleanup_panels(brdp);
 
-/*
- *     Firstly scan the list of static boards configured. Allocate
- *     resources and initialize the boards as found.
- */
-       for (i = 0; (i < stl_nrbrds); i++) {
-               confp = &stl_brdconf[i];
-               stl_parsebrd(confp, stl_brdsp[i]);
-               if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
-                       return(-ENOMEM);
-               brdp->brdnr = i;
-               brdp->brdtype = confp->brdtype;
-               brdp->ioaddr1 = confp->ioaddr1;
-               brdp->ioaddr2 = confp->ioaddr2;
-               brdp->irq = confp->irq;
-               brdp->irqtype = confp->irqtype;
-               stl_brdinit(brdp);
-       }
+       release_region(brdp->ioaddr1, brdp->iosize1);
+       if (brdp->iosize2 > 0)
+               release_region(brdp->ioaddr2, brdp->iosize2);
 
-/*
- *     Find any dynamically supported boards. That is via module load
- *     line options or auto-detected on the PCI bus.
- */
-       stl_argbrds();
-#ifdef CONFIG_PCI
-       stl_findpcibrds();
-#endif
+       for (i = 0; i < brdp->nrports; i++)
+               tty_unregister_device(stl_serial,
+                               brdp->brdnr * STL_MAXPORTS + i);
 
-       return(0);
+       stl_brds[brdp->brdnr] = NULL;
+       kfree(brdp);
 }
 
+static struct pci_driver stl_pcidriver = {
+       .name = "stallion",
+       .id_table = stl_pcibrds,
+       .probe = stl_pciprobe,
+       .remove = __devexit_p(stl_pciremove)
+};
+
 /*****************************************************************************/
 
 /*
@@ -2763,17 +2458,18 @@ static inline int stl_initbrds(void)
 
 static int stl_getbrdstats(combrd_t __user *bp)
 {
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
-       int             i;
+       combrd_t        stl_brdstats;
+       struct stlbrd   *brdp;
+       struct stlpanel *panelp;
+       unsigned int i;
 
        if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
                return -EFAULT;
        if (stl_brdstats.brd >= STL_MAXBRDS)
-               return(-ENODEV);
+               return -ENODEV;
        brdp = stl_brds[stl_brdstats.brd];
-       if (brdp == (stlbrd_t *) NULL)
-               return(-ENODEV);
+       if (brdp == NULL)
+               return -ENODEV;
 
        memset(&stl_brdstats, 0, sizeof(combrd_t));
        stl_brdstats.brd = brdp->brdnr;
@@ -2785,7 +2481,7 @@ static int stl_getbrdstats(combrd_t __user *bp)
        stl_brdstats.irq = brdp->irq;
        stl_brdstats.nrpanels = brdp->nrpanels;
        stl_brdstats.nrports = brdp->nrports;
-       for (i = 0; (i < brdp->nrpanels); i++) {
+       for (i = 0; i < brdp->nrpanels; i++) {
                panelp = brdp->panels[i];
                stl_brdstats.panels[i].panel = i;
                stl_brdstats.panels[i].hwid = panelp->hwid;
@@ -2801,24 +2497,24 @@ static int stl_getbrdstats(combrd_t __user *bp)
  *     Resolve the referenced port number into a port struct pointer.
  */
 
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
+static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
 {
-       stlbrd_t        *brdp;
-       stlpanel_t      *panelp;
+       struct stlbrd   *brdp;
+       struct stlpanel *panelp;
 
-       if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
-               return((stlport_t *) NULL);
+       if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+               return NULL;
        brdp = stl_brds[brdnr];
-       if (brdp == (stlbrd_t *) NULL)
-               return((stlport_t *) NULL);
-       if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
-               return((stlport_t *) NULL);
+       if (brdp == NULL)
+               return NULL;
+       if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
+               return NULL;
        panelp = brdp->panels[panelnr];
-       if (panelp == (stlpanel_t *) NULL)
-               return((stlport_t *) NULL);
-       if ((portnr < 0) || (portnr >= panelp->nrports))
-               return((stlport_t *) NULL);
-       return(panelp->ports[portnr]);
+       if (panelp == NULL)
+               return NULL;
+       if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
+               return NULL;
+       return panelp->ports[portnr];
 }
 
 /*****************************************************************************/
@@ -2829,8 +2525,9 @@ static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
  *     what port to get stats for (used through board control device).
  */
 
-static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
+static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
 {
+       comstats_t      stl_comstats;
        unsigned char   *head, *tail;
        unsigned long   flags;
 
@@ -2839,8 +2536,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
                        return -EFAULT;
                portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
                        stl_comstats.port);
-               if (portp == (stlport_t *) NULL)
-                       return(-ENODEV);
+               if (portp == NULL)
+                       return -ENODEV;
        }
 
        portp->stats.state = portp->istate;
@@ -2855,25 +2552,24 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
        portp->stats.rxbuffered = 0;
 
        spin_lock_irqsave(&stallion_lock, flags);
-       if (portp->tty != (struct tty_struct *) NULL) {
+       if (portp->tty != NULL)
                if (portp->tty->driver_data == portp) {
                        portp->stats.ttystate = portp->tty->flags;
                        /* No longer available as a statistic */
                        portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
-                       if (portp->tty->termios != (struct termios *) NULL) {
+                       if (portp->tty->termios != NULL) {
                                portp->stats.cflags = portp->tty->termios->c_cflag;
                                portp->stats.iflags = portp->tty->termios->c_iflag;
                                portp->stats.oflags = portp->tty->termios->c_oflag;
                                portp->stats.lflags = portp->tty->termios->c_lflag;
                        }
                }
-       }
        spin_unlock_irqrestore(&stallion_lock, flags);
 
        head = portp->tx.head;
        tail = portp->tx.tail;
-       portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
-               (STL_TXBUFSIZE - (tail - head)));
+       portp->stats.txbuffered = (head >= tail) ? (head - tail) :
+               (STL_TXBUFSIZE - (tail - head));
 
        portp->stats.signals = (unsigned long) stl_getsignals(portp);
 
@@ -2887,15 +2583,17 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
  *     Clear the port stats structure. We also return it zeroed out...
  */
 
-static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp)
+static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
 {
+       comstats_t      stl_comstats;
+
        if (!portp) {
                if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
                        return -EFAULT;
                portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
                        stl_comstats.port);
-               if (portp == (stlport_t *) NULL)
-                       return(-ENODEV);
+               if (portp == NULL)
+                       return -ENODEV;
        }
 
        memset(&portp->stats, 0, sizeof(comstats_t));
@@ -2912,17 +2610,18 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp)
  *     Return the entire driver ports structure to a user app.
  */
 
-static int stl_getportstruct(stlport_t __user *arg)
+static int stl_getportstruct(struct stlport __user *arg)
 {
-       stlport_t       *portp;
+       struct stlport  stl_dummyport;
+       struct stlport  *portp;
 
-       if (copy_from_user(&stl_dummyport, arg, sizeof(stlport_t)))
+       if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
                return -EFAULT;
        portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
                 stl_dummyport.portnr);
        if (!portp)
                return -ENODEV;
-       return copy_to_user(arg, portp, sizeof(stlport_t)) ? -EFAULT : 0;
+       return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
 }
 
 /*****************************************************************************/
@@ -2931,18 +2630,19 @@ static int stl_getportstruct(stlport_t __user *arg)
  *     Return the entire driver board structure to a user app.
  */
 
-static int stl_getbrdstruct(stlbrd_t __user *arg)
+static int stl_getbrdstruct(struct stlbrd __user *arg)
 {
-       stlbrd_t        *brdp;
+       struct stlbrd   stl_dummybrd;
+       struct stlbrd   *brdp;
 
-       if (copy_from_user(&stl_dummybrd, arg, sizeof(stlbrd_t)))
+       if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
                return -EFAULT;
-       if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
+       if (stl_dummybrd.brdnr >= STL_MAXBRDS)
                return -ENODEV;
        brdp = stl_brds[stl_dummybrd.brdnr];
        if (!brdp)
-               return(-ENODEV);
-       return copy_to_user(arg, brdp, sizeof(stlbrd_t)) ? -EFAULT : 0;
+               return -ENODEV;
+       return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
 }
 
 /*****************************************************************************/
@@ -2958,14 +2658,11 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
        int     brdnr, rc;
        void __user *argp = (void __user *)arg;
 
-#ifdef DEBUG
-       printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip,
-               (int) fp, cmd, (int) arg);
-#endif
+       pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
 
        brdnr = iminor(ip);
        if (brdnr >= STL_MAXBRDS)
-               return(-ENODEV);
+               return -ENODEV;
        rc = 0;
 
        switch (cmd) {
@@ -2989,7 +2686,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
                break;
        }
 
-       return(rc);
+       return rc;
 }
 
 static const struct tty_operations stl_ops = {
@@ -3016,55 +2713,6 @@ static const struct tty_operations stl_ops = {
        .tiocmset = stl_tiocmset,
 };
 
-/*****************************************************************************/
-
-static int __init stl_init(void)
-{
-       int i;
-       printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-       spin_lock_init(&stallion_lock);
-       spin_lock_init(&brd_lock);
-
-       stl_initbrds();
-
-       stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-       if (!stl_serial)
-               return -1;
-
-/*
- *     Set up a character driver for per board stuff. This is mainly used
- *     to do stats ioctls on the ports.
- */
-       if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
-               printk("STALLION: failed to register serial board device\n");
-
-       stallion_class = class_create(THIS_MODULE, "staliomem");
-       for (i = 0; i < 4; i++)
-               class_device_create(stallion_class, NULL,
-                                   MKDEV(STL_SIOMEMMAJOR, i), NULL,
-                                   "staliomem%d", i);
-
-       stl_serial->owner = THIS_MODULE;
-       stl_serial->driver_name = stl_drvname;
-       stl_serial->name = "ttyE";
-       stl_serial->major = STL_SERIALMAJOR;
-       stl_serial->minor_start = 0;
-       stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
-       stl_serial->subtype = SERIAL_TYPE_NORMAL;
-       stl_serial->init_termios = stl_deftermios;
-       stl_serial->flags = TTY_DRIVER_REAL_RAW;
-       tty_set_operations(stl_serial, &stl_ops);
-
-       if (tty_register_driver(stl_serial)) {
-               put_tty_driver(stl_serial);
-               printk("STALLION: failed to register serial driver\n");
-               return -1;
-       }
-
-       return 0;
-}
-
 /*****************************************************************************/
 /*                       CD1400 HARDWARE FUNCTIONS                           */
 /*****************************************************************************/
@@ -3075,21 +2723,21 @@ static int __init stl_init(void)
  *     (Maybe should make this inline...)
  */
 
-static int stl_cd1400getreg(stlport_t *portp, int regnr)
+static int stl_cd1400getreg(struct stlport *portp, int regnr)
 {
        outb((regnr + portp->uartaddr), portp->ioaddr);
        return inb(portp->ioaddr + EREG_DATA);
 }
 
-static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
+static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
 {
-       outb((regnr + portp->uartaddr), portp->ioaddr);
+       outb(regnr + portp->uartaddr, portp->ioaddr);
        outb(value, portp->ioaddr + EREG_DATA);
 }
 
-static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
+static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
 {
-       outb((regnr + portp->uartaddr), portp->ioaddr);
+       outb(regnr + portp->uartaddr, portp->ioaddr);
        if (inb(portp->ioaddr + EREG_DATA) != value) {
                outb(value, portp->ioaddr + EREG_DATA);
                return 1;
@@ -3105,16 +2753,14 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
  *     identical when dealing with ports.
  */
 
-static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
+static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
 {
        unsigned int    gfrcr;
        int             chipmask, i, j;
        int             nrchips, uartaddr, ioaddr;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
-#endif
+       pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(panelp->brdnr, panelp->pagenr);
@@ -3124,13 +2770,12 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
  */
        chipmask = 0;
        nrchips = panelp->nrports / CD1400_PORTS;
-       for (i = 0; (i < nrchips); i++) {
+       for (i = 0; i < nrchips; i++) {
                if (brdp->brdtype == BRD_ECHPCI) {
                        outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
                        ioaddr = panelp->iobase;
-               } else {
+               } else
                        ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
-               }
                uartaddr = (i & 0x01) ? 0x080 : 0;
                outb((GFRCR + uartaddr), ioaddr);
                outb(0, (ioaddr + EREG_DATA));
@@ -3138,10 +2783,10 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
                outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
                outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
                outb((GFRCR + uartaddr), ioaddr);
-               for (j = 0; (j < CCR_MAXWAIT); j++) {
+               for (j = 0; j < CCR_MAXWAIT; j++)
                        if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
                                break;
-               }
+
                if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
                        printk("STALLION: cd1400 not responding, "
                                "brd=%d panel=%d chip=%d\n",
@@ -3164,16 +2809,14 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
  *     Initialize hardware specific port registers.
  */
 
-static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
+static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
 {
        unsigned long flags;
-#ifdef DEBUG
-       printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
-               (int) brdp, (int) panelp, (int) portp);
-#endif
+       pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+                       panelp, portp);
 
-       if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
-           (portp == (stlport_t *) NULL))
+       if ((brdp == NULL) || (panelp == NULL) ||
+           (portp == NULL))
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -3197,15 +2840,13 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
  *     since it won't usually take too long to be ready.
  */
 
-static void stl_cd1400ccrwait(stlport_t *portp)
+static void stl_cd1400ccrwait(struct stlport *portp)
 {
        int     i;
 
-       for (i = 0; (i < CCR_MAXWAIT); i++) {
-               if (stl_cd1400getreg(portp, CCR) == 0) {
+       for (i = 0; i < CCR_MAXWAIT; i++)
+               if (stl_cd1400getreg(portp, CCR) == 0)
                        return;
-               }
-       }
 
        printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
                portp->portnr, portp->panelnr, portp->brdnr);
@@ -3218,9 +2859,9 @@ static void stl_cd1400ccrwait(stlport_t *portp)
  *     settings.
  */
 
-static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
+static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
 {
-       stlbrd_t        *brdp;
+       struct stlbrd   *brdp;
        unsigned long   flags;
        unsigned int    clkdiv, baudrate;
        unsigned char   cor1, cor2, cor3;
@@ -3244,7 +2885,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
        sreroff = 0;
 
        brdp = stl_brds[portp->brdnr];
-       if (brdp == (stlbrd_t *) NULL)
+       if (brdp == NULL)
                return;
 
 /*
@@ -3341,8 +2982,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
                baudrate = STL_CD1400MAXBAUD;
 
        if (baudrate > 0) {
-               for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
-                       clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
+               for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
+                       clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
                        if (clkdiv < 0x100)
                                break;
                }
@@ -3357,9 +2998,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
                mcor2 |= MCOR2_DCD;
                sreron |= SRER_MODEM;
                portp->flags |= ASYNC_CHECK_CD;
-       } else {
+       } else
                portp->flags &= ~ASYNC_CHECK_CD;
-       }
 
 /*
  *     Setup cd1400 enhanced modes if we can. In particular we want to
@@ -3384,18 +3024,16 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
  *     them all up.
  */
 
-#ifdef DEBUG
-       printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+       pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
                portp->portnr, portp->panelnr, portp->brdnr);
-       printk("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
+       pr_debug("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
                cor1, cor2, cor3, cor4, cor5);
-       printk("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
+       pr_debug("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
                mcor1, mcor2, rtpr, sreron, sreroff);
-       printk("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
-       printk("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
+       pr_debug("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
+       pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-#endif
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3443,15 +3081,13 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
  *     Set the state of the DTR and RTS signals.
  */
 
-static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
+static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
 {
        unsigned char   msvr1, msvr2;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n",
-               (int) portp, dtr, rts);
-#endif
+       pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
+                       portp, dtr, rts);
 
        msvr1 = 0;
        msvr2 = 0;
@@ -3477,15 +3113,13 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
  *     Return the state of the signals.
  */
 
-static int stl_cd1400getsignals(stlport_t *portp)
+static int stl_cd1400getsignals(struct stlport *portp)
 {
        unsigned char   msvr1, msvr2;
        unsigned long   flags;
        int             sigs;
 
-#ifdef DEBUG
-       printk("stl_cd1400getsignals(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3515,15 +3149,13 @@ static int stl_cd1400getsignals(stlport_t *portp)
  *     Enable/Disable the Transmitter and/or Receiver.
  */
 
-static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
+static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
 {
        unsigned char   ccr;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n",
-               (int) portp, rx, tx);
-#endif
+       pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
+
        ccr = 0;
 
        if (tx == 0)
@@ -3551,15 +3183,12 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
  *     Start/stop the Transmitter and/or Receiver.
  */
 
-static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
+static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
 {
        unsigned char   sreron, sreroff;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n",
-               (int) portp, rx, tx);
-#endif
+       pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
 
        sreron = 0;
        sreroff = 0;
@@ -3591,13 +3220,12 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
  *     Disable all interrupts from this port.
  */
 
-static void stl_cd1400disableintrs(stlport_t *portp)
+static void stl_cd1400disableintrs(struct stlport *portp)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
+
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
@@ -3608,13 +3236,11 @@ static void stl_cd1400disableintrs(stlport_t *portp)
 
 /*****************************************************************************/
 
-static void stl_cd1400sendbreak(stlport_t *portp, int len)
+static void stl_cd1400sendbreak(struct stlport *portp, int len)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len);
-#endif
+       pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3635,19 +3261,17 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
  *     Take flow control actions...
  */
 
-static void stl_cd1400flowctrl(stlport_t *portp, int state)
+static void stl_cd1400flowctrl(struct stlport *portp, int state)
 {
        struct tty_struct       *tty;
        unsigned long           flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400flowctrl(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+       pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        tty = portp->tty;
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -3699,19 +3323,17 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
  *     Send a flow control character...
  */
 
-static void stl_cd1400sendflow(stlport_t *portp, int state)
+static void stl_cd1400sendflow(struct stlport *portp, int state)
 {
        struct tty_struct       *tty;
        unsigned long           flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400sendflow(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+       pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        tty = portp->tty;
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -3734,15 +3356,13 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
 
 /*****************************************************************************/
 
-static void stl_cd1400flush(stlport_t *portp)
+static void stl_cd1400flush(struct stlport *portp)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_cd1400flush(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_cd1400flush(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -3765,13 +3385,11 @@ static void stl_cd1400flush(stlport_t *portp)
  *     maintains the busy port flag.
  */
 
-static int stl_cd1400datastate(stlport_t *portp)
+static int stl_cd1400datastate(struct stlport *portp)
 {
-#ifdef DEBUG
-       printk("stl_cd1400datastate(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return 0;
 
        return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
@@ -3783,14 +3401,11 @@ static int stl_cd1400datastate(stlport_t *portp)
  *     Interrupt service routine for cd1400 EasyIO boards.
  */
 
-static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
 {
        unsigned char   svrtype;
 
-#ifdef DEBUG
-       printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n",
-               (int) panelp, iobase);
-#endif
+       pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
 
        spin_lock(&brd_lock);
        outb(SVRR, iobase);
@@ -3816,14 +3431,11 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
  *     Interrupt service routine for cd1400 panels.
  */
 
-static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
 {
        unsigned char   svrtype;
 
-#ifdef DEBUG
-       printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp,
-               iobase);
-#endif
+       pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
 
        outb(SVRR, iobase);
        svrtype = inb(iobase + EREG_DATA);
@@ -3845,7 +3457,7 @@ static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
  *     this is the only way to generate them on the cd1400.
  */
 
-static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
+static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
 {
        if (portp->brklen == 1) {
                outb((COR2 + portp->uartaddr), ioaddr);
@@ -3887,16 +3499,14 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
  *     be NULL if the buffer has been freed.
  */
 
-static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        int             len, stlen;
        char            *head, *tail;
        unsigned char   ioack, srer;
 
-#ifdef DEBUG
-       printk("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
+       pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
 
        ioack = inb(ioaddr + EREG_TXACK);
        if (((ioack & panelp->ackmask) != 0) ||
@@ -3935,9 +3545,9 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
                }
                outb(srer, (ioaddr + EREG_DATA));
        } else {
-               len = MIN(len, CD1400_TXFIFOSIZE);
+               len = min(len, CD1400_TXFIFOSIZE);
                portp->stats.txtotal += len;
-               stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
+               stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
                outb((TDR + portp->uartaddr), ioaddr);
                outsb((ioaddr + EREG_DATA), tail, stlen);
                len -= stlen;
@@ -3968,17 +3578,15 @@ stl_txalldone:
  *     shutdown a port not in user context. Need to handle this case.
  */
 
-static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
 {
-       stlport_t               *portp;
+       struct stlport          *portp;
        struct tty_struct       *tty;
        unsigned int            ioack, len, buflen;
        unsigned char           status;
        char                    ch;
 
-#ifdef DEBUG
-       printk("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
+       pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
 
        ioack = inb(ioaddr + EREG_RXACK);
        if ((ioack & panelp->ackmask) != 0) {
@@ -3992,13 +3600,13 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
                outb((RDCR + portp->uartaddr), ioaddr);
                len = inb(ioaddr + EREG_DATA);
                if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-                       len = MIN(len, sizeof(stl_unwanted));
+                       len = min(len, sizeof(stl_unwanted));
                        outb((RDSR + portp->uartaddr), ioaddr);
                        insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
                        portp->stats.rxlost += len;
                        portp->stats.rxtotal += len;
                } else {
-                       len = MIN(len, buflen);
+                       len = min(len, buflen);
                        if (len > 0) {
                                unsigned char *ptr;
                                outb((RDSR + portp->uartaddr), ioaddr);
@@ -4035,18 +3643,16 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
                                                do_SAK(tty);
                                                BRDENABLE(portp->brdnr, portp->pagenr);
                                        }
-                               } else if (status & ST_PARITY) {
+                               } else if (status & ST_PARITY)
                                        status = TTY_PARITY;
-                               } else if (status & ST_FRAMING) {
+                               else if (status & ST_FRAMING)
                                        status = TTY_FRAME;
-                               } else if(status & ST_OVERRUN) {
+                               else if(status & ST_OVERRUN)
                                        status = TTY_OVERRUN;
-                               } else {
+                               else
                                        status = 0;
-                               }
-                       } else {
+                       } else
                                status = 0;
-                       }
                        tty_insert_flip_char(tty, ch, status);
                        tty_schedule_flip(tty);
                }
@@ -4068,15 +3674,13 @@ stl_rxalldone:
  *     processing routine.
  */
 
-static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    ioack;
        unsigned char   misr;
 
-#ifdef DEBUG
-       printk("stl_cd1400mdmisr(panelp=%x)\n", (int) panelp);
-#endif
+       pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
 
        ioack = inb(ioaddr + EREG_MDACK);
        if (((ioack & panelp->ackmask) != 0) ||
@@ -4108,19 +3712,19 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
  *     (Maybe should make this inline...)
  */
 
-static int stl_sc26198getreg(stlport_t *portp, int regnr)
+static int stl_sc26198getreg(struct stlport *portp, int regnr)
 {
        outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
        return inb(portp->ioaddr + XP_DATA);
 }
 
-static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
+static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
 {
        outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
        outb(value, (portp->ioaddr + XP_DATA));
 }
 
-static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
+static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
 {
        outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
        if (inb(portp->ioaddr + XP_DATA) != value) {
@@ -4136,14 +3740,14 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
  *     Functions to get and set the sc26198 global registers.
  */
 
-static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
+static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
 {
        outb(regnr, (portp->ioaddr + XP_ADDR));
        return inb(portp->ioaddr + XP_DATA);
 }
 
 #if 0
-static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value)
+static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
 {
        outb(regnr, (portp->ioaddr + XP_ADDR));
        outb(value, (portp->ioaddr + XP_DATA));
@@ -4158,15 +3762,12 @@ static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value)
  *     identical when dealing with ports.
  */
 
-static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
+static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
 {
        int     chipmask, i;
        int     nrchips, ioaddr;
 
-#ifdef DEBUG
-       printk("stl_sc26198panelinit(brdp=%x,panelp=%x)\n",
-               (int) brdp, (int) panelp);
-#endif
+       pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
 
        BRDENABLE(panelp->brdnr, panelp->pagenr);
 
@@ -4178,7 +3779,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
        if (brdp->brdtype == BRD_ECHPCI)
                outb(panelp->pagenr, brdp->ioctrl);
 
-       for (i = 0; (i < nrchips); i++) {
+       for (i = 0; i < nrchips; i++) {
                ioaddr = panelp->iobase + (i * 4); 
                outb(SCCR, (ioaddr + XP_ADDR));
                outb(CR_RESETALL, (ioaddr + XP_DATA));
@@ -4206,15 +3807,13 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
  *     Initialize hardware specific port registers.
  */
 
-static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
+static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
 {
-#ifdef DEBUG
-       printk("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n",
-               (int) brdp, (int) panelp, (int) portp);
-#endif
+       pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+                       panelp, portp);
 
-       if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
-           (portp == (stlport_t *) NULL))
+       if ((brdp == NULL) || (panelp == NULL) ||
+           (portp == NULL))
                return;
 
        portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
@@ -4234,9 +3833,9 @@ static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *p
  *     settings.
  */
 
-static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
+static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
 {
-       stlbrd_t        *brdp;
+       struct stlbrd   *brdp;
        unsigned long   flags;
        unsigned int    baudrate;
        unsigned char   mr0, mr1, mr2, clk;
@@ -4251,7 +3850,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
        imroff = 0;
 
        brdp = stl_brds[portp->brdnr];
-       if (brdp == (stlbrd_t *) NULL)
+       if (brdp == NULL)
                return;
 
 /*
@@ -4300,9 +3899,8 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
                        mr1 |= (MR1_PARENB | MR1_PARODD);
                else
                        mr1 |= (MR1_PARENB | MR1_PAREVEN);
-       } else {
+       } else
                mr1 |= MR1_PARNONE;
-       }
 
        mr1 |= MR1_ERRBLOCK;
 
@@ -4342,12 +3940,10 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
        if (baudrate > STL_SC26198MAXBAUD)
                baudrate = STL_SC26198MAXBAUD;
 
-       if (baudrate > 0) {
-               for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
+       if (baudrate > 0)
+               for (clk = 0; clk < SC26198_NRBAUDS; clk++)
                        if (baudrate <= sc26198_baudtable[clk])
                                break;
-               }
-       }
 
 /*
  *     Check what form of modem signaling is required and set it up.
@@ -4369,9 +3965,9 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
        if (tiosp->c_iflag & IXON) {
                mr0 |= MR0_SWFTX | MR0_SWFT;
                imron |= IR_XONXOFF;
-       } else {
+       } else
                imroff |= IR_XONXOFF;
-       }
+
        if (tiosp->c_iflag & IXOFF)
                mr0 |= MR0_SWFRX;
 
@@ -4385,15 +3981,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
  *     them all up.
  */
 
-#ifdef DEBUG
-       printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+       pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
                portp->portnr, portp->panelnr, portp->brdnr);
-       printk("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
-       printk("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
-       printk("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
+       pr_debug("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
+       pr_debug("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
+       pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-#endif
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4431,15 +4025,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
  *     Set the state of the DTR and RTS signals.
  */
 
-static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
+static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
 {
        unsigned char   iopioron, iopioroff;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n",
-               (int) portp, dtr, rts);
-#endif
+       pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
+                       dtr, rts);
 
        iopioron = 0;
        iopioroff = 0;
@@ -4466,15 +4058,13 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
  *     Return the state of the signals.
  */
 
-static int stl_sc26198getsignals(stlport_t *portp)
+static int stl_sc26198getsignals(struct stlport *portp)
 {
        unsigned char   ipr;
        unsigned long   flags;
        int             sigs;
 
-#ifdef DEBUG
-       printk("stl_sc26198getsignals(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4497,15 +4087,12 @@ static int stl_sc26198getsignals(stlport_t *portp)
  *     Enable/Disable the Transmitter and/or Receiver.
  */
 
-static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
+static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
 {
        unsigned char   ccr;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n",
-               (int) portp, rx, tx);
-#endif
+       pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
 
        ccr = portp->crenable;
        if (tx == 0)
@@ -4531,15 +4118,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
  *     Start/stop the Transmitter and/or Receiver.
  */
 
-static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
+static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
 {
        unsigned char   imr;
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n",
-               (int) portp, rx, tx);
-#endif
+       pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
 
        imr = portp->imr;
        if (tx == 0)
@@ -4567,13 +4151,11 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
  *     Disable all interrupts from this port.
  */
 
-static void stl_sc26198disableintrs(stlport_t *portp)
+static void stl_sc26198disableintrs(struct stlport *portp)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4585,22 +4167,20 @@ static void stl_sc26198disableintrs(stlport_t *portp)
 
 /*****************************************************************************/
 
-static void stl_sc26198sendbreak(stlport_t *portp, int len)
+static void stl_sc26198sendbreak(struct stlport *portp, int len)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len);
-#endif
+       pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
 
        spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        if (len == 1) {
                stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
                portp->stats.txbreaks++;
-       } else {
+       } else
                stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
-       }
+
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
 }
@@ -4611,20 +4191,18 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
  *     Take flow control actions...
  */
 
-static void stl_sc26198flowctrl(stlport_t *portp, int state)
+static void stl_sc26198flowctrl(struct stlport *portp, int state)
 {
        struct tty_struct       *tty;
        unsigned long           flags;
        unsigned char           mr0;
 
-#ifdef DEBUG
-       printk("stl_sc26198flowctrl(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+       pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        tty = portp->tty;
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -4682,20 +4260,18 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
  *     Send a flow control character.
  */
 
-static void stl_sc26198sendflow(stlport_t *portp, int state)
+static void stl_sc26198sendflow(struct stlport *portp, int state)
 {
        struct tty_struct       *tty;
        unsigned long           flags;
        unsigned char           mr0;
 
-#ifdef DEBUG
-       printk("stl_sc26198sendflow(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+       pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
        tty = portp->tty;
-       if (tty == (struct tty_struct *) NULL)
+       if (tty == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -4723,15 +4299,13 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
 
 /*****************************************************************************/
 
-static void stl_sc26198flush(stlport_t *portp)
+static void stl_sc26198flush(struct stlport *portp)
 {
        unsigned long   flags;
 
-#ifdef DEBUG
-       printk("stl_sc26198flush(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198flush(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
        spin_lock_irqsave(&brd_lock, flags);
@@ -4753,16 +4327,14 @@ static void stl_sc26198flush(stlport_t *portp)
  *     check the port statusy register to be sure.
  */
 
-static int stl_sc26198datastate(stlport_t *portp)
+static int stl_sc26198datastate(struct stlport *portp)
 {
        unsigned long   flags;
        unsigned char   sr;
 
-#ifdef DEBUG
-       printk("stl_sc26198datastate(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return 0;
        if (test_bit(ASYI_TXBUSY, &portp->istate))
                return 1;
@@ -4783,18 +4355,16 @@ static int stl_sc26198datastate(stlport_t *portp)
  *     to process a command...
  */
 
-static void stl_sc26198wait(stlport_t *portp)
+static void stl_sc26198wait(struct stlport *portp)
 {
        int     i;
 
-#ifdef DEBUG
-       printk("stl_sc26198wait(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198wait(portp=%p)\n", portp);
 
-       if (portp == (stlport_t *) NULL)
+       if (portp == NULL)
                return;
 
-       for (i = 0; (i < 20); i++)
+       for (i = 0; i < 20; i++)
                stl_sc26198getglobreg(portp, TSTR);
 }
 
@@ -4806,7 +4376,7 @@ static void stl_sc26198wait(stlport_t *portp)
  *     automatic flow control modes of the sc26198.
  */
 
-static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty)
+static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
 {
        unsigned char   mr0;
 
@@ -4824,9 +4394,9 @@ static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty)
  *     Interrupt service routine for sc26198 panels.
  */
 
-static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
 {
-       stlport_t       *portp;
+       struct stlport  *portp;
        unsigned int    iack;
 
        spin_lock(&brd_lock);
@@ -4862,16 +4432,14 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
  *     be NULL if the buffer has been freed.
  */
 
-static void stl_sc26198txisr(stlport_t *portp)
+static void stl_sc26198txisr(struct stlport *portp)
 {
        unsigned int    ioaddr;
        unsigned char   mr0;
        int             len, stlen;
        char            *head, *tail;
 
-#ifdef DEBUG
-       printk("stl_sc26198txisr(portp=%x)\n", (int) portp);
-#endif
+       pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
 
        ioaddr = portp->ioaddr;
        head = portp->tx.head;
@@ -4896,9 +4464,9 @@ static void stl_sc26198txisr(stlport_t *portp)
                        outb(mr0, (ioaddr + XP_DATA));
                }
        } else {
-               len = MIN(len, SC26198_TXFIFOSIZE);
+               len = min(len, SC26198_TXFIFOSIZE);
                portp->stats.txtotal += len;
-               stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
+               stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
                outb(GTXFIFO, (ioaddr + XP_ADDR));
                outsb((ioaddr + XP_DATA), tail, stlen);
                len -= stlen;
@@ -4925,14 +4493,12 @@ static void stl_sc26198txisr(stlport_t *portp)
  *     shutdown a port not in user context. Need to handle this case.
  */
 
-static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
+static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
 {
        struct tty_struct       *tty;
        unsigned int            len, buflen, ioaddr;
 
-#ifdef DEBUG
-       printk("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack);
-#endif
+       pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
 
        tty = portp->tty;
        ioaddr = portp->ioaddr;
@@ -4941,13 +4507,13 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
 
        if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
                if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-                       len = MIN(len, sizeof(stl_unwanted));
+                       len = min(len, sizeof(stl_unwanted));
                        outb(GRXFIFO, (ioaddr + XP_ADDR));
                        insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
                        portp->stats.rxlost += len;
                        portp->stats.rxtotal += len;
                } else {
-                       len = MIN(len, buflen);
+                       len = min(len, buflen);
                        if (len > 0) {
                                unsigned char *ptr;
                                outb(GRXFIFO, (ioaddr + XP_ADDR));
@@ -4967,8 +4533,8 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
  *     flow control modes of the sc26198.
  */
        if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
-               if ((tty != (struct tty_struct *) NULL) &&
-                   (tty->termios != (struct termios *) NULL) &&
+               if ((tty != NULL) &&
+                   (tty->termios != NULL) &&
                    (tty->termios->c_iflag & IXANY)) {
                        stl_sc26198txunflow(portp, tty);
                }
@@ -4981,7 +4547,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
  *     Process an RX bad character.
  */
 
-static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch)
+static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
 {
        struct tty_struct       *tty;
        unsigned int            ioaddr;
@@ -4998,7 +4564,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
        if (status & SR_RXBREAK)
                portp->stats.rxbreaks++;
 
-       if ((tty != (struct tty_struct *) NULL) &&
+       if ((tty != NULL) &&
            ((portp->rxignoremsk & status) == 0)) {
                if (portp->rxmarkmsk & status) {
                        if (status & SR_RXBREAK) {
@@ -5007,18 +4573,16 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
                                        do_SAK(tty);
                                        BRDENABLE(portp->brdnr, portp->pagenr);
                                }
-                       } else if (status & SR_RXPARITY) {
+                       } else if (status & SR_RXPARITY)
                                status = TTY_PARITY;
-                       } else if (status & SR_RXFRAMING) {
+                       else if (status & SR_RXFRAMING)
                                status = TTY_FRAME;
-                       } else if(status & SR_RXOVERRUN) {
+                       else if(status & SR_RXOVERRUN)
                                status = TTY_OVERRUN;
-                       } else {
+                       else
                                status = 0;
-                       }
-               } else {
+               } else
                        status = 0;
-               }
 
                tty_insert_flip_char(tty, ch, status);
                tty_schedule_flip(tty);
@@ -5039,7 +4603,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
  *     the FIFO).
  */
 
-static void stl_sc26198rxbadchars(stlport_t *portp)
+static void stl_sc26198rxbadchars(struct stlport *portp)
 {
        unsigned char   status, mr1;
        char            ch;
@@ -5072,13 +4636,11 @@ static void stl_sc26198rxbadchars(stlport_t *portp)
  *     processing time.
  */
 
-static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
+static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
 {
        unsigned char   cir, ipr, xisr;
 
-#ifdef DEBUG
-       printk("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack);
-#endif
+       pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
 
        cir = stl_sc26198getglobreg(portp, CIR);
 
@@ -5111,4 +4673,172 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
        }
 }
 
-/*****************************************************************************/
+static void stl_free_isabrds(void)
+{
+       struct stlbrd *brdp;
+       unsigned int i;
+
+       for (i = 0; i < stl_nrbrds; i++) {
+               if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+                       continue;
+
+               free_irq(brdp->irq, brdp);
+
+               stl_cleanup_panels(brdp);
+
+               release_region(brdp->ioaddr1, brdp->iosize1);
+               if (brdp->iosize2 > 0)
+                       release_region(brdp->ioaddr2, brdp->iosize2);
+
+               kfree(brdp);
+               stl_brds[i] = NULL;
+       }
+}
+
+/*
+ *     Loadable module initialization stuff.
+ */
+static int __init stallion_module_init(void)
+{
+       struct stlbrd   *brdp;
+       struct stlconf  conf;
+       unsigned int i, j;
+       int retval;
+
+       printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
+
+       spin_lock_init(&stallion_lock);
+       spin_lock_init(&brd_lock);
+
+/*
+ *     Find any dynamically supported boards. That is via module load
+ *     line options.
+ */
+       for (i = stl_nrbrds; i < stl_nargs; i++) {
+               memset(&conf, 0, sizeof(conf));
+               if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
+                       continue;
+               if ((brdp = stl_allocbrd()) == NULL)
+                       continue;
+               brdp->brdnr = i;
+               brdp->brdtype = conf.brdtype;
+               brdp->ioaddr1 = conf.ioaddr1;
+               brdp->ioaddr2 = conf.ioaddr2;
+               brdp->irq = conf.irq;
+               brdp->irqtype = conf.irqtype;
+               if (stl_brdinit(brdp))
+                       kfree(brdp);
+               else {
+                       for (j = 0; j < brdp->nrports; j++)
+                               tty_register_device(stl_serial,
+                                       brdp->brdnr * STL_MAXPORTS + j, NULL);
+                       stl_brds[brdp->brdnr] = brdp;
+                       stl_nrbrds = i + 1;
+               }
+       }
+
+       /* this has to be _after_ isa finding because of locking */
+       retval = pci_register_driver(&stl_pcidriver);
+       if (retval && stl_nrbrds == 0)
+               goto err;
+
+       stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+       if (!stl_serial) {
+               retval = -ENOMEM;
+               goto err_pcidr;
+       }
+
+/*
+ *     Set up a character driver for per board stuff. This is mainly used
+ *     to do stats ioctls on the ports.
+ */
+       if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
+               printk("STALLION: failed to register serial board device\n");
+
+       stallion_class = class_create(THIS_MODULE, "staliomem");
+       if (IS_ERR(stallion_class)) {
+               retval = PTR_ERR(stallion_class);
+               goto err_reg;
+       }
+       for (i = 0; i < 4; i++)
+               class_device_create(stallion_class, NULL,
+                                   MKDEV(STL_SIOMEMMAJOR, i), NULL,
+                                   "staliomem%d", i);
+
+       stl_serial->owner = THIS_MODULE;
+       stl_serial->driver_name = stl_drvname;
+       stl_serial->name = "ttyE";
+       stl_serial->major = STL_SERIALMAJOR;
+       stl_serial->minor_start = 0;
+       stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+       stl_serial->subtype = SERIAL_TYPE_NORMAL;
+       stl_serial->init_termios = stl_deftermios;
+       stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+       tty_set_operations(stl_serial, &stl_ops);
+
+       retval = tty_register_driver(stl_serial);
+       if (retval) {
+               printk("STALLION: failed to register serial driver\n");
+               goto err_clsdev;
+       }
+
+       return 0;
+err_clsdev:
+       for (i = 0; i < 4; i++)
+               class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
+       class_destroy(stallion_class);
+err_reg:
+       unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+       put_tty_driver(stl_serial);
+err_pcidr:
+       pci_unregister_driver(&stl_pcidriver);
+       stl_free_isabrds();
+err:
+       return retval;
+}
+
+static void __exit stallion_module_exit(void)
+{
+       struct stlbrd *brdp;
+       unsigned int i, j;
+       int retval;
+
+       pr_debug("cleanup_module()\n");
+
+       printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
+               stl_drvversion);
+
+/*
+ *     Free up all allocated resources used by the ports. This includes
+ *     memory and interrupts. As part of this process we will also do
+ *     a hangup on every open port - to try to flush out any processes
+ *     hanging onto ports.
+ */
+       for (i = 0; i < stl_nrbrds; i++) {
+               if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+                       continue;
+               for (j = 0; j < brdp->nrports; j++)
+                       tty_unregister_device(stl_serial,
+                               brdp->brdnr * STL_MAXPORTS + j);
+       }
+       tty_unregister_driver(stl_serial);
+       put_tty_driver(stl_serial);
+
+       for (i = 0; i < 4; i++)
+               class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
+       if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
+               printk("STALLION: failed to un-register serial memory device, "
+                       "errno=%d\n", -retval);
+       class_destroy(stallion_class);
+
+       pci_unregister_driver(&stl_pcidriver);
+
+       stl_free_isabrds();
+}
+
+module_init(stallion_module_init);
+module_exit(stallion_module_exit);
+
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
+MODULE_LICENSE("GPL");
index cc10af0..a3008ce 100644 (file)
@@ -32,7 +32,6 @@
  *      USA.
  *
  * Revision history:
- * $Log: sx.c,v $
  * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
  * - Fixed module and port counting
  * - Fixed signal handling
  *
  * */
 
-
-#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $"
-#define RCS_REV "$Revision: 1.33 $"
+#define SX_VERSION     1.33
 
 #include <linux/module.h>
 #include <linux/kdev_t.h>
 #include <linux/fcntl.h>
 #include <linux/major.h>
 #include <linux/delay.h>
+#include <linux/eisa.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/generic_serial.h>
 #include "sx.h"
 
-
 /* I don't think that this driver can handle more than 256 ports on
    one machine. You'll have to increase the number of boards in sx.h
    if you want more than 4 boards.  */
 #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
 #endif
 
-#ifdef CONFIG_PCI
-static struct pci_device_id sx_pci_tbl[] = {
-       { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID },
-       { 0 }
-};
-MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
-#endif /* CONFIG_PCI */
-
 /* Configurable options: 
    (Don't be too sure that it'll work if you toggle them) */
 
 /* Am I paranoid or not ? ;-) */
 #undef SX_PARANOIA_CHECK
 
-
 /* 20 -> 2000 per second. The card should rate-limit interrupts at 100
    Hz, but it is user configurable. I don't recommend going above 1000
    Hz. The interrupt ratelimit might trigger if the interrupt is
@@ -277,7 +265,6 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
    interrupt. Use polling. */
 #undef IRQ_RATE_LIMIT
 
-
 #if 0
 /* Not implemented */
 /* 
@@ -286,35 +273,33 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
  */
 #define SX_REPORT_FIFO
 #define SX_REPORT_OVERRUN
-#endif 
-
+#endif
 
 /* Function prototypes */
-static void sx_disable_tx_interrupts (void * ptr); 
-static void sx_enable_tx_interrupts (void * ptr); 
-static void sx_disable_rx_interrupts (void * ptr); 
-static void sx_enable_rx_interrupts (void * ptr); 
-static int  sx_get_CD (void * ptr); 
-static void sx_shutdown_port (void * ptr);
-static int  sx_set_real_termios (void  *ptr);
-static void sx_close (void  *ptr);
-static int sx_chars_in_buffer (void * ptr);
-static int sx_init_board (struct sx_board *board);
-static int sx_init_portstructs (int nboards, int nports);
-static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
+static void sx_disable_tx_interrupts(void *ptr);
+static void sx_enable_tx_interrupts(void *ptr);
+static void sx_disable_rx_interrupts(void *ptr);
+static void sx_enable_rx_interrupts(void *ptr);
+static int sx_get_CD(void *ptr);
+static void sx_shutdown_port(void *ptr);
+static int sx_set_real_termios(void *ptr);
+static void sx_close(void *ptr);
+static int sx_chars_in_buffer(void *ptr);
+static int sx_init_board(struct sx_board *board);
+static int sx_init_portstructs(int nboards, int nports);
+static int sx_fw_ioctl(struct inode *inode, struct file *filp,
+               unsigned int cmd, unsigned long arg);
 static int sx_init_drivers(void);
 
-
 static struct tty_driver *sx_driver;
 
+static DEFINE_MUTEX(sx_boards_lock);
 static struct sx_board boards[SX_NBOARDS];
 static struct sx_port *sx_ports;
 static int sx_initialized;
 static int sx_nports;
 static int sx_debug;
 
-
 /* You can have the driver poll your card. 
     - Set sx_poll to 1 to poll every timer tick (10ms on Intel). 
       This is used when the card cannot use an interrupt for some reason.
@@ -333,27 +318,36 @@ static int sx_slowpoll;
 
 static int sx_maxints = 100;
 
+#ifdef CONFIG_ISA
+
 /* These are the only open spaces in my computer. Yours may have more
    or less.... -- REW 
    duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
 */
-static int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                              0xc8000, 0xd8000, 0xe8000};
-static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                              0xc8000, 0xd8000, 0xe8000, 0xa0000};
-static int si1_probe_addrs[]= { 0xd0000};
+static int sx_probe_addrs[] = {
+       0xc0000, 0xd0000, 0xe0000,
+       0xc8000, 0xd8000, 0xe8000
+};
+static int si_probe_addrs[] = {
+       0xc0000, 0xd0000, 0xe0000,
+       0xc8000, 0xd8000, 0xe8000, 0xa0000
+};
+static int si1_probe_addrs[] = {
+       0xd0000
+};
 
 #define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
 #define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
 #define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
 
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+#endif
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
    Some architectures may need more. */
 static int sx_irqmask = -1;
 
-module_param_array(sx_probe_addrs, int, NULL, 0);
-module_param_array(si_probe_addrs, int, NULL, 0);
 module_param(sx_poll, int, 0);
 module_param(sx_slowpoll, int, 0);
 module_param(sx_maxints, int, 0);
@@ -368,13 +362,12 @@ static struct real_driver sx_real_driver = {
        sx_disable_rx_interrupts,
        sx_enable_rx_interrupts,
        sx_get_CD,
-       sx_shutdown_port, 
-       sx_set_real_termios, 
+       sx_shutdown_port,
+       sx_set_real_termios,
        sx_chars_in_buffer,
        sx_close,
 };
 
-
 /* 
    This driver can spew a whole lot of debugging output at you. If you
    need maximum performance, you should disable the DEBUG define. To
@@ -385,23 +378,17 @@ static struct real_driver sx_real_driver = {
 */
 #define DEBUG
 
-
 #ifdef DEBUG
-#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
+#define sx_dprintk(f, str...)  if (sx_debug & f) printk (str)
 #else
-#define sx_dprintk(f, str...) /* nothing */
+#define sx_dprintk(f, str...)  /* nothing */
 #endif
 
+#define func_enter()   sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
+#define func_exit()    sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__FUNCTION__)
 
-
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
-#define func_exit()  sx_dprintk (SX_DEBUG_FLOW, "sx: exit  %s\n", __FUNCTION__)
-
-#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-                                       __FUNCTION__, port->line)
-
-
-
+#define func_enter2()  sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
+                               __FUNCTION__, port->line)
 
 /* 
  *  Firmware loader driver specific routines
@@ -409,31 +396,26 @@ static struct real_driver sx_real_driver = {
  */
 
 static const struct file_operations sx_fw_fops = {
-       .owner          = THIS_MODULE,
-       .ioctl          = sx_fw_ioctl,
+       .owner = THIS_MODULE,
+       .ioctl = sx_fw_ioctl,
 };
 
 static struct miscdevice sx_fw_device = {
        SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
 };
 
-
-
-
-
 #ifdef SX_PARANOIA_CHECK
 
 /* This doesn't work. Who's paranoid around here? Not me! */
 
-static inline int sx_paranoia_check(struct sx_port const * port,
+static inline int sx_paranoia_check(struct sx_port const *port,
                                    char *name, const char *routine)
 {
+       static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
+                       "number for device %s in %s\n";
+       static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
+                       "device %s in %s\n";
 
-       static const char *badmagic =
-         KERN_ERR "sx: Warning: bad sx port magic number for device %s in %s\n";
-       static const char *badinfo =
-         KERN_ERR "sx: Warning: null sx port for device %s in %s\n";
        if (!port) {
                printk(badinfo, name, routine);
                return 1;
@@ -456,23 +438,24 @@ static inline int sx_paranoia_check(struct sx_port const * port,
 #define TIMEOUT_1 30
 #define TIMEOUT_2 1000000
 
-
 #ifdef DEBUG
 static void my_hd_io(void __iomem *p, int len)
 {
        int i, j, ch;
        unsigned char __iomem *addr = p;
 
-       for (i=0;i<len;i+=16) {
-               printk ("%p ", addr+i);
-               for (j=0;j<16;j++) {
-                       printk ("%02x %s", readb(addr+j+i), (j==7)?" ":"");
+       for (i = 0; i < len; i += 16) {
+               printk("%p ", addr + i);
+               for (j = 0; j < 16; j++) {
+                       printk("%02x %s", readb(addr + j + i),
+                                       (j == 7) ? " " : "");
                }
-               for (j=0;j<16;j++) {
-                       ch = readb(addr+j+i);
-                       printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+               for (j = 0; j < 16; j++) {
+                       ch = readb(addr + j + i);
+                       printk("%c", (ch < 0x20) ? '.' :
+                                       ((ch > 0x7f) ? '.' : ch));
                }
-               printk ("\n");
+               printk("\n");
        }
 }
 static void my_hd(void *p, int len)
@@ -480,419 +463,468 @@ static void my_hd(void *p, int len)
        int i, j, ch;
        unsigned char *addr = p;
 
-       for (i=0;i<len;i+=16) {
-               printk ("%p ", addr+i);
-               for (j=0;j<16;j++) {
-                       printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+       for (i = 0; i < len; i += 16) {
+               printk("%p ", addr + i);
+               for (j = 0; j < 16; j++) {
+                       printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
                }
-               for (j=0;j<16;j++) {
-                       ch = addr[j+i];
-                       printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+               for (j = 0; j < 16; j++) {
+                       ch = addr[j + i];
+                       printk("%c", (ch < 0x20) ? '.' :
+                                       ((ch > 0x7f) ? '.' : ch));
                }
-               printk ("\n");
+               printk("\n");
        }
 }
 #endif
 
-
-
 /* This needs redoing for Alpha -- REW -- Done. */
 
-static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
+static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
 {
-       writeb (byte, board->base+offset);
+       writeb(byte, board->base + offset);
 }
 
-static inline u8 read_sx_byte (struct sx_board *board, int offset)
+static inline u8 read_sx_byte(struct sx_board *board, int offset)
 {
-       return readb (board->base+offset);
+       return readb(board->base + offset);
 }
 
-
-static inline void write_sx_word (struct sx_board *board, int offset, u16 word)
+static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
 {
-       writew (word, board->base+offset);
+       writew(word, board->base + offset);
 }
 
-static inline u16 read_sx_word (struct sx_board *board, int offset)
+static inline u16 read_sx_word(struct sx_board *board, int offset)
 {
-       return readw (board->base + offset);
+       return readw(board->base + offset);
 }
 
-
-static int sx_busy_wait_eq (struct sx_board *board, 
-                           int offset, int mask, int correctval)
+static int sx_busy_wait_eq(struct sx_board *board,
+               int offset, int mask, int correctval)
 {
        int i;
 
-       func_enter ();
+       func_enter();
 
-       for (i=0; i < TIMEOUT_1 ;i++)
-               if ((read_sx_byte (board, offset) & mask) == correctval) {
-                       func_exit ();
+       for (i = 0; i < TIMEOUT_1; i++)
+               if ((read_sx_byte(board, offset) & mask) == correctval) {
+                       func_exit();
                        return 1;
                }
 
-       for (i=0; i < TIMEOUT_2 ;i++) {
-               if ((read_sx_byte (board, offset) & mask) == correctval) {
-                       func_exit ();
+       for (i = 0; i < TIMEOUT_2; i++) {
+               if ((read_sx_byte(board, offset) & mask) == correctval) {
+                       func_exit();
                        return 1;
                }
-               udelay (1);
+               udelay(1);
        }
 
-       func_exit ();
+       func_exit();
        return 0;
 }
 
-
-static int sx_busy_wait_neq (struct sx_board *board, 
-                            int offset, int mask, int badval)
+static int sx_busy_wait_neq(struct sx_board *board,
+               int offset, int mask, int badval)
 {
        int i;
 
-       func_enter ();
+       func_enter();
 
-       for (i=0; i < TIMEOUT_1 ;i++)
-               if ((read_sx_byte (board, offset) & mask) != badval) {
-                       func_exit ();
+       for (i = 0; i < TIMEOUT_1; i++)
+               if ((read_sx_byte(board, offset) & mask) != badval) {
+                       func_exit();
                        return 1;
                }
 
-       for (i=0; i < TIMEOUT_2 ;i++) {
-               if ((read_sx_byte (board, offset) & mask) != badval) {
-                       func_exit ();
+       for (i = 0; i < TIMEOUT_2; i++) {
+               if ((read_sx_byte(board, offset) & mask) != badval) {
+                       func_exit();
                        return 1;
                }
-               udelay (1);
+               udelay(1);
        }
 
-       func_exit ();
+       func_exit();
        return 0;
 }
 
-
-
 /* 5.6.4 of 6210028 r2.3 */
-static int sx_reset (struct sx_board *board)
+static int sx_reset(struct sx_board *board)
 {
-       func_enter ();
+       func_enter();
 
-       if (IS_SX_BOARD (board)) {
+       if (IS_SX_BOARD(board)) {
 
-               write_sx_byte (board, SX_CONFIG, 0);
-               write_sx_byte (board, SX_RESET, 1); /* Value doesn't matter */
+               write_sx_byte(board, SX_CONFIG, 0);
+               write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
 
-               if (!sx_busy_wait_eq (board, SX_RESET_STATUS, 1, 0)) {
-                       printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
+               if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
+                       printk(KERN_INFO "sx: Card doesn't respond to "
+                                       "reset...\n");
                        return 0;
                }
        } else if (IS_EISA_BOARD(board)) {
-               outb(board->irq<<4, board->eisa_base+0xc02);
+               outb(board->irq << 4, board->eisa_base + 0xc02);
        } else if (IS_SI1_BOARD(board)) {
-               write_sx_byte (board, SI1_ISA_RESET,   0); // value does not matter
+               write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
        } else {
                /* Gory details of the SI/ISA board */
-               write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_SET);
-               write_sx_byte (board, SI2_ISA_IRQ11,    SI2_ISA_IRQ11_CLEAR);
-               write_sx_byte (board, SI2_ISA_IRQ12,    SI2_ISA_IRQ12_CLEAR);
-               write_sx_byte (board, SI2_ISA_IRQ15,    SI2_ISA_IRQ15_CLEAR);
-               write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
-               write_sx_byte (board, SI2_ISA_IRQSET,   SI2_ISA_IRQSET_CLEAR);
+               write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
+               write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
+               write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
+               write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
+               write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
+               write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
        }
 
-       func_exit ();
+       func_exit();
        return 1;
 }
 
-
 /* This doesn't work on machines where "NULL" isn't 0 */
 /* If you have one of those, someone will need to write 
    the equivalent of this, which will amount to about 3 lines. I don't
    want to complicate this right now. -- REW
    (See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
-
-
-#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem)    (addr + OFFSETOF (_SXMODULE, elem))
-#define  BRD_OFFSET(board,elem)                (OFFSETOF (_SXCARD, elem))
+#define OFFSETOF(strct, elem)  ((long)&(((struct strct *)NULL)->elem))
 
+#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
+#define MODU_OFFSET(board,addr,elem)   (addr + OFFSETOF (_SXMODULE, elem))
+#define  BRD_OFFSET(board,elem)        (OFFSETOF (_SXCARD, elem))
 
 #define sx_write_channel_byte(port, elem, val) \
-   write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
+       write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
 
 #define sx_read_channel_byte(port, elem) \
-   read_sx_byte (port->board, CHAN_OFFSET (port, elem))
+       read_sx_byte (port->board, CHAN_OFFSET (port, elem))
 
 #define sx_write_channel_word(port, elem, val) \
-   write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
+       write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
 
 #define sx_read_channel_word(port, elem) \
-   read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
+       read_sx_word (port->board, CHAN_OFFSET (port, elem))
 
 #define sx_write_module_byte(board, addr, elem, val) \
-   write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
+       write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
 
 #define sx_read_module_byte(board, addr, elem) \
-   read_sx_byte (board, MODU_OFFSET (board, addr, elem))
+       read_sx_byte (board, MODU_OFFSET (board, addr, elem))
 
 #define sx_write_module_word(board, addr, elem, val) \
-   write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
+       write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
 
 #define sx_read_module_word(board, addr, elem) \
-   read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
+       read_sx_word (board, MODU_OFFSET (board, addr, elem))
 
 #define sx_write_board_byte(board, elem, val) \
-   write_sx_byte (board, BRD_OFFSET (board, elem), val)
+       write_sx_byte (board, BRD_OFFSET (board, elem), val)
 
 #define sx_read_board_byte(board, elem) \
-   read_sx_byte (board, BRD_OFFSET (board, elem))
+       read_sx_byte (board, BRD_OFFSET (board, elem))
 
 #define sx_write_board_word(board, elem, val) \
-   write_sx_word (board, BRD_OFFSET (board, elem), val)
+       write_sx_word (board, BRD_OFFSET (board, elem), val)
 
 #define sx_read_board_word(board, elem) \
-   read_sx_word (board, BRD_OFFSET (board, elem))
-
+       read_sx_word (board, BRD_OFFSET (board, elem))
 
-static int sx_start_board (struct sx_board *board)
+static int sx_start_board(struct sx_board *board)
 {
-       if (IS_SX_BOARD (board)) {
-               write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+       if (IS_SX_BOARD(board)) {
+               write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
        } else if (IS_EISA_BOARD(board)) {
                write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
-               outb((board->irq<<4)|4, board->eisa_base+0xc02);
+               outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
        } else if (IS_SI1_BOARD(board)) {
-               write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0);
-               write_sx_byte (board, SI1_ISA_INTCL, 0);
+               write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
+               write_sx_byte(board, SI1_ISA_INTCL, 0);
        } else {
                /* Don't bug me about the clear_set. 
                   I haven't the foggiest idea what it's about -- REW */
-               write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_CLEAR);
-               write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+               write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
+               write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
        }
        return 1;
 }
 
 #define SX_IRQ_REG_VAL(board) \
-        ((board->flags & SX_ISA_BOARD)?(board->irq << 4):0)
+       ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
 
 /* Note. The SX register is write-only. Therefore, we have to enable the
    bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts (struct sx_board *board)
+static int sx_start_interrupts(struct sx_board *board)
 {
 
        /* Don't call this with board->irq == 0 */
 
        if (IS_SX_BOARD(board)) {
-               write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | 
-                                                SX_CONF_BUSEN | 
-                                                SX_CONF_HOSTIRQ);
+               write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
+                               SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
        } else if (IS_EISA_BOARD(board)) {
-               inb(board->eisa_base+0xc03);  
+               inb(board->eisa_base + 0xc03);
        } else if (IS_SI1_BOARD(board)) {
-              write_sx_byte (board, SI1_ISA_INTCL,0);
-              write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0);
+               write_sx_byte(board, SI1_ISA_INTCL, 0);
+               write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
        } else {
                switch (board->irq) {
-               case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
-               case 12:write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);break;
-               case 15:write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);break;
-               default:printk (KERN_INFO "sx: SI/XIO card doesn't support interrupt %d.\n", 
-                               board->irq);
-               return 0;
+               case 11:
+                       write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
+                       break;
+               case 12:
+                       write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
+                       break;
+               case 15:
+                       write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
+                       break;
+               default:
+                       printk(KERN_INFO "sx: SI/XIO card doesn't support "
+                                       "interrupt %d.\n", board->irq);
+                       return 0;
                }
-               write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+               write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
        }
 
        return 1;
 }
 
-
-static int sx_send_command (struct sx_port *port, 
-                           int command, int mask, int newstat)
+static int sx_send_command(struct sx_port *port,
+               int command, int mask, int newstat)
 {
-       func_enter2 ();
-       write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command);
-       func_exit ();
-       return sx_busy_wait_eq (port->board, CHAN_OFFSET (port, hi_hstat), mask, newstat);
+       func_enter2();
+       write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
+       func_exit();
+       return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
+                       newstat);
 }
 
-
-static char *mod_type_s (int module_type)
+static char *mod_type_s(int module_type)
 {
        switch (module_type) {
-       case TA4:       return "TA4";
-       case TA8:       return "TA8";
-       case TA4_ASIC:  return "TA4_ASIC";
-       case TA8_ASIC:  return "TA8_ASIC";
-       case MTA_CD1400:return "MTA_CD1400";
-       case SXDC:      return "SXDC";
-       default:return "Unknown/invalid";
+       case TA4:
+               return "TA4";
+       case TA8:
+               return "TA8";
+       case TA4_ASIC:
+               return "TA4_ASIC";
+       case TA8_ASIC:
+               return "TA8_ASIC";
+       case MTA_CD1400:
+               return "MTA_CD1400";
+       case SXDC:
+               return "SXDC";
+       default:
+               return "Unknown/invalid";
        }
 }
 
-
-static char *pan_type_s (int pan_type)
+static char *pan_type_s(int pan_type)
 {
        switch (pan_type) {
-       case MOD_RS232DB25:     return "MOD_RS232DB25";
-       case MOD_RS232RJ45:     return "MOD_RS232RJ45";
-       case MOD_RS422DB25:     return "MOD_RS422DB25";
-       case MOD_PARALLEL:      return "MOD_PARALLEL";
-       case MOD_2_RS232DB25:   return "MOD_2_RS232DB25";
-       case MOD_2_RS232RJ45:   return "MOD_2_RS232RJ45";
-       case MOD_2_RS422DB25:   return "MOD_2_RS422DB25";
-       case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE";
-       case MOD_2_PARALLEL:    return "MOD_2_PARALLEL";
-       case MOD_BLANK:         return "empty";
-       default:return "invalid";
+       case MOD_RS232DB25:
+               return "MOD_RS232DB25";
+       case MOD_RS232RJ45:
+               return "MOD_RS232RJ45";
+       case MOD_RS422DB25:
+               return "MOD_RS422DB25";
+       case MOD_PARALLEL:
+               return "MOD_PARALLEL";
+       case MOD_2_RS232DB25:
+               return "MOD_2_RS232DB25";
+       case MOD_2_RS232RJ45:
+               return "MOD_2_RS232RJ45";
+       case MOD_2_RS422DB25:
+               return "MOD_2_RS422DB25";
+       case MOD_RS232DB25MALE:
+               return "MOD_RS232DB25MALE";
+       case MOD_2_PARALLEL:
+               return "MOD_2_PARALLEL";
+       case MOD_BLANK:
+               return "empty";
+       default:
+               return "invalid";
        }
 }
 
-
-static int mod_compat_type (int module_type)
+static int mod_compat_type(int module_type)
 {
        return module_type >> 4;
 }
 
 static void sx_reconfigure_port(struct sx_port *port)
 {
-       if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
-               if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-                       printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+       if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
+               if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+                       printk(KERN_WARNING "sx: Sent reconfigure command, but "
+                                       "card didn't react.\n");
                }
        } else {
-               sx_dprintk (SX_DEBUG_TERMIOS, 
-                           "sx: Not sending reconfigure: port isn't open (%02x).\n", 
-                           sx_read_channel_byte (port, hi_hstat));
-       }       
+               sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
+                               "port isn't open (%02x).\n",
+                               sx_read_channel_byte(port, hi_hstat));
+       }
 }
 
-static void sx_setsignals (struct sx_port *port, int dtr, int rts)
+static void sx_setsignals(struct sx_port *port, int dtr, int rts)
 {
        int t;
-       func_enter2 ();
+       func_enter2();
 
-       t = sx_read_channel_byte (port, hi_op);
-       if (dtr >= 0) t = dtr? (t | OP_DTR): (t & ~OP_DTR);
-       if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS);
-       sx_write_channel_byte (port, hi_op, t);
-       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+       t = sx_read_channel_byte(port, hi_op);
+       if (dtr >= 0)
+               t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
+       if (rts >= 0)
+               t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
+       sx_write_channel_byte(port, hi_op, t);
+       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
 
-       func_exit ();
+       func_exit();
 }
 
-
-
-static int sx_getsignals (struct sx_port *port)
+static int sx_getsignals(struct sx_port *port)
 {
-       int i_stat,o_stat;
-
-       o_stat = sx_read_channel_byte (port, hi_op);
-       i_stat = sx_read_channel_byte (port, hi_ip);
-
-       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) %02x/%02x\n",
-                   (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
-                   port->c_dcd, sx_get_CD (port),
-                   sx_read_channel_byte (port, hi_ip),
-                   sx_read_channel_byte (port, hi_state));
-
-       return (((o_stat & OP_DTR)?TIOCM_DTR:0) |
-               ((o_stat & OP_RTS)?TIOCM_RTS:0) |
-               ((i_stat & IP_CTS)?TIOCM_CTS:0) |
-               ((i_stat & IP_DCD)?TIOCM_CAR:0) |
-               ((i_stat & IP_DSR)?TIOCM_DSR:0) |
-               ((i_stat & IP_RI)?TIOCM_RNG:0)
-               );
+       int i_stat, o_stat;
+
+       o_stat = sx_read_channel_byte(port, hi_op);
+       i_stat = sx_read_channel_byte(port, hi_ip);
+
+       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) "
+                       "%02x/%02x\n",
+                       (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
+                       port->c_dcd, sx_get_CD(port),
+                       sx_read_channel_byte(port, hi_ip),
+                       sx_read_channel_byte(port, hi_state));
+
+       return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
+               ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
+               ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
+               ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
+               ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
+               ((i_stat & IP_RI) ? TIOCM_RNG : 0));
 }
 
-
-static void sx_set_baud (struct sx_port *port)
+static void sx_set_baud(struct sx_port *port)
 {
        int t;
 
        if (port->board->ta_type == MOD_SXDC) {
                switch (port->gs.baud) {
-                 /* Save some typing work... */
-#define e(x) case x:t= BAUD_ ## x ; break
-                       e(50);e(75);e(110);e(150);e(200);e(300);e(600);
-                        e(1200);e(1800);e(2000);e(2400);e(4800);e(7200);
-                        e(9600);e(14400);e(19200);e(28800);e(38400);
-                        e(56000);e(57600);e(64000);e(76800);e(115200);
-                       e(128000);e(150000);e(230400);e(256000);e(460800);
-                        e(921600);
-               case 134    :t = BAUD_134_5;   break;
-               case 0      :t = -1;
-                                                                break;
+                       /* Save some typing work... */
+#define e(x) case x: t = BAUD_ ## x; break
+                       e(50);
+                       e(75);
+                       e(110);
+                       e(150);
+                       e(200);
+                       e(300);
+                       e(600);
+                       e(1200);
+                       e(1800);
+                       e(2000);
+                       e(2400);
+                       e(4800);
+                       e(7200);
+                       e(9600);
+                       e(14400);
+                       e(19200);
+                       e(28800);
+                       e(38400);
+                       e(56000);
+                       e(57600);
+                       e(64000);
+                       e(76800);
+                       e(115200);
+                       e(128000);
+                       e(150000);
+                       e(230400);
+                       e(256000);
+                       e(460800);
+                       e(921600);
+               case 134:
+                       t = BAUD_134_5;
+                       break;
+               case 0:
+                       t = -1;
+                       break;
                default:
                        /* Can I return "invalid"? */
                        t = BAUD_9600;
-                       printk (KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud);
+                       printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
+                                       port->gs.baud);
                        break;
                }
 #undef e
                if (t > 0) {
-                       /* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
-                       sx_setsignals (port, 1, -1); 
+/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
+                       sx_setsignals(port, 1, -1);
                        /* XXX This is not TA & MTA compatible */
-                       sx_write_channel_byte (port, hi_csr, 0xff);
+                       sx_write_channel_byte(port, hi_csr, 0xff);
 
-                       sx_write_channel_byte (port, hi_txbaud, t);
-                       sx_write_channel_byte (port, hi_rxbaud, t);
+                       sx_write_channel_byte(port, hi_txbaud, t);
+                       sx_write_channel_byte(port, hi_rxbaud, t);
                } else {
-                       sx_setsignals (port, 0, -1);
+                       sx_setsignals(port, 0, -1);
                }
        } else {
                switch (port->gs.baud) {
-#define e(x) case x:t= CSR_ ## x ; break
-                       e(75);e(150);e(300);e(600);e(1200);e(2400);e(4800);
-                        e(1800);e(9600);
-                       e(19200);e(57600);e(38400);
-                       /* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
-               case 110: 
+#define e(x) case x: t = CSR_ ## x; break
+                       e(75);
+                       e(150);
+                       e(300);
+                       e(600);
+                       e(1200);
+                       e(2400);
+                       e(4800);
+                       e(1800);
+                       e(9600);
+                       e(19200);
+                       e(57600);
+                       e(38400);
+/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
+               case 110:
                        if (port->board->ta_type == MOD_TA) {
                                t = CSR_110;
                                break;
                        } else {
                                t = CSR_9600;
-                               printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+                               printk(KERN_INFO "sx: Unsupported baud rate: "
+                                               "%d.\n", port->gs.baud);
                                break;
                        }
-               case 115200: 
+               case 115200:
                        if (port->board->ta_type == MOD_TA) {
                                t = CSR_9600;
-                               printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+                               printk(KERN_INFO "sx: Unsupported baud rate: "
+                                               "%d.\n", port->gs.baud);
                                break;
                        } else {
                                t = CSR_110;
                                break;
                        }
-               case 0      :t = -1;
-                                                                break;
+               case 0:
+                       t = -1;
+                       break;
                default:
                        t = CSR_9600;
-                       printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+                       printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
+                                       port->gs.baud);
                        break;
                }
 #undef e
                if (t >= 0) {
-                       sx_setsignals (port, 1, -1);
-                       sx_write_channel_byte (port, hi_csr, t * 0x11);
+                       sx_setsignals(port, 1, -1);
+                       sx_write_channel_byte(port, hi_csr, t * 0x11);
                } else {
-                       sx_setsignals (port, 0, -1);
+                       sx_setsignals(port, 0, -1);
                }
        }
 }
 
-
 /* Simon Allen's version of this routine was 225 lines long. 85 is a lot
    better. -- REW */
 
-static int sx_set_real_termios (void *ptr)
+static int sx_set_real_termios(void *ptr)
 {
        struct sx_port *port = ptr;
 
@@ -907,80 +939,83 @@ static int sx_set_real_termios (void *ptr)
           belongs (next to the drop dtr if baud == 0) -- REW */
        /* sx_setsignals (port, 1, -1); */
 
-       sx_set_baud (port);
+       sx_set_baud(port);
 
 #define CFLAG port->gs.tty->termios->c_cflag
-       sx_write_channel_byte (port, hi_mr1,
-                              (C_PARENB (port->gs.tty)? MR1_WITH:MR1_NONE) |
-                              (C_PARODD (port->gs.tty)? MR1_ODD:MR1_EVEN) |
-                              (C_CRTSCTS(port->gs.tty)? MR1_RTS_RXFLOW:0) |
-                              (((CFLAG & CSIZE)==CS8) ? MR1_8_BITS:0) |
-                              (((CFLAG & CSIZE)==CS7) ? MR1_7_BITS:0) |
-                              (((CFLAG & CSIZE)==CS6) ? MR1_6_BITS:0) |
-                              (((CFLAG & CSIZE)==CS5) ? MR1_5_BITS:0) );
-
-       sx_write_channel_byte (port, hi_mr2,
-                              (C_CRTSCTS(port->gs.tty)?MR2_CTS_TXFLOW:0) |
-                              (C_CSTOPB (port->gs.tty)?MR2_2_STOP:MR2_1_STOP));
+       sx_write_channel_byte(port, hi_mr1,
+                       (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) |
+                       (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) |
+                       (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) |
+                       (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
+                       (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
+                       (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
+                       (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
+
+       sx_write_channel_byte(port, hi_mr2,
+                       (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) |
+                       (C_CSTOPB(port->gs.tty) ? MR2_2_STOP :
+                       MR2_1_STOP));
 
        switch (CFLAG & CSIZE) {
-       case CS8:sx_write_channel_byte (port, hi_mask, 0xff);break;
-       case CS7:sx_write_channel_byte (port, hi_mask, 0x7f);break;
-       case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break;
-       case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break;
+       case CS8:
+               sx_write_channel_byte(port, hi_mask, 0xff);
+               break;
+       case CS7:
+               sx_write_channel_byte(port, hi_mask, 0x7f);
+               break;
+       case CS6:
+               sx_write_channel_byte(port, hi_mask, 0x3f);
+               break;
+       case CS5:
+               sx_write_channel_byte(port, hi_mask, 0x1f);
+               break;
        default:
-               printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
+               printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
                break;
        }
 
-       sx_write_channel_byte (port, hi_prtcl, 
-                              (I_IXON   (port->gs.tty)?SP_TXEN:0) |
-                              (I_IXOFF  (port->gs.tty)?SP_RXEN:0) |
-                              (I_IXANY  (port->gs.tty)?SP_TANY:0) |
-                              SP_DCEN);
+       sx_write_channel_byte(port, hi_prtcl,
+                       (I_IXON(port->gs.tty) ? SP_TXEN : 0) |
+                       (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) |
+                       (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN);
 
-       sx_write_channel_byte (port, hi_break, 
-                              (I_IGNBRK(port->gs.tty)?BR_IGN:0 |
-                               I_BRKINT(port->gs.tty)?BR_INT:0));
+       sx_write_channel_byte(port, hi_break,
+                       (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 |
+                       I_BRKINT(port->gs.tty) ? BR_INT : 0));
 
-       sx_write_channel_byte (port, hi_txon,  START_CHAR (port->gs.tty));
-       sx_write_channel_byte (port, hi_rxon,  START_CHAR (port->gs.tty));
-       sx_write_channel_byte (port, hi_txoff, STOP_CHAR  (port->gs.tty));
-       sx_write_channel_byte (port, hi_rxoff, STOP_CHAR  (port->gs.tty));
+       sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty));
+       sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty));
+       sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty));
+       sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty));
 
        sx_reconfigure_port(port);
 
        /* Tell line discipline whether we will do input cooking */
-       if(I_OTHER(port->gs.tty)) {
+       if (I_OTHER(port->gs.tty)) {
                clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
        } else {
                set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
        }
-       sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-                   port->gs.tty->termios->c_iflag, 
-                   I_OTHER(port->gs.tty));
-
+       sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
+                       port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty));
 
 /* Tell line discipline whether we will do output cooking.
  * If OPOST is set and no other output flags are set then we can do output
  * processing.  Even if only *one* other flag in the O_OTHER group is set
  * we do cooking in software.
  */
-       if(O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
+       if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
                set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
        } else {
                clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
        }
-       sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-                   port->gs.tty->termios->c_oflag, 
-                   O_OTHER(port->gs.tty));
+       sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
+                       port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty));
        /* port->c_dcd = sx_get_CD (port); */
-       func_exit ();
+       func_exit();
        return 0;
 }
 
-
-
 /* ********************************************************************** *
  *                   the interrupt related routines                       *
  * ********************************************************************** */
@@ -996,245 +1031,260 @@ static int sx_set_real_termios (void *ptr)
    know I'm dead against that, but I think it is required in this
    case.  */
 
-
-static void sx_transmit_chars (struct sx_port *port)
+static void sx_transmit_chars(struct sx_port *port)
 {
        int c;
        int tx_ip;
        int txroom;
 
-       func_enter2 ();
-       sx_dprintk (SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", 
-                   port, port->gs.xmit_cnt);
+       func_enter2();
+       sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
+                       port, port->gs.xmit_cnt);
 
-       if (test_and_set_bit (SX_PORT_TRANSMIT_LOCK, &port->locks)) {
+       if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
                return;
        }
 
        while (1) {
                c = port->gs.xmit_cnt;
 
-               sx_dprintk (SX_DEBUG_TRANSMIT, "Copying %d ", c);
-               tx_ip  = sx_read_channel_byte (port, hi_txipos);
+               sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
+               tx_ip = sx_read_channel_byte(port, hi_txipos);
 
                /* Took me 5 minutes to deduce this formula. 
                   Luckily it is literally in the manual in section 6.5.4.3.5 */
-               txroom = (sx_read_channel_byte (port, hi_txopos) - tx_ip - 1) & 0xff;
+               txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
+                               0xff;
 
                /* Don't copy more bytes than there is room for in the buffer */
                if (c > txroom)
                        c = txroom;
-               sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom );
+               sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
 
                /* Don't copy past the end of the hardware transmit buffer */
-               if (c > 0x100 - tx_ip) 
+               if (c > 0x100 - tx_ip)
                        c = 0x100 - tx_ip;
 
-               sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100-tx_ip );
+               sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
 
                /* Don't copy pas the end of the source buffer */
-               if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) 
+               if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
                        c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
 
-               sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%ld) \n", 
-                           c, SERIAL_XMIT_SIZE- port->gs.xmit_tail);
-
-               /* If for one reason or another, we can't copy more data, we're done! */
-               if (c == 0) break;
+               sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
+                               c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
 
+               /* If for one reason or another, we can't copy more data, we're
+                  done! */
+               if (c == 0)
+                       break;
 
-               memcpy_toio (port->board->base + CHAN_OFFSET(port,hi_txbuf) + tx_ip, 
-                            port->gs.xmit_buf + port->gs.xmit_tail, c);
+               memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
+                       tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
 
                /* Update the pointer in the card */
-               sx_write_channel_byte (port, hi_txipos, (tx_ip+c) & 0xff);
+               sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
 
                /* Update the kernel buffer end */
-               port->gs.xmit_tail = (port->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
+               port->gs.xmit_tail = (port->gs.xmit_tail + c) &
+                               (SERIAL_XMIT_SIZE - 1);
 
                /* This one last. (this is essential)
-                  It would allow others to start putting more data into the buffer! */
+                  It would allow others to start putting more data into the
+                  buffer! */
                port->gs.xmit_cnt -= c;
        }
 
        if (port->gs.xmit_cnt == 0) {
-               sx_disable_tx_interrupts (port);
+               sx_disable_tx_interrupts(port);
        }
 
        if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
                tty_wakeup(port->gs.tty);
-               sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
-                           port->gs.wakeup_chars); 
+               sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
+                               port->gs.wakeup_chars);
        }
 
-       clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
-       func_exit ();
+       clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
+       func_exit();
 }
 
-
 /* Note the symmetry between receiving chars and transmitting them!
    Note: The kernel should have implemented both a receive buffer and
    a transmit buffer. */
 
 /* Inlined: Called only once. Remove the inline when you add another call */
-static inline void sx_receive_chars (struct sx_port *port)
+static inline void sx_receive_chars(struct sx_port *port)
 {
        int c;
        int rx_op;
        struct tty_struct *tty;
-       int copied=0;
+       int copied = 0;
        unsigned char *rp;
 
-       func_enter2 ();
+       func_enter2();
        tty = port->gs.tty;
        while (1) {
-               rx_op = sx_read_channel_byte (port, hi_rxopos);
-               c = (sx_read_channel_byte (port, hi_rxipos) - rx_op) & 0xff;
+               rx_op = sx_read_channel_byte(port, hi_rxopos);
+               c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
 
-               sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); 
+               sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
 
                /* Don't copy past the end of the hardware receive buffer */
-               if (rx_op + c > 0x100) c = 0x100 - rx_op;
+               if (rx_op + c > 0x100)
+                       c = 0x100 - rx_op;
 
-               sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
+               sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
 
                /* Don't copy more bytes than there is room for in the buffer */
 
                c = tty_prepare_flip_string(tty, &rp, c);
 
-               sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); 
+               sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
 
                /* If for one reason or another, we can't copy more data, we're done! */
-               if (c == 0) break;
+               if (c == 0)
+                       break;
 
-               sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, 
-                           read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
-                           CHAN_OFFSET(port, hi_rxbuf)); 
-               memcpy_fromio (rp,
-                              port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
+               sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
+                               "%d at %lx\n", c, read_sx_byte(port->board,
+                                       CHAN_OFFSET(port, hi_rxbuf) + rx_op),
+                               CHAN_OFFSET(port, hi_rxbuf));
+               memcpy_fromio(rp, port->board->base +
+                               CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
 
                /* This one last. ( Not essential.)
-                  It allows the card to start putting more data into the buffer! 
+                  It allows the card to start putting more data into the
+                  buffer!
                   Update the pointer in the card */
-               sx_write_channel_byte (port, hi_rxopos, (rx_op + c) & 0xff);
+               sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
 
                copied += c;
        }
        if (copied) {
                struct timeval tv;
 
-               do_gettimeofday (&tv);
-               sx_dprintk (SX_DEBUG_RECEIVE, 
-                           "pushing flipq port %d (%3d chars): %d.%06d  (%d/%d)\n", 
-                           port->line, copied, 
-                           (int) (tv.tv_sec % 60), (int)tv.tv_usec, tty->raw, tty->real_raw);
+               do_gettimeofday(&tv);
+               sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
+                               "chars): %d.%06d  (%d/%d)\n", port->line,
+                               copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
+                               tty->raw, tty->real_raw);
 
-               /* Tell the rest of the system the news. Great news. New characters! */
-               tty_flip_buffer_push (tty);
+               /* Tell the rest of the system the news. Great news. New
+                  characters! */
+               tty_flip_buffer_push(tty);
                /*    tty_schedule_flip (tty); */
        }
 
-       func_exit ();
+       func_exit();
 }
 
 /* Inlined: it is called only once. Remove the inline if you add another 
    call */
-static inline void sx_check_modem_signals (struct sx_port *port)
+static inline void sx_check_modem_signals(struct sx_port *port)
 {
        int hi_state;
        int c_dcd;
 
-       hi_state = sx_read_channel_byte (port, hi_state);
-       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
-                   port->c_dcd, sx_get_CD (port));
+       hi_state = sx_read_channel_byte(port, hi_state);
+       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
+                       port->c_dcd, sx_get_CD(port));
 
        if (hi_state & ST_BREAK) {
                hi_state &= ~ST_BREAK;
-               sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-               sx_write_channel_byte (port, hi_state, hi_state);
-               gs_got_break (&port->gs);
+               sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
+               sx_write_channel_byte(port, hi_state, hi_state);
+               gs_got_break(&port->gs);
        }
        if (hi_state & ST_DCD) {
                hi_state &= ~ST_DCD;
-               sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
-               sx_write_channel_byte (port, hi_state, hi_state);
-               c_dcd = sx_get_CD (port);
-               sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
+               sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
+               sx_write_channel_byte(port, hi_state, hi_state);
+               c_dcd = sx_get_CD(port);
+               sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
                if (c_dcd != port->c_dcd) {
                        port->c_dcd = c_dcd;
-                       if (sx_get_CD (port)) {
+                       if (sx_get_CD(port)) {
                                /* DCD went UP */
-                               if ((sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) &&
-                                               !(port->gs.tty->termios->c_cflag & CLOCAL) ) {
-                                       /* Are we blocking in open?*/
-                                       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n");
-                                       wake_up_interruptible(&port->gs.open_wait);
+                               if ((sx_read_channel_byte(port, hi_hstat) !=
+                                               HS_IDLE_CLOSED) &&
+                                               !(port->gs.tty->termios->
+                                                       c_cflag & CLOCAL)) {
+                                       /* Are we blocking in open? */
+                                       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+                                               "active, unblocking open\n");
+                                       wake_up_interruptible(&port->gs.
+                                                       open_wait);
                                } else {
-                                       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD raised. Ignoring.\n");
+                                       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+                                               "raised. Ignoring.\n");
                                }
                        } else {
                                /* DCD went down! */
-                               if (!(port->gs.tty->termios->c_cflag & CLOCAL) ) {
-                                       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n");
-                                       tty_hangup (port->gs.tty);
+                               if (!(port->gs.tty->termios->c_cflag & CLOCAL)){
+                                       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+                                               "dropped. hanging up....\n");
+                                       tty_hangup(port->gs.tty);
                                } else {
-                                       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. ignoring.\n");
+                                       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+                                               "dropped. ignoring.\n");
                                }
                        }
                } else {
-                       sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us DCD changed, but it didn't.\n");
+                       sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
+                               "DCD changed, but it didn't.\n");
                }
        }
 }
 
-
 /* This is what an interrupt routine should look like. 
  * Small, elegant, clear.
  */
 
-static irqreturn_t sx_interrupt (int irq, void *ptr)
+static irqreturn_t sx_interrupt(int irq, void *ptr)
 {
        struct sx_board *board = ptr;
        struct sx_port *port;
        int i;
 
-       func_enter ();
-       sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); 
+       func_enter();
+       sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
+                       board->irq);
 
        /* AAargh! The order in which to do these things is essential and
           not trivial. 
 
           - Rate limit goes before "recursive". Otherwise a series of
-            recursive calls will hang the machine in the interrupt routine. 
+          recursive calls will hang the machine in the interrupt routine.
 
           - hardware twiddling goes before "recursive". Otherwise when we
-            poll the card, and a recursive interrupt happens, we won't
-            ack the card, so it might keep on interrupting us. (especially
-            level sensitive interrupt systems like PCI).
+          poll the card, and a recursive interrupt happens, we won't
+          ack the card, so it might keep on interrupting us. (especially
+          level sensitive interrupt systems like PCI).
 
           - Rate limit goes before hardware twiddling. Otherwise we won't
-            catch a card that has gone bonkers.
+          catch a card that has gone bonkers.
 
           - The "initialized" test goes after the hardware twiddling. Otherwise
-            the card will stick us in the interrupt routine again.
+          the card will stick us in the interrupt routine again.
 
           - The initialized test goes before recursive. 
-       */
-
-
+        */
 
 #ifdef IRQ_RATE_LIMIT
        /* Aaargh! I'm ashamed. This costs more lines-of-code than the
-          actual interrupt routine!. (Well, used to when I wrote that comment) */
+          actual interrupt routine!. (Well, used to when I wrote that
+          comment) */
        {
                static int lastjif;
-               static int nintr=0;
+               static int nintr = 0;
 
                if (lastjif == jiffies) {
                        if (++nintr > IRQ_RATE_LIMIT) {
-                               free_irq (board->irq, board);
-                               printk (KERN_ERR "sx: Too many interrupts. Turning off interrupt %d.\n", 
-                                             board->irq);
+                               free_irq(board->irq, board);
+                               printk(KERN_ERR "sx: Too many interrupts. "
+                                               "Turning off interrupt %d.\n",
+                                               board->irq);
                        }
                } else {
                        lastjif = jiffies;
@@ -1243,19 +1293,20 @@ static irqreturn_t sx_interrupt (int irq, void *ptr)
        }
 #endif
 
-
        if (board->irq == irq) {
                /* Tell the card we've noticed the interrupt. */
 
-               sx_write_board_word (board, cc_int_pending, 0);
-               if (IS_SX_BOARD (board)) {
-                       write_sx_byte (board, SX_RESET_IRQ, 1);
+               sx_write_board_word(board, cc_int_pending, 0);
+               if (IS_SX_BOARD(board)) {
+                       write_sx_byte(board, SX_RESET_IRQ, 1);
                } else if (IS_EISA_BOARD(board)) {
-                       inb(board->eisa_base+0xc03);
-                       write_sx_word(board, 8, 0); 
+                       inb(board->eisa_base + 0xc03);
+                       write_sx_word(board, 8, 0);
                } else {
-                       write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
-                       write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+                       write_sx_byte(board, SI2_ISA_INTCLEAR,
+                                       SI2_ISA_INTCLEAR_CLEAR);
+                       write_sx_byte(board, SI2_ISA_INTCLEAR,
+                                       SI2_ISA_INTCLEAR_SET);
                }
        }
 
@@ -1264,53 +1315,48 @@ static irqreturn_t sx_interrupt (int irq, void *ptr)
        if (!(board->flags & SX_BOARD_INITIALIZED))
                return IRQ_HANDLED;
 
-       if (test_and_set_bit (SX_BOARD_INTR_LOCK, &board->locks)) {
-               printk (KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
+       if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
+               printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
                return IRQ_HANDLED;
        }
 
-        for (i=0;i<board->nports;i++) {
+       for (i = 0; i < board->nports; i++) {
                port = &board->ports[i];
                if (port->gs.flags & GS_ACTIVE) {
-                       if (sx_read_channel_byte (port, hi_state)) {
-                               sx_dprintk (SX_DEBUG_INTERRUPTS, 
-                                           "Port %d: modem signal change?... \n", i);
-                               sx_check_modem_signals (port); 
+                       if (sx_read_channel_byte(port, hi_state)) {
+                               sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
+                                               "modem signal change?... \n",i);
+                               sx_check_modem_signals(port);
                        }
                        if (port->gs.xmit_cnt) {
-                               sx_transmit_chars (port);
+                               sx_transmit_chars(port);
                        }
                        if (!(port->gs.flags & SX_RX_THROTTLE)) {
-                               sx_receive_chars (port);
+                               sx_receive_chars(port);
                        }
                }
        }
 
-       clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
+       clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
 
-       sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); 
-        func_exit ();
+       sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
+                       board->irq);
+       func_exit();
        return IRQ_HANDLED;
 }
 
-
-static void sx_pollfunc (unsigned long data)
+static void sx_pollfunc(unsigned long data)
 {
-       struct sx_board *board = (struct sx_board *) data;
-
-       func_enter ();
+       struct sx_board *board = (struct sx_board *)data;
 
-       sx_interrupt (0, board);
+       func_enter();
 
-       init_timer(&board->timer);
+       sx_interrupt(0, board);
 
-       board->timer.expires = jiffies + sx_poll;
-       add_timer (&board->timer);
-       func_exit ();
+       mod_timer(&board->timer, jiffies + sx_poll);
+       func_exit();
 }
 
-
-
 /* ********************************************************************** *
  *                Here are the routines that actually                     *
  *              interface with the generic_serial driver                  *
@@ -1319,9 +1365,9 @@ static void sx_pollfunc (unsigned long data)
 /* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
 /* Hmm. Ok I figured it out. You don't.  */
 
-static void sx_disable_tx_interrupts (void * ptr) 
+static void sx_disable_tx_interrupts(void *ptr)
 {
-       struct sx_port *port = ptr; 
+       struct sx_port *port = ptr;
        func_enter2();
 
        port->gs.flags &= ~GS_TX_INTEN;
@@ -1329,30 +1375,28 @@ static void sx_disable_tx_interrupts (void * ptr)
        func_exit();
 }
 
-
-static void sx_enable_tx_interrupts (void * ptr) 
+static void sx_enable_tx_interrupts(void *ptr)
 {
-       struct sx_port *port = ptr; 
+       struct sx_port *port = ptr;
        int data_in_buffer;
        func_enter2();
 
        /* First transmit the characters that we're supposed to */
-       sx_transmit_chars (port);
+       sx_transmit_chars(port);
 
        /* The sx card will never interrupt us if we don't fill the buffer
           past 25%. So we keep considering interrupts off if that's the case. */
-       data_in_buffer = (sx_read_channel_byte (port, hi_txipos) - 
-                         sx_read_channel_byte (port, hi_txopos)) & 0xff;
+       data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
+                         sx_read_channel_byte(port, hi_txopos)) & 0xff;
 
        /* XXX Must be "HIGH_WATER" for SI card according to doc. */
-       if (data_in_buffer < LOW_WATER) 
+       if (data_in_buffer < LOW_WATER)
                port->gs.flags &= ~GS_TX_INTEN;
 
        func_exit();
 }
 
-
-static void sx_disable_rx_interrupts (void * ptr) 
+static void sx_disable_rx_interrupts(void *ptr)
 {
        /*  struct sx_port *port = ptr; */
        func_enter();
@@ -1360,7 +1404,7 @@ static void sx_disable_rx_interrupts (void * ptr)
        func_exit();
 }
 
-static void sx_enable_rx_interrupts (void * ptr) 
+static void sx_enable_rx_interrupts(void *ptr)
 {
        /*  struct sx_port *port = ptr; */
        func_enter();
@@ -1368,55 +1412,48 @@ static void sx_enable_rx_interrupts (void * ptr)
        func_exit();
 }
 
-
 /* Jeez. Isn't this simple? */
-static int sx_get_CD (void * ptr) 
+static int sx_get_CD(void *ptr)
 {
        struct sx_port *port = ptr;
        func_enter2();
 
        func_exit();
-       return ((sx_read_channel_byte (port, hi_ip) & IP_DCD) != 0);
+       return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0);
 }
 
-
 /* Jeez. Isn't this simple? */
-static int sx_chars_in_buffer (void * ptr) 
+static int sx_chars_in_buffer(void *ptr)
 {
        struct sx_port *port = ptr;
        func_enter2();
 
        func_exit();
-       return ((sx_read_channel_byte (port, hi_txipos) - 
-                sx_read_channel_byte (port, hi_txopos)) & 0xff);
+       return ((sx_read_channel_byte(port, hi_txipos) -
+                sx_read_channel_byte(port, hi_txopos)) & 0xff);
 }
 
-
-static void sx_shutdown_port (void * ptr) 
+static void sx_shutdown_port(void *ptr)
 {
-       struct sx_port *port = ptr; 
+       struct sx_port *port = ptr;
 
        func_enter();
 
-       port->gs.flags &= ~ GS_ACTIVE;
+       port->gs.flags &= ~GS_ACTIVE;
        if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
-               sx_setsignals (port, 0, 0);
+               sx_setsignals(port, 0, 0);
                sx_reconfigure_port(port);
        }
 
        func_exit();
 }
 
-
-
-
-
 /* ********************************************************************** *
  *                Here are the routines that actually                     *
  *               interface with the rest of the system                    *
  * ********************************************************************** */
 
-static int sx_open  (struct tty_struct * tty, struct file * filp)
+static int sx_open(struct tty_struct *tty, struct file *filp)
 {
        struct sx_port *port;
        int retval, line;
@@ -1429,18 +1466,18 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
        }
 
        line = tty->index;
-       sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n", 
-                   current->pid, line, tty, current->signal->tty, sx_nports);
+       sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
+                       "np=%d)\n", current->pid, line, tty,
+                       current->signal->tty, sx_nports);
 
        if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
                return -ENODEV;
 
-       port = & sx_ports[line];
+       port = &sx_ports[line];
        port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
-                           1 -> 0 transition. */
+                           1 -> 0 transition. */
 
-
-       sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+       sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
 
        spin_lock_irqsave(&port->gs.driver_lock, flags);
 
@@ -1449,13 +1486,13 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
        port->gs.count++;
        spin_unlock_irqrestore(&port->gs.driver_lock, flags);
 
-       sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
+       sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
 
        /*
         * Start up serial port
         */
        retval = gs_init_port(&port->gs);
-       sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n");
+       sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
        if (retval) {
                port->gs.count--;
                return retval;
@@ -1463,19 +1500,20 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 
        port->gs.flags |= GS_ACTIVE;
        if (port->gs.count <= 1)
-               sx_setsignals (port, 1,1);
+               sx_setsignals(port, 1, 1);
 
 #if 0
        if (sx_debug & SX_DEBUG_OPEN)
-               my_hd (port, sizeof (*port));
+               my_hd(port, sizeof(*port));
 #else
        if (sx_debug & SX_DEBUG_OPEN)
-               my_hd_io (port->board->base + port->ch_base, sizeof (*port));
+               my_hd_io(port->board->base + port->ch_base, sizeof(*port));
 #endif
 
        if (port->gs.count <= 1) {
-               if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-                       printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
+               if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+                       printk(KERN_ERR "sx: Card didn't respond to LOPEN "
+                                       "command.\n");
                        spin_lock_irqsave(&port->gs.driver_lock, flags);
                        port->gs.count--;
                        spin_unlock_irqrestore(&port->gs.driver_lock, flags);
@@ -1484,75 +1522,76 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
        }
 
        retval = gs_block_til_ready(port, filp);
-       sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", 
-                   retval, port->gs.count);
+       sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
+                       retval, port->gs.count);
 
        if (retval) {
-               /* 
               * Don't lower gs.count here because sx_close() will be called later
-                */ 
+/*
+ * Don't lower gs.count here because sx_close() will be called later
+ */
 
                return retval;
        }
        /* tty->low_latency = 1; */
 
-       port->c_dcd = sx_get_CD (port);
-       sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+       port->c_dcd = sx_get_CD(port);
+       sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
 
        func_exit();
        return 0;
 
 }
 
-
-static void sx_close (void *ptr)
+static void sx_close(void *ptr)
 {
-       struct sx_port *port = ptr; 
+       struct sx_port *port = ptr;
        /* Give the port 5 seconds to close down. */
-       int to = 5 * HZ; 
+       int to = 5 * HZ;
 
-       func_enter ();
+       func_enter();
 
-       sx_setsignals (port, 0, 0);
-       sx_reconfigure_port(port);      
-       sx_send_command (port, HS_CLOSE, 0, 0);
+       sx_setsignals(port, 0, 0);
+       sx_reconfigure_port(port);
+       sx_send_command(port, HS_CLOSE, 0, 0);
 
-       while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED))
+       while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
                if (msleep_interruptible(10))
                        break;
-       if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
-               if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
-                       printk (KERN_ERR 
-                               "sx: sent the force_close command, but card didn't react\n");
+       if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
+               if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
+                               != 1) {
+                       printk(KERN_ERR "sx: sent the force_close command, but "
+                                       "card didn't react\n");
                } else
-                       sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
+                       sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
+                                       "command.\n");
        }
 
-       sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", 
-                   5 * HZ - to - 1, port->gs.count);
+       sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
+                       5 * HZ - to - 1, port->gs.count);
 
-       if(port->gs.count) {
-               sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
-               //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
-               //port->gs.count = 0;
+       if (port->gs.count) {
+               sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
+                               port->gs.count);
+               /*printk("%s SETTING port count to zero: %p count: %d\n",
+                               __FUNCTION__, port, port->gs.count);
+               port->gs.count = 0;*/
        }
 
-       func_exit ();
+       func_exit();
 }
 
-
-
 /* This is relatively thorough. But then again it is only 20 lines. */
-#define MARCHUP    for (i=min;i<max;i++) 
-#define MARCHDOWN  for (i=max-1;i>=min;i--)
-#define W0         write_sx_byte (board, i, 0x55)
-#define W1         write_sx_byte (board, i, 0xaa)
-#define R0         if (read_sx_byte (board, i) != 0x55) return 1
-#define R1         if (read_sx_byte (board, i) != 0xaa) return 1
+#define MARCHUP                for (i = min; i < max; i++)
+#define MARCHDOWN      for (i = max - 1; i >= min; i--)
+#define W0             write_sx_byte(board, i, 0x55)
+#define W1             write_sx_byte(board, i, 0xaa)
+#define R0             if (read_sx_byte(board, i) != 0x55) return 1
+#define R1             if (read_sx_byte(board, i) != 0xaa) return 1
 
 /* This memtest takes a human-noticable time. You normally only do it
    once a boot, so I guess that it is worth it. */
-static int do_memtest (struct sx_board *board, int min, int max)
+static int do_memtest(struct sx_board *board, int min, int max)
 {
        int i;
 
@@ -1561,16 +1600,37 @@ static int do_memtest (struct sx_board *board, int min, int max)
           intermittent errors. -- REW
           (For the theory behind memory testing see: 
           Testing Semiconductor Memories by A.J. van de Goor.) */
-       MARCHUP  {W0;}
-       MARCHUP   {R0;W1;R1;W0;R0;W1;}
-       MARCHUP   {R1;W0;W1;}
-       MARCHDOWN {R1;W0;W1;W0;}
-       MARCHDOWN {R0;W1;W0;}
+       MARCHUP {
+               W0;
+       }
+       MARCHUP {
+               R0;
+               W1;
+               R1;
+               W0;
+               R0;
+               W1;
+       }
+       MARCHUP {
+               R1;
+               W0;
+               W1;
+       }
+       MARCHDOWN {
+               R1;
+               W0;
+               W1;
+               W0;
+       }
+       MARCHDOWN {
+               R0;
+               W1;
+               W0;
+       }
 
        return 0;
 }
 
-
 #undef MARCHUP
 #undef MARCHDOWN
 #undef W0
@@ -1578,33 +1638,54 @@ static int do_memtest (struct sx_board *board, int min, int max)
 #undef R0
 #undef R1
 
-#define MARCHUP    for (i=min;i<max;i+=2) 
-#define MARCHDOWN  for (i=max-1;i>=min;i-=2)
-#define W0         write_sx_word (board, i, 0x55aa)
-#define W1         write_sx_word (board, i, 0xaa55)
-#define R0         if (read_sx_word (board, i) != 0x55aa) return 1
-#define R1         if (read_sx_word (board, i) != 0xaa55) return 1
+#define MARCHUP                for (i = min; i < max; i += 2)
+#define MARCHDOWN      for (i = max - 1; i >= min; i -= 2)
+#define W0             write_sx_word(board, i, 0x55aa)
+#define W1             write_sx_word(board, i, 0xaa55)
+#define R0             if (read_sx_word(board, i) != 0x55aa) return 1
+#define R1             if (read_sx_word(board, i) != 0xaa55) return 1
 
 #if 0
 /* This memtest takes a human-noticable time. You normally only do it
    once a boot, so I guess that it is worth it. */
-static int do_memtest_w (struct sx_board *board, int min, int max)
+static int do_memtest_w(struct sx_board *board, int min, int max)
 {
        int i;
 
-       MARCHUP   {W0;}
-       MARCHUP   {R0;W1;R1;W0;R0;W1;}
-       MARCHUP   {R1;W0;W1;}
-       MARCHDOWN {R1;W0;W1;W0;}
-       MARCHDOWN {R0;W1;W0;}
+       MARCHUP {
+               W0;
+       }
+       MARCHUP {
+               R0;
+               W1;
+               R1;
+               W0;
+               R0;
+               W1;
+       }
+       MARCHUP {
+               R1;
+               W0;
+               W1;
+       }
+       MARCHDOWN {
+               R1;
+               W0;
+               W1;
+               W0;
+       }
+       MARCHDOWN {
+               R0;
+               W1;
+               W0;
+       }
 
        return 0;
 }
 #endif
 
-
-static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg)
+static int sx_fw_ioctl(struct inode *inode, struct file *filp,
+               unsigned int cmd, unsigned long arg)
 {
        int rc = 0;
        int __user *descr = (int __user *)arg;
@@ -1616,7 +1697,7 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
 
        func_enter();
 
-#if 0 
+#if 0
        /* Removed superuser check: Sysops can use the permissions on the device
           file to restrict access. Recommendation: Root only. (root.root 600) */
        if (!capable(CAP_SYS_ADMIN)) {
@@ -1624,103 +1705,115 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
        }
 #endif
 
-       sx_dprintk (SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
+       sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
 
-       if (!board) board = &boards[0];
+       if (!board)
+               board = &boards[0];
        if (board->flags & SX_BOARD_PRESENT) {
-               sx_dprintk (SX_DEBUG_FIRMWARE, "Board present! (%x)\n", 
-                           board->flags);
+               sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
+                               board->flags);
        } else {
-               sx_dprintk (SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", 
-                           board->flags);
-               for (i=0;i< SX_NBOARDS;i++)
-                       sx_dprintk (SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
-               sx_dprintk (SX_DEBUG_FIRMWARE, "\n");
+               sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
+                               board->flags);
+               for (i = 0; i < SX_NBOARDS; i++)
+                       sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
+               sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
                return -EIO;
        }
 
        switch (cmd) {
        case SXIO_SET_BOARD:
-               sx_dprintk (SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
-               if (arg >= SX_NBOARDS) return -EIO;
-               sx_dprintk (SX_DEBUG_FIRMWARE, "not out of range\n");
-               if (!(boards[arg].flags & SX_BOARD_PRESENT)) return -EIO;
-               sx_dprintk (SX_DEBUG_FIRMWARE, ".. and present!\n");
+               sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+               if (arg >= SX_NBOARDS)
+                       return -EIO;
+               sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
+               if (!(boards[arg].flags & SX_BOARD_PRESENT))
+                       return -EIO;
+               sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
                board = &boards[arg];
                break;
        case SXIO_GET_TYPE:
-               rc = -ENOENT; /* If we manage to miss one, return error. */
-               if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
-               if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
-               if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
-               if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI;
-               if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
-               sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
+               rc = -ENOENT;   /* If we manage to miss one, return error. */
+               if (IS_SX_BOARD(board))
+                       rc = SX_TYPE_SX;
+               if (IS_CF_BOARD(board))
+                       rc = SX_TYPE_CF;
+               if (IS_SI_BOARD(board))
+                       rc = SX_TYPE_SI;
+               if (IS_SI1_BOARD(board))
+                       rc = SX_TYPE_SI;
+               if (IS_EISA_BOARD(board))
+                       rc = SX_TYPE_SI;
+               sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
                break;
        case SXIO_DO_RAMTEST:
-               if (sx_initialized) /* Already initialized: better not ramtest the board.  */
+               if (sx_initialized)     /* Already initialized: better not ramtest the board.  */
                        return -EPERM;
-               if (IS_SX_BOARD (board)) {
-                       rc          = do_memtest   (board, 0, 0x7000);
-                       if (!rc) rc = do_memtest   (board, 0, 0x7000);
-                       /*if (!rc) rc = do_memtest_w (board, 0, 0x7000);*/
+               if (IS_SX_BOARD(board)) {
+                       rc = do_memtest(board, 0, 0x7000);
+                       if (!rc)
+                               rc = do_memtest(board, 0, 0x7000);
+                       /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
                } else {
-                       rc             = do_memtest   (board, 0, 0x7ff8);
+                       rc = do_memtest(board, 0, 0x7ff8);
                        /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
                }
-               sx_dprintk (SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", rc);
+               sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
+                          rc);
                break;
        case SXIO_DOWNLOAD:
-               if (sx_initialized) /* Already initialized */
+               if (sx_initialized)     /* Already initialized */
                        return -EEXIST;
-               if (!sx_reset (board)) 
+               if (!sx_reset(board))
                        return -EIO;
-               sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
-               tmp = kmalloc (SX_CHUNK_SIZE, GFP_USER);
-               if (!tmp) return -ENOMEM;
-               get_user (nbytes, descr++);
-               get_user (offset, descr++); 
-               get_user (data,  descr++);
+               sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
+
+               tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
+               if (!tmp)
+                       return -ENOMEM;
+               get_user(nbytes, descr++);
+               get_user(offset, descr++);
+               get_user(data, descr++);
                while (nbytes && data) {
-                       for (i=0;i<nbytes;i += SX_CHUNK_SIZE) {
-                               if (copy_from_user(tmp, (char __user *)data+i, 
-                                                  (i + SX_CHUNK_SIZE >
-                                                   nbytes) ? nbytes - i :
-                                                             SX_CHUNK_SIZE)) {
-                                       kfree (tmp);
+                       for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
+                               if (copy_from_user(tmp, (char __user *)data + i,
+                                               (i + SX_CHUNK_SIZE > nbytes) ?
+                                               nbytes - i : SX_CHUNK_SIZE)) {
+                                       kfree(tmp);
                                        return -EFAULT;
                                }
-                               memcpy_toio(board->base2 + offset + i, tmp, 
-                                               (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
+                               memcpy_toio(board->base2 + offset + i, tmp,
+                                               (i + SX_CHUNK_SIZE > nbytes) ?
+                                               nbytes - i : SX_CHUNK_SIZE);
                        }
 
-                       get_user (nbytes, descr++);
-                       get_user (offset, descr++); 
-                       get_user (data,   descr++);
+                       get_user(nbytes, descr++);
+                       get_user(offset, descr++);
+                       get_user(data, descr++);
                }
-               kfree (tmp);
-               sx_nports += sx_init_board (board);
+               kfree(tmp);
+               sx_nports += sx_init_board(board);
                rc = sx_nports;
                break;
        case SXIO_INIT:
-               if (sx_initialized) /* Already initialized */
+               if (sx_initialized)     /* Already initialized */
                        return -EEXIST;
                /* This is not allowed until all boards are initialized... */
-               for (i=0;i<SX_NBOARDS;i++) {
-                       if ( (boards[i].flags & SX_BOARD_PRESENT) &&
-                            !(boards[i].flags & SX_BOARD_INITIALIZED))
+               for (i = 0; i < SX_NBOARDS; i++) {
+                       if ((boards[i].flags & SX_BOARD_PRESENT) &&
+                               !(boards[i].flags & SX_BOARD_INITIALIZED))
                                return -EIO;
                }
-               for (i=0;i<SX_NBOARDS;i++)
-                       if (!(boards[i].flags & SX_BOARD_PRESENT)) break;
-
-               sx_dprintk (SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
-                           "%d channels, first board: %d ports\n", 
-                           i, sx_nports, boards[0].nports);
-               rc = sx_init_portstructs (i, sx_nports);
-               sx_init_drivers ();
-               if (rc >= 0) 
+               for (i = 0; i < SX_NBOARDS; i++)
+                       if (!(boards[i].flags & SX_BOARD_PRESENT))
+                               break;
+
+               sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
+                               "%d channels, first board: %d ports\n",
+                               i, sx_nports, boards[0].nports);
+               rc = sx_init_portstructs(i, sx_nports);
+               sx_init_drivers();
+               if (rc >= 0)
                        sx_initialized++;
                break;
        case SXIO_SETDEBUG:
@@ -1737,32 +1830,32 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
                rc = sx_nports;
                break;
        default:
-               printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd);
+               printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
+                               cmd);
                break;
        }
-       func_exit ();
+       func_exit();
        return rc;
 }
 
-
-static void sx_break (struct tty_struct * tty, int flag)
+static void sx_break(struct tty_struct *tty, int flag)
 {
        struct sx_port *port = tty->driver_data;
        int rv;
 
-       func_enter ();
+       func_enter();
 
-       if (flag) 
-               rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
-       else 
-               rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
-       if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
-                       read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+       if (flag)
+               rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
+       else
+               rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
+       if (rv != 1)
+               printk(KERN_ERR "sx: couldn't send break (%x).\n",
+                       read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
 
-       func_exit ();
+       func_exit();
 }
 
-
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct sx_port *port = tty->driver_data;
@@ -1770,7 +1863,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 static int sx_tiocmset(struct tty_struct *tty, struct file *file,
-                      unsigned int set, unsigned int clear)
+               unsigned int set, unsigned int clear)
 {
        struct sx_port *port = tty->driver_data;
        int rts = -1, dtr = -1;
@@ -1789,8 +1882,8 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
-static int sx_ioctl (struct tty_struct * tty, struct file * filp, 
-                     unsigned int cmd, unsigned long arg)
+static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+               unsigned int cmd, unsigned long arg)
 {
        int rc;
        struct sx_port *port = tty->driver_data;
@@ -1803,10 +1896,10 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
        switch (cmd) {
        case TIOCGSOFTCAR:
                rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
-                             (unsigned __user *) argp);
+                               (unsigned __user *)argp);
                break;
        case TIOCSSOFTCAR:
-               if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
+               if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
                        tty->termios->c_cflag =
                                (tty->termios->c_cflag & ~CLOCAL) |
                                (ival ? CLOCAL : 0);
@@ -1827,7 +1920,6 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
        return rc;
 }
 
-
 /* The throttle/unthrottle scheme for the Specialix card is different
  * from other drivers and deserves some explanation. 
  * The Specialix hardware takes care of XON/XOFF
@@ -1844,7 +1936,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
  * flow control scheme is in use for that port. -- Simon Allen
  */
 
-static void sx_throttle (struct tty_struct * tty)
+static void sx_throttle(struct tty_struct *tty)
 {
        struct sx_port *port = (struct sx_port *)tty->driver_data;
 
@@ -1852,14 +1944,13 @@ static void sx_throttle (struct tty_struct * tty)
        /* If the port is using any type of input flow
         * control then throttle the port.
         */
-       if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
+       if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
                port->gs.flags |= SX_RX_THROTTLE;
        }
        func_exit();
 }
 
-
-static void sx_unthrottle (struct tty_struct * tty)
+static void sx_unthrottle(struct tty_struct *tty)
 {
        struct sx_port *port = (struct sx_port *)tty->driver_data;
 
@@ -1873,15 +1964,11 @@ static void sx_unthrottle (struct tty_struct * tty)
        return;
 }
 
-
 /* ********************************************************************** *
  *                    Here are the initialization routines.               *
  * ********************************************************************** */
 
-
-
-
-static int sx_init_board (struct sx_board *board)
+static int sx_init_board(struct sx_board *board)
 {
        int addr;
        int chans;
@@ -1893,36 +1980,38 @@ static int sx_init_board (struct sx_board *board)
 
        board->flags |= SX_BOARD_INITIALIZED;
 
-       if (read_sx_byte (board, 0))
+       if (read_sx_byte(board, 0))
                /* CF boards may need this. */
-               write_sx_byte(board,0, 0);
+               write_sx_byte(board, 0, 0);
 
        /* This resets the processor again, to make sure it didn't do any
           foolish things while we were downloading the image */
-       if (!sx_reset (board))
+       if (!sx_reset(board))
                return 0;
 
-       sx_start_board (board);
-       udelay (10);
-       if (!sx_busy_wait_neq (board, 0, 0xff, 0)) {
-               printk (KERN_ERR "sx: Ooops. Board won't initialize.\n");
+       sx_start_board(board);
+       udelay(10);
+       if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
+               printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
                return 0;
        }
 
        /* Ok. So now the processor on the card is running. It gathered
           some info for us... */
-       sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n");
-       if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base, 0x10);
-       sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n");
-       if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base + 0x80, 0x30);
-
-       sx_dprintk (SX_DEBUG_INIT, 
-                   "init_status: %x, %dk memory, firmware V%x.%02x,\n", 
-                   read_sx_byte (board, 0), read_sx_byte(board, 1), 
-                   read_sx_byte (board, 5), read_sx_byte(board, 4));
-
-       if (read_sx_byte (board, 0) == 0xff) {
-               printk (KERN_INFO "sx: No modules found. Sorry.\n");
+       sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
+       if (sx_debug & SX_DEBUG_INIT)
+               my_hd_io(board->base, 0x10);
+       sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
+       if (sx_debug & SX_DEBUG_INIT)
+               my_hd_io(board->base + 0x80, 0x30);
+
+       sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
+                       "V%x.%02x,\n",
+                       read_sx_byte(board, 0), read_sx_byte(board, 1),
+                       read_sx_byte(board, 5), read_sx_byte(board, 4));
+
+       if (read_sx_byte(board, 0) == 0xff) {
+               printk(KERN_INFO "sx: No modules found. Sorry.\n");
                board->nports = 0;
                return 0;
        }
@@ -1930,82 +2019,97 @@ static int sx_init_board (struct sx_board *board)
        chans = 0;
 
        if (IS_SX_BOARD(board)) {
-               sx_write_board_word (board, cc_int_count, sx_maxints);
+               sx_write_board_word(board, cc_int_count, sx_maxints);
        } else {
                if (sx_maxints)
-                       sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints);
+                       sx_write_board_word(board, cc_int_count,
+                                       SI_PROCESSOR_CLOCK / 8 / sx_maxints);
        }
 
        /* grab the first module type... */
-       /*  board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
-       board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip));
+       /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
+       board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
+                               mc_chip));
 
        /* XXX byteorder */
-       for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) {
-               type = sx_read_module_byte (board, addr, mc_chip);
-               sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n", 
-                           addr, read_sx_byte (board, addr + 2));
-
-               chans += sx_read_module_byte (board, addr, mc_type);
-
-               sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n", 
-                           mod_type_s (type),
-                           pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf),
-                           pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4));
-
-               sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n", 
-                           sx_read_module_byte (board, addr, mc_rev1),
-                           sx_read_module_byte (board, addr, mc_rev2),
-                           sx_read_module_byte (board, addr, mc_mtaasic_rev));
+       for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
+               type = sx_read_module_byte(board, addr, mc_chip);
+               sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
+                               addr, read_sx_byte(board, addr + 2));
+
+               chans += sx_read_module_byte(board, addr, mc_type);
+
+               sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
+                               "panels\n",
+                               mod_type_s(type),
+                               pan_type_s(sx_read_module_byte(board, addr,
+                                               mc_mods) & 0xf),
+                               pan_type_s(sx_read_module_byte(board, addr,
+                                               mc_mods) >> 4));
+
+               sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
+                       "version: %x\n",
+                       sx_read_module_byte(board, addr, mc_rev1),
+                       sx_read_module_byte(board, addr, mc_rev2),
+                       sx_read_module_byte(board, addr, mc_mtaasic_rev));
 
                /* The following combinations are illegal: It should theoretically
                   work, but timing problems make the bus HANG. */
 
-               if (mod_compat_type (type) != board->ta_type) {
-                       printk (KERN_ERR "sx: This is an invalid configuration.\n"
-                               "Don't mix TA/MTA/SXDC on the same hostadapter.\n");
-                       chans=0;
+               if (mod_compat_type(type) != board->ta_type) {
+                       printk(KERN_ERR "sx: This is an invalid "
+                               "configuration.\nDon't mix TA/MTA/SXDC on the "
+                               "same hostadapter.\n");
+                       chans = 0;
                        break;
                }
-               if ((IS_EISA_BOARD(board) || 
-                    IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
-                       printk (KERN_ERR "sx: This is an invalid configuration.\n"
-                               "Don't use SXDCs on an SI/XIO adapter.\n");
-                       chans=0;
+               if ((IS_EISA_BOARD(board) ||
+                               IS_SI_BOARD(board)) &&
+                               (mod_compat_type(type) == 4)) {
+                       printk(KERN_ERR "sx: This is an invalid "
+                               "configuration.\nDon't use SXDCs on an SI/XIO "
+                               "adapter.\n");
+                       chans = 0;
                        break;
                }
-#if 0 /* Problem fixed: firmware 3.05 */
+#if 0                          /* Problem fixed: firmware 3.05 */
                if (IS_SX_BOARD(board) && (type == TA8)) {
                        /* There are some issues with the firmware and the DCD/RTS
                           lines. It might work if you tie them together or something.
-                          It might also work if you get a newer sx_firmware.   Therefore
+                          It might also work if you get a newer sx_firmware.   Therefore
                           this is just a warning. */
-                       printk (KERN_WARNING "sx: The SX host doesn't work too well "
-                               "with the TA8 adapters.\nSpecialix is working on it.\n");
+                       printk(KERN_WARNING
+                              "sx: The SX host doesn't work too well "
+                              "with the TA8 adapters.\nSpecialix is working on it.\n");
                }
 #endif
        }
 
        if (chans) {
-               /* board->flags |= SX_BOARD_PRESENT; */
-               if(board->irq > 0) {
+               if (board->irq > 0) {
                        /* fixed irq, probably PCI */
-                       if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
-                               if(request_irq(board->irq, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) {
-                                       printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq);
+                       if (sx_irqmask & (1 << board->irq)) {   /* may we use this irq? */
+                               if (request_irq(board->irq, sx_interrupt,
+                                               IRQF_SHARED | IRQF_DISABLED,
+                                               "sx", board)) {
+                                       printk(KERN_ERR "sx: Cannot allocate "
+                                               "irq %d.\n", board->irq);
                                        board->irq = 0;
                                }
                        } else
                                board->irq = 0;
-               } else if(board->irq < 0 && sx_irqmask) {
+               } else if (board->irq < 0 && sx_irqmask) {
                        /* auto-allocate irq */
                        int irqnr;
-                       int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
-                       for(irqnr = 15; irqnr > 0; irqnr--)
-                               if(irqmask & (1 << irqnr))
-                                       if(! request_irq(irqnr, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board))
+                       int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
+                                       SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
+                       for (irqnr = 15; irqnr > 0; irqnr--)
+                               if (irqmask & (1 << irqnr))
+                                       if (!request_irq(irqnr, sx_interrupt,
+                                               IRQF_SHARED | IRQF_DISABLED,
+                                               "sx", board))
                                                break;
-                       if(! irqnr)
+                       if (!irqnr)
                                printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
                        board->irq = irqnr;
                } else
@@ -2013,52 +2117,48 @@ static int sx_init_board (struct sx_board *board)
 
                if (board->irq) {
                        /* Found a valid interrupt, start up interrupts! */
-                       sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq);
-                       sx_start_interrupts (board);
+                       sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
+                                       board->irq);
+                       sx_start_interrupts(board);
                        board->poll = sx_slowpoll;
                        board->flags |= SX_IRQ_ALLOCATED;
                } else {
                        /* no irq: setup board for polled operation */
                        board->poll = sx_poll;
-                       sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll);
+                       sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
+                                       board->poll);
                }
 
-               /* The timer should be initialized anyway: That way we can safely
-                        del_timer it when the module is unloaded. */
-               init_timer (&board->timer);
+               /* The timer should be initialized anyway: That way we can
+                  safely del_timer it when the module is unloaded. */
+               setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
 
-               if (board->poll) {
-                       board->timer.data = (unsigned long) board;
-                       board->timer.function = sx_pollfunc;
-                       board->timer.expires = jiffies + board->poll;
-                       add_timer (&board->timer);
-               }
+               if (board->poll)
+                       mod_timer(&board->timer, jiffies + board->poll);
        } else {
                board->irq = 0;
        }
 
        board->nports = chans;
-       sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports);
+       sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
 
        func_exit();
        return chans;
 }
 
-
-static void printheader(void)
+static void __devinit printheader(void)
 {
        static int header_printed;
 
        if (!header_printed) {
-               printk (KERN_INFO "Specialix SX driver "
-                       "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n");
-               printk (KERN_INFO "sx: version %s\n", RCS_ID);
+               printk(KERN_INFO "Specialix SX driver "
+                       "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
+               printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
                header_printed = 1;
        }
 }
 
-
-static int probe_sx (struct sx_board *board)
+static int __devinit probe_sx(struct sx_board *board)
 {
        struct vpd_prom vpdp;
        char *p;
@@ -2066,51 +2166,57 @@ static int probe_sx (struct sx_board *board)
 
        func_enter();
 
-       if (!IS_CF_BOARD (board)) {    
-               sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", 
-                           board->base + SX_VPD_ROM);
+       if (!IS_CF_BOARD(board)) {
+               sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
+                               board->base + SX_VPD_ROM);
 
                if (sx_debug & SX_DEBUG_PROBE)
                        my_hd_io(board->base + SX_VPD_ROM, 0x40);
 
-               p = (char *) &vpdp;
-               for (i=0;i< sizeof (struct vpd_prom);i++)
-                       *p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
+               p = (char *)&vpdp;
+               for (i = 0; i < sizeof(struct vpd_prom); i++)
+                       *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
 
                if (sx_debug & SX_DEBUG_PROBE)
-                       my_hd (&vpdp, 0x20);
+                       my_hd(&vpdp, 0x20);
 
-               sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+               sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
 
-               if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-                       sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", 
-                                   vpdp.identifier); 
+               if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
+                       sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
+                                       "'%s'\n", vpdp.identifier);
                        return 0;
                }
        }
 
-       printheader ();
-
-       if (!IS_CF_BOARD (board)) {
-               printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base);
-               printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", 
-                       vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-               printk (           "Manufactured: %d/%d\n", 
-                       1970 + vpdp.myear, vpdp.mweek);
+       printheader();
 
+       if (!IS_CF_BOARD(board)) {
+               printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
+                       board->hw_base);
+               printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
+                               "uniq ID:%08x, ",
+                               vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
+               printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
 
-               if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
-                   (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-                       /* This might be a bit harsh. This was the primary reason the
-                          SX/ISA card didn't work at first... */
-                       printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
+               if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
+                               SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
+                               SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
+                       /* This might be a bit harsh. This was the primary
+                          reason the SX/ISA card didn't work at first... */
+                       printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
+                                       "card. Sorry: giving up.\n");
                        return (0);
                }
 
-               if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
+               if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
+                               SX_ISA_UNIQUEID1) {
                        if (((unsigned long)board->hw_base) & 0x8000) {
-                               printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
-                               printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
+                               printk(KERN_WARNING "sx: Warning: There may be "
+                                       "hardware problems with the card at "
+                                       "%lx.\n", board->hw_base);
+                               printk(KERN_WARNING "sx: Read sx.txt for more "
+                                               "info.\n");
                        }
                }
        }
@@ -2118,17 +2224,15 @@ static int probe_sx (struct sx_board *board)
        board->nports = -1;
 
        /* This resets the processor, and keeps it off the bus. */
-       if (!sx_reset (board)) 
+       if (!sx_reset(board))
                return 0;
-       sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
-       board->flags |= SX_BOARD_PRESENT;
+       sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
 
        func_exit();
        return 1;
 }
 
-
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 
 /* Specialix probes for this card at 32k increments from 640k to 16M.
    I consider machines with less than 16M unlikely nowadays, so I'm
@@ -2136,28 +2240,27 @@ static int probe_sx (struct sx_board *board)
    card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
    0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
 
-static int probe_si (struct sx_board *board)
+static int __devinit probe_si(struct sx_board *board)
 {
        int i;
 
        func_enter();
-       sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %p.\n", board->hw_base,
-                   board->base + SI2_ISA_ID_BASE);
+       sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
+               "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
 
        if (sx_debug & SX_DEBUG_PROBE)
                my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
 
        if (!IS_EISA_BOARD(board)) {
-         if( IS_SI1_BOARD(board) ) 
-           {
-               for (i=0;i<8;i++) {
-                 write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i); 
-
+               if (IS_SI1_BOARD(board)) {
+                       for (i = 0; i < 8; i++) {
+                               write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
+                       }
                }
-           }
-               for (i=0;i<8;i++) {
-                       if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
-                               func_exit ();
+               for (i = 0; i < 8; i++) {
+                       if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
+                                       != i) {
+                               func_exit();
                                return 0;
                        }
                }
@@ -2167,20 +2270,20 @@ static int probe_si (struct sx_board *board)
           but to prevent trouble, we'd better double check that we don't
           have an SI1 board when we're probing for an SI2 board.... */
 
-       write_sx_byte (board, SI2_ISA_ID_BASE,0x10); 
-       if ( IS_SI1_BOARD(board)) {
+       write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+       if (IS_SI1_BOARD(board)) {
                /* This should be an SI1 board, which has this
                   location writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
-                       func_exit ();
-                       return 0; 
+               if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
+                       func_exit();
+                       return 0;
                }
        } else {
                /* This should be an SI2 board, which has the bottom
                   3 bits non-writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
-                       func_exit ();
-                       return 0; 
+               if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+                       func_exit();
+                       return 0;
                }
        }
 
@@ -2188,45 +2291,44 @@ static int probe_si (struct sx_board *board)
           but to prevent trouble, we'd better double check that we don't
           have an SI1 board when we're probing for an SI2 board.... */
 
-       write_sx_byte (board, SI2_ISA_ID_BASE,0x10); 
-       if ( IS_SI1_BOARD(board)) {
+       write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+       if (IS_SI1_BOARD(board)) {
                /* This should be an SI1 board, which has this
                   location writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
+               if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
                        func_exit();
-                       return 0; 
+                       return 0;
                }
        } else {
                /* This should be an SI2 board, which has the bottom
                   3 bits non-writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
-                       func_exit ();
-                       return 0; 
+               if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+                       func_exit();
+                       return 0;
                }
        }
 
-       printheader ();
+       printheader();
 
-       printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
+       printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
        /* Compared to the SX boards, it is a complete guess as to what
-                this card is up to... */
+          this card is up to... */
 
        board->nports = -1;
 
        /* This resets the processor, and keeps it off the bus. */
-       if (!sx_reset (board)) 
+       if (!sx_reset(board))
                return 0;
-       sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
-       board->flags |= SX_BOARD_PRESENT;
+       sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
 
        func_exit();
        return 1;
 }
+#endif
 
 static const struct tty_operations sx_ops = {
        .break_ctl = sx_break,
-       .open   = sx_open,
+       .open = sx_open,
        .close = gs_close,
        .write = gs_write,
        .put_char = gs_put_char,
@@ -2261,34 +2363,23 @@ static int sx_init_drivers(void)
        sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
        sx_driver->subtype = SERIAL_TYPE_NORMAL;
        sx_driver->init_termios = tty_std_termios;
-       sx_driver->init_termios.c_cflag =
-         B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       sx_driver->init_termios.c_ispeed = 9600;
+       sx_driver->init_termios.c_ospeed = 9600;
        sx_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(sx_driver, &sx_ops);
 
        if ((error = tty_register_driver(sx_driver))) {
                put_tty_driver(sx_driver);
                printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
-                      error);
+                       error);
                return 1;
        }
        func_exit();
        return 0;
 }
 
-
-static void * ckmalloc (int size)
-{
-       void *p;
-
-       p = kmalloc(size, GFP_KERNEL);
-       if (p) 
-               memset(p, 0, size);
-       return p;
-}
-
-
-static int sx_init_portstructs (int nboards, int nports)
+static int sx_init_portstructs(int nboards, int nports)
 {
        struct sx_board *board;
        struct sx_port *port;
@@ -2299,8 +2390,9 @@ static int sx_init_portstructs (int nboards, int nports)
        func_enter();
 
        /* Many drivers statically allocate the maximum number of ports
-          There is no reason not to allocate them dynamically. Is there? -- REW */
-       sx_ports          = ckmalloc(nports * sizeof (struct sx_port));
+          There is no reason not to allocate them dynamically.
+          Is there? -- REW */
+       sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
        if (!sx_ports)
                return -ENOMEM;
 
@@ -2308,10 +2400,10 @@ static int sx_init_portstructs (int nboards, int nports)
        for (i = 0; i < nboards; i++) {
                board = &boards[i];
                board->ports = port;
-               for (j=0; j < boards[i].nports;j++) {
-                       sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j);
+               for (j = 0; j < boards[i].nports; j++) {
+                       sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
                        port->gs.magic = SX_MAGIC;
-                       port->gs.close_delay = HZ/2;
+                       port->gs.close_delay = HZ / 2;
                        port->gs.closing_wait = 30 * HZ;
                        port->board = board;
                        port->gs.rd = &sx_real_driver;
@@ -2323,8 +2415,8 @@ static int sx_init_portstructs (int nboards, int nports)
                         * Initializing wait queue
                         */
                        init_waitqueue_head(&port->gs.open_wait);
-                       init_waitqueue_head(&port->gs.close_wait);              
-                       
+                       init_waitqueue_head(&port->gs.close_wait);
+
                        port++;
                }
        }
@@ -2335,28 +2427,36 @@ static int sx_init_portstructs (int nboards, int nports)
                board = &boards[i];
                board->port_base = portno;
                /* Possibly the configuration was rejected. */
-               sx_dprintk (SX_DEBUG_PROBE, "Board has %d channels\n", board->nports);
-               if (board->nports <= 0) continue;
+               sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
+                               board->nports);
+               if (board->nports <= 0)
+                       continue;
                /* XXX byteorder ?? */
-               for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) {
-                       chans = sx_read_module_byte (board, addr, mc_type); 
-                       sx_dprintk (SX_DEBUG_PROBE, "Module at %x: %d channels\n", addr, chans);
-                       sx_dprintk (SX_DEBUG_PROBE, "Port at");
-                       for (j=0;j<chans;j++) {
-                               /* The "sx-way" is the way it SHOULD be done. That way in the 
-                                  future, the firmware may for example pack the structures a bit
-                                  more efficient. Neil tells me it isn't going to happen anytime
-                                  soon though. */
+               for (addr = 0x80; addr != 0;
+                               addr = read_sx_word(board, addr) & 0x7fff) {
+                       chans = sx_read_module_byte(board, addr, mc_type);
+                       sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
+                                       "channels\n", addr, chans);
+                       sx_dprintk(SX_DEBUG_PROBE, "Port at");
+                       for (j = 0; j < chans; j++) {
+                               /* The "sx-way" is the way it SHOULD be done.
+                                  That way in the future, the firmware may for
+                                  example pack the structures a bit more
+                                  efficient. Neil tells me it isn't going to
+                                  happen anytime soon though. */
                                if (IS_SX_BOARD(board))
-                                       port->ch_base = sx_read_module_word (board, addr+j*2, mc_chan_pointer);
+                                       port->ch_base = sx_read_module_word(
+                                                       board, addr + j * 2,
+                                                       mc_chan_pointer);
                                else
-                                       port->ch_base = addr + 0x100 + 0x300*j;
+                                       port->ch_base = addr + 0x100 + 0x300 *j;
 
-                               sx_dprintk (SX_DEBUG_PROBE, " %x", port->ch_base);
+                               sx_dprintk(SX_DEBUG_PROBE, " %x",
+                                               port->ch_base);
                                port->line = portno++;
                                port++;
                        }
-                       sx_dprintk (SX_DEBUG_PROBE, "\n");
+                       sx_dprintk(SX_DEBUG_PROBE, "\n");
                }
                /* This has to be done earlier. */
                /* board->flags |= SX_BOARD_INITIALIZED; */
@@ -2366,6 +2466,17 @@ static int sx_init_portstructs (int nboards, int nports)
        return 0;
 }
 
+static unsigned int sx_find_free_board(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < SX_NBOARDS; i++)
+               if (!(boards[i].flags & SX_BOARD_PRESENT))
+                       break;
+
+       return i;
+}
+
 static void __exit sx_release_drivers(void)
 {
        func_enter();
@@ -2374,7 +2485,122 @@ static void __exit sx_release_drivers(void)
        func_exit();
 }
 
-#ifdef CONFIG_PCI
+static void __devexit sx_remove_card(struct sx_board *board,
+               struct pci_dev *pdev)
+{
+       if (board->flags & SX_BOARD_INITIALIZED) {
+               /* The board should stop messing with us. (actually I mean the
+                  interrupt) */
+               sx_reset(board);
+               if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
+                       free_irq(board->irq, board);
+
+               /* It is safe/allowed to del_timer a non-active timer */
+               del_timer(&board->timer);
+               if (pdev) {
+                       pci_iounmap(pdev, board->base);
+                       pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
+               } else {
+                       iounmap(board->base);
+                       release_region(board->hw_base, board->hw_len);
+               }
+
+               board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
+       }
+}
+
+#ifdef CONFIG_EISA
+
+static int __devinit sx_eisa_probe(struct device *dev)
+{
+       struct eisa_device *edev = to_eisa_device(dev);
+       struct sx_board *board;
+       unsigned long eisa_slot = edev->base_addr;
+       unsigned int i;
+       int retval = -EIO;
+
+       mutex_lock(&sx_boards_lock);
+       i = sx_find_free_board();
+       if (i == SX_NBOARDS) {
+               mutex_unlock(&sx_boards_lock);
+               goto err;
+       }
+       board = &boards[i];
+       board->flags |= SX_BOARD_PRESENT;
+       mutex_unlock(&sx_boards_lock);
+
+       dev_info(dev, "XIO : Signature found in EISA slot %lu, "
+                "Product %d Rev %d (REPORT THIS TO LKLM)\n",
+                eisa_slot >> 12,
+                inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
+                inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
+
+       board->eisa_base = eisa_slot;
+       board->flags &= ~SX_BOARD_TYPE;
+       board->flags |= SI_EISA_BOARD;
+
+       board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
+                         inb(eisa_slot + 0xc00)) << 16;
+       board->hw_len = SI2_EISA_WINDOW_LEN;
+       if (!request_region(board->hw_base, board->hw_len, "sx")) {
+               dev_err(dev, "can't request region\n");
+               goto err_flag;
+       }
+       board->base2 =
+       board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+       if (!board->base) {
+               dev_err(dev, "can't remap memory\n");
+               goto err_reg;
+       }
+
+       sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
+       sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
+       board->irq = inb(eisa_slot + 0xc02) >> 4;
+       sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+
+       if (!probe_si(board))
+               goto err_unmap;
+
+       dev_set_drvdata(dev, board);
+
+       return 0;
+err_unmap:
+       iounmap(board->base);
+err_reg:
+       release_region(board->hw_base, board->hw_len);
+err_flag:
+       board->flags &= ~SX_BOARD_PRESENT;
+err:
+       return retval;
+}
+
+static int __devexit sx_eisa_remove(struct device *dev)
+{
+       struct sx_board *board = dev_get_drvdata(dev);
+
+       sx_remove_card(board, NULL);
+
+       return 0;
+}
+
+static struct eisa_device_id sx_eisa_tbl[] = {
+       { "SLX" },
+       { "" }
+};
+
+MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
+
+static struct eisa_driver sx_eisadriver = {
+       .id_table = sx_eisa_tbl,
+       .driver = {
+               .name = "sx",
+               .probe = sx_eisa_probe,
+               .remove = __devexit_p(sx_eisa_remove),
+       }
+};
+
+#endif
+
  /******************************************************** 
  * Setting bit 17 in the CNTRL register of the PLX 9050  * 
  * chip forces a retry on writes while a read is pending.*
@@ -2386,233 +2612,265 @@ static void __exit sx_release_drivers(void)
    EEprom.  As the bit is read/write for the CPU, we can fix it here,
    if we detect that it isn't set correctly. -- REW */
 
-static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board)
+static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
 {
        unsigned int hwbase;
        void __iomem *rebase;
        unsigned int t;
 
-#define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x18260000
+#define CNTRL_REG_OFFSET       0x50
+#define CNTRL_REG_GOODVALUE    0x18260000
 
        pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
        hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
        rebase = ioremap(hwbase, 0x80);
-       t = readl (rebase + CNTRL_REG_OFFSET);
+       t = readl(rebase + CNTRL_REG_OFFSET);
        if (t != CNTRL_REG_GOODVALUE) {
-               printk (KERN_DEBUG "sx: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); 
-               writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+               printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
+                       "%08x\n", t, CNTRL_REG_GOODVALUE);
+               writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
        }
        iounmap(rebase);
 }
-#endif
-
 
-static int __init sx_init(void) 
+static int __devinit sx_pci_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
 {
-       int i;
-       int found = 0;
-       int eisa_slot;
        struct sx_board *board;
+       unsigned int i, reg;
+       int retval = -EIO;
 
-#ifdef CONFIG_PCI
-       struct pci_dev *pdev = NULL;
-       unsigned int tint;
-       unsigned short tshort;
-#endif
+       mutex_lock(&sx_boards_lock);
+       i = sx_find_free_board();
+       if (i == SX_NBOARDS) {
+               mutex_unlock(&sx_boards_lock);
+               goto err;
+       }
+       board = &boards[i];
+       board->flags |= SX_BOARD_PRESENT;
+       mutex_unlock(&sx_boards_lock);
 
-       func_enter();
-       sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug);
-       if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) {
-               printk (KERN_WARNING "sx: sx_debug is an address, instead of a value. "
-                       "Assuming -1.\n");
-               printk ("(%p)\n", &sx_debug);
-               sx_debug=-1;
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto err_flag;
+
+       board->flags &= ~SX_BOARD_TYPE;
+       board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
+               SX_CFPCI_BOARD;
+
+       /* CF boards use base address 3.... */
+       reg = IS_CF_BOARD(board) ? 3 : 2;
+       retval = pci_request_region(pdev, reg, "sx");
+       if (retval) {
+               dev_err(&pdev->dev, "can't request region\n");
+               goto err_flag;
+       }
+       board->hw_base = pci_resource_start(pdev, reg);
+       board->base2 =
+       board->base = pci_iomap(pdev, reg, WINDOW_LEN(board));
+       if (!board->base) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               goto err_reg;
        }
 
-       if (misc_register(&sx_fw_device) < 0) {
-               printk(KERN_ERR "SX: Unable to register firmware loader driver.\n");
-               return -EIO;
+       /* Most of the stuff on the CF board is offset by 0x18000 ....  */
+       if (IS_CF_BOARD(board))
+               board->base += 0x18000;
+
+       board->irq = pdev->irq;
+
+       dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
+                board->irq, board->flags);
+
+       if (!probe_sx(board)) {
+               retval = -EIO;
+               goto err_unmap;
        }
 
-#ifdef CONFIG_PCI
-       while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
-                                       PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 
-                                             pdev))) {
-               if (pci_enable_device(pdev))
-                       continue;
+       fix_sx_pci(pdev, board);
 
-               /* Specialix has a whole bunch of cards with
-                  0x2000 as the device ID. They say its because
-                  the standard requires it. Stupid standard. */
-               /* It seems that reading a word doesn't work reliably on 2.0.
-                  Also, reading a non-aligned dword doesn't work. So we read the
-                  whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
-                  ourselves */
-               /* I don't know why the define doesn't work, constant 0x2c does --REW */ 
-               pci_read_config_dword (pdev, 0x2c, &tint);
-               tshort = (tint >> 16) & 0xffff;
-               sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-               /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d    (%x)\n", pdev, tint); */ 
-               if ((tshort != 0x0200) && (tshort != 0x0300)) {
-                       sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", 
-                                   tshort);
-                       continue;
-               }
-               board = &boards[found];
+       pci_set_drvdata(pdev, board);
 
-               board->flags &= ~SX_BOARD_TYPE;
-               board->flags |= (tshort == 0x200)?SX_PCI_BOARD:
-                                                 SX_CFPCI_BOARD;
-
-               /* CF boards use base address 3.... */
-               if (IS_CF_BOARD (board))
-                       board->hw_base = pci_resource_start (pdev, 3);
-               else
-                       board->hw_base = pci_resource_start (pdev, 2);
-               board->base2 = 
-               board->base = ioremap(board->hw_base, WINDOW_LEN (board));
-               if (!board->base) {
-                       printk(KERN_ERR "ioremap failed\n");
-                       /* XXX handle error */
-               }
+       return 0;
+err_unmap:
+       pci_iounmap(pdev, board->base);
+err_reg:
+       pci_release_region(pdev, reg);
+err_flag:
+       board->flags &= ~SX_BOARD_PRESENT;
+err:
+       return retval;
+}
 
-               /* Most of the stuff on the CF board is offset by
-                  0x18000 ....  */
-               if (IS_CF_BOARD (board)) board->base += 0x18000;
+static void __devexit sx_pci_remove(struct pci_dev *pdev)
+{
+       struct sx_board *board = pci_get_drvdata(pdev);
 
-               board->irq = pdev->irq;
+       sx_remove_card(board, pdev);
+}
 
-               sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n", 
-                           tint, boards[found].base, board->irq, board->flags);
+/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
+   its because the standard requires it. So check for SUBVENDOR_ID. */
+static struct pci_device_id sx_pci_tbl[] = {
+       { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+               .subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+       { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+               .subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+       { 0 }
+};
 
-               if (probe_sx (board)) {
-                       found++;
-                       fix_sx_pci (pdev, board);
-               } else 
-                       iounmap(board->base2);
-       }
+MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
+
+static struct pci_driver sx_pcidriver = {
+       .name = "sx",
+       .id_table = sx_pci_tbl,
+       .probe = sx_pci_probe,
+       .remove = __devexit_p(sx_pci_remove)
+};
+
+static int __init sx_init(void)
+{
+#ifdef CONFIG_EISA
+       int retval1;
 #endif
+#ifdef CONFIG_ISA
+       struct sx_board *board;
+       unsigned int i;
+#endif
+       unsigned int found = 0;
+       int retval;
+
+       func_enter();
+       sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
+                       sx_debug);
+       if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
+               printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
+                               "value. Assuming -1.\n(%p)\n", &sx_debug);
+               sx_debug = -1;
+       }
 
-       for (i=0;i<NR_SX_ADDRS;i++) {
+       if (misc_register(&sx_fw_device) < 0) {
+               printk(KERN_ERR "SX: Unable to register firmware loader "
+                               "driver.\n");
+               return -EIO;
+       }
+#ifdef CONFIG_ISA
+       for (i = 0; i < NR_SX_ADDRS; i++) {
                board = &boards[found];
                board->hw_base = sx_probe_addrs[i];
+               board->hw_len = SX_WINDOW_LEN;
+               if (!request_region(board->hw_base, board->hw_len, "sx"))
+                       continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, SX_WINDOW_LEN);
+               board->base = ioremap(board->hw_base, board->hw_len);
+               if (!board->base)
+                       goto err_sx_reg;
                board->flags &= ~SX_BOARD_TYPE;
-               board->flags |= SX_ISA_BOARD;
-               board->irq = sx_irqmask?-1:0;
+               board->flags |= SX_ISA_BOARD;
+               board->irq = sx_irqmask ? -1 : 0;
 
-               if (probe_sx (board)) {
+               if (probe_sx(board)) {
+                       board->flags |= SX_BOARD_PRESENT;
                        found++;
                } else {
                        iounmap(board->base);
+err_sx_reg:
+                       release_region(board->hw_base, board->hw_len);
                }
        }
 
-       for (i=0;i<NR_SI_ADDRS;i++) {
+       for (i = 0; i < NR_SI_ADDRS; i++) {
                board = &boards[found];
                board->hw_base = si_probe_addrs[i];
+               board->hw_len = SI2_ISA_WINDOW_LEN;
+               if (!request_region(board->hw_base, board->hw_len, "sx"))
+                       continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
+               board->base = ioremap(board->hw_base, board->hw_len);
+               if (!board->base)
+                       goto err_si_reg;
                board->flags &= ~SX_BOARD_TYPE;
-               board->flags |=  SI_ISA_BOARD;
-               board->irq = sx_irqmask ?-1:0;
+               board->flags |= SI_ISA_BOARD;
+               board->irq = sx_irqmask ? -1 : 0;
 
-               if (probe_si (board)) {
+               if (probe_si(board)) {
+                       board->flags |= SX_BOARD_PRESENT;
                        found++;
                } else {
-                       iounmap (board->base);
+                       iounmap(board->base);
+err_si_reg:
+                       release_region(board->hw_base, board->hw_len);
                }
        }
-       for (i=0;i<NR_SI1_ADDRS;i++) {
+       for (i = 0; i < NR_SI1_ADDRS; i++) {
                board = &boards[found];
                board->hw_base = si1_probe_addrs[i];
+               board->hw_len = SI1_ISA_WINDOW_LEN;
+               if (!request_region(board->hw_base, board->hw_len, "sx"))
+                       continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN);
+               board->base = ioremap(board->hw_base, board->hw_len);
+               if (!board->base)
+                       goto err_si1_reg;
                board->flags &= ~SX_BOARD_TYPE;
-               board->flags |=  SI1_ISA_BOARD;
-               board->irq = sx_irqmask ?-1:0;
+               board->flags |= SI1_ISA_BOARD;
+               board->irq = sx_irqmask ? -1 : 0;
 
-               if (probe_si (board)) {
+               if (probe_si(board)) {
+                       board->flags |= SX_BOARD_PRESENT;
                        found++;
                } else {
-                       iounmap (board->base);
+                       iounmap(board->base);
+err_si1_reg:
+                       release_region(board->hw_base, board->hw_len);
                }
        }
+#endif
+#ifdef CONFIG_EISA
+       retval1 = eisa_driver_register(&sx_eisadriver);
+#endif
+       retval = pci_register_driver(&sx_pcidriver);
 
-        sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
-        for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
-        {
-                if((inb(eisa_slot+0xc80)==0x4d) &&
-                   (inb(eisa_slot+0xc81)==0x98))
-                {
-                       sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
-                                               "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
-
-                       board = &boards[found];
-                       board->eisa_base = eisa_slot;
-                       board->flags &= ~SX_BOARD_TYPE;
-                       board->flags |= SI_EISA_BOARD;
-
-                       board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
-                       board->base2 =
-                       board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
-
-                       sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
-                       sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
-                       board->irq = inb(board->eisa_base+0xc02)>>4; 
-                       sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
-                       
-                       probe_si(board);
-
-                       found++;
-               }
-       }
        if (found) {
-               printk (KERN_INFO "sx: total of %d boards detected.\n", found);
-       } else {
-               misc_deregister(&sx_fw_device);
+               printk(KERN_INFO "sx: total of %d boards detected.\n", found);
+               retval = 0;
+       } else if (retval) {
+#ifdef CONFIG_EISA
+               retval = retval1;
+               if (retval1)
+#endif
+                       misc_deregister(&sx_fw_device);
        }
 
        func_exit();
-       return found?0:-EIO;
+       return retval;
 }
 
-
-static void __exit sx_exit (void)
+static void __exit sx_exit(void)
 {
-       int i; 
-       struct sx_board *board;
+       int i;
 
        func_enter();
-       for (i = 0; i < SX_NBOARDS; i++) {
-               board = &boards[i];
-               if (board->flags & SX_BOARD_INITIALIZED) {
-                       sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %p\n", board->base);
-                       /* The board should stop messing with us.
-                          (actually I mean the interrupt) */
-                       sx_reset (board);
-                       if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
-                               free_irq (board->irq, board);
-
-                       /* It is safe/allowed to del_timer a non-active timer */
-                       del_timer (& board->timer);
-                       iounmap(board->base);
-               }
-       }
+#ifdef CONFIG_EISA
+       eisa_driver_unregister(&sx_eisadriver);
+#endif
+       pci_unregister_driver(&sx_pcidriver);
+
+       for (i = 0; i < SX_NBOARDS; i++)
+               sx_remove_card(&boards[i], NULL);
+
        if (misc_deregister(&sx_fw_device) < 0) {
-               printk (KERN_INFO "sx: couldn't deregister firmware loader device\n");
+               printk(KERN_INFO "sx: couldn't deregister firmware loader "
+                               "device\n");
        }
-       sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized);
+       sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
+                       sx_initialized);
        if (sx_initialized)
-               sx_release_drivers ();
+               sx_release_drivers();
 
-       kfree (sx_ports);
+       kfree(sx_ports);
        func_exit();
 }
 
 module_init(sx_init);
 module_exit(sx_exit);
-
-
index e01f83c..432aad0 100644 (file)
@@ -35,6 +35,7 @@ struct sx_board {
   void __iomem *base;
   void __iomem *base2;
   unsigned long hw_base;
+  resource_size_t hw_len;
   int eisa_base;
   int port_base; /* Number of the first port */
   struct sx_port *ports;
index 06784ad..acc6fab 100644 (file)
 #include <linux/hdlc.h>
 #include <linux/dma-mapping.h>
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -320,7 +322,7 @@ struct mgsl_struct {
        int dosyncppp;
        spinlock_t netlock;
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 };
@@ -728,7 +730,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info );
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(struct mgsl_struct *info);
 static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
@@ -802,7 +804,7 @@ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, u
 /*
  * Bottom half interrupt handlers
  */
-static void mgsl_bh_handler(void* Context);
+static void mgsl_bh_handler(struct work_struct *work);
 static void mgsl_bh_receive(struct mgsl_struct *info);
 static void mgsl_bh_transmit(struct mgsl_struct *info);
 static void mgsl_bh_status(struct mgsl_struct *info);
@@ -1071,9 +1073,10 @@ static int mgsl_bh_action(struct mgsl_struct *info)
 /*
  *     Perform bottom half processing of work items queued by ISR.
  */
-static void mgsl_bh_handler(void* Context)
+static void mgsl_bh_handler(struct work_struct *work)
 {
-       struct mgsl_struct *info = (struct mgsl_struct*)Context;
+       struct mgsl_struct *info =
+               container_of(work, struct mgsl_struct, task);
        int action;
 
        if (!info)
@@ -1276,7 +1279,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info )
                info->drop_rts_on_tx_done = 0;
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else 
@@ -1341,7 +1344,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
                                info->input_signal_events.dcd_up++;
                        } else
                                info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount) {
                                if (status & MISCSTATUS_DCD)
                                        netif_carrier_on(info->netdev);
@@ -3057,7 +3060,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
  *     
  * Return Value:               None
  */
-static void mgsl_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
        unsigned long flags;
@@ -4312,7 +4315,7 @@ static void mgsl_add_device( struct mgsl_struct *info )
                        info->max_frame_size );
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 
@@ -4337,7 +4340,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
        } else {
                memset(info, 0, sizeof(struct mgsl_struct));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, mgsl_bh_handler, info);
+               INIT_WORK(&info->task, mgsl_bh_handler);
                info->max_frame_size = 4096;
                info->close_delay = 5*HZ/10;
                info->closing_wait = 30*HZ;
@@ -4402,6 +4405,8 @@ static int mgsl_init_tty(void)
        serial_driver->init_termios = tty_std_termios;
        serial_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver->init_termios.c_ispeed = 9600;
+       serial_driver->init_termios.c_ospeed = 9600;
        serial_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(serial_driver, &mgsl_ops);
        if ((rc = tty_register_driver(serial_driver)) < 0) {
@@ -4470,7 +4475,7 @@ static void synclink_cleanup(void)
 
        info = mgsl_device_list;
        while(info) {
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                hdlcdev_exit(info);
 #endif
                mgsl_release_resources(info);
@@ -6644,7 +6649,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
                                return_frame = 1;
                }
                framesize = 0;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                {
                        struct net_device_stats *stats = hdlc_stats(info->netdev);
                        stats->rx_errors++;
@@ -6720,7 +6725,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
                                                *ptmp);
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
                        else
@@ -7624,7 +7629,7 @@ static void mgsl_tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
        
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
@@ -7700,7 +7705,7 @@ static int usc_loopmode_active( struct mgsl_struct * info)
        return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
index d4334c7..792c79c 100644 (file)
 
 #include "linux/synclink.h"
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 /*
@@ -149,7 +151,7 @@ static struct tty_driver *serial_driver;
 static int  open(struct tty_struct *tty, struct file * filp);
 static void close(struct tty_struct *tty, struct file * filp);
 static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
 
 static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
 static void put_char(struct tty_struct *tty, unsigned char ch);
@@ -171,7 +173,7 @@ static void set_break(struct tty_struct *tty, int break_state);
 /*
  * generic HDLC support and callbacks
  */
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(struct slgt_info *info);
 static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
@@ -359,7 +361,7 @@ struct slgt_info {
        int netcount;
        int dosyncppp;
        spinlock_t netlock;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 
@@ -485,7 +487,7 @@ static void enable_loopback(struct slgt_info *info);
 static void set_rate(struct slgt_info *info, u32 data_rate);
 
 static int  bh_action(struct slgt_info *info);
-static void bh_handler(void* context);
+static void bh_handler(struct work_struct *work);
 static void bh_transmit(struct slgt_info *info);
 static void isr_serial(struct slgt_info *info);
 static void isr_rdma(struct slgt_info *info);
@@ -814,7 +816,7 @@ static void hangup(struct tty_struct *tty)
        wake_up_interruptible(&info->open_wait);
 }
 
-static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct slgt_info *info = tty->driver_data;
        unsigned long flags;
@@ -1354,7 +1356,7 @@ static void set_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
@@ -1878,9 +1880,9 @@ static int bh_action(struct slgt_info *info)
 /*
  * perform bottom half processing
  */
-static void bh_handler(void* context)
+static void bh_handler(struct work_struct *work)
 {
-       struct slgt_info *info = context;
+       struct slgt_info *info = container_of(work, struct slgt_info, task);
        int action;
 
        if (!info)
@@ -2002,7 +2004,7 @@ static void dcd_change(struct slgt_info *info)
        } else {
                info->input_signal_events.dcd_down++;
        }
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount) {
                if (info->signals & SerialSignal_DCD)
                        netif_carrier_on(info->netdev);
@@ -2180,7 +2182,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
                        set_signals(info);
                }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                if (info->netcount)
                        hdlcdev_tx_done(info);
                else
@@ -3306,7 +3308,7 @@ static void add_device(struct slgt_info *info)
                devstr, info->device_name, info->phys_reg_addr,
                info->irq_level, info->max_frame_size);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 }
@@ -3326,7 +3328,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
        } else {
                memset(info, 0, sizeof(struct slgt_info));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, bh_handler, info);
+               INIT_WORK(&info->task, bh_handler);
                info->max_frame_size = 4096;
                info->raw_rx_size = DMABUFSIZE;
                info->close_delay = 5*HZ/10;
@@ -3488,7 +3490,7 @@ static void slgt_cleanup(void)
        /* release devices */
        info = slgt_device_list;
        while(info) {
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                hdlcdev_exit(info);
 #endif
                free_dma_bufs(info);
@@ -3522,6 +3524,7 @@ static int __init slgt_init(void)
 
        if (!slgt_device_list) {
                printk("%s no devices found\n",driver_name);
+               pci_unregister_driver(&pci_driver);
                return -ENODEV;
        }
 
@@ -3543,6 +3546,8 @@ static int __init slgt_init(void)
        serial_driver->init_termios = tty_std_termios;
        serial_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver->init_termios.c_ispeed = 9600;
+       serial_driver->init_termios.c_ospeed = 9600;
        serial_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(serial_driver, &ops);
        if ((rc = tty_register_driver(serial_driver)) < 0) {
@@ -4433,7 +4438,7 @@ check_again:
                        framesize = 0;
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (framesize == 0) {
                struct net_device_stats *stats = hdlc_stats(info->netdev);
                stats->rx_errors++;
@@ -4476,7 +4481,7 @@ check_again:
                                framesize++;
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info,info->tmp_rbuf, framesize);
                        else
@@ -4779,7 +4784,7 @@ static void tx_timeout(unsigned long context)
        info->tx_count = 0;
        spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
@@ -4799,6 +4804,6 @@ static void rx_timeout(unsigned long context)
        spin_lock_irqsave(&info->lock, flags);
        info->pending_bh |= BH_RECEIVE;
        spin_unlock_irqrestore(&info->lock, flags);
-       bh_handler(info);
+       bh_handler(&info->task);
 }
 
index 3e932b6..53e8ccf 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -280,7 +282,7 @@ typedef struct _synclinkmp_info {
        int dosyncppp;
        spinlock_t netlock;
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 
@@ -517,7 +519,7 @@ static struct tty_driver *serial_driver;
 static int  open(struct tty_struct *tty, struct file * filp);
 static void close(struct tty_struct *tty, struct file * filp);
 static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
 
 static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
 static void put_char(struct tty_struct *tty, unsigned char ch);
@@ -536,7 +538,7 @@ static void throttle(struct tty_struct * tty);
 static void unthrottle(struct tty_struct * tty);
 static void set_break(struct tty_struct *tty, int break_state);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(SLMP_INFO *info);
 static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
@@ -602,7 +604,7 @@ static void enable_loopback(SLMP_INFO *info, int enable);
 static void set_rate(SLMP_INFO *info, u32 data_rate);
 
 static int  bh_action(SLMP_INFO *info);
-static void bh_handler(void* Context);
+static void bh_handler(struct work_struct *work);
 static void bh_receive(SLMP_INFO *info);
 static void bh_transmit(SLMP_INFO *info);
 static void bh_status(SLMP_INFO *info);
@@ -916,7 +918,7 @@ static void hangup(struct tty_struct *tty)
 
 /* Set new termios settings
  */
-static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
        unsigned long flags;
@@ -1607,7 +1609,7 @@ static void set_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
@@ -2063,9 +2065,9 @@ int bh_action(SLMP_INFO *info)
 
 /* Perform bottom half processing of work items queued by ISR.
  */
-void bh_handler(void* Context)
+void bh_handler(struct work_struct *work)
 {
-       SLMP_INFO *info = (SLMP_INFO*)Context;
+       SLMP_INFO *info = container_of(work, SLMP_INFO, task);
        int action;
 
        if (!info)
@@ -2339,7 +2341,7 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status)
                        set_signals(info);
                }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                if (info->netcount)
                        hdlcdev_tx_done(info);
                else
@@ -2523,7 +2525,7 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
                                info->input_signal_events.dcd_up++;
                        } else
                                info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount) {
                                if (status & SerialSignal_DCD)
                                        netif_carrier_on(info->netdev);
@@ -3783,7 +3785,7 @@ void add_device(SLMP_INFO *info)
                info->irq_level,
                info->max_frame_size );
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 }
@@ -3805,7 +3807,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
        } else {
                memset(info, 0, sizeof(SLMP_INFO));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, bh_handler, info);
+               INIT_WORK(&info->task, bh_handler);
                info->max_frame_size = 4096;
                info->close_delay = 5*HZ/10;
                info->closing_wait = 30*HZ;
@@ -3977,7 +3979,7 @@ static void synclinkmp_cleanup(void)
        /* release devices */
        info = synclinkmp_device_list;
        while(info) {
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                hdlcdev_exit(info);
 #endif
                free_dma_bufs(info);
@@ -4032,6 +4034,8 @@ static int __init synclinkmp_init(void)
        serial_driver->init_termios = tty_std_termios;
        serial_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver->init_termios.c_ispeed = 9600;
+       serial_driver->init_termios.c_ospeed = 9600;
        serial_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(serial_driver, &ops);
        if ((rc = tty_register_driver(serial_driver)) < 0) {
@@ -4979,7 +4983,7 @@ CheckAgain:
                        info->icount.rxcrc++;
 
                framesize = 0;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                {
                        struct net_device_stats *stats = hdlc_stats(info->netdev);
                        stats->rx_errors++;
@@ -5020,7 +5024,7 @@ CheckAgain:
                                        index = 0;
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info,info->tmp_rx_buf,framesize);
                        else
@@ -5531,7 +5535,7 @@ void tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
index 5f49280..05810c8 100644 (file)
@@ -182,6 +182,18 @@ static struct sysrq_key_op sysrq_showstate_op = {
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
+static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
+{
+       show_state_filter(TASK_UNINTERRUPTIBLE);
+}
+static struct sysrq_key_op sysrq_showstate_blocked_op = {
+       .handler        = sysrq_handle_showstate_blocked,
+       .help_msg       = "showBlockedTasks",
+       .action_msg     = "Show Blocked State",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
+};
+
+
 static void sysrq_handle_showmem(int key, struct tty_struct *tty)
 {
        show_mem();
@@ -219,13 +231,13 @@ static struct sysrq_key_op sysrq_term_op = {
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
 
-static void moom_callback(void *ignored)
+static void moom_callback(struct work_struct *ignored)
 {
        out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
                        GFP_KERNEL, 0);
 }
 
-static DECLARE_WORK(moom_work, moom_callback, NULL);
+static DECLARE_WORK(moom_work, moom_callback);
 
 static void sysrq_handle_moom(int key, struct tty_struct *tty)
 {
@@ -304,7 +316,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        /* May be assigned at init time by SMP VOYAGER */
        NULL,                           /* v */
        NULL,                           /* w */
-       NULL,                           /* x */
+       &sysrq_showstate_blocked_op,    /* x */
        NULL,                           /* y */
        NULL                            /* z */
 };
index bb1bad4..4c431cb 100644 (file)
@@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le
        unsigned int minor;
        char value;
 
-       minor = iminor(file->f_dentry->d_inode);
+       minor = iminor(file->f_path.dentry->d_inode);
        switch (minor) {
        case 0:
                value = get_led();
@@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
        int retval = 0;
        char c;
 
-       minor = iminor(file->f_dentry->d_inode);
+       minor = iminor(file->f_path.dentry->d_inode);
        switch (minor) {
        case 0:
                type = TYPE_LED;
index 9df0ca1..47fb20f 100644 (file)
@@ -285,7 +285,7 @@ static ssize_t
 tipar_write (struct file *file, const char __user *buf, size_t count,
                loff_t * ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+       unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
        ssize_t n;
 
        parport_claim_or_block(table[minor].dev);
@@ -313,7 +313,7 @@ static ssize_t
 tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
 {
        int b = 0;
-       unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+       unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
        ssize_t retval = 0;
        ssize_t n = 0;
 
index dd36fd0..07067c3 100644 (file)
@@ -249,6 +249,7 @@ int tosh_smm(SMMRegisters *regs)
 
        return eax;
 }
+EXPORT_SYMBOL(tosh_smm);
 
 
 static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
index 6e1329d..33e1f66 100644 (file)
@@ -325,9 +325,9 @@ static void user_reader_timeout(unsigned long ptr)
        schedule_work(&chip->work);
 }
 
-static void timeout_work(void *ptr)
+static void timeout_work(struct work_struct *work)
 {
-       struct tpm_chip *chip = ptr;
+       struct tpm_chip *chip = container_of(work, struct tpm_chip, work);
 
        down(&chip->buffer_mutex);
        atomic_set(&chip->data_pending, 0);
@@ -1105,7 +1105,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
        init_MUTEX(&chip->tpm_mutex);
        INIT_LIST_HEAD(&chip->list);
 
-       INIT_WORK(&chip->work, timeout_work, chip);
+       INIT_WORK(&chip->work, timeout_work);
 
        init_timer(&chip->user_read_timer);
        chip->user_read_timer.function = user_reader_timeout;
@@ -1155,6 +1155,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
 
        if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
                list_del(&chip->list);
+               misc_deregister(&chip->vendor.miscdev);
                put_device(dev);
                clear_bit(chip->dev_num, dev_mask);
                kfree(chip);
index 50dc492..4044c86 100644 (file)
 #define TTY_PARANOIA_CHECK 1
 #define CHECK_TTY_COUNT 1
 
-struct termios tty_std_termios = {     /* for the benefit of tty drivers  */
+struct ktermios tty_std_termios = {    /* for the benefit of tty drivers  */
        .c_iflag = ICRNL | IXON,
        .c_oflag = OPOST | ONLCR,
        .c_cflag = B38400 | CS8 | CREAD | HUPCL,
        .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
                   ECHOCTL | ECHOKE | IEXTEN,
-       .c_cc = INIT_C_CC
+       .c_cc = INIT_C_CC,
+       .c_ispeed = 38400,
+       .c_ospeed = 38400
 };
 
 EXPORT_SYMBOL(tty_std_termios);
@@ -126,7 +128,7 @@ EXPORT_SYMBOL(tty_std_termios);
    
 LIST_HEAD(tty_drivers);                        /* linked list of tty drivers */
 
-/* Semaphore to protect creating and releasing a tty. This is shared with
+/* Mutex to protect creating and releasing a tty. This is shared with
    vt.c for deeply disgusting hack reasons */
 DEFINE_MUTEX(tty_mutex);
 EXPORT_SYMBOL(tty_mutex);
@@ -250,7 +252,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
                                    "!= #fd's(%d) in %s\n",
                       tty->name, tty->count, count, routine);
                return count;
-       }       
+       }
 #endif
        return 0;
 }
@@ -259,18 +261,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
  * Tty buffer allocation management
  */
 
-
-/**
- *     tty_buffer_free_all             -       free buffers used by a tty
- *     @tty: tty to free from
- *
- *     Remove all the buffers pending on a tty whether queued with data
- *     or in the free ring. Must be called when the tty is no longer in use
- *
- *     Locking: none
- */
-
-
 /**
  *     tty_buffer_free_all             -       free buffers used by a tty
  *     @tty: tty to free from
@@ -614,7 +604,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
  *     they are not on hot paths so a little discipline won't do 
  *     any harm.
  *
- *     Locking: takes termios_sem
+ *     Locking: takes termios_mutex
  */
  
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -915,7 +905,7 @@ static void tty_ldisc_enable(struct tty_struct *tty)
  *     context.
  *
  *     Locking: takes tty_ldisc_lock.
- *             called functions take termios_sem
+ *              called functions take termios_mutex
  */
  
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -1251,10 +1241,26 @@ void tty_ldisc_flush(struct tty_struct *tty)
 }
 
 EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
+ *     tty_reset_termios       -       reset terminal state
+ *     @tty: tty to reset
+ *
+ *     Restore a terminal to the driver default state
+ */
+
+static void tty_reset_termios(struct tty_struct *tty)
+{
+       mutex_lock(&tty->termios_mutex);
+       *tty->termios = tty->driver->init_termios;
+       tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+       tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+       mutex_unlock(&tty->termios_mutex);
+}
        
 /**
  *     do_tty_hangup           -       actual handler for hangup events
- *     @data: tty device
+ *     @work: tty device
  *
  *     This can be called by the "eventd" kernel thread.  That is process
  *     synchronous but doesn't hold any locks, so we need to make sure we
@@ -1267,16 +1273,17 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
  *
  *     Locking:
  *             BKL
- *             redirect lock for undoing redirection
- *             file list lock for manipulating list of ttys
- *             tty_ldisc_lock from called functions
- *             termios_sem resetting termios data
- *             tasklist_lock to walk task list for hangup event
- *
+ *               redirect lock for undoing redirection
+ *               file list lock for manipulating list of ttys
+ *               tty_ldisc_lock from called functions
+ *               termios_mutex resetting termios data
+ *               tasklist_lock to walk task list for hangup event
+ *                 ->siglock to protect ->signal/->sighand
  */
-static void do_tty_hangup(void *data)
+static void do_tty_hangup(struct work_struct *work)
 {
-       struct tty_struct *tty = (struct tty_struct *) data;
+       struct tty_struct *tty =
+               container_of(work, struct tty_struct, hangup_work);
        struct file * cons_filp = NULL;
        struct file *filp, *f = NULL;
        struct task_struct *p;
@@ -1338,11 +1345,7 @@ static void do_tty_hangup(void *data)
         * N_TTY.
         */
        if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
-       {
-               mutex_lock(&tty->termios_mutex);
-               *tty->termios = tty->driver->init_termios;
-               mutex_unlock(&tty->termios_mutex);
-       }
+               tty_reset_termios(tty);
        
        /* Defer ldisc switch */
        /* tty_deferred_ldisc_switch(N_TTY);
@@ -1353,14 +1356,18 @@ static void do_tty_hangup(void *data)
        read_lock(&tasklist_lock);
        if (tty->session > 0) {
                do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+                       spin_lock_irq(&p->sighand->siglock);
                        if (p->signal->tty == tty)
                                p->signal->tty = NULL;
-                       if (!p->signal->leader)
+                       if (!p->signal->leader) {
+                               spin_unlock_irq(&p->sighand->siglock);
                                continue;
-                       group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-                       group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+                       }
+                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
                        if (tty->pgrp > 0)
                                p->signal->tty_old_pgrp = tty->pgrp;
+                       spin_unlock_irq(&p->sighand->siglock);
                } while_each_task_pid(tty->session, PIDTYPE_SID, p);
        }
        read_unlock(&tasklist_lock);
@@ -1433,7 +1440,7 @@ void tty_vhangup(struct tty_struct * tty)
 
        printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
 #endif
-       do_tty_hangup((void *) tty);
+       do_tty_hangup(&tty->hangup_work);
 }
 EXPORT_SYMBOL(tty_vhangup);
 
@@ -1452,6 +1459,14 @@ int tty_hung_up_p(struct file * filp)
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
+static void session_clear_tty(pid_t session)
+{
+       struct task_struct *p;
+       do_each_task_pid(session, PIDTYPE_SID, p) {
+               proc_clear_tty(p);
+       } while_each_task_pid(session, PIDTYPE_SID, p);
+}
+
 /**
  *     disassociate_ctty       -       disconnect controlling tty
  *     @on_exit: true if exiting so need to "hang up" the session
@@ -1468,31 +1483,35 @@ EXPORT_SYMBOL(tty_hung_up_p);
  *     The argument on_exit is set to 1 if called when a process is
  *     exiting; it is 0 if called by the ioctl TIOCNOTTY.
  *
- *     Locking: tty_mutex is taken to protect current->signal->tty
+ *     Locking:
  *             BKL is taken for hysterical raisins
- *             Tasklist lock is taken (under tty_mutex) to walk process
- *             lists for the session.
+ *               tty_mutex is taken to protect tty
+ *               ->siglock is taken to protect ->signal/->sighand
+ *               tasklist_lock is taken to walk process list for sessions
+ *                 ->siglock is taken to protect ->signal/->sighand
  */
 
 void disassociate_ctty(int on_exit)
 {
        struct tty_struct *tty;
-       struct task_struct *p;
        int tty_pgrp = -1;
+       int session;
 
        lock_kernel();
 
        mutex_lock(&tty_mutex);
-       tty = current->signal->tty;
+       tty = get_current_tty();
        if (tty) {
                tty_pgrp = tty->pgrp;
                mutex_unlock(&tty_mutex);
+               /* XXX: here we race, there is nothing protecting tty */
                if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
                        tty_vhangup(tty);
        } else {
-               if (current->signal->tty_old_pgrp) {
-                       kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
-                       kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+               pid_t old_pgrp = current->signal->tty_old_pgrp;
+               if (old_pgrp) {
+                       kill_pg(old_pgrp, SIGHUP, on_exit);
+                       kill_pg(old_pgrp, SIGCONT, on_exit);
                }
                mutex_unlock(&tty_mutex);
                unlock_kernel();        
@@ -1504,19 +1523,29 @@ void disassociate_ctty(int on_exit)
                        kill_pg(tty_pgrp, SIGCONT, on_exit);
        }
 
-       /* Must lock changes to tty_old_pgrp */
-       mutex_lock(&tty_mutex);
+       spin_lock_irq(&current->sighand->siglock);
        current->signal->tty_old_pgrp = 0;
-       tty->session = 0;
-       tty->pgrp = -1;
+       session = process_session(current);
+       spin_unlock_irq(&current->sighand->siglock);
+
+       mutex_lock(&tty_mutex);
+       /* It is possible that do_tty_hangup has free'd this tty */
+       tty = get_current_tty();
+       if (tty) {
+               tty->session = 0;
+               tty->pgrp = 0;
+       } else {
+#ifdef TTY_DEBUG_HANGUP
+               printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+                      " = NULL", tty);
+#endif
+       }
+       mutex_unlock(&tty_mutex);
 
        /* Now clear signal->tty under the lock */
        read_lock(&tasklist_lock);
-       do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
-               p->signal->tty = NULL;
-       } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+       session_clear_tty(session);
        read_unlock(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
        unlock_kernel();
 }
 
@@ -1614,7 +1643,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
        struct tty_ldisc *ld;
 
        tty = (struct tty_struct *)file->private_data;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        if (tty_paranoia_check(tty, inode, "tty_read"))
                return -EIO;
        if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1717,7 +1746,7 @@ static inline ssize_t do_tty_write(
                cond_resched();
        }
        if (written) {
-               struct inode *inode = file->f_dentry->d_inode;
+               struct inode *inode = file->f_path.dentry->d_inode;
                inode->i_mtime = current_fs_time(inode->i_sb);
                ret = written;
        }
@@ -1748,7 +1777,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou
                         loff_t *ppos)
 {
        struct tty_struct * tty;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t ret;
        struct tty_ldisc *ld;
        
@@ -1855,8 +1884,8 @@ static int init_dev(struct tty_driver *driver, int idx,
        struct tty_struct **ret_tty)
 {
        struct tty_struct *tty, *o_tty;
-       struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
-       struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
+       struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
+       struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
        int retval = 0;
 
        /* check whether we're reopening an existing tty */
@@ -1903,7 +1932,7 @@ static int init_dev(struct tty_driver *driver, int idx,
        }
 
        if (!*tp_loc) {
-               tp = (struct termios *) kmalloc(sizeof(struct termios),
+               tp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
                                                GFP_KERNEL);
                if (!tp)
                        goto free_mem_out;
@@ -1911,11 +1940,11 @@ static int init_dev(struct tty_driver *driver, int idx,
        }
 
        if (!*ltp_loc) {
-               ltp = (struct termios *) kmalloc(sizeof(struct termios),
+               ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
                                                 GFP_KERNEL);
                if (!ltp)
                        goto free_mem_out;
-               memset(ltp, 0, sizeof(struct termios));
+               memset(ltp, 0, sizeof(struct ktermios));
        }
 
        if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -1936,19 +1965,19 @@ static int init_dev(struct tty_driver *driver, int idx,
                }
 
                if (!*o_tp_loc) {
-                       o_tp = (struct termios *)
-                               kmalloc(sizeof(struct termios), GFP_KERNEL);
+                       o_tp = (struct ktermios *)
+                               kmalloc(sizeof(struct ktermios), GFP_KERNEL);
                        if (!o_tp)
                                goto free_mem_out;
                        *o_tp = driver->other->init_termios;
                }
 
                if (!*o_ltp_loc) {
-                       o_ltp = (struct termios *)
-                               kmalloc(sizeof(struct termios), GFP_KERNEL);
+                       o_ltp = (struct ktermios *)
+                               kmalloc(sizeof(struct ktermios), GFP_KERNEL);
                        if (!o_ltp)
                                goto free_mem_out;
-                       memset(o_ltp, 0, sizeof(struct termios));
+                       memset(o_ltp, 0, sizeof(struct ktermios));
                }
 
                /*
@@ -1987,6 +2016,9 @@ static int init_dev(struct tty_driver *driver, int idx,
                *ltp_loc = ltp;
        tty->termios = *tp_loc;
        tty->termios_locked = *ltp_loc;
+       /* Compatibility until drivers always set this */
+       tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+       tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
        driver->refcount++;
        tty->count++;
 
@@ -2089,7 +2121,7 @@ release_mem_out:
 static void release_mem(struct tty_struct *tty, int idx)
 {
        struct tty_struct *o_tty;
-       struct termios *tp;
+       struct ktermios *tp;
        int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
 
        if ((o_tty = tty->link) != NULL) {
@@ -2155,7 +2187,7 @@ static void release_dev(struct file * filp)
        unsigned long flags;
        
        tty = (struct tty_struct *)filp->private_data;
-       if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
+       if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev"))
                return;
 
        check_tty_count(tty, "release_dev");
@@ -2336,16 +2368,10 @@ static void release_dev(struct file * filp)
         * tty.
         */
        if (tty_closing || o_tty_closing) {
-               struct task_struct *p;
-
                read_lock(&tasklist_lock);
-               do_each_task_pid(tty->session, PIDTYPE_SID, p) {
-                       p->signal->tty = NULL;
-               } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+               session_clear_tty(tty->session);
                if (o_tty)
-                       do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
-                               p->signal->tty = NULL;
-                       } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+                       session_clear_tty(o_tty->session);
                read_unlock(&tasklist_lock);
        }
 
@@ -2442,9 +2468,9 @@ static void release_dev(struct file * filp)
  *     The termios state of a pty is reset on first open so that
  *     settings don't persist across reuse.
  *
- *     Locking: tty_mutex protects current->signal->tty, get_tty_driver and
- *             init_dev work. tty->count should protect the rest.
- *             task_lock is held to update task details for sessions
+ *     Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ *              tty->count should protect the rest.
+ *              ->siglock protects ->signal/->sighand
  */
 
 static int tty_open(struct inode * inode, struct file * filp)
@@ -2466,12 +2492,13 @@ retry_open:
        mutex_lock(&tty_mutex);
 
        if (device == MKDEV(TTYAUX_MAJOR,0)) {
-               if (!current->signal->tty) {
+               tty = get_current_tty();
+               if (!tty) {
                        mutex_unlock(&tty_mutex);
                        return -ENXIO;
                }
-               driver = current->signal->tty->driver;
-               index = current->signal->tty->index;
+               driver = tty->driver;
+               index = tty->index;
                filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
                /* noctty = 1; */
                goto got_driver;
@@ -2546,17 +2573,16 @@ got_driver:
                        filp->f_op = &tty_fops;
                goto retry_open;
        }
+
+       mutex_lock(&tty_mutex);
+       spin_lock_irq(&current->sighand->siglock);
        if (!noctty &&
            current->signal->leader &&
            !current->signal->tty &&
-           tty->session == 0) {
-               task_lock(current);
-               current->signal->tty = tty;
-               task_unlock(current);
-               current->signal->tty_old_pgrp = 0;
-               tty->session = current->signal->session;
-               tty->pgrp = process_group(current);
-       }
+           tty->session == 0)
+               __proc_set_tty(current, tty);
+       spin_unlock_irq(&current->sighand->siglock);
+       mutex_unlock(&tty_mutex);
        return 0;
 }
 
@@ -2671,7 +2697,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait)
        int ret = 0;
 
        tty = (struct tty_struct *)filp->private_data;
-       if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
+       if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
                return 0;
                
        ld = tty_ldisc_ref_wait(tty);
@@ -2687,7 +2713,7 @@ static int tty_fasync(int fd, struct file * filp, int on)
        int retval;
 
        tty = (struct tty_struct *)filp->private_data;
-       if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
+       if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
                return 0;
        
        retval = fasync_helper(fd, filp, on, &tty->fasync);
@@ -2746,7 +2772,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
  *
  *     Copies the kernel idea of the window size into the user buffer.
  *
- *     Locking: tty->termios_sem is taken to ensure the winsize data
+ *     Locking: tty->termios_mutex is taken to ensure the winsize data
  *             is consistent.
  */
 
@@ -2773,8 +2799,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
  *     Locking:
  *             Called function use the console_sem is used to ensure we do
  *     not try and resize the console twice at once.
- *             The tty->termios_sem is used to ensure we don't double
- *     resize and get confused. Lock order - tty->termios.sem before
+ *             The tty->termios_mutex is used to ensure we don't double
+ *     resize and get confused. Lock order - tty->termios_mutex before
  *     console sem
  */
 
@@ -2879,25 +2905,28 @@ static int fionbio(struct file *file, int __user *p)
  *     leader to set this tty as the controlling tty for the session.
  *
  *     Locking:
- *             Takes tasklist lock internally to walk sessions
- *             Takes task_lock() when updating signal->tty
  *             Takes tty_mutex() to protect tty instance
- *
+ *             Takes tasklist_lock internally to walk sessions
+ *             Takes ->siglock() when updating signal->tty
  */
 
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
-       struct task_struct *p;
-
+       int ret = 0;
        if (current->signal->leader &&
-           (current->signal->session == tty->session))
-               return 0;
+                       (process_session(current) == tty->session))
+               return ret;
+
+       mutex_lock(&tty_mutex);
        /*
         * The process must be a session leader and
         * not have a controlling tty already.
         */
-       if (!current->signal->leader || current->signal->tty)
-               return -EPERM;
+       if (!current->signal->leader || current->signal->tty) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        if (tty->session > 0) {
                /*
                 * This tty is already the controlling
@@ -2907,24 +2936,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                        /*
                         * Steal it away
                         */
-
                        read_lock(&tasklist_lock);
-                       do_each_task_pid(tty->session, PIDTYPE_SID, p) {
-                               p->signal->tty = NULL;
-                       } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+                       session_clear_tty(tty->session);
                        read_unlock(&tasklist_lock);
-               } else
-                       return -EPERM;
+               } else {
+                       ret = -EPERM;
+                       goto unlock;
+               }
        }
-       mutex_lock(&tty_mutex);
-       task_lock(current);
-       current->signal->tty = tty;
-       task_unlock(current);
+       proc_set_tty(current, tty);
+unlock:
        mutex_unlock(&tty_mutex);
-       current->signal->tty_old_pgrp = 0;
-       tty->session = current->signal->session;
-       tty->pgrp = process_group(current);
-       return 0;
+       return ret;
 }
 
 /**
@@ -2936,7 +2959,7 @@ static int tiocsctty(struct tty_struct *tty, int arg)
  *     Obtain the process group of the tty. If there is no process group
  *     return an error.
  *
- *     Locking: none. Reference to ->signal->tty is safe.
+ *     Locking: none. Reference to current->signal->tty is safe.
  */
 
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -2973,13 +2996,13 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
                return retval;
        if (!current->signal->tty ||
            (current->signal->tty != real_tty) ||
-           (real_tty->session != current->signal->session))
+           (real_tty->session != process_session(current)))
                return -ENOTTY;
        if (get_user(pgrp, p))
                return -EFAULT;
        if (pgrp < 0)
                return -EINVAL;
-       if (session_of_pgrp(pgrp) != current->signal->session)
+       if (session_of_pgrp(pgrp) != process_session(current))
                return -EPERM;
        real_tty->pgrp = pgrp;
        return 0;
@@ -2994,7 +3017,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
  *     Obtain the session id of the tty. If there is no session
  *     return an error.
  *
- *     Locking: none. Reference to ->signal->tty is safe.
+ *     Locking: none. Reference to current->signal->tty is safe.
  */
 
 static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3213,14 +3236,11 @@ int tty_ioctl(struct inode * inode, struct file * file,
                        clear_bit(TTY_EXCLUSIVE, &tty->flags);
                        return 0;
                case TIOCNOTTY:
-                       /* FIXME: taks lock or tty_mutex ? */
                        if (current->signal->tty != tty)
                                return -ENOTTY;
                        if (current->signal->leader)
                                disassociate_ctty(0);
-                       task_lock(current);
-                       current->signal->tty = NULL;
-                       task_unlock(current);
+                       proc_clear_tty(current);
                        return 0;
                case TIOCSCTTY:
                        return tiocsctty(tty, arg);
@@ -3304,12 +3324,13 @@ int tty_ioctl(struct inode * inode, struct file * file,
  * Nasty bug: do_SAK is being called in interrupt context.  This can
  * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
  */
-static void __do_SAK(void *arg)
+static void __do_SAK(struct work_struct *work)
 {
+       struct tty_struct *tty =
+               container_of(work, struct tty_struct, SAK_work);
 #ifdef TTY_SOFT_SAK
        tty_hangup(tty);
 #else
-       struct tty_struct *tty = arg;
        struct task_struct *g, *p;
        int session;
        int             i;
@@ -3319,7 +3340,7 @@ static void __do_SAK(void *arg)
        
        if (!tty)
                return;
-       session  = tty->session;
+       session = tty->session;
        
        /* We don't want an ldisc switch during this */
        disc = tty_ldisc_ref(tty);
@@ -3334,7 +3355,7 @@ static void __do_SAK(void *arg)
        /* Kill the entire session */
        do_each_task_pid(session, PIDTYPE_SID, p) {
                printk(KERN_NOTICE "SAK: killed process %d"
-                       " (%s): p->signal->session==tty->session\n",
+                       " (%s): process_session(p)==tty->session\n",
                        p->pid, p->comm);
                send_sig(SIGKILL, p, 1);
        } while_each_task_pid(session, PIDTYPE_SID, p);
@@ -3344,7 +3365,7 @@ static void __do_SAK(void *arg)
        do_each_thread(g, p) {
                if (p->signal->tty == tty) {
                        printk(KERN_NOTICE "SAK: killed process %d"
-                           " (%s): p->signal->session==tty->session\n",
+                           " (%s): process_session(p)==tty->session\n",
                            p->pid, p->comm);
                        send_sig(SIGKILL, p, 1);
                        continue;
@@ -3388,7 +3409,7 @@ void do_SAK(struct tty_struct *tty)
 {
        if (!tty)
                return;
-       PREPARE_WORK(&tty->SAK_work, __do_SAK, tty);
+       PREPARE_WORK(&tty->SAK_work, __do_SAK);
        schedule_work(&tty->SAK_work);
 }
 
@@ -3396,7 +3417,7 @@ EXPORT_SYMBOL(do_SAK);
 
 /**
  *     flush_to_ldisc
- *     @private_: tty structure passed from work queue.
+ *     @work: tty structure passed from work queue.
  *
  *     This routine is called out of the software interrupt to flush data
  *     from the buffer chain to the line discipline.
@@ -3406,9 +3427,10 @@ EXPORT_SYMBOL(do_SAK);
  *     receive_buf method is single threaded for each tty instance.
  */
  
-static void flush_to_ldisc(void *private_)
+static void flush_to_ldisc(struct work_struct *work)
 {
-       struct tty_struct *tty = (struct tty_struct *) private_;
+       struct tty_struct *tty =
+               container_of(work, struct tty_struct, buf.work.work);
        unsigned long   flags;
        struct tty_ldisc *disc;
        struct tty_buffer *tbuf, *head;
@@ -3453,84 +3475,6 @@ static void flush_to_ldisc(void *private_)
        tty_ldisc_deref(disc);
 }
 
-/*
- * Routine which returns the baud rate of the tty
- *
- * Note that the baud_table needs to be kept in sync with the
- * include/asm/termbits.h file.
- */
-static int baud_table[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 230400, 460800,
-#ifdef __sparc__
-       76800, 153600, 307200, 614400, 921600
-#else
-       500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
-       2500000, 3000000, 3500000, 4000000
-#endif
-};
-
-static int n_baud_table = ARRAY_SIZE(baud_table);
-
-/**
- *     tty_termios_baud_rate
- *     @termios: termios structure
- *
- *     Convert termios baud rate data into a speed. This should be called
- *     with the termios lock held if this termios is a terminal termios
- *     structure. May change the termios data.
- *
- *     Locking: none
- */
-int tty_termios_baud_rate(struct termios *termios)
-{
-       unsigned int cbaud;
-       
-       cbaud = termios->c_cflag & CBAUD;
-
-       if (cbaud & CBAUDEX) {
-               cbaud &= ~CBAUDEX;
-
-               if (cbaud < 1 || cbaud + 15 > n_baud_table)
-                       termios->c_cflag &= ~CBAUDEX;
-               else
-                       cbaud += 15;
-       }
-       return baud_table[cbaud];
-}
-
-EXPORT_SYMBOL(tty_termios_baud_rate);
-
-/**
- *     tty_get_baud_rate       -       get tty bit rates
- *     @tty: tty to query
- *
- *     Returns the baud rate as an integer for this terminal. The
- *     termios lock must be held by the caller and the terminal bit
- *     flags may be updated.
- *
- *     Locking: none
- */
-int tty_get_baud_rate(struct tty_struct *tty)
-{
-       int baud = tty_termios_baud_rate(tty->termios);
-
-       if (baud == 38400 && tty->alt_speed) {
-               if (!tty->warned) {
-                       printk(KERN_WARNING "Use of setserial/setrocket to "
-                                           "set SPD_* flags is deprecated\n");
-                       tty->warned = 1;
-               }
-               baud = tty->alt_speed;
-       }
-       
-       return baud;
-}
-
-EXPORT_SYMBOL(tty_get_baud_rate);
-
 /**
  *     tty_flip_buffer_push    -       terminal
  *     @tty: tty to push
@@ -3553,7 +3497,7 @@ void tty_flip_buffer_push(struct tty_struct *tty)
        spin_unlock_irqrestore(&tty->buf.lock, flags);
 
        if (tty->low_latency)
-               flush_to_ldisc((void *) tty);
+               flush_to_ldisc(&tty->buf.work.work);
        else
                schedule_delayed_work(&tty->buf.work, 1);
 }
@@ -3580,17 +3524,17 @@ static void initialize_tty_struct(struct tty_struct *tty)
        tty->overrun_time = jiffies;
        tty->buf.head = tty->buf.tail = NULL;
        tty_buffer_init(tty);
-       INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
+       INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
        init_MUTEX(&tty->buf.pty_sem);
        mutex_init(&tty->termios_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
-       INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
+       INIT_WORK(&tty->hangup_work, do_tty_hangup);
        mutex_init(&tty->atomic_read_lock);
        mutex_init(&tty->atomic_write_lock);
        spin_lock_init(&tty->read_lock);
        INIT_LIST_HEAD(&tty->tty_files);
-       INIT_WORK(&tty->SAK_work, NULL, NULL);
+       INIT_WORK(&tty->SAK_work, NULL);
 }
 
 /*
@@ -3753,8 +3697,8 @@ int tty_register_driver(struct tty_driver *driver)
 
        if (p) {
                driver->ttys = (struct tty_struct **)p;
-               driver->termios = (struct termios **)(p + driver->num);
-               driver->termios_locked = (struct termios **)(p + driver->num * 2);
+               driver->termios = (struct ktermios **)(p + driver->num);
+               driver->termios_locked = (struct ktermios **)(p + driver->num * 2);
        } else {
                driver->ttys = NULL;
                driver->termios = NULL;
@@ -3793,7 +3737,7 @@ EXPORT_SYMBOL(tty_register_driver);
 int tty_unregister_driver(struct tty_driver *driver)
 {
        int i;
-       struct termios *tp;
+       struct ktermios *tp;
        void *p;
 
        if (driver->refcount)
@@ -3831,9 +3775,52 @@ int tty_unregister_driver(struct tty_driver *driver)
        cdev_del(&driver->cdev);
        return 0;
 }
-
 EXPORT_SYMBOL(tty_unregister_driver);
 
+dev_t tty_devnum(struct tty_struct *tty)
+{
+       return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
+}
+EXPORT_SYMBOL(tty_devnum);
+
+void proc_clear_tty(struct task_struct *p)
+{
+       spin_lock_irq(&p->sighand->siglock);
+       p->signal->tty = NULL;
+       spin_unlock_irq(&p->sighand->siglock);
+}
+EXPORT_SYMBOL(proc_clear_tty);
+
+void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+       if (tty) {
+               tty->session = process_session(tsk);
+               tty->pgrp = process_group(tsk);
+       }
+       tsk->signal->tty = tty;
+       tsk->signal->tty_old_pgrp = 0;
+}
+
+void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+       spin_lock_irq(&tsk->sighand->siglock);
+       __proc_set_tty(tsk, tty);
+       spin_unlock_irq(&tsk->sighand->siglock);
+}
+
+struct tty_struct *get_current_tty(void)
+{
+       struct tty_struct *tty;
+       WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
+       tty = current->signal->tty;
+       /*
+        * session->tty can be changed/cleared from under us, make sure we
+        * issue the load. The obtained pointer, when not NULL, is valid as
+        * long as we hold tty_mutex.
+        */
+       barrier();
+       return tty;
+}
 
 /*
  * Initialize the console device. This is called *early*, so
index 3b6fa7b..dee47f4 100644 (file)
@@ -36,6 +36,7 @@
 #define TERMIOS_FLUSH  1
 #define TERMIOS_WAIT   2
 #define TERMIOS_TERMIO 4
+#define TERMIOS_OLD    8
 
 
 /**
@@ -84,9 +85,9 @@ stop_waiting:
 
 EXPORT_SYMBOL(tty_wait_until_sent);
 
-static void unset_locked_termios(struct termios *termios,
-                                struct termios *old,
-                                struct termios *locked)
+static void unset_locked_termios(struct ktermios *termios,
+                                struct ktermios *old,
+                                struct ktermios *locked)
 {
        int     i;
        
@@ -105,8 +106,204 @@ static void unset_locked_termios(struct termios *termios,
        for (i=0; i < NCCS; i++)
                termios->c_cc[i] = locked->c_cc[i] ?
                        old->c_cc[i] : termios->c_cc[i];
+       /* FIXME: What should we do for i/ospeed */
 }
 
+/*
+ * Routine which returns the baud rate of the tty
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
+ */
+static const speed_t baud_table[] = {
+       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+       9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+       76800, 153600, 307200, 614400, 921600
+#else
+       500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+       2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+#ifndef __sparc__
+static const tcflag_t baud_bits[] = {
+       B0, B50, B75, B110, B134, B150, B200, B300, B600,
+       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+       B57600, B115200, B230400, B460800, B500000, B576000,
+       B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
+       B3000000, B3500000, B4000000
+};
+#else
+static const tcflag_t baud_bits[] = {
+       B0, B50, B75, B110, B134, B150, B200, B300, B600,
+       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+       B57600, B115200, B230400, B460800, B76800, B153600,
+       B307200, B614400, B921600
+};
+#endif
+
+static int n_baud_table = ARRAY_SIZE(baud_table);
+
+/**
+ *     tty_termios_baud_rate
+ *     @termios: termios structure
+ *
+ *     Convert termios baud rate data into a speed. This should be called
+ *     with the termios lock held if this termios is a terminal termios
+ *     structure. May change the termios data. Device drivers can call this
+ *     function but should use ->c_[io]speed directly as they are updated.
+ *
+ *     Locking: none
+ */
+
+speed_t tty_termios_baud_rate(struct ktermios *termios)
+{
+       unsigned int cbaud;
+
+       cbaud = termios->c_cflag & CBAUD;
+
+#ifdef BOTHER
+       /* Magic token for arbitary speed via c_ispeed/c_ospeed */
+       if (cbaud == BOTHER)
+               return termios->c_ospeed;
+#endif
+       if (cbaud & CBAUDEX) {
+               cbaud &= ~CBAUDEX;
+
+               if (cbaud < 1 || cbaud + 15 > n_baud_table)
+                       termios->c_cflag &= ~CBAUDEX;
+               else
+                       cbaud += 15;
+       }
+       return baud_table[cbaud];
+}
+
+EXPORT_SYMBOL(tty_termios_baud_rate);
+
+/**
+ *     tty_termios_input_baud_rate
+ *     @termios: termios structure
+ *
+ *     Convert termios baud rate data into a speed. This should be called
+ *     with the termios lock held if this termios is a terminal termios
+ *     structure. May change the termios data. Device drivers can call this
+ *     function but should use ->c_[io]speed directly as they are updated.
+ *
+ *     Locking: none
+ */
+
+speed_t tty_termios_input_baud_rate(struct ktermios *termios)
+{
+#ifdef IBSHIFT
+       unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
+
+       if (cbaud == B0)
+               return tty_termios_baud_rate(termios);
+
+       /* Magic token for arbitary speed via c_ispeed*/
+       if (cbaud == BOTHER)
+               return termios->c_ispeed;
+
+       if (cbaud & CBAUDEX) {
+               cbaud &= ~CBAUDEX;
+
+               if (cbaud < 1 || cbaud + 15 > n_baud_table)
+                       termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
+               else
+                       cbaud += 15;
+       }
+       return baud_table[cbaud];
+#else
+       return tty_termios_baud_rate(termios);
+#endif
+}
+
+EXPORT_SYMBOL(tty_termios_input_baud_rate);
+
+#ifdef BOTHER
+
+/**
+ *     tty_termios_encode_baud_rate
+ *     @termios: termios structure
+ *     @ispeed: input speed
+ *     @ospeed: output speed
+ *
+ *     Encode the speeds set into the passed termios structure. This is
+ *     used as a library helper for drivers os that they can report back
+ *     the actual speed selected when it differs from the speed requested
+ *
+ *     For now input and output speed must agree.
+ *
+ *     Locking: Caller should hold termios lock. This is already held
+ *     when calling this function from the driver termios handler.
+ */
+
+void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
+{
+       int i = 0;
+       int ifound = 0, ofound = 0;
+
+       termios->c_ispeed = ibaud;
+       termios->c_ospeed = obaud;
+
+       termios->c_cflag &= ~CBAUD;
+       /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/
+       if (termios->c_ispeed == termios->c_ospeed)
+               ifound = 1;
+
+       do {
+               if (obaud == baud_table[i]) {
+                       termios->c_cflag |= baud_bits[i];
+                       ofound = 1;
+                       /* So that if ibaud == obaud we don't set it */
+                       continue;
+               }
+               if (ibaud == baud_table[i]) {
+                       termios->c_cflag |= (baud_bits[i] << IBSHIFT);
+                       ifound = 1;
+               }
+       }
+       while(++i < n_baud_table);
+       if (!ofound)
+               termios->c_cflag |= BOTHER;
+       if (!ifound)
+               termios->c_cflag |= (BOTHER << IBSHIFT);
+}
+
+EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
+
+#endif
+
+/**
+ *     tty_get_baud_rate       -       get tty bit rates
+ *     @tty: tty to query
+ *
+ *     Returns the baud rate as an integer for this terminal. The
+ *     termios lock must be held by the caller and the terminal bit
+ *     flags may be updated.
+ *
+ *     Locking: none
+ */
+
+speed_t tty_get_baud_rate(struct tty_struct *tty)
+{
+       speed_t baud = tty_termios_baud_rate(tty->termios);
+
+       if (baud == 38400 && tty->alt_speed) {
+               if (!tty->warned) {
+                       printk(KERN_WARNING "Use of setserial/setrocket to "
+                                           "set SPD_* flags is deprecated\n");
+                       tty->warned = 1;
+               }
+               baud = tty->alt_speed;
+       }
+
+       return baud;
+}
+
+EXPORT_SYMBOL(tty_get_baud_rate);
+
 /**
  *     change_termios          -       update termios values
  *     @tty: tty to update
@@ -119,10 +316,10 @@ static void unset_locked_termios(struct termios *termios,
  *     Locking: termios_sem
  */
 
-static void change_termios(struct tty_struct * tty, struct termios * new_termios)
+static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
 {
        int canon_change;
-       struct termios old_termios = *tty->termios;
+       struct ktermios old_termios = *tty->termios;
        struct tty_ldisc *ld;
        
        /*
@@ -195,23 +392,39 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 
 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
 {
-       struct termios tmp_termios;
+       struct ktermios tmp_termios;
        struct tty_ldisc *ld;
        int retval = tty_check_change(tty);
 
        if (retval)
                return retval;
 
+       memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
+
        if (opt & TERMIOS_TERMIO) {
-               memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
                if (user_termio_to_kernel_termios(&tmp_termios,
                                                (struct termio __user *)arg))
                        return -EFAULT;
+#ifdef TCGETS2
+       } else if (opt & TERMIOS_OLD) {
+               if (user_termios_to_kernel_termios_1(&tmp_termios,
+                                               (struct termios __user *)arg))
+                       return -EFAULT;
        } else {
                if (user_termios_to_kernel_termios(&tmp_termios,
-                                               (struct termios __user *)arg))
+                                               (struct termios2 __user *)arg))
                        return -EFAULT;
        }
+#else
+       } else if (user_termios_to_kernel_termios(&tmp_termios,
+                                       (struct termios __user *)arg))
+               return -EFAULT;
+#endif
+
+       /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
+          so its unconditionally usable */
+       tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
+       tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
 
        ld = tty_ldisc_ref(tty);
        
@@ -286,8 +499,8 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
        struct sgttyb tmp;
 
        mutex_lock(&tty->termios_mutex);
-       tmp.sg_ispeed = 0;
-       tmp.sg_ospeed = 0;
+       tmp.sg_ispeed = tty->termios->c_ispeed;
+       tmp.sg_ospeed = tty->termios->c_ospeed;
        tmp.sg_erase = tty->termios->c_cc[VERASE];
        tmp.sg_kill = tty->termios->c_cc[VKILL];
        tmp.sg_flags = get_sgflags(tty);
@@ -296,7 +509,7 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
        return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
-static void set_sgflags(struct termios * termios, int flags)
+static void set_sgflags(struct ktermios * termios, int flags)
 {
        termios->c_iflag = ICRNL | IXON;
        termios->c_oflag = 0;
@@ -337,7 +550,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 {
        int retval;
        struct sgttyb tmp;
-       struct termios termios;
+       struct ktermios termios;
 
        retval = tty_check_change(tty);
        if (retval)
@@ -351,6 +564,10 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
        termios.c_cc[VERASE] = tmp.sg_erase;
        termios.c_cc[VKILL] = tmp.sg_kill;
        set_sgflags(&termios, tmp.sg_flags);
+       /* Try and encode into Bfoo format */
+#ifdef BOTHER
+       tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
+#endif
        mutex_unlock(&tty->termios_mutex);
        change_termios(tty, &termios);
        return 0;
@@ -481,16 +698,33 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                case TIOCSLTC:
                        return set_ltchars(real_tty, p);
 #endif
+               case TCSETSF:
+                       return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
+               case TCSETSW:
+                       return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
+               case TCSETS:
+                       return set_termios(real_tty, p, TERMIOS_OLD);
+#ifndef TCGETS2
                case TCGETS:
                        if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
                                return -EFAULT;
                        return 0;
-               case TCSETSF:
+#else
+               case TCGETS:
+                       if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
+                               return -EFAULT;
+                       return 0;
+               case TCGETS2:
+                       if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
+                               return -EFAULT;
+                       return 0;
+               case TCSETSF2:
                        return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
-               case TCSETSW:
+               case TCSETSW2:
                        return set_termios(real_tty, p, TERMIOS_WAIT);
-               case TCSETS:
+               case TCSETS2:
                        return set_termios(real_tty, p, 0);
+#endif
                case TCGETA:
                        return get_termio(real_tty, p);
                case TCSETAF:
index f442b57..2677651 100644 (file)
@@ -72,7 +72,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
        int size;
 
        down(&con_buf_sem);
-       size = vcs_size(file->f_dentry->d_inode);
+       size = vcs_size(file->f_path.dentry->d_inode);
        switch (orig) {
                default:
                        up(&con_buf_sem);
@@ -98,7 +98,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 static ssize_t
 vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        unsigned int currcons = iminor(inode);
        struct vc_data *vc;
        long pos;
@@ -271,7 +271,7 @@ unlock_out:
 static ssize_t
 vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        unsigned int currcons = iminor(inode);
        struct vc_data *vc;
        long pos;
index 73c78bf..94d79cb 100644 (file)
@@ -442,7 +442,7 @@ static ssize_t viotap_write(struct file *file, const char *buf,
        if (op == NULL)
                return -ENOMEM;
 
-       get_dev_info(file->f_dentry->d_inode, &devi);
+       get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        /*
         * We need to make sure we can send a request.  We use
@@ -532,7 +532,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count,
        if (op == NULL)
                return -ENOMEM;
 
-       get_dev_info(file->f_dentry->d_inode, &devi);
+       get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        /*
         * We need to make sure we can send a request.  We use
@@ -612,7 +612,7 @@ static int viotap_ioctl(struct inode *inode, struct file *file,
        if (op == NULL)
                return -ENOMEM;
 
-       get_dev_info(file->f_dentry->d_inode, &devi);
+       get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        down(&reqSem);
 
@@ -777,7 +777,7 @@ static int viotap_open(struct inode *inode, struct file *file)
        if (op == NULL)
                return -ENOMEM;
 
-       get_dev_info(file->f_dentry->d_inode, &devi);
+       get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        /* Note: We currently only support one mode! */
        if ((devi.devno >= viotape_numdev) || (devi.mode)) {
@@ -822,7 +822,7 @@ static int viotap_release(struct inode *inode, struct file *file)
                return -ENOMEM;
        init_completion(&op->com);
 
-       get_dev_info(file->f_dentry->d_inode, &devi);
+       get_dev_info(file->f_path.dentry->d_inode, &devi);
 
        if (devi.devno >= viotape_numdev) {
                ret = -ENODEV;
index d0b94dd..e01317c 100644 (file)
@@ -153,6 +153,8 @@ static int scc_init_drivers(void)
        scc_driver->init_termios = tty_std_termios;
        scc_driver->init_termios.c_cflag =
          B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       scc_driver->init_termios.c_ispeed = 9600;
+       scc_driver->init_termios.c_ospeed = 9600;
        scc_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(scc_driver, &scc_ops);
 
index 8e79493..a744dad 100644 (file)
@@ -506,7 +506,7 @@ static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
        unsigned int pin;
        char value = '0';
 
-       pin = iminor(file->f_dentry->d_inode);
+       pin = iminor(file->f_path.dentry->d_inode);
        if (pin >= giu_nr_pins)
                return -EBADF;
 
@@ -530,7 +530,7 @@ static ssize_t gpio_write(struct file *file, const char __user *data,
        char c;
        int retval = 0;
 
-       pin = iminor(file->f_dentry->d_inode);
+       pin = iminor(file->f_path.dentry->d_inode);
        if (pin >= giu_nr_pins)
                return -EBADF;
 
index 87587b4..a8239da 100644 (file)
@@ -152,10 +152,10 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y);
 static void save_cur(struct vc_data *vc);
 static void reset_terminal(struct vc_data *vc, int do_clear);
 static void con_flush_chars(struct tty_struct *tty);
-static void set_vesa_blanking(char __user *p);
+static int set_vesa_blanking(char __user *p);
 static void set_cursor(struct vc_data *vc);
 static void hide_cursor(struct vc_data *vc);
-static void console_callback(void *ignored);
+static void console_callback(struct work_struct *ignored);
 static void blank_screen_t(unsigned long dummy);
 static void set_palette(struct vc_data *vc);
 
@@ -174,7 +174,7 @@ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
 static int blankinterval = 10*60*HZ;
 static int vesa_off_interval;
 
-static DECLARE_WORK(console_work, console_callback, NULL);
+static DECLARE_WORK(console_work, console_callback);
 
 /*
  * fg_console is the current virtual console,
@@ -2154,7 +2154,7 @@ out:
  * with other console code and prevention of re-entrancy is
  * ensured with console_sem.
  */
-static void console_callback(void *ignored)
+static void console_callback(struct work_struct *ignored)
 {
        acquire_console_sem();
 
@@ -2369,7 +2369,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = __put_user(data, p);
                        break;
                case TIOCL_SETVESABLANK:
-                       set_vesa_blanking(p);
+                       ret = set_vesa_blanking(p);
                        break;
                case TIOCL_GETKMSGREDIRECT:
                        data = kmsg_redirect;
@@ -3313,11 +3313,15 @@ postcore_initcall(vtconsole_class_init);
  *     Screen blanking
  */
 
-static void set_vesa_blanking(char __user *p)
+static int set_vesa_blanking(char __user *p)
 {
-    unsigned int mode;
-    get_user(mode, p + 1);
-    vesa_blank_mode = (mode < 4) ? mode : 0;
+       unsigned int mode;
+
+       if (get_user(mode, p + 1))
+               return -EFAULT;
+
+       vesa_blank_mode = (mode < 4) ? mode : 0;
+       return 0;
 }
 
 void do_blank_screen(int entering_gfx)
index 4e7a114..cb86967 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/watchdog.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
+#include <asm/arch/at91_st.h>
 
 
 #define WDT_DEFAULT_TIME       5       /* seconds */
index e275dd4..6113872 100644 (file)
@@ -634,7 +634,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
        usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
 
        /* set up the memory buffer's */
-       if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) {
+       if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) {
                printk(KERN_ERR PFX "Out of memory\n");
                goto error;
        }
index 7fcb77a..b6bcdbb 100644 (file)
@@ -77,11 +77,11 @@ static struct clocksource clocksource_acpi_pm = {
 
 
 #ifdef CONFIG_PCI
-static int acpi_pm_good;
+static int __devinitdata acpi_pm_good;
 static int __init acpi_pm_good_setup(char *__str)
 {
-       acpi_pm_good = 1;
-       return 1;
+       acpi_pm_good = 1;
+       return 1;
 }
 __setup("acpi_pm_good", acpi_pm_good_setup);
 
@@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
                        acpi_pm_check_graylist);
 #endif
 
+#ifndef CONFIG_X86_64
+#include "mach_timer.h"
+#define PMTMR_EXPECTED_RATE \
+  ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10))
+/*
+ * Some boards have the PMTMR running way too fast. We check
+ * the PMTMR rate against PIT channel 2 to catch these cases.
+ */
+static int verify_pmtmr_rate(void)
+{
+       u32 value1, value2;
+       unsigned long count, delta;
+
+       mach_prepare_counter();
+       value1 = read_pmtmr();
+       mach_countup(&count);
+       value2 = read_pmtmr();
+       delta = (value2 - value1) & ACPI_PM_MASK;
+
+       /* Check that the PMTMR delta is within 5% of what we expect */
+       if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
+           delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
+               printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% "
+                       "of normal - aborting.\n",
+                       100UL * delta / PMTMR_EXPECTED_RATE);
+               return -1;
+       }
+
+       return 0;
+}
+#else
+#define verify_pmtmr_rate() (0)
+#endif
 
 static int __init init_acpi_pm_clocksource(void)
 {
@@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void)
        return -ENODEV;
 
 pm_good:
+       if (verify_pmtmr_rate() != 0)
+               return -ENODEV;
+
        return clocksource_register(&clocksource_acpi_pm);
 }
 
index 05f8ce2..b418b16 100644 (file)
 #include <linux/connector.h>
 #include <linux/delay.h>
 
-void cn_queue_wrapper(void *data)
+void cn_queue_wrapper(struct work_struct *work)
 {
-       struct cn_callback_data *d = data;
+       struct cn_callback_entry *cbq =
+               container_of(work, struct cn_callback_entry, work.work);
+       struct cn_callback_data *d = &cbq->data;
 
        d->callback(d->callback_priv);
 
@@ -57,7 +59,7 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc
        memcpy(&cbq->id.id, id, sizeof(struct cb_id));
        cbq->data.callback = callback;
        
-       INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
+       INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper);
        return cbq;
 }
 
index b49bacf..5e7cd45 100644 (file)
@@ -135,40 +135,39 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
        spin_lock_bh(&dev->cbdev->queue_lock);
        list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
                if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
-                       if (likely(!test_bit(0, &__cbq->work.pending) &&
+                       if (likely(!test_bit(WORK_STRUCT_PENDING,
+                                            &__cbq->work.work.management) &&
                                        __cbq->data.ddata == NULL)) {
                                __cbq->data.callback_priv = msg;
 
                                __cbq->data.ddata = data;
                                __cbq->data.destruct_data = destruct_data;
 
-                               if (queue_work(dev->cbdev->cn_queue,
-                                               &__cbq->work))
+                               if (queue_delayed_work(
+                                           dev->cbdev->cn_queue,
+                                           &__cbq->work, 0))
                                        err = 0;
                        } else {
-                               struct work_struct *w;
                                struct cn_callback_data *d;
                                
-                               w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
-                               if (w) {
-                                       d = (struct cn_callback_data *)(w+1);
-
+                               __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC);
+                               if (__cbq) {
+                                       d = &__cbq->data;
                                        d->callback_priv = msg;
                                        d->callback = __cbq->data.callback;
                                        d->ddata = data;
                                        d->destruct_data = destruct_data;
-                                       d->free = w;
+                                       d->free = __cbq;
 
-                                       INIT_LIST_HEAD(&w->entry);
-                                       w->pending = 0;
-                                       w->func = &cn_queue_wrapper;
-                                       w->data = d;
-                                       init_timer(&w->timer);
+                                       INIT_DELAYED_WORK(&__cbq->work,
+                                                         &cn_queue_wrapper);
                                        
-                                       if (queue_work(dev->cbdev->cn_queue, w))
+                                       if (queue_delayed_work(
+                                                   dev->cbdev->cn_queue,
+                                                   &__cbq->work, 0))
                                                err = 0;
                                        else {
-                                               kfree(w);
+                                               kfree(__cbq);
                                                err = -EINVAL;
                                        }
                                } else
index dd0c262..47ab42d 100644 (file)
@@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
 /* internal prototypes */
 static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
-static void handle_update(void *data);
+static void handle_update(struct work_struct *work);
 
 /**
  * Two notifier lists: the "policy" list is involved in the
@@ -665,7 +665,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        mutex_init(&policy->lock);
        mutex_lock(&policy->lock);
        init_completion(&policy->kobj_unregister);
-       INIT_WORK(&policy->update, handle_update, (void *)(long)cpu);
+       INIT_WORK(&policy->update, handle_update);
 
        /* call driver. From then on the cpufreq must be able
         * to accept all calls to ->verify and ->setpolicy for this CPU
@@ -895,9 +895,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
 }
 
 
-static void handle_update(void *data)
+static void handle_update(struct work_struct *work)
 {
-       unsigned int cpu = (unsigned int)(long)data;
+       struct cpufreq_policy *policy =
+               container_of(work, struct cpufreq_policy, update);
+       unsigned int cpu = policy->cpu;
        dprintk("handle_update for cpu %u called\n", cpu);
        cpufreq_update_policy(cpu);
 }
@@ -1535,7 +1537,6 @@ int cpufreq_update_policy(unsigned int cpu)
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_cpu_callback(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
@@ -1575,7 +1576,6 @@ static struct notifier_block __cpuinitdata cpufreq_cpu_notifier =
 {
     .notifier_call = cpufreq_cpu_callback,
 };
-#endif /* CONFIG_HOTPLUG_CPU */
 
 /*********************************************************************
  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
index c4c578d..5ef5ede 100644 (file)
@@ -59,7 +59,7 @@ static unsigned int                           def_sampling_rate;
 #define MAX_SAMPLING_DOWN_FACTOR               (10)
 #define TRANSITION_LATENCY_LIMIT               (10 * 1000)
 
-static void do_dbs_timer(void *data);
+static void do_dbs_timer(struct work_struct *work);
 
 struct cpu_dbs_info_s {
        struct cpufreq_policy   *cur_policy;
@@ -82,7 +82,7 @@ static unsigned int dbs_enable;       /* number of CPUs using this policy */
  * is recursive for the same process. -Venki
  */
 static DEFINE_MUTEX    (dbs_mutex);
-static DECLARE_WORK    (dbs_work, do_dbs_timer, NULL);
+static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer);
 
 struct dbs_tuners {
        unsigned int            sampling_rate;
@@ -420,7 +420,7 @@ static void dbs_check_cpu(int cpu)
        }
 }
 
-static void do_dbs_timer(void *data)
+static void do_dbs_timer(struct work_struct *work)
 { 
        int i;
        lock_cpu_hotplug();
@@ -435,7 +435,6 @@ static void do_dbs_timer(void *data)
 
 static inline void dbs_timer_init(void)
 {
-       INIT_WORK(&dbs_work, do_dbs_timer, NULL);
        schedule_delayed_work(&dbs_work,
                        usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
        return;
index bf8aa45..e1cc511 100644 (file)
@@ -47,13 +47,17 @@ static unsigned int def_sampling_rate;
 #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER   (1000)
 #define TRANSITION_LATENCY_LIMIT               (10 * 1000)
 
-static void do_dbs_timer(void *data);
+static void do_dbs_timer(struct work_struct *work);
+
+/* Sampling types */
+enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
 
 struct cpu_dbs_info_s {
        cputime64_t prev_cpu_idle;
        cputime64_t prev_cpu_wall;
        struct cpufreq_policy *cur_policy;
-       struct work_struct work;
+       struct delayed_work work;
+       enum dbs_sample sample_type;
        unsigned int enable;
        struct cpufreq_frequency_table *freq_table;
        unsigned int freq_lo;
@@ -407,30 +411,31 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
        }
 }
 
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-static void do_dbs_timer(void *data)
+static void do_dbs_timer(struct work_struct *work)
 {
        unsigned int cpu = smp_processor_id();
        struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
+       enum dbs_sample sample_type = dbs_info->sample_type;
        /* We want all CPUs to do sampling nearly on same jiffy */
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+
+       /* Permit rescheduling of this work item */
+       work_release(work);
+
        delay -= jiffies % delay;
 
        if (!dbs_info->enable)
                return;
        /* Common NORMAL_SAMPLE setup */
-       INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE);
+       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        if (!dbs_tuners_ins.powersave_bias ||
-           (unsigned long) data == DBS_NORMAL_SAMPLE) {
+           sample_type == DBS_NORMAL_SAMPLE) {
                lock_cpu_hotplug();
                dbs_check_cpu(dbs_info);
                unlock_cpu_hotplug();
                if (dbs_info->freq_lo) {
                        /* Setup timer for SUB_SAMPLE */
-                       INIT_WORK(&dbs_info->work, do_dbs_timer,
-                                       (void *)DBS_SUB_SAMPLE);
+                       dbs_info->sample_type = DBS_SUB_SAMPLE;
                        delay = dbs_info->freq_hi_jiffies;
                }
        } else {
@@ -449,7 +454,8 @@ static inline void dbs_timer_init(unsigned int cpu)
        delay -= jiffies % delay;
 
        ondemand_powersave_bias_init();
-       INIT_WORK(&dbs_info->work, do_dbs_timer, NULL);
+       INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
+       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
 }
 
index adb5541..879250d 100644 (file)
@@ -51,4 +51,17 @@ config CRYPTO_DEV_PADLOCK_SHA
          If unsure say M. The compiled module will be
          called padlock-sha.ko
 
+config CRYPTO_DEV_GEODE
+       tristate "Support for the Geode LX AES engine"
+       depends on CRYPTO && X86_32 && PCI
+       select CRYPTO_ALGAPI
+       select CRYPTO_BLKCIPHER
+       default m
+       help
+         Say 'Y' here to use the AMD Geode LX processor on-board AES
+         engine for the CryptoAPI AES alogrithm.
+
+         To compile this driver as a module, choose M here: the module
+         will be called geode-aes.
+
 endmenu
index 4c3d0ec..6059cf8 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
+obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
new file mode 100644 (file)
index 0000000..43a6839
--- /dev/null
@@ -0,0 +1,474 @@
+ /* Copyright (C) 2004-2006, Advanced Micro Devices, 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/crypto.h>
+#include <linux/spinlock.h>
+#include <crypto/algapi.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geode-aes.h"
+
+/* Register definitions */
+
+#define AES_CTRLA_REG  0x0000
+
+#define AES_CTRL_START     0x01
+#define AES_CTRL_DECRYPT   0x00
+#define AES_CTRL_ENCRYPT   0x02
+#define AES_CTRL_WRKEY     0x04
+#define AES_CTRL_DCA       0x08
+#define AES_CTRL_SCA       0x10
+#define AES_CTRL_CBC       0x20
+
+#define AES_INTR_REG  0x0008
+
+#define AES_INTRA_PENDING (1 << 16)
+#define AES_INTRB_PENDING (1 << 17)
+
+#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
+#define AES_INTR_MASK     0x07
+
+#define AES_SOURCEA_REG   0x0010
+#define AES_DSTA_REG      0x0014
+#define AES_LENA_REG      0x0018
+#define AES_WRITEKEY0_REG 0x0030
+#define AES_WRITEIV0_REG  0x0040
+
+/*  A very large counter that is used to gracefully bail out of an
+ *  operation in case of trouble
+ */
+
+#define AES_OP_TIMEOUT    0x50000
+
+/* Static structures */
+
+static void __iomem * _iobase;
+static spinlock_t lock;
+
+/* Write a 128 bit field (either a writable key or IV) */
+static inline void
+_writefield(u32 offset, void *value)
+{
+       int i;
+       for(i = 0; i < 4; i++)
+               iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4));
+}
+
+/* Read a 128 bit field (either a writable key or IV) */
+static inline void
+_readfield(u32 offset, void *value)
+{
+       int i;
+       for(i = 0; i < 4; i++)
+               ((u32 *) value)[i] = ioread32(_iobase + offset + (i * 4));
+}
+
+static int
+do_crypt(void *src, void *dst, int len, u32 flags)
+{
+       u32 status;
+       u32 counter = AES_OP_TIMEOUT;
+
+       iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG);
+       iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG);
+       iowrite32(len,  _iobase + AES_LENA_REG);
+
+       /* Start the operation */
+       iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
+
+       do
+               status = ioread32(_iobase + AES_INTR_REG);
+       while(!(status & AES_INTRA_PENDING) && --counter);
+
+       /* Clear the event */
+       iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
+       return counter ? 0 : 1;
+}
+
+static unsigned int
+geode_aes_crypt(struct geode_aes_op *op)
+{
+
+       u32 flags = 0;
+       int iflags;
+
+       if (op->len == 0 || op->src == op->dst)
+               return 0;
+
+       if (op->flags & AES_FLAGS_COHERENT)
+               flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+
+       if (op->dir == AES_DIR_ENCRYPT)
+               flags |= AES_CTRL_ENCRYPT;
+
+       /* Start the critical section */
+
+       spin_lock_irqsave(&lock, iflags);
+
+       if (op->mode == AES_MODE_CBC) {
+               flags |= AES_CTRL_CBC;
+               _writefield(AES_WRITEIV0_REG, op->iv);
+       }
+
+       if (op->flags & AES_FLAGS_USRKEY) {
+               flags |= AES_CTRL_WRKEY;
+               _writefield(AES_WRITEKEY0_REG, op->key);
+       }
+
+       do_crypt(op->src, op->dst, op->len, flags);
+
+       if (op->mode == AES_MODE_CBC)
+               _readfield(AES_WRITEIV0_REG, op->iv);
+
+       spin_unlock_irqrestore(&lock, iflags);
+
+       return op->len;
+}
+
+/* CRYPTO-API Functions */
+
+static int
+geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if (len != AES_KEY_LENGTH) {
+               tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+
+       memcpy(op->key, key, len);
+       return 0;
+}
+
+static void
+geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if ((out == NULL) || (in == NULL))
+               return;
+
+       op->src = (void *) in;
+       op->dst = (void *) out;
+       op->mode = AES_MODE_ECB;
+       op->flags = 0;
+       op->len = AES_MIN_BLOCK_SIZE;
+       op->dir = AES_DIR_ENCRYPT;
+
+       geode_aes_crypt(op);
+}
+
+
+static void
+geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if ((out == NULL) || (in == NULL))
+               return;
+
+       op->src = (void *) in;
+       op->dst = (void *) out;
+       op->mode = AES_MODE_ECB;
+       op->flags = 0;
+       op->len = AES_MIN_BLOCK_SIZE;
+       op->dir = AES_DIR_DECRYPT;
+
+       geode_aes_crypt(op);
+}
+
+
+static struct crypto_alg geode_alg = {
+       .cra_name               =       "aes",
+       .cra_driver_name        =       "geode-aes-128",
+       .cra_priority           =       300,
+       .cra_alignmask          =       15,
+       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_alg.cra_list),
+       .cra_u                  =       {
+               .cipher = {
+                       .cia_min_keysize        =  AES_KEY_LENGTH,
+                       .cia_max_keysize        =  AES_KEY_LENGTH,
+                       .cia_setkey             =  geode_setkey,
+                       .cia_encrypt            =  geode_encrypt,
+                       .cia_decrypt            =  geode_decrypt
+               }
+       }
+};
+
+static int
+geode_cbc_decrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_CBC;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_DECRYPT;
+
+               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+
+               ret = geode_aes_crypt(op);
+
+               memcpy(walk.iv, op->iv, AES_IV_LENGTH);
+               nbytes -= ret;
+
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static int
+geode_cbc_encrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_CBC;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_ENCRYPT;
+
+               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static struct crypto_alg geode_cbc_alg = {
+       .cra_name               =       "cbc(aes)",
+       .cra_driver_name        =       "cbc-aes-geode-128",
+       .cra_priority           =       400,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_alignmask          =       15,
+       .cra_type               =       &crypto_blkcipher_type,
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_cbc_alg.cra_list),
+       .cra_u                  =       {
+               .blkcipher = {
+                       .min_keysize            =       AES_KEY_LENGTH,
+                       .max_keysize            =       AES_KEY_LENGTH,
+                       .setkey                 =       geode_setkey,
+                       .encrypt                =       geode_cbc_encrypt,
+                       .decrypt                =       geode_cbc_decrypt,
+               }
+       }
+};
+
+static int
+geode_ecb_decrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_ECB;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_DECRYPT;
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static int
+geode_ecb_encrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_ECB;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_ENCRYPT;
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               ret =  blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static struct crypto_alg geode_ecb_alg = {
+       .cra_name               =       "ecb(aes)",
+       .cra_driver_name        =       "ecb-aes-geode-128",
+       .cra_priority           =       400,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_alignmask          =       15,
+       .cra_type               =       &crypto_blkcipher_type,
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_ecb_alg.cra_list),
+       .cra_u                  =       {
+               .blkcipher = {
+                       .min_keysize            =       AES_KEY_LENGTH,
+                       .max_keysize            =       AES_KEY_LENGTH,
+                       .setkey                 =       geode_setkey,
+                       .encrypt                =       geode_ecb_encrypt,
+                       .decrypt                =       geode_ecb_decrypt,
+               }
+       }
+};
+
+static void
+geode_aes_remove(struct pci_dev *dev)
+{
+       crypto_unregister_alg(&geode_alg);
+       crypto_unregister_alg(&geode_ecb_alg);
+       crypto_unregister_alg(&geode_cbc_alg);
+
+       pci_iounmap(dev, _iobase);
+       _iobase = NULL;
+
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+}
+
+
+static int
+geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       int ret;
+
+       if ((ret = pci_enable_device(dev)))
+               return ret;
+
+       if ((ret = pci_request_regions(dev, "geode-aes-128")))
+               goto eenable;
+
+       _iobase = pci_iomap(dev, 0, 0);
+
+       if (_iobase == NULL) {
+               ret = -ENOMEM;
+               goto erequest;
+       }
+
+       spin_lock_init(&lock);
+
+       /* Clear any pending activity */
+       iowrite32(AES_INTR_PENDING | AES_INTR_MASK, _iobase + AES_INTR_REG);
+
+       if ((ret = crypto_register_alg(&geode_alg)))
+               goto eiomap;
+
+       if ((ret = crypto_register_alg(&geode_ecb_alg)))
+               goto ealg;
+
+       if ((ret = crypto_register_alg(&geode_cbc_alg)))
+               goto eecb;
+
+       printk(KERN_NOTICE "geode-aes: GEODE AES engine enabled.\n");
+       return 0;
+
+ eecb:
+       crypto_unregister_alg(&geode_ecb_alg);
+
+ ealg:
+       crypto_unregister_alg(&geode_alg);
+
+ eiomap:
+       pci_iounmap(dev, _iobase);
+
+ erequest:
+       pci_release_regions(dev);
+
+ eenable:
+       pci_disable_device(dev);
+
+       printk(KERN_ERR "geode-aes:  GEODE AES initialization failed.\n");
+       return ret;
+}
+
+static struct pci_device_id geode_aes_tbl[] = {
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, PCI_ANY_ID, PCI_ANY_ID} ,
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, geode_aes_tbl);
+
+static struct pci_driver geode_aes_driver = {
+       .name = "Geode LX AES",
+       .id_table = geode_aes_tbl,
+       .probe = geode_aes_probe,
+       .remove = __devexit_p(geode_aes_remove)
+};
+
+static int __init
+geode_aes_init(void)
+{
+       return pci_module_init(&geode_aes_driver);
+}
+
+static void __exit
+geode_aes_exit(void)
+{
+       pci_unregister_driver(&geode_aes_driver);
+}
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+MODULE_DESCRIPTION("Geode LX Hardware AES driver");
+MODULE_LICENSE("GPL");
+
+module_init(geode_aes_init);
+module_exit(geode_aes_exit);
diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
new file mode 100644 (file)
index 0000000..8003a36
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (C) 2003-2006, Advanced Micro Devices, 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.
+ */
+
+#ifndef _GEODE_AES_H_
+#define _GEODE_AES_H_
+
+#define AES_KEY_LENGTH 16
+#define AES_IV_LENGTH  16
+
+#define AES_MIN_BLOCK_SIZE 16
+
+#define AES_MODE_ECB 0
+#define AES_MODE_CBC 1
+
+#define AES_DIR_DECRYPT 0
+#define AES_DIR_ENCRYPT 1
+
+#define AES_FLAGS_USRKEY   (1 << 0)
+#define AES_FLAGS_COHERENT (1 << 1)
+
+struct geode_aes_op {
+
+       void *src;
+       void *dst;
+
+       u32 mode;
+       u32 dir;
+       u32 flags;
+       int len;
+
+       u8 key[AES_KEY_LENGTH];
+       u8 iv[AES_IV_LENGTH];
+};
+
+#endif
index 0358419..8e87261 100644 (file)
@@ -636,10 +636,10 @@ static int ioat_self_test(struct ioat_device *device)
        dma_cookie_t cookie;
        int err = 0;
 
-       src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
        if (!src)
                return -ENOMEM;
-       dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
        if (!dest) {
                kfree(src);
                return -ENOMEM;
index 75e9e38..1b4fc92 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sysdev.h>
 #include <linux/ctype.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/edac.h>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
new file mode 100644 (file)
index 0000000..96d4a0b
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# HID driver configuration
+#
+menu "HID Devices"
+       depends on INPUT
+
+config HID
+       tristate "Generic HID support"
+       default y
+       ---help---
+         Say Y here if you want generic HID support to connect keyboards,
+         mice, joysticks, graphic tablets, or any other HID based devices
+         to your computer. You also need to select particular types of
+         HID devices you want to compile support for, in the particular
+         driver menu (USB, Bluetooth)
+
+endmenu
+
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
new file mode 100644 (file)
index 0000000..6432392
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Makefile for the HID driver
+#
+
+# Multipart objects.
+hid-objs       := hid-core.o hid-input.o
+
+# Optional parts of multipart objects.
+
+obj-$(CONFIG_HID)              += hid.o
+
+ifeq ($(CONFIG_INPUT_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
new file mode 100644 (file)
index 0000000..18c2b3c
--- /dev/null
@@ -0,0 +1,1003 @@
+/*
+ *  HID support for Linux
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <linux/input.h>
+#include <linux/wait.h>
+
+#undef DEBUG
+#undef DEBUG_DATA
+
+#include <linux/hid.h>
+#include <linux/hiddev.h>
+
+/*
+ * Version Information
+ */
+
+#define DRIVER_VERSION "v2.6"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
+#define DRIVER_DESC "USB HID core driver"
+#define DRIVER_LICENSE "GPL"
+
+/*
+ * Module parameters.
+ */
+
+static unsigned int hid_mousepoll_interval;
+module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
+MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
+
+/*
+ * Register a new report for a device.
+ */
+
+static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
+{
+       struct hid_report_enum *report_enum = device->report_enum + type;
+       struct hid_report *report;
+
+       if (report_enum->report_id_hash[id])
+               return report_enum->report_id_hash[id];
+
+       if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
+               return NULL;
+
+       if (id != 0)
+               report_enum->numbered = 1;
+
+       report->id = id;
+       report->type = type;
+       report->size = 0;
+       report->device = device;
+       report_enum->report_id_hash[id] = report;
+
+       list_add_tail(&report->list, &report_enum->report_list);
+
+       return report;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+{
+       struct hid_field *field;
+
+       if (report->maxfield == HID_MAX_FIELDS) {
+               dbg("too many fields in report");
+               return NULL;
+       }
+
+       if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+               + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+
+       field->index = report->maxfield++;
+       report->field[field->index] = field;
+       field->usage = (struct hid_usage *)(field + 1);
+       field->value = (unsigned *)(field->usage + usages);
+       field->report = report;
+
+       return field;
+}
+
+/*
+ * Open a collection. The type/usage is pushed on the stack.
+ */
+
+static int open_collection(struct hid_parser *parser, unsigned type)
+{
+       struct hid_collection *collection;
+       unsigned usage;
+
+       usage = parser->local.usage[0];
+
+       if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
+               dbg("collection stack overflow");
+               return -1;
+       }
+
+       if (parser->device->maxcollection == parser->device->collection_size) {
+               collection = kmalloc(sizeof(struct hid_collection) *
+                               parser->device->collection_size * 2, GFP_KERNEL);
+               if (collection == NULL) {
+                       dbg("failed to reallocate collection array");
+                       return -1;
+               }
+               memcpy(collection, parser->device->collection,
+                       sizeof(struct hid_collection) *
+                       parser->device->collection_size);
+               memset(collection + parser->device->collection_size, 0,
+                       sizeof(struct hid_collection) *
+                       parser->device->collection_size);
+               kfree(parser->device->collection);
+               parser->device->collection = collection;
+               parser->device->collection_size *= 2;
+       }
+
+       parser->collection_stack[parser->collection_stack_ptr++] =
+               parser->device->maxcollection;
+
+       collection = parser->device->collection +
+               parser->device->maxcollection++;
+       collection->type = type;
+       collection->usage = usage;
+       collection->level = parser->collection_stack_ptr - 1;
+
+       if (type == HID_COLLECTION_APPLICATION)
+               parser->device->maxapplication++;
+
+       return 0;
+}
+
+/*
+ * Close a collection.
+ */
+
+static int close_collection(struct hid_parser *parser)
+{
+       if (!parser->collection_stack_ptr) {
+               dbg("collection stack underflow");
+               return -1;
+       }
+       parser->collection_stack_ptr--;
+       return 0;
+}
+
+/*
+ * Climb up the stack, search for the specified collection type
+ * and return the usage.
+ */
+
+static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
+{
+       int n;
+       for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
+               if (parser->device->collection[parser->collection_stack[n]].type == type)
+                       return parser->device->collection[parser->collection_stack[n]].usage;
+       return 0; /* we know nothing about this usage type */
+}
+
+/*
+ * Add a usage to the temporary parser table.
+ */
+
+static int hid_add_usage(struct hid_parser *parser, unsigned usage)
+{
+       if (parser->local.usage_index >= HID_MAX_USAGES) {
+               dbg("usage index exceeded");
+               return -1;
+       }
+       parser->local.usage[parser->local.usage_index] = usage;
+       parser->local.collection_index[parser->local.usage_index] =
+               parser->collection_stack_ptr ?
+               parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
+       parser->local.usage_index++;
+       return 0;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
+{
+       struct hid_report *report;
+       struct hid_field *field;
+       int usages;
+       unsigned offset;
+       int i;
+
+       if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+               dbg("hid_register_report failed");
+               return -1;
+       }
+
+       if (parser->global.logical_maximum < parser->global.logical_minimum) {
+               dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+               return -1;
+       }
+
+       offset = report->size;
+       report->size += parser->global.report_size * parser->global.report_count;
+
+       if (!parser->local.usage_index) /* Ignore padding fields */
+               return 0;
+
+       usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+
+       if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
+               return 0;
+
+       field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
+       field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
+       field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
+
+       for (i = 0; i < usages; i++) {
+               int j = i;
+               /* Duplicate the last usage we parsed if we have excess values */
+               if (i >= parser->local.usage_index)
+                       j = parser->local.usage_index - 1;
+               field->usage[i].hid = parser->local.usage[j];
+               field->usage[i].collection_index =
+                       parser->local.collection_index[j];
+       }
+
+       field->maxusage = usages;
+       field->flags = flags;
+       field->report_offset = offset;
+       field->report_type = report_type;
+       field->report_size = parser->global.report_size;
+       field->report_count = parser->global.report_count;
+       field->logical_minimum = parser->global.logical_minimum;
+       field->logical_maximum = parser->global.logical_maximum;
+       field->physical_minimum = parser->global.physical_minimum;
+       field->physical_maximum = parser->global.physical_maximum;
+       field->unit_exponent = parser->global.unit_exponent;
+       field->unit = parser->global.unit;
+
+       return 0;
+}
+
+/*
+ * Read data value from item.
+ */
+
+static u32 item_udata(struct hid_item *item)
+{
+       switch (item->size) {
+               case 1: return item->data.u8;
+               case 2: return item->data.u16;
+               case 4: return item->data.u32;
+       }
+       return 0;
+}
+
+static s32 item_sdata(struct hid_item *item)
+{
+       switch (item->size) {
+               case 1: return item->data.s8;
+               case 2: return item->data.s16;
+               case 4: return item->data.s32;
+       }
+       return 0;
+}
+
+/*
+ * Process a global item.
+ */
+
+static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
+{
+       switch (item->tag) {
+
+               case HID_GLOBAL_ITEM_TAG_PUSH:
+
+                       if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+                               dbg("global enviroment stack overflow");
+                               return -1;
+                       }
+
+                       memcpy(parser->global_stack + parser->global_stack_ptr++,
+                               &parser->global, sizeof(struct hid_global));
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_POP:
+
+                       if (!parser->global_stack_ptr) {
+                               dbg("global enviroment stack underflow");
+                               return -1;
+                       }
+
+                       memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
+                               sizeof(struct hid_global));
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+                       parser->global.usage_page = item_udata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+                       parser->global.logical_minimum = item_sdata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+                       if (parser->global.logical_minimum < 0)
+                               parser->global.logical_maximum = item_sdata(item);
+                       else
+                               parser->global.logical_maximum = item_udata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+                       parser->global.physical_minimum = item_sdata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+                       if (parser->global.physical_minimum < 0)
+                               parser->global.physical_maximum = item_sdata(item);
+                       else
+                               parser->global.physical_maximum = item_udata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+                       parser->global.unit_exponent = item_sdata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_UNIT:
+                       parser->global.unit = item_udata(item);
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+                       if ((parser->global.report_size = item_udata(item)) > 32) {
+                               dbg("invalid report_size %d", parser->global.report_size);
+                               return -1;
+                       }
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+                       if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
+                               dbg("invalid report_count %d", parser->global.report_count);
+                               return -1;
+                       }
+                       return 0;
+
+               case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+                       if ((parser->global.report_id = item_udata(item)) == 0) {
+                               dbg("report_id 0 is invalid");
+                               return -1;
+                       }
+                       return 0;
+
+               default:
+                       dbg("unknown global tag 0x%x", item->tag);
+                       return -1;
+       }
+}
+
+/*
+ * Process a local item.
+ */
+
+static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
+{
+       __u32 data;
+       unsigned n;
+
+       if (item->size == 0) {
+               dbg("item data expected for local item");
+               return -1;
+       }
+
+       data = item_udata(item);
+
+       switch (item->tag) {
+
+               case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+                       if (data) {
+                               /*
+                                * We treat items before the first delimiter
+                                * as global to all usage sets (branch 0).
+                                * In the moment we process only these global
+                                * items and the first delimiter set.
+                                */
+                               if (parser->local.delimiter_depth != 0) {
+                                       dbg("nested delimiters");
+                                       return -1;
+                               }
+                               parser->local.delimiter_depth++;
+                               parser->local.delimiter_branch++;
+                       } else {
+                               if (parser->local.delimiter_depth < 1) {
+                                       dbg("bogus close delimiter");
+                                       return -1;
+                               }
+                               parser->local.delimiter_depth--;
+                       }
+                       return 1;
+
+               case HID_LOCAL_ITEM_TAG_USAGE:
+
+                       if (parser->local.delimiter_branch > 1) {
+                               dbg("alternative usage ignored");
+                               return 0;
+                       }
+
+                       if (item->size <= 2)
+                               data = (parser->global.usage_page << 16) + data;
+
+                       return hid_add_usage(parser, data);
+
+               case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+
+                       if (parser->local.delimiter_branch > 1) {
+                               dbg("alternative usage ignored");
+                               return 0;
+                       }
+
+                       if (item->size <= 2)
+                               data = (parser->global.usage_page << 16) + data;
+
+                       parser->local.usage_minimum = data;
+                       return 0;
+
+               case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+
+                       if (parser->local.delimiter_branch > 1) {
+                               dbg("alternative usage ignored");
+                               return 0;
+                       }
+
+                       if (item->size <= 2)
+                               data = (parser->global.usage_page << 16) + data;
+
+                       for (n = parser->local.usage_minimum; n <= data; n++)
+                               if (hid_add_usage(parser, n)) {
+                                       dbg("hid_add_usage failed\n");
+                                       return -1;
+                               }
+                       return 0;
+
+               default:
+
+                       dbg("unknown local item tag 0x%x", item->tag);
+                       return 0;
+       }
+       return 0;
+}
+
+/*
+ * Process a main item.
+ */
+
+static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
+{
+       __u32 data;
+       int ret;
+
+       data = item_udata(item);
+
+       switch (item->tag) {
+               case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+                       ret = open_collection(parser, data & 0xff);
+                       break;
+               case HID_MAIN_ITEM_TAG_END_COLLECTION:
+                       ret = close_collection(parser);
+                       break;
+               case HID_MAIN_ITEM_TAG_INPUT:
+                       ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+                       break;
+               case HID_MAIN_ITEM_TAG_OUTPUT:
+                       ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+                       break;
+               case HID_MAIN_ITEM_TAG_FEATURE:
+                       ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+                       break;
+               default:
+                       dbg("unknown main item tag 0x%x", item->tag);
+                       ret = 0;
+       }
+
+       memset(&parser->local, 0, sizeof(parser->local));       /* Reset the local parser environment */
+
+       return ret;
+}
+
+/*
+ * Process a reserved item.
+ */
+
+static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
+{
+       dbg("reserved item type, tag 0x%x", item->tag);
+       return 0;
+}
+
+/*
+ * Free a report and all registered fields. The field->usage and
+ * field->value table's are allocated behind the field, so we need
+ * only to free(field) itself.
+ */
+
+static void hid_free_report(struct hid_report *report)
+{
+       unsigned n;
+
+       for (n = 0; n < report->maxfield; n++)
+               kfree(report->field[n]);
+       kfree(report);
+}
+
+/*
+ * Free a device structure, all reports, and all fields.
+ */
+
+void hid_free_device(struct hid_device *device)
+{
+       unsigned i,j;
+
+       for (i = 0; i < HID_REPORT_TYPES; i++) {
+               struct hid_report_enum *report_enum = device->report_enum + i;
+
+               for (j = 0; j < 256; j++) {
+                       struct hid_report *report = report_enum->report_id_hash[j];
+                       if (report)
+                               hid_free_report(report);
+               }
+       }
+
+       kfree(device->rdesc);
+       kfree(device);
+}
+EXPORT_SYMBOL_GPL(hid_free_device);
+
+/*
+ * Fetch a report description item from the data stream. We support long
+ * items, though they are not used yet.
+ */
+
+static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+{
+       u8 b;
+
+       if ((end - start) <= 0)
+               return NULL;
+
+       b = *start++;
+
+       item->type = (b >> 2) & 3;
+       item->tag  = (b >> 4) & 15;
+
+       if (item->tag == HID_ITEM_TAG_LONG) {
+
+               item->format = HID_ITEM_FORMAT_LONG;
+
+               if ((end - start) < 2)
+                       return NULL;
+
+               item->size = *start++;
+               item->tag  = *start++;
+
+               if ((end - start) < item->size)
+                       return NULL;
+
+               item->data.longdata = start;
+               start += item->size;
+               return start;
+       }
+
+       item->format = HID_ITEM_FORMAT_SHORT;
+       item->size = b & 3;
+
+       switch (item->size) {
+
+               case 0:
+                       return start;
+
+               case 1:
+                       if ((end - start) < 1)
+                               return NULL;
+                       item->data.u8 = *start++;
+                       return start;
+
+               case 2:
+                       if ((end - start) < 2)
+                               return NULL;
+                       item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
+                       start = (__u8 *)((__le16 *)start + 1);
+                       return start;
+
+               case 3:
+                       item->size++;
+                       if ((end - start) < 4)
+                               return NULL;
+                       item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
+                       start = (__u8 *)((__le32 *)start + 1);
+                       return start;
+       }
+
+       return NULL;
+}
+
+/*
+ * Parse a report description into a hid_device structure. Reports are
+ * enumerated, fields are attached to these reports.
+ */
+
+struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+{
+       struct hid_device *device;
+       struct hid_parser *parser;
+       struct hid_item item;
+       __u8 *end;
+       unsigned i;
+       static int (*dispatch_type[])(struct hid_parser *parser,
+                                     struct hid_item *item) = {
+               hid_parser_main,
+               hid_parser_global,
+               hid_parser_local,
+               hid_parser_reserved
+       };
+
+       if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
+               return NULL;
+
+       if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
+                                  HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
+               kfree(device);
+               return NULL;
+       }
+       device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
+       for (i = 0; i < HID_REPORT_TYPES; i++)
+               INIT_LIST_HEAD(&device->report_enum[i].report_list);
+
+       if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
+               kfree(device->collection);
+               kfree(device);
+               return NULL;
+       }
+       memcpy(device->rdesc, start, size);
+       device->rsize = size;
+
+       if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+               kfree(device->rdesc);
+               kfree(device->collection);
+               kfree(device);
+               return NULL;
+       }
+       parser->device = device;
+
+       end = start + size;
+       while ((start = fetch_item(start, end, &item)) != NULL) {
+
+               if (item.format != HID_ITEM_FORMAT_SHORT) {
+                       dbg("unexpected long global item");
+                       kfree(device->collection);
+                       hid_free_device(device);
+                       kfree(parser);
+                       return NULL;
+               }
+
+               if (dispatch_type[item.type](parser, &item)) {
+                       dbg("item %u %u %u %u parsing failed\n",
+                               item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+                       kfree(device->collection);
+                       hid_free_device(device);
+                       kfree(parser);
+                       return NULL;
+               }
+
+               if (start == end) {
+                       if (parser->collection_stack_ptr) {
+                               dbg("unbalanced collection at end of report description");
+                               kfree(device->collection);
+                               hid_free_device(device);
+                               kfree(parser);
+                               return NULL;
+                       }
+                       if (parser->local.delimiter_depth) {
+                               dbg("unbalanced delimiter at end of report description");
+                               kfree(device->collection);
+                               hid_free_device(device);
+                               kfree(parser);
+                               return NULL;
+                       }
+                       kfree(parser);
+                       return device;
+               }
+       }
+
+       dbg("item fetching failed at offset %d\n", (int)(end - start));
+       kfree(device->collection);
+       hid_free_device(device);
+       kfree(parser);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(hid_parse_report);
+
+/*
+ * Convert a signed n-bit integer to signed 32-bit integer. Common
+ * cases are done through the compiler, the screwed things has to be
+ * done by hand.
+ */
+
+static s32 snto32(__u32 value, unsigned n)
+{
+       switch (n) {
+               case 8:  return ((__s8)value);
+               case 16: return ((__s16)value);
+               case 32: return ((__s32)value);
+       }
+       return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+}
+
+/*
+ * Convert a signed 32-bit integer to a signed n-bit integer.
+ */
+
+static u32 s32ton(__s32 value, unsigned n)
+{
+       s32 a = value >> (n - 1);
+       if (a && a != -1)
+               return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+       return value & ((1 << n) - 1);
+}
+
+/*
+ * Extract/implement a data field from/to a little endian report (bit array).
+ *
+ * Code sort-of follows HID spec:
+ *     http://www.usb.org/developers/devclass_docs/HID1_11.pdf
+ *
+ * While the USB HID spec allows unlimited length bit fields in "report
+ * descriptors", most devices never use more than 16 bits.
+ * One model of UPS is claimed to report "LINEV" as a 32-bit field.
+ * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
+ */
+
+static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+{
+       u64 x;
+
+       WARN_ON(n > 32);
+
+       report += offset >> 3;  /* adjust byte index */
+       offset &= 7;            /* now only need bit offset into one byte */
+       x = get_unaligned((u64 *) report);
+       x = le64_to_cpu(x);
+       x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
+       return (u32) x;
+}
+
+/*
+ * "implement" : set bits in a little endian bit stream.
+ * Same concepts as "extract" (see comments above).
+ * The data mangled in the bit stream remains in little endian
+ * order the whole time. It make more sense to talk about
+ * endianness of register values by considering a register
+ * a "cached" copy of the little endiad bit stream.
+ */
+static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+{
+       u64 x;
+       u64 m = (1ULL << n) - 1;
+
+       WARN_ON(n > 32);
+
+       WARN_ON(value > m);
+       value &= m;
+
+       report += offset >> 3;
+       offset &= 7;
+
+       x = get_unaligned((u64 *)report);
+       x &= cpu_to_le64(~(m << offset));
+       x |= cpu_to_le64(((u64) value) << offset);
+       put_unaligned(x, (u64 *) report);
+}
+
+/*
+ * Search an array for a value.
+ */
+
+static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+{
+       while (n--) {
+               if (*array++ == value)
+                       return 0;
+       }
+       return -1;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
+{
+       hid_dump_input(usage, value);
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_hid_event(hid, field, usage, value);
+       if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
+               hid->hiddev_hid_event(hid, field, usage, value);
+}
+
+/*
+ * Analyse a received field, and fetch the data from it. The field
+ * content is stored for next report processing (we do differential
+ * reporting to the layer).
+ */
+
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
+{
+       unsigned n;
+       unsigned count = field->report_count;
+       unsigned offset = field->report_offset;
+       unsigned size = field->report_size;
+       __s32 min = field->logical_minimum;
+       __s32 max = field->logical_maximum;
+       __s32 *value;
+
+       if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
+               return;
+
+       for (n = 0; n < count; n++) {
+
+                       value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
+                                                   extract(data, offset + n * size, size);
+
+                       if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
+                           && value[n] >= min && value[n] <= max
+                           && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+                               goto exit;
+       }
+
+       for (n = 0; n < count; n++) {
+
+               if (HID_MAIN_ITEM_VARIABLE & field->flags) {
+                       hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
+                       continue;
+               }
+
+               if (field->value[n] >= min && field->value[n] <= max
+                       && field->usage[field->value[n] - min].hid
+                       && search(value, field->value[n], count))
+                               hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
+
+               if (value[n] >= min && value[n] <= max
+                       && field->usage[value[n] - min].hid
+                       && search(field->value, value[n], count))
+                               hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
+       }
+
+       memcpy(field->value, value, count * sizeof(__s32));
+exit:
+       kfree(value);
+}
+EXPORT_SYMBOL_GPL(hid_input_field);
+
+/*
+ * Output the field into the report.
+ */
+
+static void hid_output_field(struct hid_field *field, __u8 *data)
+{
+       unsigned count = field->report_count;
+       unsigned offset = field->report_offset;
+       unsigned size = field->report_size;
+       unsigned n;
+
+       for (n = 0; n < count; n++) {
+               if (field->logical_minimum < 0) /* signed values */
+                       implement(data, offset + n * size, size, s32ton(field->value[n], size));
+               else                            /* unsigned values */
+                       implement(data, offset + n * size, size, field->value[n]);
+       }
+}
+
+/*
+ * Create a report.
+ */
+
+void hid_output_report(struct hid_report *report, __u8 *data)
+{
+       unsigned n;
+
+       if (report->id > 0)
+               *data++ = report->id;
+
+       for (n = 0; n < report->maxfield; n++)
+               hid_output_field(report->field[n], data);
+}
+EXPORT_SYMBOL_GPL(hid_output_report);
+
+/*
+ * Set a field value. The report this field belongs to has to be
+ * created and transferred to the device, to set this value in the
+ * device.
+ */
+
+int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
+{
+       unsigned size = field->report_size;
+
+       hid_dump_input(field->usage + offset, value);
+
+       if (offset >= field->report_count) {
+               dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+               hid_dump_field(field, 8);
+               return -1;
+       }
+       if (field->logical_minimum < 0) {
+               if (value != snto32(s32ton(value, size), size)) {
+                       dbg("value %d is out of range", value);
+                       return -1;
+               }
+       }
+       field->value[offset] = value;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hid_set_field);
+
+int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+{
+       struct hid_report_enum *report_enum = hid->report_enum + type;
+       struct hid_report *report;
+       int n, rsize;
+
+       if (!hid)
+               return -ENODEV;
+
+       if (!size) {
+               dbg("empty report");
+               return -1;
+       }
+
+#ifdef DEBUG_DATA
+       printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
+#endif
+
+       n = 0;                          /* Normally report number is 0 */
+       if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
+               n = *data++;
+               size--;
+       }
+
+#ifdef DEBUG_DATA
+       {
+               int i;
+               printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
+               for (i = 0; i < size; i++)
+                       printk(" %02x", data[i]);
+               printk("\n");
+       }
+#endif
+
+       if (!(report = report_enum->report_id_hash[n])) {
+               dbg("undefined report_id %d received", n);
+               return -1;
+       }
+
+       rsize = ((report->size - 1) >> 3) + 1;
+
+       if (size < rsize) {
+               dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+               return -1;
+       }
+
+       if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+               hid->hiddev_report_event(hid, report);
+
+       for (n = 0; n < report->maxfield; n++)
+               hid_input_field(hid, report->field[n], data, interrupt);
+
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_report_event(hid, report);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hid_input_report);
+
+MODULE_LICENSE(DRIVER_LICENSE);
+
similarity index 88%
rename from drivers/usb/input/hid-input.c
rename to drivers/hid/hid-input.c
index 68e7ebb..14cdf09 100644 (file)
@@ -2,8 +2,9 @@
  * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2006 Jiri Kosina
  *
- *  USB HID to Linux Input mapping
+ *  HID to Linux Input mapping
  */
 
 /*
@@ -33,7 +34,7 @@
 
 #undef DEBUG
 
-#include "hid.h"
+#include <linux/hid.h>
 
 #define unk    KEY_UNKNOWN
 
@@ -81,42 +82,42 @@ struct hidinput_key_translation {
 
 static struct hidinput_key_translation powerbook_fn_keys[] = {
        { KEY_BACKSPACE, KEY_DELETE },
-       { KEY_F1,       KEY_BRIGHTNESSDOWN,     POWERBOOK_FLAG_FKEY },
-       { KEY_F2,       KEY_BRIGHTNESSUP,       POWERBOOK_FLAG_FKEY },
-       { KEY_F3,       KEY_MUTE,               POWERBOOK_FLAG_FKEY },
-       { KEY_F4,       KEY_VOLUMEDOWN,         POWERBOOK_FLAG_FKEY },
-       { KEY_F5,       KEY_VOLUMEUP,           POWERBOOK_FLAG_FKEY },
-       { KEY_F6,       KEY_NUMLOCK,            POWERBOOK_FLAG_FKEY },
-       { KEY_F7,       KEY_SWITCHVIDEOMODE,    POWERBOOK_FLAG_FKEY },
-       { KEY_F8,       KEY_KBDILLUMTOGGLE,     POWERBOOK_FLAG_FKEY },
-       { KEY_F9,       KEY_KBDILLUMDOWN,       POWERBOOK_FLAG_FKEY },
-       { KEY_F10,      KEY_KBDILLUMUP,         POWERBOOK_FLAG_FKEY },
-       { KEY_UP,       KEY_PAGEUP },
-       { KEY_DOWN,     KEY_PAGEDOWN },
-       { KEY_LEFT,     KEY_HOME },
-       { KEY_RIGHT,    KEY_END },
+       { KEY_F1,       KEY_BRIGHTNESSDOWN,     POWERBOOK_FLAG_FKEY },
+       { KEY_F2,       KEY_BRIGHTNESSUP,       POWERBOOK_FLAG_FKEY },
+       { KEY_F3,       KEY_MUTE,               POWERBOOK_FLAG_FKEY },
+       { KEY_F4,       KEY_VOLUMEDOWN,         POWERBOOK_FLAG_FKEY },
+       { KEY_F5,       KEY_VOLUMEUP,           POWERBOOK_FLAG_FKEY },
+       { KEY_F6,       KEY_NUMLOCK,            POWERBOOK_FLAG_FKEY },
+       { KEY_F7,       KEY_SWITCHVIDEOMODE,    POWERBOOK_FLAG_FKEY },
+       { KEY_F8,       KEY_KBDILLUMTOGGLE,     POWERBOOK_FLAG_FKEY },
+       { KEY_F9,       KEY_KBDILLUMDOWN,       POWERBOOK_FLAG_FKEY },
+       { KEY_F10,      KEY_KBDILLUMUP,         POWERBOOK_FLAG_FKEY },
+       { KEY_UP,       KEY_PAGEUP },
+       { KEY_DOWN,     KEY_PAGEDOWN },
+       { KEY_LEFT,     KEY_HOME },
+       { KEY_RIGHT,    KEY_END },
        { }
 };
 
 static struct hidinput_key_translation powerbook_numlock_keys[] = {
-       { KEY_J,        KEY_KP1 },
-       { KEY_K,        KEY_KP2 },
-       { KEY_L,        KEY_KP3 },
-       { KEY_U,        KEY_KP4 },
-       { KEY_I,        KEY_KP5 },
-       { KEY_O,        KEY_KP6 },
-       { KEY_7,        KEY_KP7 },
-       { KEY_8,        KEY_KP8 },
-       { KEY_9,        KEY_KP9 },
-       { KEY_M,        KEY_KP0 },
-       { KEY_DOT,      KEY_KPDOT },
-       { KEY_SLASH,    KEY_KPPLUS },
+       { KEY_J,        KEY_KP1 },
+       { KEY_K,        KEY_KP2 },
+       { KEY_L,        KEY_KP3 },
+       { KEY_U,        KEY_KP4 },
+       { KEY_I,        KEY_KP5 },
+       { KEY_O,        KEY_KP6 },
+       { KEY_7,        KEY_KP7 },
+       { KEY_8,        KEY_KP8 },
+       { KEY_9,        KEY_KP9 },
+       { KEY_M,        KEY_KP0 },
+       { KEY_DOT,      KEY_KPDOT },
+       { KEY_SLASH,    KEY_KPPLUS },
        { KEY_SEMICOLON, KEY_KPMINUS },
-       { KEY_P,        KEY_KPASTERISK },
-       { KEY_MINUS,    KEY_KPEQUAL },
-       { KEY_0,        KEY_KPSLASH },
-       { KEY_F6,       KEY_NUMLOCK },
-       { KEY_KPENTER,  KEY_KPENTER },
+       { KEY_P,        KEY_KPASTERISK },
+       { KEY_MINUS,    KEY_KPEQUAL },
+       { KEY_0,        KEY_KPSLASH },
+       { KEY_F6,       KEY_NUMLOCK },
+       { KEY_KPENTER,  KEY_KPENTER },
        { KEY_BACKSPACE, KEY_BACKSPACE },
        { }
 };
@@ -127,11 +128,6 @@ static struct hidinput_key_translation powerbook_iso_keyboard[] = {
        { }
 };
 
-static int usbhid_pb_fnmode = 1;
-module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
-       "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
 static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
 {
        struct hidinput_key_translation *trans;
@@ -145,7 +141,7 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra
 }
 
 static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
-                            struct hid_usage *usage, __s32 value)
+               struct hid_usage *usage, __s32 value)
 {
        struct hidinput_key_translation *trans;
 
@@ -158,7 +154,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
                return 1;
        }
 
-       if (usbhid_pb_fnmode) {
+       if (hid->pb_fnmode) {
                int do_translate;
 
                trans = find_translation(powerbook_fn_keys, usage->code);
@@ -167,8 +163,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
                                do_translate = 1;
                        else if (trans->flags & POWERBOOK_FLAG_FKEY)
                                do_translate =
-                                       (usbhid_pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
-                                       (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
+                                       (hid->pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+                                       (hid->pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
                        else
                                do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
 
@@ -185,7 +181,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
                }
 
                if (test_bit(usage->code, hid->pb_pressed_numlock) ||
-                   test_bit(LED_NUML, input->led)) {
+                               test_bit(LED_NUML, input->led)) {
                        trans = find_translation(powerbook_numlock_keys, usage->code);
 
                        if (trans) {
@@ -227,10 +223,11 @@ static void hidinput_pb_setup(struct input_dev *input)
 
        for (trans = powerbook_iso_keyboard; trans->from; trans++)
                set_bit(trans->to, input->keybit);
+
 }
 #else
 static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
-                                   struct hid_usage *usage, __s32 value)
+               struct hid_usage *usage, __s32 value)
 {
        return 0;
 }
@@ -581,6 +578,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
                goto ignore;
 
+       if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) &&
+               usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE))
+               field->flags &= ~HID_MAIN_ITEM_RELATIVE;
+
        set_bit(usage->type, input->evbit);
 
        while (usage->code <= max && test_and_set_bit(usage->code, bit))
@@ -720,8 +721,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
        list_for_each_entry(hidinput, &hid->inputs, list)
                input_sync(hidinput->input);
 }
+EXPORT_SYMBOL_GPL(hidinput_report_event);
 
-static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
 {
        struct hid_report *report;
        int i, j;
@@ -736,41 +738,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
        }
        return -1;
 }
-
-static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-       struct hid_device *hid = dev->private;
-       struct hid_field *field;
-       int offset;
-
-       if (type == EV_FF)
-               return input_ff_event(dev, type, code, value);
-
-       if (type != EV_LED)
-               return -1;
-
-       if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
-               warn("event field not found");
-               return -1;
-       }
-
-       hid_set_field(field, offset, value);
-       hid_submit_report(hid, field->report, USB_DIR_OUT);
-
-       return 0;
-}
-
-static int hidinput_open(struct input_dev *dev)
-{
-       struct hid_device *hid = dev->private;
-       return hid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
-       struct hid_device *hid = dev->private;
-       hid_close(hid);
-}
+EXPORT_SYMBOL_GPL(hidinput_find_field);
 
 /*
  * Register the input device; print a message.
@@ -780,7 +748,6 @@ static void hidinput_close(struct input_dev *dev)
 
 int hidinput_connect(struct hid_device *hid)
 {
-       struct usb_device *dev = hid->dev;
        struct hid_report *report;
        struct hid_input *hidinput = NULL;
        struct input_dev *input_dev;
@@ -814,16 +781,18 @@ int hidinput_connect(struct hid_device *hid)
                                }
 
                                input_dev->private = hid;
-                               input_dev->event = hidinput_input_event;
-                               input_dev->open = hidinput_open;
-                               input_dev->close = hidinput_close;
+                               input_dev->event = hid->hidinput_input_event;
+                               input_dev->open = hid->hidinput_open;
+                               input_dev->close = hid->hidinput_close;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
                                input_dev->uniq = hid->uniq;
-                               usb_to_input_id(dev, &input_dev->id);
-                               input_dev->cdev.dev = &hid->intf->dev;
-
+                               input_dev->id.bustype = hid->bus;
+                               input_dev->id.vendor  = hid->vendor;
+                               input_dev->id.product = hid->product;
+                               input_dev->id.version = hid->version;
+                               input_dev->cdev.dev = hid->dev;
                                hidinput->input = input_dev;
                                list_add_tail(&hidinput->list, &hid->inputs);
                        }
@@ -845,16 +814,12 @@ int hidinput_connect(struct hid_device *hid)
                        }
                }
 
-       /* This only gets called when we are a single-input (most of the
-        * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
-        * only useful in this case, and not for multi-input quirks. */
-       if (hidinput) {
-               hid_ff_init(hid);
+       if (hidinput)
                input_register_device(hidinput->input);
-       }
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(hidinput_connect);
 
 void hidinput_disconnect(struct hid_device *hid)
 {
@@ -866,3 +831,5 @@ void hidinput_disconnect(struct hid_device *hid)
                kfree(hidinput);
        }
 }
+EXPORT_SYMBOL_GPL(hidinput_disconnect);
+
index 04bee52..90f91d0 100644 (file)
@@ -196,11 +196,11 @@ config I2C_IBM_IIC
          will be called i2c-ibm_iic.
 
 config I2C_IOP3XX
-       tristate "Intel IOP3xx and IXP4xx on-chip I2C interface"
-       depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX) && I2C
+       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
+       depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C
        help
          Say Y here if you want to use the IIC bus controller on
-         the Intel IOP3xx I/O Processors or IXP4xx Network Processors.
+         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-iop3xx.
index c95a6c1..c3b1567 100644 (file)
@@ -357,133 +357,6 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 
 
 #ifdef CONFIG_I2C_PXA_SLAVE
-/*
- * I2C EEPROM emulation.
- */
-static struct i2c_eeprom_emu eeprom = {
-       .size = I2C_EEPROM_EMU_SIZE,
-       .watch = LIST_HEAD_INIT(eeprom.watch),
-};
-
-struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void)
-{
-       return &eeprom;
-}
-
-int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data,
-                             unsigned int addr, unsigned int size,
-                             struct i2c_eeprom_emu_watcher *watcher)
-{
-       struct i2c_eeprom_emu_watch *watch;
-       unsigned long flags;
-
-       if (addr + size > emu->size)
-               return -EINVAL;
-
-       watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL);
-       if (watch) {
-               watch->start = addr;
-               watch->end = addr + size - 1;
-               watch->ops = watcher;
-               watch->data = data;
-
-               local_irq_save(flags);
-               list_add(&watch->node, &emu->watch);
-               local_irq_restore(flags);
-       }
-
-       return watch ? 0 : -ENOMEM;
-}
-
-void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data,
-                              struct i2c_eeprom_emu_watcher *watcher)
-{
-       struct i2c_eeprom_emu_watch *watch, *n;
-       unsigned long flags;
-
-       list_for_each_entry_safe(watch, n, &emu->watch, node) {
-               if (watch->ops == watcher && watch->data == data) {
-                       local_irq_save(flags);
-                       list_del(&watch->node);
-                       local_irq_restore(flags);
-                       kfree(watch);
-               }
-       }
-}
-
-static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event)
-{
-       struct i2c_eeprom_emu *emu = ptr;
-
-       eedbg(3, "i2c_eeprom_emu_event: %d\n", event);
-
-       switch (event) {
-       case I2C_SLAVE_EVENT_START_WRITE:
-               emu->seen_start = 1;
-               eedbg(2, "i2c_eeprom: write initiated\n");
-               break;
-
-       case I2C_SLAVE_EVENT_START_READ:
-               emu->seen_start = 0;
-               eedbg(2, "i2c_eeprom: read initiated\n");
-               break;
-
-       case I2C_SLAVE_EVENT_STOP:
-               emu->seen_start = 0;
-               eedbg(2, "i2c_eeprom: received stop\n");
-               break;
-
-       default:
-               eedbg(0, "i2c_eeprom: unhandled event\n");
-               break;
-       }
-}
-
-static int i2c_eeprom_emu_read(void *ptr)
-{
-       struct i2c_eeprom_emu *emu = ptr;
-       int ret;
-
-       ret = emu->bytes[emu->ptr];
-       emu->ptr = (emu->ptr + 1) % emu->size;
-
-       return ret;
-}
-
-static void i2c_eeprom_emu_write(void *ptr, unsigned int val)
-{
-       struct i2c_eeprom_emu *emu = ptr;
-       struct i2c_eeprom_emu_watch *watch;
-
-       if (emu->seen_start != 0) {
-               eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val);
-               emu->ptr = val;
-               emu->seen_start = 0;
-               return;
-       }
-
-       emu->bytes[emu->ptr] = val;
-
-       eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n",
-             emu->ptr, val);
-
-       list_for_each_entry(watch, &emu->watch, node) {
-               if (!watch->ops || !watch->ops->write)
-                       continue;
-               if (watch->start <= emu->ptr && watch->end >= emu->ptr)
-                       watch->ops->write(watch->data, emu->ptr, val);
-       }
-
-       emu->ptr = (emu->ptr + 1) % emu->size;
-}
-
-struct i2c_slave_client eeprom_client = {
-       .data   = &eeprom,
-       .event  = i2c_eeprom_emu_event,
-       .read   = i2c_eeprom_emu_read,
-       .write  = i2c_eeprom_emu_write
-};
-
 /*
  * PXA I2C Slave mode
  */
@@ -963,11 +836,9 @@ static int i2c_pxa_probe(struct platform_device *dev)
        i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
 
 #ifdef CONFIG_I2C_PXA_SLAVE
-       i2c->slave = &eeprom_client;
        if (plat) {
                i2c->slave_addr = plat->slave_addr;
-               if (plat->slave)
-                       i2c->slave = plat->slave;
+               i2c->slave = plat->slave;
        }
 #endif
 
index 4630f19..15edf40 100644 (file)
@@ -140,12 +140,14 @@ ulong ds1374_get_rtc_time(void)
        return t1;
 }
 
-static void ds1374_set_work(void *arg)
+static ulong new_time;
+
+static void ds1374_set_work(struct work_struct *work)
 {
        ulong t1, t2;
        int limit = 10;         /* arbitrary retry limit */
 
-       t1 = *(ulong *) arg;
+       t1 = new_time;
 
        mutex_lock(&ds1374_mutex);
 
@@ -167,11 +169,9 @@ static void ds1374_set_work(void *arg)
                         "can't confirm time set from rtc chip\n");
 }
 
-static ulong new_time;
-
 static struct workqueue_struct *ds1374_workqueue;
 
-static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
+static DECLARE_WORK(ds1374_work, ds1374_set_work);
 
 int ds1374_set_rtc_time(ulong nowtime)
 {
@@ -180,7 +180,7 @@ int ds1374_set_rtc_time(ulong nowtime)
        if (in_interrupt())
                queue_work(ds1374_workqueue, &ds1374_work);
        else
-               ds1374_set_work(&new_time);
+               ds1374_set_work(NULL);
 
        return 0;
 }
index 2dd0a34..420377c 100644 (file)
@@ -215,8 +215,15 @@ m41t00_set(void *arg)
 }
 
 static ulong new_time;
+/* well, isn't this API just _lovely_? */
+static void
+m41t00_barf(struct work_struct *unusable)
+{
+       m41t00_set(&new_time);
+}
+
 static struct workqueue_struct *m41t00_wq;
-static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
+static DECLARE_WORK(m41t00_work, m41t00_barf);
 
 int
 m41t00_set_rtc_time(ulong nowtime)
index 94a4e9a..2e22a2f 100644 (file)
@@ -119,7 +119,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
                return -ENOMEM;
 
        pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n",
-               iminor(file->f_dentry->d_inode), count);
+               iminor(file->f_path.dentry->d_inode), count);
 
        ret = i2c_master_recv(client,tmp,count);
        if (ret >= 0)
@@ -147,7 +147,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
        }
 
        pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n",
-               iminor(file->f_dentry->d_inode), count);
+               iminor(file->f_path.dentry->d_inode), count);
 
        ret = i2c_master_send(client,tmp,count);
        kfree(tmp);
index 0c68d0f..e23bc0d 100644 (file)
@@ -389,14 +389,6 @@ config BLK_DEV_RZ1000
          Linux. This may slow disk throughput by a few percent, but at least
          things will operate 100% reliably.
 
-config BLK_DEV_SL82C105
-       tristate "Winbond SL82c105 support"
-       depends on PCI && (PPC || ARM) && BLK_DEV_IDEPCI
-       help
-         If you have a Winbond SL82c105 IDE controller, say Y here to enable
-         special configuration for this chip. This is common on various CHRP
-         motherboards, but could be used elsewhere. If in doubt, say Y.
-
 config BLK_DEV_IDEDMA_PCI
        bool "Generic PCI bus-master DMA support"
        depends on PCI && BLK_DEV_IDEPCI
@@ -712,6 +704,14 @@ config BLK_DEV_SIS5513
 
          Please read the comments at the top of <file:drivers/ide/pci/sis5513.c>.
 
+config BLK_DEV_SL82C105
+       tristate "Winbond SL82c105 support"
+       depends on (PPC || ARM)
+       help
+         If you have a Winbond SL82c105 IDE controller, say Y here to enable
+         special configuration for this chip. This is common on various CHRP
+         motherboards, but could be used elsewhere. If in doubt, say Y.
+
 config BLK_DEV_SLC90E66
        tristate "SLC90E66 chipset support"
        help
index 8821494..5969cec 100644 (file)
@@ -687,8 +687,15 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
        struct request *rq = HWGROUP(drive)->rq;
+       ide_hwif_t *hwif = HWIF(drive);
        int stat, err, sense_key;
        
+       /* We may have bogus DMA interrupts in PIO state here */
+       if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) {
+               stat = hwif->INB(hwif->dma_status);
+               /* Should we force the bit as well ? */
+               hwif->OUTB(stat, hwif->dma_status);
+       }
        /* Check for errors. */
        stat = HWIF(drive)->INB(IDE_STATUS_REG);
        if (stat_ret)
index dad9c47..5a5c565 100644 (file)
@@ -1000,10 +1000,6 @@ static int ide_init_queue(ide_drive_t *drive)
        /* needs drive->queue to be set */
        ide_toggle_bounce(drive, 1);
 
-       /* enable led activity for disk drives only */
-       if (drive->media == ide_disk && hwif->led_act)
-               blk_queue_activity_fn(q, hwif->led_act, drive);
-
        return 0;
 }
 
index 287a662..1689076 100644 (file)
@@ -973,8 +973,8 @@ ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
  *     @drive: drive
  *
  *     Automatically remove all the driver specific settings for this
- *     drive. This function may sleep and must not be called from IRQ
- *     context. The caller must hold ide_setting_sem.
+ *     drive. This function may not be called from IRQ context. The
+ *     caller must hold ide_setting_sem.
  */
  
 static void auto_remove_settings (ide_drive_t *drive)
@@ -1874,11 +1874,22 @@ void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
        unsigned long flags;
        
-       down(&ide_setting_sem);
-       spin_lock_irqsave(&ide_lock, flags);
 #ifdef CONFIG_PROC_FS
        ide_remove_proc_entries(drive->proc, driver->proc);
 #endif
+       down(&ide_setting_sem);
+       spin_lock_irqsave(&ide_lock, flags);
+       /*
+        * ide_setting_sem protects the settings list
+        * ide_lock protects the use of settings
+        *
+        * so we need to hold both, ide_settings_sem because we want to
+        * modify the settings list, and ide_lock because we cannot take
+        * a setting out that is being used.
+        *
+        * OTOH both ide_{read,write}_setting are only ever used under
+        * ide_setting_sem.
+        */
        auto_remove_settings(drive);
        spin_unlock_irqrestore(&ide_lock, flags);
        up(&ide_setting_sem);
index d419e4b..89109be 100644 (file)
@@ -586,11 +586,11 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
 {
        unsigned long flags;
        u8 tmpbyte;
-       struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0));
+       struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
 
        pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
 
-       isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+       isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
 #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
        if (!ali_proc) {
@@ -613,8 +613,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
                 * clear bit 7
                 */
                pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
-               local_irq_restore(flags);
-               return 0;
+               goto out;
        }
 
        /*
@@ -637,10 +636,8 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
         * box without a device at 0:0.0. The ALi bridge will be at
         * 0:0.0 so if we didn't find one we know what is cooking.
         */
-       if (north && north->vendor != PCI_VENDOR_ID_AL) {
-               local_irq_restore(flags);
-               return 0;
-       }
+       if (north && north->vendor != PCI_VENDOR_ID_AL)
+               goto out;
 
        if (m5229_revision < 0xC5 && isa_dev)
        {       
@@ -661,6 +658,9 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
                        pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
                }
        }
+out:
+       pci_dev_put(north);
+       pci_dev_put(isa_dev);
        local_irq_restore(flags);
        return 0;
 }
index 6c097e8..7cb4857 100644 (file)
@@ -9,6 +9,7 @@
  *  Split from:
  *  linux/drivers/ide/pdc202xx.c       Version 0.35    Mar. 30, 2002
  *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2005-2006            MontaVista Software, Inc.
  *  Portions Copyright (C) 1999 Promise Technology, Inc.
  *  Author: Frank Tiernan (frankt@promise.com)
  *  Released under terms of General Public License
 
 #define PDC202_DEBUG_CABLE     0
 
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
 static const char *pdc_quirk_drives[] = {
        "QUANTUM FIREBALLlct08 08",
        "QUANTUM FIREBALLP KA6.4",
@@ -50,37 +59,11 @@ static const char *pdc_quirk_drives[] = {
        NULL
 };
 
-#define set_2regs(a, b)                                        \
-       do {                                            \
-               hwif->OUTB((a + adj), indexreg);        \
-               hwif->OUTB(b, datareg);                 \
-       } while(0)
-
-#define set_ultra(a, b, c)                             \
-       do {                                            \
-               set_2regs(0x10,(a));                    \
-               set_2regs(0x11,(b));                    \
-               set_2regs(0x12,(c));                    \
-       } while(0)
-
-#define set_ata2(a, b)                                 \
-       do {                                            \
-               set_2regs(0x0e,(a));                    \
-               set_2regs(0x0f,(b));                    \
-       } while(0)
-
-#define set_pio(a, b, c)                               \
-       do {                                            \
-               set_2regs(0x0c,(a));                    \
-               set_2regs(0x0d,(b));                    \
-               set_2regs(0x13,(c));                    \
-       } while(0)
-
-static u8 pdcnew_ratemask (ide_drive_t *drive)
+static u8 max_dma_rate(struct pci_dev *pdev)
 {
        u8 mode;
 
-       switch(HWIF(drive)->pci_dev->device) {
+       switch(pdev->device) {
                case PCI_DEVICE_ID_PROMISE_20277:
                case PCI_DEVICE_ID_PROMISE_20276:
                case PCI_DEVICE_ID_PROMISE_20275:
@@ -95,12 +78,21 @@ static u8 pdcnew_ratemask (ide_drive_t *drive)
                default:
                        return 0;
        }
-       if (!eighty_ninty_three(drive))
-               mode = min(mode, (u8)1);
+
        return mode;
 }
 
-static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+static u8 pdcnew_ratemask(ide_drive_t *drive)
+{
+       u8 mode = max_dma_rate(HWIF(drive)->pci_dev);
+
+       if (!eighty_ninty_three(drive))
+               mode = min_t(u8, mode, 1);
+
+       return  mode;
+}
+
+static int check_in_drive_lists(ide_drive_t *drive, const char **list)
 {
        struct hd_driveid *id = drive->id;
 
@@ -120,43 +112,141 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
        return 0;
 }
 
-static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+/**
+ * get_indexed_reg - Get indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
+{
+       u8 value;
+
+       hwif->OUTB(index, hwif->dma_vendor1);
+       value = hwif->INB(hwif->dma_vendor3);
+
+       DBG("index[%02X] value[%02X]\n", index, value);
+       return value;
+}
+
+/**
+ * set_indexed_reg - Set indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
+{
+       hwif->OUTB(index, hwif->dma_vendor1);
+       hwif->OUTB(value, hwif->dma_vendor3);
+       DBG("index[%02X] value[%02X]\n", index, value);
+}
+
+/*
+ * ATA Timing Tables based on 133 MHz PLL output clock.
+ *
+ * If the PLL outputs 100 MHz clock, the ASIC hardware will set
+ * the timing registers automatically when "set features" command is
+ * issued to the device. However, if the PLL output clock is 133 MHz,
+ * the following tables must be used.
+ */
+static struct pio_timing {
+       u8 reg0c, reg0d, reg13;
+} pio_timings [] = {
+       { 0xfb, 0x2b, 0xac },   /* PIO mode 0, IORDY off, Prefetch off */
+       { 0x46, 0x29, 0xa4 },   /* PIO mode 1, IORDY off, Prefetch off */
+       { 0x23, 0x26, 0x64 },   /* PIO mode 2, IORDY off, Prefetch off */
+       { 0x27, 0x0d, 0x35 },   /* PIO mode 3, IORDY on,  Prefetch off */
+       { 0x23, 0x09, 0x25 },   /* PIO mode 4, IORDY on,  Prefetch off */
+};
+
+static struct mwdma_timing {
+       u8 reg0e, reg0f;
+} mwdma_timings [] = {
+       { 0xdf, 0x5f },         /* MWDMA mode 0 */
+       { 0x6b, 0x27 },         /* MWDMA mode 1 */
+       { 0x69, 0x25 },         /* MWDMA mode 2 */
+};
+
+static struct udma_timing {
+       u8 reg10, reg11, reg12;
+} udma_timings [] = {
+       { 0x4a, 0x0f, 0xd5 },   /* UDMA mode 0 */
+       { 0x3a, 0x0a, 0xd0 },   /* UDMA mode 1 */
+       { 0x2a, 0x07, 0xcd },   /* UDMA mode 2 */
+       { 0x1a, 0x05, 0xcd },   /* UDMA mode 3 */
+       { 0x1a, 0x03, 0xcd },   /* UDMA mode 4 */
+       { 0x1a, 0x02, 0xcb },   /* UDMA mode 5 */
+       { 0x1a, 0x01, 0xcb },   /* UDMA mode 6 */
+};
+
+static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long indexreg  = hwif->dma_vendor1;
-       unsigned long datareg   = hwif->dma_vendor3;
-       u8 thold                = 0x10;
-       u8 adj                  = (drive->dn%2) ? 0x08 : 0x00;
-       u8 speed                = ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
-
-       if (speed == XFER_UDMA_2) {
-               hwif->OUTB((thold + adj), indexreg);
-               hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg);
-       }
+       u8 adj                  = (drive->dn & 1) ? 0x08 : 0x00;
+       int                     err;
 
-       switch (speed) {
-               case XFER_UDMA_7:
-                       speed = XFER_UDMA_6;
-               case XFER_UDMA_6:       set_ultra(0x1a, 0x01, 0xcb); break;
-               case XFER_UDMA_5:       set_ultra(0x1a, 0x02, 0xcb); break;
-               case XFER_UDMA_4:       set_ultra(0x1a, 0x03, 0xcd); break;
-               case XFER_UDMA_3:       set_ultra(0x1a, 0x05, 0xcd); break;
-               case XFER_UDMA_2:       set_ultra(0x2a, 0x07, 0xcd); break;
-               case XFER_UDMA_1:       set_ultra(0x3a, 0x0a, 0xd0); break;
-               case XFER_UDMA_0:       set_ultra(0x4a, 0x0f, 0xd5); break;
-               case XFER_MW_DMA_2:     set_ata2(0x69, 0x25); break;
-               case XFER_MW_DMA_1:     set_ata2(0x6b, 0x27); break;
-               case XFER_MW_DMA_0:     set_ata2(0xdf, 0x5f); break;
-               case XFER_PIO_4:        set_pio(0x23, 0x09, 0x25); break;
-               case XFER_PIO_3:        set_pio(0x27, 0x0d, 0x35); break;
-               case XFER_PIO_2:        set_pio(0x23, 0x26, 0x64); break;
-               case XFER_PIO_1:        set_pio(0x46, 0x29, 0xa4); break;
-               case XFER_PIO_0:        set_pio(0xfb, 0x2b, 0xac); break;
-               default:
-                       ;
-       }
+       speed = ide_rate_filter(pdcnew_ratemask(drive), speed);
+
+       /*
+        * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will
+        * automatically set the timing registers based on 100 MHz PLL output.
+        */
+       err = ide_config_drive_speed(drive, speed);
+
+       /*
+        * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
+        * chips, we must override the default register settings...
+        */
+       if (max_dma_rate(hwif->pci_dev) == 4) {
+               u8 mode = speed & 0x07;
+
+               switch (speed) {
+                       case XFER_UDMA_6:
+                       case XFER_UDMA_5:
+                       case XFER_UDMA_4:
+                       case XFER_UDMA_3:
+                       case XFER_UDMA_2:
+                       case XFER_UDMA_1:
+                       case XFER_UDMA_0:
+                               set_indexed_reg(hwif, 0x10 + adj,
+                                               udma_timings[mode].reg10);
+                               set_indexed_reg(hwif, 0x11 + adj,
+                                               udma_timings[mode].reg11);
+                               set_indexed_reg(hwif, 0x12 + adj,
+                                               udma_timings[mode].reg12);
+                               break;
+
+                       case XFER_MW_DMA_2:
+                       case XFER_MW_DMA_1:
+                       case XFER_MW_DMA_0:
+                               set_indexed_reg(hwif, 0x0e + adj,
+                                               mwdma_timings[mode].reg0e);
+                               set_indexed_reg(hwif, 0x0f + adj,
+                                               mwdma_timings[mode].reg0f);
+                               break;
+                       case XFER_PIO_4:
+                       case XFER_PIO_3:
+                       case XFER_PIO_2:
+                       case XFER_PIO_1:
+                       case XFER_PIO_0:
+                               set_indexed_reg(hwif, 0x0c + adj,
+                                               pio_timings[mode].reg0c);
+                               set_indexed_reg(hwif, 0x0d + adj,
+                                               pio_timings[mode].reg0d);
+                               set_indexed_reg(hwif, 0x13 + adj,
+                                               pio_timings[mode].reg13);
+                               break;
+                       default:
+                               printk(KERN_ERR "pdc202xx_new: "
+                                      "Unknown speed %d ignored\n", speed);
+               }
+       } else if (speed == XFER_UDMA_2) {
+               /* Set tHOLD bit to 0 if using UDMA mode 2 */
+               u8 tmp = get_indexed_reg(hwif, 0x10 + adj);
 
-       return (ide_config_drive_speed(drive, speed));
+               set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
+       }
+
+       return err;
 }
 
 /*   0    1    2    3    4    5    6   7   8
@@ -168,55 +258,55 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
  */
 static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
 {
-       u8 speed;
-
-       if (pio == 5) pio = 4;
-       speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
-
-       (void)pdcnew_new_tune_chipset(drive, speed);
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio);
 }
 
-static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif)
+static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
 {
-       hwif->OUTB(0x0b, hwif->dma_vendor1);
-       return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04)));
+       return get_indexed_reg(hwif, 0x0b) & 0x04;
 }
-static int config_chipset_for_dma (ide_drive_t *drive)
+
+static int config_chipset_for_dma(ide_drive_t *drive)
 {
        struct hd_driveid *id   = drive->id;
        ide_hwif_t *hwif        = HWIF(drive);
-       u8 speed                = -1;
-       u8 cable;
-
-       u8 ultra_66             = ((id->dma_ultra & 0x0010) ||
-                                  (id->dma_ultra & 0x0008)) ? 1 : 0;
-
-       cable = pdcnew_new_cable_detect(hwif);
+       u8 ultra_66             = (id->dma_ultra & 0x0078) ? 1 : 0;
+       u8 cable                = pdcnew_cable_detect(hwif);
+       u8 speed;
 
        if (ultra_66 && cable) {
-               printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary");
+               printk(KERN_WARNING "Warning: %s channel "
+                      "requires an 80-pin cable for operation.\n",
+                      hwif->channel ? "Secondary" : "Primary");
                printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
        }
 
        if (drive->media != ide_disk)
                return 0;
-       if (id->capability & 4) {       /* IORDY_EN & PREFETCH_EN */
-               hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1);
-               hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3);
+
+       if (id->capability & 4) {
+               /*
+                * Set IORDY_EN & PREFETCH_EN (this seems to have
+                * NO real effect since this register is reloaded
+                * by hardware when the transfer mode is selected)
+                */
+               u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00;
+
+               tmp = get_indexed_reg(hwif, 0x13 + adj);
+               set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03);
        }
 
        speed = ide_dma_speed(drive, pdcnew_ratemask(drive));
 
-       if (!(speed)) {
-               hwif->tuneproc(drive, 5);
+       if (!speed)
                return 0;
-       }
 
        (void) hwif->speedproc(drive, speed);
        return ide_dma_enable(drive);
 }
 
-static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive)
+static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct hd_driveid *id   = drive->id;
@@ -234,16 +324,16 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive)
 
        } else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-               hwif->tuneproc(drive, 5);
+               hwif->tuneproc(drive, 255);
                return hwif->ide_dma_off_quietly(drive);
        }
        /* IORDY not supported */
        return 0;
 }
 
-static int pdcnew_quirkproc (ide_drive_t *drive)
+static int pdcnew_quirkproc(ide_drive_t *drive)
 {
-       return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
+       return check_in_drive_lists(drive, pdc_quirk_drives);
 }
 
 static int pdcnew_ide_dma_lostirq(ide_drive_t *drive)
@@ -260,21 +350,100 @@ static int pdcnew_ide_dma_timeout(ide_drive_t *drive)
        return __ide_dma_timeout(drive);
 }
 
-static void pdcnew_new_reset (ide_drive_t *drive)
+static void pdcnew_reset(ide_drive_t *drive)
 {
        /*
         * Deleted this because it is redundant from the caller.
         */
-       printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
+       printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
                HWIF(drive)->channel ? "Secondary" : "Primary");
 }
 
+/**
+ * read_counter - Read the byte count registers
+ * @dma_base: for the port address
+ */
+static long __devinit read_counter(u32 dma_base)
+{
+       u32  pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
+       u8   cnt0, cnt1, cnt2, cnt3;
+       long count = 0, last;
+       int  retry = 3;
+
+       do {
+               last = count;
+
+               /* Read the current count */
+               outb(0x20, pri_dma_base + 0x01);
+               cnt0 = inb(pri_dma_base + 0x03);
+               outb(0x21, pri_dma_base + 0x01);
+               cnt1 = inb(pri_dma_base + 0x03);
+               outb(0x20, sec_dma_base + 0x01);
+               cnt2 = inb(sec_dma_base + 0x03);
+               outb(0x21, sec_dma_base + 0x01);
+               cnt3 = inb(sec_dma_base + 0x03);
+
+               count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;
+
+               /*
+                * The 30-bit decrementing counter is read in 4 pieces.
+                * Incorrect value may be read when the most significant bytes
+                * are changing...
+                */
+       } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));
+
+       DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",
+                 cnt0, cnt1, cnt2, cnt3);
+
+       return count;
+}
+
+/**
+ * detect_pll_input_clock - Detect the PLL input clock in Hz.
+ * @dma_base: for the port address
+ * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
+ */
+static long __devinit detect_pll_input_clock(unsigned long dma_base)
+{
+       long start_count, end_count;
+       long pll_input;
+       u8 scr1;
+
+       start_count = read_counter(dma_base);
+
+       /* Start the test mode */
+       outb(0x01, dma_base + 0x01);
+       scr1 = inb(dma_base + 0x03);
+       DBG("scr1[%02X]\n", scr1);
+       outb(scr1 | 0x40, dma_base + 0x03);
+
+       /* Let the counter run for 10 ms. */
+       mdelay(10);
+
+       end_count = read_counter(dma_base);
+
+       /* Stop the test mode */
+       outb(0x01, dma_base + 0x01);
+       scr1 = inb(dma_base + 0x03);
+       DBG("scr1[%02X]\n", scr1);
+       outb(scr1 & ~0x40, dma_base + 0x03);
+
+       /*
+        * Calculate the input clock in Hz
+        * (the clock counter is 30 bit wide and counts down)
+        */
+       pll_input = ((start_count - end_count) & 0x3ffffff) * 100;
+
+       DBG("start[%ld] end[%ld]\n", start_count, end_count);
+
+       return pll_input;
+}
+
 #ifdef CONFIG_PPC_PMAC
 static void __devinit apple_kiwi_init(struct pci_dev *pdev)
 {
        struct device_node *np = pci_device_to_OF_node(pdev);
        unsigned int class_rev = 0;
-       void __iomem *mmio;
        u8 conf;
 
        if (np == NULL || !device_is_compatible(np, "kiwi-root"))
@@ -285,30 +454,20 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
 
        if (class_rev >= 0x03) {
                /* Setup chip magic config stuff (from darwin) */
-               pci_read_config_byte(pdev, 0x40, &conf);
-               pci_write_config_byte(pdev, 0x40, conf | 0x01);
-       }
-       mmio = ioremap(pci_resource_start(pdev, 5),
-                                     pci_resource_len(pdev, 5));
-
-       /* Setup some PLL stuffs */
-       switch (pdev->device) {
-       case PCI_DEVICE_ID_PROMISE_20270:
-               writew(0x0d2b, mmio + 0x1202);
-               mdelay(30);
-               break;
-       case PCI_DEVICE_ID_PROMISE_20271:
-               writew(0x0826, mmio + 0x1202);
-               mdelay(30);
-               break;
+               pci_read_config_byte (pdev, 0x40, &conf);
+               pci_write_config_byte(pdev, 0x40, (conf | 0x01));
        }
-
-       iounmap(mmio);
 }
 #endif /* CONFIG_PPC_PMAC */
 
 static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
 {
+       unsigned long dma_base = pci_resource_start(dev, 4);
+       unsigned long sec_dma_base = dma_base + 0x08;
+       long pll_input, pll_output, ratio;
+       int f, r;
+       u8 pll_ctl0, pll_ctl1;
+
        if (dev->resource[PCI_ROM_RESOURCE].start) {
                pci_write_config_dword(dev, PCI_ROM_ADDRESS,
                        dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
@@ -320,6 +479,106 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
        apple_kiwi_init(dev);
 #endif
 
+       /* Calculate the required PLL output frequency */
+       switch(max_dma_rate(dev)) {
+               case 4: /* it's 133 MHz for Ultra133 chips */
+                       pll_output = 133333333;
+                       break;
+               case 3: /* and  100 MHz for Ultra100 chips */
+               default:
+                       pll_output = 100000000;
+                       break;
+       }
+
+       /*
+        * Detect PLL input clock.
+        * On some systems, where PCI bus is running at non-standard clock rate
+        * (e.g. 25 or 40 MHz), we have to adjust the cycle time.
+        * PDC20268 and newer chips employ PLL circuit to help correct timing
+        * registers setting.
+        */
+       pll_input = detect_pll_input_clock(dma_base);
+       printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000);
+
+       /* Sanity check */
+       if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
+               printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n",
+                      name, pll_input);
+               goto out;
+       }
+
+#ifdef DEBUG
+       DBG("pll_output is %ld Hz\n", pll_output);
+
+       /* Show the current clock value of PLL control register
+        * (maybe already configured by the BIOS)
+        */
+       outb(0x02, sec_dma_base + 0x01);
+       pll_ctl0 = inb(sec_dma_base + 0x03);
+       outb(0x03, sec_dma_base + 0x01);
+       pll_ctl1 = inb(sec_dma_base + 0x03);
+
+       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+       /*
+        * Calculate the ratio of F, R and NO
+        * POUT = (F + 2) / (( R + 2) * NO)
+        */
+       ratio = pll_output / (pll_input / 1000);
+       if (ratio < 8600L) { /* 8.6x */
+               /* Using NO = 0x01, R = 0x0d */
+               r = 0x0d;
+       } else if (ratio < 12900L) { /* 12.9x */
+               /* Using NO = 0x01, R = 0x08 */
+               r = 0x08;
+       } else if (ratio < 16100L) { /* 16.1x */
+               /* Using NO = 0x01, R = 0x06 */
+               r = 0x06;
+       } else if (ratio < 64000L) { /* 64x */
+               r = 0x00;
+       } else {
+               /* Invalid ratio */
+               printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio);
+               goto out;
+       }
+
+       f = (ratio * (r + 2)) / 1000 - 2;
+
+       DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio);
+
+       if (unlikely(f < 0 || f > 127)) {
+               /* Invalid F */
+               printk(KERN_ERR "%s: F[%d] invalid!\n", name, f);
+               goto out;
+       }
+
+       pll_ctl0 = (u8) f;
+       pll_ctl1 = (u8) r;
+
+       DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+
+       outb(0x02,     sec_dma_base + 0x01);
+       outb(pll_ctl0, sec_dma_base + 0x03);
+       outb(0x03,     sec_dma_base + 0x01);
+       outb(pll_ctl1, sec_dma_base + 0x03);
+
+       /* Wait the PLL circuit to be stable */
+       mdelay(30);
+
+#ifdef DEBUG
+       /*
+        *  Show the current clock value of PLL control register
+        */
+       outb(0x02, sec_dma_base + 0x01);
+       pll_ctl0 = inb(sec_dma_base + 0x03);
+       outb(0x03, sec_dma_base + 0x01);
+       pll_ctl1 = inb(sec_dma_base + 0x03);
+
+       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ out:
        return dev->irq;
 }
 
@@ -329,8 +588,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
 
        hwif->tuneproc  = &pdcnew_tune_drive;
        hwif->quirkproc = &pdcnew_quirkproc;
-       hwif->speedproc = &pdcnew_new_tune_chipset;
-       hwif->resetproc = &pdcnew_new_reset;
+       hwif->speedproc = &pdcnew_tune_chipset;
+       hwif->resetproc = &pdcnew_reset;
 
        hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 
@@ -342,11 +601,14 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
        hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
        hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq;
        hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout;
-       if (!(hwif->udma_four))
-               hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1;
+
+       if (!hwif->udma_four)
+               hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+
        if (!noautodma)
                hwif->autodma = 1;
        hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
+
 #if PDC202_DEBUG_CABLE
        printk(KERN_DEBUG "%s: %s-pin cable\n",
                hwif->name, hwif->udma_four ? "80" : "40");
@@ -362,6 +624,7 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev,
                                         ide_pci_device_t *d)
 {
        struct pci_dev *findev = NULL;
+       int ret;
 
        if ((dev->bus->self &&
             dev->bus->self->vendor == PCI_VENDOR_ID_DEC) &&
@@ -369,14 +632,16 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev,
                if (PCI_SLOT(dev->devfn) & 2)
                        return -ENODEV;
                d->extra = 0;
-               while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
+               while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
                        if ((findev->vendor == dev->vendor) &&
                            (findev->device == dev->device) &&
                            (PCI_SLOT(findev->devfn) & 2)) {
                                if (findev->irq != dev->irq) {
                                        findev->irq = dev->irq;
                                }
-                               return ide_setup_pci_devices(dev, findev, d);
+                               ret = ide_setup_pci_devices(dev, findev, d);
+                               pci_dev_put(findev);
+                               return ret;
                        }
                }
        }
index cdc3aab..b1e9a8e 100644 (file)
@@ -505,6 +505,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
                /* This is a painful system best to let it self tune for now */
                return;
        }
+       /* ESB2 appears to generate spurious DMA interrupts in PIO mode
+          when in native mode */
+       if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
+               hwif->atapi_irq_bogon = 1;
 
        hwif->autodma = 0;
        hwif->tuneproc = &piix_tune_drive;
index 92edf76..6b31313 100644 (file)
@@ -800,9 +800,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
 
                        if (trueid == 0x5517) { /* SiS 961/961B */
 
-                               lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */
+                               lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
                                pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
                                pci_read_config_byte(dev, 0x49, &prefctl);
+                               pci_dev_put(lpc_bridge);
 
                                if (sbrev == 0x10 && (prefctl & 0x80)) {
                                        printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
index 0b4b604..5afefe8 100644 (file)
@@ -299,14 +299,14 @@ static void sl82c105_selectproc(ide_drive_t *drive)
        //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
 
        mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16;
-       old = val = *((u32 *)&hwif->hwif_data);
+       old = val = (u32)pci_get_drvdata(dev);
        if (drive->using_dma)
                val &= ~mask;
        else
                val |= mask;
        if (old != val) {
                pci_write_config_dword(dev, 0x40, val); 
-               *((u32 *)&hwif->hwif_data) = val;
+               pci_set_drvdata(dev, (void *)val);
        }
 }
 
@@ -316,14 +316,13 @@ static void sl82c105_selectproc(ide_drive_t *drive)
  */
 static void sl82c105_resetproc(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
+       struct pci_dev *dev = HWIF(drive)->pci_dev;
        u32 val;
 
        DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
 
        pci_read_config_dword(dev, 0x40, &val);
-       *((u32 *)&hwif->hwif_data) = val;
+       pci_set_drvdata(dev, (void *)val);
 }
        
 /*
@@ -394,6 +393,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
        pci_read_config_dword(dev, 0x40, &val);
        val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
        pci_write_config_dword(dev, 0x40, val);
+       pci_set_drvdata(dev, (void *)val);
 
        return dev->irq;
 }
@@ -404,30 +404,25 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
 
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
-       struct pci_dev *dev = hwif->pci_dev;
        unsigned int rev;
        u8 dma_state;
-       u32 val;
-       
+
        DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
        hwif->tuneproc = tune_sl82c105;
        hwif->selectproc = sl82c105_selectproc;
        hwif->resetproc = sl82c105_resetproc;
-       
-       /* Default to PIO 0 for fallback unless tuned otherwise,
-        * we always autotune PIO, this is done before DMA is
-        * checked, so there is no risk of accidentally disabling
-        * DMA
-         */
+
+       /*
+        * Default to PIO 0 for fallback unless tuned otherwise.
+        * We always autotune PIO,  this is done before DMA is checked,
+        * so there's no risk of accidentally disabling DMA
+        */
        hwif->drives[0].pio_speed = XFER_PIO_0;
        hwif->drives[0].autotune = 1;
-       hwif->drives[1].pio_speed = XFER_PIO_1;
+       hwif->drives[1].pio_speed = XFER_PIO_0;
        hwif->drives[1].autotune = 1;
 
-       pci_read_config_dword(dev, 0x40, &val);
-       *((u32 *)&hwif->hwif_data) = val;
-       
        hwif->atapi_dma = 0;
        hwif->mwdma_mask = 0;
        hwif->swdma_mask = 0;
index eb7ab11..61f1a96 100644 (file)
@@ -282,11 +282,11 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
         * Find the ISA bridge to see how good the IDE is.
         */
        via_config = via_config_find(&isa);
-       if (!via_config->id) {
-               printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
-               pci_dev_put(isa);
-               return -ENODEV;
-       }
+
+       /* We checked this earlier so if it fails here deeep badness
+          is involved */
+
+       BUG_ON(!via_config->id);
 
        /*
         * Setup or disable Clk66 if appropriate
@@ -494,6 +494,17 @@ static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = {
 
 static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       struct pci_dev *isa = NULL;
+       struct via_isa_bridge *via_config;
+       /*
+        * Find the ISA bridge and check we know what it is.
+        */
+       via_config = via_config_find(&isa);
+       pci_dev_put(isa);
+       if (!via_config->id) {
+               printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
+               return -ENODEV;
+       }
        return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]);
 }
 
index 0719b64..695e239 100644 (file)
@@ -844,11 +844,11 @@ void __init ide_scan_pcibus (int scan_direction)
 
        pre_init = 0;
        if (!scan_direction) {
-               while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                        ide_scan_pcidev(dev);
                }
        } else {
-               while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                        ide_scan_pcidev(dev);
                }
        }
index 672b92e..e7d5657 100644 (file)
@@ -36,7 +36,7 @@ config IEEE1394_VERBOSEDEBUG
          else says N.
 
 config IEEE1394_OUI_DB
-       bool "OUI Database built-in"
+       bool "OUI Database built-in (deprecated)"
        depends on IEEE1394
        help
          If you say Y here, then an OUI list (vendor unique ID's) will be
@@ -67,16 +67,11 @@ config IEEE1394_CONFIG_ROM_IP1394
          eth1394 option below.
 
 config IEEE1394_EXPORT_FULL_API
-       bool "Export all symbols of ieee1394's API"
+       bool "Export all symbols of ieee1394's API (deprecated)"
        depends on IEEE1394
        default n
        help
-         Export all symbols of ieee1394's driver programming interface, even
-         those that are not currently used by the standard IEEE 1394 drivers.
-
-         This option does not affect the interface to userspace applications.
-         Say Y here if you want to compile externally developed drivers that
-         make extended use of ieee1394's API. It is otherwise safe to say N.
+         This option will be removed soon.  Don't worry, say N.
 
 comment "Device Drivers"
        depends on IEEE1394
@@ -125,7 +120,7 @@ comment "SBP-2 support (for storage devices) requires SCSI"
 
 config IEEE1394_SBP2
        tristate "SBP-2 support (Harddisks etc.)"
-       depends on IEEE1394 && SCSI && (PCI || BROKEN)
+       depends on IEEE1394 && SCSI
        help
          This option enables you to use SBP-2 devices connected to an IEEE
          1394 bus.  SBP-2 devices include storage devices like harddisks and
@@ -161,17 +156,12 @@ config IEEE1394_ETH1394
          MCAP, therefore multicast support is significantly limited.
 
 config IEEE1394_DV1394
-       tristate "OHCI-DV I/O support"
+       tristate "OHCI-DV I/O support (deprecated)"
        depends on IEEE1394 && IEEE1394_OHCI1394
        help
-         This driver allows you to transmit and receive DV (digital video)
-         streams on an OHCI-1394 card using a simple frame-oriented
-         interface.
-
-         The user-space API for dv1394 is documented in dv1394.h.
-
-         To compile this driver as a module, say M here: the
-         module will be called dv1394.
+         The dv1394 driver will be removed from Linux in a future release.
+         Its functionality is now provided by raw1394 together with libraries
+         such as libiec61883.
 
 config IEEE1394_RAWIO
        tristate "Raw IEEE1394 I/O support"
index 6f53611..d9650d3 100644 (file)
@@ -3,8 +3,11 @@
 #
 
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-                highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
+                highlevel.o csr.o nodemgr.o dma.o iso.o \
                 csr1212.o config_roms.o
+ifdef CONFIG_IEEE1394_OUI_DB
+ieee1394-objs += oui.o
+endif
 
 obj-$(CONFIG_IEEE1394) += ieee1394.o
 obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
index ab0c80f..52ac83e 100644 (file)
@@ -158,12 +158,10 @@ static void host_reset(struct hpsb_host *host)
  */
 static inline void calculate_expire(struct csr_control *csr)
 {
-       unsigned long usecs =
-               (csr->split_timeout_hi & 0x07) * USEC_PER_SEC +
-               (csr->split_timeout_lo >> 19) * 125L;
-
-       csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L);
+       unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 +
+                            (csr->split_timeout_lo >> 19) * 125;
 
+       csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000);
        HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
 }
 
index 6c72f04..1084da4 100644 (file)
@@ -1536,27 +1536,20 @@ static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count
 
 static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct video_card *video;
+       struct video_card *video = file_to_video_card(file);
        unsigned long flags;
        int ret = -EINVAL;
        void __user *argp = (void __user *)arg;
 
        DECLARE_WAITQUEUE(wait, current);
 
-       lock_kernel();
-       video = file_to_video_card(file);
-
        /* serialize this to prevent multi-threaded mayhem */
        if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx)) {
-                       unlock_kernel();
+               if (!mutex_trylock(&video->mtx))
                        return -EAGAIN;
-               }
        } else {
-               if (mutex_lock_interruptible(&video->mtx)) {
-                       unlock_kernel();
+               if (mutex_lock_interruptible(&video->mtx))
                        return -ERESTARTSYS;
-               }
        }
 
        switch(cmd)
@@ -1780,7 +1773,6 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
  out:
        mutex_unlock(&video->mtx);
-       unlock_kernel();
        return ret;
 }
 
@@ -2188,12 +2180,8 @@ static struct ieee1394_device_id dv1394_id_table[] = {
 MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
 
 static struct hpsb_protocol_driver dv1394_driver = {
-       .name           = "DV/1394 Driver",
+       .name           = "dv1394",
        .id_table       = dv1394_id_table,
-       .driver         = {
-               .name   = "dv1394",
-               .bus    = &ieee1394_bus_type,
-       },
 };
 
 
@@ -2587,6 +2575,10 @@ static int __init dv1394_init_module(void)
 {
        int ret;
 
+       printk(KERN_WARNING
+              "WARNING: The dv1394 driver is unsupported and will be removed "
+              "from Linux soon. Use raw1394 instead.\n");
+
        cdev_init(&dv1394_cdev, &dv1394_fops);
        dv1394_cdev.owner = THIS_MODULE;
        kobject_set_name(&dv1394_cdev.kobj, "dv1394");
index 31e5cc4..97e5c3d 100644 (file)
@@ -133,7 +133,7 @@ struct eth1394_node_info {
 #define ETH1394_DRIVER_NAME "eth1394"
 static const char driver_name[] = ETH1394_DRIVER_NAME;
 
-static kmem_cache_t *packet_task_cache;
+static struct kmem_cache *packet_task_cache;
 
 static struct hpsb_highlevel eth1394_highlevel;
 
@@ -474,12 +474,10 @@ static struct ieee1394_device_id eth1394_id_table[] = {
 MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
 
 static struct hpsb_protocol_driver eth1394_proto_driver = {
-       .name           = "IPv4 over 1394 Driver",
+       .name           = ETH1394_DRIVER_NAME,
        .id_table       = eth1394_id_table,
        .update         = eth1394_update,
        .driver         = {
-               .name           = ETH1394_DRIVER_NAME,
-               .bus            = &ieee1394_bus_type,
                .probe          = eth1394_probe,
                .remove         = eth1394_remove,
        },
index 50f2dd2..4b33011 100644 (file)
@@ -24,7 +24,6 @@ struct hpsb_address_serve {
 /* Only the following structures are of interest to actual highlevel drivers. */
 
 struct hpsb_highlevel {
-       struct module *owner;
        const char *name;
 
        /* Any of the following pointers can legally be NULL, except for
index d90a3a1..ee82a53 100644 (file)
 #include "config_roms.h"
 
 
-static void delayed_reset_bus(void * __reset_info)
+static void delayed_reset_bus(struct work_struct *work)
 {
-       struct hpsb_host *host = (struct hpsb_host*)__reset_info;
+       struct hpsb_host *host =
+               container_of(work, struct hpsb_host, delayed_reset.work);
        int generation = host->csr.generation + 1;
 
        /* The generation field rolls over to 2 rather than 0 per IEEE
@@ -43,9 +44,10 @@ static void delayed_reset_bus(void * __reset_info)
 
        CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
        if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
-               /* CSR image creation failed, reset generation field and do not
-                * issue a bus reset. */
-               CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation);
+               /* CSR image creation failed.
+                * Reset generation field and do not issue a bus reset. */
+               CSR_SET_BUS_INFO_GENERATION(host->csr.rom,
+                                           host->csr.generation);
                return;
        }
 
@@ -53,7 +55,8 @@ static void delayed_reset_bus(void * __reset_info)
 
        host->update_config_rom = 0;
        if (host->driver->set_hw_config_rom)
-               host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
+               host->driver->set_hw_config_rom(host,
+                                               host->csr.rom->bus_info_data);
 
        host->csr.gen_timestamp[host->csr.generation] = jiffies;
        hpsb_reset_bus(host, SHORT_RESET);
@@ -69,7 +72,8 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
        return -1;
 }
 
-static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
+static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command,
+                       unsigned long arg)
 {
        return -1;
 }
@@ -122,15 +126,13 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
        int i;
        int hostnum = 0;
 
-       h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL);
+       h = kzalloc(sizeof(*h) + extra, GFP_KERNEL);
        if (!h)
                return NULL;
 
        h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
-       if (!h->csr.rom) {
-               kfree(h);
-               return NULL;
-       }
+       if (!h->csr.rom)
+               goto fail;
 
        h->hostdata = h + 1;
        h->driver = drv;
@@ -145,21 +147,20 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 
        atomic_set(&h->generation, 0);
 
-       INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
+       INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus);
        
        init_timer(&h->timeout);
        h->timeout.data = (unsigned long) h;
        h->timeout.function = abort_timedouts;
-       h->timeout_interval = HZ / 20; // 50ms by default
+       h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */
 
        h->topology_map = h->csr.topology_map + 3;
        h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
        mutex_lock(&host_num_alloc);
-
        while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
                hostnum++;
-
+       mutex_unlock(&host_num_alloc);
        h->id = hostnum;
 
        memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
@@ -170,13 +171,19 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
        h->class_dev.class = &hpsb_host_class;
        snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
-       device_register(&h->device);
-       class_device_register(&h->class_dev);
+       if (device_register(&h->device))
+               goto fail;
+       if (class_device_register(&h->class_dev)) {
+               device_unregister(&h->device);
+               goto fail;
+       }
        get_device(&h->device);
 
-       mutex_unlock(&host_num_alloc);
-
        return h;
+
+fail:
+       kfree(h);
+       return NULL;
 }
 
 int hpsb_add_host(struct hpsb_host *host)
@@ -228,13 +235,14 @@ int hpsb_update_config_rom_image(struct hpsb_host *host)
        if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
                /* Wait 60 seconds from the last time this generation number was
                 * used. */
-               reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
+               reset_delay =
+                       (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
        else
                /* Wait 1 second in case some other code wants to change the
                 * Config ROM in the near future. */
                reset_delay = HZ;
 
-       PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host);
+       PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus);
        schedule_delayed_work(&host->delayed_reset, reset_delay);
 
        return 0;
index bc6dbfa..d553e38 100644 (file)
@@ -62,7 +62,7 @@ struct hpsb_host {
        struct class_device class_dev;
 
        int update_config_rom;
-       struct work_struct delayed_reset;
+       struct delayed_work delayed_reset;
        unsigned int config_roms;
 
        struct list_head addr_space;
index 5fccf9f..9a48ca2 100644 (file)
@@ -1237,10 +1237,10 @@ EXPORT_SYMBOL(highlevel_remove_host);
 /** nodemgr.c **/
 EXPORT_SYMBOL(hpsb_node_fill_packet);
 EXPORT_SYMBOL(hpsb_node_write);
-EXPORT_SYMBOL(hpsb_register_protocol);
+EXPORT_SYMBOL(__hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
-EXPORT_SYMBOL(ieee1394_bus_type);
 #ifdef CONFIG_IEEE1394_EXPORT_FULL_API
+EXPORT_SYMBOL(ieee1394_bus_type);
 EXPORT_SYMBOL(nodemgr_for_each_host);
 #endif
 
index af4a78a..536ba3f 100644 (file)
@@ -217,7 +217,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
 /* return the index (within a minor number block) of a file */
 static inline unsigned char ieee1394_file_to_instance(struct file *file)
 {
-       return file->f_dentry->d_inode->i_cindex;
+       return file->f_path.dentry->d_inode->i_cindex;
 }
 
 extern int hpsb_disable_irm;
index 8e7b83f..61307ca 100644 (file)
@@ -14,7 +14,9 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/freezer.h>
 #include <asm/atomic.h>
 
 #include "csr.h"
@@ -66,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
 {
        quadlet_t q;
        u8 i, *speed, old_speed, good_speed;
-       int ret;
+       int error;
 
        speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
        old_speed = *speed;
@@ -78,9 +80,9 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
         * just finished its initialization. */
        for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
                *speed = i;
-               ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                               &q, sizeof(quadlet_t));
-               if (ret)
+               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
+                                 &q, sizeof(quadlet_t));
+               if (error)
                        break;
                *buffer = q;
                good_speed = i;
@@ -94,19 +96,19 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
                return 0;
        }
        *speed = old_speed;
-       return ret;
+       return error;
 }
 
 static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
-                            void *buffer, void *__ci)
+                           void *buffer, void *__ci)
 {
        struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
-       int i, ret;
+       int i, error;
 
        for (i = 1; ; i++) {
-               ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                               buffer, length);
-               if (!ret) {
+               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
+                                 buffer, length);
+               if (!error) {
                        ci->speed_unverified = 0;
                        break;
                }
@@ -117,14 +119,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
                /* The ieee1394_core guessed the node's speed capability from
                 * the self ID.  Check whether a lower speed works. */
                if (ci->speed_unverified && length == sizeof(quadlet_t)) {
-                       ret = nodemgr_check_speed(ci, addr, buffer);
-                       if (!ret)
+                       error = nodemgr_check_speed(ci, addr, buffer);
+                       if (!error)
                                break;
                }
                if (msleep_interruptible(334))
                        return -EINTR;
        }
-       return ret;
+       return error;
 }
 
 static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
@@ -259,9 +261,20 @@ static struct device nodemgr_dev_template_ne = {
        .release        = nodemgr_release_ne,
 };
 
+/* This dummy driver prevents the host devices from being scanned. We have no
+ * useful drivers for them yet, and there would be a deadlock possible if the
+ * driver core scans the host device while the host's low-level driver (i.e.
+ * the host's parent device) is being removed. */
+static struct device_driver nodemgr_mid_layer_driver = {
+       .bus            = &ieee1394_bus_type,
+       .name           = "nodemgr",
+       .owner          = THIS_MODULE,
+};
+
 struct device nodemgr_dev_template_host = {
        .bus            = &ieee1394_bus_type,
        .release        = nodemgr_release_host,
+       .driver         = &nodemgr_mid_layer_driver,
 };
 
 
@@ -306,8 +319,8 @@ static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \
        return sprintf(buf, format_string, (type)driver->field);\
 }                                                              \
 static struct driver_attribute driver_attr_drv_##field = {     \
-        .attr = {.name = __stringify(field), .mode = S_IRUGO },        \
-        .show   = fw_drv_show_##field,                         \
+       .attr = {.name = __stringify(field), .mode = S_IRUGO }, \
+       .show   = fw_drv_show_##field,                          \
 };
 
 
@@ -361,7 +374,7 @@ static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
 #endif
        spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
 
-       return sprintf(buf, "0x%016llx\n", tm);
+       return sprintf(buf, "0x%016llx\n", (unsigned long long)tm);
 }
 static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
 #endif /* HPSB_DEBUG_TLABELS */
@@ -373,11 +386,11 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute
        int state = simple_strtoul(buf, NULL, 10);
 
        if (state == 1) {
-               down_write(&dev->bus->subsys.rwsem);
-               device_release_driver(dev);
                ud->ignore_driver = 1;
-               up_write(&dev->bus->subsys.rwsem);
-       } else if (!state)
+               down_write(&ieee1394_bus_type.subsys.rwsem);
+               device_release_driver(dev);
+               up_write(&ieee1394_bus_type.subsys.rwsem);
+       } else if (state == 0)
                ud->ignore_driver = 0;
 
        return count;
@@ -412,11 +425,14 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
 static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
 
 
-static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count)
+static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
+                            size_t count)
 {
+       int error = 0;
+
        if (simple_strtoul(buf, NULL, 10) == 1)
-               bus_rescan_devices(&ieee1394_bus_type);
-       return count;
+               error = bus_rescan_devices(&ieee1394_bus_type);
+       return error ? error : count;
 }
 static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
 {
@@ -432,7 +448,7 @@ static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size
 
        if (state == 1)
                ignore_drivers = 1;
-       else if (!state)
+       else if (state == 0)
                ignore_drivers = 0;
 
        return count;
@@ -525,7 +541,7 @@ static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf)
        int length = 0;
        char *scratch = buf;
 
-        driver = container_of(drv, struct hpsb_protocol_driver, driver);
+       driver = container_of(drv, struct hpsb_protocol_driver, driver);
 
        for (id = driver->id_table; id->match_flags != 0; id++) {
                int need_coma = 0;
@@ -582,7 +598,11 @@ static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
-               driver_create_file(drv, fw_drv_attrs[i]);
+               if (driver_create_file(drv, fw_drv_attrs[i]))
+                       goto fail;
+       return;
+fail:
+       HPSB_ERR("Failed to add sysfs attribute for driver %s", driver->name);
 }
 
 
@@ -602,7 +622,12 @@ static void nodemgr_create_ne_dev_files(struct node_entry *ne)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
-               device_create_file(dev, fw_ne_attrs[i]);
+               if (device_create_file(dev, fw_ne_attrs[i]))
+                       goto fail;
+       return;
+fail:
+       HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
+                (unsigned long long)ne->guid);
 }
 
 
@@ -612,11 +637,16 @@ static void nodemgr_create_host_dev_files(struct hpsb_host *host)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++)
-               device_create_file(dev, fw_host_attrs[i]);
+               if (device_create_file(dev, fw_host_attrs[i]))
+                       goto fail;
+       return;
+fail:
+       HPSB_ERR("Failed to add sysfs attribute for host %d", host->id);
 }
 
 
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid);
+static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
+                                              nodeid_t nodeid);
 
 static void nodemgr_update_host_dev_links(struct hpsb_host *host)
 {
@@ -627,12 +657,18 @@ static void nodemgr_update_host_dev_links(struct hpsb_host *host)
        sysfs_remove_link(&dev->kobj, "busmgr_id");
        sysfs_remove_link(&dev->kobj, "host_id");
 
-       if ((ne = find_entry_by_nodeid(host, host->irm_id)))
-               sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id");
-       if ((ne = find_entry_by_nodeid(host, host->busmgr_id)))
-               sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id");
-       if ((ne = find_entry_by_nodeid(host, host->node_id)))
-               sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id");
+       if ((ne = find_entry_by_nodeid(host, host->irm_id)) &&
+           sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"))
+               goto fail;
+       if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) &&
+           sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"))
+               goto fail;
+       if ((ne = find_entry_by_nodeid(host, host->node_id)) &&
+           sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"))
+               goto fail;
+       return;
+fail:
+       HPSB_ERR("Failed to update sysfs attributes for host %d", host->id);
 }
 
 static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
@@ -641,32 +677,39 @@ static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
-               device_create_file(dev, fw_ud_attrs[i]);
-
+               if (device_create_file(dev, fw_ud_attrs[i]))
+                       goto fail;
        if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
-               device_create_file(dev, &dev_attr_ud_specifier_id);
-
+               if (device_create_file(dev, &dev_attr_ud_specifier_id))
+                       goto fail;
        if (ud->flags & UNIT_DIRECTORY_VERSION)
-               device_create_file(dev, &dev_attr_ud_version);
-
+               if (device_create_file(dev, &dev_attr_ud_version))
+                       goto fail;
        if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
-               device_create_file(dev, &dev_attr_ud_vendor_id);
-               if (ud->vendor_name_kv)
-                       device_create_file(dev, &dev_attr_ud_vendor_name_kv);
+               if (device_create_file(dev, &dev_attr_ud_vendor_id))
+                       goto fail;
+               if (ud->vendor_name_kv &&
+                   device_create_file(dev, &dev_attr_ud_vendor_name_kv))
+                       goto fail;
        }
-
        if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
-               device_create_file(dev, &dev_attr_ud_model_id);
-               if (ud->model_name_kv)
-                       device_create_file(dev, &dev_attr_ud_model_name_kv);
+               if (device_create_file(dev, &dev_attr_ud_model_id))
+                       goto fail;
+               if (ud->model_name_kv &&
+                   device_create_file(dev, &dev_attr_ud_model_name_kv))
+                       goto fail;
        }
+       return;
+fail:
+       HPSB_ERR("Failed to add sysfs attributes for unit %s",
+                ud->device.bus_id);
 }
 
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
 {
-        struct hpsb_protocol_driver *driver;
-        struct unit_directory *ud;
+       struct hpsb_protocol_driver *driver;
+       struct unit_directory *ud;
        struct ieee1394_device_id *id;
 
        /* We only match unit directories */
@@ -674,55 +717,77 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
                return 0;
 
        ud = container_of(dev, struct unit_directory, device);
-       driver = container_of(drv, struct hpsb_protocol_driver, driver);
-
        if (ud->ne->in_limbo || ud->ignore_driver)
                return 0;
 
-        for (id = driver->id_table; id->match_flags != 0; id++) {
-                if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
-                    id->vendor_id != ud->vendor_id)
-                        continue;
+       /* We only match drivers of type hpsb_protocol_driver */
+       if (drv == &nodemgr_mid_layer_driver)
+               return 0;
 
-                if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
-                    id->model_id != ud->model_id)
-                        continue;
+       driver = container_of(drv, struct hpsb_protocol_driver, driver);
+       for (id = driver->id_table; id->match_flags != 0; id++) {
+               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+                   id->vendor_id != ud->vendor_id)
+                       continue;
 
-                if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
-                    id->specifier_id != ud->specifier_id)
-                        continue;
+               if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
+                   id->model_id != ud->model_id)
+                       continue;
 
-                if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
-                    id->version != ud->version)
-                        continue;
+               if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
+                   id->specifier_id != ud->specifier_id)
+                       continue;
+
+               if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
+                   id->version != ud->version)
+                       continue;
 
                return 1;
-        }
+       }
 
        return 0;
 }
 
 
+static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
+
 static void nodemgr_remove_uds(struct node_entry *ne)
 {
-       struct class_device *cdev, *next;
-       struct unit_directory *ud;
-
-       list_for_each_entry_safe(cdev, next, &nodemgr_ud_class.children, node) {
-               ud = container_of(cdev, struct unit_directory, class_dev);
-
-               if (ud->ne != ne)
-                       continue;
-
+       struct class_device *cdev;
+       struct unit_directory *tmp, *ud;
+
+       /* Iteration over nodemgr_ud_class.children has to be protected by
+        * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+        * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
+        * release the semaphore, and then unregister the ud. Since this code
+        * may be called from other contexts besides the knodemgrds, protect the
+        * gap after release of the semaphore by nodemgr_serialize_remove_uds.
+        */
+       mutex_lock(&nodemgr_serialize_remove_uds);
+       for (;;) {
+               ud = NULL;
+               down(&nodemgr_ud_class.sem);
+               list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
+                       tmp = container_of(cdev, struct unit_directory,
+                                          class_dev);
+                       if (tmp->ne == ne) {
+                               ud = tmp;
+                               break;
+                       }
+               }
+               up(&nodemgr_ud_class.sem);
+               if (ud == NULL)
+                       break;
                class_device_unregister(&ud->class_dev);
                device_unregister(&ud->device);
        }
+       mutex_unlock(&nodemgr_serialize_remove_uds);
 }
 
 
 static void nodemgr_remove_ne(struct node_entry *ne)
 {
-       struct device *dev = &ne->device;
+       struct device *dev;
 
        dev = get_device(&ne->device);
        if (!dev)
@@ -747,7 +812,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data)
 
 static void nodemgr_remove_host_dev(struct device *dev)
 {
-       device_for_each_child(dev, NULL, __nodemgr_remove_host_dev);
+       WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev));
        sysfs_remove_link(&dev->kobj, "irm_id");
        sysfs_remove_link(&dev->kobj, "busmgr_id");
        sysfs_remove_link(&dev->kobj, "host_id");
@@ -761,16 +826,16 @@ static void nodemgr_update_bus_options(struct node_entry *ne)
 #endif
        quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]);
 
-       ne->busopt.irmc         = (busoptions >> 31) & 1;
-       ne->busopt.cmc          = (busoptions >> 30) & 1;
-       ne->busopt.isc          = (busoptions >> 29) & 1;
-       ne->busopt.bmc          = (busoptions >> 28) & 1;
-       ne->busopt.pmc          = (busoptions >> 27) & 1;
-       ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
-       ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
+       ne->busopt.irmc         = (busoptions >> 31) & 1;
+       ne->busopt.cmc          = (busoptions >> 30) & 1;
+       ne->busopt.isc          = (busoptions >> 29) & 1;
+       ne->busopt.bmc          = (busoptions >> 28) & 1;
+       ne->busopt.pmc          = (busoptions >> 27) & 1;
+       ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
+       ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
        ne->busopt.max_rom      = (busoptions >> 8) & 0x3;
-       ne->busopt.generation   = (busoptions >> 4) & 0xf;
-       ne->busopt.lnkspd       = busoptions & 0x7;
+       ne->busopt.generation   = (busoptions >> 4) & 0xf;
+       ne->busopt.lnkspd       = busoptions & 0x7;
 
        HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
                     "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d",
@@ -791,7 +856,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
 
        ne = kzalloc(sizeof(*ne), GFP_KERNEL);
        if (!ne)
-               return NULL;
+               goto fail_alloc;
 
        ne->host = host;
        ne->nodeid = nodeid;
@@ -814,12 +879,15 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
        snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
                 (unsigned long long)(ne->guid));
 
-       device_register(&ne->device);
-       class_device_register(&ne->class_dev);
+       if (device_register(&ne->device))
+               goto fail_devreg;
+       if (class_device_register(&ne->class_dev))
+               goto fail_classdevreg;
        get_device(&ne->device);
 
-       if (ne->guid_vendor_oui)
-               device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui);
+       if (ne->guid_vendor_oui &&
+           device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui))
+               goto fail_addoiu;
        nodemgr_create_ne_dev_files(ne);
 
        nodemgr_update_bus_options(ne);
@@ -829,17 +897,28 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
                   NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
 
        return ne;
+
+fail_addoiu:
+       put_device(&ne->device);
+fail_classdevreg:
+       device_unregister(&ne->device);
+fail_devreg:
+       kfree(ne);
+fail_alloc:
+       HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+                NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
+
+       return NULL;
 }
 
 
 static struct node_entry *find_entry_by_guid(u64 guid)
 {
-       struct class *class = &nodemgr_ne_class;
        struct class_device *cdev;
        struct node_entry *ne, *ret_ne = NULL;
 
-       down_read(&class->subsys.rwsem);
-       list_for_each_entry(cdev, &class->children, node) {
+       down(&nodemgr_ne_class.sem);
+       list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
                ne = container_of(cdev, struct node_entry, class_dev);
 
                if (ne->guid == guid) {
@@ -847,20 +926,20 @@ static struct node_entry *find_entry_by_guid(u64 guid)
                        break;
                }
        }
-       up_read(&class->subsys.rwsem);
+       up(&nodemgr_ne_class.sem);
 
-        return ret_ne;
+       return ret_ne;
 }
 
 
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid)
+static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
+                                              nodeid_t nodeid)
 {
-       struct class *class = &nodemgr_ne_class;
        struct class_device *cdev;
        struct node_entry *ne, *ret_ne = NULL;
 
-       down_read(&class->subsys.rwsem);
-       list_for_each_entry(cdev, &class->children, node) {
+       down(&nodemgr_ne_class.sem);
+       list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
                ne = container_of(cdev, struct node_entry, class_dev);
 
                if (ne->host == host && ne->nodeid == nodeid) {
@@ -868,7 +947,7 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t
                        break;
                }
        }
-       up_read(&class->subsys.rwsem);
+       up(&nodemgr_ne_class.sem);
 
        return ret_ne;
 }
@@ -890,13 +969,25 @@ static void nodemgr_register_device(struct node_entry *ne,
        snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
                 ne->device.bus_id, ud->id);
 
-       device_register(&ud->device);
-       class_device_register(&ud->class_dev);
+       if (device_register(&ud->device))
+               goto fail_devreg;
+       if (class_device_register(&ud->class_dev))
+               goto fail_classdevreg;
        get_device(&ud->device);
 
-       if (ud->vendor_oui)
-               device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
+       if (ud->vendor_oui &&
+           device_create_file(&ud->device, &dev_attr_ud_vendor_oui))
+               goto fail_addoui;
        nodemgr_create_ud_dev_files(ud);
+
+       return;
+
+fail_addoui:
+       put_device(&ud->device);
+fail_classdevreg:
+       device_unregister(&ud->device);
+fail_devreg:
+       HPSB_ERR("Failed to create unit %s", ud->device.bus_id);
 }      
 
 
@@ -976,10 +1067,9 @@ static struct unit_directory *nodemgr_process_unit_directory
                        /* Logical Unit Number */
                        if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
                                if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
-                                       ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL);
+                                       ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL);
                                        if (!ud_child)
                                                goto unit_directory_error;
-                                       memcpy(ud_child, ud, sizeof(*ud_child));
                                        nodemgr_register_device(ne, ud_child, &ne->device);
                                        ud_child = NULL;
                                        
@@ -1093,10 +1183,16 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
                last_key_id = kv->key.id;
        }
 
-       if (ne->vendor_oui)
-               device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
-       if (ne->vendor_name_kv)
-               device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv);
+       if (ne->vendor_oui &&
+           device_create_file(&ne->device, &dev_attr_ne_vendor_oui))
+               goto fail;
+       if (ne->vendor_name_kv &&
+           device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv))
+               goto fail;
+       return;
+fail:
+       HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
+                (unsigned long long)ne->guid);
 }
 
 #ifdef CONFIG_HOTPLUG
@@ -1160,16 +1256,20 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
 #endif /* CONFIG_HOTPLUG */
 
 
-int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
+int __hpsb_register_protocol(struct hpsb_protocol_driver *drv,
+                            struct module *owner)
 {
-       int ret;
+       int error;
 
-       /* This will cause a probe for devices */
-       ret = driver_register(&driver->driver);
-       if (!ret)
-               nodemgr_create_drv_files(driver);
+       drv->driver.bus = &ieee1394_bus_type;
+       drv->driver.owner = owner;
+       drv->driver.name = drv->name;
 
-       return ret;
+       /* This will cause a probe for devices */
+       error = driver_register(&drv->driver);
+       if (!error)
+               nodemgr_create_drv_files(drv);
+       return error;
 }
 
 void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
@@ -1297,26 +1397,25 @@ static void nodemgr_node_scan_one(struct host_info *hi,
 
 static void nodemgr_node_scan(struct host_info *hi, int generation)
 {
-        int count;
-        struct hpsb_host *host = hi->host;
-        struct selfid *sid = (struct selfid *)host->topology_map;
-        nodeid_t nodeid = LOCAL_BUS;
+       int count;
+       struct hpsb_host *host = hi->host;
+       struct selfid *sid = (struct selfid *)host->topology_map;
+       nodeid_t nodeid = LOCAL_BUS;
 
-        /* Scan each node on the bus */
-        for (count = host->selfid_count; count; count--, sid++) {
-                if (sid->extended)
-                        continue;
+       /* Scan each node on the bus */
+       for (count = host->selfid_count; count; count--, sid++) {
+               if (sid->extended)
+                       continue;
 
-                if (!sid->link_active) {
-                        nodeid++;
-                        continue;
-                }
-                nodemgr_node_scan_one(hi, nodeid++, generation);
-        }
+               if (!sid->link_active) {
+                       nodeid++;
+                       continue;
+               }
+               nodemgr_node_scan_one(hi, nodeid++, generation);
+       }
 }
 
 
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
 static void nodemgr_suspend_ne(struct node_entry *ne)
 {
        struct class_device *cdev;
@@ -1326,21 +1425,22 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
                   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
 
        ne->in_limbo = 1;
-       device_create_file(&ne->device, &dev_attr_ne_in_limbo);
+       WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
 
-       down_write(&ne->device.bus->subsys.rwsem);
+       down(&nodemgr_ud_class.sem);
        list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
                ud = container_of(cdev, struct unit_directory, class_dev);
-
                if (ud->ne != ne)
                        continue;
 
+               down_write(&ieee1394_bus_type.subsys.rwsem);
                if (ud->device.driver &&
                    (!ud->device.driver->suspend ||
                      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
                        device_release_driver(&ud->device);
+               up_write(&ieee1394_bus_type.subsys.rwsem);
        }
-       up_write(&ne->device.bus->subsys.rwsem);
+       up(&nodemgr_ud_class.sem);
 }
 
 
@@ -1352,45 +1452,47 @@ static void nodemgr_resume_ne(struct node_entry *ne)
        ne->in_limbo = 0;
        device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
-       down_read(&nodemgr_ud_class.subsys.rwsem);
-       down_read(&ne->device.bus->subsys.rwsem);
+       down(&nodemgr_ud_class.sem);
        list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
                ud = container_of(cdev, struct unit_directory, class_dev);
-
                if (ud->ne != ne)
                        continue;
 
+               down_read(&ieee1394_bus_type.subsys.rwsem);
                if (ud->device.driver && ud->device.driver->resume)
                        ud->device.driver->resume(&ud->device);
+               up_read(&ieee1394_bus_type.subsys.rwsem);
        }
-       up_read(&ne->device.bus->subsys.rwsem);
-       up_read(&nodemgr_ud_class.subsys.rwsem);
+       up(&nodemgr_ud_class.sem);
 
        HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
                   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
 }
 
 
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
        struct unit_directory *ud;
        struct hpsb_protocol_driver *pdrv;
        struct class_device *cdev;
 
+       down(&nodemgr_ud_class.sem);
        list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
                ud = container_of(cdev, struct unit_directory, class_dev);
-               if (ud->ne != ne || !ud->device.driver)
+               if (ud->ne != ne)
                        continue;
 
-               pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
-
-               if (pdrv->update && pdrv->update(ud)) {
-                       down_write(&ud->device.bus->subsys.rwsem);
-                       device_release_driver(&ud->device);
-                       up_write(&ud->device.bus->subsys.rwsem);
+               down_write(&ieee1394_bus_type.subsys.rwsem);
+               if (ud->device.driver) {
+                       pdrv = container_of(ud->device.driver,
+                                           struct hpsb_protocol_driver,
+                                           driver);
+                       if (pdrv->update && pdrv->update(ud))
+                               device_release_driver(&ud->device);
                }
+               up_write(&ieee1394_bus_type.subsys.rwsem);
        }
+       up(&nodemgr_ud_class.sem);
 }
 
 
@@ -1404,7 +1506,7 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
 {
        const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
        quadlet_t bc_remote, bc_local;
-       int ret;
+       int error;
 
        if (!ne->host->is_irm || ne->generation != generation ||
            ne->nodeid == ne->host->node_id)
@@ -1413,16 +1515,14 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
        bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
 
        /* Check if the register is implemented and 1394a compliant. */
-       ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
-                       sizeof(bc_remote));
-       if (!ret && bc_remote & cpu_to_be32(0x80000000) &&
+       error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
+                         sizeof(bc_remote));
+       if (!error && bc_remote & cpu_to_be32(0x80000000) &&
            bc_remote != bc_local)
                hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
 }
 
 
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the
- * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */
 static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
 {
        struct device *dev;
@@ -1455,7 +1555,6 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
        struct hpsb_host *host = hi->host;
-       struct class *class = &nodemgr_ne_class;
        struct class_device *cdev;
        struct node_entry *ne;
 
@@ -1468,18 +1567,18 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
         * while probes are time-consuming. (Well, those probes need some
         * improvement...) */
 
-       down_read(&class->subsys.rwsem);
-       list_for_each_entry(cdev, &class->children, node) {
+       down(&nodemgr_ne_class.sem);
+       list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
                ne = container_of(cdev, struct node_entry, class_dev);
                if (!ne->needs_probe)
                        nodemgr_probe_ne(hi, ne, generation);
        }
-       list_for_each_entry(cdev, &class->children, node) {
+       list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
                ne = container_of(cdev, struct node_entry, class_dev);
                if (ne->needs_probe)
                        nodemgr_probe_ne(hi, ne, generation);
        }
-        up_read(&class->subsys.rwsem);
+       up(&nodemgr_ne_class.sem);
 
 
        /* If we had a bus reset while we were scanning the bus, it is
@@ -1497,15 +1596,14 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
         * just removed.  */
 
        if (generation == get_hpsb_generation(host))
-               bus_rescan_devices(&ieee1394_bus_type);
-
-       return;
+               if (bus_rescan_devices(&ieee1394_bus_type))
+                       HPSB_DEBUG("bus_rescan_devices had an error");
 }
 
 static int nodemgr_send_resume_packet(struct hpsb_host *host)
 {
        struct hpsb_packet *packet;
-       int ret = 1;
+       int error = -ENOMEM;
 
        packet = hpsb_make_phypacket(host,
                        EXTPHYPACKET_TYPE_RESUME |
@@ -1513,12 +1611,12 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
        if (packet) {
                packet->no_waiter = 1;
                packet->generation = get_hpsb_generation(host);
-               ret = hpsb_send_packet(packet);
+               error = hpsb_send_packet(packet);
        }
-       if (ret)
+       if (error)
                HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
                          host->id);
-       return ret;
+       return error;
 }
 
 /* Perform a few high-level IRM responsibilities. */
@@ -1691,19 +1789,18 @@ exit:
 
 int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
 {
-       struct class *class = &hpsb_host_class;
        struct class_device *cdev;
        struct hpsb_host *host;
        int error = 0;
 
-       down_read(&class->subsys.rwsem);
-       list_for_each_entry(cdev, &class->children, node) {
+       down(&hpsb_host_class.sem);
+       list_for_each_entry(cdev, &hpsb_host_class.children, node) {
                host = container_of(cdev, struct hpsb_host, class_dev);
 
                if ((error = cb(host, __data)))
                        break;
        }
-       up_read(&class->subsys.rwsem);
+       up(&hpsb_host_class.sem);
 
        return error;
 }
@@ -1725,10 +1822,10 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
 
 void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
 {
-        pkt->host = ne->host;
-        pkt->generation = ne->generation;
+       pkt->host = ne->host;
+       pkt->generation = ne->generation;
        barrier();
-        pkt->node_id = ne->nodeid;
+       pkt->node_id = ne->nodeid;
 }
 
 int hpsb_node_write(struct node_entry *ne, u64 addr,
@@ -1788,26 +1885,25 @@ static struct hpsb_highlevel nodemgr_highlevel = {
 
 int init_ieee1394_nodemgr(void)
 {
-       int ret;
+       int error;
 
-       ret = class_register(&nodemgr_ne_class);
-       if (ret < 0)
-               return ret;
+       error = class_register(&nodemgr_ne_class);
+       if (error)
+               return error;
 
-       ret = class_register(&nodemgr_ud_class);
-       if (ret < 0) {
+       error = class_register(&nodemgr_ud_class);
+       if (error) {
                class_unregister(&nodemgr_ne_class);
-               return ret;
+               return error;
        }
-
+       error = driver_register(&nodemgr_mid_layer_driver);
        hpsb_register_highlevel(&nodemgr_highlevel);
-
        return 0;
 }
 
 void cleanup_ieee1394_nodemgr(void)
 {
-        hpsb_unregister_highlevel(&nodemgr_highlevel);
+       hpsb_unregister_highlevel(&nodemgr_highlevel);
 
        class_unregister(&nodemgr_ud_class);
        class_unregister(&nodemgr_ne_class);
index 0e1e7d9..e25cbad 100644 (file)
@@ -144,7 +144,12 @@ struct hpsb_protocol_driver {
        struct device_driver driver;
 };
 
-int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
+int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *);
+static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
+{
+       return __hpsb_register_protocol(driver, THIS_MODULE);
+}
+
 void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
 
 static inline int hpsb_node_entry_valid(struct node_entry *ne)
index 6e8ea91..628130a 100644 (file)
@@ -468,7 +468,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
 /* Global initialization */
 static void ohci_initialize(struct ti_ohci *ohci)
 {
-       char irq_buf[16];
        quadlet_t buf;
        int num_ports, i;
 
@@ -586,11 +585,10 @@ static void ohci_initialize(struct ti_ohci *ohci)
        reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
 
        buf = reg_read(ohci, OHCI1394_Version);
-       sprintf (irq_buf, "%d", ohci->dev->irq);
-       PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s]  "
+       PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d]  "
              "MMIO=[%llx-%llx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
              ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
-             ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
+             ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
              (unsigned long long)pci_resource_start(ohci->dev, 0),
              (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
              ohci->max_packet_size,
@@ -1225,7 +1223,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
        int ctx;
        int ret = -ENOMEM;
 
-       recv = kmalloc(sizeof(*recv), SLAB_KERNEL);
+       recv = kmalloc(sizeof(*recv), GFP_KERNEL);
        if (!recv)
                return -ENOMEM;
 
@@ -1918,7 +1916,7 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
        int ctx;
        int ret = -ENOMEM;
 
-       xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL);
+       xmit = kmalloc(sizeof(*xmit), GFP_KERNEL);
        if (!xmit)
                return -ENOMEM;
 
@@ -3021,7 +3019,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
                        return -ENOMEM;
                }
 
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i);
+               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
                OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
@@ -3117,7 +3115,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
        OHCI_DMA_ALLOC("dma_rcv prg pool");
 
        for (i = 0; i < d->num_desc; i++) {
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i);
+               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
                OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
@@ -3217,6 +3215,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
        struct ti_ohci *ohci;   /* shortcut to currently handled device */
        resource_size_t ohci_base;
 
+#ifdef CONFIG_PPC_PMAC
+       /* Necessary on some machines if ohci1394 was loaded/ unloaded before */
+       if (machine_is(powermac)) {
+               struct device_node *ofn = pci_device_to_OF_node(dev);
+
+               if (ofn) {
+                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
+                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+               }
+       }
+#endif /* CONFIG_PPC_PMAC */
+
         if (pci_enable_device(dev))
                FAIL(-ENXIO, "Failed to enable OHCI hardware");
         pci_set_master(dev);
@@ -3505,17 +3515,14 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
 #endif
 
 #ifdef CONFIG_PPC_PMAC
-       /* On UniNorth, power down the cable and turn off the chip
-        * clock when the module is removed to save power on
-        * laptops. Turning it back ON is done by the arch code when
-        * pci_enable_device() is called */
-       {
-               struct device_node* of_node;
+       /* On UniNorth, power down the cable and turn off the chip clock
+        * to save power on laptops */
+       if (machine_is(powermac)) {
+               struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
 
-               of_node = pci_device_to_OF_node(ohci->dev);
-               if (of_node) {
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
-                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
+               if (ofn) {
+                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
                }
        }
 #endif /* CONFIG_PPC_PMAC */
@@ -3529,59 +3536,102 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int ohci1394_pci_resume (struct pci_dev *pdev)
-{
-/* PowerMac resume code comes first */
-#ifdef CONFIG_PPC_PMAC
-       if (machine_is(powermac)) {
-               struct device_node *of_node;
-
-               /* Re-enable 1394 */
-               of_node = pci_device_to_OF_node (pdev);
-               if (of_node)
-                       pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
-       }
-#endif /* CONFIG_PPC_PMAC */
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       return pci_enable_device(pdev);
-}
-
-static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
+static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        int err;
+       struct ti_ohci *ohci = pci_get_drvdata(pdev);
 
        printk(KERN_INFO "%s does not fully support suspend and resume yet\n",
               OHCI1394_DRIVER_NAME);
 
+       if (!ohci) {
+               printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
+                      OHCI1394_DRIVER_NAME);
+               return -ENXIO;
+       }
+       DBGMSG("suspend called");
+
+       /* Clear the async DMA contexts and stop using the controller */
+       hpsb_bus_reset(ohci->host);
+
+       /* See ohci1394_pci_remove() for comments on this sequence */
+       reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
+       reg_write(ohci, OHCI1394_BusOptions,
+                 (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
+                 0x00ff0000);
+       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
+       set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
+       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
+       ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+       ohci_soft_reset(ohci);
+
        err = pci_save_state(pdev);
        if (err) {
-               printk(KERN_ERR "%s: pci_save_state failed with %d\n",
-                      OHCI1394_DRIVER_NAME, err);
+               PRINT(KERN_ERR, "pci_save_state failed with %d", err);
                return err;
        }
        err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#ifdef OHCI1394_DEBUG
        if (err)
-               printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n",
-                      OHCI1394_DRIVER_NAME, err);
-#endif /* OHCI1394_DEBUG */
+               DBGMSG("pci_set_power_state failed with %d", err);
 
 /* PowerMac suspend code comes last */
 #ifdef CONFIG_PPC_PMAC
        if (machine_is(powermac)) {
-               struct device_node *of_node;
+               struct device_node *ofn = pci_device_to_OF_node(pdev);
 
-               /* Disable 1394 */
-               of_node = pci_device_to_OF_node (pdev);
-               if (of_node)
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
+               if (ofn)
+                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
        }
 #endif /* CONFIG_PPC_PMAC */
 
        return 0;
 }
+
+static int ohci1394_pci_resume(struct pci_dev *pdev)
+{
+       int err;
+       struct ti_ohci *ohci = pci_get_drvdata(pdev);
+
+       if (!ohci) {
+               printk(KERN_ERR "%s: tried to resume nonexisting host\n",
+                      OHCI1394_DRIVER_NAME);
+               return -ENXIO;
+       }
+       DBGMSG("resume called");
+
+/* PowerMac resume code comes first */
+#ifdef CONFIG_PPC_PMAC
+       if (machine_is(powermac)) {
+               struct device_node *ofn = pci_device_to_OF_node(pdev);
+
+               if (ofn)
+                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+       }
+#endif /* CONFIG_PPC_PMAC */
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       err = pci_enable_device(pdev);
+       if (err) {
+               PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
+               return err;
+       }
+
+       /* See ohci1394_pci_probe() for comments on this sequence */
+       ohci_soft_reset(ohci);
+       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
+       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+       mdelay(50);
+       ohci_initialize(ohci);
+
+       return 0;
+}
 #endif /* CONFIG_PM */
 
 #define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
index 0a7412e..13a6179 100644 (file)
@@ -1428,10 +1428,9 @@ static int __devinit add_card(struct pci_dev *dev,
                struct i2c_algo_bit_data i2c_adapter_data;
 
                error = -ENOMEM;
-               i2c_ad = kmalloc(sizeof(*i2c_ad), SLAB_KERNEL);
+               i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL);
                if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
 
-               memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
                 i2c_adapter_data = bit_data;
                 i2c_ad->algo_data = &i2c_adapter_data;
                 i2c_adapter_data.data = lynx;
index c7731d1..50daabf 100644 (file)
@@ -27,12 +27,12 @@ struct file_info {
 
         struct hpsb_host *host;
 
-        struct list_head req_pending;
-        struct list_head req_complete;
+        struct list_head req_pending;  /* protected by reqlists_lock */
+        struct list_head req_complete; /* protected by reqlists_lock */
         spinlock_t reqlists_lock;
         wait_queue_head_t wait_complete;
 
-        struct list_head addr_list;
+        struct list_head addr_list;    /* protected by host_info_lock */
 
         u8 __user *fcp_buffer;
 
@@ -63,7 +63,7 @@ struct arm_addr {
         u8     client_transactions;
         u64    recvb;
         u16    rec_length;
-        u8     *addr_space_buffer; /* accessed by read/write/lock */
+        u8     *addr_space_buffer; /* accessed by read/write/lock requests */
 };
 
 struct pending_request {
@@ -79,7 +79,7 @@ struct pending_request {
 struct host_info {
         struct list_head list;
         struct hpsb_host *host;
-        struct list_head file_info_list;
+        struct list_head file_info_list;  /* protected by host_info_lock */
 };
 
 #endif  /* IEEE1394_RAW1394_PRIVATE_H */
index 5ec4f5e..ad2108f 100644 (file)
@@ -99,6 +99,21 @@ static struct hpsb_address_ops arm_ops = {
 
 static void queue_complete_cb(struct pending_request *req);
 
+#include <asm/current.h>
+static void print_old_iso_deprecation(void)
+{
+       static pid_t p;
+
+       if (p == current->pid)
+               return;
+       p = current->pid;
+       printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
+              " isochronous request types which will be removed in a next"
+              " kernel release\n", current->comm);
+       printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
+              " newer interface\n");
+}
+
 static struct pending_request *__alloc_pending_request(gfp_t flags)
 {
        struct pending_request *req;
@@ -112,7 +127,7 @@ static struct pending_request *__alloc_pending_request(gfp_t flags)
 
 static inline struct pending_request *alloc_pending_request(void)
 {
-       return __alloc_pending_request(SLAB_KERNEL);
+       return __alloc_pending_request(GFP_KERNEL);
 }
 
 static void free_pending_request(struct pending_request *req)
@@ -259,7 +274,7 @@ static void host_reset(struct hpsb_host *host)
        if (hi != NULL) {
                list_for_each_entry(fi, &hi->file_info_list, list) {
                        if (fi->notification == RAW1394_NOTIFY_ON) {
-                               req = __alloc_pending_request(SLAB_ATOMIC);
+                               req = __alloc_pending_request(GFP_ATOMIC);
 
                                if (req != NULL) {
                                        req->file_info = fi;
@@ -306,13 +321,13 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
                        if (!(fi->listen_channels & (1ULL << channel)))
                                continue;
 
-                       req = __alloc_pending_request(SLAB_ATOMIC);
+                       req = __alloc_pending_request(GFP_ATOMIC);
                        if (!req)
                                break;
 
                        if (!ibs) {
                                ibs = kmalloc(sizeof(*ibs) + length,
-                                             SLAB_ATOMIC);
+                                             GFP_ATOMIC);
                                if (!ibs) {
                                        kfree(req);
                                        break;
@@ -367,13 +382,13 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
                        if (!fi->fcp_buffer)
                                continue;
 
-                       req = __alloc_pending_request(SLAB_ATOMIC);
+                       req = __alloc_pending_request(GFP_ATOMIC);
                        if (!req)
                                break;
 
                        if (!ibs) {
                                ibs = kmalloc(sizeof(*ibs) + length,
-                                             SLAB_ATOMIC);
+                                             GFP_ATOMIC);
                                if (!ibs) {
                                        kfree(req);
                                        break;
@@ -593,7 +608,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
        switch (req->req.type) {
        case RAW1394_REQ_LIST_CARDS:
                spin_lock_irqsave(&host_info_lock, flags);
-               khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC);
+               khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC);
 
                if (khl) {
                        req->req.misc = host_count;
@@ -1045,7 +1060,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
        }
        if (arm_addr->notification_options & ARM_READ) {
                DBGMSG("arm_read -> entering notification-section");
-               req = __alloc_pending_request(SLAB_ATOMIC);
+               req = __alloc_pending_request(GFP_ATOMIC);
                if (!req) {
                        DBGMSG("arm_read -> rcode_conflict_error");
                        spin_unlock_irqrestore(&host_info_lock, irqflags);
@@ -1064,7 +1079,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
                            sizeof(struct arm_response) +
                            sizeof(struct arm_request_response);
                }
-               req->data = kmalloc(size, SLAB_ATOMIC);
+               req->data = kmalloc(size, GFP_ATOMIC);
                if (!(req->data)) {
                        free_pending_request(req);
                        DBGMSG("arm_read -> rcode_conflict_error");
@@ -1198,7 +1213,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
        }
        if (arm_addr->notification_options & ARM_WRITE) {
                DBGMSG("arm_write -> entering notification-section");
-               req = __alloc_pending_request(SLAB_ATOMIC);
+               req = __alloc_pending_request(GFP_ATOMIC);
                if (!req) {
                        DBGMSG("arm_write -> rcode_conflict_error");
                        spin_unlock_irqrestore(&host_info_lock, irqflags);
@@ -1209,7 +1224,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
                    sizeof(struct arm_request) + sizeof(struct arm_response) +
                    (length) * sizeof(byte_t) +
                    sizeof(struct arm_request_response);
-               req->data = kmalloc(size, SLAB_ATOMIC);
+               req->data = kmalloc(size, GFP_ATOMIC);
                if (!(req->data)) {
                        free_pending_request(req);
                        DBGMSG("arm_write -> rcode_conflict_error");
@@ -1400,7 +1415,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
        if (arm_addr->notification_options & ARM_LOCK) {
                byte_t *buf1, *buf2;
                DBGMSG("arm_lock -> entering notification-section");
-               req = __alloc_pending_request(SLAB_ATOMIC);
+               req = __alloc_pending_request(GFP_ATOMIC);
                if (!req) {
                        DBGMSG("arm_lock -> rcode_conflict_error");
                        spin_unlock_irqrestore(&host_info_lock, irqflags);
@@ -1408,7 +1423,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
                                                           The request may be retried */
                }
                size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, SLAB_ATOMIC);
+               req->data = kmalloc(size, GFP_ATOMIC);
                if (!(req->data)) {
                        free_pending_request(req);
                        DBGMSG("arm_lock -> rcode_conflict_error");
@@ -1628,7 +1643,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
        if (arm_addr->notification_options & ARM_LOCK) {
                byte_t *buf1, *buf2;
                DBGMSG("arm_lock64 -> entering notification-section");
-               req = __alloc_pending_request(SLAB_ATOMIC);
+               req = __alloc_pending_request(GFP_ATOMIC);
                if (!req) {
                        spin_unlock_irqrestore(&host_info_lock, irqflags);
                        DBGMSG("arm_lock64 -> rcode_conflict_error");
@@ -1636,7 +1651,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
                                                           The request may be retried */
                }
                size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, SLAB_ATOMIC);
+               req->data = kmalloc(size, GFP_ATOMIC);
                if (!(req->data)) {
                        free_pending_request(req);
                        spin_unlock_irqrestore(&host_info_lock, irqflags);
@@ -1737,7 +1752,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
                return (-EINVAL);
        }
        /* addr-list-entry for fileinfo */
-       addr = kmalloc(sizeof(*addr), SLAB_KERNEL);
+       addr = kmalloc(sizeof(*addr), GFP_KERNEL);
        if (!addr) {
                req->req.length = 0;
                return (-ENOMEM);
@@ -2103,7 +2118,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
        int ret = sizeof(struct raw1394_request);
-       quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
        int status;
 
        if (!data)
@@ -2133,7 +2148,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req)
 static int update_config_rom(struct file_info *fi, struct pending_request *req)
 {
        int ret = sizeof(struct raw1394_request);
-       quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
        if (!data)
                return -ENOMEM;
        if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
@@ -2292,6 +2307,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
                return sizeof(struct raw1394_request);
 
        case RAW1394_REQ_ISO_SEND:
+               print_old_iso_deprecation();
                return handle_iso_send(fi, req, node);
 
        case RAW1394_REQ_ARM_REGISTER:
@@ -2310,6 +2326,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
                return reset_notification(fi, req);
 
        case RAW1394_REQ_ISO_LISTEN:
+               print_old_iso_deprecation();
                handle_iso_listen(fi, req);
                return sizeof(struct raw1394_request);
 
@@ -2443,7 +2460,7 @@ static void queue_rawiso_event(struct file_info *fi)
        /* only one ISO activity event may be in the queue */
        if (!__rawiso_event_in_queue(fi)) {
                struct pending_request *req =
-                   __alloc_pending_request(SLAB_ATOMIC);
+                   __alloc_pending_request(GFP_ATOMIC);
 
                if (req) {
                        req->file_info = fi;
@@ -2779,7 +2796,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
 {
        struct file_info *fi;
 
-       fi = kzalloc(sizeof(*fi), SLAB_KERNEL);
+       fi = kzalloc(sizeof(*fi), GFP_KERNEL);
        if (!fi)
                return -ENOMEM;
 
@@ -2970,12 +2987,8 @@ static struct ieee1394_device_id raw1394_id_table[] = {
 MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
 
 static struct hpsb_protocol_driver raw1394_driver = {
-       .name = "raw1394 Driver",
+       .name = "raw1394",
        .id_table = raw1394_id_table,
-       .driver = {
-                  .name = "raw1394",
-                  .bus = &ieee1394_bus_type,
-                  },
 };
 
 /******************************************************************************/
index 6986ac1..e68b80b 100644 (file)
  * driver. It also registers as a SCSI lower-level driver in order to accept
  * SCSI commands for transport using SBP-2.
  *
- * You may access any attached SBP-2 storage devices as if they were SCSI
- * devices (e.g. mount /dev/sda1,  fdisk, mkfs, etc.).
+ * You may access any attached SBP-2 (usually storage devices) as regular
+ * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc..
  *
- * Current Issues:
+ * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2
+ * specification and for where to purchase the official standard.
  *
- *     - Error Handling: SCSI aborts and bus reset requests are handled somewhat
- *       but the code needs additional debugging.
+ * TODO:
+ *   - look into possible improvements of the SCSI error handlers
+ *   - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size
+ *   - handle Logical_Unit_Number.ordered
+ *   - handle src == 1 in status blocks
+ *   - reimplement the DMA mapping in absence of physical DMA so that
+ *     bus_to_virt is no longer required
+ *   - debug the handling of absent physical DMA
+ *   - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection
+ *     (this is easy but depends on the previous two TODO items)
+ *   - make the parameter serialize_io configurable per device
+ *   - move all requests to fetch agent registers into non-atomic context,
+ *     replace all usages of sbp2util_node_write_no_wait by true transactions
+ * Grep for inline FIXME comments below.
  */
 
 #include <linux/blkdev.h>
@@ -49,7 +62,6 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
  * (probably due to PCI latency/throughput issues with the part). You can
  * bump down the speed if you are running into problems.
  */
-static int max_speed = IEEE1394_SPEED_MAX;
-module_param(max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)");
+static int sbp2_max_speed = IEEE1394_SPEED_MAX;
+module_param_named(max_speed, sbp2_max_speed, int, 0644);
+MODULE_PARM_DESC(max_speed, "Force max speed "
+                "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
 
 /*
  * Set serialize_io to 1 if you'd like only one scsi command sent
  * down to us at a time (debugging). This might be necessary for very
  * badly behaved sbp2 devices.
- *
- * TODO: Make this configurable per device.
  */
-static int serialize_io = 1;
-module_param(serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)");
+static int sbp2_serialize_io = 1;
+module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
+                "(default = 1, faster = 0)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -121,10 +133,10 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default
  * the Oxsemi sbp2 chipsets have no problems supporting very large
  * transfer sizes.
  */
-static int max_sectors = SBP2_MAX_SECTORS;
-module_param(max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
-                __stringify(SBP2_MAX_SECTORS) ")");
+static int sbp2_max_sectors = SBP2_MAX_SECTORS;
+module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
+MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
+                "(default = " __stringify(SBP2_MAX_SECTORS) ")");
 
 /*
  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
@@ -139,9 +151,10 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
  * concurrent logins. Depending on firmware, four or two concurrent logins
  * are possible on OXFW911 and newer Oxsemi bridges.
  */
-static int exclusive_login = 1;
-module_param(exclusive_login, int, 0644);
-MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)");
+static int sbp2_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+                "(default = 1)");
 
 /*
  * If any of the following workarounds is required for your device to work,
@@ -179,123 +192,123 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
        ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
        ", or a combination)");
 
-/*
- * Export information about protocols/devices supported by this driver.
- */
-static struct ieee1394_device_id sbp2_id_table[] = {
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = SBP2_SW_VERSION_ENTRY & 0xffffff},
-       {}
-};
-
-MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
-
-/*
- * Debug levels, configured via kernel config, or enable here.
- */
-
-#define CONFIG_IEEE1394_SBP2_DEBUG 0
-/* #define CONFIG_IEEE1394_SBP2_DEBUG_ORBS */
-/* #define CONFIG_IEEE1394_SBP2_DEBUG_DMA */
-/* #define CONFIG_IEEE1394_SBP2_DEBUG 1 */
-/* #define CONFIG_IEEE1394_SBP2_DEBUG 2 */
-/* #define CONFIG_IEEE1394_SBP2_PACKET_DUMP */
-
-#ifdef CONFIG_IEEE1394_SBP2_DEBUG_ORBS
-#define SBP2_ORB_DEBUG(fmt, args...)   HPSB_ERR("sbp2(%s): "fmt, __FUNCTION__, ## args)
-static u32 global_outstanding_command_orbs = 0;
-#define outstanding_orb_incr global_outstanding_command_orbs++
-#define outstanding_orb_decr global_outstanding_command_orbs--
-#else
-#define SBP2_ORB_DEBUG(fmt, args...)   do {} while (0)
-#define outstanding_orb_incr           do {} while (0)
-#define outstanding_orb_decr           do {} while (0)
-#endif
-
-#ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA
-#define SBP2_DMA_ALLOC(fmt, args...) \
-       HPSB_ERR("sbp2(%s)alloc(%d): "fmt, __FUNCTION__, \
-                ++global_outstanding_dmas, ## args)
-#define SBP2_DMA_FREE(fmt, args...) \
-       HPSB_ERR("sbp2(%s)free(%d): "fmt, __FUNCTION__, \
-                --global_outstanding_dmas, ## args)
-static u32 global_outstanding_dmas = 0;
-#else
-#define SBP2_DMA_ALLOC(fmt, args...)   do {} while (0)
-#define SBP2_DMA_FREE(fmt, args...)    do {} while (0)
-#endif
 
-#if CONFIG_IEEE1394_SBP2_DEBUG >= 2
-#define SBP2_DEBUG(fmt, args...)       HPSB_ERR("sbp2: "fmt, ## args)
-#define SBP2_INFO(fmt, args...)                HPSB_ERR("sbp2: "fmt, ## args)
-#define SBP2_NOTICE(fmt, args...)      HPSB_ERR("sbp2: "fmt, ## args)
-#define SBP2_WARN(fmt, args...)                HPSB_ERR("sbp2: "fmt, ## args)
-#elif CONFIG_IEEE1394_SBP2_DEBUG == 1
-#define SBP2_DEBUG(fmt, args...)       HPSB_DEBUG("sbp2: "fmt, ## args)
-#define SBP2_INFO(fmt, args...)                HPSB_INFO("sbp2: "fmt, ## args)
-#define SBP2_NOTICE(fmt, args...)      HPSB_NOTICE("sbp2: "fmt, ## args)
-#define SBP2_WARN(fmt, args...)                HPSB_WARN("sbp2: "fmt, ## args)
-#else
-#define SBP2_DEBUG(fmt, args...)       do {} while (0)
-#define SBP2_INFO(fmt, args...)                HPSB_INFO("sbp2: "fmt, ## args)
-#define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args)
-#define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args)
-#endif
-
-#define SBP2_ERR(fmt, args...)         HPSB_ERR("sbp2: "fmt, ## args)
-#define SBP2_DEBUG_ENTER()             SBP2_DEBUG("%s", __FUNCTION__)
+#define SBP2_INFO(fmt, args...)        HPSB_INFO("sbp2: "fmt, ## args)
+#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
 
 /*
  * Globals
  */
+static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32);
+static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *,
+                                     void (*)(struct scsi_cmnd *));
+static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *);
+static int sbp2_start_device(struct sbp2_lu *);
+static void sbp2_remove_device(struct sbp2_lu *);
+static int sbp2_login_device(struct sbp2_lu *);
+static int sbp2_reconnect_device(struct sbp2_lu *);
+static int sbp2_logout_device(struct sbp2_lu *);
+static void sbp2_host_reset(struct hpsb_host *);
+static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *,
+                                   u64, size_t, u16);
+static int sbp2_agent_reset(struct sbp2_lu *, int);
+static void sbp2_parse_unit_directory(struct sbp2_lu *,
+                                     struct unit_directory *);
+static int sbp2_set_busy_timeout(struct sbp2_lu *);
+static int sbp2_max_speed_and_size(struct sbp2_lu *);
 
-static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id,
-                                          u32 status);
-
-static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
-                                     u32 scsi_status, struct scsi_cmnd *SCpnt,
-                                     void (*done)(struct scsi_cmnd *));
-
-static struct scsi_host_template scsi_driver_template;
 
 static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
 
-static void sbp2_host_reset(struct hpsb_host *host);
-
-static int sbp2_probe(struct device *dev);
-static int sbp2_remove(struct device *dev);
-static int sbp2_update(struct unit_directory *ud);
-
 static struct hpsb_highlevel sbp2_highlevel = {
-       .name =         SBP2_DEVICE_NAME,
-       .host_reset =   sbp2_host_reset,
+       .name           = SBP2_DEVICE_NAME,
+       .host_reset     = sbp2_host_reset,
 };
 
 static struct hpsb_address_ops sbp2_ops = {
-       .write = sbp2_handle_status_write
+       .write          = sbp2_handle_status_write
 };
 
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *,
+                                    u64, size_t, u16);
+static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64,
+                                   size_t, u16);
+
 static struct hpsb_address_ops sbp2_physdma_ops = {
-       .read = sbp2_handle_physdma_read,
-       .write = sbp2_handle_physdma_write,
+       .read           = sbp2_handle_physdma_read,
+       .write          = sbp2_handle_physdma_write,
 };
 #endif
 
+
+/*
+ * Interface to driver core and IEEE 1394 core
+ */
+static struct ieee1394_device_id sbp2_id_table[] = {
+       {
+        .match_flags   = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+        .specifier_id  = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+        .version       = SBP2_SW_VERSION_ENTRY & 0xffffff},
+       {}
+};
+MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
+
+static int sbp2_probe(struct device *);
+static int sbp2_remove(struct device *);
+static int sbp2_update(struct unit_directory *);
+
 static struct hpsb_protocol_driver sbp2_driver = {
-       .name           = "SBP2 Driver",
+       .name           = SBP2_DEVICE_NAME,
        .id_table       = sbp2_id_table,
        .update         = sbp2_update,
        .driver         = {
-               .name           = SBP2_DEVICE_NAME,
-               .bus            = &ieee1394_bus_type,
                .probe          = sbp2_probe,
                .remove         = sbp2_remove,
        },
 };
 
+
+/*
+ * Interface to SCSI core
+ */
+static int sbp2scsi_queuecommand(struct scsi_cmnd *,
+                                void (*)(struct scsi_cmnd *));
+static int sbp2scsi_abort(struct scsi_cmnd *);
+static int sbp2scsi_reset(struct scsi_cmnd *);
+static int sbp2scsi_slave_alloc(struct scsi_device *);
+static int sbp2scsi_slave_configure(struct scsi_device *);
+static void sbp2scsi_slave_destroy(struct scsi_device *);
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *,
+                                          struct device_attribute *, char *);
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_sysfs_sdev_attrs[] = {
+       &dev_attr_ieee1394_id,
+       NULL
+};
+
+static struct scsi_host_template sbp2_shost_template = {
+       .module                  = THIS_MODULE,
+       .name                    = "SBP-2 IEEE-1394",
+       .proc_name               = SBP2_DEVICE_NAME,
+       .queuecommand            = sbp2scsi_queuecommand,
+       .eh_abort_handler        = sbp2scsi_abort,
+       .eh_device_reset_handler = sbp2scsi_reset,
+       .slave_alloc             = sbp2scsi_slave_alloc,
+       .slave_configure         = sbp2scsi_slave_configure,
+       .slave_destroy           = sbp2scsi_slave_destroy,
+       .this_id                 = -1,
+       .sg_tablesize            = SG_ALL,
+       .use_clustering          = ENABLE_CLUSTERING,
+       .cmd_per_lun             = SBP2_MAX_CMDS,
+       .can_queue               = SBP2_MAX_CMDS,
+       .emulated                = 1,
+       .sdev_attrs              = sbp2_sysfs_sdev_attrs,
+};
+
+
 /*
  * List of devices with known bugs.
  *
@@ -363,8 +376,6 @@ static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
 
        for (length = (length >> 2); length--; )
                temp[length] = be32_to_cpu(temp[length]);
-
-       return;
 }
 
 /*
@@ -376,8 +387,6 @@ static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 
        for (length = (length >> 2); length--; )
                temp[length] = cpu_to_be32(temp[length]);
-
-       return;
 }
 #else /* BIG_ENDIAN */
 /* Why waste the cpu cycles? */
@@ -385,339 +394,246 @@ static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 #define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)
 #endif
 
-#ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP
-/*
- * Debug packet dump routine. Length is in bytes.
- */
-static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
-                                u32 dump_phys_addr)
-{
-       int i;
-       unsigned char *dump = buffer;
-
-       if (!dump || !length || !dump_name)
-               return;
-
-       if (dump_phys_addr)
-               printk("[%s, 0x%x]", dump_name, dump_phys_addr);
-       else
-               printk("[%s]", dump_name);
-       for (i = 0; i < length; i++) {
-               if (i > 0x3f) {
-                       printk("\n   ...");
-                       break;
-               }
-               if ((i & 0x3) == 0)
-                       printk("  ");
-               if ((i & 0xf) == 0)
-                       printk("\n   ");
-               printk("%02x ", (int)dump[i]);
-       }
-       printk("\n");
-
-       return;
-}
-#else
-#define sbp2util_packet_dump(w,x,y,z) do {} while (0)
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(access_wq);
+static DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq);
 
 /*
  * Waits for completion of an SBP-2 access request.
  * Returns nonzero if timed out or prematurely interrupted.
  */
-static int sbp2util_access_timeout(struct scsi_id_instance_data *scsi_id,
-                                  int timeout)
+static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout)
 {
-       long leftover = wait_event_interruptible_timeout(
-                               access_wq, scsi_id->access_complete, timeout);
+       long leftover;
 
-       scsi_id->access_complete = 0;
+       leftover = wait_event_interruptible_timeout(
+                       sbp2_access_wq, lu->access_complete, timeout);
+       lu->access_complete = 0;
        return leftover <= 0;
 }
 
-/* Frees an allocated packet */
-static void sbp2_free_packet(struct hpsb_packet *packet)
+static void sbp2_free_packet(void *packet)
 {
        hpsb_free_tlabel(packet);
        hpsb_free_packet(packet);
 }
 
-/* This is much like hpsb_node_write(), except it ignores the response
- * subaction and returns immediately. Can be used from interrupts.
+/*
+ * This is much like hpsb_node_write(), except it ignores the response
+ * subaction and returns immediately. Can be used from atomic context.
  */
 static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
-                                      quadlet_t *buffer, size_t length)
+                                      quadlet_t *buf, size_t len)
 {
        struct hpsb_packet *packet;
 
-       packet = hpsb_make_writepacket(ne->host, ne->nodeid,
-                                      addr, buffer, length);
+       packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len);
        if (!packet)
                return -ENOMEM;
 
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))sbp2_free_packet,
-                                     packet);
-
+       hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet);
        hpsb_node_fill_packet(ne, packet);
-
        if (hpsb_send_packet(packet) < 0) {
                sbp2_free_packet(packet);
                return -EIO;
        }
-
        return 0;
 }
 
-static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id,
-                                       u64 offset, quadlet_t *data, size_t len)
+static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset,
+                                       quadlet_t *data, size_t len)
 {
-       /*
-        * There is a small window after a bus reset within which the node
-        * entry's generation is current but the reconnect wasn't completed.
-        */
-       if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET))
+       /* There is a small window after a bus reset within which the node
+        * entry's generation is current but the reconnect wasn't completed. */
+       if (unlikely(atomic_read(&lu->state) == SBP2LU_STATE_IN_RESET))
                return;
 
-       if (hpsb_node_write(scsi_id->ne,
-                           scsi_id->sbp2_command_block_agent_addr + offset,
+       if (hpsb_node_write(lu->ne, lu->command_block_agent_addr + offset,
                            data, len))
                SBP2_ERR("sbp2util_notify_fetch_agent failed.");
-       /*
-        * Now accept new SCSI commands, unless a bus reset happended during
-        * hpsb_node_write.
-        */
-       if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET))
-               scsi_unblock_requests(scsi_id->scsi_host);
+
+       /* Now accept new SCSI commands, unless a bus reset happended during
+        * hpsb_node_write. */
+       if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_RESET))
+               scsi_unblock_requests(lu->shost);
 }
 
-static void sbp2util_write_orb_pointer(void *p)
+static void sbp2util_write_orb_pointer(struct work_struct *work)
 {
+       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
        quadlet_t data[2];
 
-       data[0] = ORB_SET_NODE_ID(
-                       ((struct scsi_id_instance_data *)p)->hi->host->node_id);
-       data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma;
+       data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id);
+       data[1] = lu->last_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
-       sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8);
+       sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8);
 }
 
-static void sbp2util_write_doorbell(void *p)
+static void sbp2util_write_doorbell(struct work_struct *work)
 {
-       sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4);
+       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
+
+       sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4);
 }
 
-/*
- * This function is called to create a pool of command orbs used for
- * command processing. It is called when a new sbp2 device is detected.
- */
-static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id)
+static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        int i;
        unsigned long flags, orbs;
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
 
-       orbs = serialize_io ? 2 : SBP2_MAX_CMDS;
+       orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
 
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
        for (i = 0; i < orbs; i++) {
-               command = kzalloc(sizeof(*command), GFP_ATOMIC);
-               if (!command) {
-                       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock,
-                                              flags);
+               cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+               if (!cmd) {
+                       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
                        return -ENOMEM;
                }
-               command->command_orb_dma =
-                   pci_map_single(hi->host->pdev, &command->command_orb,
-                                  sizeof(struct sbp2_command_orb),
-                                  PCI_DMA_TODEVICE);
-               SBP2_DMA_ALLOC("single command orb DMA");
-               command->sge_dma =
-                   pci_map_single(hi->host->pdev,
-                                  &command->scatter_gather_element,
-                                  sizeof(command->scatter_gather_element),
-                                  PCI_DMA_BIDIRECTIONAL);
-               SBP2_DMA_ALLOC("scatter_gather_element");
-               INIT_LIST_HEAD(&command->list);
-               list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-       }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+               cmd->command_orb_dma = dma_map_single(&hi->host->device,
+                                               &cmd->command_orb,
+                                               sizeof(struct sbp2_command_orb),
+                                               DMA_TO_DEVICE);
+               cmd->sge_dma = dma_map_single(&hi->host->device,
+                                       &cmd->scatter_gather_element,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
+               INIT_LIST_HEAD(&cmd->list);
+               list_add_tail(&cmd->list, &lu->cmd_orb_completed);
+       }
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
        return 0;
 }
 
-/*
- * This function is called to delete a pool of command orbs.
- */
-static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id)
+static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
 {
-       struct hpsb_host *host = scsi_id->hi->host;
+       struct hpsb_host *host = lu->hi->host;
        struct list_head *lh, *next;
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
        unsigned long flags;
 
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {
-               list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) {
-                       command = list_entry(lh, struct sbp2_command_info, list);
-
-                       /* Release our generic DMA's */
-                       pci_unmap_single(host->pdev, command->command_orb_dma,
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       if (!list_empty(&lu->cmd_orb_completed))
+               list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
+                       cmd = list_entry(lh, struct sbp2_command_info, list);
+                       dma_unmap_single(&host->device, cmd->command_orb_dma,
                                         sizeof(struct sbp2_command_orb),
-                                        PCI_DMA_TODEVICE);
-                       SBP2_DMA_FREE("single command orb DMA");
-                       pci_unmap_single(host->pdev, command->sge_dma,
-                                        sizeof(command->scatter_gather_element),
-                                        PCI_DMA_BIDIRECTIONAL);
-                       SBP2_DMA_FREE("scatter_gather_element");
-
-                       kfree(command);
+                                        DMA_TO_DEVICE);
+                       dma_unmap_single(&host->device, cmd->sge_dma,
+                                        sizeof(cmd->scatter_gather_element),
+                                        DMA_BIDIRECTIONAL);
+                       kfree(cmd);
                }
-       }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
        return;
 }
 
 /*
- * This function finds the sbp2_command for a given outstanding command
- * orb.Only looks at the inuse list.
+ * Finds the sbp2_command for a given outstanding command ORB.
+ * Only looks at the in-use list.
  */
 static struct sbp2_command_info *sbp2util_find_command_for_orb(
-               struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
+                               struct sbp2_lu *lu, dma_addr_t orb)
 {
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
        unsigned long flags;
 
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-               list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
-                       if (command->command_orb_dma == orb) {
-                               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-                               return command;
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       if (!list_empty(&lu->cmd_orb_inuse))
+               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
+                       if (cmd->command_orb_dma == orb) {
+                               spin_unlock_irqrestore(
+                                               &lu->cmd_orb_lock, flags);
+                               return cmd;
                        }
-               }
-       }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-
-       SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);
-
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
        return NULL;
 }
 
 /*
- * This function finds the sbp2_command for a given outstanding SCpnt.
- * Only looks at the inuse list.
- * Must be called with scsi_id->sbp2_command_orb_lock held.
+ * Finds the sbp2_command for a given outstanding SCpnt.
+ * Only looks at the in-use list.
+ * Must be called with lu->cmd_orb_lock held.
  */
 static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
-               struct scsi_id_instance_data *scsi_id, void *SCpnt)
+                               struct sbp2_lu *lu, void *SCpnt)
 {
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
 
-       if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
-               list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
-                       if (command->Current_SCpnt == SCpnt)
-                               return command;
+       if (!list_empty(&lu->cmd_orb_inuse))
+               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
+                       if (cmd->Current_SCpnt == SCpnt)
+                               return cmd;
        return NULL;
 }
 
-/*
- * This function allocates a command orb used to send a scsi command.
- */
 static struct sbp2_command_info *sbp2util_allocate_command_orb(
-               struct scsi_id_instance_data *scsi_id,
-               struct scsi_cmnd *Current_SCpnt,
-               void (*Current_done)(struct scsi_cmnd *))
+                               struct sbp2_lu *lu,
+                               struct scsi_cmnd *Current_SCpnt,
+                               void (*Current_done)(struct scsi_cmnd *))
 {
        struct list_head *lh;
-       struct sbp2_command_info *command = NULL;
+       struct sbp2_command_info *cmd = NULL;
        unsigned long flags;
 
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {
-               lh = scsi_id->sbp2_command_orb_completed.next;
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       if (!list_empty(&lu->cmd_orb_completed)) {
+               lh = lu->cmd_orb_completed.next;
                list_del(lh);
-               command = list_entry(lh, struct sbp2_command_info, list);
-               command->Current_done = Current_done;
-               command->Current_SCpnt = Current_SCpnt;
-               list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
-       } else {
+               cmd = list_entry(lh, struct sbp2_command_info, list);
+               cmd->Current_done = Current_done;
+               cmd->Current_SCpnt = Current_SCpnt;
+               list_add_tail(&cmd->list, &lu->cmd_orb_inuse);
+       } else
                SBP2_ERR("%s: no orbs available", __FUNCTION__);
-       }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-       return command;
-}
-
-/* Free our DMA's */
-static void sbp2util_free_command_dma(struct sbp2_command_info *command)
-{
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0];
-       struct hpsb_host *host;
-
-       if (!scsi_id) {
-               SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__);
-               return;
-       }
-
-       host = scsi_id->ud->ne->host;
-
-       if (command->cmd_dma) {
-               if (command->dma_type == CMD_DMA_SINGLE) {
-                       pci_unmap_single(host->pdev, command->cmd_dma,
-                                        command->dma_size, command->dma_dir);
-                       SBP2_DMA_FREE("single bulk");
-               } else if (command->dma_type == CMD_DMA_PAGE) {
-                       pci_unmap_page(host->pdev, command->cmd_dma,
-                                      command->dma_size, command->dma_dir);
-                       SBP2_DMA_FREE("single page");
-               } /* XXX: Check for CMD_DMA_NONE bug */
-               command->dma_type = CMD_DMA_NONE;
-               command->cmd_dma = 0;
-       }
-
-       if (command->sge_buffer) {
-               pci_unmap_sg(host->pdev, command->sge_buffer,
-                            command->dma_size, command->dma_dir);
-               SBP2_DMA_FREE("scatter list");
-               command->sge_buffer = NULL;
-       }
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
+       return cmd;
 }
 
 /*
- * This function moves a command to the completed orb list.
- * Must be called with scsi_id->sbp2_command_orb_lock held.
+ * Unmaps the DMAs of a command and moves the command to the completed ORB list.
+ * Must be called with lu->cmd_orb_lock held.
  */
-static void sbp2util_mark_command_completed(
-               struct scsi_id_instance_data *scsi_id,
-               struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
+                                           struct sbp2_command_info *cmd)
 {
-       list_del(&command->list);
-       sbp2util_free_command_dma(command);
-       list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
+       struct hpsb_host *host = lu->ud->ne->host;
+
+       if (cmd->cmd_dma) {
+               if (cmd->dma_type == CMD_DMA_SINGLE)
+                       dma_unmap_single(&host->device, cmd->cmd_dma,
+                                        cmd->dma_size, cmd->dma_dir);
+               else if (cmd->dma_type == CMD_DMA_PAGE)
+                       dma_unmap_page(&host->device, cmd->cmd_dma,
+                                      cmd->dma_size, cmd->dma_dir);
+               /* XXX: Check for CMD_DMA_NONE bug */
+               cmd->dma_type = CMD_DMA_NONE;
+               cmd->cmd_dma = 0;
+       }
+       if (cmd->sge_buffer) {
+               dma_unmap_sg(&host->device, cmd->sge_buffer,
+                            cmd->dma_size, cmd->dma_dir);
+               cmd->sge_buffer = NULL;
+       }
+       list_move_tail(&cmd->list, &lu->cmd_orb_completed);
 }
 
 /*
- * Is scsi_id valid? Is the 1394 node still present?
+ * Is lu valid? Is the 1394 node still present?
  */
-static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id)
+static inline int sbp2util_node_is_available(struct sbp2_lu *lu)
 {
-       return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
+       return lu && lu->ne && !lu->ne->in_limbo;
 }
 
 /*********************************************
  * IEEE-1394 core driver stack related section
  *********************************************/
-static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud);
 
 static int sbp2_probe(struct device *dev)
 {
        struct unit_directory *ud;
-       struct scsi_id_instance_data *scsi_id;
-
-       SBP2_DEBUG_ENTER();
+       struct sbp2_lu *lu;
 
        ud = container_of(dev, struct unit_directory, device);
 
@@ -726,67 +642,58 @@ static int sbp2_probe(struct device *dev)
        if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
                return -ENODEV;
 
-       scsi_id = sbp2_alloc_device(ud);
-
-       if (!scsi_id)
+       lu = sbp2_alloc_device(ud);
+       if (!lu)
                return -ENOMEM;
 
-       sbp2_parse_unit_directory(scsi_id, ud);
-
-       return sbp2_start_device(scsi_id);
+       sbp2_parse_unit_directory(lu, ud);
+       return sbp2_start_device(lu);
 }
 
 static int sbp2_remove(struct device *dev)
 {
        struct unit_directory *ud;
-       struct scsi_id_instance_data *scsi_id;
+       struct sbp2_lu *lu;
        struct scsi_device *sdev;
 
-       SBP2_DEBUG_ENTER();
-
        ud = container_of(dev, struct unit_directory, device);
-       scsi_id = ud->device.driver_data;
-       if (!scsi_id)
+       lu = ud->device.driver_data;
+       if (!lu)
                return 0;
 
-       if (scsi_id->scsi_host) {
+       if (lu->shost) {
                /* Get rid of enqueued commands if there is no chance to
                 * send them. */
-               if (!sbp2util_node_is_available(scsi_id))
-                       sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
-               /* scsi_remove_device() will trigger shutdown functions of SCSI
+               if (!sbp2util_node_is_available(lu))
+                       sbp2scsi_complete_all_commands(lu, DID_NO_CONNECT);
+               /* scsi_remove_device() may trigger shutdown functions of SCSI
                 * highlevel drivers which would deadlock if blocked. */
-               atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN);
-               scsi_unblock_requests(scsi_id->scsi_host);
+               atomic_set(&lu->state, SBP2LU_STATE_IN_SHUTDOWN);
+               scsi_unblock_requests(lu->shost);
        }
-       sdev = scsi_id->sdev;
+       sdev = lu->sdev;
        if (sdev) {
-               scsi_id->sdev = NULL;
+               lu->sdev = NULL;
                scsi_remove_device(sdev);
        }
 
-       sbp2_logout_device(scsi_id);
-       sbp2_remove_device(scsi_id);
+       sbp2_logout_device(lu);
+       sbp2_remove_device(lu);
 
        return 0;
 }
 
 static int sbp2_update(struct unit_directory *ud)
 {
-       struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
-
-       SBP2_DEBUG_ENTER();
+       struct sbp2_lu *lu = ud->device.driver_data;
 
-       if (sbp2_reconnect_device(scsi_id)) {
+       if (sbp2_reconnect_device(lu)) {
+               /* Reconnect has failed. Perhaps we didn't reconnect fast
+                * enough. Try a regular login, but first log out just in
+                * case of any weirdness. */
+               sbp2_logout_device(lu);
 
-               /*
-                * Ok, reconnect has failed. Perhaps we didn't
-                * reconnect fast enough. Try doing a regular login, but
-                * first do a logout just in case of any weirdness.
-                */
-               sbp2_logout_device(scsi_id);
-
-               if (sbp2_login_device(scsi_id)) {
+               if (sbp2_login_device(lu)) {
                        /* Login failed too, just fail, and the backend
                         * will call our sbp2_remove for us */
                        SBP2_ERR("Failed to reconnect to sbp2 device!");
@@ -794,69 +701,59 @@ static int sbp2_update(struct unit_directory *ud)
                }
        }
 
-       /* Set max retries to something large on the device. */
-       sbp2_set_busy_timeout(scsi_id);
+       sbp2_set_busy_timeout(lu);
+       sbp2_agent_reset(lu, 1);
+       sbp2_max_speed_and_size(lu);
 
-       /* Do a SBP-2 fetch agent reset. */
-       sbp2_agent_reset(scsi_id, 1);
-
-       /* Get the max speed and packet size that we can use. */
-       sbp2_max_speed_and_size(scsi_id);
-
-       /* Complete any pending commands with busy (so they get
-        * retried) and remove them from our queue
-        */
-       sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
+       /* Complete any pending commands with busy (so they get retried)
+        * and remove them from our queue. */
+       sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
 
        /* Accept new commands unless there was another bus reset in the
         * meantime. */
-       if (hpsb_node_entry_valid(scsi_id->ne)) {
-               atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
-               scsi_unblock_requests(scsi_id->scsi_host);
+       if (hpsb_node_entry_valid(lu->ne)) {
+               atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
+               scsi_unblock_requests(lu->shost);
        }
        return 0;
 }
 
-/* This functions is called by the sbp2_probe, for each new device. We now
- * allocate one scsi host for each scsi_id (unit directory). */
-static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud)
+static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
 {
-       struct sbp2scsi_host_info *hi;
-       struct Scsi_Host *scsi_host = NULL;
-       struct scsi_id_instance_data *scsi_id = NULL;
+       struct sbp2_fwhost_info *hi;
+       struct Scsi_Host *shost = NULL;
+       struct sbp2_lu *lu = NULL;
 
-       SBP2_DEBUG_ENTER();
-
-       scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
-       if (!scsi_id) {
-               SBP2_ERR("failed to create scsi_id");
+       lu = kzalloc(sizeof(*lu), GFP_KERNEL);
+       if (!lu) {
+               SBP2_ERR("failed to create lu");
                goto failed_alloc;
        }
 
-       scsi_id->ne = ud->ne;
-       scsi_id->ud = ud;
-       scsi_id->speed_code = IEEE1394_SPEED_100;
-       scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
-       scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
-       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
-       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
-       INIT_LIST_HEAD(&scsi_id->scsi_list);
-       spin_lock_init(&scsi_id->sbp2_command_orb_lock);
-       atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
-       INIT_WORK(&scsi_id->protocol_work, NULL, NULL);
+       lu->ne = ud->ne;
+       lu->ud = ud;
+       lu->speed_code = IEEE1394_SPEED_100;
+       lu->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
+       lu->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
+       INIT_LIST_HEAD(&lu->cmd_orb_inuse);
+       INIT_LIST_HEAD(&lu->cmd_orb_completed);
+       INIT_LIST_HEAD(&lu->lu_list);
+       spin_lock_init(&lu->cmd_orb_lock);
+       atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
+       INIT_WORK(&lu->protocol_work, NULL);
 
-       ud->device.driver_data = scsi_id;
+       ud->device.driver_data = lu;
 
        hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
        if (!hi) {
-               hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi));
+               hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host,
+                                         sizeof(*hi));
                if (!hi) {
                        SBP2_ERR("failed to allocate hostinfo");
                        goto failed_alloc;
                }
-               SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo");
                hi->host = ud->ne->host;
-               INIT_LIST_HEAD(&hi->scsi_ids);
+               INIT_LIST_HEAD(&hi->logical_units);
 
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
                /* Handle data movement if physical dma is not
@@ -876,9 +773,9 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
                goto failed_alloc;
        }
 
-       scsi_id->hi = hi;
+       lu->hi = hi;
 
-       list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
+       list_add_tail(&lu->lu_list, &hi->logical_units);
 
        /* Register the status FIFO address range. We could use the same FIFO
         * for targets at different nodes. However we need different FIFOs per
@@ -888,302 +785,214 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
         * then be performed as unified transactions. This slightly reduces
         * bandwidth usage, and some Prolific based devices seem to require it.
         */
-       scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
+       lu->status_fifo_addr = hpsb_allocate_and_register_addrspace(
                        &sbp2_highlevel, ud->ne->host, &sbp2_ops,
                        sizeof(struct sbp2_status_block), sizeof(quadlet_t),
                        ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
-       if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
+       if (lu->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
                SBP2_ERR("failed to allocate status FIFO address range");
                goto failed_alloc;
        }
 
-       /* Register our host with the SCSI stack. */
-       scsi_host = scsi_host_alloc(&scsi_driver_template,
-                                   sizeof(unsigned long));
-       if (!scsi_host) {
+       shost = scsi_host_alloc(&sbp2_shost_template, sizeof(unsigned long));
+       if (!shost) {
                SBP2_ERR("failed to register scsi host");
                goto failed_alloc;
        }
 
-       scsi_host->hostdata[0] = (unsigned long)scsi_id;
+       shost->hostdata[0] = (unsigned long)lu;
 
-       if (!scsi_add_host(scsi_host, &ud->device)) {
-               scsi_id->scsi_host = scsi_host;
-               return scsi_id;
+       if (!scsi_add_host(shost, &ud->device)) {
+               lu->shost = shost;
+               return lu;
        }
 
        SBP2_ERR("failed to add scsi host");
-       scsi_host_put(scsi_host);
+       scsi_host_put(shost);
 
 failed_alloc:
-       sbp2_remove_device(scsi_id);
+       sbp2_remove_device(lu);
        return NULL;
 }
 
 static void sbp2_host_reset(struct hpsb_host *host)
 {
-       struct sbp2scsi_host_info *hi;
-       struct scsi_id_instance_data *scsi_id;
+       struct sbp2_fwhost_info *hi;
+       struct sbp2_lu *lu;
 
        hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
        if (!hi)
                return;
-       list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
-               if (likely(atomic_read(&scsi_id->state) !=
+       list_for_each_entry(lu, &hi->logical_units, lu_list)
+               if (likely(atomic_read(&lu->state) !=
                           SBP2LU_STATE_IN_SHUTDOWN)) {
-                       atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET);
-                       scsi_block_requests(scsi_id->scsi_host);
+                       atomic_set(&lu->state, SBP2LU_STATE_IN_RESET);
+                       scsi_block_requests(lu->shost);
                }
 }
 
-/*
- * This function is where we first pull the node unique ids, and then
- * allocate memory and register a SBP-2 device.
- */
-static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
+static int sbp2_start_device(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        int error;
 
-       SBP2_DEBUG_ENTER();
-
-       /* Login FIFO DMA */
-       scsi_id->login_response =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->login_response = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_login_response),
-                                    &scsi_id->login_response_dma);
-       if (!scsi_id->login_response)
+                                    &lu->login_response_dma, GFP_KERNEL);
+       if (!lu->login_response)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for login FIFO");
 
-       /* Query logins ORB DMA */
-       scsi_id->query_logins_orb =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->query_logins_orb = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_query_logins_orb),
-                                    &scsi_id->query_logins_orb_dma);
-       if (!scsi_id->query_logins_orb)
+                                    &lu->query_logins_orb_dma, GFP_KERNEL);
+       if (!lu->query_logins_orb)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for query logins ORB");
 
-       /* Query logins response DMA */
-       scsi_id->query_logins_response =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->query_logins_response = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_query_logins_response),
-                                    &scsi_id->query_logins_response_dma);
-       if (!scsi_id->query_logins_response)
+                                    &lu->query_logins_response_dma, GFP_KERNEL);
+       if (!lu->query_logins_response)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for query logins response");
 
-       /* Reconnect ORB DMA */
-       scsi_id->reconnect_orb =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->reconnect_orb = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_reconnect_orb),
-                                    &scsi_id->reconnect_orb_dma);
-       if (!scsi_id->reconnect_orb)
+                                    &lu->reconnect_orb_dma, GFP_KERNEL);
+       if (!lu->reconnect_orb)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB");
 
-       /* Logout ORB DMA */
-       scsi_id->logout_orb =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->logout_orb = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_logout_orb),
-                                    &scsi_id->logout_orb_dma);
-       if (!scsi_id->logout_orb)
+                                    &lu->logout_orb_dma, GFP_KERNEL);
+       if (!lu->logout_orb)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for logout ORB");
 
-       /* Login ORB DMA */
-       scsi_id->login_orb =
-               pci_alloc_consistent(hi->host->pdev,
+       lu->login_orb = dma_alloc_coherent(&hi->host->device,
                                     sizeof(struct sbp2_login_orb),
-                                    &scsi_id->login_orb_dma);
-       if (!scsi_id->login_orb)
+                                    &lu->login_orb_dma, GFP_KERNEL);
+       if (!lu->login_orb)
                goto alloc_fail;
-       SBP2_DMA_ALLOC("consistent DMA region for login ORB");
-
-       SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
 
-       /*
-        * Create our command orb pool
-        */
-       if (sbp2util_create_command_orb_pool(scsi_id)) {
+       if (sbp2util_create_command_orb_pool(lu)) {
                SBP2_ERR("sbp2util_create_command_orb_pool failed!");
-               sbp2_remove_device(scsi_id);
+               sbp2_remove_device(lu);
                return -ENOMEM;
        }
 
-       /* Schedule a timeout here. The reason is that we may be so close
-        * to a bus reset, that the device is not available for logins.
-        * This can happen when the bus reset is caused by the host
-        * connected to the sbp2 device being removed. That host would
-        * have a certain amount of time to relogin before the sbp2 device
-        * allows someone else to login instead. One second makes sense. */
+       /* Wait a second before trying to log in. Previously logged in
+        * initiators need a chance to reconnect. */
        if (msleep_interruptible(1000)) {
-               sbp2_remove_device(scsi_id);
+               sbp2_remove_device(lu);
                return -EINTR;
        }
 
-       /*
-        * Login to the sbp-2 device
-        */
-       if (sbp2_login_device(scsi_id)) {
-               /* Login failed, just remove the device. */
-               sbp2_remove_device(scsi_id);
+       if (sbp2_login_device(lu)) {
+               sbp2_remove_device(lu);
                return -EBUSY;
        }
 
-       /*
-        * Set max retries to something large on the device
-        */
-       sbp2_set_busy_timeout(scsi_id);
-
-       /*
-        * Do a SBP-2 fetch agent reset
-        */
-       sbp2_agent_reset(scsi_id, 1);
+       sbp2_set_busy_timeout(lu);
+       sbp2_agent_reset(lu, 1);
+       sbp2_max_speed_and_size(lu);
 
-       /*
-        * Get the max speed and packet size that we can use
-        */
-       sbp2_max_speed_and_size(scsi_id);
-
-       /* Add this device to the scsi layer now */
-       error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
+       error = scsi_add_device(lu->shost, 0, lu->ud->id, 0);
        if (error) {
                SBP2_ERR("scsi_add_device failed");
-               sbp2_logout_device(scsi_id);
-               sbp2_remove_device(scsi_id);
+               sbp2_logout_device(lu);
+               sbp2_remove_device(lu);
                return error;
        }
 
        return 0;
 
 alloc_fail:
-       SBP2_ERR("Could not allocate memory for scsi_id");
-       sbp2_remove_device(scsi_id);
+       SBP2_ERR("Could not allocate memory for lu");
+       sbp2_remove_device(lu);
        return -ENOMEM;
 }
 
-/*
- * This function removes an sbp2 device from the sbp2scsi_host_info struct.
- */
-static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
+static void sbp2_remove_device(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi;
-
-       SBP2_DEBUG_ENTER();
+       struct sbp2_fwhost_info *hi;
 
-       if (!scsi_id)
+       if (!lu)
                return;
 
-       hi = scsi_id->hi;
+       hi = lu->hi;
 
-       /* This will remove our scsi device aswell */
-       if (scsi_id->scsi_host) {
-               scsi_remove_host(scsi_id->scsi_host);
-               scsi_host_put(scsi_id->scsi_host);
+       if (lu->shost) {
+               scsi_remove_host(lu->shost);
+               scsi_host_put(lu->shost);
        }
        flush_scheduled_work();
-       sbp2util_remove_command_orb_pool(scsi_id);
+       sbp2util_remove_command_orb_pool(lu);
 
-       list_del(&scsi_id->scsi_list);
+       list_del(&lu->lu_list);
 
-       if (scsi_id->login_response) {
-               pci_free_consistent(hi->host->pdev,
+       if (lu->login_response)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_login_response),
-                                   scsi_id->login_response,
-                                   scsi_id->login_response_dma);
-               SBP2_DMA_FREE("single login FIFO");
-       }
-
-       if (scsi_id->login_orb) {
-               pci_free_consistent(hi->host->pdev,
+                                   lu->login_response,
+                                   lu->login_response_dma);
+       if (lu->login_orb)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_login_orb),
-                                   scsi_id->login_orb,
-                                   scsi_id->login_orb_dma);
-               SBP2_DMA_FREE("single login ORB");
-       }
-
-       if (scsi_id->reconnect_orb) {
-               pci_free_consistent(hi->host->pdev,
+                                   lu->login_orb,
+                                   lu->login_orb_dma);
+       if (lu->reconnect_orb)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_reconnect_orb),
-                                   scsi_id->reconnect_orb,
-                                   scsi_id->reconnect_orb_dma);
-               SBP2_DMA_FREE("single reconnect orb");
-       }
-
-       if (scsi_id->logout_orb) {
-               pci_free_consistent(hi->host->pdev,
+                                   lu->reconnect_orb,
+                                   lu->reconnect_orb_dma);
+       if (lu->logout_orb)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_logout_orb),
-                                   scsi_id->logout_orb,
-                                   scsi_id->logout_orb_dma);
-               SBP2_DMA_FREE("single logout orb");
-       }
-
-       if (scsi_id->query_logins_orb) {
-               pci_free_consistent(hi->host->pdev,
+                                   lu->logout_orb,
+                                   lu->logout_orb_dma);
+       if (lu->query_logins_orb)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_query_logins_orb),
-                                   scsi_id->query_logins_orb,
-                                   scsi_id->query_logins_orb_dma);
-               SBP2_DMA_FREE("single query logins orb");
-       }
-
-       if (scsi_id->query_logins_response) {
-               pci_free_consistent(hi->host->pdev,
+                                   lu->query_logins_orb,
+                                   lu->query_logins_orb_dma);
+       if (lu->query_logins_response)
+               dma_free_coherent(&hi->host->device,
                                    sizeof(struct sbp2_query_logins_response),
-                                   scsi_id->query_logins_response,
-                                   scsi_id->query_logins_response_dma);
-               SBP2_DMA_FREE("single query logins data");
-       }
+                                   lu->query_logins_response,
+                                   lu->query_logins_response_dma);
 
-       if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
+       if (lu->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
                hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
-                                         scsi_id->status_fifo_addr);
+                                         lu->status_fifo_addr);
 
-       scsi_id->ud->device.driver_data = NULL;
+       lu->ud->device.driver_data = NULL;
 
        if (hi)
                module_put(hi->host->driver->owner);
 
-       SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
-
-       kfree(scsi_id);
+       kfree(lu);
 }
 
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
 /*
- * This function deals with physical dma write requests (for adapters that do not support
- * physical dma in hardware). Mostly just here for debugging...
+ * Deal with write requests on adapters which do not support physical DMA or
+ * have it switched off.
  */
 static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
                                     int destid, quadlet_t *data, u64 addr,
                                     size_t length, u16 flags)
 {
-
-       /*
-        * Manually put the data in the right place.
-        */
        memcpy(bus_to_virt((u32) addr), data, length);
-       sbp2util_packet_dump(data, length, "sbp2 phys dma write by device",
-                            (u32) addr);
        return RCODE_COMPLETE;
 }
 
 /*
- * This function deals with physical dma read requests (for adapters that do not support
- * physical dma in hardware). Mostly just here for debugging...
+ * Deal with read requests on adapters which do not support physical DMA or
+ * have it switched off.
  */
 static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
                                    quadlet_t *data, u64 addr, size_t length,
                                    u16 flags)
 {
-
-       /*
-        * Grab data from memory and send a read response.
-        */
        memcpy(data, bus_to_virt((u32) addr), length);
-       sbp2util_packet_dump(data, length, "sbp2 phys dma read by device",
-                            (u32) addr);
        return RCODE_COMPLETE;
 }
 #endif
@@ -1192,74 +1001,69 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
  * SBP-2 protocol related section
  **************************************/
 
-/*
- * This function queries the device for the maximum concurrent logins it
- * supports.
- */
-static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
+static int sbp2_query_logins(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        quadlet_t data[2];
        int max_logins;
        int active_logins;
 
-       SBP2_DEBUG_ENTER();
-
-       scsi_id->query_logins_orb->reserved1 = 0x0;
-       scsi_id->query_logins_orb->reserved2 = 0x0;
-
-       scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;
-       scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       lu->query_logins_orb->reserved1 = 0x0;
+       lu->query_logins_orb->reserved2 = 0x0;
 
-       scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
-       scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
-       scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
+       lu->query_logins_orb->query_response_lo = lu->query_logins_response_dma;
+       lu->query_logins_orb->query_response_hi =
+                       ORB_SET_NODE_ID(hi->host->node_id);
+       lu->query_logins_orb->lun_misc =
+                       ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
+       lu->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
+       lu->query_logins_orb->lun_misc |= ORB_SET_LUN(lu->lun);
 
-       scsi_id->query_logins_orb->reserved_resp_length =
-               ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
+       lu->query_logins_orb->reserved_resp_length =
+               ORB_SET_QUERY_LOGINS_RESP_LENGTH(
+                       sizeof(struct sbp2_query_logins_response));
 
-       scsi_id->query_logins_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
-       scsi_id->query_logins_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
+       lu->query_logins_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
+       lu->query_logins_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
 
-       sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
+       sbp2util_cpu_to_be32_buffer(lu->query_logins_orb,
+                                   sizeof(struct sbp2_query_logins_orb));
 
-       sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
-                            "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
-
-       memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
+       memset(lu->query_logins_response, 0,
+              sizeof(struct sbp2_query_logins_response));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = scsi_id->query_logins_orb_dma;
+       data[1] = lu->query_logins_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
+       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
 
-       if (sbp2util_access_timeout(scsi_id, 2*HZ)) {
+       if (sbp2util_access_timeout(lu, 2*HZ)) {
                SBP2_INFO("Error querying logins to SBP-2 device - timed out");
                return -EIO;
        }
 
-       if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
+       if (lu->status_block.ORB_offset_lo != lu->query_logins_orb_dma) {
                SBP2_INFO("Error querying logins to SBP-2 device - timed out");
                return -EIO;
        }
 
-       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
                SBP2_INFO("Error querying logins to SBP-2 device - failed");
                return -EIO;
        }
 
-       sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));
-
-       SBP2_DEBUG("length_max_logins = %x",
-                  (unsigned int)scsi_id->query_logins_response->length_max_logins);
+       sbp2util_cpu_to_be32_buffer(lu->query_logins_response,
+                                   sizeof(struct sbp2_query_logins_response));
 
-       max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
+       max_logins = RESPONSE_GET_MAX_LOGINS(
+                       lu->query_logins_response->length_max_logins);
        SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
 
-       active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
+       active_logins = RESPONSE_GET_ACTIVE_LOGINS(
+                       lu->query_logins_response->length_max_logins);
        SBP2_INFO("Number of active logins: %d", active_logins);
 
        if (active_logins >= max_logins) {
@@ -1269,332 +1073,231 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
        return 0;
 }
 
-/*
- * This function is called in order to login to a particular SBP-2 device,
- * after a bus reset.
- */
-static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
+static int sbp2_login_device(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        quadlet_t data[2];
 
-       SBP2_DEBUG_ENTER();
-
-       if (!scsi_id->login_orb) {
-               SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);
+       if (!lu->login_orb)
                return -EIO;
-       }
 
-       if (!exclusive_login) {
-               if (sbp2_query_logins(scsi_id)) {
-                       SBP2_INFO("Device does not support any more concurrent logins");
-                       return -EIO;
-               }
+       if (!sbp2_exclusive_login && sbp2_query_logins(lu)) {
+               SBP2_INFO("Device does not support any more concurrent logins");
+               return -EIO;
        }
 
-       /* Set-up login ORB, assume no password */
-       scsi_id->login_orb->password_hi = 0;
-       scsi_id->login_orb->password_lo = 0;
+       /* assume no password */
+       lu->login_orb->password_hi = 0;
+       lu->login_orb->password_lo = 0;
 
-       scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
-       scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       lu->login_orb->login_response_lo = lu->login_response_dma;
+       lu->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       lu->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
 
-       scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
-       scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);   /* One second reconnect time */
-       scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login);     /* Exclusive access to device */
-       scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);      /* Notify us of login complete */
-       scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
+       /* one second reconnect time */
+       lu->login_orb->lun_misc |= ORB_SET_RECONNECT(0);
+       lu->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(sbp2_exclusive_login);
+       lu->login_orb->lun_misc |= ORB_SET_NOTIFY(1);
+       lu->login_orb->lun_misc |= ORB_SET_LUN(lu->lun);
 
-       scsi_id->login_orb->passwd_resp_lengths =
+       lu->login_orb->passwd_resp_lengths =
                ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
 
-       scsi_id->login_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
-       scsi_id->login_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
+       lu->login_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
+       lu->login_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
 
-       sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
+       sbp2util_cpu_to_be32_buffer(lu->login_orb,
+                                   sizeof(struct sbp2_login_orb));
 
-       sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb),
-                            "sbp2 login orb", scsi_id->login_orb_dma);
-
-       memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
+       memset(lu->login_response, 0, sizeof(struct sbp2_login_response));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = scsi_id->login_orb_dma;
+       data[1] = lu->login_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
+       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
 
-       /*
-        * Wait for login status (up to 20 seconds)...
-        */
-       if (sbp2util_access_timeout(scsi_id, 20*HZ)) {
+       /* wait up to 20 seconds for login status */
+       if (sbp2util_access_timeout(lu, 20*HZ)) {
                SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Sanity. Make sure status returned matches login orb.
-        */
-       if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
+       /* make sure that the returned status matches the login ORB */
+       if (lu->status_block.ORB_offset_lo != lu->login_orb_dma) {
                SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
-       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
                SBP2_ERR("Error logging into SBP-2 device - failed");
                return -EIO;
        }
 
-       /*
-        * Byte swap the login response, for use when reconnecting or
-        * logging out.
-        */
-       sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response));
-
-       /*
-        * Grab our command block agent address from the login response.
-        */
-       SBP2_DEBUG("command_block_agent_hi = %x",
-                  (unsigned int)scsi_id->login_response->command_block_agent_hi);
-       SBP2_DEBUG("command_block_agent_lo = %x",
-                  (unsigned int)scsi_id->login_response->command_block_agent_lo);
-
-       scsi_id->sbp2_command_block_agent_addr =
-               ((u64)scsi_id->login_response->command_block_agent_hi) << 32;
-       scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);
-       scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
+       sbp2util_cpu_to_be32_buffer(lu->login_response,
+                                   sizeof(struct sbp2_login_response));
+       lu->command_block_agent_addr =
+                       ((u64)lu->login_response->command_block_agent_hi) << 32;
+       lu->command_block_agent_addr |=
+                       ((u64)lu->login_response->command_block_agent_lo);
+       lu->command_block_agent_addr &= 0x0000ffffffffffffULL;
 
        SBP2_INFO("Logged into SBP-2 device");
        return 0;
 }
 
-/*
- * This function is called in order to logout from a particular SBP-2
- * device, usually called during driver unload.
- */
-static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
+static int sbp2_logout_device(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        quadlet_t data[2];
        int error;
 
-       SBP2_DEBUG_ENTER();
-
-       /*
-        * Set-up logout ORB
-        */
-       scsi_id->logout_orb->reserved1 = 0x0;
-       scsi_id->logout_orb->reserved2 = 0x0;
-       scsi_id->logout_orb->reserved3 = 0x0;
-       scsi_id->logout_orb->reserved4 = 0x0;
-
-       scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST);
-       scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
-
-       /* Notify us when complete */
-       scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+       lu->logout_orb->reserved1 = 0x0;
+       lu->logout_orb->reserved2 = 0x0;
+       lu->logout_orb->reserved3 = 0x0;
+       lu->logout_orb->reserved4 = 0x0;
 
-       scsi_id->logout_orb->reserved5 = 0x0;
-       scsi_id->logout_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
-       scsi_id->logout_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
+       lu->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST);
+       lu->logout_orb->login_ID_misc |=
+                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
+       lu->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
-       /*
-        * Byte swap ORB if necessary
-        */
-       sbp2util_cpu_to_be32_buffer(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb));
+       lu->logout_orb->reserved5 = 0x0;
+       lu->logout_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
+       lu->logout_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
 
-       sbp2util_packet_dump(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb),
-                            "sbp2 logout orb", scsi_id->logout_orb_dma);
+       sbp2util_cpu_to_be32_buffer(lu->logout_orb,
+                                   sizeof(struct sbp2_logout_orb));
 
-       /*
-        * Ok, let's write to the target's management agent register
-        */
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = scsi_id->logout_orb_dma;
+       data[1] = lu->logout_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       error = hpsb_node_write(scsi_id->ne,
-                               scsi_id->sbp2_management_agent_addr, data, 8);
+       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
        if (error)
                return error;
 
-       /* Wait for device to logout...1 second. */
-       if (sbp2util_access_timeout(scsi_id, HZ))
+       /* wait up to 1 second for the device to complete logout */
+       if (sbp2util_access_timeout(lu, HZ))
                return -EIO;
 
        SBP2_INFO("Logged out of SBP-2 device");
        return 0;
 }
 
-/*
- * This function is called in order to reconnect to a particular SBP-2
- * device, after a bus reset.
- */
-static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
+static int sbp2_reconnect_device(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        quadlet_t data[2];
        int error;
 
-       SBP2_DEBUG_ENTER();
+       lu->reconnect_orb->reserved1 = 0x0;
+       lu->reconnect_orb->reserved2 = 0x0;
+       lu->reconnect_orb->reserved3 = 0x0;
+       lu->reconnect_orb->reserved4 = 0x0;
 
-       /*
-        * Set-up reconnect ORB
-        */
-       scsi_id->reconnect_orb->reserved1 = 0x0;
-       scsi_id->reconnect_orb->reserved2 = 0x0;
-       scsi_id->reconnect_orb->reserved3 = 0x0;
-       scsi_id->reconnect_orb->reserved4 = 0x0;
-
-       scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST);
-       scsi_id->reconnect_orb->login_ID_misc |=
-               ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
+       lu->reconnect_orb->login_ID_misc =
+                       ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST);
+       lu->reconnect_orb->login_ID_misc |=
+                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
+       lu->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
-       /* Notify us when complete */
-       scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+       lu->reconnect_orb->reserved5 = 0x0;
+       lu->reconnect_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
+       lu->reconnect_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
 
-       scsi_id->reconnect_orb->reserved5 = 0x0;
-       scsi_id->reconnect_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
-       scsi_id->reconnect_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
-
-       /*
-        * Byte swap ORB if necessary
-        */
-       sbp2util_cpu_to_be32_buffer(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb));
-
-       sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb),
-                            "sbp2 reconnect orb", scsi_id->reconnect_orb_dma);
+       sbp2util_cpu_to_be32_buffer(lu->reconnect_orb,
+                                   sizeof(struct sbp2_reconnect_orb));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = scsi_id->reconnect_orb_dma;
+       data[1] = lu->reconnect_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       error = hpsb_node_write(scsi_id->ne,
-                               scsi_id->sbp2_management_agent_addr, data, 8);
+       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
        if (error)
                return error;
 
-       /*
-        * Wait for reconnect status (up to 1 second)...
-        */
-       if (sbp2util_access_timeout(scsi_id, HZ)) {
+       /* wait up to 1 second for reconnect status */
+       if (sbp2util_access_timeout(lu, HZ)) {
                SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Sanity. Make sure status returned matches reconnect orb.
-        */
-       if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
+       /* make sure that the returned status matches the reconnect ORB */
+       if (lu->status_block.ORB_offset_lo != lu->reconnect_orb_dma) {
                SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
-       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
                SBP2_ERR("Error reconnecting to SBP-2 device - failed");
                return -EIO;
        }
 
-       HPSB_DEBUG("Reconnected to SBP-2 device");
+       SBP2_INFO("Reconnected to SBP-2 device");
        return 0;
 }
 
 /*
- * This function is called in order to set the busy timeout (number of
- * retries to attempt) on the sbp2 device.
+ * Set the target node's Single Phase Retry limit. Affects the target's retry
+ * behaviour if our node is too busy to accept requests.
  */
-static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
+static int sbp2_set_busy_timeout(struct sbp2_lu *lu)
 {
        quadlet_t data;
 
-       SBP2_DEBUG_ENTER();
-
        data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-       if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+       if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
                SBP2_ERR("%s error", __FUNCTION__);
        return 0;
 }
 
-/*
- * This function is called to parse sbp2 device's config rom unit
- * directory. Used to determine things like sbp2 management agent offset,
- * and command set used (SCSI or RBC).
- */
-static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
+static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
                                      struct unit_directory *ud)
 {
        struct csr1212_keyval *kv;
        struct csr1212_dentry *dentry;
        u64 management_agent_addr;
-       u32 command_set_spec_id, command_set, unit_characteristics,
-           firmware_revision;
+       u32 unit_characteristics, firmware_revision;
        unsigned workarounds;
        int i;
 
-       SBP2_DEBUG_ENTER();
+       management_agent_addr = 0;
+       unit_characteristics = 0;
+       firmware_revision = 0;
 
-       management_agent_addr = 0x0;
-       command_set_spec_id = 0x0;
-       command_set = 0x0;
-       unit_characteristics = 0x0;
-       firmware_revision = 0x0;
-
-       /* Handle different fields in the unit directory, based on keys */
        csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {
                switch (kv->key.id) {
                case CSR1212_KV_ID_DEPENDENT_INFO:
-                       if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {
-                               /* Save off the management agent address */
+                       if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET)
                                management_agent_addr =
                                    CSR1212_REGISTER_SPACE_BASE +
                                    (kv->value.csr_offset << 2);
 
-                               SBP2_DEBUG("sbp2_management_agent_addr = %x",
-                                          (unsigned int)management_agent_addr);
-                       } else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-                               scsi_id->sbp2_lun =
-                                   ORB_SET_LUN(kv->value.immediate);
-                       }
-                       break;
-
-               case SBP2_COMMAND_SET_SPEC_ID_KEY:
-                       /* Command spec organization */
-                       command_set_spec_id = kv->value.immediate;
-                       SBP2_DEBUG("sbp2_command_set_spec_id = %x",
-                                  (unsigned int)command_set_spec_id);
-                       break;
-
-               case SBP2_COMMAND_SET_KEY:
-                       /* Command set used by sbp2 device */
-                       command_set = kv->value.immediate;
-                       SBP2_DEBUG("sbp2_command_set = %x",
-                                  (unsigned int)command_set);
+                       else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE)
+                               lu->lun = ORB_SET_LUN(kv->value.immediate);
                        break;
 
                case SBP2_UNIT_CHARACTERISTICS_KEY:
-                       /*
-                        * Unit characterisitcs (orb related stuff
-                        * that I'm not yet paying attention to)
-                        */
+                       /* FIXME: This is ignored so far.
+                        * See SBP-2 clause 7.4.8. */
                        unit_characteristics = kv->value.immediate;
-                       SBP2_DEBUG("sbp2_unit_characteristics = %x",
-                                  (unsigned int)unit_characteristics);
                        break;
 
                case SBP2_FIRMWARE_REVISION_KEY:
-                       /* Firmware revision */
                        firmware_revision = kv->value.immediate;
-                       SBP2_DEBUG("sbp2_firmware_revision = %x",
-                                  (unsigned int)firmware_revision);
                        break;
 
                default:
+                       /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY.
+                        * Its "ordered" bit has consequences for command ORB
+                        * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */
                        break;
                }
        }
@@ -1626,28 +1329,24 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        /* We would need one SCSI host template for each target to adjust
         * max_sectors on the fly, therefore warn only. */
        if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
-           (max_sectors * 512) > (128 * 1024))
-               SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
+           (sbp2_max_sectors * 512) > (128 * 1024))
+               SBP2_INFO("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
                          "max transfer size. WARNING: Current max_sectors "
                          "setting is larger than 128KB (%d sectors)",
                          NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
-                         max_sectors);
+                         sbp2_max_sectors);
 
        /* If this is a logical unit directory entry, process the parent
         * to get the values. */
        if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
-               struct unit_directory *parent_ud =
-                       container_of(ud->device.parent, struct unit_directory, device);
-               sbp2_parse_unit_directory(scsi_id, parent_ud);
+               struct unit_directory *parent_ud = container_of(
+                       ud->device.parent, struct unit_directory, device);
+               sbp2_parse_unit_directory(lu, parent_ud);
        } else {
-               scsi_id->sbp2_management_agent_addr = management_agent_addr;
-               scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
-               scsi_id->sbp2_command_set = command_set;
-               scsi_id->sbp2_unit_characteristics = unit_characteristics;
-               scsi_id->sbp2_firmware_revision = firmware_revision;
-               scsi_id->workarounds = workarounds;
+               lu->management_agent_addr = management_agent_addr;
+               lu->workarounds = workarounds;
                if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
-                       scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun);
+                       lu->lun = ORB_SET_LUN(ud->lun);
        }
 }
 
@@ -1662,133 +1361,114 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
  * the speed that it needs to use, and the max_rec the host supports, and
  * it takes care of the rest.
  */
-static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
+static int sbp2_max_speed_and_size(struct sbp2_lu *lu)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        u8 payload;
 
-       SBP2_DEBUG_ENTER();
-
-       scsi_id->speed_code =
-           hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)];
+       lu->speed_code = hi->host->speed[NODEID_TO_NODE(lu->ne->nodeid)];
 
-       /* Bump down our speed if the user requested it */
-       if (scsi_id->speed_code > max_speed) {
-               scsi_id->speed_code = max_speed;
-               SBP2_ERR("Forcing SBP-2 max speed down to %s",
-                        hpsb_speedto_str[scsi_id->speed_code]);
+       if (lu->speed_code > sbp2_max_speed) {
+               lu->speed_code = sbp2_max_speed;
+               SBP2_INFO("Reducing speed to %s",
+                         hpsb_speedto_str[sbp2_max_speed]);
        }
 
        /* Payload size is the lesser of what our speed supports and what
         * our host supports.  */
-       payload = min(sbp2_speedto_max_payload[scsi_id->speed_code],
+       payload = min(sbp2_speedto_max_payload[lu->speed_code],
                      (u8) (hi->host->csr.max_rec - 1));
 
        /* If physical DMA is off, work around limitation in ohci1394:
         * packet size must not exceed PAGE_SIZE */
-       if (scsi_id->ne->host->low_addr_space < (1ULL << 32))
+       if (lu->ne->host->low_addr_space < (1ULL << 32))
                while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
                       payload)
                        payload--;
 
-       HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
-                  NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
-                  hpsb_speedto_str[scsi_id->speed_code],
-                  SBP2_PAYLOAD_TO_BYTES(payload));
+       SBP2_INFO("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
+                 NODE_BUS_ARGS(hi->host, lu->ne->nodeid),
+                 hpsb_speedto_str[lu->speed_code],
+                 SBP2_PAYLOAD_TO_BYTES(payload));
 
-       scsi_id->max_payload_size = payload;
+       lu->max_payload_size = payload;
        return 0;
 }
 
-/*
- * This function is called in order to perform a SBP-2 agent reset.
- */
-static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
+static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
 {
        quadlet_t data;
        u64 addr;
        int retval;
        unsigned long flags;
 
-       SBP2_DEBUG_ENTER();
-
-       cancel_delayed_work(&scsi_id->protocol_work);
+       /* flush lu->protocol_work */
        if (wait)
                flush_scheduled_work();
 
        data = ntohl(SBP2_AGENT_RESET_DATA);
-       addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
+       addr = lu->command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
 
        if (wait)
-               retval = hpsb_node_write(scsi_id->ne, addr, &data, 4);
+               retval = hpsb_node_write(lu->ne, addr, &data, 4);
        else
-               retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4);
+               retval = sbp2util_node_write_no_wait(lu->ne, addr, &data, 4);
 
        if (retval < 0) {
                SBP2_ERR("hpsb_node_write failed.\n");
                return -EIO;
        }
 
-       /*
-        * Need to make sure orb pointer is written on next command
-        */
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       scsi_id->last_orb = NULL;
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+       /* make sure that the ORB_POINTER is written on next command */
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       lu->last_orb = NULL;
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
        return 0;
 }
 
 static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
-                                    struct sbp2scsi_host_info *hi,
-                                    struct sbp2_command_info *command,
+                                    struct sbp2_fwhost_info *hi,
+                                    struct sbp2_command_info *cmd,
                                     unsigned int scsi_use_sg,
                                     struct scatterlist *sgpnt,
                                     u32 orb_direction,
                                     enum dma_data_direction dma_dir)
 {
-       command->dma_dir = dma_dir;
+       cmd->dma_dir = dma_dir;
        orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
        orb->misc |= ORB_SET_DIRECTION(orb_direction);
 
-       /* Special case if only one element (and less than 64KB in size) */
+       /* special case if only one element (and less than 64KB in size) */
        if ((scsi_use_sg == 1) &&
            (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
 
-               SBP2_DEBUG("Only one s/g element");
-               command->dma_size = sgpnt[0].length;
-               command->dma_type = CMD_DMA_PAGE;
-               command->cmd_dma = pci_map_page(hi->host->pdev,
-                                               sgpnt[0].page,
-                                               sgpnt[0].offset,
-                                               command->dma_size,
-                                               command->dma_dir);
-               SBP2_DMA_ALLOC("single page scatter element");
+               cmd->dma_size = sgpnt[0].length;
+               cmd->dma_type = CMD_DMA_PAGE;
+               cmd->cmd_dma = dma_map_page(&hi->host->device,
+                                           sgpnt[0].page, sgpnt[0].offset,
+                                           cmd->dma_size, cmd->dma_dir);
 
-               orb->data_descriptor_lo = command->cmd_dma;
-               orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
+               orb->data_descriptor_lo = cmd->cmd_dma;
+               orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
 
        } else {
                struct sbp2_unrestricted_page_table *sg_element =
-                                       &command->scatter_gather_element[0];
+                                               &cmd->scatter_gather_element[0];
                u32 sg_count, sg_len;
                dma_addr_t sg_addr;
-               int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
+               int i, count = dma_map_sg(&hi->host->device, sgpnt, scsi_use_sg,
                                          dma_dir);
 
-               SBP2_DMA_ALLOC("scatter list");
-
-               command->dma_size = scsi_use_sg;
-               command->sge_buffer = sgpnt;
+               cmd->dma_size = scsi_use_sg;
+               cmd->sge_buffer = sgpnt;
 
                /* use page tables (s/g) */
                orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-               orb->data_descriptor_lo = command->sge_dma;
+               orb->data_descriptor_lo = cmd->sge_dma;
 
-               /*
-                * Loop through and fill out our sbp-2 page tables
-                * (and split up anything too large)
-                */
+               /* loop through and fill out our SBP-2 page tables
+                * (and split up anything too large) */
                for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
                        sg_len = sg_dma_len(sgpnt);
                        sg_addr = sg_dma_address(sgpnt);
@@ -1808,70 +1488,53 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
                        }
                }
 
-               /* Number of page table (s/g) elements */
                orb->misc |= ORB_SET_DATA_SIZE(sg_count);
 
-               sbp2util_packet_dump(sg_element,
-                                    (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-                                    "sbp2 s/g list", command->sge_dma);
-
-               /* Byte swap page tables if necessary */
                sbp2util_cpu_to_be32_buffer(sg_element,
-                                           (sizeof(struct sbp2_unrestricted_page_table)) *
-                                           sg_count);
+                               (sizeof(struct sbp2_unrestricted_page_table)) *
+                               sg_count);
        }
 }
 
 static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
-                                       struct sbp2scsi_host_info *hi,
-                                       struct sbp2_command_info *command,
+                                       struct sbp2_fwhost_info *hi,
+                                       struct sbp2_command_info *cmd,
                                        struct scatterlist *sgpnt,
                                        u32 orb_direction,
                                        unsigned int scsi_request_bufflen,
                                        void *scsi_request_buffer,
                                        enum dma_data_direction dma_dir)
 {
-       command->dma_dir = dma_dir;
-       command->dma_size = scsi_request_bufflen;
-       command->dma_type = CMD_DMA_SINGLE;
-       command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
-                                         command->dma_size, command->dma_dir);
+       cmd->dma_dir = dma_dir;
+       cmd->dma_size = scsi_request_bufflen;
+       cmd->dma_type = CMD_DMA_SINGLE;
+       cmd->cmd_dma = dma_map_single(&hi->host->device, scsi_request_buffer,
+                                     cmd->dma_size, cmd->dma_dir);
        orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
        orb->misc |= ORB_SET_DIRECTION(orb_direction);
 
-       SBP2_DMA_ALLOC("single bulk");
-
-       /*
-        * Handle case where we get a command w/o s/g enabled (but
-        * check for transfers larger than 64K)
-        */
+       /* handle case where we get a command w/o s/g enabled
+        * (but check for transfers larger than 64K) */
        if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
 
-               orb->data_descriptor_lo = command->cmd_dma;
+               orb->data_descriptor_lo = cmd->cmd_dma;
                orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
 
        } else {
+               /* The buffer is too large. Turn this into page tables. */
+
                struct sbp2_unrestricted_page_table *sg_element =
-                       &command->scatter_gather_element[0];
+                                               &cmd->scatter_gather_element[0];
                u32 sg_count, sg_len;
                dma_addr_t sg_addr;
 
-               /*
-                * Need to turn this into page tables, since the
-                * buffer is too large.
-                */
-               orb->data_descriptor_lo = command->sge_dma;
-
-               /* Use page tables (s/g) */
+               orb->data_descriptor_lo = cmd->sge_dma;
                orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
 
-               /*
-                * fill out our sbp-2 page tables (and split up
-                * the large buffer)
-                */
+               /* fill out our SBP-2 page tables; split up the large buffer */
                sg_count = 0;
                sg_len = scsi_request_bufflen;
-               sg_addr = command->cmd_dma;
+               sg_addr = cmd->cmd_dma;
                while (sg_len) {
                        sg_element[sg_count].segment_base_lo = sg_addr;
                        if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
@@ -1887,50 +1550,40 @@ static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
                        sg_count++;
                }
 
-               /* Number of page table (s/g) elements */
                orb->misc |= ORB_SET_DATA_SIZE(sg_count);
 
-               sbp2util_packet_dump(sg_element,
-                                    (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-                                    "sbp2 s/g list", command->sge_dma);
-
-               /* Byte swap page tables if necessary */
                sbp2util_cpu_to_be32_buffer(sg_element,
-                                           (sizeof(struct sbp2_unrestricted_page_table)) *
-                                            sg_count);
+                               (sizeof(struct sbp2_unrestricted_page_table)) *
+                               sg_count);
        }
 }
 
-/*
- * This function is called to create the actual command orb and s/g list
- * out of the scsi command itself.
- */
-static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
-                                   struct sbp2_command_info *command,
+static void sbp2_create_command_orb(struct sbp2_lu *lu,
+                                   struct sbp2_command_info *cmd,
                                    unchar *scsi_cmd,
                                    unsigned int scsi_use_sg,
                                    unsigned int scsi_request_bufflen,
                                    void *scsi_request_buffer,
                                    enum dma_data_direction dma_dir)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
-       struct sbp2_command_orb *command_orb = &command->command_orb;
+       struct sbp2_command_orb *orb = &cmd->command_orb;
        u32 orb_direction;
 
        /*
-        * Set-up our command ORB..
+        * Set-up our command ORB.
         *
         * NOTE: We're doing unrestricted page tables (s/g), as this is
         * best performance (at least with the devices I have). This means
         * that data_size becomes the number of s/g elements, and
         * page_size should be zero (for unrestricted).
         */
-       command_orb->next_ORB_hi = ORB_SET_NULL_PTR(1);
-       command_orb->next_ORB_lo = 0x0;
-       command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size);
-       command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);
-       command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
+       orb->next_ORB_hi = ORB_SET_NULL_PTR(1);
+       orb->next_ORB_lo = 0x0;
+       orb->misc = ORB_SET_MAX_PAYLOAD(lu->max_payload_size);
+       orb->misc |= ORB_SET_SPEED(lu->speed_code);
+       orb->misc |= ORB_SET_NOTIFY(1);
 
        if (dma_dir == DMA_NONE)
                orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
@@ -1939,66 +1592,51 @@ static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
        else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
                orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
        else {
-               SBP2_WARN("Falling back to DMA_NONE");
+               SBP2_INFO("Falling back to DMA_NONE");
                orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
        }
 
-       /* Set-up our pagetable stuff */
+       /* set up our page table stuff */
        if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-               SBP2_DEBUG("No data transfer");
-               command_orb->data_descriptor_hi = 0x0;
-               command_orb->data_descriptor_lo = 0x0;
-               command_orb->misc |= ORB_SET_DIRECTION(1);
-       } else if (scsi_use_sg) {
-               SBP2_DEBUG("Use scatter/gather");
-               sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,
-                                        sgpnt, orb_direction, dma_dir);
-       } else {
-               SBP2_DEBUG("No scatter/gather");
-               sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,
-                                           orb_direction, scsi_request_bufflen,
+               orb->data_descriptor_hi = 0x0;
+               orb->data_descriptor_lo = 0x0;
+               orb->misc |= ORB_SET_DIRECTION(1);
+       } else if (scsi_use_sg)
+               sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
+                                        orb_direction, dma_dir);
+       else
+               sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
+                                           scsi_request_bufflen,
                                            scsi_request_buffer, dma_dir);
-       }
 
-       /* Byte swap command ORB if necessary */
-       sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));
+       sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
-       /* Put our scsi command in the command ORB */
-       memset(command_orb->cdb, 0, 12);
-       memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
+       memset(orb->cdb, 0, 12);
+       memcpy(orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
 }
 
-/*
- * This function is called in order to begin a regular SBP-2 command.
- */
-static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
-                                struct sbp2_command_info *command)
+static void sbp2_link_orb_command(struct sbp2_lu *lu,
+                                 struct sbp2_command_info *cmd)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
-       struct sbp2_command_orb *command_orb = &command->command_orb;
+       struct sbp2_fwhost_info *hi = lu->hi;
        struct sbp2_command_orb *last_orb;
        dma_addr_t last_orb_dma;
-       u64 addr = scsi_id->sbp2_command_block_agent_addr;
+       u64 addr = lu->command_block_agent_addr;
        quadlet_t data[2];
        size_t length;
        unsigned long flags;
 
-       outstanding_orb_incr;
-       SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
-                      command_orb, global_outstanding_command_orbs);
-
-       pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
-                                      sizeof(struct sbp2_command_orb),
-                                      PCI_DMA_TODEVICE);
-       pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma,
-                                      sizeof(command->scatter_gather_element),
-                                      PCI_DMA_BIDIRECTIONAL);
-       /*
-        * Check to see if there are any previous orbs to use
-        */
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       last_orb = scsi_id->last_orb;
-       last_orb_dma = scsi_id->last_orb_dma;
+       dma_sync_single_for_device(&hi->host->device, cmd->command_orb_dma,
+                                  sizeof(struct sbp2_command_orb),
+                                  DMA_TO_DEVICE);
+       dma_sync_single_for_device(&hi->host->device, cmd->sge_dma,
+                                  sizeof(cmd->scatter_gather_element),
+                                  DMA_BIDIRECTIONAL);
+
+       /* check to see if there are any previous orbs to use */
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       last_orb = lu->last_orb;
+       last_orb_dma = lu->last_orb_dma;
        if (!last_orb) {
                /*
                 * last_orb == NULL means: We know that the target's fetch agent
@@ -2006,7 +1644,7 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
                 */
                addr += SBP2_ORB_POINTER_OFFSET;
                data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-               data[1] = command->command_orb_dma;
+               data[1] = cmd->command_orb_dma;
                sbp2util_cpu_to_be32_buffer(data, 8);
                length = 8;
        } else {
@@ -2017,27 +1655,25 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
                 * The target's fetch agent may or may not have read this
                 * previous ORB yet.
                 */
-               pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,
-                                           sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_TODEVICE);
-               last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
+               dma_sync_single_for_cpu(&hi->host->device, last_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+               last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
                wmb();
                /* Tells hardware that this pointer is valid */
                last_orb->next_ORB_hi = 0;
-               pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,
-                                              sizeof(struct sbp2_command_orb),
-                                              PCI_DMA_TODEVICE);
+               dma_sync_single_for_device(&hi->host->device, last_orb_dma,
+                                          sizeof(struct sbp2_command_orb),
+                                          DMA_TO_DEVICE);
                addr += SBP2_DOORBELL_OFFSET;
                data[0] = 0;
                length = 4;
        }
-       scsi_id->last_orb = command_orb;
-       scsi_id->last_orb_dma = command->command_orb_dma;
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+       lu->last_orb = &cmd->command_orb;
+       lu->last_orb_dma = cmd->command_orb_dma;
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
-       SBP2_ORB_DEBUG("write to %s register, command orb %p",
-                       last_orb ? "DOORBELL" : "ORB_POINTER", command_orb);
-       if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) {
+       if (sbp2util_node_write_no_wait(lu->ne, addr, data, length)) {
                /*
                 * sbp2util_node_write_no_wait failed. We certainly ran out
                 * of transaction labels, perhaps just because there were no
@@ -2046,52 +1682,29 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
                 * the workqueue job will sleep to guaranteedly get a tlabel.
                 * We do not accept new commands until the job is over.
                 */
-               scsi_block_requests(scsi_id->scsi_host);
-               PREPARE_WORK(&scsi_id->protocol_work,
+               scsi_block_requests(lu->shost);
+               PREPARE_WORK(&lu->protocol_work,
                             last_orb ? sbp2util_write_doorbell:
-                                       sbp2util_write_orb_pointer,
-                            scsi_id);
-               schedule_work(&scsi_id->protocol_work);
+                                       sbp2util_write_orb_pointer);
+               schedule_work(&lu->protocol_work);
        }
 }
 
-/*
- * This function is called in order to begin a regular SBP-2 command.
- */
-static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
-                            struct scsi_cmnd *SCpnt,
+static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
                             void (*done)(struct scsi_cmnd *))
 {
-       unchar *cmd = (unchar *) SCpnt->cmnd;
+       unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
        unsigned int request_bufflen = SCpnt->request_bufflen;
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
 
-       SBP2_DEBUG_ENTER();
-       SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
-       SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
-
-       /*
-        * Allocate a command orb and s/g structure
-        */
-       command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done);
-       if (!command) {
+       cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
+       if (!cmd)
                return -EIO;
-       }
 
-       /*
-        * Now actually fill in the comamnd orb and sbp2 s/g list
-        */
-       sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,
+       sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
                                request_bufflen, SCpnt->request_buffer,
                                SCpnt->sc_data_direction);
-
-       sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),
-                            "sbp2 command orb", command->command_orb_dma);
-
-       /*
-        * Link up the orb, and ring the doorbell if needed
-        */
-       sbp2_link_orb_command(scsi_id, command);
+       sbp2_link_orb_command(lu, cmd);
 
        return 0;
 }
@@ -2099,13 +1712,10 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 /*
  * Translates SBP-2 status into SCSI sense data for check conditions
  */
-static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
+static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
+                                             unchar *sense_data)
 {
-       SBP2_DEBUG_ENTER();
-
-       /*
-        * Ok, it's pretty ugly...   ;-)
-        */
+       /* OK, it's pretty ugly... ;-) */
        sense_data[0] = 0x70;
        sense_data[1] = 0x0;
        sense_data[2] = sbp2_status[9];
@@ -2123,28 +1733,21 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
        sense_data[14] = sbp2_status[20];
        sense_data[15] = sbp2_status[21];
 
-       return sbp2_status[8] & 0x3f;   /* return scsi status */
+       return sbp2_status[8] & 0x3f;
 }
 
-/*
- * This function deals with status writes from the SBP-2 device
- */
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
                                    int destid, quadlet_t *data, u64 addr,
                                    size_t length, u16 fl)
 {
-       struct sbp2scsi_host_info *hi;
-       struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
+       struct sbp2_fwhost_info *hi;
+       struct sbp2_lu *lu = NULL, *lu_tmp;
        struct scsi_cmnd *SCpnt = NULL;
        struct sbp2_status_block *sb;
        u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
        unsigned long flags;
 
-       SBP2_DEBUG_ENTER();
-
-       sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
-
        if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {
                SBP2_ERR("Wrong size of status block");
                return RCODE_ADDRESS_ERROR;
@@ -2158,131 +1761,97 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
                SBP2_ERR("host info is NULL - this is bad!");
                return RCODE_ADDRESS_ERROR;
        }
-       /*
-        * Find our scsi_id structure by looking at the status fifo address
-        * written to by the sbp2 device.
-        */
-       list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) {
-               if (scsi_id_tmp->ne->nodeid == nodeid &&
-                   scsi_id_tmp->status_fifo_addr == addr) {
-                       scsi_id = scsi_id_tmp;
+
+       /* Find the unit which wrote the status. */
+       list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) {
+               if (lu_tmp->ne->nodeid == nodeid &&
+                   lu_tmp->status_fifo_addr == addr) {
+                       lu = lu_tmp;
                        break;
                }
        }
-       if (unlikely(!scsi_id)) {
-               SBP2_ERR("scsi_id is NULL - device is gone?");
+       if (unlikely(!lu)) {
+               SBP2_ERR("lu is NULL - device is gone?");
                return RCODE_ADDRESS_ERROR;
        }
 
-       /*
-        * Put response into scsi_id status fifo buffer. The first two bytes
+       /* Put response into lu status fifo buffer. The first two bytes
         * come in big endian bit order. Often the target writes only a
         * truncated status block, minimally the first two quadlets. The rest
-        * is implied to be zeros.
-        */
-       sb = &scsi_id->status_block;
+        * is implied to be zeros. */
+       sb = &lu->status_block;
        memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));
        memcpy(sb, data, length);
        sbp2util_be32_to_cpu_buffer(sb, 8);
 
-       /*
-        * Ignore unsolicited status. Handle command ORB status.
-        */
+       /* Ignore unsolicited status. Handle command ORB status. */
        if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))
-               command = NULL;
+               cmd = NULL;
        else
-               command = sbp2util_find_command_for_orb(scsi_id,
-                                                       sb->ORB_offset_lo);
-       if (command) {
-               SBP2_DEBUG("Found status for command ORB");
-               pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
-                                           sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_TODEVICE);
-               pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
-                                           sizeof(command->scatter_gather_element),
-                                           PCI_DMA_BIDIRECTIONAL);
-
-               SBP2_ORB_DEBUG("matched command orb %p", &command->command_orb);
-               outstanding_orb_decr;
-
-               /*
-                * Matched status with command, now grab scsi command pointers
-                * and check status.
-                */
+               cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
+       if (cmd) {
+               dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+               dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
+               /* Grab SCSI command pointers and check status. */
                /*
                 * FIXME: If the src field in the status is 1, the ORB DMA must
                 * not be reused until status for a subsequent ORB is received.
                 */
-               SCpnt = command->Current_SCpnt;
-               spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-               sbp2util_mark_command_completed(scsi_id, command);
-               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+               SCpnt = cmd->Current_SCpnt;
+               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+               sbp2util_mark_command_completed(lu, cmd);
+               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
                if (SCpnt) {
                        u32 h = sb->ORB_offset_hi_misc;
                        u32 r = STATUS_GET_RESP(h);
 
                        if (r != RESP_STATUS_REQUEST_COMPLETE) {
-                               SBP2_WARN("resp 0x%x, sbp_status 0x%x",
+                               SBP2_INFO("resp 0x%x, sbp_status 0x%x",
                                          r, STATUS_GET_SBP_STATUS(h));
                                scsi_status =
                                        r == RESP_STATUS_TRANSPORT_FAILURE ?
                                        SBP2_SCSI_STATUS_BUSY :
                                        SBP2_SCSI_STATUS_COMMAND_TERMINATED;
                        }
-                       /*
-                        * See if the target stored any scsi status information.
-                        */
-                       if (STATUS_GET_LEN(h) > 1) {
-                               SBP2_DEBUG("CHECK CONDITION");
+
+                       if (STATUS_GET_LEN(h) > 1)
                                scsi_status = sbp2_status_to_sense_data(
                                        (unchar *)sb, SCpnt->sense_buffer);
-                       }
-                       /*
-                        * Check to see if the dead bit is set. If so, we'll
-                        * have to initiate a fetch agent reset.
-                        */
-                       if (STATUS_TEST_DEAD(h)) {
-                               SBP2_DEBUG("Dead bit set - "
-                                          "initiating fetch agent reset");
-                                sbp2_agent_reset(scsi_id, 0);
-                       }
-                       SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb);
+
+                       if (STATUS_TEST_DEAD(h))
+                                sbp2_agent_reset(lu, 0);
                }
 
-               /*
-                * Check here to see if there are no commands in-use. If there
+               /* Check here to see if there are no commands in-use. If there
                 * are none, we know that the fetch agent left the active state
                 * _and_ that we did not reactivate it yet. Therefore clear
                 * last_orb so that next time we write directly to the
                 * ORB_POINTER register. That way the fetch agent does not need
-                * to refetch the next_ORB.
-                */
-               spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-               if (list_empty(&scsi_id->sbp2_command_orb_inuse))
-                       scsi_id->last_orb = NULL;
-               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+                * to refetch the next_ORB. */
+               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+               if (list_empty(&lu->cmd_orb_inuse))
+                       lu->last_orb = NULL;
+               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
        } else {
-               /*
-                * It's probably a login/logout/reconnect status.
-                */
-               if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) ||
-                   (sb->ORB_offset_lo == scsi_id->login_orb_dma) ||
-                   (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) ||
-                   (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) {
-                       scsi_id->access_complete = 1;
-                       wake_up_interruptible(&access_wq);
+               /* It's probably status after a management request. */
+               if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) ||
+                   (sb->ORB_offset_lo == lu->login_orb_dma) ||
+                   (sb->ORB_offset_lo == lu->query_logins_orb_dma) ||
+                   (sb->ORB_offset_lo == lu->logout_orb_dma)) {
+                       lu->access_complete = 1;
+                       wake_up_interruptible(&sbp2_access_wq);
                }
        }
 
-       if (SCpnt) {
-               SBP2_DEBUG("Completing SCSI command");
-               sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt,
-                                         command->Current_done);
-               SBP2_ORB_DEBUG("command orb completed");
-       }
-
+       if (SCpnt)
+               sbp2scsi_complete_command(lu, scsi_status, SCpnt,
+                                         cmd->Current_done);
        return RCODE_COMPLETE;
 }
 
@@ -2290,77 +1859,57 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
  * SCSI interface related section
  **************************************/
 
-/*
- * This routine is the main request entry routine for doing I/O. It is
- * called from the scsi stack directly.
- */
 static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
                                 void (*done)(struct scsi_cmnd *))
 {
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
-       struct sbp2scsi_host_info *hi;
+       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
+       struct sbp2_fwhost_info *hi;
        int result = DID_NO_CONNECT << 16;
 
-       SBP2_DEBUG_ENTER();
-#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
-       scsi_print_command(SCpnt);
-#endif
-
-       if (!sbp2util_node_is_available(scsi_id))
+       if (unlikely(!sbp2util_node_is_available(lu)))
                goto done;
 
-       hi = scsi_id->hi;
+       hi = lu->hi;
 
-       if (!hi) {
-               SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
+       if (unlikely(!hi)) {
+               SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!");
                goto done;
        }
 
-       /*
-        * Until we handle multiple luns, just return selection time-out
-        * to any IO directed at non-zero LUNs
-        */
-       if (SCpnt->device->lun)
+       /* Multiple units are currently represented to the SCSI core as separate
+        * targets, not as one target with multiple LUs. Therefore return
+        * selection time-out to any IO directed at non-zero LUNs. */
+       if (unlikely(SCpnt->device->lun))
                goto done;
 
-       /*
-        * Check for request sense command, and handle it here
-        * (autorequest sense)
-        */
+       /* handle the request sense command here (auto-request sense) */
        if (SCpnt->cmnd[0] == REQUEST_SENSE) {
-               SBP2_DEBUG("REQUEST_SENSE");
-               memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
+               memcpy(SCpnt->request_buffer, SCpnt->sense_buffer,
+                      SCpnt->request_bufflen);
                memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-               sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
+               sbp2scsi_complete_command(lu, SBP2_SCSI_STATUS_GOOD, SCpnt,
+                                         done);
                return 0;
        }
 
-       /*
-        * Check to see if we are in the middle of a bus reset.
-        */
-       if (!hpsb_node_entry_valid(scsi_id->ne)) {
+       if (unlikely(!hpsb_node_entry_valid(lu->ne))) {
                SBP2_ERR("Bus reset in progress - rejecting command");
                result = DID_BUS_BUSY << 16;
                goto done;
        }
 
-       /*
-        * Bidirectional commands are not yet implemented,
-        * and unknown transfer direction not handled.
-        */
-       if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) {
+       /* Bidirectional commands are not yet implemented,
+        * and unknown transfer direction not handled. */
+       if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) {
                SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
                result = DID_ERROR << 16;
                goto done;
        }
 
-       /*
-        * Try and send our SCSI command
-        */
-       if (sbp2_send_command(scsi_id, SCpnt, done)) {
+       if (sbp2_send_command(lu, SCpnt, done)) {
                SBP2_ERR("Error sending SCSI command");
-               sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
+               sbp2scsi_complete_command(lu,
+                                         SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
                                          SCpnt, done);
        }
        return 0;
@@ -2371,75 +1920,46 @@ done:
        return 0;
 }
 
-/*
- * This function is called in order to complete all outstanding SBP-2
- * commands (in case of resets, etc.).
- */
-static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id,
-                                          u32 status)
+static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
 {
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
+       struct sbp2_fwhost_info *hi = lu->hi;
        struct list_head *lh;
-       struct sbp2_command_info *command;
+       struct sbp2_command_info *cmd;
        unsigned long flags;
 
-       SBP2_DEBUG_ENTER();
-
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-               SBP2_DEBUG("Found pending command to complete");
-               lh = scsi_id->sbp2_command_orb_inuse.next;
-               command = list_entry(lh, struct sbp2_command_info, list);
-               pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
-                                           sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_TODEVICE);
-               pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
-                                           sizeof(command->scatter_gather_element),
-                                           PCI_DMA_BIDIRECTIONAL);
-               sbp2util_mark_command_completed(scsi_id, command);
-               if (command->Current_SCpnt) {
-                       command->Current_SCpnt->result = status << 16;
-                       command->Current_done(command->Current_SCpnt);
+       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+       while (!list_empty(&lu->cmd_orb_inuse)) {
+               lh = lu->cmd_orb_inuse.next;
+               cmd = list_entry(lh, struct sbp2_command_info, list);
+               dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+               dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
+               sbp2util_mark_command_completed(lu, cmd);
+               if (cmd->Current_SCpnt) {
+                       cmd->Current_SCpnt->result = status << 16;
+                       cmd->Current_done(cmd->Current_SCpnt);
                }
        }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
        return;
 }
 
 /*
- * This function is called in order to complete a regular SBP-2 command.
- *
- * This can be called in interrupt context.
+ * Complete a regular SCSI command. Can be called in atomic context.
  */
-static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
-                                     u32 scsi_status, struct scsi_cmnd *SCpnt,
+static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status,
+                                     struct scsi_cmnd *SCpnt,
                                      void (*done)(struct scsi_cmnd *))
 {
-       SBP2_DEBUG_ENTER();
-
-       /*
-        * Sanity
-        */
        if (!SCpnt) {
                SBP2_ERR("SCpnt is NULL");
                return;
        }
 
-       /*
-        * If a bus reset is in progress and there was an error, don't
-        * complete the command, just let it get retried at the end of the
-        * bus reset.
-        */
-       if (!hpsb_node_entry_valid(scsi_id->ne)
-           && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
-               SBP2_ERR("Bus reset in progress - retry command later");
-               return;
-       }
-
-       /*
-        * Switch on scsi status
-        */
        switch (scsi_status) {
        case SBP2_SCSI_STATUS_GOOD:
                SCpnt->result = DID_OK << 16;
@@ -2451,12 +1971,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
                break;
 
        case SBP2_SCSI_STATUS_CHECK_CONDITION:
-               SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
                SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
-#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
-               scsi_print_command(SCpnt);
-               scsi_print_sense(SBP2_DEVICE_NAME, SCpnt);
-#endif
                break;
 
        case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
@@ -2478,118 +1993,88 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
                SCpnt->result = DID_ERROR << 16;
        }
 
-       /*
-        * If a bus reset is in progress and there was an error, complete
-        * the command as busy so that it will get retried.
-        */
-       if (!hpsb_node_entry_valid(scsi_id->ne)
+       /* If a bus reset is in progress and there was an error, complete
+        * the command as busy so that it will get retried. */
+       if (!hpsb_node_entry_valid(lu->ne)
            && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
                SBP2_ERR("Completing command with busy (bus reset)");
                SCpnt->result = DID_BUS_BUSY << 16;
        }
 
-       /*
-        * If a unit attention occurs, return busy status so it gets
-        * retried... it could have happened because of a 1394 bus reset
-        * or hot-plug...
-        * XXX  DID_BUS_BUSY is actually a bad idea because it will defy
-        * the scsi layer's retry logic.
-        */
-#if 0
-       if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) &&
-           (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
-               SBP2_DEBUG("UNIT ATTENTION - return busy");
-               SCpnt->result = DID_BUS_BUSY << 16;
-       }
-#endif
-
-       /*
-        * Tell scsi stack that we're done with this command
-        */
+       /* Tell the SCSI stack that we're done with this command. */
        done(SCpnt);
 }
 
 static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 {
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
 
-       scsi_id->sdev = sdev;
+       lu->sdev = sdev;
        sdev->allow_restart = 1;
 
-       if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+       if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
                sdev->inquiry_len = 36;
        return 0;
 }
 
 static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 {
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
 
        blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
        sdev->use_10_for_rw = 1;
 
        if (sdev->type == TYPE_DISK &&
-           scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+           lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
                sdev->skip_ms_page_8 = 1;
-       if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+       if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
                sdev->fix_capacity = 1;
        return 0;
 }
 
 static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
 {
-       ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
+       ((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL;
        return;
 }
 
 /*
- * Called by scsi stack when something has really gone wrong.  Usually
- * called when a command has timed-out for some reason.
+ * Called by scsi stack when something has really gone wrong.
+ * Usually called when a command has timed-out for some reason.
  */
 static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
 {
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
-       struct sbp2scsi_host_info *hi = scsi_id->hi;
-       struct sbp2_command_info *command;
+       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
+       struct sbp2_fwhost_info *hi = lu->hi;
+       struct sbp2_command_info *cmd;
        unsigned long flags;
 
-       SBP2_ERR("aborting sbp2 command");
+       SBP2_INFO("aborting sbp2 command");
        scsi_print_command(SCpnt);
 
-       if (sbp2util_node_is_available(scsi_id)) {
-
-               /*
-                * Right now, just return any matching command structures
-                * to the free pool.
-                */
-               spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-               command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
-               if (command) {
-                       SBP2_DEBUG("Found command to abort");
-                       pci_dma_sync_single_for_cpu(hi->host->pdev,
-                                                   command->command_orb_dma,
-                                                   sizeof(struct sbp2_command_orb),
-                                                   PCI_DMA_TODEVICE);
-                       pci_dma_sync_single_for_cpu(hi->host->pdev,
-                                                   command->sge_dma,
-                                                   sizeof(command->scatter_gather_element),
-                                                   PCI_DMA_BIDIRECTIONAL);
-                       sbp2util_mark_command_completed(scsi_id, command);
-                       if (command->Current_SCpnt) {
-                               command->Current_SCpnt->result = DID_ABORT << 16;
-                               command->Current_done(command->Current_SCpnt);
+       if (sbp2util_node_is_available(lu)) {
+               sbp2_agent_reset(lu, 1);
+
+               /* Return a matching command structure to the free pool. */
+               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
+               cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
+               if (cmd) {
+                       dma_sync_single_for_cpu(&hi->host->device,
+                                       cmd->command_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+                       dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
+                       sbp2util_mark_command_completed(lu, cmd);
+                       if (cmd->Current_SCpnt) {
+                               cmd->Current_SCpnt->result = DID_ABORT << 16;
+                               cmd->Current_done(cmd->Current_SCpnt);
                        }
                }
-               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
 
-               /*
-                * Initiate a fetch agent reset.
-                */
-               sbp2_agent_reset(scsi_id, 1);
-               sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
+               sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
        }
 
        return SUCCESS;
@@ -2600,14 +2085,13 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
  */
 static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 {
-       struct scsi_id_instance_data *scsi_id =
-               (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
 
-       SBP2_ERR("reset requested");
+       SBP2_INFO("reset requested");
 
-       if (sbp2util_node_is_available(scsi_id)) {
-               SBP2_ERR("Generating sbp2 fetch agent reset");
-               sbp2_agent_reset(scsi_id, 1);
+       if (sbp2util_node_is_available(lu)) {
+               SBP2_INFO("generating sbp2 fetch agent reset");
+               sbp2_agent_reset(lu, 1);
        }
 
        return SUCCESS;
@@ -2618,90 +2102,50 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
                                           char *buf)
 {
        struct scsi_device *sdev;
-       struct scsi_id_instance_data *scsi_id;
-       int lun;
+       struct sbp2_lu *lu;
 
        if (!(sdev = to_scsi_device(dev)))
                return 0;
 
-       if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
+       if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
                return 0;
 
-       lun = ORB_SET_LUN(scsi_id->sbp2_lun);
-
-       return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid,
-                      scsi_id->ud->id, lun);
+       return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,
+                      lu->ud->id, ORB_SET_LUN(lu->lun));
 }
-static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
-
-static struct device_attribute *sbp2_sysfs_sdev_attrs[] = {
-       &dev_attr_ieee1394_id,
-       NULL
-};
 
 MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
 MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
 MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
 MODULE_LICENSE("GPL");
 
-/* SCSI host template */
-static struct scsi_host_template scsi_driver_template = {
-       .module =                       THIS_MODULE,
-       .name =                         "SBP-2 IEEE-1394",
-       .proc_name =                    SBP2_DEVICE_NAME,
-       .queuecommand =                 sbp2scsi_queuecommand,
-       .eh_abort_handler =             sbp2scsi_abort,
-       .eh_device_reset_handler =      sbp2scsi_reset,
-       .slave_alloc =                  sbp2scsi_slave_alloc,
-       .slave_configure =              sbp2scsi_slave_configure,
-       .slave_destroy =                sbp2scsi_slave_destroy,
-       .this_id =                      -1,
-       .sg_tablesize =                 SG_ALL,
-       .use_clustering =               ENABLE_CLUSTERING,
-       .cmd_per_lun =                  SBP2_MAX_CMDS,
-       .can_queue =                    SBP2_MAX_CMDS,
-       .emulated =                     1,
-       .sdev_attrs =                   sbp2_sysfs_sdev_attrs,
-};
-
 static int sbp2_module_init(void)
 {
        int ret;
 
-       SBP2_DEBUG_ENTER();
-
-       /* Module load debug option to force one command at a time (serializing I/O) */
-       if (serialize_io) {
-               SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
-               SBP2_INFO("Try serialize_io=0 for better performance");
-               scsi_driver_template.can_queue = 1;
-               scsi_driver_template.cmd_per_lun = 1;
+       if (sbp2_serialize_io) {
+               sbp2_shost_template.can_queue = 1;
+               sbp2_shost_template.cmd_per_lun = 1;
        }
 
        if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
-           (max_sectors * 512) > (128 * 1024))
-               max_sectors = 128 * 1024 / 512;
-       scsi_driver_template.max_sectors = max_sectors;
+           (sbp2_max_sectors * 512) > (128 * 1024))
+               sbp2_max_sectors = 128 * 1024 / 512;
+       sbp2_shost_template.max_sectors = sbp2_max_sectors;
 
-       /* Register our high level driver with 1394 stack */
        hpsb_register_highlevel(&sbp2_highlevel);
-
        ret = hpsb_register_protocol(&sbp2_driver);
        if (ret) {
                SBP2_ERR("Failed to register protocol");
                hpsb_unregister_highlevel(&sbp2_highlevel);
                return ret;
        }
-
        return 0;
 }
 
 static void __exit sbp2_module_exit(void)
 {
-       SBP2_DEBUG_ENTER();
-
        hpsb_unregister_protocol(&sbp2_driver);
-
        hpsb_unregister_highlevel(&sbp2_highlevel);
 }
 
index abbe48e..9ae8423 100644 (file)
 #define SBP2_DEVICE_NAME               "sbp2"
 
 /*
- * SBP2 specific structures and defines
+ * SBP-2 specific definitions
  */
 
-#define ORB_DIRECTION_WRITE_TO_MEDIA    0x0
-#define ORB_DIRECTION_READ_FROM_MEDIA   0x1
-#define ORB_DIRECTION_NO_DATA_TRANSFER  0x2
-
-#define ORB_SET_NULL_PTR(value)                        ((value & 0x1) << 31)
-#define ORB_SET_NOTIFY(value)                  ((value & 0x1) << 31)
-#define ORB_SET_RQ_FMT(value)                  ((value & 0x3) << 29)   /* unused ? */
-#define ORB_SET_NODE_ID(value)                 ((value & 0xffff) << 16)
-#define ORB_SET_STATUS_FIFO_HI(value, id)      (value >> 32 | ORB_SET_NODE_ID(id))
-#define ORB_SET_STATUS_FIFO_LO(value)          (value & 0xffffffff)
-#define ORB_SET_DATA_SIZE(value)               (value & 0xffff)
-#define ORB_SET_PAGE_SIZE(value)               ((value & 0x7) << 16)
-#define ORB_SET_PAGE_TABLE_PRESENT(value)      ((value & 0x1) << 19)
-#define ORB_SET_MAX_PAYLOAD(value)             ((value & 0xf) << 20)
-#define ORB_SET_SPEED(value)                   ((value & 0x7) << 24)
-#define ORB_SET_DIRECTION(value)               ((value & 0x1) << 27)
+#define ORB_DIRECTION_WRITE_TO_MEDIA   0x0
+#define ORB_DIRECTION_READ_FROM_MEDIA  0x1
+#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
+
+#define ORB_SET_NULL_PTR(v)            (((v) & 0x1) << 31)
+#define ORB_SET_NOTIFY(v)              (((v) & 0x1) << 31)
+#define ORB_SET_RQ_FMT(v)              (((v) & 0x3) << 29)
+#define ORB_SET_NODE_ID(v)             (((v) & 0xffff) << 16)
+#define ORB_SET_STATUS_FIFO_HI(v, id)  ((v) >> 32 | ORB_SET_NODE_ID(id))
+#define ORB_SET_STATUS_FIFO_LO(v)      ((v) & 0xffffffff)
+#define ORB_SET_DATA_SIZE(v)           ((v) & 0xffff)
+#define ORB_SET_PAGE_SIZE(v)           (((v) & 0x7) << 16)
+#define ORB_SET_PAGE_TABLE_PRESENT(v)  (((v) & 0x1) << 19)
+#define ORB_SET_MAX_PAYLOAD(v)         (((v) & 0xf) << 20)
+#define ORB_SET_SPEED(v)               (((v) & 0x7) << 24)
+#define ORB_SET_DIRECTION(v)           (((v) & 0x1) << 27)
 
 struct sbp2_command_orb {
        u32 next_ORB_hi;
@@ -64,12 +64,12 @@ struct sbp2_command_orb {
 #define SBP2_LOGICAL_UNIT_RESET                0xe
 #define SBP2_TARGET_RESET_REQUEST      0xf
 
-#define ORB_SET_LUN(value)                      (value & 0xffff)
-#define ORB_SET_FUNCTION(value)                 ((value & 0xf) << 16)
-#define ORB_SET_RECONNECT(value)                ((value & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(value)                ((value & 0x1) << 28)
-#define ORB_SET_LOGIN_RESP_LENGTH(value)        (value & 0xffff)
-#define ORB_SET_PASSWD_LENGTH(value)            ((value & 0xffff) << 16)
+#define ORB_SET_LUN(v)                 ((v) & 0xffff)
+#define ORB_SET_FUNCTION(v)            (((v) & 0xf) << 16)
+#define ORB_SET_RECONNECT(v)           (((v) & 0xf) << 20)
+#define ORB_SET_EXCLUSIVE(v)           (((v) & 0x1) << 28)
+#define ORB_SET_LOGIN_RESP_LENGTH(v)   ((v) & 0xffff)
+#define ORB_SET_PASSWD_LENGTH(v)       (((v) & 0xffff) << 16)
 
 struct sbp2_login_orb {
        u32 password_hi;
@@ -82,9 +82,9 @@ struct sbp2_login_orb {
        u32 status_fifo_lo;
 } __attribute__((packed));
 
-#define RESPONSE_GET_LOGIN_ID(value)            (value & 0xffff)
-#define RESPONSE_GET_LENGTH(value)              ((value >> 16) & 0xffff)
-#define RESPONSE_GET_RECONNECT_HOLD(value)      (value & 0xffff)
+#define RESPONSE_GET_LOGIN_ID(v)       ((v) & 0xffff)
+#define RESPONSE_GET_LENGTH(v)         (((v) >> 16) & 0xffff)
+#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff)
 
 struct sbp2_login_response {
        u32 length_login_ID;
@@ -93,9 +93,8 @@ struct sbp2_login_response {
        u32 reconnect_hold;
 } __attribute__((packed));
 
-#define ORB_SET_LOGIN_ID(value)                 (value & 0xffff)
-
-#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff)
+#define ORB_SET_LOGIN_ID(v)                 ((v) & 0xffff)
+#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff)
 
 struct sbp2_query_logins_orb {
        u32 reserved1;
@@ -108,8 +107,8 @@ struct sbp2_query_logins_orb {
        u32 status_fifo_lo;
 } __attribute__((packed));
 
-#define RESPONSE_GET_MAX_LOGINS(value)          (value & 0xffff)
-#define RESPONSE_GET_ACTIVE_LOGINS(value)       ((RESPONSE_GET_LENGTH(value) - 4) / 12)
+#define RESPONSE_GET_MAX_LOGINS(v)     ((v) & 0xffff)
+#define RESPONSE_GET_ACTIVE_LOGINS(v)  ((RESPONSE_GET_LENGTH((v)) - 4) / 12)
 
 struct sbp2_query_logins_response {
        u32 length_max_logins;
@@ -140,8 +139,8 @@ struct sbp2_logout_orb {
        u32 status_fifo_lo;
 } __attribute__((packed));
 
-#define PAGE_TABLE_SET_SEGMENT_BASE_HI(value)   (value & 0xffff)
-#define PAGE_TABLE_SET_SEGMENT_LENGTH(value)    ((value & 0xffff) << 16)
+#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v)      ((v) & 0xffff)
+#define PAGE_TABLE_SET_SEGMENT_LENGTH(v)       (((v) & 0xffff) << 16)
 
 struct sbp2_unrestricted_page_table {
        u32 length_segment_base_hi;
@@ -171,23 +170,14 @@ struct sbp2_unrestricted_page_table {
 #define SFMT_DEFERRED_ERROR                    0x1
 #define SFMT_VENDOR_DEPENDENT_STATUS           0x3
 
-#define SBP2_SCSI_STATUS_GOOD                  0x0
-#define SBP2_SCSI_STATUS_CHECK_CONDITION       0x2
-#define SBP2_SCSI_STATUS_CONDITION_MET         0x4
-#define SBP2_SCSI_STATUS_BUSY                  0x8
-#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT  0x18
-#define SBP2_SCSI_STATUS_COMMAND_TERMINATED    0x22
-
-#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT     0xff
-
-#define STATUS_GET_SRC(value)                  (((value) >> 30) & 0x3)
-#define STATUS_GET_RESP(value)                 (((value) >> 28) & 0x3)
-#define STATUS_GET_LEN(value)                  (((value) >> 24) & 0x7)
-#define STATUS_GET_SBP_STATUS(value)           (((value) >> 16) & 0xff)
-#define STATUS_GET_ORB_OFFSET_HI(value)                ((value) & 0x0000ffff)
-#define STATUS_TEST_DEAD(value)                        ((value) & 0x08000000)
+#define STATUS_GET_SRC(v)                      (((v) >> 30) & 0x3)
+#define STATUS_GET_RESP(v)                     (((v) >> 28) & 0x3)
+#define STATUS_GET_LEN(v)                      (((v) >> 24) & 0x7)
+#define STATUS_GET_SBP_STATUS(v)               (((v) >> 16) & 0xff)
+#define STATUS_GET_ORB_OFFSET_HI(v)            ((v) & 0x0000ffff)
+#define STATUS_TEST_DEAD(v)                    ((v) & 0x08000000)
 /* test 'resp' | 'dead' | 'sbp2_status' */
-#define STATUS_TEST_RDS(value)                 ((value) & 0x38ff0000)
+#define STATUS_TEST_RDS(v)                     ((v) & 0x38ff0000)
 
 struct sbp2_status_block {
        u32 ORB_offset_hi_misc;
@@ -195,66 +185,70 @@ struct sbp2_status_block {
        u8 command_set_dependent[24];
 } __attribute__((packed));
 
+
 /*
- * Miscellaneous SBP2 related config rom defines
+ * SBP2 related configuration ROM definitions
  */
 
-#define SBP2_UNIT_DIRECTORY_OFFSET_KEY                         0xd1
-#define SBP2_CSR_OFFSET_KEY                                    0x54
-#define SBP2_UNIT_SPEC_ID_KEY                                  0x12
-#define SBP2_UNIT_SW_VERSION_KEY                               0x13
-#define SBP2_COMMAND_SET_SPEC_ID_KEY                           0x38
-#define SBP2_COMMAND_SET_KEY                                   0x39
-#define SBP2_UNIT_CHARACTERISTICS_KEY                          0x3a
-#define SBP2_DEVICE_TYPE_AND_LUN_KEY                           0x14
-#define SBP2_FIRMWARE_REVISION_KEY                             0x3c
+#define SBP2_UNIT_DIRECTORY_OFFSET_KEY         0xd1
+#define SBP2_CSR_OFFSET_KEY                    0x54
+#define SBP2_UNIT_SPEC_ID_KEY                  0x12
+#define SBP2_UNIT_SW_VERSION_KEY               0x13
+#define SBP2_COMMAND_SET_SPEC_ID_KEY           0x38
+#define SBP2_COMMAND_SET_KEY                   0x39
+#define SBP2_UNIT_CHARACTERISTICS_KEY          0x3a
+#define SBP2_DEVICE_TYPE_AND_LUN_KEY           0x14
+#define SBP2_FIRMWARE_REVISION_KEY             0x3c
 
-#define SBP2_AGENT_STATE_OFFSET                                        0x00ULL
-#define SBP2_AGENT_RESET_OFFSET                                        0x04ULL
-#define SBP2_ORB_POINTER_OFFSET                                        0x08ULL
-#define SBP2_DOORBELL_OFFSET                                   0x10ULL
-#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET                  0x14ULL
-#define SBP2_UNSOLICITED_STATUS_VALUE                          0xf
+#define SBP2_AGENT_STATE_OFFSET                        0x00ULL
+#define SBP2_AGENT_RESET_OFFSET                        0x04ULL
+#define SBP2_ORB_POINTER_OFFSET                        0x08ULL
+#define SBP2_DOORBELL_OFFSET                   0x10ULL
+#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET  0x14ULL
+#define SBP2_UNSOLICITED_STATUS_VALUE          0xf
 
-#define SBP2_BUSY_TIMEOUT_ADDRESS                              0xfffff0000210ULL
-#define SBP2_BUSY_TIMEOUT_VALUE                                        0xf
+#define SBP2_BUSY_TIMEOUT_ADDRESS              0xfffff0000210ULL
+/* biggest possible value for Single Phase Retry count is 0xf */
+#define SBP2_BUSY_TIMEOUT_VALUE                        0xf
 
-#define SBP2_AGENT_RESET_DATA                                  0xf
+#define SBP2_AGENT_RESET_DATA                  0xf
 
-/*
- * Unit spec id and sw version entry for SBP-2 devices
- */
+#define SBP2_UNIT_SPEC_ID_ENTRY                        0x0000609e
+#define SBP2_SW_VERSION_ENTRY                  0x00010483
 
-#define SBP2_UNIT_SPEC_ID_ENTRY                                        0x0000609e
-#define SBP2_SW_VERSION_ENTRY                                  0x00010483
 
 /*
- * SCSI specific stuff
+ * SCSI specific definitions
  */
 
-#define SBP2_MAX_SG_ELEMENT_LENGTH     0xf000
-#define SBP2_MAX_SECTORS               255     /* Max sectors supported */
-#define SBP2_MAX_CMDS                  8       /* This should be safe */
+#define SBP2_MAX_SG_ELEMENT_LENGTH             0xf000
+#define SBP2_MAX_SECTORS                       255
+/* There is no real limitation of the queue depth (i.e. length of the linked
+ * list of command ORBs) at the target. The chosen depth is merely an
+ * implementation detail of the sbp2 driver. */
+#define SBP2_MAX_CMDS                          8
+
+#define SBP2_SCSI_STATUS_GOOD                  0x0
+#define SBP2_SCSI_STATUS_CHECK_CONDITION       0x2
+#define SBP2_SCSI_STATUS_CONDITION_MET         0x4
+#define SBP2_SCSI_STATUS_BUSY                  0x8
+#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT  0x18
+#define SBP2_SCSI_STATUS_COMMAND_TERMINATED    0x22
+#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT     0xff
 
-/* Flags for detected oddities and brokeness */
-#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
-#define SBP2_WORKAROUND_INQUIRY_36     0x2
-#define SBP2_WORKAROUND_MODE_SENSE_8   0x4
-#define SBP2_WORKAROUND_FIX_CAPACITY   0x8
-#define SBP2_WORKAROUND_OVERRIDE       0x100
 
-/* This is the two dma types we use for cmd_dma below */
-enum cmd_dma_types {
+/*
+ * Representations of commands and devices
+ */
+
+enum sbp2_dma_types {
        CMD_DMA_NONE,
        CMD_DMA_PAGE,
        CMD_DMA_SINGLE
 };
 
-/*
- * Encapsulates all the info necessary for an outstanding command.
- */
+/* Per SCSI command */
 struct sbp2_command_info {
-
        struct list_head list;
        struct sbp2_command_orb command_orb ____cacheline_aligned;
        dma_addr_t command_orb_dma ____cacheline_aligned;
@@ -262,25 +256,25 @@ struct sbp2_command_info {
        void (*Current_done)(struct scsi_cmnd *);
 
        /* Also need s/g structure for each sbp2 command */
-       struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned;
+       struct sbp2_unrestricted_page_table
+                       scatter_gather_element[SG_ALL] ____cacheline_aligned;
        dma_addr_t sge_dma ____cacheline_aligned;
        void *sge_buffer;
        dma_addr_t cmd_dma;
-       enum cmd_dma_types dma_type;
+       enum sbp2_dma_types dma_type;
        unsigned long dma_size;
-       int dma_dir;
-
+       enum dma_data_direction dma_dir;
 };
 
-struct sbp2scsi_host_info;
+/* Per FireWire host */
+struct sbp2_fwhost_info {
+       struct hpsb_host *host;
+       struct list_head logical_units;
+};
 
-/*
- * Information needed on a per scsi id basis (one for each sbp2 device)
- */
-struct scsi_id_instance_data {
-       /*
-        * Various sbp2 specific structures
-        */
+/* Per logical unit */
+struct sbp2_lu {
+       /* Operation request blocks */
        struct sbp2_command_orb *last_orb;
        dma_addr_t last_orb_dma;
        struct sbp2_login_orb *login_orb;
@@ -297,116 +291,59 @@ struct scsi_id_instance_data {
        dma_addr_t logout_orb_dma;
        struct sbp2_status_block status_block;
 
-       /*
-        * Stuff we need to know about the sbp2 device itself
-        */
-       u64 sbp2_management_agent_addr;
-       u64 sbp2_command_block_agent_addr;
+       /* How to talk to the unit */
+       u64 management_agent_addr;
+       u64 command_block_agent_addr;
        u32 speed_code;
        u32 max_payload_size;
+       u16 lun;
 
-       /*
-        * Values pulled from the device's unit directory
-        */
-       u32 sbp2_command_set_spec_id;
-       u32 sbp2_command_set;
-       u32 sbp2_unit_characteristics;
-       u32 sbp2_lun;
-       u32 sbp2_firmware_revision;
-
-       /*
-        * Address for the device to write status blocks to
-        */
+       /* Address for the unit to write status blocks to */
        u64 status_fifo_addr;
 
-       /*
-        * Waitqueue flag for logins, reconnects, logouts, query logins
-        */
-       int access_complete:1;
+       /* Waitqueue flag for logins, reconnects, logouts, query logins */
+       unsigned int access_complete:1;
 
-       /*
-        * Pool of command orbs, so we can have more than overlapped command per id
-        */
-       spinlock_t sbp2_command_orb_lock;
-       struct list_head sbp2_command_orb_inuse;
-       struct list_head sbp2_command_orb_completed;
+       /* Pool of command ORBs for this logical unit */
+       spinlock_t cmd_orb_lock;
+       struct list_head cmd_orb_inuse;
+       struct list_head cmd_orb_completed;
 
-       struct list_head scsi_list;
+       /* Backlink to FireWire host; list of units attached to the host */
+       struct sbp2_fwhost_info *hi;
+       struct list_head lu_list;
 
-       /* Node entry, as retrieved from NodeMgr entries */
+       /* IEEE 1394 core's device representations */
        struct node_entry *ne;
        struct unit_directory *ud;
 
-       /* A backlink to our host_info */
-       struct sbp2scsi_host_info *hi;
-
-       /* SCSI related pointers */
+       /* SCSI core's device representations */
        struct scsi_device *sdev;
-       struct Scsi_Host *scsi_host;
+       struct Scsi_Host *shost;
 
        /* Device specific workarounds/brokeness */
        unsigned workarounds;
 
+       /* Connection state */
        atomic_t state;
+
+       /* For deferred requests to the fetch agent */
        struct work_struct protocol_work;
 };
 
-/* For use in scsi_id_instance_data.state */
+/* For use in sbp2_lu.state */
 enum sbp2lu_state_types {
        SBP2LU_STATE_RUNNING,           /* all normal */
        SBP2LU_STATE_IN_RESET,          /* between bus reset and reconnect */
        SBP2LU_STATE_IN_SHUTDOWN        /* when sbp2_remove was called */
 };
 
-/* Sbp2 host data structure (one per IEEE1394 host) */
-struct sbp2scsi_host_info {
-       struct hpsb_host *host;         /* IEEE1394 host */
-       struct list_head scsi_ids;      /* List of scsi ids on this host */
-};
-
-/*
- * Function prototypes
- */
-
-/*
- * Various utility prototypes
- */
-static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id);
-static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id);
-static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb);
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt);
-static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
-                                                         struct scsi_cmnd *Current_SCpnt,
-                                                         void (*Current_done)(struct scsi_cmnd *));
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
-               struct sbp2_command_info *command);
-
-
-static int sbp2_start_device(struct scsi_id_instance_data *scsi_id);
-static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id);
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
-                                     u64 addr, size_t length, u16 flags);
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                    u64 addr, size_t length, u16 flags);
-#endif
-
-/*
- * SBP-2 protocol related prototypes
- */
-static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id);
-static int sbp2_login_device(struct scsi_id_instance_data *scsi_id);
-static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id);
-static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
-static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
-                                   quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
-static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
-                                             unchar *sense_data);
-static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
-                                     struct unit_directory *ud);
-static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
-static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
+/* For use in sbp2_lu.workarounds and in the corresponding
+ * module load parameter */
+#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
+#define SBP2_WORKAROUND_INQUIRY_36     0x2
+#define SBP2_WORKAROUND_MODE_SENSE_8   0x4
+#define SBP2_WORKAROUND_FIX_CAPACITY   0x8
+#define SBP2_WORKAROUND_OVERRIDE       0x100
 
 #endif /* SBP2_H */
index 9bc6505..598b19f 100644 (file)
@@ -714,8 +714,8 @@ static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
        return ret;
 }
 
-static int __video1394_ioctl(struct file *file,
-                            unsigned int cmd, unsigned long arg)
+static long video1394_ioctl(struct file *file,
+                           unsigned int cmd, unsigned long arg)
 {
        struct file_ctx *ctx = (struct file_ctx *)file->private_data;
        struct ti_ohci *ohci = ctx->ohci;
@@ -884,13 +884,14 @@ static int __video1394_ioctl(struct file *file,
                struct dma_iso_ctx *d;
                int next_prg;
 
-               if (copy_from_user(&v, argp, sizeof(v)))
+               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
                        return -EFAULT;
 
                d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (d == NULL) return -EFAULT;
+               if (unlikely(d == NULL))
+                       return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
+               if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -898,7 +899,7 @@ static int __video1394_ioctl(struct file *file,
 
                spin_lock_irqsave(&d->lock,flags);
 
-               if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
+               if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d is already used",v.buffer);
                        spin_unlock_irqrestore(&d->lock,flags);
@@ -949,13 +950,14 @@ static int __video1394_ioctl(struct file *file,
                struct dma_iso_ctx *d;
                int i = 0;
 
-               if (copy_from_user(&v, argp, sizeof(v)))
+               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
                        return -EFAULT;
 
                d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (d == NULL) return -EFAULT;
+               if (unlikely(d == NULL))
+                       return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
+               if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1008,7 +1010,7 @@ static int __video1394_ioctl(struct file *file,
                spin_unlock_irqrestore(&d->lock, flags);
 
                v.buffer=i;
-               if (copy_to_user(argp, &v, sizeof(v)))
+               if (unlikely(copy_to_user(argp, &v, sizeof(v))))
                        return -EFAULT;
 
                return 0;
@@ -1156,15 +1158,6 @@ static int __video1394_ioctl(struct file *file,
        }
 }
 
-static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       int err;
-       lock_kernel();
-       err = __video1394_ioctl(file, cmd, arg);
-       unlock_kernel();
-       return err;
-}
-
 /*
  *     This maps the vmalloced and reserved buffer to user space.
  *
@@ -1177,17 +1170,14 @@ static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long a
 static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct file_ctx *ctx = (struct file_ctx *)file->private_data;
-       int res = -EINVAL;
 
-       lock_kernel();
        if (ctx->current_ctx == NULL) {
                PRINT(KERN_ERR, ctx->ohci->host->id,
                                "Current iso context not set");
-       } else
-               res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
-       unlock_kernel();
+               return -EINVAL;
+       }
 
-       return res;
+       return dma_region_mmap(&ctx->current_ctx->dma, file, vma);
 }
 
 static unsigned int video1394_poll(struct file *file, poll_table *pt)
@@ -1198,14 +1188,12 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt)
        struct dma_iso_ctx *d;
        int i;
 
-       lock_kernel();
        ctx = file->private_data;
        d = ctx->current_ctx;
        if (d == NULL) {
                PRINT(KERN_ERR, ctx->ohci->host->id,
                                "Current iso context not set");
-               mask = POLLERR;
-               goto done;
+               return POLLERR;
        }
 
        poll_wait(file, &d->waitq, pt);
@@ -1218,8 +1206,6 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt)
                }
        }
        spin_unlock_irqrestore(&d->lock, flags);
-done:
-       unlock_kernel();
 
        return mask;
 }
@@ -1255,7 +1241,6 @@ static int video1394_release(struct inode *inode, struct file *file)
        struct list_head *lh, *next;
        u64 mask;
 
-       lock_kernel();
        list_for_each_safe(lh, next, &ctx->context_list) {
                struct dma_iso_ctx *d;
                d = list_entry(lh, struct dma_iso_ctx, link);
@@ -1276,7 +1261,6 @@ static int video1394_release(struct inode *inode, struct file *file)
        kfree(ctx);
        file->private_data = NULL;
 
-       unlock_kernel();
        return 0;
 }
 
@@ -1324,12 +1308,8 @@ static struct ieee1394_device_id video1394_id_table[] = {
 MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
 
 static struct hpsb_protocol_driver video1394_driver = {
-       .name           = "1394 Digital Camera Driver",
+       .name           = VIDEO1394_DRIVER_NAME,
        .id_table       = video1394_id_table,
-       .driver         = {
-               .name   = VIDEO1394_DRIVER_NAME,
-               .bus    = &ieee1394_bus_type,
-       },
 };
 
 
index 7767a11..af93979 100644 (file)
@@ -55,11 +55,11 @@ struct addr_req {
        int status;
 };
 
-static void process_req(void *data);
+static void process_req(struct work_struct *work);
 
 static DEFINE_MUTEX(lock);
 static LIST_HEAD(req_list);
-static DECLARE_WORK(work, process_req, NULL);
+static DECLARE_DELAYED_WORK(work, process_req);
 static struct workqueue_struct *addr_wq;
 
 void rdma_addr_register_client(struct rdma_addr_client *client)
@@ -215,7 +215,7 @@ out:
        return ret;
 }
 
-static void process_req(void *data)
+static void process_req(struct work_struct *work)
 {
        struct addr_req *req, *temp_req;
        struct sockaddr_in *src_in, *dst_in;
index 20e9f64..98272fb 100644 (file)
@@ -285,9 +285,10 @@ err:
        kfree(tprops);
 }
 
-static void ib_cache_task(void *work_ptr)
+static void ib_cache_task(struct work_struct *_work)
 {
-       struct ib_update_work *work = work_ptr;
+       struct ib_update_work *work =
+               container_of(_work, struct ib_update_work, work);
 
        ib_cache_update(work->device, work->port_num);
        kfree(work);
@@ -306,7 +307,7 @@ static void ib_cache_event(struct ib_event_handler *handler,
            event->event == IB_EVENT_CLIENT_REREGISTER) {
                work = kmalloc(sizeof *work, GFP_ATOMIC);
                if (work) {
-                       INIT_WORK(&work->work, ib_cache_task, work);
+                       INIT_WORK(&work->work, ib_cache_task);
                        work->device   = event->device;
                        work->port_num = event->element.port_num;
                        schedule_work(&work->work);
index e5dc453..79c937b 100644 (file)
@@ -101,7 +101,7 @@ struct cm_av {
 };
 
 struct cm_work {
-       struct work_struct work;
+       struct delayed_work work;
        struct list_head list;
        struct cm_port *port;
        struct ib_mad_recv_wc *mad_recv_wc;     /* Received MADs */
@@ -161,7 +161,7 @@ struct cm_id_private {
        atomic_t work_count;
 };
 
-static void cm_work_handler(void *data);
+static void cm_work_handler(struct work_struct *work);
 
 static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
 {
@@ -668,8 +668,7 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
                return ERR_PTR(-ENOMEM);
 
        timewait_info->work.local_id = local_id;
-       INIT_WORK(&timewait_info->work.work, cm_work_handler,
-                 &timewait_info->work);
+       INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler);
        timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT;
        return timewait_info;
 }
@@ -2995,9 +2994,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
        }
 }
 
-static void cm_work_handler(void *data)
+static void cm_work_handler(struct work_struct *_work)
 {
-       struct cm_work *work = data;
+       struct cm_work *work = container_of(_work, struct cm_work, work.work);
        int ret;
 
        switch (work->cm_event.event) {
@@ -3087,12 +3086,12 @@ static int cm_establish(struct ib_cm_id *cm_id)
         * we need to find the cm_id once we're in the context of the
         * worker thread, rather than holding a reference on it.
         */
-       INIT_WORK(&work->work, cm_work_handler, work);
+       INIT_DELAYED_WORK(&work->work, cm_work_handler);
        work->local_id = cm_id->local_id;
        work->remote_id = cm_id->remote_id;
        work->mad_recv_wc = NULL;
        work->cm_event.event = IB_CM_USER_ESTABLISHED;
-       queue_work(cm.wq, &work->work);
+       queue_delayed_work(cm.wq, &work->work, 0);
 out:
        return ret;
 }
@@ -3191,11 +3190,11 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
                return;
        }
 
-       INIT_WORK(&work->work, cm_work_handler, work);
+       INIT_DELAYED_WORK(&work->work, cm_work_handler);
        work->cm_event.event = event;
        work->mad_recv_wc = mad_recv_wc;
        work->port = (struct cm_port *)mad_agent->context;
-       queue_work(cm.wq, &work->work);
+       queue_delayed_work(cm.wq, &work->work, 0);
 }
 
 static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
index cf48f26..985a6b5 100644 (file)
@@ -1340,9 +1340,9 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
        return (id_priv->query_id < 0) ? id_priv->query_id : 0;
 }
 
-static void cma_work_handler(void *data)
+static void cma_work_handler(struct work_struct *_work)
 {
-       struct cma_work *work = data;
+       struct cma_work *work = container_of(_work, struct cma_work, work);
        struct rdma_id_private *id_priv = work->id;
        int destroy = 0;
 
@@ -1373,7 +1373,7 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
                return -ENOMEM;
 
        work->id = id_priv;
-       INIT_WORK(&work->work, cma_work_handler, work);
+       INIT_WORK(&work->work, cma_work_handler);
        work->old_state = CMA_ROUTE_QUERY;
        work->new_state = CMA_ROUTE_RESOLVED;
        work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
@@ -1430,7 +1430,7 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms)
                return -ENOMEM;
 
        work->id = id_priv;
-       INIT_WORK(&work->work, cma_work_handler, work);
+       INIT_WORK(&work->work, cma_work_handler);
        work->old_state = CMA_ROUTE_QUERY;
        work->new_state = CMA_ROUTE_RESOLVED;
        work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
@@ -1583,7 +1583,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv)
        }
 
        work->id = id_priv;
-       INIT_WORK(&work->work, cma_work_handler, work);
+       INIT_WORK(&work->work, cma_work_handler);
        work->old_state = CMA_ADDR_QUERY;
        work->new_state = CMA_ADDR_RESOLVED;
        work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
index cf797d7..1039ad5 100644 (file)
@@ -828,9 +828,9 @@ static int process_event(struct iwcm_id_private *cm_id_priv,
  * thread asleep on the destroy_comp list vs. an object destroyed
  * here synchronously when the last reference is removed.
  */
-static void cm_work_handler(void *arg)
+static void cm_work_handler(struct work_struct *_work)
 {
-       struct iwcm_work *work = arg;
+       struct iwcm_work *work = container_of(_work, struct iwcm_work, work);
        struct iw_cm_event levent;
        struct iwcm_id_private *cm_id_priv = work->cm_id;
        unsigned long flags;
@@ -900,7 +900,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id,
                goto out;
        }
 
-       INIT_WORK(&work->work, cm_work_handler, work);
+       INIT_WORK(&work->work, cm_work_handler);
        work->cm_id = cm_id_priv;
        work->event = *iw_event;
 
index 3f9c162..15f38d9 100644 (file)
@@ -65,8 +65,8 @@ static struct ib_mad_agent_private *find_mad_agent(
 static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
                                    struct ib_mad_private *mad);
 static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv);
-static void timeout_sends(void *data);
-static void local_completions(void *data);
+static void timeout_sends(struct work_struct *work);
+static void local_completions(struct work_struct *work);
 static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
                              struct ib_mad_agent_private *agent_priv,
                              u8 mgmt_class);
@@ -356,10 +356,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
        INIT_LIST_HEAD(&mad_agent_priv->wait_list);
        INIT_LIST_HEAD(&mad_agent_priv->done_list);
        INIT_LIST_HEAD(&mad_agent_priv->rmpp_list);
-       INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv);
+       INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends);
        INIT_LIST_HEAD(&mad_agent_priv->local_list);
-       INIT_WORK(&mad_agent_priv->local_work, local_completions,
-                  mad_agent_priv);
+       INIT_WORK(&mad_agent_priv->local_work, local_completions);
        atomic_set(&mad_agent_priv->refcount, 1);
        init_completion(&mad_agent_priv->comp);
 
@@ -2198,12 +2197,12 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv,
 /*
  * IB MAD completion callback
  */
-static void ib_mad_completion_handler(void *data)
+static void ib_mad_completion_handler(struct work_struct *work)
 {
        struct ib_mad_port_private *port_priv;
        struct ib_wc wc;
 
-       port_priv = (struct ib_mad_port_private *)data;
+       port_priv = container_of(work, struct ib_mad_port_private, work);
        ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP);
 
        while (ib_poll_cq(port_priv->cq, 1, &wc) == 1) {
@@ -2324,7 +2323,7 @@ void ib_cancel_mad(struct ib_mad_agent *mad_agent,
 }
 EXPORT_SYMBOL(ib_cancel_mad);
 
-static void local_completions(void *data)
+static void local_completions(struct work_struct *work)
 {
        struct ib_mad_agent_private *mad_agent_priv;
        struct ib_mad_local_private *local;
@@ -2334,7 +2333,8 @@ static void local_completions(void *data)
        struct ib_wc wc;
        struct ib_mad_send_wc mad_send_wc;
 
-       mad_agent_priv = (struct ib_mad_agent_private *)data;
+       mad_agent_priv =
+               container_of(work, struct ib_mad_agent_private, local_work);
 
        spin_lock_irqsave(&mad_agent_priv->lock, flags);
        while (!list_empty(&mad_agent_priv->local_list)) {
@@ -2434,14 +2434,15 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
        return ret;
 }
 
-static void timeout_sends(void *data)
+static void timeout_sends(struct work_struct *work)
 {
        struct ib_mad_agent_private *mad_agent_priv;
        struct ib_mad_send_wr_private *mad_send_wr;
        struct ib_mad_send_wc mad_send_wc;
        unsigned long flags, delay;
 
-       mad_agent_priv = (struct ib_mad_agent_private *)data;
+       mad_agent_priv = container_of(work, struct ib_mad_agent_private,
+                                     timed_work.work);
        mad_send_wc.vendor_err = 0;
 
        spin_lock_irqsave(&mad_agent_priv->lock, flags);
@@ -2799,7 +2800,7 @@ static int ib_mad_port_open(struct ib_device *device,
                ret = -ENOMEM;
                goto error8;
        }
-       INIT_WORK(&port_priv->work, ib_mad_completion_handler, port_priv);
+       INIT_WORK(&port_priv->work, ib_mad_completion_handler);
 
        spin_lock_irqsave(&ib_mad_port_list_lock, flags);
        list_add_tail(&port_priv->port_list, &ib_mad_port_list);
index d06b590..d5548e7 100644 (file)
@@ -102,7 +102,7 @@ struct ib_mad_agent_private {
        struct list_head send_list;
        struct list_head wait_list;
        struct list_head done_list;
-       struct work_struct timed_work;
+       struct delayed_work timed_work;
        unsigned long timeout;
        struct list_head local_list;
        struct work_struct local_work;
index 1ef79d0..3663fd7 100644 (file)
@@ -45,8 +45,8 @@ enum rmpp_state {
 struct mad_rmpp_recv {
        struct ib_mad_agent_private *agent;
        struct list_head list;
-       struct work_struct timeout_work;
-       struct work_struct cleanup_work;
+       struct delayed_work timeout_work;
+       struct delayed_work cleanup_work;
        struct completion comp;
        enum rmpp_state state;
        spinlock_t lock;
@@ -233,9 +233,10 @@ static void nack_recv(struct ib_mad_agent_private *agent,
        }
 }
 
-static void recv_timeout_handler(void *data)
+static void recv_timeout_handler(struct work_struct *work)
 {
-       struct mad_rmpp_recv *rmpp_recv = data;
+       struct mad_rmpp_recv *rmpp_recv =
+               container_of(work, struct mad_rmpp_recv, timeout_work.work);
        struct ib_mad_recv_wc *rmpp_wc;
        unsigned long flags;
 
@@ -254,9 +255,10 @@ static void recv_timeout_handler(void *data)
        ib_free_recv_mad(rmpp_wc);
 }
 
-static void recv_cleanup_handler(void *data)
+static void recv_cleanup_handler(struct work_struct *work)
 {
-       struct mad_rmpp_recv *rmpp_recv = data;
+       struct mad_rmpp_recv *rmpp_recv =
+               container_of(work, struct mad_rmpp_recv, cleanup_work.work);
        unsigned long flags;
 
        spin_lock_irqsave(&rmpp_recv->agent->lock, flags);
@@ -285,8 +287,8 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
 
        rmpp_recv->agent = agent;
        init_completion(&rmpp_recv->comp);
-       INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv);
-       INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv);
+       INIT_DELAYED_WORK(&rmpp_recv->timeout_work, recv_timeout_handler);
+       INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler);
        spin_lock_init(&rmpp_recv->lock);
        rmpp_recv->state = RMPP_STATE_ACTIVE;
        atomic_set(&rmpp_recv->refcount, 1);
index 1706d3c..e45afba 100644 (file)
@@ -360,9 +360,10 @@ static void free_sm_ah(struct kref *kref)
        kfree(sm_ah);
 }
 
-static void update_sm_ah(void *port_ptr)
+static void update_sm_ah(struct work_struct *work)
 {
-       struct ib_sa_port *port = port_ptr;
+       struct ib_sa_port *port =
+               container_of(work, struct ib_sa_port, update_task);
        struct ib_sa_sm_ah *new_ah, *old_ah;
        struct ib_port_attr port_attr;
        struct ib_ah_attr   ah_attr;
@@ -992,8 +993,7 @@ static void ib_sa_add_one(struct ib_device *device)
                if (IS_ERR(sa_dev->port[i].agent))
                        goto err;
 
-               INIT_WORK(&sa_dev->port[i].update_task,
-                         update_sm_ah, &sa_dev->port[i]);
+               INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);
        }
 
        ib_set_client_data(device, &sa_client, sa_dev);
@@ -1010,7 +1010,7 @@ static void ib_sa_add_one(struct ib_device *device)
                goto err;
 
        for (i = 0; i <= e - s; ++i)
-               update_sm_ah(&sa_dev->port[i]);
+               update_sm_ah(&sa_dev->port[i].update_task);
 
        return;
 
index 4e16314..a617ca7 100644 (file)
@@ -534,9 +534,9 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
         * module reference.
         */
        filp->f_op         = fops_get(&uverbs_event_fops);
-       filp->f_vfsmnt     = mntget(uverbs_event_mnt);
-       filp->f_dentry     = dget(uverbs_event_mnt->mnt_root);
-       filp->f_mapping    = filp->f_dentry->d_inode->i_mapping;
+       filp->f_path.mnt           = mntget(uverbs_event_mnt);
+       filp->f_path.dentry        = dget(uverbs_event_mnt->mnt_root);
+       filp->f_mapping    = filp->f_path.dentry->d_inode->i_mapping;
        filp->f_flags      = O_RDONLY;
        filp->f_mode       = FMODE_READ;
        filp->private_data = ev_file;
index efe147d..db12cc0 100644 (file)
@@ -179,9 +179,10 @@ void ib_umem_release(struct ib_device *dev, struct ib_umem *umem)
        up_write(&current->mm->mmap_sem);
 }
 
-static void ib_umem_account(void *work_ptr)
+static void ib_umem_account(struct work_struct *_work)
 {
-       struct ib_umem_account_work *work = work_ptr;
+       struct ib_umem_account_work *work =
+               container_of(_work, struct ib_umem_account_work, work);
 
        down_write(&work->mm->mmap_sem);
        work->mm->locked_vm -= work->diff;
@@ -216,7 +217,7 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem)
                return;
        }
 
-       INIT_WORK(&work->work, ib_umem_account, work);
+       INIT_WORK(&work->work, ib_umem_account);
        work->mm   = mm;
        work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
 
index 40caeb5..36620a2 100644 (file)
@@ -164,7 +164,7 @@ void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r)
  */
 void *vq_repbuf_alloc(struct c2_dev *c2dev)
 {
-       return kmem_cache_alloc(c2dev->host_msg_cache, SLAB_ATOMIC);
+       return kmem_cache_alloc(c2dev->host_msg_cache, GFP_ATOMIC);
 }
 
 /*
index 214e2fd..0d6e2c4 100644 (file)
@@ -57,7 +57,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
        struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
                                              ib_device);
 
-       av = kmem_cache_alloc(av_cache, SLAB_KERNEL);
+       av = kmem_cache_alloc(av_cache, GFP_KERNEL);
        if (!av) {
                ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p",
                         pd, ah_attr);
index 458fe19..93995b6 100644 (file)
@@ -134,7 +134,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
        if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
                return ERR_PTR(-EINVAL);
 
-       my_cq = kmem_cache_alloc(cq_cache, SLAB_KERNEL);
+       my_cq = kmem_cache_alloc(cq_cache, GFP_KERNEL);
        if (!my_cq) {
                ehca_err(device, "Out of memory for ehca_cq struct device=%p",
                         device);
index 3d1c1c5..cc47e4c 100644 (file)
@@ -108,7 +108,7 @@ static struct kmem_cache *ctblk_cache = NULL;
 
 void *ehca_alloc_fw_ctrlblock(void)
 {
-       void *ret = kmem_cache_zalloc(ctblk_cache, SLAB_KERNEL);
+       void *ret = kmem_cache_zalloc(ctblk_cache, GFP_KERNEL);
        if (!ret)
                ehca_gen_err("Out of memory for ctblk");
        return ret;
index abce676..0a5e221 100644 (file)
@@ -53,7 +53,7 @@ static struct ehca_mr *ehca_mr_new(void)
 {
        struct ehca_mr *me;
 
-       me = kmem_cache_alloc(mr_cache, SLAB_KERNEL);
+       me = kmem_cache_alloc(mr_cache, GFP_KERNEL);
        if (me) {
                memset(me, 0, sizeof(struct ehca_mr));
                spin_lock_init(&me->mrlock);
@@ -72,7 +72,7 @@ static struct ehca_mw *ehca_mw_new(void)
 {
        struct ehca_mw *me;
 
-       me = kmem_cache_alloc(mw_cache, SLAB_KERNEL);
+       me = kmem_cache_alloc(mw_cache, GFP_KERNEL);
        if (me) {
                memset(me, 0, sizeof(struct ehca_mw));
                spin_lock_init(&me->mwlock);
index 2c3cdc6..d5345e5 100644 (file)
@@ -50,7 +50,7 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
 {
        struct ehca_pd *pd;
 
-       pd = kmem_cache_alloc(pd_cache, SLAB_KERNEL);
+       pd = kmem_cache_alloc(pd_cache, GFP_KERNEL);
        if (!pd) {
                ehca_err(device, "device=%p context=%p out of memory",
                         device, context);
index 8682aa5..c6c9cef 100644 (file)
@@ -450,7 +450,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
        if (pd->uobject && udata)
                context = pd->uobject->context;
 
-       my_qp = kmem_cache_alloc(qp_cache, SLAB_KERNEL);
+       my_qp = kmem_cache_alloc(qp_cache, GFP_KERNEL);
        if (!my_qp) {
                ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
                return ERR_PTR(-ENOMEM);
index a9ddc69..340f27e 100644 (file)
@@ -1745,9 +1745,9 @@ static int ipath_assign_port(struct file *fp,
                goto done;
        }
 
-       i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE;
+       i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE;
        ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
-                  (long)fp->f_dentry->d_inode->i_rdev, i_minor);
+                  (long)fp->f_path.dentry->d_inode->i_rdev, i_minor);
 
        if (i_minor)
                ret = find_free_port(i_minor - 1, fp, uinfo);
index d9ff283..79a60f0 100644 (file)
@@ -118,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->i_private;
+       dd = file->f_path.dentry->d_inode->i_private;
 
        for (i = 0; i < NUM_COUNTERS; i++)
                counters[i] = ipath_snap_cntr(dd, i);
@@ -138,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->i_private;
+       dd = file->f_path.dentry->d_inode->i_private;
 
        guid = be64_to_cpu(dd->ipath_guid);
 
@@ -177,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->i_private;
+       dd = file->f_path.dentry->d_inode->i_private;
 
        /* so we only initialize non-zero fields. */
        memset(portinfo, 0, sizeof portinfo);
@@ -324,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
                goto bail;
        }
 
-       dd = file->f_dentry->d_inode->i_private;
+       dd = file->f_path.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;
@@ -377,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
                goto bail_tmp;
        }
 
-       dd = file->f_dentry->d_inode->i_private;
+       dd = file->f_path.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 413754b..8536aeb 100644 (file)
@@ -214,9 +214,10 @@ struct ipath_user_pages_work {
        unsigned long num_pages;
 };
 
-static void user_pages_account(void *ptr)
+static void user_pages_account(struct work_struct *_work)
 {
-       struct ipath_user_pages_work *work = ptr;
+       struct ipath_user_pages_work *work =
+               container_of(_work, struct ipath_user_pages_work, work);
 
        down_write(&work->mm->mmap_sem);
        work->mm->locked_vm -= work->num_pages;
@@ -242,7 +243,7 @@ void ipath_release_user_pages_on_close(struct page **p, size_t num_pages)
 
        goto bail;
 
-       INIT_WORK(&work->work, user_pages_account, work);
+       INIT_WORK(&work->work, user_pages_account);
        work->mm = mm;
        work->num_pages = num_pages;
 
index 57cdc1b..27caf3b 100644 (file)
@@ -189,7 +189,7 @@ int mthca_create_ah(struct mthca_dev *dev,
 on_hca_fail:
        if (ah->type == MTHCA_AH_PCI_POOL) {
                ah->av = pci_pool_alloc(dev->av_table.pool,
-                                       SLAB_ATOMIC, &ah->avdma);
+                                       GFP_ATOMIC, &ah->avdma);
                if (!ah->av)
                        return -ENOMEM;
 
index cd044ea..e948158 100644 (file)
@@ -57,7 +57,7 @@ static int catas_reset_disable;
 module_param_named(catas_reset_disable, catas_reset_disable, int, 0644);
 MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero");
 
-static void catas_reset(void *work_ptr)
+static void catas_reset(struct work_struct *work)
 {
        struct mthca_dev *dev, *tmpdev;
        LIST_HEAD(tlist);
@@ -203,7 +203,7 @@ void mthca_stop_catas_poll(struct mthca_dev *dev)
 
 int __init mthca_catas_init(void)
 {
-       INIT_WORK(&catas_work, catas_reset, NULL);
+       INIT_WORK(&catas_work, catas_reset);
 
        catas_wq = create_singlethread_workqueue("mthca_catas");
        if (!catas_wq)
index 21422a3..7ec7c4b 100644 (file)
@@ -124,7 +124,7 @@ static int mthca_query_device(struct ib_device *ibdev,
                props->max_map_per_fmr = 255;
        else
                props->max_map_per_fmr =
-                       (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1;
+                       (1 << (32 - ilog2(mdev->limits.num_mpts))) - 1;
 
        err = 0;
  out:
@@ -816,7 +816,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
                lkey = ucmd.lkey;
        }
 
-       ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status);
+       ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status);
        if (status)
                ret = -EINVAL;
 
index 33e3ba7..d844a25 100644 (file)
@@ -636,11 +636,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 
        if (mthca_is_memfree(dev)) {
                if (qp->rq.max)
-                       qp_context->rq_size_stride = long_log2(qp->rq.max) << 3;
+                       qp_context->rq_size_stride = ilog2(qp->rq.max) << 3;
                qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
 
                if (qp->sq.max)
-                       qp_context->sq_size_stride = long_log2(qp->sq.max) << 3;
+                       qp_context->sq_size_stride = ilog2(qp->sq.max) << 3;
                qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
        }
 
index 34d2c47..10684da 100644 (file)
@@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
 
        memset(context, 0, sizeof *context);
 
-       logsize = long_log2(srq->max);
+       logsize = ilog2(srq->max);
        context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
        context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
        context->db_index = cpu_to_be32(srq->db_index);
@@ -213,7 +213,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
        if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz))
                return -EINVAL;
 
-       srq->wqe_shift = long_log2(ds);
+       srq->wqe_shift = ilog2(ds);
 
        srq->srqn = mthca_alloc(&dev->srq_table.alloc);
        if (srq->srqn == -1)
index f2b6185..9954799 100644 (file)
@@ -136,11 +136,11 @@ struct ipoib_dev_priv {
        struct list_head multicast_list;
        struct rb_root multicast_tree;
 
-       struct work_struct pkey_task;
-       struct work_struct mcast_task;
+       struct delayed_work pkey_task;
+       struct delayed_work mcast_task;
        struct work_struct flush_task;
        struct work_struct restart_task;
-       struct work_struct ah_reap_task;
+       struct delayed_work ah_reap_task;
 
        struct ib_device *ca;
        u8                port;
@@ -254,13 +254,13 @@ int ipoib_add_pkey_attr(struct net_device *dev);
 
 void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                struct ipoib_ah *address, u32 qpn);
-void ipoib_reap_ah(void *dev_ptr);
+void ipoib_reap_ah(struct work_struct *work);
 
 void ipoib_flush_paths(struct net_device *dev);
 struct ipoib_dev_priv *ipoib_intf_alloc(const char *format);
 
 int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
-void ipoib_ib_dev_flush(void *dev);
+void ipoib_ib_dev_flush(struct work_struct *work);
 void ipoib_ib_dev_cleanup(struct net_device *dev);
 
 int ipoib_ib_dev_open(struct net_device *dev);
@@ -271,10 +271,10 @@ int ipoib_ib_dev_stop(struct net_device *dev);
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
 void ipoib_dev_cleanup(struct net_device *dev);
 
-void ipoib_mcast_join_task(void *dev_ptr);
+void ipoib_mcast_join_task(struct work_struct *work);
 void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb);
 
-void ipoib_mcast_restart_task(void *dev_ptr);
+void ipoib_mcast_restart_task(struct work_struct *work);
 int ipoib_mcast_start_thread(struct net_device *dev);
 int ipoib_mcast_stop_thread(struct net_device *dev, int flush);
 
@@ -312,7 +312,7 @@ void ipoib_event(struct ib_event_handler *handler,
 int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey);
 int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
 
-void ipoib_pkey_poll(void *dev);
+void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
index 8bf5e9e..f10fba5 100644 (file)
@@ -400,10 +400,11 @@ static void __ipoib_reap_ah(struct net_device *dev)
        spin_unlock_irq(&priv->tx_lock);
 }
 
-void ipoib_reap_ah(void *dev_ptr)
+void ipoib_reap_ah(struct work_struct *work)
 {
-       struct net_device *dev = dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ipoib_dev_priv *priv =
+               container_of(work, struct ipoib_dev_priv, ah_reap_task.work);
+       struct net_device *dev = priv->dev;
 
        __ipoib_reap_ah(dev);
 
@@ -613,10 +614,11 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
        return 0;
 }
 
-void ipoib_ib_dev_flush(void *_dev)
+void ipoib_ib_dev_flush(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *)_dev;
-       struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv;
+       struct ipoib_dev_priv *cpriv, *priv =
+               container_of(work, struct ipoib_dev_priv, flush_task);
+       struct net_device *dev = priv->dev;
 
        if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) {
                ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
@@ -638,14 +640,14 @@ void ipoib_ib_dev_flush(void *_dev)
         */
        if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
                ipoib_ib_dev_up(dev);
-               ipoib_mcast_restart_task(dev);
+               ipoib_mcast_restart_task(&priv->restart_task);
        }
 
        mutex_lock(&priv->vlan_mutex);
 
        /* Flush any child interfaces too */
        list_for_each_entry(cpriv, &priv->child_intfs, list)
-               ipoib_ib_dev_flush(cpriv->dev);
+               ipoib_ib_dev_flush(&cpriv->flush_task);
 
        mutex_unlock(&priv->vlan_mutex);
 }
@@ -672,10 +674,11 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
  * change async notification is available.
  */
 
-void ipoib_pkey_poll(void *dev_ptr)
+void ipoib_pkey_poll(struct work_struct *work)
 {
-       struct net_device *dev = dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ipoib_dev_priv *priv =
+               container_of(work, struct ipoib_dev_priv, pkey_task.work);
+       struct net_device *dev = priv->dev;
 
        ipoib_pkey_dev_check_presence(dev);
 
index 5ba3154..c092802 100644 (file)
@@ -940,11 +940,11 @@ static void ipoib_setup(struct net_device *dev)
        INIT_LIST_HEAD(&priv->dead_ahs);
        INIT_LIST_HEAD(&priv->multicast_list);
 
-       INIT_WORK(&priv->pkey_task,    ipoib_pkey_poll,          priv->dev);
-       INIT_WORK(&priv->mcast_task,   ipoib_mcast_join_task,    priv->dev);
-       INIT_WORK(&priv->flush_task,   ipoib_ib_dev_flush,       priv->dev);
-       INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task, priv->dev);
-       INIT_WORK(&priv->ah_reap_task, ipoib_reap_ah,            priv->dev);
+       INIT_DELAYED_WORK(&priv->pkey_task,    ipoib_pkey_poll);
+       INIT_DELAYED_WORK(&priv->mcast_task,   ipoib_mcast_join_task);
+       INIT_WORK(&priv->flush_task,   ipoib_ib_dev_flush);
+       INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
+       INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah);
 }
 
 struct ipoib_dev_priv *ipoib_intf_alloc(const char *name)
index d282d65..b04b72c 100644 (file)
@@ -399,7 +399,8 @@ static void ipoib_mcast_join_complete(int status,
                mcast->backoff = 1;
                mutex_lock(&mcast_mutex);
                if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-                       queue_work(ipoib_workqueue, &priv->mcast_task);
+                       queue_delayed_work(ipoib_workqueue,
+                                          &priv->mcast_task, 0);
                mutex_unlock(&mcast_mutex);
                complete(&mcast->done);
                return;
@@ -435,7 +436,8 @@ static void ipoib_mcast_join_complete(int status,
 
        if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
                if (status == -ETIMEDOUT)
-                       queue_work(ipoib_workqueue, &priv->mcast_task);
+                       queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+                                          0);
                else
                        queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
                                           mcast->backoff * HZ);
@@ -517,10 +519,11 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                mcast->query_id = ret;
 }
 
-void ipoib_mcast_join_task(void *dev_ptr)
+void ipoib_mcast_join_task(struct work_struct *work)
 {
-       struct net_device *dev = dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ipoib_dev_priv *priv =
+               container_of(work, struct ipoib_dev_priv, mcast_task.work);
+       struct net_device *dev = priv->dev;
 
        if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
                return;
@@ -610,7 +613,7 @@ int ipoib_mcast_start_thread(struct net_device *dev)
 
        mutex_lock(&mcast_mutex);
        if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
-               queue_work(ipoib_workqueue, &priv->mcast_task);
+               queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);
        mutex_unlock(&mcast_mutex);
 
        spin_lock_irq(&priv->lock);
@@ -818,10 +821,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
        }
 }
 
-void ipoib_mcast_restart_task(void *dev_ptr)
+void ipoib_mcast_restart_task(struct work_struct *work)
 {
-       struct net_device *dev = dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ipoib_dev_priv *priv =
+               container_of(work, struct ipoib_dev_priv, restart_task);
+       struct net_device *dev = priv->dev;
        struct dev_mc_list *mclist;
        struct ipoib_mcast *mcast, *tmcast;
        LIST_HEAD(remove_list);
index 5e12250..3aedd59 100644 (file)
@@ -114,7 +114,7 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task  *iser_ctask,
 
        if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
                mem = (void *)__get_free_pages(GFP_NOIO,
-                     long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+                     ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
        else
                mem = kmalloc(cmd_data_len, GFP_NOIO);
 
@@ -211,7 +211,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
 
        if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
                free_pages((unsigned long)mem_copy->copy_buf,
-                          long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+                          ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
        else
                kfree(mem_copy->copy_buf);
 
index 18a0000..693b770 100644 (file)
@@ -48,7 +48,7 @@
 
 static void iser_cq_tasklet_fn(unsigned long data);
 static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
-static void iser_comp_error_worker(void *data);
+static void iser_comp_error_worker(struct work_struct *work);
 
 static void iser_cq_event_callback(struct ib_event *cause, void *context)
 {
@@ -480,8 +480,7 @@ int iser_conn_init(struct iser_conn **ibconn)
        init_waitqueue_head(&ib_conn->wait);
        atomic_set(&ib_conn->post_recv_buf_count, 0);
        atomic_set(&ib_conn->post_send_buf_count, 0);
-       INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker,
-                 ib_conn);
+       INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker);
        INIT_LIST_HEAD(&ib_conn->conn_list);
        spin_lock_init(&ib_conn->lock);
 
@@ -754,9 +753,10 @@ int iser_post_send(struct iser_desc *tx_desc)
        return ret_val;
 }
 
-static void iser_comp_error_worker(void *data)
+static void iser_comp_error_worker(struct work_struct *work)
 {
-       struct iser_conn *ib_conn = data;
+       struct iser_conn *ib_conn =
+               container_of(work, struct iser_conn, comperror_work);
 
        /* getting here when the state is UP means that the conn is being *
         * terminated asynchronously from the iSCSI layer's perspective.  */
index 64ab5fc..a628959 100644 (file)
@@ -390,9 +390,10 @@ static void srp_disconnect_target(struct srp_target_port *target)
        wait_for_completion(&target->done);
 }
 
-static void srp_remove_work(void *target_ptr)
+static void srp_remove_work(struct work_struct *work)
 {
-       struct srp_target_port *target = target_ptr;
+       struct srp_target_port *target =
+               container_of(work, struct srp_target_port, work);
 
        spin_lock_irq(target->scsi_host->host_lock);
        if (target->state != SRP_TARGET_DEAD) {
@@ -575,7 +576,7 @@ err:
        spin_lock_irq(target->scsi_host->host_lock);
        if (target->state == SRP_TARGET_CONNECTING) {
                target->state = SRP_TARGET_DEAD;
-               INIT_WORK(&target->work, srp_remove_work, target);
+               INIT_WORK(&target->work, srp_remove_work);
                schedule_work(&target->work);
        }
        spin_unlock_irq(target->scsi_host->host_lock);
index a005b1d..da575de 100644 (file)
@@ -21,3 +21,4 @@ obj-$(CONFIG_INPUT_MOUSE)     += mouse/
 obj-$(CONFIG_INPUT_JOYSTICK)   += joystick/
 obj-$(CONFIG_INPUT_TOUCHSCREEN)        += touchscreen/
 obj-$(CONFIG_INPUT_MISC)       += misc/
+
index 35656ca..783b341 100644 (file)
@@ -203,7 +203,7 @@ static int erase_effect(struct input_dev *dev, int effect_id,
 }
 
 /**
- * input_ff_erase - erase an effect from device
+ * input_ff_erase - erase a force-feedback effect from device
  * @dev: input device to erase effect from
  * @effect_id: id of the ffect to be erased
  * @file: purported owner of the request
@@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(input_ff_create);
 
 /**
  * input_ff_free() - frees force feedback portion of input device
- * @dev: input device supporintg force feedback
+ * @dev: input device supporting force feedback
  *
  * This function is only needed in error path as input core will
  * automatically free force feedback structures when device is
index cd8b729..eba18b6 100644 (file)
@@ -460,7 +460,7 @@ static void ml_ff_destroy(struct ff_device *ff)
 }
 
 /**
- * input_ff_create_memless() - create memoryless FF device
+ * input_ff_create_memless() - create memoryless force-feedback device
  * @dev: input device supporting force-feedback
  * @data: driver-specific data to be passed into @play_effect
  * @play_effect: driver-specific method for playing FF effect
index a0af97e..a00fe47 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kthread.h>
 #include <linux/sched.h>       /* HZ */
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 /*#include <asm/io.h>*/
 
@@ -730,12 +731,6 @@ static int gameport_driver_remove(struct device *dev)
        return 0;
 }
 
-static struct bus_type gameport_bus = {
-       .name   = "gameport",
-       .probe  = gameport_driver_probe,
-       .remove = gameport_driver_remove,
-};
-
 static void gameport_add_driver(struct gameport_driver *drv)
 {
        int error;
@@ -781,6 +776,15 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
        return !gameport_drv->ignore;
 }
 
+static struct bus_type gameport_bus = {
+       .name           = "gameport",
+       .dev_attrs      = gameport_device_attrs,
+       .drv_attrs      = gameport_driver_attrs,
+       .match          = gameport_bus_match,
+       .probe          = gameport_driver_probe,
+       .remove         = gameport_driver_remove,
+};
+
 static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
 {
        mutex_lock(&gameport->drv_mutex);
@@ -790,7 +794,6 @@ static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *
 
 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
 {
-
        if (gameport->open) {
                if (gameport->open(gameport, mode)) {
                        return -1;
@@ -818,9 +821,6 @@ static int __init gameport_init(void)
 {
        int error;
 
-       gameport_bus.dev_attrs = gameport_device_attrs;
-       gameport_bus.drv_attrs = gameport_driver_attrs;
-       gameport_bus.match = gameport_bus_match;
        error = bus_register(&gameport_bus);
        if (error) {
                printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
index d65d810..6b4d456 100644 (file)
@@ -309,7 +309,7 @@ static int __init l4_init(void)
        int i, cards = 0;
 
        if (!request_region(L4_PORT, 1, "lightning"))
-               return -1;
+               return -EBUSY;
 
        for (i = 0; i < 2; i++)
                if (l4_add_card(i) == 0)
@@ -319,7 +319,7 @@ static int __init l4_init(void)
 
        if (!cards) {
                release_region(L4_PORT, 1);
-               return -1;
+               return -ENODEV;
        }
 
        return 0;
index 1c8c8a5..7cf2b4f 100644 (file)
@@ -37,7 +37,7 @@ static struct input_handler *input_table[8];
 
 /**
  * input_event() - report new input event
- * @handle: device that generated the event
+ * @dev: device that generated the event
  * @type: type of the event
  * @code: event code
  * @value: value of the event
@@ -900,6 +900,15 @@ struct class input_class = {
 };
 EXPORT_SYMBOL_GPL(input_class);
 
+/**
+ * input_allocate_device - allocate memory for new input device
+ *
+ * Returns prepared struct input_dev or NULL.
+ *
+ * NOTE: Use input_free_device() to free devices that have not been
+ * registered; input_unregister_device() should be used for already
+ * registered devices.
+ */
 struct input_dev *input_allocate_device(void)
 {
        struct input_dev *dev;
@@ -919,6 +928,20 @@ struct input_dev *input_allocate_device(void)
 }
 EXPORT_SYMBOL(input_allocate_device);
 
+/**
+ * input_free_device - free memory occupied by input_dev structure
+ * @dev: input device to free
+ *
+ * This function should only be used if input_register_device()
+ * was not called yet or if it failed. Once device was registered
+ * use input_unregister_device() and memory will be freed once last
+ * refrence to the device is dropped.
+ *
+ * Device should be allocated by input_allocate_device().
+ *
+ * NOTE: If there are references to the input device then memory
+ * will not be freed until last reference is dropped.
+ */
 void input_free_device(struct input_dev *dev)
 {
        if (dev) {
index 704bf70..6279ced 100644 (file)
@@ -521,11 +521,19 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
        for (i = 0; i < 2; i++)
                if (port->adi[i].length > 0) {
                        adi_init_center(port->adi + i);
-                       input_register_device(port->adi[i].dev);
+                       err = input_register_device(port->adi[i].dev);
+                       if (err)
+                               goto fail3;
                }
 
        return 0;
 
+ fail3: while (--i >= 0) {
+               if (port->adi[i].length > 0) {
+                       input_unregister_device(port->adi[i].dev);
+                       port->adi[i].dev = NULL;
+               }
+       }
  fail2:        for (i = 0; i < 2; i++)
                if (port->adi[i].dev)
                        input_free_device(port->adi[i].dev);
index 650acf3..e608691 100644 (file)
@@ -147,7 +147,11 @@ static int __init amijoy_init(void)
                        amijoy_dev[i]->absmax[ABS_X + j] = 1;
                }
 
-               input_register_device(amijoy_dev[i]);
+               err = input_register_device(amijoy_dev[i]);
+               if (err) {
+                       input_free_device(amijoy_dev[i]);
+                       goto fail;
+               }
        }
        return 0;
 
index e9a02db..7ef6845 100644 (file)
@@ -434,6 +434,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
 {
        struct input_dev *input_dev;
        int i, j, t, v, w, x, y, z;
+       int error;
 
        analog_name(analog);
        snprintf(analog->phys, sizeof(analog->phys),
@@ -505,7 +506,11 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
 
        analog_decode(analog, port->axes, port->initial, port->buttons);
 
-       input_register_device(analog->dev);
+       error = input_register_device(analog->dev);
+       if (error) {
+               input_free_device(analog->dev);
+               return error;
+       }
 
        return 0;
 }
@@ -668,7 +673,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
        return 0;
 
  fail3: while (--i >= 0)
-               input_unregister_device(port->analog[i].dev);
+               if (port->analog[i].mask)
+                       input_unregister_device(port->analog[i].dev);
  fail2:        gameport_close(gameport);
  fail1:        gameport_set_drvdata(gameport, NULL);
        kfree(port);
index d5e42eb..034ec39 100644 (file)
@@ -223,12 +223,15 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
                for (j = 0; cobra_btn[j]; j++)
                        set_bit(cobra_btn[j], input_dev->keybit);
 
-               input_register_device(cobra->dev[i]);
+               err = input_register_device(cobra->dev[i]);
+               if (err)
+                       goto fail4;
        }
 
        return 0;
 
- fail3:        for (i = 0; i < 2; i++)
+ fail4:        input_free_device(cobra->dev[i]);
+ fail3:        while (--i >= 0)
                if (cobra->dev[i])
                        input_unregister_device(cobra->dev[i]);
  fail2:        gameport_close(gameport);
index e4a699f..bacbab5 100644 (file)
@@ -341,7 +341,9 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
                input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
        }
 
-       input_register_device(gf2k->dev);
+       err = input_register_device(gf2k->dev);
+       if (err)
+               goto fail2;
 
        return 0;
 
index 6243894..8120a9c 100644 (file)
@@ -423,7 +423,10 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
 
                if (!port->registered) {
                        dbg("New Grip pad in multiport slot %d.\n", slot);
-                       register_slot(slot, grip);
+                       if (register_slot(slot, grip)) {
+                               port->mode = GRIP_MODE_RESET;
+                               port->dirty = 0;
+                       }
                }
                return flags;
        }
@@ -585,6 +588,7 @@ static int register_slot(int slot, struct grip_mp *grip)
        struct grip_port *port = grip->port[slot];
        struct input_dev *input_dev;
        int j, t;
+       int err;
 
        port->dev = input_dev = input_allocate_device();
        if (!input_dev)
@@ -610,7 +614,12 @@ static int register_slot(int slot, struct grip_mp *grip)
                if (t > 0)
                        set_bit(t, input_dev->keybit);
 
-       input_register_device(port->dev);
+       err = input_register_device(port->dev);
+       if (err) {
+               input_free_device(port->dev);
+               return err;
+       }
+
        port->registered = 1;
 
        if (port->dirty)                    /* report initial state, if any */
index 840ed9b..dbc5d92 100644 (file)
@@ -250,7 +250,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
        for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
                set_bit(t, input_dev->keybit);
 
-       input_register_device(guillemot->dev);
+       err = input_register_device(guillemot->dev);
+       if (err)
+               goto fail2;
 
        return 0;
 
index 24c684b..3393a37 100644 (file)
@@ -325,8 +325,8 @@ int iforce_init_device(struct iforce *iforce)
 
        if (i == 20) { /* 5 seconds */
                printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
-               input_free_device(input_dev);
-               return -ENODEV;
+               error = -ENODEV;
+               goto fail;
        }
 
 /*
@@ -439,10 +439,8 @@ int iforce_init_device(struct iforce *iforce)
                        set_bit(iforce->type->ff[i], input_dev->ffbit);
 
                error = input_ff_create(input_dev, ff_effects);
-               if (error) {
-                       input_free_device(input_dev);
-                       return error;
-               }
+               if (error)
+                       goto fail;
 
                ff = input_dev->ff;
                ff->upload = iforce_upload_effect;
@@ -455,22 +453,35 @@ int iforce_init_device(struct iforce *iforce)
  * Register input device.
  */
 
-       input_register_device(iforce->dev);
+       error = input_register_device(iforce->dev);
+       if (error)
+               goto fail;
 
        printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
 
        return 0;
+
+ fail: input_free_device(input_dev);
+       return error;
 }
 
 static int __init iforce_init(void)
 {
+       int err = 0;
+
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
-       usb_register(&iforce_usb_driver);
+       err = usb_register(&iforce_usb_driver);
+       if (err)
+               return err;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-       serio_register_driver(&iforce_serio_drv);
+       err = serio_register_driver(&iforce_serio_drv);
+#ifdef CONFIG_JOYSTICK_IFORCE_USB
+       if (err)
+               usb_deregister(&iforce_usb_driver);
 #endif
-       return 0;
+#endif
+       return err;
 }
 
 static void __exit iforce_exit(void)
index ca08f45..ec4be53 100644 (file)
@@ -141,21 +141,19 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
        serio_set_drvdata(serio, iforce);
 
        err = serio_open(serio, drv);
-       if (err) {
-               serio_set_drvdata(serio, NULL);
-               kfree(iforce);
-               return err;
-       }
+       if (err)
+               goto fail1;
 
        err = iforce_init_device(iforce);
-       if (err) {
-               serio_close(serio);
-               serio_set_drvdata(serio, NULL);
-               kfree(iforce);
-               return -ENODEV;
-       }
+       if (err)
+               goto fail2;
 
        return 0;
+
+ fail2:        serio_close(serio);
+ fail1:        serio_set_drvdata(serio, NULL);
+       kfree(iforce);
+       return err;
 }
 
 static void iforce_serio_disconnect(struct serio *serio)
index bbfeb9c..fec8b3d 100644 (file)
@@ -283,7 +283,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
        for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
                set_bit(t, input_dev->keybit);
 
-       input_register_device(interact->dev);
+       err = input_register_device(interact->dev);
+       if (err)
+               goto fail2;
 
        return 0;
 
index e3d1944..4112789 100644 (file)
@@ -157,7 +157,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
        magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!magellan || !input_dev)
-               goto fail;
+               goto fail1;
 
        magellan->dev = input_dev;
        snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys);
@@ -183,13 +183,17 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(magellan->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(magellan->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(magellan);
        return err;
 }
@@ -227,8 +231,7 @@ static struct serio_driver magellan_drv = {
 
 static int __init magellan_init(void)
 {
-       serio_register_driver(&magellan_drv);
-       return 0;
+       return serio_register_driver(&magellan_drv);
 }
 
 static void __exit magellan_exit(void)
index 2a9808c..08bf113 100644 (file)
@@ -215,7 +215,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
        spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!spaceball || !input_dev)
-               goto fail;
+               goto fail1;
 
        spaceball->dev = input_dev;
        snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys);
@@ -252,13 +252,17 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(spaceball->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(spaceball->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(spaceball);
        return err;
 }
@@ -296,8 +300,7 @@ static struct serio_driver spaceball_drv = {
 
 static int __init spaceball_init(void)
 {
-       serio_register_driver(&spaceball_drv);
-       return 0;
+       return serio_register_driver(&spaceball_drv);
 }
 
 static void __exit spaceball_exit(void)
index c4db024..c9c7921 100644 (file)
@@ -172,7 +172,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
        spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!spaceorb || !input_dev)
-               goto fail;
+               goto fail1;
 
        spaceorb->dev = input_dev;
        snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys);
@@ -198,13 +198,17 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(spaceorb->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(spaceorb->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(spaceorb);
        return err;
 }
@@ -242,8 +246,7 @@ static struct serio_driver spaceorb_drv = {
 
 static int __init spaceorb_init(void)
 {
-       serio_register_driver(&spaceorb_drv);
-       return 0;
+       return serio_register_driver(&spaceorb_drv);
 }
 
 static void __exit spaceorb_exit(void)
index 1ffb032..ecb0916 100644 (file)
@@ -143,7 +143,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
        stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!stinger || !input_dev)
-               goto fail;
+               goto fail1;
 
        stinger->dev = input_dev;
        snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys);
@@ -168,13 +168,17 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(stinger->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(stinger->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(stinger);
        return err;
 }
@@ -212,8 +216,7 @@ static struct serio_driver stinger_drv = {
 
 static int __init stinger_init(void)
 {
-       serio_register_driver(&stinger_drv);
-       return 0;
+       return serio_register_driver(&stinger_drv);
 }
 
 static void __exit stinger_exit(void)
index 49085df..9cf17d6 100644 (file)
@@ -194,7 +194,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
        twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!twidjoy || !input_dev)
-               goto fail;
+               goto fail1;
 
        twidjoy->dev = input_dev;
        snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys);
@@ -221,13 +221,17 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(twidjoy->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(twidjoy->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(twidjoy);
        return err;
 }
@@ -265,8 +269,7 @@ static struct serio_driver twidjoy_drv = {
 
 static int __init twidjoy_init(void)
 {
-       serio_register_driver(&twidjoy_drv);
-       return 0;
+       return serio_register_driver(&twidjoy_drv);
 }
 
 static void __exit twidjoy_exit(void)
index 35edea1..29d339a 100644 (file)
@@ -149,7 +149,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
        warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!warrior || !input_dev)
-               goto fail;
+               goto fail1;
 
        warrior->dev = input_dev;
        snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys);
@@ -176,13 +176,17 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(warrior->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(warrior->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(warrior);
        return err;
 }
@@ -220,8 +224,7 @@ static struct serio_driver warrior_drv = {
 
 static int __init warrior_init(void)
 {
-       serio_register_driver(&warrior_drv);
-       return 0;
+       return serio_register_driver(&warrior_drv);
 }
 
 static void __exit warrior_exit(void)
index 81a333f..049f2f5 100644 (file)
@@ -203,4 +203,15 @@ config KEYBOARD_OMAP
          To compile this driver as a module, choose M here: the
          module will be called omap-keypad.
 
+config KEYBOARD_AAED2000
+       tristate "AAED-2000 keyboard"
+       depends on MACH_AAED2000
+       default y
+       help
+         Say Y here to enable the keyboard on the Agilent AAED-2000
+         development board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aaed2000_kbd.
+
 endif
index 4c79e7b..5687979 100644 (file)
@@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_SPITZ)          += spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
 obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
+obj-$(CONFIG_KEYBOARD_AAED2000)         += aaed2000_kbd.o
 
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
new file mode 100644 (file)
index 0000000..65fcb6a
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  Keyboard driver for the AAED-2000 dev board
+ *
+ *  Copyright (c) 2006 Nicolas Bellido Y Ortega
+ *
+ *  Based on corgikbd.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/aaed2000.h>
+
+#define KB_ROWS                        12
+#define KB_COLS                        8
+#define KB_ROWMASK(r)          (1 << (r))
+#define SCANCODE(r,c)          (((c) * KB_ROWS) + (r))
+#define NR_SCANCODES           (KB_COLS * KB_ROWS)
+
+#define SCAN_INTERVAL          (50) /* ms */
+#define KB_ACTIVATE_DELAY      (20) /* us */
+
+static unsigned char aaedkbd_keycode[NR_SCANCODES] = {
+       KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0,
+       KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0,
+       KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0,
+       KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0,
+       KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK,
+       KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB,
+       KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE,
+       0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL
+};
+
+struct aaedkbd {
+       unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)];
+       struct input_dev *input;
+       struct work_struct workq;
+       int kbdscan_state[KB_COLS];
+       int kbdscan_count[KB_COLS];
+};
+
+#define KBDSCAN_STABLE_COUNT 2
+
+static void aaedkbd_report_col(struct aaedkbd *aaedkbd,
+                               unsigned int col, unsigned int rowd)
+{
+       unsigned int scancode, pressed;
+       unsigned int row;
+
+       for (row = 0; row < KB_ROWS; row++) {
+               scancode = SCANCODE(row, col);
+               pressed = rowd & KB_ROWMASK(row);
+
+               input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed);
+       }
+}
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void aaedkbd_work(void *data)
+{
+       struct aaedkbd *aaedkbd = data;
+       unsigned int col, rowd;
+
+       col = 0;
+       do {
+               AAEC_GPIO_KSCAN = col + 8;
+               udelay(KB_ACTIVATE_DELAY);
+               rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN;
+
+               if (rowd != aaedkbd->kbdscan_state[col]) {
+                       aaedkbd->kbdscan_count[col] = 0;
+                       aaedkbd->kbdscan_state[col] = rowd;
+               } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) {
+                       aaedkbd_report_col(aaedkbd, col, rowd);
+                       col++;
+               }
+       } while (col < KB_COLS);
+
+       AAEC_GPIO_KSCAN = 0x07;
+       input_sync(aaedkbd->input);
+
+       schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
+}
+
+static int aaedkbd_open(struct input_dev *indev)
+{
+       struct aaedkbd *aaedkbd = indev->private;
+
+       schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
+
+       return 0;
+}
+
+static void aaedkbd_close(struct input_dev *indev)
+{
+       struct aaedkbd *aaedkbd = indev->private;
+
+       cancel_delayed_work(&aaedkbd->workq);
+       flush_scheduled_work();
+}
+
+static int __devinit aaedkbd_probe(struct platform_device *pdev)
+{
+       struct aaedkbd *aaedkbd;
+       struct input_dev *input_dev;
+       int i;
+       int error;
+
+       aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!aaedkbd || !input_dev) {
+               error = -ENOMEM;
+               goto fail;
+       }
+
+       platform_set_drvdata(pdev, aaedkbd);
+
+       aaedkbd->input = input_dev;
+
+       /* Init keyboard rescan workqueue */
+       INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd);
+
+       memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode));
+
+       input_dev->name = "AAED-2000 Keyboard";
+       input_dev->phys = "aaedkbd/input0";
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
+       input_dev->cdev.dev = &pdev->dev;
+       input_dev->private = aaedkbd;
+
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+       input_dev->keycode = aaedkbd->keycode;
+       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode);
+
+       for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++)
+               set_bit(aaedkbd->keycode[i], input_dev->keybit);
+       clear_bit(0, input_dev->keybit);
+
+       input_dev->open = aaedkbd_open;
+       input_dev->close = aaedkbd_close;
+
+       error = input_register_device(aaedkbd->input);
+       if (error)
+               goto fail;
+
+       return 0;
+
+ fail: kfree(aaedkbd);
+       input_free_device(input_dev);
+       return error;
+}
+
+static int __devexit aaedkbd_remove(struct platform_device *pdev)
+{
+       struct aaedkbd *aaedkbd = platform_get_drvdata(pdev);
+
+       input_unregister_device(aaedkbd->input);
+       kfree(aaedkbd);
+
+       return 0;
+}
+
+static struct platform_driver aaedkbd_driver = {
+       .probe          = aaedkbd_probe,
+       .remove         = __devexit_p(aaedkbd_remove),
+       .driver         = {
+               .name   = "aaed2000-keyboard",
+       },
+};
+
+static int __init aaedkbd_init(void)
+{
+       return platform_driver_register(&aaedkbd_driver);
+}
+
+static void __exit aaedkbd_exit(void)
+{
+       platform_driver_unregister(&aaedkbd_driver);
+}
+
+module_init(aaedkbd_init);
+module_exit(aaedkbd_exit);
+
+MODULE_AUTHOR("Nicolas Bellido Y Ortega");
+MODULE_DESCRIPTION("AAED-2000 Keyboard Driver");
+MODULE_LICENSE("GPLv2");
index 8abdbd0..16583d7 100644 (file)
@@ -190,7 +190,7 @@ static int __init amikbd_init(void)
        int i, j;
 
        if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
-               return -EIO;
+               return -ENODEV;
 
        if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
                return -EBUSY;
@@ -198,8 +198,8 @@ static int __init amikbd_init(void)
        amikbd_dev = input_allocate_device();
        if (!amikbd_dev) {
                printk(KERN_ERR "amikbd: not enough memory for input device\n");
-               release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto fail1;
        }
 
        amikbd_dev->name = "Amiga Keyboard";
@@ -231,10 +231,22 @@ static int __init amikbd_init(void)
                memcpy(key_maps[i], temp_map, sizeof(temp_map));
        }
        ciaa.cra &= ~0x41;       /* serial data in, turn off TA */
-       request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
+       if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
+                       amikbd_interrupt)) {
+               err = -EBUSY;
+               goto fail2;
+       }
+
+       err = input_register_device(amikbd_dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(amikbd_dev);
        return 0;
+
+ fail3:        free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
+ fail2:        input_free_device(amikbd_dev);
+ fail1:        release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+       return err;
 }
 
 static void __exit amikbd_exit(void)
index cbb9366..c621a91 100644 (file)
@@ -567,9 +567,9 @@ static int atkbd_set_leds(struct atkbd *atkbd)
  * interrupt context.
  */
 
-static void atkbd_event_work(void *data)
+static void atkbd_event_work(struct work_struct *work)
 {
-       struct atkbd *atkbd = data;
+       struct atkbd *atkbd = container_of(work, struct atkbd, event_work);
 
        mutex_lock(&atkbd->event_mutex);
 
@@ -939,11 +939,11 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
        atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
        dev = input_allocate_device();
        if (!atkbd || !dev)
-               goto fail;
+               goto fail1;
 
        atkbd->dev = dev;
        ps2_init(&atkbd->ps2dev, serio);
-       INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
+       INIT_WORK(&atkbd->event_work, atkbd_event_work);
        mutex_init(&atkbd->event_mutex);
 
        switch (serio->id.type) {
@@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
 
        if (atkbd->write) {
 
                if (atkbd_probe(atkbd)) {
-                       serio_close(serio);
                        err = -ENODEV;
-                       goto fail;
+                       goto fail3;
                }
 
                atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
        atkbd_set_keycode_table(atkbd);
        atkbd_set_device_attrs(atkbd);
 
-       sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+       err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+       if (err)
+               goto fail3;
 
        atkbd_enable(atkbd);
 
-       input_register_device(atkbd->dev);
+       err = input_register_device(atkbd->dev);
+       if (err)
+               goto fail4;
 
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(dev);
+ fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(dev);
        kfree(atkbd);
        return err;
 }
@@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
 {
-       struct input_dev *new_dev;
+       struct input_dev *old_dev, *new_dev;
        unsigned long value;
        char *rest;
+       int err;
+       unsigned char old_extra, old_set;
 
        if (!atkbd->write)
                return -EIO;
@@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
        if (atkbd->extra != value) {
                /*
                 * Since device's properties will change we need to
-                * unregister old device. But allocate new one first
-                * to make sure we have it.
+                * unregister old device. But allocate and register
+                * new one first to make sure we have it.
                 */
-               if (!(new_dev = input_allocate_device()))
+               old_dev = atkbd->dev;
+               old_extra = atkbd->extra;
+               old_set = atkbd->set;
+
+               new_dev = input_allocate_device();
+               if (!new_dev)
                        return -ENOMEM;
-               input_unregister_device(atkbd->dev);
+
                atkbd->dev = new_dev;
                atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
                atkbd_activate(atkbd);
+               atkbd_set_keycode_table(atkbd);
                atkbd_set_device_attrs(atkbd);
-               input_register_device(atkbd->dev);
+
+               err = input_register_device(atkbd->dev);
+               if (err) {
+                       input_free_device(new_dev);
+
+                       atkbd->dev = old_dev;
+                       atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+                       atkbd_set_keycode_table(atkbd);
+                       atkbd_set_device_attrs(atkbd);
+
+                       return err;
+               }
+               input_unregister_device(old_dev);
+
        }
        return count;
 }
@@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
 {
-       struct input_dev *new_dev;
+       struct input_dev *old_dev, *new_dev;
        unsigned long value;
        char *rest;
+       int err;
+       unsigned char old_scroll;
 
        value = simple_strtoul(buf, &rest, 10);
        if (*rest || value > 1)
                return -EINVAL;
 
        if (atkbd->scroll != value) {
-               if (!(new_dev = input_allocate_device()))
+               old_dev = atkbd->dev;
+               old_scroll = atkbd->scroll;
+
+               new_dev = input_allocate_device();
+               if (!new_dev)
                        return -ENOMEM;
-               input_unregister_device(atkbd->dev);
+
                atkbd->dev = new_dev;
                atkbd->scroll = value;
                atkbd_set_keycode_table(atkbd);
                atkbd_set_device_attrs(atkbd);
-               input_register_device(atkbd->dev);
+
+               err = input_register_device(atkbd->dev);
+               if (err) {
+                       input_free_device(new_dev);
+
+                       atkbd->scroll = old_scroll;
+                       atkbd->dev = old_dev;
+                       atkbd_set_keycode_table(atkbd);
+                       atkbd_set_device_attrs(atkbd);
+
+                       return err;
+               }
+               input_unregister_device(old_dev);
        }
        return count;
 }
@@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 {
-       struct input_dev *new_dev;
+       struct input_dev *old_dev, *new_dev;
        unsigned long value;
        char *rest;
+       int err;
+       unsigned char old_set, old_extra;
 
        if (!atkbd->write)
                return -EIO;
@@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
                return -EINVAL;
 
        if (atkbd->set != value) {
-               if (!(new_dev = input_allocate_device()))
+               old_dev = atkbd->dev;
+               old_extra = atkbd->extra;
+               old_set = atkbd->set;
+
+               new_dev = input_allocate_device();
+               if (!new_dev)
                        return -ENOMEM;
-               input_unregister_device(atkbd->dev);
+
                atkbd->dev = new_dev;
                atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
                atkbd_activate(atkbd);
                atkbd_set_keycode_table(atkbd);
                atkbd_set_device_attrs(atkbd);
-               input_register_device(atkbd->dev);
+
+               err = input_register_device(atkbd->dev);
+               if (err) {
+                       input_free_device(new_dev);
+
+                       atkbd->dev = old_dev;
+                       atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+                       atkbd_set_keycode_table(atkbd);
+                       atkbd_set_device_attrs(atkbd);
+
+                       return err;
+               }
+               input_unregister_device(old_dev);
        }
        return count;
 }
@@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
 {
-       struct input_dev *new_dev;
+       struct input_dev *old_dev, *new_dev;
        unsigned long value;
        char *rest;
+       int err;
+       unsigned char old_softrepeat, old_softraw;
 
        if (!atkbd->write)
                return -EIO;
@@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
                return -EINVAL;
 
        if (atkbd->softrepeat != value) {
-               if (!(new_dev = input_allocate_device()))
+               old_dev = atkbd->dev;
+               old_softrepeat = atkbd->softrepeat;
+               old_softraw = atkbd->softraw;
+
+               new_dev = input_allocate_device();
+               if (!new_dev)
                        return -ENOMEM;
-               input_unregister_device(atkbd->dev);
+
                atkbd->dev = new_dev;
                atkbd->softrepeat = value;
                if (atkbd->softrepeat)
                        atkbd->softraw = 1;
                atkbd_set_device_attrs(atkbd);
-               input_register_device(atkbd->dev);
+
+               err = input_register_device(atkbd->dev);
+               if (err) {
+                       input_free_device(new_dev);
+
+                       atkbd->dev = old_dev;
+                       atkbd->softrepeat = old_softrepeat;
+                       atkbd->softraw = old_softraw;
+                       atkbd_set_device_attrs(atkbd);
+
+                       return err;
+               }
+               input_unregister_device(old_dev);
        }
        return count;
 }
@@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
 
 static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
 {
-       struct input_dev *new_dev;
+       struct input_dev *old_dev, *new_dev;
        unsigned long value;
        char *rest;
+       int err;
+       unsigned char old_softraw;
 
        value = simple_strtoul(buf, &rest, 10);
        if (*rest || value > 1)
                return -EINVAL;
 
        if (atkbd->softraw != value) {
-               if (!(new_dev = input_allocate_device()))
+               old_dev = atkbd->dev;
+               old_softraw = atkbd->softraw;
+
+               new_dev = input_allocate_device();
+               if (!new_dev)
                        return -ENOMEM;
-               input_unregister_device(atkbd->dev);
+
                atkbd->dev = new_dev;
                atkbd->softraw = value;
                atkbd_set_device_attrs(atkbd);
-               input_register_device(atkbd->dev);
+
+               err = input_register_device(atkbd->dev);
+               if (err) {
+                       input_free_device(new_dev);
+
+                       atkbd->dev = old_dev;
+                       atkbd->softraw = old_softraw;
+                       atkbd_set_device_attrs(atkbd);
+
+                       return err;
+               }
+               input_unregister_device(old_dev);
        }
        return count;
 }
@@ -1290,8 +1389,7 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
 
 static int __init atkbd_init(void)
 {
-       serio_register_driver(&atkbd_drv);
-       return 0;
+       return serio_register_driver(&atkbd_drv);
 }
 
 static void __exit atkbd_exit(void)
index befdd60..1016c94 100644 (file)
@@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev)
 {
        struct corgikbd *corgikbd;
        struct input_dev *input_dev;
-       int i;
+       int i, err = -ENOMEM;
 
        corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!corgikbd || !input_dev) {
-               kfree(corgikbd);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
+       if (!corgikbd || !input_dev)
+               goto fail;
 
        platform_set_drvdata(pdev, corgikbd);
 
@@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        set_bit(SW_TABLET_MODE, input_dev->swbit);
        set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
-       input_register_device(corgikbd->input);
+       err = input_register_device(corgikbd->input);
+       if (err)
+               goto fail;
 
        mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
@@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
 
        return 0;
+
+ fail: input_free_device(input_dev);
+       kfree(corgikbd);
+       return err;
 }
 
 static int corgikbd_remove(struct platform_device *pdev)
index e774dd3..7cc9728 100644 (file)
@@ -381,8 +381,7 @@ struct serio_driver hil_kbd_serio_drv = {
 
 static int __init hil_kbd_init(void)
 {
-       serio_register_driver(&hil_kbd_serio_drv);
-        return 0;
+       return serio_register_driver(&hil_kbd_serio_drv);
 }
                 
 static void __exit hil_kbd_exit(void)
index 979b93e..3d4d0a0 100644 (file)
@@ -572,9 +572,9 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
  * were in.
  */
 static void
-lkkbd_reinit (void *data)
+lkkbd_reinit (struct work_struct *work)
 {
-       struct lkkbd *lk = data;
+       struct lkkbd *lk = container_of(work, struct lkkbd, tq);
        int division;
        unsigned char leds_on = 0;
        unsigned char leds_off = 0;
@@ -646,12 +646,12 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
        input_dev = input_allocate_device ();
        if (!lk || !input_dev) {
                err = -ENOMEM;
-               goto fail;
+               goto fail1;
        }
 
        lk->serio = serio;
        lk->dev = input_dev;
-       INIT_WORK (&lk->tq, lkkbd_reinit, lk);
+       INIT_WORK (&lk->tq, lkkbd_reinit);
        lk->bell_volume = bell_volume;
        lk->keyclick_volume = keyclick_volume;
        lk->ctrlclick_volume = ctrlclick_volume;
@@ -691,15 +691,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 
        err = serio_open (serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device (lk->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device (lk->dev);
        lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
 
        return 0;
 
- fail: serio_set_drvdata (serio, NULL);
-       input_free_device (input_dev);
+ fail3:        serio_close (serio);
+ fail2:        serio_set_drvdata (serio, NULL);
+ fail1:        input_free_device (input_dev);
        kfree (lk);
        return err;
 }
@@ -749,8 +753,7 @@ static struct serio_driver lkkbd_drv = {
 static int __init
 lkkbd_init (void)
 {
-       serio_register_driver(&lkkbd_drv);
-       return 0;
+       return serio_register_driver(&lkkbd_drv);
 }
 
 static void __exit
index 5788dbc..2ade518 100644 (file)
@@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev)
 {
        struct locomokbd *locomokbd;
        struct input_dev *input_dev;
-       int i, ret;
+       int i, err;
 
        locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!locomokbd || !input_dev) {
-               ret = -ENOMEM;
-               goto free;
+               err = -ENOMEM;
+               goto err_free_mem;
        }
 
        /* try and claim memory region */
        if (!request_mem_region((unsigned long) dev->mapbase,
                                dev->length,
                                LOCOMO_DRIVER_NAME(dev))) {
-               ret = -EBUSY;
+               err = -EBUSY;
                printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
-               goto free;
+               goto err_free_mem;
        }
 
        locomokbd->ldev = dev;
@@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev)
        clear_bit(0, input_dev->keybit);
 
        /* attempt to get the interrupt */
-       ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
-       if (ret) {
+       err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
+       if (err) {
                printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
-               goto out;
+               goto err_release_region;
        }
 
-       input_register_device(locomokbd->input);
+       err = input_register_device(locomokbd->input);
+       if (err)
+               goto err_free_irq;
 
        return 0;
 
-out:
+ err_free_irq:
+       free_irq(dev->irq[0], locomokbd);
+ err_release_region:
        release_mem_region((unsigned long) dev->mapbase, dev->length);
        locomo_set_drvdata(dev, NULL);
-free:
+ err_free_mem:
        input_free_device(input_dev);
        kfree(locomokbd);
 
-       return ret;
+       return err;
 }
 
 static int locomokbd_remove(struct locomo_dev *dev)
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
deleted file mode 100644 (file)
index cc6aaf9..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *     $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
- *     SEGA Dreamcast keyboard driver
- *     Based on drivers/usb/usbkbd.c
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/maple.h>
-
-MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
-MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
-MODULE_LICENSE("GPL");
-
-static unsigned char dc_kbd_keycode[256] = {
-         0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
-        50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
-         4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-        27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
-        65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
-       105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
-        72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
-       191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
-       115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
-       122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
-       150,158,159,128,136,177,178,176,142,152,173,140
-};
-
-
-struct dc_kbd {
-       struct input_dev *dev;
-       unsigned char new[8];
-       unsigned char old[8];
-};
-
-
-static void dc_scan_kbd(struct dc_kbd *kbd)
-{
-       int i;
-       struct input_dev *dev = kbd->dev;
-
-       for (i = 0; i < 8; i++)
-               input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
-       for (i = 2; i < 8; i++) {
-
-               if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
-                       if (dc_kbd_keycode[kbd->old[i]])
-                               input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
-                       else
-                               printk("Unknown key (scancode %#x) released.",
-                                      kbd->old[i]);
-               }
-
-               if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
-                       if(dc_kbd_keycode[kbd->new[i]])
-                               input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
-                       else
-                               printk("Unknown key (scancode %#x) pressed.",
-                                      kbd->new[i]);
-               }
-       }
-
-       input_sync(dev);
-
-       memcpy(kbd->old, kbd->new, 8);
-}
-
-
-static void dc_kbd_callback(struct mapleq *mq)
-{
-       struct maple_device *mapledev = mq->dev;
-       struct dc_kbd *kbd = mapledev->private_data;
-       unsigned long *buf = mq->recvbuf;
-
-       if (buf[1] == mapledev->function) {
-               memcpy(kbd->new, buf + 2, 8);
-               dc_scan_kbd(kbd);
-       }
-}
-
-static int dc_kbd_connect(struct maple_device *dev)
-{
-       struct dc_kbd *kbd;
-       struct input_dev *input_dev;
-       unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
-       int i;
-
-       dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!kbd || !input_dev) {
-               kfree(kbd);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
-
-       kbd->dev = input_dev;
-
-       input_dev->name = dev->product_name;
-       input_dev->id.bustype = BUS_MAPLE;
-       input_dev->private = kbd;
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-       for (i = 0; i < 255; i++)
-               set_bit(dc_kbd_keycode[i], input_dev->keybit);
-       clear_bit(0, input_dev->keybit);
-
-       input_register_device(kbd->dev);
-
-       maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
-       return 0;
-}
-
-
-static void dc_kbd_disconnect(struct maple_device *dev)
-{
-       struct dc_kbd *kbd = dev->private_data;
-
-       input_unregister_device(kbd->dev);
-       kfree(kbd);
-}
-
-
-static struct maple_driver dc_kbd_driver = {
-       .function =     MAPLE_FUNC_KEYBOARD,
-       .name =         "Dreamcast keyboard",
-       .connect =      dc_kbd_connect,
-       .disconnect =   dc_kbd_disconnect,
-};
-
-
-static int __init dc_kbd_init(void)
-{
-       maple_register_driver(&dc_kbd_driver);
-       return 0;
-}
-
-
-static void __exit dc_kbd_exit(void)
-{
-       maple_unregister_driver(&dc_kbd_driver);
-}
-
-
-module_init(dc_kbd_init);
-module_exit(dc_kbd_exit);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 9282e4e..aa29b50 100644 (file)
@@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
        nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!nkbd || !input_dev)
-               goto fail;
+               goto fail1;
 
        nkbd->serio = serio;
        nkbd->dev = input_dev;
@@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(nkbd->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(nkbd->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(nkbd);
        return err;
 }
@@ -165,8 +169,7 @@ static struct serio_driver nkbd_drv = {
 
 static int __init nkbd_init(void)
 {
-       serio_register_driver(&nkbd_drv);
-       return 0;
+       return serio_register_driver(&nkbd_drv);
 }
 
 static void __exit nkbd_exit(void)
index 28b2748..8a2166c 100644 (file)
@@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 {
        struct spitzkbd *spitzkbd;
        struct input_dev *input_dev;
-       int i;
+       int i, err = -ENOMEM;
 
        spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
-       if (!spitzkbd)
-               return -ENOMEM;
-
        input_dev = input_allocate_device();
-       if (!input_dev) {
-               kfree(spitzkbd);
-               return -ENOMEM;
-       }
+       if (!spitzkbd || !input_dev)
+               goto fail;
 
        platform_set_drvdata(dev, spitzkbd);
        strcpy(spitzkbd->phys, "spitzkbd/input0");
@@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        set_bit(SW_TABLET_MODE, input_dev->swbit);
        set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
-       input_register_device(input_dev);
+       err = input_register_device(input_dev);
+       if (err)
+               goto fail;
 
        mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
@@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                    "Spitzkbd SWB", spitzkbd);
-       request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+       request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
                    IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                    "Spitzkbd HP", spitzkbd);
 
-       printk(KERN_INFO "input: Spitz Keyboard Registered\n");
-
        return 0;
+
+ fail: input_free_device(input_dev);
+       kfree(spitzkbd);
+       return err;
 }
 
 static int spitzkbd_remove(struct platform_device *dev)
@@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = {
        .resume         = spitzkbd_resume,
        .driver         = {
                .name   = "spitz-keyboard",
+               .owner  = THIS_MODULE,
        },
 };
 
index e60937d..f7b5c5b 100644 (file)
@@ -173,8 +173,7 @@ static struct serio_driver skbd_drv = {
 
 static int __init skbd_init(void)
 {
-       serio_register_driver(&skbd_drv);
-       return 0;
+       return serio_register_driver(&skbd_drv);
 }
 
 static void __exit skbd_exit(void)
index cac4781..3826db9 100644 (file)
@@ -208,9 +208,9 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
  * were in.
  */
 
-static void sunkbd_reinit(void *data)
+static void sunkbd_reinit(struct work_struct *work)
 {
-       struct sunkbd *sunkbd = data;
+       struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
 
        wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
 
@@ -243,23 +243,23 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
        sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!sunkbd || !input_dev)
-               goto fail;
+               goto fail1;
 
        sunkbd->serio = serio;
        sunkbd->dev = input_dev;
        init_waitqueue_head(&sunkbd->wait);
-       INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
+       INIT_WORK(&sunkbd->tq, sunkbd_reinit);
        snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
 
        serio_set_drvdata(serio, sunkbd);
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
 
        if (sunkbd_initialize(sunkbd) < 0) {
-               serio_close(serio);
-               goto fail;
+               err = -ENODEV;
+               goto fail3;
        }
 
        snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type);
@@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
        clear_bit(0, input_dev->keybit);
 
        sunkbd_enable(sunkbd, 1);
-       input_register_device(sunkbd->dev);
+
+       err = input_register_device(sunkbd->dev);
+       if (err)
+               goto fail4;
+
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail4:        sunkbd_enable(sunkbd, 0);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(sunkbd);
        return err;
 }
@@ -346,8 +352,7 @@ static struct serio_driver sunkbd_drv = {
 
 static int __init sunkbd_init(void)
 {
-       serio_register_driver(&sunkbd_drv);
-       return 0;
+       return serio_register_driver(&sunkbd_drv);
 }
 
 static void __exit sunkbd_exit(void)
index 8c11dc9..a820934 100644 (file)
@@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
        xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!xtkbd || !input_dev)
-               goto fail;
+               goto fail1;
 
        xtkbd->serio = serio;
        xtkbd->dev = input_dev;
@@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(xtkbd->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(xtkbd->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(xtkbd);
        return err;
 }
@@ -170,8 +174,7 @@ static struct serio_driver xtkbd_drv = {
 
 static int __init xtkbd_init(void)
 {
-       serio_register_driver(&xtkbd_drv);
-       return 0;
+       return serio_register_driver(&xtkbd_drv);
 }
 
 static void __exit xtkbd_exit(void)
index ab4da79..31d5a13 100644 (file)
@@ -695,7 +695,9 @@ static int __init hp_sdc_rtc_init(void)
 
        if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
                return ret;
-       misc_register(&hp_sdc_rtc_dev);
+       if (misc_register(&hp_sdc_rtc_dev) != 0)
+               printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
+
         create_proc_read_entry ("driver/rtc", 0, NULL,
                                hp_sdc_rtc_read_proc, NULL);
 
index 599a7b2..239a0e1 100644 (file)
@@ -95,10 +95,13 @@ static void amimouse_close(struct input_dev *dev)
 
 static int __init amimouse_init(void)
 {
+       int err;
+
        if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
                return -ENODEV;
 
-       if (!(amimouse_dev = input_allocate_device()))
+       amimouse_dev = input_allocate_device();
+       if (!amimouse_dev)
                return -ENOMEM;
 
        amimouse_dev->name = "Amiga mouse";
@@ -114,7 +117,11 @@ static int __init amimouse_init(void)
        amimouse_dev->open = amimouse_open;
        amimouse_dev->close = amimouse_close;
 
-       input_register_device(amimouse_dev);
+       err = input_register_device(amimouse_dev);
+       if (err) {
+               input_free_device(amimouse_dev);
+               return err;
+       }
 
        return 0;
 }
index 4f2b503..bfb174f 100644 (file)
@@ -417,8 +417,7 @@ static struct serio_driver hil_ptr_serio_driver = {
 
 static int __init hil_ptr_init(void)
 {
-       serio_register_driver(&hil_ptr_serio_driver);
-        return 0;
+       return serio_register_driver(&hil_ptr_serio_driver);
 }
                 
 static void __exit hil_ptr_exit(void)
index e1252fa..13dd967 100644 (file)
@@ -135,6 +135,7 @@ static void inport_close(struct input_dev *dev)
 static int __init inport_init(void)
 {
        unsigned char a, b, c;
+       int err;
 
        if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
                printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -145,15 +146,16 @@ static int __init inport_init(void)
        b = inb(INPORT_SIGNATURE_PORT);
        c = inb(INPORT_SIGNATURE_PORT);
        if (a == b || a != c) {
-               release_region(INPORT_BASE, INPORT_EXTENT);
                printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_release_region;
        }
 
-       if (!(inport_dev = input_allocate_device())) {
+       inport_dev = input_allocate_device();
+       if (!inport_dev) {
                printk(KERN_ERR "inport.c: Not enough memory for input device\n");
-               release_region(INPORT_BASE, INPORT_EXTENT);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_release_region;
        }
 
        inport_dev->name = INPORT_NAME;
@@ -174,9 +176,18 @@ static int __init inport_init(void)
        outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
        outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
 
-       input_register_device(inport_dev);
+       err = input_register_device(inport_dev);
+       if (err)
+               goto err_free_dev;
 
        return 0;
+
+ err_free_dev:
+       input_free_device(inport_dev);
+ err_release_region:
+       release_region(INPORT_BASE, INPORT_EXTENT);
+
+       return err;
 }
 
 static void __exit inport_exit(void)
index c57e885..29542f0 100644 (file)
 #include "lifebook.h"
 
 static struct dmi_system_id lifebook_dmi_table[] = {
-       {
-               .ident = "LifeBook B",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
-               },
-       },
-       {
-               .ident = "Lifebook B",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
-               },
-       },
-       {
-               .ident = "Lifebook B213x/B2150",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
-               },
-       },
-       {
-               .ident = "Zephyr",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
-               },
-       },
-       {
-               .ident = "CF-18",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
-               },
-       },
-       {
-               .ident = "Lifebook B142",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
-               },
-
-       },
-       { }
+       {
+               .ident = "FLORA-ie 55mi",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"),
+               },
+       },
+       {
+               .ident = "LifeBook B",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
+               },
+       },
+       {
+               .ident = "Lifebook B",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
+               },
+       },
+       {
+               .ident = "Lifebook B213x/B2150",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
+               },
+       },
+       {
+               .ident = "Zephyr",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
+               },
+       },
+       {
+               .ident = "CF-18",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
+               },
+       },
+       {
+               .ident = "Lifebook B142",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
+               },
+       },
+       { }
 };
 
-
 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
 {
        unsigned char *packet = psmouse->packet;
index 8e9c2f3..db20599 100644 (file)
@@ -124,6 +124,8 @@ static void logibm_close(struct input_dev *dev)
 
 static int __init logibm_init(void)
 {
+       int err;
+
        if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
                printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
                return -EBUSY;
@@ -134,18 +136,19 @@ static int __init logibm_init(void)
        udelay(100);
 
        if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
-               release_region(LOGIBM_BASE, LOGIBM_EXTENT);
                printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_release_region;
        }
 
        outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
        outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
 
-       if (!(logibm_dev = input_allocate_device())) {
+       logibm_dev = input_allocate_device();
+       if (!logibm_dev) {
                printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
-               release_region(LOGIBM_BASE, LOGIBM_EXTENT);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_release_region;
        }
 
        logibm_dev->name = "Logitech bus mouse";
@@ -162,9 +165,18 @@ static int __init logibm_init(void)
        logibm_dev->open  = logibm_open;
        logibm_dev->close = logibm_close;
 
-       input_register_device(logibm_dev);
+       err = input_register_device(logibm_dev);
+       if (err)
+               goto err_free_dev;
 
        return 0;
+
+ err_free_dev:
+       input_free_device(logibm_dev);
+ err_release_region:
+       release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+
+       return err;
 }
 
 static void __exit logibm_exit(void)
index 8a4f862..d3ddea2 100644 (file)
@@ -328,6 +328,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
        unsigned char model, buttons;
        const struct ps2pp_info *model_info;
        int use_ps2pp = 0;
+       int error;
 
        param[0] = 0;
        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
@@ -393,8 +394,14 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
                                psmouse->set_resolution = ps2pp_set_resolution;
                                psmouse->disconnect = ps2pp_disconnect;
 
-                               device_create_file(&psmouse->ps2dev.serio->dev,
-                                                  &psmouse_attr_smartscroll.dattr);
+                               error = device_create_file(&psmouse->ps2dev.serio->dev,
+                                                          &psmouse_attr_smartscroll.dattr);
+                               if (error) {
+                                       printk(KERN_ERR
+                                               "logips2pp.c: failed to create smartscroll "
+                                               "sysfs attribute, error: %d\n", error);
+                                       return -1;
+                               }
                        }
                }
 
index 8c075aa..f155c1f 100644 (file)
@@ -108,6 +108,7 @@ static int pc110pad_open(struct input_dev *dev)
 static int __init pc110pad_init(void)
 {
        struct pci_dev *dev;
+       int err;
 
        dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
        if (dev) {
@@ -124,16 +125,16 @@ static int __init pc110pad_init(void)
        outb(PC110PAD_OFF, pc110pad_io + 2);
 
        if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
-               release_region(pc110pad_io, 4);
                printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
-               return -EBUSY;
+               err = -EBUSY;
+               goto err_release_region;
        }
 
-       if (!(pc110pad_dev = input_allocate_device())) {
-               free_irq(pc110pad_irq, NULL);
-               release_region(pc110pad_io, 4);
+       pc110pad_dev = input_allocate_device();
+       if (!pc110pad_dev) {
                printk(KERN_ERR "pc110pad: Not enough memory.\n");
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_free_irq;
        }
 
        pc110pad_dev->name = "IBM PC110 TouchPad";
@@ -153,9 +154,20 @@ static int __init pc110pad_init(void)
        pc110pad_dev->open = pc110pad_open;
        pc110pad_dev->close = pc110pad_close;
 
-       input_register_device(pc110pad_dev);
+       err = input_register_device(pc110pad_dev);
+       if (err)
+               goto err_free_dev;
 
        return 0;
+
+ err_free_dev:
+       input_free_device(pc110pad_dev);
+ err_free_irq:
+       free_irq(pc110pad_irq, NULL);
+ err_release_region:
+       release_region(pc110pad_io, 4);
+
+       return err;
 }
 
 static void __exit pc110pad_exit(void)
index 6f9b2c7..a0e4a03 100644 (file)
@@ -888,9 +888,10 @@ static int psmouse_poll(struct psmouse *psmouse)
  * psmouse_resync() attempts to re-validate current protocol.
  */
 
-static void psmouse_resync(void *p)
+static void psmouse_resync(struct work_struct *work)
 {
-       struct psmouse *psmouse = p, *parent = NULL;
+       struct psmouse *parent = NULL, *psmouse =
+               container_of(work, struct psmouse, resync_work);
        struct serio *serio = psmouse->ps2dev.serio;
        psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
        int failed = 0, enabled = 0;
@@ -1102,7 +1103,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
        struct psmouse *psmouse, *parent = NULL;
        struct input_dev *input_dev;
-       int retval = -ENOMEM;
+       int retval = 0, error = -ENOMEM;
 
        mutex_lock(&psmouse_mutex);
 
@@ -1118,10 +1119,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!psmouse || !input_dev)
-               goto out;
+               goto err_free;
 
        ps2_init(&psmouse->ps2dev, serio);
-       INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
+       INIT_WORK(&psmouse->resync_work, psmouse_resync);
        psmouse->dev = input_dev;
        snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
 
@@ -1129,14 +1130,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
 
        serio_set_drvdata(serio, psmouse);
 
-       retval = serio_open(serio, drv);
-       if (retval)
-               goto out;
+       error = serio_open(serio, drv);
+       if (error)
+               goto err_clear_drvdata;
 
        if (psmouse_probe(psmouse) < 0) {
-               serio_close(serio);
-               retval = -ENODEV;
-               goto out;
+               error = -ENODEV;
+               goto err_close_serio;
        }
 
        psmouse->rate = psmouse_rate;
@@ -1150,30 +1150,44 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
        psmouse_initialize(psmouse);
 
-       input_register_device(psmouse->dev);
+       error = input_register_device(psmouse->dev);
+       if (error)
+               goto err_protocol_disconnect;
 
        if (parent && parent->pt_activate)
                parent->pt_activate(parent);
 
-       sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
+       error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
+       if (error)
+               goto err_pt_deactivate;
 
        psmouse_activate(psmouse);
 
-       retval = 0;
-
-out:
-       if (retval) {
-               serio_set_drvdata(serio, NULL);
-               input_free_device(input_dev);
-               kfree(psmouse);
-       }
-
+ out:
        /* If this is a pass-through port the parent needs to be re-activated */
        if (parent)
                psmouse_activate(parent);
 
        mutex_unlock(&psmouse_mutex);
        return retval;
+
+ err_pt_deactivate:
+       if (parent && parent->pt_deactivate)
+               parent->pt_deactivate(parent);
+ err_protocol_disconnect:
+       if (psmouse->disconnect)
+               psmouse->disconnect(psmouse);
+       psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ err_close_serio:
+       serio_close(serio);
+ err_clear_drvdata:
+       serio_set_drvdata(serio, NULL);
+ err_free:
+       input_free_device(input_dev);
+       kfree(psmouse);
+
+       retval = error;
+       goto out;
 }
 
 
@@ -1336,14 +1350,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 
 static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
 {
-       unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+       unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
 
-       return sprintf(buf, "%lu\n", *field);
+       return sprintf(buf, "%u\n", *field);
 }
 
 static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
 {
-       unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+       unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
        unsigned long value;
        char *rest;
 
@@ -1351,6 +1365,9 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
        if (*rest)
                return -EINVAL;
 
+       if ((unsigned int)value != value)
+               return -EINVAL;
+
        *field = value;
 
        return count;
@@ -1365,17 +1382,20 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
 {
        struct serio *serio = psmouse->ps2dev.serio;
        struct psmouse *parent = NULL;
-       struct input_dev *new_dev;
-       const struct psmouse_protocol *proto;
+       struct input_dev *old_dev, *new_dev;
+       const struct psmouse_protocol *proto, *old_proto;
+       int error;
        int retry = 0;
 
-       if (!(proto = psmouse_protocol_by_name(buf, count)))
+       proto = psmouse_protocol_by_name(buf, count);
+       if (!proto)
                return -EINVAL;
 
        if (psmouse->type == proto->type)
                return count;
 
-       if (!(new_dev = input_allocate_device()))
+       new_dev = input_allocate_device();
+       if (!new_dev)
                return -ENOMEM;
 
        while (serio->child) {
@@ -1408,11 +1428,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
                        parent->pt_deactivate(parent);
        }
 
+       old_dev = psmouse->dev;
+       old_proto = psmouse_protocol_by_type(psmouse->type);
+
        if (psmouse->disconnect)
                psmouse->disconnect(psmouse);
 
        psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-       input_unregister_device(psmouse->dev);
 
        psmouse->dev = new_dev;
        psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -1426,7 +1448,23 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
        psmouse_initialize(psmouse);
        psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-       input_register_device(psmouse->dev);
+       error = input_register_device(psmouse->dev);
+       if (error) {
+               if (psmouse->disconnect)
+                       psmouse->disconnect(psmouse);
+
+               psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+               input_free_device(new_dev);
+               psmouse->dev = old_dev;
+               psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+               psmouse_switch_protocol(psmouse, old_proto);
+               psmouse_initialize(psmouse);
+               psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
+               return error;
+       }
+
+       input_unregister_device(old_dev);
 
        if (parent && parent->pt_activate)
                parent->pt_activate(parent);
@@ -1487,15 +1525,19 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
 
 static int __init psmouse_init(void)
 {
+       int err;
+
        kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
        if (!kpsmoused_wq) {
                printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
                return -ENOMEM;
        }
 
-       serio_register_driver(&psmouse_drv);
+       err = serio_register_driver(&psmouse_drv);
+       if (err)
+               destroy_workqueue(kpsmoused_wq);
 
-       return 0;
+       return err;
 }
 
 static void __exit psmouse_exit(void)
index ea04685..fbdcfd8 100644 (file)
@@ -66,7 +66,10 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
 
 static int __init rpcmouse_init(void)
 {
-       if (!(rpcmouse_dev = input_allocate_device()))
+       int err;
+
+       rpcmouse_dev = input_allocate_device();
+       if (!rpcmouse_dev)
                return -ENOMEM;
 
        rpcmouse_dev->name = "Acorn RiscPC Mouse";
@@ -85,13 +88,22 @@ static int __init rpcmouse_init(void)
 
        if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) {
                printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
-               input_free_device(rpcmouse_dev);
-               return -EBUSY;
+               err = -EBUSY;
+               goto err_free_dev;
        }
 
-       input_register_device(rpcmouse_dev);
+       err = input_register_device(rpcmouse_dev);
+       if (err)
+               goto err_free_irq;
 
        return 0;
+
+ err_free_irq:
+       free_irq(IRQ_VSYNCPULSE, rpcmouse_dev);
+ err_free_dev:
+       input_free_device(rpcmouse_dev);
+
+       return err;
 }
 
 static void __exit rpcmouse_exit(void)
index 2a272c5..a85d747 100644 (file)
@@ -246,7 +246,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
        sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!sermouse || !input_dev)
-               goto fail;
+               goto fail1;
 
        sermouse->dev = input_dev;
        snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
@@ -275,14 +275,17 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
 
-       input_register_device(sermouse->dev);
+       err = input_register_device(sermouse->dev);
+       if (err)
+               goto fail3;
 
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(sermouse);
        return err;
 }
@@ -348,8 +351,7 @@ static struct serio_driver sermouse_drv = {
 
 static int __init sermouse_init(void)
 {
-       serio_register_driver(&sermouse_drv);
-       return 0;
+       return serio_register_driver(&sermouse_drv);
 }
 
 static void __exit sermouse_exit(void)
index ae5871a..9ab5b5e 100644 (file)
@@ -293,6 +293,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
        struct ps2dev *ps2dev = &psmouse->ps2dev;
        unsigned char firmware_id;
        unsigned char button_info;
+       int error;
 
        if (trackpoint_start_protocol(psmouse, &firmware_id))
                return -1;
@@ -305,7 +306,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
                button_info = 0;
        }
 
-       psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
+       psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
        if (!priv)
                return -1;
 
@@ -318,7 +319,14 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
        trackpoint_defaults(priv);
        trackpoint_sync(psmouse);
 
-       sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+       error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+       if (error) {
+               printk(KERN_ERR
+                       "trackpoint.c: failed to create sysfs attributes, error: %d\n",
+                       error);
+               kfree(priv);
+               return -1;
+       }
 
        printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
                firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
index ffdb50e..c3d64fc 100644 (file)
@@ -497,7 +497,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
        mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
        input_dev = input_allocate_device ();
        if (!mouse || !input_dev)
-               goto fail;
+               goto fail1;
 
        mouse->dev = input_dev;
        mouse->serio = serio;
@@ -527,7 +527,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 
        err = serio_open (serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
 
        /*
         * Request selftest. Standard packet format and differential
@@ -535,12 +535,15 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
         */
        serio->write (serio, 'T'); /* Test */
 
-       input_register_device (input_dev);
+       err = input_register_device (input_dev);
+       if (err)
+               goto fail3;
 
        return 0;
 
- fail: serio_set_drvdata (serio, NULL);
-       input_free_device (input_dev);
+ fail3:        serio_close (serio);
+ fail2:        serio_set_drvdata (serio, NULL);
+ fail1:        input_free_device (input_dev);
        kfree (mouse);
        return err;
 }
@@ -571,8 +574,7 @@ static struct serio_driver vsxxxaa_drv = {
 static int __init
 vsxxxaa_init (void)
 {
-       serio_register_driver(&vsxxxaa_drv);
-       return 0;
+       return serio_register_driver(&vsxxxaa_drv);
 }
 
 static void __exit
index a22a74a..664bcc8 100644 (file)
@@ -196,12 +196,12 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
        switch (code) {
                case BTN_TOUCH:
                case BTN_0:
-               case BTN_FORWARD:
                case BTN_LEFT:          index = 0; break;
                case BTN_STYLUS:
                case BTN_1:
                case BTN_RIGHT:         index = 1; break;
                case BTN_2:
+               case BTN_FORWARD:
                case BTN_STYLUS2:
                case BTN_MIDDLE:        index = 2; break;
                case BTN_3:
index 8738edd..d36bd54 100644 (file)
@@ -110,6 +110,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
                },
        },
+       {
+               .ident = "Fujitsu Lifebook P7010",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+               },
+       },
        {
                .ident = "Fujitsu Lifebook P5020D",
                .matches = {
index 7e3141f..debe944 100644 (file)
@@ -255,25 +255,10 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)
 static int i8042_aux_write(struct serio *serio, unsigned char c)
 {
        struct i8042_port *port = serio->port_data;
-       int retval;
-
-/*
- * Send the byte out.
- */
-
-       if (port->mux == -1)
-               retval = i8042_command(&c, I8042_CMD_AUX_SEND);
-       else
-               retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
-
-/*
- * Make sure the interrupt happens and the character is received even
- * in the case the IRQ isn't wired, so that we can receive further
- * characters later.
- */
 
-       i8042_interrupt(0, NULL);
-       return retval;
+       return i8042_command(&c, port->mux == -1 ?
+                                       I8042_CMD_AUX_SEND :
+                                       I8042_CMD_MUX_SEND + port->mux);
 }
 
 /*
@@ -337,23 +322,27 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
                dfl = 0;
                if (str & I8042_STR_MUXERR) {
                        dbg("MUX error, status is %02x, data is %02x", str, data);
-                       switch (data) {
-                               default:
 /*
  * When MUXERR condition is signalled the data register can only contain
  * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
- * it is not always the case. Some KBC just get confused which port the
- * data came from and signal error leaving the data intact. They _do not_
- * revert to legacy mode (actually I've never seen KBC reverting to legacy
- * mode yet, when we see one we'll add proper handling).
- * Anyway, we will assume that the data came from the same serio last byte
+ * it is not always the case. Some KBCs also report 0xfc when there is
+ * nothing connected to the port while others sometimes get confused which
+ * port the data came from and signal error leaving the data intact. They
+ * _do not_ revert to legacy mode (actually I've never seen KBC reverting
+ * to legacy mode yet, when we see one we'll add proper handling).
+ * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the
+ * rest assume that the data came from the same serio last byte
  * was transmitted (if transmission happened not too long ago).
  */
+
+                       switch (data) {
+                               default:
                                        if (time_before(jiffies, last_transmit + HZ/10)) {
                                                str = last_str;
                                                break;
                                        }
                                        /* fall through - report timeout */
+                               case 0xfc:
                                case 0xfd:
                                case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
                                case 0xff: dfl = SERIO_PARITY;  data = 0xfe; break;
index e5b1b60..b3e84d3 100644 (file)
@@ -251,9 +251,9 @@ EXPORT_SYMBOL(ps2_command);
  * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.)
  */
 
-static void ps2_execute_scheduled_command(void *data)
+static void ps2_execute_scheduled_command(struct work_struct *work)
 {
-       struct ps2work *ps2work = data;
+       struct ps2work *ps2work = container_of(work, struct ps2work, work);
 
        ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command);
        kfree(ps2work);
@@ -278,7 +278,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
        ps2work->ps2dev = ps2dev;
        ps2work->command = command;
        memcpy(ps2work->param, param, send);
-       INIT_WORK(&ps2work->work, ps2_execute_scheduled_command, ps2work);
+       INIT_WORK(&ps2work->work, ps2_execute_scheduled_command);
 
        if (!schedule_work(&ps2work->work)) {
                kfree(ps2work);
index 211943f..f0ce822 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -44,8 +45,7 @@ EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
 EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(__serio_unregister_port_delayed);
-EXPORT_SYMBOL(__serio_register_driver);
+EXPORT_SYMBOL(serio_register_driver);
 EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
@@ -62,11 +62,10 @@ static LIST_HEAD(serio_list);
 
 static struct bus_type serio_bus;
 
-static void serio_add_driver(struct serio_driver *drv);
 static void serio_add_port(struct serio *serio);
-static void serio_destroy_port(struct serio *serio);
 static void serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
+static void serio_attach_driver(struct serio_driver *drv);
 
 static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
 {
@@ -170,11 +169,10 @@ static void serio_find_driver(struct serio *serio)
  */
 
 enum serio_event_type {
-       SERIO_RESCAN,
-       SERIO_RECONNECT,
+       SERIO_RESCAN_PORT,
+       SERIO_RECONNECT_PORT,
        SERIO_REGISTER_PORT,
-       SERIO_UNREGISTER_PORT,
-       SERIO_REGISTER_DRIVER,
+       SERIO_ATTACH_DRIVER,
 };
 
 struct serio_event {
@@ -189,11 +187,12 @@ static LIST_HEAD(serio_event_list);
 static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
 static struct task_struct *serio_task;
 
-static void serio_queue_event(void *object, struct module *owner,
-                             enum serio_event_type event_type)
+static int serio_queue_event(void *object, struct module *owner,
+                            enum serio_event_type event_type)
 {
        unsigned long flags;
        struct serio_event *event;
+       int retval = 0;
 
        spin_lock_irqsave(&serio_event_lock, flags);
 
@@ -212,24 +211,34 @@ static void serio_queue_event(void *object, struct module *owner,
                }
        }
 
-       if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
-               if (!try_module_get(owner)) {
-                       printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
-                       kfree(event);
-                       goto out;
-               }
-
-               event->type = event_type;
-               event->object = object;
-               event->owner = owner;
+       event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
+       if (!event) {
+               printk(KERN_ERR
+                       "serio: Not enough memory to queue event %d\n",
+                       event_type);
+               retval = -ENOMEM;
+               goto out;
+       }
 
-               list_add_tail(&event->node, &serio_event_list);
-               wake_up(&serio_wait);
-       } else {
-               printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
+       if (!try_module_get(owner)) {
+               printk(KERN_WARNING
+                       "serio: Can't get module reference, dropping event %d\n",
+                       event_type);
+               kfree(event);
+               retval = -EINVAL;
+               goto out;
        }
+
+       event->type = event_type;
+       event->object = object;
+       event->owner = owner;
+
+       list_add_tail(&event->node, &serio_event_list);
+       wake_up(&serio_wait);
+
 out:
        spin_unlock_irqrestore(&serio_event_lock, flags);
+       return retval;
 }
 
 static void serio_free_event(struct serio_event *event)
@@ -307,22 +316,17 @@ static void serio_handle_event(void)
                                serio_add_port(event->object);
                                break;
 
-                       case SERIO_UNREGISTER_PORT:
-                               serio_disconnect_port(event->object);
-                               serio_destroy_port(event->object);
-                               break;
-
-                       case SERIO_RECONNECT:
+                       case SERIO_RECONNECT_PORT:
                                serio_reconnect_port(event->object);
                                break;
 
-                       case SERIO_RESCAN:
+                       case SERIO_RESCAN_PORT:
                                serio_disconnect_port(event->object);
                                serio_find_driver(event->object);
                                break;
 
-                       case SERIO_REGISTER_DRIVER:
-                               serio_add_driver(event->object);
+                       case SERIO_ATTACH_DRIVER:
+                               serio_attach_driver(event->object);
                                break;
 
                        default:
@@ -674,12 +678,12 @@ static void serio_disconnect_port(struct serio *serio)
 
 void serio_rescan(struct serio *serio)
 {
-       serio_queue_event(serio, NULL, SERIO_RESCAN);
+       serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
 }
 
 void serio_reconnect(struct serio *serio)
 {
-       serio_queue_event(serio, NULL, SERIO_RECONNECT);
+       serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
 }
 
 /*
@@ -716,16 +720,6 @@ void serio_unregister_child_port(struct serio *serio)
        mutex_unlock(&serio_mutex);
 }
 
-/*
- * Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_mutex is
- * taken or not and when delayed execution is feasible.
- */
-void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
-{
-       serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
-}
-
 
 /*
  * Serio driver operations
@@ -784,28 +778,52 @@ static int serio_driver_remove(struct device *dev)
        return 0;
 }
 
-static struct bus_type serio_bus = {
-       .name = "serio",
-       .probe = serio_driver_probe,
-       .remove = serio_driver_remove,
-};
-
-static void serio_add_driver(struct serio_driver *drv)
+static void serio_attach_driver(struct serio_driver *drv)
 {
        int error;
 
-       error = driver_register(&drv->driver);
+       error = driver_attach(&drv->driver);
        if (error)
-               printk(KERN_ERR
-                       "serio: driver_register() failed for %s, error: %d\n",
+               printk(KERN_WARNING
+                       "serio: driver_attach() failed for %s with error %d\n",
                        drv->driver.name, error);
 }
 
-void __serio_register_driver(struct serio_driver *drv, struct module *owner)
+int serio_register_driver(struct serio_driver *drv)
 {
+       int manual_bind = drv->manual_bind;
+       int error;
+
        drv->driver.bus = &serio_bus;
 
-       serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+       /*
+        * Temporarily disable automatic binding because probing
+        * takes long time and we are better off doing it in kseriod
+        */
+       drv->manual_bind = 1;
+
+       error = driver_register(&drv->driver);
+       if (error) {
+               printk(KERN_ERR
+                       "serio: driver_register() failed for %s, error: %d\n",
+                       drv->driver.name, error);
+               return error;
+       }
+
+       /*
+        * Restore original bind mode and let kseriod bind the
+        * driver to free ports
+        */
+       if (!manual_bind) {
+               drv->manual_bind = 0;
+               error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
+               if (error) {
+                       driver_unregister(&drv->driver);
+                       return error;
+               }
+       }
+
+       return 0;
 }
 
 void serio_unregister_driver(struct serio_driver *drv)
@@ -946,15 +964,21 @@ irqreturn_t serio_interrupt(struct serio *serio,
        return ret;
 }
 
+static struct bus_type serio_bus = {
+       .name           = "serio",
+       .dev_attrs      = serio_device_attrs,
+       .drv_attrs      = serio_driver_attrs,
+       .match          = serio_bus_match,
+       .uevent         = serio_uevent,
+       .probe          = serio_driver_probe,
+       .remove         = serio_driver_remove,
+       .resume         = serio_resume,
+};
+
 static int __init serio_init(void)
 {
        int error;
 
-       serio_bus.dev_attrs = serio_device_attrs;
-       serio_bus.drv_attrs = serio_driver_attrs;
-       serio_bus.match = serio_bus_match;
-       serio_bus.uevent = serio_uevent;
-       serio_bus.resume = serio_resume;
        error = bus_register(&serio_bus);
        if (error) {
                printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
index 7c8d039..088ebc3 100644 (file)
@@ -389,8 +389,7 @@ static struct serio_driver serio_raw_drv = {
 
 static int __init serio_raw_init(void)
 {
-       serio_register_driver(&serio_raw_drv);
-       return 0;
+       return serio_register_driver(&serio_raw_drv);
 }
 
 static void __exit serio_raw_exit(void)
index 9418bbe..3d5f196 100644 (file)
@@ -144,4 +144,19 @@ config TOUCHSCREEN_TOUCHWIN
          To compile this driver as a module, choose M here: the
          module will be called touchwin.
 
+config TOUCHSCREEN_UCB1400
+       tristate "Philips UCB1400 touchscreen"
+       depends on SND_AC97_BUS
+       help
+         This enables support for the Philips UCB1400 touchscreen interface.
+         The UCB1400 is an AC97 audio codec.  The touchscreen interface
+         will be initialized only after the ALSA subsystem has been
+         brought up and the UCB1400 detected.  You therefore have to
+         configure ALSA support as well (either built-in or modular,
+         independently of whether this driver is itself built-in or
+         modular) for this driver to work.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ucb1400_ts.
+
 endif
index 1abb8f1..30e6e22 100644 (file)
@@ -15,3 +15,4 @@ obj-$(CONFIG_TOUCHSCREEN_HP600)       += hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)     += penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
index f56d6a0..c6164b6 100644 (file)
@@ -76,6 +76,7 @@ struct ads7846 {
        char                    phys[32];
 
        struct spi_device       *spi;
+       struct attribute_group  *attr_group;
        u16                     model;
        u16                     vref_delay_usecs;
        u16                     x_plate_ohms;
@@ -189,7 +190,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 {
        struct spi_device       *spi = to_spi_device(dev);
        struct ads7846          *ts = dev_get_drvdata(dev);
-       struct ser_req          *req = kzalloc(sizeof *req, SLAB_KERNEL);
+       struct ser_req          *req = kzalloc(sizeof *req, GFP_KERNEL);
        int                     status;
        int                     sample;
        int                     i;
@@ -317,6 +318,48 @@ static ssize_t ads7846_disable_store(struct device *dev,
 
 static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
 
+static struct attribute *ads7846_attributes[] = {
+       &dev_attr_temp0.attr,
+       &dev_attr_temp1.attr,
+       &dev_attr_vbatt.attr,
+       &dev_attr_vaux.attr,
+       &dev_attr_pen_down.attr,
+       &dev_attr_disable.attr,
+       NULL,
+};
+
+static struct attribute_group ads7846_attr_group = {
+       .attrs = ads7846_attributes,
+};
+
+/*
+ * ads7843/7845 don't have temperature sensors, and
+ * use the other sensors a bit differently too
+ */
+
+static struct attribute *ads7843_attributes[] = {
+       &dev_attr_vbatt.attr,
+       &dev_attr_vaux.attr,
+       &dev_attr_pen_down.attr,
+       &dev_attr_disable.attr,
+       NULL,
+};
+
+static struct attribute_group ads7843_attr_group = {
+       .attrs = ads7843_attributes,
+};
+
+static struct attribute *ads7845_attributes[] = {
+       &dev_attr_vaux.attr,
+       &dev_attr_pen_down.attr,
+       &dev_attr_disable.attr,
+       NULL,
+};
+
+static struct attribute_group ads7845_attr_group = {
+       .attrs = ads7845_attributes,
+};
+
 /*--------------------------------------------------------------------------*/
 
 /*
@@ -788,38 +831,30 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        (void) ads7846_read12_ser(&spi->dev,
                          READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
 
-       /* ads7843/7845 don't have temperature sensors, and
-        * use the other sensors a bit differently too
-        */
-       if (ts->model == 7846) {
-               device_create_file(&spi->dev, &dev_attr_temp0);
-               device_create_file(&spi->dev, &dev_attr_temp1);
+       switch (ts->model) {
+       case 7846:
+               ts->attr_group = &ads7846_attr_group;
+               break;
+       case 7845:
+               ts->attr_group = &ads7845_attr_group;
+               break;
+       default:
+               ts->attr_group = &ads7843_attr_group;
+               break;
        }
-       if (ts->model != 7845)
-               device_create_file(&spi->dev, &dev_attr_vbatt);
-       device_create_file(&spi->dev, &dev_attr_vaux);
-
-       device_create_file(&spi->dev, &dev_attr_pen_down);
-
-       device_create_file(&spi->dev, &dev_attr_disable);
+       err = sysfs_create_group(&spi->dev.kobj, ts->attr_group);
+       if (err)
+               goto err_free_irq;
 
        err = input_register_device(input_dev);
        if (err)
-               goto err_remove_attr;
+               goto err_remove_attr_group;
 
        return 0;
 
- err_remove_attr:
-       device_remove_file(&spi->dev, &dev_attr_disable);
-       device_remove_file(&spi->dev, &dev_attr_pen_down);
-       if (ts->model == 7846) {
-               device_remove_file(&spi->dev, &dev_attr_temp1);
-               device_remove_file(&spi->dev, &dev_attr_temp0);
-       }
-       if (ts->model != 7845)
-               device_remove_file(&spi->dev, &dev_attr_vbatt);
-       device_remove_file(&spi->dev, &dev_attr_vaux);
-
+ err_remove_attr_group:
+       sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+ err_free_irq:
        free_irq(spi->irq, ts);
  err_free_mem:
        input_free_device(input_dev);
@@ -835,15 +870,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
 
        ads7846_suspend(spi, PMSG_SUSPEND);
 
-       device_remove_file(&spi->dev, &dev_attr_disable);
-       device_remove_file(&spi->dev, &dev_attr_pen_down);
-       if (ts->model == 7846) {
-               device_remove_file(&spi->dev, &dev_attr_temp1);
-               device_remove_file(&spi->dev, &dev_attr_temp0);
-       }
-       if (ts->model != 7845)
-               device_remove_file(&spi->dev, &dev_attr_vbatt);
-       device_remove_file(&spi->dev, &dev_attr_vaux);
+       sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
 
        free_irq(ts->spi->irq, ts);
        /* suspend left the IRQ disabled */
index 66121f6..e294558 100644 (file)
@@ -175,17 +175,19 @@ static int read_xydata(struct corgi_ts *corgi_ts)
 
 static void new_data(struct corgi_ts *corgi_ts)
 {
+       struct input_dev *dev = corgi_ts->input;
+
        if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
                return;
 
        if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
                return;
 
-       input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x);
-       input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y);
-       input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
-       input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
-       input_sync(corgi_ts->input);
+       input_report_abs(dev, ABS_X, corgi_ts->tc.x);
+       input_report_abs(dev, ABS_Y, corgi_ts->tc.y);
+       input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure);
+       input_report_key(dev, BTN_TOUCH, corgi_ts->pendown);
+       input_sync(dev);
 }
 
 static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
@@ -219,12 +221,14 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
 static void corgi_ts_timer(unsigned long data)
 {
        struct corgi_ts *corgits_data = (struct corgi_ts *) data;
+
        ts_interrupt_main(corgits_data, 1);
 }
 
 static irqreturn_t ts_interrupt(int irq, void *dev_id)
 {
        struct corgi_ts *corgits_data = dev_id;
+
        ts_interrupt_main(corgits_data, 0);
        return IRQ_HANDLED;
 }
@@ -272,7 +276,7 @@ static int __init corgits_probe(struct platform_device *pdev)
        corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!corgi_ts || !input_dev)
-               goto fail;
+               goto fail1;
 
        platform_set_drvdata(pdev, corgi_ts);
 
@@ -281,7 +285,7 @@ static int __init corgits_probe(struct platform_device *pdev)
 
        if (corgi_ts->irq_gpio < 0) {
                err = -ENODEV;
-               goto fail;
+               goto fail1;
        }
 
        corgi_ts->input = input_dev;
@@ -319,10 +323,12 @@ static int __init corgits_probe(struct platform_device *pdev)
 
        if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) {
                err = -EBUSY;
-               goto fail;
+               goto fail1;
        }
 
-       input_register_device(corgi_ts->input);
+       err = input_register_device(corgi_ts->input);
+       if (err)
+               goto fail2;
 
        corgi_ts->power_mode = PWR_MODE_ACTIVE;
 
@@ -331,17 +337,17 @@ static int __init corgits_probe(struct platform_device *pdev)
 
        return 0;
 
- fail: input_free_device(input_dev);
+ fail2:        free_irq(corgi_ts->irq_gpio, corgi_ts);
+ fail1:        input_free_device(input_dev);
        kfree(corgi_ts);
        return err;
-
 }
 
 static int corgits_remove(struct platform_device *pdev)
 {
        struct corgi_ts *corgi_ts = platform_get_drvdata(pdev);
 
-       free_irq(corgi_ts->irq_gpio, NULL);
+       free_irq(corgi_ts->irq_gpio, corgi_ts);
        del_timer_sync(&corgi_ts->timer);
        corgi_ts->machinfo->put_hsync();
        input_unregister_device(corgi_ts->input);
index 913e1b7..9d61cd1 100644 (file)
@@ -397,8 +397,7 @@ static struct serio_driver elo_drv = {
 
 static int __init elo_init(void)
 {
-       serio_register_driver(&elo_drv);
-       return 0;
+       return serio_register_driver(&elo_drv);
 }
 
 static void __exit elo_exit(void)
index 817c219..9157eb1 100644 (file)
@@ -123,7 +123,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
        input_dev = input_allocate_device();
        if (!gunze || !input_dev) {
                err = -ENOMEM;
-               goto fail;
+               goto fail1;
        }
 
        gunze->serio = serio;
@@ -146,13 +146,17 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
+
+       err = input_register_device(gunze->dev);
+       if (err)
+               goto fail3;
 
-       input_register_device(gunze->dev);
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(gunze);
        return err;
 }
@@ -190,8 +194,7 @@ static struct serio_driver gunze_drv = {
 
 static int __init gunze_init(void)
 {
-       serio_register_driver(&gunze_drv);
-       return 0;
+       return serio_register_driver(&gunze_drv);
 }
 
 static void __exit gunze_exit(void)
index d9e61ee..c4116d4 100644 (file)
@@ -478,8 +478,7 @@ static struct serio_driver h3600ts_drv = {
 
 static int __init h3600ts_init(void)
 {
-       serio_register_driver(&h3600ts_drv);
-       return 0;
+       return serio_register_driver(&h3600ts_drv);
 }
 
 static void __exit h3600ts_exit(void)
index 58fca31..2490874 100644 (file)
@@ -76,38 +76,47 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
 
 static int __init hp680_ts_init(void)
 {
+       int err;
+
        hp680_ts_dev = input_allocate_device();
        if (!hp680_ts_dev)
                return -ENOMEM;
 
        hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
-       hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
        hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 
-       hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN;
-       hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
-       hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX;
-       hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+       input_set_abs_params(hp680_ts_dev, ABS_X,
+               HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
+       input_set_abs_params(hp680_ts_dev, ABS_Y,
+               HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);
 
        hp680_ts_dev->name = "HP Jornada touchscreen";
        hp680_ts_dev->phys = "hp680_ts/input0";
 
-       input_register_device(hp680_ts_dev);
-
        if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
                        IRQF_DISABLED, MODNAME, 0) < 0) {
                printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
                       HP680_TS_IRQ);
-               input_unregister_device(hp680_ts_dev);
-               return -EBUSY;
+               err = -EBUSY;
+               goto fail1;
        }
 
+       err = input_register_device(hp680_ts_dev);
+       if (err)
+               goto fail2;
+
        return 0;
+
+ fail2:        free_irq(HP680_TS_IRQ, NULL);
+       cancel_delayed_work(&work);
+       flush_scheduled_work();
+ fail1:        input_free_device(hp680_ts_dev);
+       return err;
 }
 
 static void __exit hp680_ts_exit(void)
 {
-       free_irq(HP680_TS_IRQ, 0);
+       free_irq(HP680_TS_IRQ, NULL);
        cancel_delayed_work(&work);
        flush_scheduled_work();
        input_unregister_device(hp680_ts_dev);
index 4cbcaa6..44140fe 100644 (file)
@@ -96,15 +96,13 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id)
                goto end;
        }
 
-       if (~status & MK712_STATUS_TOUCH)
-       {
+       if (~status & MK712_STATUS_TOUCH) {
                debounce = 1;
                input_report_key(mk712_dev, BTN_TOUCH, 0);
                goto end;
        }
 
-       if (debounce)
-       {
+       if (debounce) {
                debounce = 0;
                goto end;
        }
@@ -113,8 +111,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id)
        input_report_abs(mk712_dev, ABS_X, last_x);
        input_report_abs(mk712_dev, ABS_Y, last_y);
 
-end:
-
+ end:
        last_x = inw(mk712_io + MK712_X) & 0x0fff;
        last_y = inw(mk712_io + MK712_Y) & 0x0fff;
        input_sync(mk712_dev);
@@ -169,13 +166,14 @@ static int __init mk712_init(void)
            (inw(mk712_io + MK712_STATUS) & 0xf333)) {
                printk(KERN_WARNING "mk712: device not present\n");
                err = -ENODEV;
-               goto fail;
+               goto fail1;
        }
 
-       if (!(mk712_dev = input_allocate_device())) {
+       mk712_dev = input_allocate_device();
+       if (!mk712_dev) {
                printk(KERN_ERR "mk712: not enough memory\n");
                err = -ENOMEM;
-               goto fail;
+               goto fail1;
        }
 
        mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
@@ -196,13 +194,17 @@ static int __init mk712_init(void)
        if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
                printk(KERN_WARNING "mk712: unable to get IRQ\n");
                err = -EBUSY;
-               goto fail;
+               goto fail1;
        }
 
-       input_register_device(mk712_dev);
+       err = input_register_device(mk712_dev);
+       if (err)
+               goto fail2;
+
        return 0;
 
- fail: input_free_device(mk712_dev);
+ fail2:        free_irq(mk712_irq, mk712_dev);
+ fail1:        input_free_device(mk712_dev);
        release_region(mk712_io, 8);
        return err;
 }
index 3b4c616..c3c2d73 100644 (file)
@@ -137,7 +137,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
        input_dev = input_allocate_device();
        if (!mtouch || !input_dev) {
                err = -ENOMEM;
-               goto fail;
+               goto fail1;
        }
 
        mtouch->serio = serio;
@@ -160,14 +160,17 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
 
        err = serio_open(serio, drv);
        if (err)
-               goto fail;
+               goto fail2;
 
-       input_register_device(mtouch->dev);
+       err = input_register_device(mtouch->dev);
+       if (err)
+               goto fail3;
 
        return 0;
 
- fail: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
        kfree(mtouch);
        return err;
 }
@@ -205,8 +208,7 @@ static struct serio_driver mtouch_drv = {
 
 static int __init mtouch_init(void)
 {
-       serio_register_driver(&mtouch_drv);
-       return 0;
+       return serio_register_driver(&mtouch_drv);
 }
 
 static void __exit mtouch_exit(void)
index 6c7d0c2..bd27679 100644 (file)
@@ -171,8 +171,7 @@ static struct serio_driver pm_drv = {
 
 static int __init pm_init(void)
 {
-       serio_register_driver(&pm_drv);
-       return 0;
+       return serio_register_driver(&pm_drv);
 }
 
 static void __exit pm_exit(void)
index c74f74e..35ba46c 100644 (file)
@@ -182,8 +182,7 @@ static struct serio_driver tr_drv = {
 
 static int __init tr_init(void)
 {
-       serio_register_driver(&tr_drv);
-       return 0;
+       return serio_register_driver(&tr_drv);
 }
 
 static void __exit tr_exit(void)
index 9911820..4dc073d 100644 (file)
@@ -189,8 +189,7 @@ static struct serio_driver tw_drv = {
 
 static int __init tw_init(void)
 {
-       serio_register_driver(&tw_drv);
-       return 0;
+       return serio_register_driver(&tw_drv);
 }
 
 static void __exit tw_exit(void)
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
new file mode 100644 (file)
index 0000000..4358a0a
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ *  Philips UCB1400 touchscreen driver
+ *
+ *  Author:    Nicolas Pitre
+ *  Created:   September 25, 2006
+ *  Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This code is heavily based on ucb1x00-*.c copyrighted by Russell King
+ * covering the UCB1100, UCB1200 and UCB1300..  Support for the UCB1400 has
+ * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/ac97_codec.h>
+
+
+/*
+ * Interesting UCB1400 AC-link registers
+ */
+
+#define UCB_IE_RIS             0x5e
+#define UCB_IE_FAL             0x60
+#define UCB_IE_STATUS          0x62
+#define UCB_IE_CLEAR           0x62
+#define UCB_IE_ADC             (1 << 11)
+#define UCB_IE_TSPX            (1 << 12)
+
+#define UCB_TS_CR              0x64
+#define UCB_TS_CR_TSMX_POW     (1 << 0)
+#define UCB_TS_CR_TSPX_POW     (1 << 1)
+#define UCB_TS_CR_TSMY_POW     (1 << 2)
+#define UCB_TS_CR_TSPY_POW     (1 << 3)
+#define UCB_TS_CR_TSMX_GND     (1 << 4)
+#define UCB_TS_CR_TSPX_GND     (1 << 5)
+#define UCB_TS_CR_TSMY_GND     (1 << 6)
+#define UCB_TS_CR_TSPY_GND     (1 << 7)
+#define UCB_TS_CR_MODE_INT     (0 << 8)
+#define UCB_TS_CR_MODE_PRES    (1 << 8)
+#define UCB_TS_CR_MODE_POS     (2 << 8)
+#define UCB_TS_CR_BIAS_ENA     (1 << 11)
+#define UCB_TS_CR_TSPX_LOW     (1 << 12)
+#define UCB_TS_CR_TSMX_LOW     (1 << 13)
+
+#define UCB_ADC_CR             0x66
+#define UCB_ADC_SYNC_ENA       (1 << 0)
+#define UCB_ADC_VREFBYP_CON    (1 << 1)
+#define UCB_ADC_INP_TSPX       (0 << 2)
+#define UCB_ADC_INP_TSMX       (1 << 2)
+#define UCB_ADC_INP_TSPY       (2 << 2)
+#define UCB_ADC_INP_TSMY       (3 << 2)
+#define UCB_ADC_INP_AD0                (4 << 2)
+#define UCB_ADC_INP_AD1                (5 << 2)
+#define UCB_ADC_INP_AD2                (6 << 2)
+#define UCB_ADC_INP_AD3                (7 << 2)
+#define UCB_ADC_EXT_REF                (1 << 5)
+#define UCB_ADC_START          (1 << 7)
+#define UCB_ADC_ENA            (1 << 15)
+
+#define UCB_ADC_DATA           0x68
+#define UCB_ADC_DAT_VALID      (1 << 15)
+#define UCB_ADC_DAT_VALUE(x)   ((x) & 0x3ff)
+
+#define UCB_ID                 0x7e
+#define UCB_ID_1400             0x4304
+
+
+struct ucb1400 {
+       ac97_t                  *ac97;
+       struct input_dev        *ts_idev;
+
+       int                     irq;
+
+       wait_queue_head_t       ts_wait;
+       struct task_struct      *ts_task;
+
+       unsigned int            irq_pending;    /* not bit field shared */
+       unsigned int            ts_restart:1;
+       unsigned int            adcsync:1;
+};
+
+static int adcsync;
+
+static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
+{
+       return ucb->ac97->bus->ops->read(ucb->ac97, reg);
+}
+
+static inline void ucb1400_reg_write(struct ucb1400 *ucb, u16 reg, u16 val)
+{
+       ucb->ac97->bus->ops->write(ucb->ac97, reg, val);
+}
+
+static inline void ucb1400_adc_enable(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+}
+
+static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
+{
+       unsigned int val;
+
+       if (ucb->adcsync)
+               adc_channel |= UCB_ADC_SYNC_ENA;
+
+       ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
+       ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel | UCB_ADC_START);
+
+       for (;;) {
+               val = ucb1400_reg_read(ucb, UCB_ADC_DATA);
+               if (val & UCB_ADC_DAT_VALID)
+                       break;
+               /* yield to other processes */
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+
+       return UCB_ADC_DAT_VALUE(val);
+}
+
+static inline void ucb1400_adc_disable(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
+}
+
+/* Switch to interrupt mode. */
+static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+                       UCB_TS_CR_MODE_INT);
+}
+
+/*
+ * Switch to pressure mode, and read pressure.  We don't need to wait
+ * here, since both plates are being driven.
+ */
+static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+}
+
+/*
+ * Switch to X position mode and measure Y plate.  We switch the plate
+ * configuration in pressure mode, then switch to position mode.  This
+ * gives a faster response time.  Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+       udelay(55);
+
+       return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+}
+
+/*
+ * Switch to Y position mode and measure X plate.  We switch the plate
+ * configuration in pressure mode, then switch to position mode.  This
+ * gives a faster response time.  Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+       udelay(55);
+
+       return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
+}
+
+/*
+ * Switch to X plate resistance mode.  Set MX to ground, PX to
+ * supply.  Measure current.
+ */
+static inline unsigned int ucb1400_ts_read_xres(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       return ucb1400_adc_read(ucb, 0);
+}
+
+/*
+ * Switch to Y plate resistance mode.  Set MY to ground, PY to
+ * supply.  Measure current.
+ */
+static inline unsigned int ucb1400_ts_read_yres(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       return ucb1400_adc_read(ucb, 0);
+}
+
+static inline int ucb1400_ts_pen_down(struct ucb1400 *ucb)
+{
+       unsigned short val = ucb1400_reg_read(ucb, UCB_TS_CR);
+       return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
+}
+
+static inline void ucb1400_ts_irq_enable(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, UCB_IE_TSPX);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+       ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_TSPX);
+}
+
+static inline void ucb1400_ts_irq_disable(struct ucb1400 *ucb)
+{
+       ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
+}
+
+static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y)
+{
+       input_report_abs(idev, ABS_X, x);
+       input_report_abs(idev, ABS_Y, y);
+       input_report_abs(idev, ABS_PRESSURE, pressure);
+       input_sync(idev);
+}
+
+static void ucb1400_ts_event_release(struct input_dev *idev)
+{
+       input_report_abs(idev, ABS_PRESSURE, 0);
+       input_sync(idev);
+}
+
+static void ucb1400_handle_pending_irq(struct ucb1400 *ucb)
+{
+       unsigned int isr;
+
+       isr = ucb1400_reg_read(ucb, UCB_IE_STATUS);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, isr);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       if (isr & UCB_IE_TSPX)
+               ucb1400_ts_irq_disable(ucb);
+       else
+               printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+
+       enable_irq(ucb->irq);
+}
+
+static int ucb1400_ts_thread(void *_ucb)
+{
+       struct ucb1400 *ucb = _ucb;
+       struct task_struct *tsk = current;
+       int valid = 0;
+
+       tsk->policy = SCHED_FIFO;
+       tsk->rt_priority = 1;
+
+       while (!kthread_should_stop()) {
+               unsigned int x, y, p;
+               long timeout;
+
+               ucb->ts_restart = 0;
+
+               if (ucb->irq_pending) {
+                       ucb->irq_pending = 0;
+                       ucb1400_handle_pending_irq(ucb);
+               }
+
+               ucb1400_adc_enable(ucb);
+               x = ucb1400_ts_read_xpos(ucb);
+               y = ucb1400_ts_read_ypos(ucb);
+               p = ucb1400_ts_read_pressure(ucb);
+               ucb1400_adc_disable(ucb);
+
+               /* Switch back to interrupt mode. */
+               ucb1400_ts_mode_int(ucb);
+
+               msleep(10);
+
+               if (ucb1400_ts_pen_down(ucb)) {
+                       ucb1400_ts_irq_enable(ucb);
+
+                       /*
+                        * If we spat out a valid sample set last time,
+                        * spit out a "pen off" sample here.
+                        */
+                       if (valid) {
+                               ucb1400_ts_event_release(ucb->ts_idev);
+                               valid = 0;
+                       }
+
+                       timeout = MAX_SCHEDULE_TIMEOUT;
+               } else {
+                       valid = 1;
+                       ucb1400_ts_evt_add(ucb->ts_idev, p, x, y);
+                       timeout = msecs_to_jiffies(10);
+               }
+
+               wait_event_interruptible_timeout(ucb->ts_wait,
+                       ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
+                       timeout);
+               try_to_freeze();
+       }
+
+       /* Send the "pen off" if we are stopping with the pen still active */
+       if (valid)
+               ucb1400_ts_event_release(ucb->ts_idev);
+
+       ucb->ts_task = NULL;
+       return 0;
+}
+
+/*
+ * A restriction with interrupts exists when using the ucb1400, as
+ * the codec read/write routines may sleep while waiting for codec
+ * access completion and uses semaphores for access control to the
+ * AC97 bus.  A complete codec read cycle could take  anywhere from
+ * 60 to 100uSec so we *definitely* don't want to spin inside the
+ * interrupt handler waiting for codec access.  So, we handle the
+ * interrupt by scheduling a RT kernel thread to run in process
+ * context instead of interrupt context.
+ */
+static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
+{
+       struct ucb1400 *ucb = devid;
+
+       if (irqnr == ucb->irq) {
+               disable_irq(ucb->irq);
+               ucb->irq_pending = 1;
+               wake_up(&ucb->ts_wait);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+static int ucb1400_ts_open(struct input_dev *idev)
+{
+       struct ucb1400 *ucb = idev->private;
+       int ret = 0;
+
+       BUG_ON(ucb->ts_task);
+
+       ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts");
+       if (IS_ERR(ucb->ts_task)) {
+               ret = PTR_ERR(ucb->ts_task);
+               ucb->ts_task = NULL;
+       }
+
+       return ret;
+}
+
+static void ucb1400_ts_close(struct input_dev *idev)
+{
+       struct ucb1400 *ucb = idev->private;
+
+       if (ucb->ts_task)
+               kthread_stop(ucb->ts_task);
+
+       ucb1400_ts_irq_disable(ucb);
+       ucb1400_reg_write(ucb, UCB_TS_CR, 0);
+}
+
+#ifdef CONFIG_PM
+static int ucb1400_ts_resume(struct device *dev)
+{
+       struct ucb1400 *ucb = dev_get_drvdata(dev);
+
+       if (ucb->ts_task) {
+               /*
+                * Restart the TS thread to ensure the
+                * TS interrupt mode is set up again
+                * after sleep.
+                */
+               ucb->ts_restart = 1;
+               wake_up(&ucb->ts_wait);
+       }
+       return 0;
+}
+#else
+#define ucb1400_ts_resume NULL
+#endif
+
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
+/*
+ * Try to probe our interrupt, rather than relying on lots of
+ * hard-coded machine dependencies.
+ */
+static int ucb1400_detect_irq(struct ucb1400 *ucb)
+{
+       unsigned long mask, timeout;
+
+       mask = probe_irq_on();
+       if (!mask) {
+               probe_irq_off(mask);
+               return -EBUSY;
+       }
+
+       /* Enable the ADC interrupt. */
+       ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+       ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       /* Cause an ADC interrupt. */
+       ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+       ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+
+       /* Wait for the conversion to complete. */
+       timeout = jiffies + HZ/2;
+       while (!(ucb1400_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VALID)) {
+               cpu_relax();
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "ucb1400: timed out in IRQ probe\n");
+                       probe_irq_off(mask);
+                       return -ENODEV;
+               }
+       }
+       ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
+
+       /* Disable and clear interrupt. */
+       ucb1400_reg_write(ucb, UCB_IE_RIS, 0);
+       ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+       ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       /* Read triggered interrupt. */
+       ucb->irq = probe_irq_off(mask);
+       if (ucb->irq < 0 || ucb->irq == NO_IRQ)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int ucb1400_ts_probe(struct device *dev)
+{
+       struct ucb1400 *ucb;
+       struct input_dev *idev;
+       int error, id, x_res, y_res;
+
+       ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL);
+       idev = input_allocate_device();
+       if (!ucb || !idev) {
+               error = -ENOMEM;
+               goto err_free_devs;
+       }
+
+       ucb->ts_idev = idev;
+       ucb->adcsync = adcsync;
+       ucb->ac97 = to_ac97_t(dev);
+       init_waitqueue_head(&ucb->ts_wait);
+
+       id = ucb1400_reg_read(ucb, UCB_ID);
+       if (id != UCB_ID_1400) {
+               error = -ENODEV;
+               goto err_free_devs;
+       }
+
+       error = ucb1400_detect_irq(ucb);
+       if (error) {
+               printk(KERN_ERR "UCB1400: IRQ probe failed\n");
+               goto err_free_devs;
+       }
+
+       error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING,
+                               "UCB1400", ucb);
+       if (error) {
+               printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n",
+                               ucb->irq, error);
+               goto err_free_devs;
+       }
+       printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
+
+       idev->private           = ucb;
+       idev->cdev.dev          = dev;
+       idev->name              = "UCB1400 touchscreen interface";
+       idev->id.vendor         = ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
+       idev->id.product        = id;
+       idev->open              = ucb1400_ts_open;
+       idev->close             = ucb1400_ts_close;
+       idev->evbit[0]          = BIT(EV_ABS);
+
+       ucb1400_adc_enable(ucb);
+       x_res = ucb1400_ts_read_xres(ucb);
+       y_res = ucb1400_ts_read_yres(ucb);
+       ucb1400_adc_disable(ucb);
+       printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res);
+
+       input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0);
+       input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0);
+       input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
+
+       error = input_register_device(idev);
+       if (error)
+               goto err_free_irq;
+
+       dev_set_drvdata(dev, ucb);
+       return 0;
+
+ err_free_irq:
+       free_irq(ucb->irq, ucb);
+ err_free_devs:
+       input_free_device(idev);
+       kfree(ucb);
+       return error;
+}
+
+static int ucb1400_ts_remove(struct device *dev)
+{
+       struct ucb1400 *ucb = dev_get_drvdata(dev);
+
+       free_irq(ucb->irq, ucb);
+       input_unregister_device(ucb->ts_idev);
+       dev_set_drvdata(dev, NULL);
+       kfree(ucb);
+       return 0;
+}
+
+static struct device_driver ucb1400_ts_driver = {
+       .owner          = THIS_MODULE,
+       .bus            = &ac97_bus_type,
+       .probe          = ucb1400_ts_probe,
+       .remove         = ucb1400_ts_remove,
+       .resume         = ucb1400_ts_resume,
+};
+
+static int __init ucb1400_ts_init(void)
+{
+       return driver_register(&ucb1400_ts_driver);
+}
+
+static void __exit ucb1400_ts_exit(void)
+{
+       driver_unregister(&ucb1400_ts_driver);
+}
+
+module_param(adcsync, int, 0444);
+
+module_init(ucb1400_ts_init);
+module_exit(ucb1400_ts_exit);
+
+MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver");
+MODULE_LICENSE("GPL");
index 6ae6eb3..946c38c 100644 (file)
@@ -627,8 +627,10 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
 }
 
 void
-actcapi_dispatch(act2000_card *card)
+actcapi_dispatch(struct work_struct *work)
 {
+       struct act2000_card *card =
+               container_of(work, struct act2000_card, rcv_tq);
        struct sk_buff *skb;
        actcapi_msg *msg;
        __u16 ccmd;
index 49f453c..e55f6a9 100644 (file)
@@ -356,7 +356,7 @@ extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int
 extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *);
 extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *);
 extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8);
-extern void actcapi_dispatch(act2000_card *);
+extern void actcapi_dispatch(struct work_struct *);
 #ifdef DEBUG_MSG
 extern void actcapi_debug_msg(struct sk_buff *skb, int);
 #else
index d89dcde..e3e5c13 100644 (file)
@@ -192,8 +192,11 @@ act2000_set_msn(act2000_card *card, char *eazmsn)
 }
 
 static void
-act2000_transmit(struct act2000_card *card)
+act2000_transmit(struct work_struct *work)
 {
+       struct act2000_card *card =
+               container_of(work, struct act2000_card, snd_tq);
+
        switch (card->bus) {
                case ACT2000_BUS_ISA:
                        act2000_isa_send(card);
@@ -207,8 +210,11 @@ act2000_transmit(struct act2000_card *card)
 }
 
 static void
-act2000_receive(struct act2000_card *card)
+act2000_receive(struct work_struct *work)
 {
+       struct act2000_card *card =
+               container_of(work, struct act2000_card, poll_tq);
+
        switch (card->bus) {
                case ACT2000_BUS_ISA:
                        act2000_isa_receive(card);
@@ -227,7 +233,7 @@ act2000_poll(unsigned long data)
        act2000_card * card = (act2000_card *)data;
        unsigned long flags;
 
-       act2000_receive(card);
+       act2000_receive(&card->poll_tq);
        spin_lock_irqsave(&card->lock, flags);
        mod_timer(&card->ptimer, jiffies+3);
        spin_unlock_irqrestore(&card->lock, flags);
@@ -567,20 +573,19 @@ act2000_alloccard(int bus, int port, int irq, char *id)
 {
        int i;
         act2000_card *card;
-        if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) {
+        if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) {
                 printk(KERN_WARNING
                       "act2000: (%s) Could not allocate card-struct.\n", id);
                 return;
         }
-        memset((char *) card, 0, sizeof(act2000_card));
         spin_lock_init(&card->lock);
         spin_lock_init(&card->mnlock);
        skb_queue_head_init(&card->sndq);
        skb_queue_head_init(&card->rcvq);
        skb_queue_head_init(&card->ackq);
-       INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card);
-       INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card);
-       INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card);
+       INIT_WORK(&card->snd_tq, act2000_transmit);
+       INIT_WORK(&card->rcv_tq, actcapi_dispatch);
+       INIT_WORK(&card->poll_tq, act2000_receive);
        init_timer(&card->ptimer);
        card->interface.owner = THIS_MODULE;
         card->interface.channels = ACT2000_BCH;
index 11844bb..d22c022 100644 (file)
@@ -215,13 +215,12 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
        unsigned int minor = 0;
        unsigned long flags;
 
-       mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
+       mp = kzalloc(sizeof(*mp), GFP_ATOMIC);
        if (!mp) {
                printk(KERN_ERR "capi: can't alloc capiminor\n");
                return NULL;
        }
 
-       memset(mp, 0, sizeof(struct capiminor));
        mp->ap = ap;
        mp->ncci = ncci;
        mp->msgid = 0;
@@ -304,10 +303,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
        struct capiminor *mp = NULL;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
-       np = kmalloc(sizeof(*np), GFP_ATOMIC);
+       np = kzalloc(sizeof(*np), GFP_ATOMIC);
        if (!np)
                return NULL;
-       memset(np, 0, sizeof(struct capincci));
        np->ncci = ncci;
        np->cdev = cdev;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -384,10 +382,9 @@ static struct capidev *capidev_alloc(void)
        struct capidev *cdev;
        unsigned long flags;
 
-       cdev = kmalloc(sizeof(*cdev), GFP_KERNEL);
+       cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
        if (!cdev)
                return NULL;
-       memset(cdev, 0, sizeof(struct capidev));
 
        init_MUTEX(&cdev->ncci_list_sem);
        skb_queue_head_init(&cdev->recvqueue);
@@ -1010,7 +1007,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
        struct capiminor *mp;
 
-       if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0)
+       if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
                return -ENXIO;
        if (mp->nccip == 0)
                return -ENXIO;
@@ -1203,7 +1200,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
        return error;
 }
 
-static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
 {
 #ifdef _DEBUG_TTYFUNCS
        printk(KERN_DEBUG "capinc_tty_set_termios\n");
index b6f9476..097bfa7 100644 (file)
@@ -334,12 +334,11 @@ static capidrv_plci *new_plci(capidrv_contr * card, int chan)
 {
        capidrv_plci *plcip;
 
-       plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);
+       plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
 
        if (plcip == 0)
                return NULL;
 
-       memset(plcip, 0, sizeof(capidrv_plci));
        plcip->state = ST_PLCI_NONE;
        plcip->plci = 0;
        plcip->msgid = 0;
@@ -404,12 +403,11 @@ static inline capidrv_ncci *new_ncci(capidrv_contr * card,
 {
        capidrv_ncci *nccip;
 
-       nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
+       nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
 
        if (nccip == 0)
                return NULL;
 
-       memset(nccip, 0, sizeof(capidrv_ncci));
        nccip->ncci = ncci;
        nccip->state = ST_NCCI_NONE;
        nccip->plcip = plcip;
@@ -2005,12 +2003,11 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
                printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
                return -1;
        }
-       if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
+       if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
                printk(KERN_WARNING
                 "capidrv: (%s) Could not allocate contr-struct.\n", id);
                return -1;
        }
-       memset(card, 0, sizeof(capidrv_contr));
        card->owner = THIS_MODULE;
        init_timer(&card->listentimer);
        strcpy(card->name, id);
index 8c4fcb9..783a255 100644 (file)
@@ -208,9 +208,10 @@ static void notify_down(u32 contr)
        }
 }
 
-static void notify_handler(void *data)
+static void notify_handler(struct work_struct *work)
 {
-       struct capi_notifier *np = data;
+       struct capi_notifier *np =
+               container_of(work, struct capi_notifier, work);
 
        switch (np->cmd) {
        case KCI_CONTRUP:
@@ -235,7 +236,7 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci)
        if (!np)
                return -ENOMEM;
 
-       INIT_WORK(&np->work, notify_handler, np);
+       INIT_WORK(&np->work, notify_handler);
        np->cmd = cmd;
        np->controller = controller;
        np->applid = applid;
@@ -248,10 +249,11 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci)
        
 /* -------- Receiver ------------------------------------------ */
 
-static void recv_handler(void *_ap)
+static void recv_handler(struct work_struct *work)
 {
        struct sk_buff *skb;
-       struct capi20_appl *ap = (struct capi20_appl *) _ap;
+       struct capi20_appl *ap =
+               container_of(work, struct capi20_appl, recv_work);
 
        if ((!ap) || (ap->release_in_progress))
                return;
@@ -527,7 +529,7 @@ u16 capi20_register(struct capi20_appl *ap)
        ap->callback = NULL;
        init_MUTEX(&ap->recv_sem);
        skb_queue_head_init(&ap->recv_queue);
-       INIT_WORK(&ap->recv_work, recv_handler, (void *)ap);
+       INIT_WORK(&ap->recv_work, recv_handler);
        ap->release_in_progress = 0;
 
        write_unlock_irqrestore(&application_lock, flags);
index 5b203fe..708d47a 100644 (file)
@@ -5,6 +5,7 @@ config ISDN_DRV_GIGASET
        tristate "Siemens Gigaset support (isdn)"
        depends on ISDN_I4L
        select CRC_CCITT
+       select BITREVERSE
        help
          Say m here if you have a Gigaset or Sinus isdn device.
 
index ce3cd77..88e958f 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
+#include <linux/bitrev.h>
 
 //#define GIG_M10x_STUFF_VOICE_DATA
 
@@ -302,7 +303,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
                                inputstate |= INS_skip_frame;
                                break;
                        }
-                       *__skb_put(skb, 1) = gigaset_invtab[c];
+                       *__skb_put(skb, 1) = bitrev8(c);
                }
 
                if (unlikely(!numbytes))
@@ -543,7 +544,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
        cp = skb->data;
        len = skb->len;
        while (len--) {
-               c = gigaset_invtab[*cp++];
+               c = bitrev8(*cp++);
                if (c == DLE_FLAG)
                        *(skb_put(iraw_skb, 1)) = c;
                *(skb_put(iraw_skb, 1)) = c;
index 0c93732..63b629b 100644 (file)
@@ -572,7 +572,7 @@ static int atread_submit(struct cardstate *cs, int timeout)
                             ucs->rcvbuf, ucs->rcvbuf_size,
                             read_ctrl_callback, cs->inbuf);
 
-       if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
+       if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) {
                update_basstate(ucs, 0, BS_ATRDPEND);
                dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
                        get_usb_rcmsg(ret));
@@ -747,7 +747,7 @@ static void read_int_callback(struct urb *urb)
        check_pending(ucs);
 
 resubmit:
-       rc = usb_submit_urb(urb, SLAB_ATOMIC);
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
        if (unlikely(rc != 0 && rc != -ENODEV)) {
                dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
                        get_usb_rcmsg(rc));
@@ -807,7 +807,7 @@ static void read_iso_callback(struct urb *urb)
                        urb->number_of_packets = BAS_NUMFRAMES;
                        gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
                                __func__);
-                       rc = usb_submit_urb(urb, SLAB_ATOMIC);
+                       rc = usb_submit_urb(urb, GFP_ATOMIC);
                        if (unlikely(rc != 0 && rc != -ENODEV)) {
                                dev_err(bcs->cs->dev,
                                        "could not resubmit isochronous read "
@@ -900,7 +900,7 @@ static int starturbs(struct bc_state *bcs)
                }
 
                dump_urb(DEBUG_ISO, "Initial isoc read", urb);
-               if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0)
+               if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
                        goto error;
        }
 
@@ -935,7 +935,7 @@ static int starturbs(struct bc_state *bcs)
        /* submit two URBs, keep third one */
        for (k = 0; k < 2; ++k) {
                dump_urb(DEBUG_ISO, "Initial isoc write", urb);
-               rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
+               rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC);
                if (rc != 0)
                        goto error;
        }
@@ -1042,7 +1042,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
                return 0;       /* no data to send */
        urb->number_of_packets = nframe;
 
-       rc = usb_submit_urb(urb, SLAB_ATOMIC);
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
        if (unlikely(rc)) {
                if (rc == -ENODEV)
                        /* device removed - give up silently */
@@ -1341,7 +1341,7 @@ static void read_iso_tasklet(unsigned long data)
                urb->dev = bcs->cs->hw.bas->udev;
                urb->transfer_flags = URB_ISO_ASAP;
                urb->number_of_packets = BAS_NUMFRAMES;
-               rc = usb_submit_urb(urb, SLAB_ATOMIC);
+               rc = usb_submit_urb(urb, GFP_ATOMIC);
                if (unlikely(rc != 0 && rc != -ENODEV)) {
                        dev_err(cs->dev,
                                "could not resubmit isochronous read URB: %s\n",
@@ -1458,7 +1458,7 @@ static void write_ctrl_callback(struct urb *urb)
                           ucs->retry_ctrl);
                /* urb->dev is clobbered by USB subsystem */
                urb->dev = ucs->udev;
-               rc = usb_submit_urb(urb, SLAB_ATOMIC);
+               rc = usb_submit_urb(urb, GFP_ATOMIC);
                if (unlikely(rc)) {
                        dev_err(&ucs->interface->dev,
                                "could not resubmit request 0x%02x: %s\n",
@@ -1517,7 +1517,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
                             (unsigned char*) &ucs->dr_ctrl, NULL, 0,
                             write_ctrl_callback, ucs);
        ucs->retry_ctrl = 0;
-       ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC);
+       ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC);
        if (unlikely(ret)) {
                dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n",
                        req, get_usb_rcmsg(ret));
@@ -1763,7 +1763,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
                             usb_sndctrlpipe(ucs->udev, 0),
                             (unsigned char*) &ucs->dr_cmd_out, buf, len,
                             write_command_callback, cs);
-       rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC);
+       rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC);
        if (unlikely(rc)) {
                update_basstate(ucs, 0, BS_ATWRPEND);
                dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
@@ -2218,21 +2218,21 @@ static int gigaset_probe(struct usb_interface *interface,
         * - three for the different uses of the default control pipe
         * - three for each isochronous pipe
         */
-       if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
-           !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
-           !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) ||
-           !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL)))
+       if (!(ucs->urb_int_in = usb_alloc_urb(0, GFP_KERNEL)) ||
+           !(ucs->urb_cmd_in = usb_alloc_urb(0, GFP_KERNEL)) ||
+           !(ucs->urb_cmd_out = usb_alloc_urb(0, GFP_KERNEL)) ||
+           !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL)))
                goto allocerr;
 
        for (j = 0; j < 2; ++j) {
                ubc = cs->bcs[j].hw.bas;
                for (i = 0; i < BAS_OUTURBS; ++i)
                        if (!(ubc->isoouturbs[i].urb =
-                             usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+                             usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL)))
                                goto allocerr;
                for (i = 0; i < BAS_INURBS; ++i)
                        if (!(ubc->isoinurbs[i] =
-                             usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+                             usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL)))
                                goto allocerr;
        }
 
@@ -2246,7 +2246,7 @@ static int gigaset_probe(struct usb_interface *interface,
                                        (endpoint->bEndpointAddress) & 0x0f),
                         ucs->int_in_buf, 3, read_int_callback, cs,
                         endpoint->bInterval);
-       if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) {
+       if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) {
                dev_err(cs->dev, "could not submit interrupt URB: %s\n",
                        get_usb_rcmsg(rc));
                goto error;
index defd574..95eff3b 100644 (file)
@@ -33,43 +33,6 @@ MODULE_PARM_DESC(debug, "debug level");
 #define VALID_ID       0x02
 #define ASSIGNED       0x04
 
-/* bitwise byte inversion table */
-__u8 gigaset_invtab[256] = {
-       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-EXPORT_SYMBOL_GPL(gigaset_invtab);
-
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
                        size_t len, const unsigned char *buf)
 {
index 06298cc..a0317ab 100644 (file)
@@ -876,10 +876,6 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb,
        }
 }
 
-
-/* bitwise byte inversion table */
-extern __u8 gigaset_invtab[];  /* in common.c */
-
 /* append received bytes to inbuf */
 int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
                       unsigned numbytes);
index 7edea01..458b646 100644 (file)
@@ -127,7 +127,7 @@ static int  if_write_room(struct tty_struct *tty);
 static int  if_chars_in_buffer(struct tty_struct *tty);
 static void if_throttle(struct tty_struct *tty);
 static void if_unthrottle(struct tty_struct *tty);
-static void if_set_termios(struct tty_struct *tty, struct termios *old);
+static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
 static int  if_tiocmget(struct tty_struct *tty, struct file *file);
 static int  if_tiocmset(struct tty_struct *tty, struct file *file,
                        unsigned int set, unsigned int clear);
@@ -490,7 +490,7 @@ static void if_unthrottle(struct tty_struct *tty)
        mutex_unlock(&cs->mutex);
 }
 
-static void if_set_termios(struct tty_struct *tty, struct termios *old)
+static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
        struct cardstate *cs;
        unsigned int iflag;
index 8667daa..df988eb 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
+#include <linux/bitrev.h>
 
 /* access methods for isowbuf_t */
 /* ============================ */
@@ -487,7 +488,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
        gig_dbg(DEBUG_STREAM, "put %d bytes", count);
        write = atomic_read(&iwb->write);
        do {
-               c = gigaset_invtab[*in++];
+               c = bitrev8(*in++);
                iwb->data[write++] = c;
                write %= BAS_OUTBUFSIZE;
        } while (--count > 0);
@@ -876,7 +877,7 @@ static inline void trans_receive(unsigned char *src, unsigned count,
        while (count > 0) {
                dst = skb_put(skb, count < dobytes ? count : dobytes);
                while (count > 0 && dobytes > 0) {
-                       *dst++ = gigaset_invtab[*src++];
+                       *dst++ = bitrev8(*src++);
                        count--;
                        dobytes--;
                }
index 5ebf49a..04f2ad7 100644 (file)
@@ -410,7 +410,7 @@ static void gigaset_read_int_callback(struct urb *urb)
 
        if (resubmit) {
                spin_lock_irqsave(&cs->lock, flags);
-               r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+               r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV;
                spin_unlock_irqrestore(&cs->lock, flags);
                if (r)
                        dev_err(cs->dev, "error %d when resubmitting urb.\n",
@@ -486,7 +486,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
                        atomic_set(&ucs->busy, 1);
 
                        spin_lock_irqsave(&cs->lock, flags);
-                       status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
+                       status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV;
                        spin_unlock_irqrestore(&cs->lock, flags);
 
                        if (status) {
@@ -664,7 +664,7 @@ static int write_modem(struct cardstate *cs)
                                                  ucs->bulk_out_endpointAddr & 0x0f),
                                  ucs->bulk_out_buffer, count,
                                  gigaset_write_bulk_callback, cs);
-               ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+               ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC);
        } else {
                ret = -ENODEV;
        }
@@ -763,7 +763,7 @@ static int gigaset_probe(struct usb_interface *interface,
                goto error;
        }
 
-       ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
+       ucs->bulk_out_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!ucs->bulk_out_urb) {
                dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n");
                retval = -ENOMEM;
@@ -774,7 +774,7 @@ static int gigaset_probe(struct usb_interface *interface,
 
        atomic_set(&ucs->busy, 0);
 
-       ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
+       ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!ucs->read_urb) {
                dev_err(cs->dev, "No free urbs available\n");
                retval = -ENOMEM;
@@ -797,7 +797,7 @@ static int gigaset_probe(struct usb_interface *interface,
                         gigaset_read_int_callback,
                         cs->inbuf + 0, endpoint->bInterval);
 
-       retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
+       retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL);
        if (retval) {
                dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval);
                goto error;
index fd5d736..eba1046 100644 (file)
@@ -121,10 +121,9 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
     p_dev->conf.Present = PRESENT_OPTION;
 
     /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local)
         goto err;
-    memset(local, 0, sizeof(local_info_t));
     p_dev->priv = local;
 
     return avmcs_config(p_dev);
index da27292..7a69a18 100644 (file)
@@ -65,18 +65,15 @@ avmcard *b1_alloc_card(int nr_controllers)
        avmctrl_info *cinfo;
        int i;
 
-       card = kmalloc(sizeof(*card), GFP_KERNEL);
+       card = kzalloc(sizeof(*card), GFP_KERNEL);
        if (!card)
                return NULL;
 
-       memset(card, 0, sizeof(*card));
-
-        cinfo = kmalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
+       cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
        if (!cinfo) {
                kfree(card);
                return NULL;
        }
-       memset(cinfo, 0, sizeof(*cinfo) * nr_controllers);
 
        card->ctrlinfo = cinfo;
        for (i = 0; i < nr_controllers; i++) {
@@ -718,12 +715,11 @@ avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
        avmcard_dmainfo *p;
        void *buf;
 
-       p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
+       p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
        if (!p) {
                printk(KERN_WARNING "%s: no memory.\n", name);
                goto err;
        }
-       memset(p, 0, sizeof(avmcard_dmainfo));
 
        p->recvbuf.size = rsize;
        buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
index e47c60b..c925020 100644 (file)
@@ -584,6 +584,7 @@ static void __exit t1isa_exit(void)
 {
        int i;
 
+       unregister_capi_driver(&capi_driver_t1isa);
        for (i = 0; i < MAX_CARDS; i++) {
                if (!io[i])
                        break;
index 6851c62..d835e74 100644 (file)
@@ -756,14 +756,14 @@ int diva_get_driver_info (dword id, byte* data, int data_length) {
 
     data_length -= 9;
 
-    if ((to_copy = MIN(strlen(clients[id].drvName), data_length-1))) {
+    if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length-1)))) {
       memcpy (p, clients[id].drvName, to_copy);
       p += to_copy;
       data_length -= to_copy;
       if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) {
         *p++ = '(';
         data_length -= 1;
-        if ((to_copy = MIN(strlen(clients[id].hDbg->drvTag), data_length-2))) {
+        if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length-2)))) {
           memcpy (p, clients[id].hDbg->drvTag, to_copy);
           p += to_copy;
           data_length -= to_copy;
index 0617d7c..e1df8d9 100644 (file)
@@ -133,7 +133,7 @@ void pr_out(ADAPTER * a)
     i = this->XCurrent;
     X = PTR_X(a,this);
     while(i<this->XNum && length<270) {
-      clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
+      clength = min((word)(270-length),(word)(X[i].PLength-this->XOffset));
       a->ram_out_buffer(a,
                         &ReqOut->XBuffer.P[length],
                         PTR_P(a,this,&X[i].P[this->XOffset]),
@@ -622,7 +622,7 @@ byte isdn_ind(ADAPTER * a,
                                                      sizeof(a->stream_buffer),
                                                      &final, NULL, NULL);
         }
-        IoAdapter->RBuffer.length = MIN(MLength, 270);
+        IoAdapter->RBuffer.length = min(MLength, (word)270);
         if (IoAdapter->RBuffer.length != MLength) {
           this->complete = 0;
         } else {
@@ -676,9 +676,9 @@ byte isdn_ind(ADAPTER * a,
         this->RCurrent++;
       }
       if (cma) {
-        clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset);
+        clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
       } else {
-        clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
+        clength = min(a->ram_inw(a, &RBuffer->length)-offset,
                       R[this->RCurrent].PLength-this->ROffset);
       }
       if(R[this->RCurrent].P) {
index dae2e83..91fc92c 100644 (file)
@@ -185,7 +185,7 @@ void diva_log_info(unsigned char *format, ...)
        unsigned char line[160];
 
        va_start(args, format);
-       vsprintf(line, format, args);
+       vsnprintf(line, sizeof(line), format, args);
        va_end(args);
 
        printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line);
index 4a27e23..6fd9b00 100644 (file)
@@ -262,7 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
     case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
        diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
        memset (&prms, 0x00, sizeof(prms));
-       prms.structure_length = MIN(sizeof(prms), pI->structure_length);
+       prms.structure_length = min_t(size_t, sizeof(prms), pI->structure_length);
        memset (pI, 0x00, pI->structure_length);
        prms.flag_dynamic_l1_down    = (IoAdapter->capi_cfg.cfg_1 & \
          DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0;
index 2313966..18f8798 100644 (file)
@@ -92,7 +92,7 @@ int diva_istream_write (void* context,
     return (-1); /* was not able to write       */
    break;     /* only part of message was written */
   }
-  to_write = MIN(length, DIVA_DFIFO_DATA_SZ);
+  to_write = min(length, DIVA_DFIFO_DATA_SZ);
   if (to_write) {
    a->ram_out_buffer (a,
 #ifdef PLATFORM_GT_32BIT
@@ -176,7 +176,7 @@ int diva_istream_read (void* context,
     return (-1); /* was not able to read */
    break;
   }
-  to_read = MIN(max_length, tmp[1]);
+  to_read = min(max_length, (int)tmp[1]);
   if (to_read) {
    a->ram_in_buffer(a,
 #ifdef PLATFORM_GT_32BIT
index a66836c..2444811 100644 (file)
 #define        NULL    ((void *) 0)
 #endif
 
-#ifndef        MIN
-#define MIN(a,b)       ((a)>(b) ? (b) : (a))
-#endif
-
-#ifndef        MAX
-#define MAX(a,b)       ((a)>(b) ? (a) : (b))
-#endif
-
 #ifndef        far
 #define far
 #endif
index cfd2718..34ab5f7 100644 (file)
@@ -110,7 +110,7 @@ config HISAX_16_3
 
 config HISAX_TELESPCI
        bool "Teles PCI"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
        help
          This enables HiSax support for the Teles PCI.
          See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -238,7 +238,7 @@ config HISAX_MIC
 
 config HISAX_NETJET
        bool "NETjet card"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
        help
          This enables HiSax support for the NetJet from Traverse
          Technologies.
@@ -249,7 +249,7 @@ config HISAX_NETJET
 
 config HISAX_NETJET_U
        bool "NETspider U card"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
        help
          This enables HiSax support for the Netspider U interface ISDN card
          from Traverse Technologies.
@@ -317,7 +317,7 @@ config HISAX_GAZEL
 
 config HISAX_HFC_PCI
        bool "HFC PCI-Bus cards"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
        help
          This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
 
@@ -344,18 +344,11 @@ config HISAX_HFC_SX
 
 config HISAX_ENTERNOW_PCI
        bool "Formula-n enter:now PCI card"
-       depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+       depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
        help
          This enables HiSax support for the Formula-n enter:now PCI
          ISDN card.
 
-config HISAX_AMD7930
-       bool "Am7930 (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && SPARC && BROKEN
-       help
-         This enables HiSax support for the AMD7930 chips on some SPARCs.
-         This code is not finished yet.
-
 endif
 
 if ISDN_DRV_HISAX
@@ -402,6 +395,7 @@ config HISAX_ST5481
        tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
        depends on USB && EXPERIMENTAL
        select CRC_CCITT
+       select BITREVERSE
        help
          This enables the driver for ST5481 based USB ISDN adapters,
          e.g. the BeWan Gazel 128 USB
index bec5901..3b19cae 100644 (file)
@@ -232,9 +232,10 @@ Amd7930_new_ph(struct IsdnCardState *cs)
 
 
 static void
-Amd7930_bh(struct IsdnCardState *cs)
+Amd7930_bh(struct work_struct *work)
 {
-
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
         struct PStack *stptr;
 
        if (!cs)
@@ -789,7 +790,7 @@ Amd7930_init(struct IsdnCardState *cs)
 void __devinit
 setup_Amd7930(struct IsdnCardState *cs)
 {
-        INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs);
+        INIT_WORK(&cs->tqueue, Amd7930_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
        cs->dbusytimer.data = (long) cs;
        init_timer(&cs->dbusytimer);
index 876fec6..9e70c20 100644 (file)
@@ -123,11 +123,10 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
     DEBUG(0, "avma1cs_attach()\n");
 
     /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local)
        return -ENOMEM;
 
-    memset(local, 0, sizeof(local_info_t));
     p_dev->priv = local;
 
     /* The io structure describes IO port mapping */
index 785b085..17ec0b7 100644 (file)
@@ -227,14 +227,6 @@ const char *CardType[] = {
 #define DEFAULT_CFG {5,0x2E0,0,0}
 #endif
 
-
-#ifdef CONFIG_HISAX_AMD7930
-#undef DEFAULT_CARD
-#undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_AMD7930
-#define DEFAULT_CFG {12,0x3e0,0,0}
-#endif
-
 #ifdef CONFIG_HISAX_NICCY
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -545,10 +537,6 @@ extern int setup_hfcpci(struct IsdnCard *card);
 extern int setup_hfcsx(struct IsdnCard *card);
 #endif
 
-#if CARD_AMD7930
-extern int setup_amd7930(struct IsdnCard *card);
-#endif
-
 #if CARD_NICCY
 extern int setup_niccy(struct IsdnCard *card);
 #endif
@@ -869,14 +857,13 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
        struct IsdnCard *card = cards + cardnr;
        struct IsdnCardState *cs;
 
-       cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+       cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
        if (!cs) {
                printk(KERN_WARNING
                       "HiSax: No memory for IsdnCardState(card %d)\n",
                       cardnr + 1);
                goto out;
        }
-       memset(cs, 0, sizeof(struct IsdnCardState));
        card->cs = cs;
        spin_lock_init(&cs->statlock);
        spin_lock_init(&cs->lock);
@@ -1064,11 +1051,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
                ret = setup_niccy(card);
                break;
 #endif
-#if CARD_AMD7930
-       case ISDN_CTYPE_AMD7930:
-               ret = setup_amd7930(card);
-               break;
-#endif
 #if CARD_ISURF
        case ISDN_CTYPE_ISURF:
                ret = setup_isurf(card);
@@ -1137,7 +1119,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
        cs->tx_skb = NULL;
        cs->tx_cnt = 0;
        cs->event = 0;
-       cs->tqueue.data = cs;
 
        skb_queue_head_init(&cs->rq);
        skb_queue_head_init(&cs->sq);
@@ -1438,7 +1419,6 @@ static int __init HiSax_init(void)
                        break;
                case ISDN_CTYPE_ELSA_PCI:
                case ISDN_CTYPE_NETJET_S:
-               case ISDN_CTYPE_AMD7930:
                case ISDN_CTYPE_TELESPCI:
                case ISDN_CTYPE_W6692:
                case ISDN_CTYPE_NETJET_U:
@@ -1554,7 +1534,7 @@ static void hisax_b_l2l1(struct PStack *st, int pr, void *arg);
 static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg);
 static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs);
 static void hisax_bc_close(struct BCState *bcs);
-static void hisax_bh(struct IsdnCardState *cs);
+static void hisax_bh(struct work_struct *work);
 static void EChannel_proc_rcv(struct hisax_d_if *d_if);
 
 int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
@@ -1586,7 +1566,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
        hisax_d_if->cs = cs;
        cs->hw.hisax_d_if = hisax_d_if;
        cs->cardmsg = hisax_cardmsg;
-       INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs);
+       INIT_WORK(&cs->tqueue, hisax_bh);
        cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1;
        for (i = 0; i < 2; i++) {
                cs->bcs[i].BC_SetStack = hisax_bc_setstack;
@@ -1618,8 +1598,10 @@ static void hisax_sched_event(struct IsdnCardState *cs, int event)
        schedule_work(&cs->tqueue);
 }
 
-static void hisax_bh(struct IsdnCardState *cs)
+static void hisax_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        struct PStack *st;
        int pr;
 
index 3dacfff..6eebeb4 100644 (file)
@@ -1121,7 +1121,11 @@ setup_diva(struct IsdnCard *card)
                        bytecnt = 32;
                }
        }
+
+#ifdef __ISAPNP__
 ready:
+#endif
+
        printk(KERN_INFO
                "Diva: %s card configured at %#lx IRQ %d\n",
                (cs->subtyp == DIVA_PCI) ? "PCI" :
index 4e180d2..79ab9dd 100644 (file)
@@ -146,9 +146,8 @@ static int elsa_cs_probe(struct pcmcia_device *link)
     DEBUG(0, "elsa_cs_attach()\n");
 
     /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return -ENOMEM;
-    memset(local, 0, sizeof(local_info_t));
 
     local->p_dev = link;
     link->priv = local;
index 0d44a3f..34fade9 100644 (file)
@@ -26,12 +26,10 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
        int i;
 
        fsm->jumpmatrix = (FSMFNPTR *)
-               kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+               kzalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
        if (!fsm->jumpmatrix)
                return -ENOMEM;
 
-       memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
-
        for (i = 0; i < fncount; i++) 
                if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
                        printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
index d852c9d..a2fa4ec 100644 (file)
@@ -1083,8 +1083,9 @@ tx_b_frame(struct hfc4s8s_btype *bch)
 /* bottom half handler for interrupt */
 /*************************************/
 static void
-hfc4s8s_bh(hfc4s8s_hw * hw)
+hfc4s8s_bh(struct work_struct *work)
 {
+       hfc4s8s_hw *hw = container_of(work, hfc4s8s_hw, tqueue);
        u_char b;
        struct hfc4s8s_l1 *l1p;
        volatile u_char *fifo_stat;
@@ -1550,7 +1551,7 @@ setup_instance(hfc4s8s_hw * hw)
                goto out;
        }
 
-       INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw);
+       INIT_WORK(&hw->tqueue, hfc4s8s_bh);
 
        if (request_irq
            (hw->irq, hfc4s8s_interrupt, IRQF_SHARED, hw->card_name, hw)) {
@@ -1590,11 +1591,10 @@ hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data;
        hfc4s8s_hw *hw;
 
-       if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
+       if (!(hw = kzalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
                printk(KERN_ERR "No kmem for HFC-4S/8S card\n");
                return (err);
        }
-       memset(hw, 0, sizeof(hfc4s8s_hw));
 
        hw->pdev = pdev;
        err = pci_enable_device(pdev);
index 6360e82..8d98644 100644 (file)
@@ -549,10 +549,11 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
 }
 
 static void
-hfcd_bh(struct IsdnCardState *cs)
+hfcd_bh(struct work_struct *work)
 {
-       if (!cs)
-               return;
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
+
        if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
                switch (cs->dc.hfcd.ph_state) {
                        case (0):
@@ -1072,5 +1073,5 @@ set_cs_func(struct IsdnCardState *cs)
        cs->dbusytimer.function = (void *) hfc_dbusy_timer;
        cs->dbusytimer.data = (long) cs;
        init_timer(&cs->dbusytimer);
-       INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs);
+       INIT_WORK(&cs->tqueue, hfcd_bh);
 }
index 93f60b5..8a48a3c 100644 (file)
@@ -1211,7 +1211,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
                        break;
                case (HW_TESTLOOP | REQUEST):
                        spin_lock_irqsave(&cs->lock, flags);
-                       switch ((int) arg) {
+                       switch ((long) arg) {
                                case (1):
                                        Write_hfc(cs, HFCPCI_B1_SSL, 0x80);     /* tx slot */
                                        Write_hfc(cs, HFCPCI_B1_RSL, 0x80);     /* rx slot */
@@ -1229,7 +1229,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
                                default:
                                        spin_unlock_irqrestore(&cs->lock, flags);
                                        if (cs->debug & L1_DEB_WARN)
-                                               debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
+                                               debugl1(cs, "hfcpci_l1hw loop invalid %4lx", (long) arg);
                                        return;
                        }
                        cs->hw.hfcpci.trm |= 0x80;      /* enable IOM-loop */
@@ -1506,8 +1506,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
 /* handle L1 state changes */
 /***************************/
 static void
-hfcpci_bh(struct IsdnCardState *cs)
+hfcpci_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        u_long  flags;
 //      struct PStack *stptr;
 
@@ -1709,9 +1711,9 @@ setup_hfcpci(struct IsdnCard *card)
                pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
                cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
                printk(KERN_INFO
-                      "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
-                      (u_int) cs->hw.hfcpci.pci_io,
-                      (u_int) cs->hw.hfcpci.fifos,
+                      "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+                      cs->hw.hfcpci.pci_io,
+                      cs->hw.hfcpci.fifos,
                       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
                       cs->irq, HZ);
                spin_lock_irqsave(&cs->lock, flags);
@@ -1722,7 +1724,7 @@ setup_hfcpci(struct IsdnCard *card)
                Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
                /* At this point the needed PCI config is done */
                /* fifos are still not enabled */
-               INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs);
+               INIT_WORK(&cs->tqueue,  hfcpci_bh);
                cs->setstack_d = setstack_hfcpci;
                cs->BC_Send_Data = &hfcpci_send_data;
                cs->readisac = NULL;
index 954d153..4fd09d2 100644 (file)
@@ -1251,8 +1251,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
 /* handle L1 state changes */
 /***************************/
 static void
-hfcsx_bh(struct IsdnCardState *cs)
+hfcsx_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        u_long flags;
 
        if (!cs)
@@ -1499,7 +1501,7 @@ setup_hfcsx(struct IsdnCard *card)
        cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
        cs->dbusytimer.data = (long) cs;
        init_timer(&cs->dbusytimer);
-       INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs);
+       INIT_WORK(&cs->tqueue, hfcsx_bh);
        cs->readisac = NULL;
        cs->writeisac = NULL;
        cs->readisacfifo = NULL;
index 7105b04..5a6989f 100644 (file)
@@ -1481,9 +1481,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
                        iface = iface_used;
                        if (!
                            (context =
-                            kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
+                            kzalloc(sizeof(hfcusb_data), GFP_KERNEL)))
                                return (-ENOMEM);       /* got no mem */
-                       memset(context, 0, sizeof(hfcusb_data));
 
                        ep = iface->endpoint;
                        vcf = validconf[small_match];
index 159c589..3f1137e 100644 (file)
@@ -1139,12 +1139,6 @@ struct IsdnCardState {
 #define  CARD_HFC_SX 0
 #endif
 
-#ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 1
-#else
-#define CARD_AMD7930 0
-#endif
-
 #ifdef CONFIG_HISAX_NICCY
 #define        CARD_NICCY 1
 #ifndef ISDN_CHIP_ISAC
index f6db55a..9e088fc 100644 (file)
@@ -841,12 +841,10 @@ new_adapter(void)
        struct hisax_b_if *b_if[2];
        int i;
 
-       adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
+       adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
        if (!adapter)
                return NULL;
 
-       memset(adapter, 0, sizeof(struct fritz_adapter));
-
        adapter->isac.hisax_d_if.owner = THIS_MODULE;
        adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
        adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
index 81eac34..d0fefcf 100644 (file)
@@ -433,7 +433,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
        char buf[256];
        
        va_start(args, fmt);
-       vsprintf(buf, fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        DBG(DBG_L1M, "%s", buf);
        va_end(args);
 }
index da70692..682cac3 100644 (file)
@@ -77,8 +77,10 @@ icc_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-icc_bh(struct IsdnCardState *cs)
+icc_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        struct PStack *stptr;
        
        if (!cs)
@@ -674,7 +676,7 @@ clear_pending_icc_ints(struct IsdnCardState *cs)
 void __devinit
 setup_icc(struct IsdnCardState *cs)
 {
-       INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs);
+       INIT_WORK(&cs->tqueue, icc_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
        cs->dbusytimer.data = (long) cs;
        init_timer(&cs->dbusytimer);
index 282f349..4e9f238 100644 (file)
@@ -81,8 +81,10 @@ isac_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-isac_bh(struct IsdnCardState *cs)
+isac_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        struct PStack *stptr;
        
        if (!cs)
@@ -674,7 +676,7 @@ clear_pending_isac_ints(struct IsdnCardState *cs)
 void __devinit
 setup_isac(struct IsdnCardState *cs)
 {
-       INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs);
+       INIT_WORK(&cs->tqueue, isac_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
        cs->dbusytimer.data = (long) cs;
        init_timer(&cs->dbusytimer);
index 674af67..6f1a658 100644 (file)
@@ -437,8 +437,10 @@ extern void BChannel_bh(struct BCState *);
 #define B_LL_OK                10
 
 static void
-isar_bh(struct BCState *bcs)
+isar_bh(struct work_struct *work)
 {
+       struct BCState *bcs = container_of(work, struct BCState, tqueue);
+
        BChannel_bh(bcs);
        if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
                ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
@@ -1580,7 +1582,7 @@ isar_setup(struct IsdnCardState *cs)
                cs->bcs[i].mode = 0;
                cs->bcs[i].hw.isar.dpath = i + 1;
                modeisar(&cs->bcs[i], 0, 0);
-               INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]);
+               INIT_WORK(&cs->bcs[i].tqueue, isar_bh);
        }
 }
 
index cbdf54c..268dced 100644 (file)
@@ -35,30 +35,6 @@ MODULE_LICENSE("GPL");
 
 /*-------------------------------------------------------------------*/
 
-/* bit swap table.
- * Very handy for devices with different bit order,
- * and neccessary for each transparent B-channel access for all
- * devices which works with this HDLC decoder without bit reversal.
- */
-const unsigned char isdnhdlc_bit_rev_tab[256] = {
-       0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
-       0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
-       0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
-       0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
-       0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
-       0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
-       0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
-       0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
-       0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
-       0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
-       0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
-       0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
-       0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
-       0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
-       0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
-       0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
-};
-
 enum {
        HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
        HDLC_GET_DATA,HDLC_FAST_FLAG
@@ -621,7 +597,6 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
        return len;
 }
 
-EXPORT_SYMBOL(isdnhdlc_bit_rev_tab);
 EXPORT_SYMBOL(isdnhdlc_rcv_init);
 EXPORT_SYMBOL(isdnhdlc_decode);
 EXPORT_SYMBOL(isdnhdlc_out_init);
index 2693159..45167d2 100644 (file)
@@ -41,10 +41,10 @@ struct isdnhdlc_vars {
        unsigned char shift_reg;
        unsigned char ffvalue;
 
-       int data_received:1;    // set if transferring data
-       int dchannel:1;         // set if D channel (send idle instead of flags)
-       int do_adapt56:1;       // set if 56K adaptation
-        int do_closing:1;      // set if in closing phase (need to send CRC + flag
+       unsigned int data_received:1;   // set if transferring data
+       unsigned int dchannel:1;        // set if D channel (send idle instead of flags)
+       unsigned int do_adapt56:1;      // set if 56K adaptation
+       unsigned int do_closing:1;      // set if in closing phase (need to send CRC + flag
 };
 
 
@@ -57,8 +57,6 @@ struct isdnhdlc_vars {
 #define HDLC_CRC_ERROR         2
 #define HDLC_LENGTH_ERROR      3
 
-extern const unsigned char isdnhdlc_bit_rev_tab[256];
-
 extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
 
 extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
index bab3568..a14204e 100644 (file)
@@ -315,8 +315,10 @@ BChannel_proc_ack(struct BCState *bcs)
 }
 
 void
-BChannel_bh(struct BCState *bcs)
+BChannel_bh(struct work_struct *work)
 {
+       struct BCState *bcs = container_of(work, struct BCState, tqueue);
+
        if (!bcs)
                return;
        if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event))
@@ -362,7 +364,7 @@ init_bcstate(struct IsdnCardState *cs, int bc)
 
        bcs->cs = cs;
        bcs->channel = bc;
-       INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs);
+       INIT_WORK(&bcs->tqueue, BChannel_bh);
        spin_lock_init(&bcs->aclock);
        bcs->BC_SetStack = NULL;
        bcs->BC_Close = NULL;
index 9522141..030d162 100644 (file)
@@ -677,7 +677,11 @@ setup_sedlbauer(struct IsdnCard *card)
                return (0);
 #endif /* CONFIG_PCI */
        }       
+
+#ifdef __ISAPNP__
 ready: 
+#endif
+
        /* In case of the sedlbauer pcmcia card, this region is in use,
         * reserved for us by the card manager. So we do not check it
         * here, it would fail.
index 46ed653..45debde 100644 (file)
@@ -155,9 +155,8 @@ static int sedlbauer_probe(struct pcmcia_device *link)
     DEBUG(0, "sedlbauer_attach()\n");
 
     /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return -ENOMEM;
-    memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
 
     local->p_dev = link;
index 75d0f24..fa64115 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/usb.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
+#include <linux/bitrev.h>
 #include "st5481.h"
 
 static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg)
@@ -72,7 +73,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr)
                                        register unsigned char *dest = urb->transfer_buffer+len;
                                        register unsigned int count;
                                        for (count = 0; count < bytes_sent; count++)
-                                               *dest++ = isdnhdlc_bit_rev_tab[*src++];
+                                               *dest++ = bitrev8(*src++);
                                }
                                len += bytes_sent;
                        } else {
index 1d8c261..b8c4855 100644 (file)
@@ -173,7 +173,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
        char buf[256];
        
        va_start(args, fmt);
-       vsprintf(buf, fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        DBG(8, "%s", buf);
        va_end(args);
 }
@@ -275,7 +275,7 @@ static void dout_debug(struct FsmInst *fi, char *fmt, ...)
        char buf[256];
        
        va_start(args, fmt);
-       vsprintf(buf, fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        DBG(0x2, "%s", buf);
        va_end(args);
 }
index 2716aa5..bb3a28a 100644 (file)
@@ -69,12 +69,10 @@ static int probe_st5481(struct usb_interface *intf,
             le16_to_cpu(dev->descriptor.idProduct),
             number_of_leds);
 
-       adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
+       adapter = kzalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
        if (!adapter)
                return -ENOMEM;
 
-       memset(adapter, 0, sizeof(struct st5481_adapter));
-
        adapter->number_of_leds = number_of_leds;
        adapter->usb_dev = dev;
 
index 6b754f1..3e3e182 100644 (file)
@@ -137,9 +137,8 @@ static int teles_probe(struct pcmcia_device *link)
     DEBUG(0, "teles_attach()\n");
 
     /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return -ENOMEM;
-    memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
 
     local->p_dev = link;
index 1655341..3aeceaf 100644 (file)
@@ -101,8 +101,10 @@ W6692_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-W6692_bh(struct IsdnCardState *cs)
+W6692_bh(struct work_struct *work)
 {
+       struct IsdnCardState *cs =
+               container_of(work, struct IsdnCardState, tqueue);
        struct PStack *stptr;
 
        if (!cs)
@@ -1070,7 +1072,7 @@ setup_w6692(struct IsdnCard *card)
               id_list[cs->subtyp].card_name, cs->irq,
               cs->hw.w6692.iobase);
 
-       INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs);
+       INIT_WORK(&cs->tqueue, W6692_bh);
        cs->readW6692 = &ReadW6692;
        cs->writeW6692 = &WriteW6692;
        cs->readisacfifo = &ReadISACfifo;
index 82e42a8..a120649 100644 (file)
@@ -71,8 +71,9 @@ ergo_interrupt(int intno, void *dev_id)
 /* may be queued from everywhere (interrupts included).                       */
 /******************************************************************************/
 static void
-ergo_irq_bh(hysdn_card * card)
+ergo_irq_bh(struct work_struct *ugli_api)
 {
+       hysdn_card * card = container_of(ugli_api, hysdn_card, irq_queue);
        tErgDpram *dpr;
        int again;
        unsigned long flags;
@@ -442,7 +443,7 @@ ergo_inithardware(hysdn_card * card)
        card->writebootseq = ergo_writebootseq;
        card->waitpofready = ergo_waitpofready;
        card->set_errlog_state = ergo_set_errlog_state;
-       INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card);
+       INIT_WORK(&card->irq_queue, ergo_irq_bh);
        card->hysdn_lock = SPIN_LOCK_UNLOCKED;
 
        return (0);
index 6bac43c..b2ae4ec 100644 (file)
@@ -745,12 +745,11 @@ hycapi_capi_create(hysdn_card *card)
                return 1;
        }
        if (!card->hyctrlinfo) {
-               cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
+               cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
                if (!cinfo) {
                        printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n");
                        return -ENOMEM;
                }
-               memset(cinfo, 0, sizeof(hycapictrl_info));
                card->hyctrlinfo = cinfo;
                cinfo->card = card;
                spin_lock_init(&cinfo->lock);
index 6d0eb0f..be787e1 100644 (file)
@@ -278,14 +278,13 @@ pof_write_open(hysdn_card * card, unsigned char **bufp)
                return (-ERR_ALREADY_BOOT);     /* boot already active */
        }
        /* error no mem available */
-       if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) {
+       if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) {
                if (card->debug_flags & LOG_MEM_ERR)
                        hysdn_addlog(card, "POF open: unable to allocate mem");
                return (-EFAULT);
        }
        card->boot = boot;
        card->state = CARD_STATE_BOOTING;
-       memset(boot, 0, sizeof(struct boot_data));
 
        card->stopcard(card);   /* first stop the card */
        if (card->testram(card)) {
index b702ed2..9e01748 100644 (file)
@@ -81,11 +81,10 @@ search_cards(void)
                if (pci_enable_device(akt_pcidev))
                        continue;
 
-               if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) {
+               if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
                        printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
                        return;
                }
-               memset(card, 0, sizeof(hysdn_card));
                card->myid = cardmax;   /* set own id */
                card->bus = akt_pcidev->bus->number;
                card->devfn = akt_pcidev->devfn;        /* slot + function */
index d205249..557d96c 100644 (file)
@@ -278,11 +278,10 @@ hysdn_net_create(hysdn_card * card)
                return (-ENOMEM);
        }
        hysdn_net_release(card);        /* release an existing net device */
-       if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
+       if ((dev = kzalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
                printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
                return (-ENOMEM);
        }
-       memset(dev, 0, sizeof(struct net_local));       /* clean the structure */
 
        spin_lock_init(&((struct net_local *) dev)->lock);
 
index fcd4992..f241f5e 100644 (file)
@@ -204,7 +204,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off)
 {
        struct log_data *inf;
        int len;
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        struct procdata *pd = NULL;
        hysdn_card *card;
 
@@ -354,7 +354,7 @@ static unsigned int
 hysdn_log_poll(struct file *file, poll_table * wait)
 {
        unsigned int mask = 0;
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        hysdn_card *card;
        struct procdata *pd = NULL;
 
@@ -405,8 +405,7 @@ hysdn_proclog_init(hysdn_card * card)
 
        /* create a cardlog proc entry */
 
-       if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
-               memset(pd, 0, sizeof(struct procdata));
+       if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
                sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
                if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
                        pd->log->proc_fops = &log_fops; 
index 0afe442..a20f33b 100644 (file)
@@ -331,12 +331,10 @@ static void *bsd_alloc (struct isdn_ppp_comp_data *data)
         * Allocate the main control structure for this instance.
         */
        maxmaxcode = MAXCODE(bits);
-       db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL);
+       db = kzalloc (sizeof (struct bsd_db),GFP_KERNEL);
        if (!db)
                return NULL;
 
-       memset (db, 0, sizeof(struct bsd_db));
-
        db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
        decomp = db->xmit ? 0 : 1;
 
index 69aee26..6a2ef0a 100644 (file)
@@ -1059,7 +1059,7 @@ isdn_info_update(void)
 static ssize_t
 isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
 {
-       uint minor = iminor(file->f_dentry->d_inode);
+       uint minor = iminor(file->f_path.dentry->d_inode);
        int len = 0;
        int drvidx;
        int chidx;
@@ -1166,7 +1166,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
 static ssize_t
 isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
 {
-       uint minor = iminor(file->f_dentry->d_inode);
+       uint minor = iminor(file->f_path.dentry->d_inode);
        int drvidx;
        int chidx;
        int retval;
@@ -1228,7 +1228,7 @@ static unsigned int
 isdn_poll(struct file *file, poll_table * wait)
 {
        unsigned int mask = 0;
-       unsigned int minor = iminor(file->f_dentry->d_inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 
        lock_kernel();
@@ -2072,21 +2072,19 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
 
        if ((adding) && (d->rcverr))
                kfree(d->rcverr);
-       if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+       if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
                printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
                return -1;
        }
-       memset((char *) d->rcverr, 0, sizeof(int) * m);
 
        if ((adding) && (d->rcvcount))
                kfree(d->rcvcount);
-       if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+       if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
                printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
                if (!adding)
                        kfree(d->rcverr);
                return -1;
        }
-       memset((char *) d->rcvcount, 0, sizeof(int) * m);
 
        if ((adding) && (d->rpqueue)) {
                for (j = 0; j < d->channels; j++)
@@ -2226,11 +2224,10 @@ register_isdn(isdn_if * i)
                printk(KERN_WARNING "register_isdn: No write routine given.\n");
                return 0;
        }
-       if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
+       if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
                printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
                return 0;
        }
-       memset((char *) d, 0, sizeof(isdn_driver_t));
 
        d->maxbufsize = i->maxbufsize;
        d->pktcount = 0;
index 1f8d6ae..c36c817 100644 (file)
@@ -984,9 +984,9 @@ void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
 /*
  * called from tq_immediate
  */
-static void isdn_net_softint(void *private)
+static void isdn_net_softint(struct work_struct *work)
 {
-       isdn_net_local *lp = private;
+       isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
        struct sk_buff *skb;
 
        spin_lock_bh(&lp->xmit_lock);
@@ -2542,17 +2542,15 @@ isdn_net_new(char *name, struct net_device *master)
                printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
                return NULL;
        }
-       if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
+       if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
                printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
                return NULL;
        }
-       memset(netdev, 0, sizeof(isdn_net_dev));
-       if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
+       if (!(netdev->local = kzalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
                printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
                kfree(netdev);
                return NULL;
        }
-       memset(netdev->local, 0, sizeof(isdn_net_local));
        if (name == NULL)
                strcpy(netdev->local->name, "         ");
        else
@@ -2596,7 +2594,7 @@ isdn_net_new(char *name, struct net_device *master)
        netdev->local->netdev = netdev;
        netdev->local->next = netdev->local;
 
-       INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local);
+       INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
        spin_lock_init(&netdev->local->xmit_lock);
 
        netdev->local->isdn_device = -1;
index 119412d..4381179 100644 (file)
@@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
 
        if (is->debug & 0x2)
                printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-                               iminor(file->f_dentry->d_inode));
+                               iminor(file->f_path.dentry->d_inode));
 
        /* just registers wait_queue hook. This doesn't really wait. */
        poll_wait(file, &is->wq, wait);
@@ -876,14 +876,12 @@ isdn_ppp_init(void)
 #endif /* CONFIG_ISDN_MPP */
 
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               if (!(ippp_table[i] = (struct ippp_struct *)
-                     kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
+               if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
                        printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
                        for (j = 0; j < i; j++)
                                kfree(ippp_table[j]);
                        return -1;
                }
-               memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
                spin_lock_init(&ippp_table[i]->buflock);
                ippp_table[i]->state = 0;
                ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
@@ -1529,10 +1527,8 @@ static int isdn_ppp_mp_bundle_array_init(void)
 {
        int i;
        int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
-       if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, 
-                                                       GFP_KERNEL)) == NULL )
+       if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
                return -ENOMEM;
-       memset(isdn_ppp_bundle_arr, 0, sz);
        for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
                spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
        return 0;
@@ -2246,13 +2242,12 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
 {
        struct ippp_ccp_reset *r;
-       r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+       r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
        if(!r) {
                printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
                       " structure - no mem\n");
                return NULL;
        }
-       memset(r, 0, sizeof(struct ippp_ccp_reset));
        printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
        is->reset = r;
        return r;
@@ -2338,10 +2333,9 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
                       id);
                return NULL;
        } else {
-               rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+               rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
                if(!rs)
                        return NULL;
-               memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
                rs->state = CCPResetIdle;
                rs->is = is;
                rs->id = id;
@@ -2536,6 +2530,11 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
                rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
   
                skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
+               if (!skb_out) {
+                       kfree_skb(skb);
+                       printk(KERN_ERR "ippp: decomp memory allocation failure\n");
+                       return NULL;
+               }
                len = ipc->decompress(stat, skb, skb_out, &rsparm);
                kfree_skb(skb);
                if (len <= 0) {
index 2b91bb0..fc80afe 100644 (file)
@@ -1464,7 +1464,7 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
 }
 
 static void
-isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
index 38619e8..5484d3c 100644 (file)
@@ -92,9 +92,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
        int i;
        isdn_v110_stream *v;
 
-       if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
+       if ((v = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
                return NULL;
-       memset(v, 0, sizeof(isdn_v110_stream));
        v->key = key;
        v->nbits = 0;
        for (i = 0; key & (1 << i); i++)
index 730bbd0..1e699bc 100644 (file)
@@ -1519,12 +1519,11 @@ icn_initcard(int port, char *id)
        icn_card *card;
        int i;
 
-       if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) {
+       if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) {
                printk(KERN_WARNING
                       "icn: (%s) Could not allocate card-struct.\n", id);
                return (icn_card *) 0;
        }
-       memset((char *) card, 0, sizeof(icn_card));
        spin_lock_init(&card->lock);
        card->port = port;
        card->interface.owner = THIS_MODULE;
index c3ae2ed..e3add27 100644 (file)
@@ -1430,12 +1430,11 @@ isdnloop_initcard(char *id)
        isdnloop_card *card;
        int i;
 
-       if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) {
+       if (!(card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL))) {
                printk(KERN_WARNING
                 "isdnloop: (%s) Could not allocate card-struct.\n", id);
                return (isdnloop_card *) 0;
        }
-       memset((char *) card, 0, sizeof(isdnloop_card));
        card->interface.owner = THIS_MODULE;
        card->interface.channels = ISDNLOOP_BCH;
        card->interface.hl_hdrlen  = 1; /* scratch area for storing ack flag*/ 
index 6ead5e1..11c1b0b 100644 (file)
@@ -68,21 +68,18 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list);
 static int pcbit_check_msn(struct pcbit_dev *dev, char *msn);
 
 
-extern void pcbit_deliver(void * data);
-
 int pcbit_init_dev(int board, int mem_base, int irq)
 {
        struct pcbit_dev *dev;
        isdn_if *dev_if;
 
-       if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL)
+       if ((dev=kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL)
        {
                printk("pcbit_init: couldn't malloc pcbit_dev struct\n");
                return -ENOMEM;
        }
 
        dev_pcbit[board] = dev;
-       memset(dev, 0, sizeof(struct pcbit_dev));
        init_waitqueue_head(&dev->set_running_wq);
        spin_lock_init(&dev->lock);
 
@@ -106,7 +103,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
                return -EACCES;
        }
 
-       dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+       dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
        if (!dev->b1) {
                printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
                iounmap(dev->sh_mem);
@@ -115,7 +112,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
                return -ENOMEM;
        }
     
-       dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+       dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
        if (!dev->b2) {
                printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
                kfree(dev->b1);
@@ -125,11 +122,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
                return -ENOMEM;
        }
 
-       memset(dev->b1, 0, sizeof(struct pcbit_chan));
-       memset(dev->b2, 0, sizeof(struct pcbit_chan));
        dev->b2->id = 1;
 
-       INIT_WORK(&dev->qdelivery, pcbit_deliver, dev);
+       INIT_WORK(&dev->qdelivery, pcbit_deliver);
 
        /*
         *  interrupts
index 937fd21..6ff8557 100644 (file)
@@ -67,7 +67,6 @@ extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg,
  *  Prototypes
  */
 
-void pcbit_deliver(void *data);
 static void pcbit_transmit(struct pcbit_dev *dev);
 
 static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack);
@@ -299,11 +298,12 @@ pcbit_transmit(struct pcbit_dev *dev)
  */
 
 void
-pcbit_deliver(void *data)
+pcbit_deliver(struct work_struct *work)
 {
        struct frame_buf *frame;
        unsigned long flags, msg;
-       struct pcbit_dev *dev = (struct pcbit_dev *) data;
+       struct pcbit_dev *dev =
+               container_of(work, struct pcbit_dev, qdelivery);
 
        spin_lock_irqsave(&dev->lock, flags);
 
@@ -369,13 +369,12 @@ pcbit_receive(struct pcbit_dev *dev)
                        kfree(dev->read_frame);
                        dev->read_frame = NULL;
                }
-               frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC);
+               frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC);
 
                if (frame == NULL) {
                        printk(KERN_WARNING "kmalloc failed\n");
                        return;
                }
-               memset(frame, 0, sizeof(struct frame_buf));
 
                cpu = pcbit_readb(dev);
                proc = pcbit_readb(dev);
index 388bace..19c18e8 100644 (file)
@@ -166,4 +166,6 @@ struct pcbit_ioctl {
 #define L2_RUNNING  5
 #define L2_ERROR    6
 
+extern void pcbit_deliver(struct work_struct *work);
+
 #endif
index 06c9872..150759a 100644 (file)
@@ -271,14 +271,13 @@ static int __init sc_init(void)
                 * Horray! We found a board, Make sure we can register
                 * it with ISDN4Linux
                 */
-               interface = kmalloc(sizeof(isdn_if), GFP_KERNEL);
+               interface = kzalloc(sizeof(isdn_if), GFP_KERNEL);
                if (interface == NULL) {
                        /*
                         * Oops, can't malloc isdn_if
                         */
                        continue;
                }
-               memset(interface, 0, sizeof(isdn_if));
 
                interface->owner = THIS_MODULE;
                interface->hl_hdrlen = 0;
@@ -294,7 +293,7 @@ static int __init sc_init(void)
                /*
                 * Allocate the board structure
                 */
-               sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL);
+               sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL);
                if (sc_adapter[cinst] == NULL) {
                        /*
                         * Oops, can't alloc memory for the board
@@ -302,7 +301,6 @@ static int __init sc_init(void)
                        kfree(interface);
                        continue;
                }
-               memset(sc_adapter[cinst], 0, sizeof(board));
                spin_lock_init(&sc_adapter[cinst]->lock);
 
                if(!register_isdn(interface)) {
@@ -326,7 +324,7 @@ static int __init sc_init(void)
                /*
                 * Allocate channels status structures
                 */
-               sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL);
+               sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL);
                if (sc_adapter[cinst]->channel == NULL) {
                        /*
                         * Oops, can't alloc memory for the channels
@@ -336,7 +334,6 @@ static int __init sc_init(void)
                        kfree(sc_adapter[cinst]);
                        continue;
                }
-               memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels);
 
                /*
                 * Lock down the hardware resources
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
new file mode 100644 (file)
index 0000000..36412e9
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# KVM configuration
+#
+config KVM
+       tristate "Kernel-based Virtual Machine (KVM) support"
+       depends on X86 && EXPERIMENTAL
+       ---help---
+         Support hosting fully virtualized guest machines using hardware
+         virtualization extensions.  You will need a fairly recent
+         processor equipped with virtualization extensions. You will also
+         need to select one or more of the processor modules below.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         To compile this as a module, choose M here: the module
+         will be called kvm.
+
+         If unsure, say N.
+
+config KVM_INTEL
+       tristate "KVM for Intel processors support"
+       depends on KVM
+       ---help---
+         Provides support for KVM on Intel processors equipped with the VT
+         extensions.
+
+config KVM_AMD
+       tristate "KVM for AMD processors support"
+       depends on KVM
+       ---help---
+         Provides support for KVM on AMD processors equipped with the AMD-V
+         (SVM) extensions.
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
new file mode 100644 (file)
index 0000000..c0a789f
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+kvm-objs := kvm_main.o mmu.o x86_emulate.o
+obj-$(CONFIG_KVM) += kvm.o
+kvm-intel-objs = vmx.o
+obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
+kvm-amd-objs = svm.o
+obj-$(CONFIG_KVM_AMD) += kvm-amd.o
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
new file mode 100644 (file)
index 0000000..5785d08
--- /dev/null
@@ -0,0 +1,551 @@
+#ifndef __KVM_H
+#define __KVM_H
+
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include "vmx.h"
+#include <linux/kvm.h>
+
+#define CR0_PE_MASK (1ULL << 0)
+#define CR0_TS_MASK (1ULL << 3)
+#define CR0_NE_MASK (1ULL << 5)
+#define CR0_WP_MASK (1ULL << 16)
+#define CR0_NW_MASK (1ULL << 29)
+#define CR0_CD_MASK (1ULL << 30)
+#define CR0_PG_MASK (1ULL << 31)
+
+#define CR3_WPT_MASK (1ULL << 3)
+#define CR3_PCD_MASK (1ULL << 4)
+
+#define CR3_RESEVED_BITS 0x07ULL
+#define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL)
+#define CR3_FLAGS_MASK ((1ULL << 5) - 1)
+
+#define CR4_VME_MASK (1ULL << 0)
+#define CR4_PSE_MASK (1ULL << 4)
+#define CR4_PAE_MASK (1ULL << 5)
+#define CR4_PGE_MASK (1ULL << 7)
+#define CR4_VMXE_MASK (1ULL << 13)
+
+#define KVM_GUEST_CR0_MASK \
+       (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \
+        | CR0_NW_MASK | CR0_CD_MASK)
+#define KVM_VM_CR0_ALWAYS_ON \
+       (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK)
+#define KVM_GUEST_CR4_MASK \
+       (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)
+#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
+#define KVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK)
+
+#define INVALID_PAGE (~(hpa_t)0)
+#define UNMAPPED_GVA (~(gpa_t)0)
+
+#define KVM_MAX_VCPUS 1
+#define KVM_MEMORY_SLOTS 4
+#define KVM_NUM_MMU_PAGES 256
+
+#define FX_IMAGE_SIZE 512
+#define FX_IMAGE_ALIGN 16
+#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
+
+#define DE_VECTOR 0
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+
+#define SELECTOR_TI_MASK (1 << 2)
+#define SELECTOR_RPL_MASK 0x03
+
+#define IOPL_SHIFT 12
+
+/*
+ * Address types:
+ *
+ *  gva - guest virtual address
+ *  gpa - guest physical address
+ *  gfn - guest frame number
+ *  hva - host virtual address
+ *  hpa - host physical address
+ *  hfn - host frame number
+ */
+
+typedef unsigned long  gva_t;
+typedef u64            gpa_t;
+typedef unsigned long  gfn_t;
+
+typedef unsigned long  hva_t;
+typedef u64            hpa_t;
+typedef unsigned long  hfn_t;
+
+struct kvm_mmu_page {
+       struct list_head link;
+       hpa_t page_hpa;
+       unsigned long slot_bitmap; /* One bit set per slot which has memory
+                                   * in this shadow page.
+                                   */
+       int global;              /* Set if all ptes in this page are global */
+       u64 *parent_pte;
+};
+
+struct vmcs {
+       u32 revision_id;
+       u32 abort;
+       char data[0];
+};
+
+#define vmx_msr_entry kvm_msr_entry
+
+struct kvm_vcpu;
+
+/*
+ * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
+ * 32-bit).  The kvm_mmu structure abstracts the details of the current mmu
+ * mode.
+ */
+struct kvm_mmu {
+       void (*new_cr3)(struct kvm_vcpu *vcpu);
+       int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
+       void (*inval_page)(struct kvm_vcpu *vcpu, gva_t gva);
+       void (*free)(struct kvm_vcpu *vcpu);
+       gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
+       hpa_t root_hpa;
+       int root_level;
+       int shadow_root_level;
+};
+
+struct kvm_guest_debug {
+       int enabled;
+       unsigned long bp[4];
+       int singlestep;
+};
+
+enum {
+       VCPU_REGS_RAX = 0,
+       VCPU_REGS_RCX = 1,
+       VCPU_REGS_RDX = 2,
+       VCPU_REGS_RBX = 3,
+       VCPU_REGS_RSP = 4,
+       VCPU_REGS_RBP = 5,
+       VCPU_REGS_RSI = 6,
+       VCPU_REGS_RDI = 7,
+#ifdef __x86_64__
+       VCPU_REGS_R8 = 8,
+       VCPU_REGS_R9 = 9,
+       VCPU_REGS_R10 = 10,
+       VCPU_REGS_R11 = 11,
+       VCPU_REGS_R12 = 12,
+       VCPU_REGS_R13 = 13,
+       VCPU_REGS_R14 = 14,
+       VCPU_REGS_R15 = 15,
+#endif
+       NR_VCPU_REGS
+};
+
+enum {
+       VCPU_SREG_CS,
+       VCPU_SREG_DS,
+       VCPU_SREG_ES,
+       VCPU_SREG_FS,
+       VCPU_SREG_GS,
+       VCPU_SREG_SS,
+       VCPU_SREG_TR,
+       VCPU_SREG_LDTR,
+};
+
+struct kvm_vcpu {
+       struct kvm *kvm;
+       union {
+               struct vmcs *vmcs;
+               struct vcpu_svm *svm;
+       };
+       struct mutex mutex;
+       int   cpu;
+       int   launched;
+       unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
+#define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
+       unsigned long irq_pending[NR_IRQ_WORDS];
+       unsigned long regs[NR_VCPU_REGS]; /* for rsp: vcpu_load_rsp_rip() */
+       unsigned long rip;      /* needs vcpu_load_rsp_rip() */
+
+       unsigned long cr0;
+       unsigned long cr2;
+       unsigned long cr3;
+       unsigned long cr4;
+       unsigned long cr8;
+       u64 shadow_efer;
+       u64 apic_base;
+       int nmsrs;
+       struct vmx_msr_entry *guest_msrs;
+       struct vmx_msr_entry *host_msrs;
+
+       struct list_head free_pages;
+       struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES];
+       struct kvm_mmu mmu;
+
+       struct kvm_guest_debug guest_debug;
+
+       char fx_buf[FX_BUF_SIZE];
+       char *host_fx_image;
+       char *guest_fx_image;
+
+       int mmio_needed;
+       int mmio_read_completed;
+       int mmio_is_write;
+       int mmio_size;
+       unsigned char mmio_data[8];
+       gpa_t mmio_phys_addr;
+
+       struct {
+               int active;
+               u8 save_iopl;
+               struct kvm_save_segment {
+                       u16 selector;
+                       unsigned long base;
+                       u32 limit;
+                       u32 ar;
+               } tr, es, ds, fs, gs;
+       } rmode;
+};
+
+struct kvm_memory_slot {
+       gfn_t base_gfn;
+       unsigned long npages;
+       unsigned long flags;
+       struct page **phys_mem;
+       unsigned long *dirty_bitmap;
+};
+
+struct kvm {
+       spinlock_t lock; /* protects everything except vcpus */
+       int nmemslots;
+       struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS];
+       struct list_head active_mmu_pages;
+       struct kvm_vcpu vcpus[KVM_MAX_VCPUS];
+       int memory_config_version;
+       int busy;
+};
+
+struct kvm_stat {
+       u32 pf_fixed;
+       u32 pf_guest;
+       u32 tlb_flush;
+       u32 invlpg;
+
+       u32 exits;
+       u32 io_exits;
+       u32 mmio_exits;
+       u32 signal_exits;
+       u32 irq_exits;
+};
+
+struct descriptor_table {
+       u16 limit;
+       unsigned long base;
+} __attribute__((packed));
+
+struct kvm_arch_ops {
+       int (*cpu_has_kvm_support)(void);          /* __init */
+       int (*disabled_by_bios)(void);             /* __init */
+       void (*hardware_enable)(void *dummy);      /* __init */
+       void (*hardware_disable)(void *dummy);
+       int (*hardware_setup)(void);               /* __init */
+       void (*hardware_unsetup)(void);            /* __exit */
+
+       int (*vcpu_create)(struct kvm_vcpu *vcpu);
+       void (*vcpu_free)(struct kvm_vcpu *vcpu);
+
+       struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu);
+       void (*vcpu_put)(struct kvm_vcpu *vcpu);
+
+       int (*set_guest_debug)(struct kvm_vcpu *vcpu,
+                              struct kvm_debug_guest *dbg);
+       int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
+       int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
+       u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
+       void (*get_segment)(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg);
+       void (*set_segment)(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg);
+       int (*is_long_mode)(struct kvm_vcpu *vcpu);
+       void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+       void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
+       void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu,
+                                     unsigned long cr0);
+       void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
+       void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
+       void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
+       void (*get_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+       void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+       void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+       void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+       unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr);
+       void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value,
+                      int *exception);
+       void (*cache_regs)(struct kvm_vcpu *vcpu);
+       void (*decache_regs)(struct kvm_vcpu *vcpu);
+       unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
+       void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
+
+       void (*invlpg)(struct kvm_vcpu *vcpu, gva_t addr);
+       void (*tlb_flush)(struct kvm_vcpu *vcpu);
+       void (*inject_page_fault)(struct kvm_vcpu *vcpu,
+                                 unsigned long addr, u32 err_code);
+
+       void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
+
+       int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run);
+       int (*vcpu_setup)(struct kvm_vcpu *vcpu);
+       void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+};
+
+extern struct kvm_stat kvm_stat;
+extern struct kvm_arch_ops *kvm_arch_ops;
+
+#define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt)
+#define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt)
+
+int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module);
+void kvm_exit_arch(void);
+
+void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
+int kvm_mmu_init(struct kvm_vcpu *vcpu);
+
+int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
+void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
+
+hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa);
+#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
+#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
+static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
+hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva);
+
+void kvm_emulator_want_group7_invlpg(void);
+
+extern hpa_t bad_page_address;
+
+static inline struct page *gfn_to_page(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+       return slot->phys_mem[gfn - slot->base_gfn];
+}
+
+struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
+void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
+
+enum emulation_result {
+       EMULATE_DONE,       /* no further processing */
+       EMULATE_DO_MMIO,      /* kvm_run filled with mmio request */
+       EMULATE_FAIL,         /* can't emulate this instruction */
+};
+
+int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
+                       unsigned long cr2, u16 error_code);
+void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
+void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
+void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+                  unsigned long *rflags);
+
+unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr);
+void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
+                    unsigned long *rflags);
+
+struct x86_emulate_ctxt;
+
+int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
+int emulate_clts(struct kvm_vcpu *vcpu);
+int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
+                   unsigned long *dest);
+int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
+                   unsigned long value);
+
+void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
+void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
+
+#ifdef __x86_64__
+void set_efer(struct kvm_vcpu *vcpu, u64 efer);
+#endif
+
+void fx_init(struct kvm_vcpu *vcpu);
+
+void load_msrs(struct vmx_msr_entry *e, int n);
+void save_msrs(struct vmx_msr_entry *e, int n);
+void kvm_resched(struct kvm_vcpu *vcpu);
+
+int kvm_read_guest(struct kvm_vcpu *vcpu,
+              gva_t addr,
+              unsigned long size,
+              void *dest);
+
+int kvm_write_guest(struct kvm_vcpu *vcpu,
+               gva_t addr,
+               unsigned long size,
+               void *data);
+
+unsigned long segment_base(u16 selector);
+
+static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn)
+{
+       struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+       return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL;
+}
+
+static inline int is_pae(struct kvm_vcpu *vcpu)
+{
+       return vcpu->cr4 & CR4_PAE_MASK;
+}
+
+static inline int is_pse(struct kvm_vcpu *vcpu)
+{
+       return vcpu->cr4 & CR4_PSE_MASK;
+}
+
+static inline int is_paging(struct kvm_vcpu *vcpu)
+{
+       return vcpu->cr0 & CR0_PG_MASK;
+}
+
+static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+       return slot - kvm->memslots;
+}
+
+static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
+{
+       struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
+
+       return (struct kvm_mmu_page *)page->private;
+}
+
+static inline u16 read_fs(void)
+{
+       u16 seg;
+       asm ("mov %%fs, %0" : "=g"(seg));
+       return seg;
+}
+
+static inline u16 read_gs(void)
+{
+       u16 seg;
+       asm ("mov %%gs, %0" : "=g"(seg));
+       return seg;
+}
+
+static inline u16 read_ldt(void)
+{
+       u16 ldt;
+       asm ("sldt %0" : "=g"(ldt));
+       return ldt;
+}
+
+static inline void load_fs(u16 sel)
+{
+       asm ("mov %0, %%fs" : : "rm"(sel));
+}
+
+static inline void load_gs(u16 sel)
+{
+       asm ("mov %0, %%gs" : : "rm"(sel));
+}
+
+#ifndef load_ldt
+static inline void load_ldt(u16 sel)
+{
+       asm ("lldt %0" : : "g"(sel));
+}
+#endif
+
+static inline void get_idt(struct descriptor_table *table)
+{
+       asm ("sidt %0" : "=m"(*table));
+}
+
+static inline void get_gdt(struct descriptor_table *table)
+{
+       asm ("sgdt %0" : "=m"(*table));
+}
+
+static inline unsigned long read_tr_base(void)
+{
+       u16 tr;
+       asm ("str %0" : "=g"(tr));
+       return segment_base(tr);
+}
+
+#ifdef __x86_64__
+static inline unsigned long read_msr(unsigned long msr)
+{
+       u64 value;
+
+       rdmsrl(msr, value);
+       return value;
+}
+#endif
+
+static inline void fx_save(void *image)
+{
+       asm ("fxsave (%0)":: "r" (image));
+}
+
+static inline void fx_restore(void *image)
+{
+       asm ("fxrstor (%0)":: "r" (image));
+}
+
+static inline void fpu_init(void)
+{
+       asm ("finit");
+}
+
+static inline u32 get_rdx_init_val(void)
+{
+       return 0x600; /* P6 family */
+}
+
+#define ASM_VMX_VMCLEAR_RAX       ".byte 0x66, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMLAUNCH          ".byte 0x0f, 0x01, 0xc2"
+#define ASM_VMX_VMRESUME          ".byte 0x0f, 0x01, 0xc3"
+#define ASM_VMX_VMPTRLD_RAX       ".byte 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMREAD_RDX_RAX    ".byte 0x0f, 0x78, 0xd0"
+#define ASM_VMX_VMWRITE_RAX_RDX   ".byte 0x0f, 0x79, 0xd0"
+#define ASM_VMX_VMWRITE_RSP_RDX   ".byte 0x0f, 0x79, 0xd4"
+#define ASM_VMX_VMXOFF            ".byte 0x0f, 0x01, 0xc4"
+#define ASM_VMX_VMXON_RAX         ".byte 0xf3, 0x0f, 0xc7, 0x30"
+
+#define MSR_IA32_TIME_STAMP_COUNTER            0x010
+
+#define TSS_IOPB_BASE_OFFSET 0x66
+#define TSS_BASE_SIZE 0x68
+#define TSS_IOPB_SIZE (65536 / 8)
+#define TSS_REDIRECTION_SIZE (256 / 8)
+#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
+
+#ifdef __x86_64__
+
+/*
+ * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.  Therefore
+ * we need to allocate shadow page tables in the first 4GB of memory, which
+ * happens to fit the DMA32 zone.
+ */
+#define GFP_KVM_MMU (GFP_KERNEL | __GFP_DMA32)
+
+#else
+
+#define GFP_KVM_MMU GFP_KERNEL
+
+#endif
+
+#endif
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
new file mode 100644 (file)
index 0000000..b6b8a41
--- /dev/null
@@ -0,0 +1,1935 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ *   Avi Kivity   <avi@qumranet.com>
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "kvm.h"
+
+#include <linux/kvm.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <linux/percpu.h>
+#include <linux/gfp.h>
+#include <asm/msr.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <linux/reboot.h>
+#include <asm/io.h>
+#include <linux/debugfs.h>
+#include <linux/highmem.h>
+#include <linux/file.h>
+#include <asm/desc.h>
+
+#include "x86_emulate.h"
+#include "segment_descriptor.h"
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+struct kvm_arch_ops *kvm_arch_ops;
+struct kvm_stat kvm_stat;
+EXPORT_SYMBOL_GPL(kvm_stat);
+
+static struct kvm_stats_debugfs_item {
+       const char *name;
+       u32 *data;
+       struct dentry *dentry;
+} debugfs_entries[] = {
+       { "pf_fixed", &kvm_stat.pf_fixed },
+       { "pf_guest", &kvm_stat.pf_guest },
+       { "tlb_flush", &kvm_stat.tlb_flush },
+       { "invlpg", &kvm_stat.invlpg },
+       { "exits", &kvm_stat.exits },
+       { "io_exits", &kvm_stat.io_exits },
+       { "mmio_exits", &kvm_stat.mmio_exits },
+       { "signal_exits", &kvm_stat.signal_exits },
+       { "irq_exits", &kvm_stat.irq_exits },
+       { 0, 0 }
+};
+
+static struct dentry *debugfs_dir;
+
+#define MAX_IO_MSRS 256
+
+#define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
+#define LMSW_GUEST_MASK 0x0eULL
+#define CR4_RESEVED_BITS (~((1ULL << 11) - 1))
+#define CR8_RESEVED_BITS (~0x0fULL)
+#define EFER_RESERVED_BITS 0xfffffffffffff2fe
+
+struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+{
+       int i;
+
+       for (i = 0; i < vcpu->nmsrs; ++i)
+               if (vcpu->guest_msrs[i].index == msr)
+                       return &vcpu->guest_msrs[i];
+       return 0;
+}
+EXPORT_SYMBOL_GPL(find_msr_entry);
+
+#ifdef __x86_64__
+// LDT or TSS descriptor in the GDT. 16 bytes.
+struct segment_descriptor_64 {
+       struct segment_descriptor s;
+       u32 base_higher;
+       u32 pad_zero;
+};
+
+#endif
+
+unsigned long segment_base(u16 selector)
+{
+       struct descriptor_table gdt;
+       struct segment_descriptor *d;
+       unsigned long table_base;
+       typedef unsigned long ul;
+       unsigned long v;
+
+       if (selector == 0)
+               return 0;
+
+       asm ("sgdt %0" : "=m"(gdt));
+       table_base = gdt.base;
+
+       if (selector & 4) {           /* from ldt */
+               u16 ldt_selector;
+
+               asm ("sldt %0" : "=g"(ldt_selector));
+               table_base = segment_base(ldt_selector);
+       }
+       d = (struct segment_descriptor *)(table_base + (selector & ~7));
+       v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24);
+#ifdef __x86_64__
+       if (d->system == 0
+           && (d->type == 2 || d->type == 9 || d->type == 11))
+               v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32;
+#endif
+       return v;
+}
+EXPORT_SYMBOL_GPL(segment_base);
+
+int kvm_read_guest(struct kvm_vcpu *vcpu,
+                            gva_t addr,
+                            unsigned long size,
+                            void *dest)
+{
+       unsigned char *host_buf = dest;
+       unsigned long req_size = size;
+
+       while (size) {
+               hpa_t paddr;
+               unsigned now;
+               unsigned offset;
+               hva_t guest_buf;
+
+               paddr = gva_to_hpa(vcpu, addr);
+
+               if (is_error_hpa(paddr))
+                       break;
+
+               guest_buf = (hva_t)kmap_atomic(
+                                       pfn_to_page(paddr >> PAGE_SHIFT),
+                                       KM_USER0);
+               offset = addr & ~PAGE_MASK;
+               guest_buf |= offset;
+               now = min(size, PAGE_SIZE - offset);
+               memcpy(host_buf, (void*)guest_buf, now);
+               host_buf += now;
+               addr += now;
+               size -= now;
+               kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0);
+       }
+       return req_size - size;
+}
+EXPORT_SYMBOL_GPL(kvm_read_guest);
+
+int kvm_write_guest(struct kvm_vcpu *vcpu,
+                            gva_t addr,
+                            unsigned long size,
+                            void *data)
+{
+       unsigned char *host_buf = data;
+       unsigned long req_size = size;
+
+       while (size) {
+               hpa_t paddr;
+               unsigned now;
+               unsigned offset;
+               hva_t guest_buf;
+
+               paddr = gva_to_hpa(vcpu, addr);
+
+               if (is_error_hpa(paddr))
+                       break;
+
+               guest_buf = (hva_t)kmap_atomic(
+                               pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0);
+               offset = addr & ~PAGE_MASK;
+               guest_buf |= offset;
+               now = min(size, PAGE_SIZE - offset);
+               memcpy((void*)guest_buf, host_buf, now);
+               host_buf += now;
+               addr += now;
+               size -= now;
+               kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0);
+       }
+       return req_size - size;
+}
+EXPORT_SYMBOL_GPL(kvm_write_guest);
+
+static int vcpu_slot(struct kvm_vcpu *vcpu)
+{
+       return vcpu - vcpu->kvm->vcpus;
+}
+
+/*
+ * Switches to specified vcpu, until a matching vcpu_put()
+ */
+static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot)
+{
+       struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot];
+
+       mutex_lock(&vcpu->mutex);
+       if (unlikely(!vcpu->vmcs)) {
+               mutex_unlock(&vcpu->mutex);
+               return 0;
+       }
+       return kvm_arch_ops->vcpu_load(vcpu);
+}
+
+static void vcpu_put(struct kvm_vcpu *vcpu)
+{
+       kvm_arch_ops->vcpu_put(vcpu);
+       put_cpu();
+       mutex_unlock(&vcpu->mutex);
+}
+
+static int kvm_dev_open(struct inode *inode, struct file *filp)
+{
+       struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
+       int i;
+
+       if (!kvm)
+               return -ENOMEM;
+
+       spin_lock_init(&kvm->lock);
+       INIT_LIST_HEAD(&kvm->active_mmu_pages);
+       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+               struct kvm_vcpu *vcpu = &kvm->vcpus[i];
+
+               mutex_init(&vcpu->mutex);
+               vcpu->mmu.root_hpa = INVALID_PAGE;
+               INIT_LIST_HEAD(&vcpu->free_pages);
+       }
+       filp->private_data = kvm;
+       return 0;
+}
+
+/*
+ * Free any memory in @free but not in @dont.
+ */
+static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
+                                 struct kvm_memory_slot *dont)
+{
+       int i;
+
+       if (!dont || free->phys_mem != dont->phys_mem)
+               if (free->phys_mem) {
+                       for (i = 0; i < free->npages; ++i)
+                               __free_page(free->phys_mem[i]);
+                       vfree(free->phys_mem);
+               }
+
+       if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
+               vfree(free->dirty_bitmap);
+
+       free->phys_mem = 0;
+       free->npages = 0;
+       free->dirty_bitmap = 0;
+}
+
+static void kvm_free_physmem(struct kvm *kvm)
+{
+       int i;
+
+       for (i = 0; i < kvm->nmemslots; ++i)
+               kvm_free_physmem_slot(&kvm->memslots[i], 0);
+}
+
+static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
+{
+       kvm_arch_ops->vcpu_free(vcpu);
+       kvm_mmu_destroy(vcpu);
+}
+
+static void kvm_free_vcpus(struct kvm *kvm)
+{
+       unsigned int i;
+
+       for (i = 0; i < KVM_MAX_VCPUS; ++i)
+               kvm_free_vcpu(&kvm->vcpus[i]);
+}
+
+static int kvm_dev_release(struct inode *inode, struct file *filp)
+{
+       struct kvm *kvm = filp->private_data;
+
+       kvm_free_vcpus(kvm);
+       kvm_free_physmem(kvm);
+       kfree(kvm);
+       return 0;
+}
+
+static void inject_gp(struct kvm_vcpu *vcpu)
+{
+       kvm_arch_ops->inject_gp(vcpu, 0);
+}
+
+static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu,
+                                        unsigned long cr3)
+{
+       gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT;
+       unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5;
+       int i;
+       u64 pdpte;
+       u64 *pdpt;
+       struct kvm_memory_slot *memslot;
+
+       spin_lock(&vcpu->kvm->lock);
+       memslot = gfn_to_memslot(vcpu->kvm, pdpt_gfn);
+       /* FIXME: !memslot - emulate? 0xff? */
+       pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0);
+
+       for (i = 0; i < 4; ++i) {
+               pdpte = pdpt[offset + i];
+               if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull))
+                       break;
+       }
+
+       kunmap_atomic(pdpt, KM_USER0);
+       spin_unlock(&vcpu->kvm->lock);
+
+       return i != 4;
+}
+
+void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       if (cr0 & CR0_RESEVED_BITS) {
+               printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
+                      cr0, vcpu->cr0);
+               inject_gp(vcpu);
+               return;
+       }
+
+       if ((cr0 & CR0_NW_MASK) && !(cr0 & CR0_CD_MASK)) {
+               printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n");
+               inject_gp(vcpu);
+               return;
+       }
+
+       if ((cr0 & CR0_PG_MASK) && !(cr0 & CR0_PE_MASK)) {
+               printk(KERN_DEBUG "set_cr0: #GP, set PG flag "
+                      "and a clear PE flag\n");
+               inject_gp(vcpu);
+               return;
+       }
+
+       if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
+#ifdef __x86_64__
+               if ((vcpu->shadow_efer & EFER_LME)) {
+                       int cs_db, cs_l;
+
+                       if (!is_pae(vcpu)) {
+                               printk(KERN_DEBUG "set_cr0: #GP, start paging "
+                                      "in long mode while PAE is disabled\n");
+                               inject_gp(vcpu);
+                               return;
+                       }
+                       kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+                       if (cs_l) {
+                               printk(KERN_DEBUG "set_cr0: #GP, start paging "
+                                      "in long mode while CS.L == 1\n");
+                               inject_gp(vcpu);
+                               return;
+
+                       }
+               } else
+#endif
+               if (is_pae(vcpu) &&
+                           pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) {
+                       printk(KERN_DEBUG "set_cr0: #GP, pdptrs "
+                              "reserved bits\n");
+                       inject_gp(vcpu);
+                       return;
+               }
+
+       }
+
+       kvm_arch_ops->set_cr0(vcpu, cr0);
+       vcpu->cr0 = cr0;
+
+       spin_lock(&vcpu->kvm->lock);
+       kvm_mmu_reset_context(vcpu);
+       spin_unlock(&vcpu->kvm->lock);
+       return;
+}
+EXPORT_SYMBOL_GPL(set_cr0);
+
+void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
+{
+       set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f));
+}
+EXPORT_SYMBOL_GPL(lmsw);
+
+void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+       if (cr4 & CR4_RESEVED_BITS) {
+               printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
+               inject_gp(vcpu);
+               return;
+       }
+
+       if (kvm_arch_ops->is_long_mode(vcpu)) {
+               if (!(cr4 & CR4_PAE_MASK)) {
+                       printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while "
+                              "in long mode\n");
+                       inject_gp(vcpu);
+                       return;
+               }
+       } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK)
+                  && pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) {
+               printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n");
+               inject_gp(vcpu);
+       }
+
+       if (cr4 & CR4_VMXE_MASK) {
+               printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n");
+               inject_gp(vcpu);
+               return;
+       }
+       kvm_arch_ops->set_cr4(vcpu, cr4);
+       spin_lock(&vcpu->kvm->lock);
+       kvm_mmu_reset_context(vcpu);
+       spin_unlock(&vcpu->kvm->lock);
+}
+EXPORT_SYMBOL_GPL(set_cr4);
+
+void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+       if (kvm_arch_ops->is_long_mode(vcpu)) {
+               if ( cr3 & CR3_L_MODE_RESEVED_BITS) {
+                       printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
+                       inject_gp(vcpu);
+                       return;
+               }
+       } else {
+               if (cr3 & CR3_RESEVED_BITS) {
+                       printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
+                       inject_gp(vcpu);
+                       return;
+               }
+               if (is_paging(vcpu) && is_pae(vcpu) &&
+                   pdptrs_have_reserved_bits_set(vcpu, cr3)) {
+                       printk(KERN_DEBUG "set_cr3: #GP, pdptrs "
+                              "reserved bits\n");
+                       inject_gp(vcpu);
+                       return;
+               }
+       }
+
+       vcpu->cr3 = cr3;
+       spin_lock(&vcpu->kvm->lock);
+       vcpu->mmu.new_cr3(vcpu);
+       spin_unlock(&vcpu->kvm->lock);
+}
+EXPORT_SYMBOL_GPL(set_cr3);
+
+void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+{
+       if ( cr8 & CR8_RESEVED_BITS) {
+               printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
+               inject_gp(vcpu);
+               return;
+       }
+       vcpu->cr8 = cr8;
+}
+EXPORT_SYMBOL_GPL(set_cr8);
+
+void fx_init(struct kvm_vcpu *vcpu)
+{
+       struct __attribute__ ((__packed__)) fx_image_s {
+               u16 control; //fcw
+               u16 status; //fsw
+               u16 tag; // ftw
+               u16 opcode; //fop
+               u64 ip; // fpu ip
+               u64 operand;// fpu dp
+               u32 mxcsr;
+               u32 mxcsr_mask;
+
+       } *fx_image;
+
+       fx_save(vcpu->host_fx_image);
+       fpu_init();
+       fx_save(vcpu->guest_fx_image);
+       fx_restore(vcpu->host_fx_image);
+
+       fx_image = (struct fx_image_s *)vcpu->guest_fx_image;
+       fx_image->mxcsr = 0x1f80;
+       memset(vcpu->guest_fx_image + sizeof(struct fx_image_s),
+              0, FX_IMAGE_SIZE - sizeof(struct fx_image_s));
+}
+EXPORT_SYMBOL_GPL(fx_init);
+
+/*
+ * Creates some virtual cpus.  Good luck creating more than one.
+ */
+static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n)
+{
+       int r;
+       struct kvm_vcpu *vcpu;
+
+       r = -EINVAL;
+       if (n < 0 || n >= KVM_MAX_VCPUS)
+               goto out;
+
+       vcpu = &kvm->vcpus[n];
+
+       mutex_lock(&vcpu->mutex);
+
+       if (vcpu->vmcs) {
+               mutex_unlock(&vcpu->mutex);
+               return -EEXIST;
+       }
+
+       vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf,
+                                          FX_IMAGE_ALIGN);
+       vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
+
+       vcpu->cpu = -1;  /* First load will set up TR */
+       vcpu->kvm = kvm;
+       r = kvm_arch_ops->vcpu_create(vcpu);
+       if (r < 0)
+               goto out_free_vcpus;
+
+       kvm_arch_ops->vcpu_load(vcpu);
+
+       r = kvm_arch_ops->vcpu_setup(vcpu);
+       if (r >= 0)
+               r = kvm_mmu_init(vcpu);
+
+       vcpu_put(vcpu);
+
+       if (r < 0)
+               goto out_free_vcpus;
+
+       return 0;
+
+out_free_vcpus:
+       kvm_free_vcpu(vcpu);
+       mutex_unlock(&vcpu->mutex);
+out:
+       return r;
+}
+
+/*
+ * Allocate some memory and give it an address in the guest physical address
+ * space.
+ *
+ * Discontiguous memory is allowed, mostly for framebuffers.
+ */
+static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm,
+                                          struct kvm_memory_region *mem)
+{
+       int r;
+       gfn_t base_gfn;
+       unsigned long npages;
+       unsigned long i;
+       struct kvm_memory_slot *memslot;
+       struct kvm_memory_slot old, new;
+       int memory_config_version;
+
+       r = -EINVAL;
+       /* General sanity checks */
+       if (mem->memory_size & (PAGE_SIZE - 1))
+               goto out;
+       if (mem->guest_phys_addr & (PAGE_SIZE - 1))
+               goto out;
+       if (mem->slot >= KVM_MEMORY_SLOTS)
+               goto out;
+       if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr)
+               goto out;
+
+       memslot = &kvm->memslots[mem->slot];
+       base_gfn = mem->guest_phys_addr >> PAGE_SHIFT;
+       npages = mem->memory_size >> PAGE_SHIFT;
+
+       if (!npages)
+               mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
+
+raced:
+       spin_lock(&kvm->lock);
+
+       memory_config_version = kvm->memory_config_version;
+       new = old = *memslot;
+
+       new.base_gfn = base_gfn;
+       new.npages = npages;
+       new.flags = mem->flags;
+
+       /* Disallow changing a memory slot's size. */
+       r = -EINVAL;
+       if (npages && old.npages && npages != old.npages)
+               goto out_unlock;
+
+       /* Check for overlaps */
+       r = -EEXIST;
+       for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
+               struct kvm_memory_slot *s = &kvm->memslots[i];
+
+               if (s == memslot)
+                       continue;
+               if (!((base_gfn + npages <= s->base_gfn) ||
+                     (base_gfn >= s->base_gfn + s->npages)))
+                       goto out_unlock;
+       }
+       /*
+        * Do memory allocations outside lock.  memory_config_version will
+        * detect any races.
+        */
+       spin_unlock(&kvm->lock);
+
+       /* Deallocate if slot is being removed */
+       if (!npages)
+               new.phys_mem = 0;
+
+       /* Free page dirty bitmap if unneeded */
+       if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
+               new.dirty_bitmap = 0;
+
+       r = -ENOMEM;
+
+       /* Allocate if a slot is being created */
+       if (npages && !new.phys_mem) {
+               new.phys_mem = vmalloc(npages * sizeof(struct page *));
+
+               if (!new.phys_mem)
+                       goto out_free;
+
+               memset(new.phys_mem, 0, npages * sizeof(struct page *));
+               for (i = 0; i < npages; ++i) {
+                       new.phys_mem[i] = alloc_page(GFP_HIGHUSER
+                                                    | __GFP_ZERO);
+                       if (!new.phys_mem[i])
+                               goto out_free;
+               }
+       }
+
+       /* Allocate page dirty bitmap if needed */
+       if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
+               unsigned dirty_bytes = ALIGN(npages, BITS_PER_LONG) / 8;
+
+               new.dirty_bitmap = vmalloc(dirty_bytes);
+               if (!new.dirty_bitmap)
+                       goto out_free;
+               memset(new.dirty_bitmap, 0, dirty_bytes);
+       }
+
+       spin_lock(&kvm->lock);
+
+       if (memory_config_version != kvm->memory_config_version) {
+               spin_unlock(&kvm->lock);
+               kvm_free_physmem_slot(&new, &old);
+               goto raced;
+       }
+
+       r = -EAGAIN;
+       if (kvm->busy)
+               goto out_unlock;
+
+       if (mem->slot >= kvm->nmemslots)
+               kvm->nmemslots = mem->slot + 1;
+
+       *memslot = new;
+       ++kvm->memory_config_version;
+
+       spin_unlock(&kvm->lock);
+
+       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+               struct kvm_vcpu *vcpu;
+
+               vcpu = vcpu_load(kvm, i);
+               if (!vcpu)
+                       continue;
+               kvm_mmu_reset_context(vcpu);
+               vcpu_put(vcpu);
+       }
+
+       kvm_free_physmem_slot(&old, &new);
+       return 0;
+
+out_unlock:
+       spin_unlock(&kvm->lock);
+out_free:
+       kvm_free_physmem_slot(&new, &old);
+out:
+       return r;
+}
+
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm,
+                                      struct kvm_dirty_log *log)
+{
+       struct kvm_memory_slot *memslot;
+       int r, i;
+       int n;
+       unsigned long any = 0;
+
+       spin_lock(&kvm->lock);
+
+       /*
+        * Prevent changes to guest memory configuration even while the lock
+        * is not taken.
+        */
+       ++kvm->busy;
+       spin_unlock(&kvm->lock);
+       r = -EINVAL;
+       if (log->slot >= KVM_MEMORY_SLOTS)
+               goto out;
+
+       memslot = &kvm->memslots[log->slot];
+       r = -ENOENT;
+       if (!memslot->dirty_bitmap)
+               goto out;
+
+       n = ALIGN(memslot->npages, 8) / 8;
+
+       for (i = 0; !any && i < n; ++i)
+               any = memslot->dirty_bitmap[i];
+
+       r = -EFAULT;
+       if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
+               goto out;
+
+
+       if (any) {
+               spin_lock(&kvm->lock);
+               kvm_mmu_slot_remove_write_access(kvm, log->slot);
+               spin_unlock(&kvm->lock);
+               memset(memslot->dirty_bitmap, 0, n);
+               for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+                       struct kvm_vcpu *vcpu = vcpu_load(kvm, i);
+
+                       if (!vcpu)
+                               continue;
+                       kvm_arch_ops->tlb_flush(vcpu);
+                       vcpu_put(vcpu);
+               }
+       }
+
+       r = 0;
+
+out:
+       spin_lock(&kvm->lock);
+       --kvm->busy;
+       spin_unlock(&kvm->lock);
+       return r;
+}
+
+struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
+{
+       int i;
+
+       for (i = 0; i < kvm->nmemslots; ++i) {
+               struct kvm_memory_slot *memslot = &kvm->memslots[i];
+
+               if (gfn >= memslot->base_gfn
+                   && gfn < memslot->base_gfn + memslot->npages)
+                       return memslot;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gfn_to_memslot);
+
+void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
+{
+       int i;
+       struct kvm_memory_slot *memslot = 0;
+       unsigned long rel_gfn;
+
+       for (i = 0; i < kvm->nmemslots; ++i) {
+               memslot = &kvm->memslots[i];
+
+               if (gfn >= memslot->base_gfn
+                   && gfn < memslot->base_gfn + memslot->npages) {
+
+                       if (!memslot || !memslot->dirty_bitmap)
+                               return;
+
+                       rel_gfn = gfn - memslot->base_gfn;
+
+                       /* avoid RMW */
+                       if (!test_bit(rel_gfn, memslot->dirty_bitmap))
+                               set_bit(rel_gfn, memslot->dirty_bitmap);
+                       return;
+               }
+       }
+}
+
+static int emulator_read_std(unsigned long addr,
+                            unsigned long *val,
+                            unsigned int bytes,
+                            struct x86_emulate_ctxt *ctxt)
+{
+       struct kvm_vcpu *vcpu = ctxt->vcpu;
+       void *data = val;
+
+       while (bytes) {
+               gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+               unsigned offset = addr & (PAGE_SIZE-1);
+               unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset);
+               unsigned long pfn;
+               struct kvm_memory_slot *memslot;
+               void *page;
+
+               if (gpa == UNMAPPED_GVA)
+                       return X86EMUL_PROPAGATE_FAULT;
+               pfn = gpa >> PAGE_SHIFT;
+               memslot = gfn_to_memslot(vcpu->kvm, pfn);
+               if (!memslot)
+                       return X86EMUL_UNHANDLEABLE;
+               page = kmap_atomic(gfn_to_page(memslot, pfn), KM_USER0);
+
+               memcpy(data, page + offset, tocopy);
+
+               kunmap_atomic(page, KM_USER0);
+
+               bytes -= tocopy;
+               data += tocopy;
+               addr += tocopy;
+       }
+
+       return X86EMUL_CONTINUE;
+}
+
+static int emulator_write_std(unsigned long addr,
+                             unsigned long val,
+                             unsigned int bytes,
+                             struct x86_emulate_ctxt *ctxt)
+{
+       printk(KERN_ERR "emulator_write_std: addr %lx n %d\n",
+              addr, bytes);
+       return X86EMUL_UNHANDLEABLE;
+}
+
+static int emulator_read_emulated(unsigned long addr,
+                                 unsigned long *val,
+                                 unsigned int bytes,
+                                 struct x86_emulate_ctxt *ctxt)
+{
+       struct kvm_vcpu *vcpu = ctxt->vcpu;
+
+       if (vcpu->mmio_read_completed) {
+               memcpy(val, vcpu->mmio_data, bytes);
+               vcpu->mmio_read_completed = 0;
+               return X86EMUL_CONTINUE;
+       } else if (emulator_read_std(addr, val, bytes, ctxt)
+                  == X86EMUL_CONTINUE)
+               return X86EMUL_CONTINUE;
+       else {
+               gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+               if (gpa == UNMAPPED_GVA)
+                       return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT;
+               vcpu->mmio_needed = 1;
+               vcpu->mmio_phys_addr = gpa;
+               vcpu->mmio_size = bytes;
+               vcpu->mmio_is_write = 0;
+
+               return X86EMUL_UNHANDLEABLE;
+       }
+}
+
+static int emulator_write_emulated(unsigned long addr,
+                                  unsigned long val,
+                                  unsigned int bytes,
+                                  struct x86_emulate_ctxt *ctxt)
+{
+       struct kvm_vcpu *vcpu = ctxt->vcpu;
+       gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+
+       if (gpa == UNMAPPED_GVA)
+               return X86EMUL_PROPAGATE_FAULT;
+
+       vcpu->mmio_needed = 1;
+       vcpu->mmio_phys_addr = gpa;
+       vcpu->mmio_size = bytes;
+       vcpu->mmio_is_write = 1;
+       memcpy(vcpu->mmio_data, &val, bytes);
+
+       return X86EMUL_CONTINUE;
+}
+
+static int emulator_cmpxchg_emulated(unsigned long addr,
+                                    unsigned long old,
+                                    unsigned long new,
+                                    unsigned int bytes,
+                                    struct x86_emulate_ctxt *ctxt)
+{
+       static int reported;
+
+       if (!reported) {
+               reported = 1;
+               printk(KERN_WARNING "kvm: emulating exchange as write\n");
+       }
+       return emulator_write_emulated(addr, new, bytes, ctxt);
+}
+
+static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+       return kvm_arch_ops->get_segment_base(vcpu, seg);
+}
+
+int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
+{
+       spin_lock(&vcpu->kvm->lock);
+       vcpu->mmu.inval_page(vcpu, address);
+       spin_unlock(&vcpu->kvm->lock);
+       kvm_arch_ops->invlpg(vcpu, address);
+       return X86EMUL_CONTINUE;
+}
+
+int emulate_clts(struct kvm_vcpu *vcpu)
+{
+       unsigned long cr0 = vcpu->cr0;
+
+       cr0 &= ~CR0_TS_MASK;
+       kvm_arch_ops->set_cr0(vcpu, cr0);
+       return X86EMUL_CONTINUE;
+}
+
+int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, unsigned long *dest)
+{
+       struct kvm_vcpu *vcpu = ctxt->vcpu;
+
+       switch (dr) {
+       case 0 ... 3:
+               *dest = kvm_arch_ops->get_dr(vcpu, dr);
+               return X86EMUL_CONTINUE;
+       default:
+               printk(KERN_DEBUG "%s: unexpected dr %u\n",
+                      __FUNCTION__, dr);
+               return X86EMUL_UNHANDLEABLE;
+       }
+}
+
+int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
+{
+       unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
+       int exception;
+
+       kvm_arch_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception);
+       if (exception) {
+               /* FIXME: better handling */
+               return X86EMUL_UNHANDLEABLE;
+       }
+       return X86EMUL_CONTINUE;
+}
+
+static void report_emulation_failure(struct x86_emulate_ctxt *ctxt)
+{
+       static int reported;
+       u8 opcodes[4];
+       unsigned long rip = ctxt->vcpu->rip;
+       unsigned long rip_linear;
+
+       rip_linear = rip + get_segment_base(ctxt->vcpu, VCPU_SREG_CS);
+
+       if (reported)
+               return;
+
+       emulator_read_std(rip_linear, (void *)opcodes, 4, ctxt);
+
+       printk(KERN_ERR "emulation failed but !mmio_needed?"
+              " rip %lx %02x %02x %02x %02x\n",
+              rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
+       reported = 1;
+}
+
+struct x86_emulate_ops emulate_ops = {
+       .read_std            = emulator_read_std,
+       .write_std           = emulator_write_std,
+       .read_emulated       = emulator_read_emulated,
+       .write_emulated      = emulator_write_emulated,
+       .cmpxchg_emulated    = emulator_cmpxchg_emulated,
+};
+
+int emulate_instruction(struct kvm_vcpu *vcpu,
+                       struct kvm_run *run,
+                       unsigned long cr2,
+                       u16 error_code)
+{
+       struct x86_emulate_ctxt emulate_ctxt;
+       int r;
+       int cs_db, cs_l;
+
+       kvm_arch_ops->cache_regs(vcpu);
+
+       kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+
+       emulate_ctxt.vcpu = vcpu;
+       emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu);
+       emulate_ctxt.cr2 = cr2;
+       emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM)
+               ? X86EMUL_MODE_REAL : cs_l
+               ? X86EMUL_MODE_PROT64 : cs_db
+               ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+
+       if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
+               emulate_ctxt.cs_base = 0;
+               emulate_ctxt.ds_base = 0;
+               emulate_ctxt.es_base = 0;
+               emulate_ctxt.ss_base = 0;
+       } else {
+               emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
+               emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
+               emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
+               emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
+       }
+
+       emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
+       emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);
+
+       vcpu->mmio_is_write = 0;
+       r = x86_emulate_memop(&emulate_ctxt, &emulate_ops);
+
+       if ((r || vcpu->mmio_is_write) && run) {
+               run->mmio.phys_addr = vcpu->mmio_phys_addr;
+               memcpy(run->mmio.data, vcpu->mmio_data, 8);
+               run->mmio.len = vcpu->mmio_size;
+               run->mmio.is_write = vcpu->mmio_is_write;
+       }
+
+       if (r) {
+               if (!vcpu->mmio_needed) {
+                       report_emulation_failure(&emulate_ctxt);
+                       return EMULATE_FAIL;
+               }
+               return EMULATE_DO_MMIO;
+       }
+
+       kvm_arch_ops->decache_regs(vcpu);
+       kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags);
+
+       if (vcpu->mmio_is_write)
+               return EMULATE_DO_MMIO;
+
+       return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(emulate_instruction);
+
+static u64 mk_cr_64(u64 curr_cr, u32 new_val)
+{
+       return (curr_cr & ~((1ULL << 32) - 1)) | new_val;
+}
+
+void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
+{
+       struct descriptor_table dt = { limit, base };
+
+       kvm_arch_ops->set_gdt(vcpu, &dt);
+}
+
+void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
+{
+       struct descriptor_table dt = { limit, base };
+
+       kvm_arch_ops->set_idt(vcpu, &dt);
+}
+
+void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+                  unsigned long *rflags)
+{
+       lmsw(vcpu, msw);
+       *rflags = kvm_arch_ops->get_rflags(vcpu);
+}
+
+unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
+{
+       switch (cr) {
+       case 0:
+               return vcpu->cr0;
+       case 2:
+               return vcpu->cr2;
+       case 3:
+               return vcpu->cr3;
+       case 4:
+               return vcpu->cr4;
+       default:
+               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+               return 0;
+       }
+}
+
+void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
+                    unsigned long *rflags)
+{
+       switch (cr) {
+       case 0:
+               set_cr0(vcpu, mk_cr_64(vcpu->cr0, val));
+               *rflags = kvm_arch_ops->get_rflags(vcpu);
+               break;
+       case 2:
+               vcpu->cr2 = val;
+               break;
+       case 3:
+               set_cr3(vcpu, val);
+               break;
+       case 4:
+               set_cr4(vcpu, mk_cr_64(vcpu->cr4, val));
+               break;
+       default:
+               vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+       }
+}
+
+/*
+ * Reads an msr value (of 'msr_index') into 'pdata'.
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+       return kvm_arch_ops->get_msr(vcpu, msr_index, pdata);
+}
+
+#ifdef __x86_64__
+
+void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+       struct vmx_msr_entry *msr;
+
+       if (efer & EFER_RESERVED_BITS) {
+               printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
+                      efer);
+               inject_gp(vcpu);
+               return;
+       }
+
+       if (is_paging(vcpu)
+           && (vcpu->shadow_efer & EFER_LME) != (efer & EFER_LME)) {
+               printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n");
+               inject_gp(vcpu);
+               return;
+       }
+
+       efer &= ~EFER_LMA;
+       efer |= vcpu->shadow_efer & EFER_LMA;
+
+       vcpu->shadow_efer = efer;
+
+       msr = find_msr_entry(vcpu, MSR_EFER);
+
+       if (!(efer & EFER_LMA))
+           efer &= ~EFER_LME;
+       msr->data = efer;
+}
+EXPORT_SYMBOL_GPL(set_efer);
+
+#endif
+
+/*
+ * Writes msr value into into the appropriate "register".
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+       return kvm_arch_ops->set_msr(vcpu, msr_index, data);
+}
+
+void kvm_resched(struct kvm_vcpu *vcpu)
+{
+       vcpu_put(vcpu);
+       cond_resched();
+       /* Cannot fail -  no vcpu unplug yet. */
+       vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
+}
+EXPORT_SYMBOL_GPL(kvm_resched);
+
+void load_msrs(struct vmx_msr_entry *e, int n)
+{
+       int i;
+
+       for (i = 0; i < n; ++i)
+               wrmsrl(e[i].index, e[i].data);
+}
+EXPORT_SYMBOL_GPL(load_msrs);
+
+void save_msrs(struct vmx_msr_entry *e, int n)
+{
+       int i;
+
+       for (i = 0; i < n; ++i)
+               rdmsrl(e[i].index, e[i].data);
+}
+EXPORT_SYMBOL_GPL(save_msrs);
+
+static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)
+{
+       struct kvm_vcpu *vcpu;
+       int r;
+
+       if (kvm_run->vcpu < 0 || kvm_run->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
+       vcpu = vcpu_load(kvm, kvm_run->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       if (kvm_run->emulated) {
+               kvm_arch_ops->skip_emulated_instruction(vcpu);
+               kvm_run->emulated = 0;
+       }
+
+       if (kvm_run->mmio_completed) {
+               memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
+               vcpu->mmio_read_completed = 1;
+       }
+
+       vcpu->mmio_needed = 0;
+
+       r = kvm_arch_ops->run(vcpu, kvm_run);
+
+       vcpu_put(vcpu);
+       return r;
+}
+
+static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs)
+{
+       struct kvm_vcpu *vcpu;
+
+       if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
+       vcpu = vcpu_load(kvm, regs->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       kvm_arch_ops->cache_regs(vcpu);
+
+       regs->rax = vcpu->regs[VCPU_REGS_RAX];
+       regs->rbx = vcpu->regs[VCPU_REGS_RBX];
+       regs->rcx = vcpu->regs[VCPU_REGS_RCX];
+       regs->rdx = vcpu->regs[VCPU_REGS_RDX];
+       regs->rsi = vcpu->regs[VCPU_REGS_RSI];
+       regs->rdi = vcpu->regs[VCPU_REGS_RDI];
+       regs->rsp = vcpu->regs[VCPU_REGS_RSP];
+       regs->rbp = vcpu->regs[VCPU_REGS_RBP];
+#ifdef __x86_64__
+       regs->r8 = vcpu->regs[VCPU_REGS_R8];
+       regs->r9 = vcpu->regs[VCPU_REGS_R9];
+       regs->r10 = vcpu->regs[VCPU_REGS_R10];
+       regs->r11 = vcpu->regs[VCPU_REGS_R11];
+       regs->r12 = vcpu->regs[VCPU_REGS_R12];
+       regs->r13 = vcpu->regs[VCPU_REGS_R13];
+       regs->r14 = vcpu->regs[VCPU_REGS_R14];
+       regs->r15 = vcpu->regs[VCPU_REGS_R15];
+#endif
+
+       regs->rip = vcpu->rip;
+       regs->rflags = kvm_arch_ops->get_rflags(vcpu);
+
+       /*
+        * Don't leak debug flags in case they were set for guest debugging
+        */
+       if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep)
+               regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs)
+{
+       struct kvm_vcpu *vcpu;
+
+       if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
+       vcpu = vcpu_load(kvm, regs->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       vcpu->regs[VCPU_REGS_RAX] = regs->rax;
+       vcpu->regs[VCPU_REGS_RBX] = regs->rbx;
+       vcpu->regs[VCPU_REGS_RCX] = regs->rcx;
+       vcpu->regs[VCPU_REGS_RDX] = regs->rdx;
+       vcpu->regs[VCPU_REGS_RSI] = regs->rsi;
+       vcpu->regs[VCPU_REGS_RDI] = regs->rdi;
+       vcpu->regs[VCPU_REGS_RSP] = regs->rsp;
+       vcpu->regs[VCPU_REGS_RBP] = regs->rbp;
+#ifdef __x86_64__
+       vcpu->regs[VCPU_REGS_R8] = regs->r8;
+       vcpu->regs[VCPU_REGS_R9] = regs->r9;
+       vcpu->regs[VCPU_REGS_R10] = regs->r10;
+       vcpu->regs[VCPU_REGS_R11] = regs->r11;
+       vcpu->regs[VCPU_REGS_R12] = regs->r12;
+       vcpu->regs[VCPU_REGS_R13] = regs->r13;
+       vcpu->regs[VCPU_REGS_R14] = regs->r14;
+       vcpu->regs[VCPU_REGS_R15] = regs->r15;
+#endif
+
+       vcpu->rip = regs->rip;
+       kvm_arch_ops->set_rflags(vcpu, regs->rflags);
+
+       kvm_arch_ops->decache_regs(vcpu);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static void get_segment(struct kvm_vcpu *vcpu,
+                       struct kvm_segment *var, int seg)
+{
+       return kvm_arch_ops->get_segment(vcpu, var, seg);
+}
+
+static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+{
+       struct kvm_vcpu *vcpu;
+       struct descriptor_table dt;
+
+       if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+       vcpu = vcpu_load(kvm, sregs->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       get_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
+       get_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
+       get_segment(vcpu, &sregs->es, VCPU_SREG_ES);
+       get_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
+       get_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
+       get_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
+
+       get_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
+       get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
+
+       kvm_arch_ops->get_idt(vcpu, &dt);
+       sregs->idt.limit = dt.limit;
+       sregs->idt.base = dt.base;
+       kvm_arch_ops->get_gdt(vcpu, &dt);
+       sregs->gdt.limit = dt.limit;
+       sregs->gdt.base = dt.base;
+
+       sregs->cr0 = vcpu->cr0;
+       sregs->cr2 = vcpu->cr2;
+       sregs->cr3 = vcpu->cr3;
+       sregs->cr4 = vcpu->cr4;
+       sregs->cr8 = vcpu->cr8;
+       sregs->efer = vcpu->shadow_efer;
+       sregs->apic_base = vcpu->apic_base;
+
+       memcpy(sregs->interrupt_bitmap, vcpu->irq_pending,
+              sizeof sregs->interrupt_bitmap);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static void set_segment(struct kvm_vcpu *vcpu,
+                       struct kvm_segment *var, int seg)
+{
+       return kvm_arch_ops->set_segment(vcpu, var, seg);
+}
+
+static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+{
+       struct kvm_vcpu *vcpu;
+       int mmu_reset_needed = 0;
+       int i;
+       struct descriptor_table dt;
+
+       if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+       vcpu = vcpu_load(kvm, sregs->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
+       set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
+       set_segment(vcpu, &sregs->es, VCPU_SREG_ES);
+       set_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
+       set_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
+       set_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
+
+       set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
+       set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
+
+       dt.limit = sregs->idt.limit;
+       dt.base = sregs->idt.base;
+       kvm_arch_ops->set_idt(vcpu, &dt);
+       dt.limit = sregs->gdt.limit;
+       dt.base = sregs->gdt.base;
+       kvm_arch_ops->set_gdt(vcpu, &dt);
+
+       vcpu->cr2 = sregs->cr2;
+       mmu_reset_needed |= vcpu->cr3 != sregs->cr3;
+       vcpu->cr3 = sregs->cr3;
+
+       vcpu->cr8 = sregs->cr8;
+
+       mmu_reset_needed |= vcpu->shadow_efer != sregs->efer;
+#ifdef __x86_64__
+       kvm_arch_ops->set_efer(vcpu, sregs->efer);
+#endif
+       vcpu->apic_base = sregs->apic_base;
+
+       mmu_reset_needed |= vcpu->cr0 != sregs->cr0;
+       kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0);
+
+       mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
+       kvm_arch_ops->set_cr4(vcpu, sregs->cr4);
+
+       if (mmu_reset_needed)
+               kvm_mmu_reset_context(vcpu);
+
+       memcpy(vcpu->irq_pending, sregs->interrupt_bitmap,
+              sizeof vcpu->irq_pending);
+       vcpu->irq_summary = 0;
+       for (i = 0; i < NR_IRQ_WORDS; ++i)
+               if (vcpu->irq_pending[i])
+                       __set_bit(i, &vcpu->irq_summary);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+/*
+ * List of msr numbers which we expose to userspace through KVM_GET_MSRS
+ * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
+ */
+static u32 msrs_to_save[] = {
+       MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
+       MSR_K6_STAR,
+#ifdef __x86_64__
+       MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
+#endif
+       MSR_IA32_TIME_STAMP_COUNTER,
+};
+
+
+/*
+ * Adapt set_msr() to msr_io()'s calling convention
+ */
+static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
+{
+       return set_msr(vcpu, index, *data);
+}
+
+/*
+ * Read or write a bunch of msrs. All parameters are kernel addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs,
+                   struct kvm_msr_entry *entries,
+                   int (*do_msr)(struct kvm_vcpu *vcpu,
+                                 unsigned index, u64 *data))
+{
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       if (msrs->vcpu < 0 || msrs->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
+       vcpu = vcpu_load(kvm, msrs->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       for (i = 0; i < msrs->nmsrs; ++i)
+               if (do_msr(vcpu, entries[i].index, &entries[i].data))
+                       break;
+
+       vcpu_put(vcpu);
+
+       return i;
+}
+
+/*
+ * Read or write a bunch of msrs. Parameters are user addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs,
+                 int (*do_msr)(struct kvm_vcpu *vcpu,
+                               unsigned index, u64 *data),
+                 int writeback)
+{
+       struct kvm_msrs msrs;
+       struct kvm_msr_entry *entries;
+       int r, n;
+       unsigned size;
+
+       r = -EFAULT;
+       if (copy_from_user(&msrs, user_msrs, sizeof msrs))
+               goto out;
+
+       r = -E2BIG;
+       if (msrs.nmsrs >= MAX_IO_MSRS)
+               goto out;
+
+       r = -ENOMEM;
+       size = sizeof(struct kvm_msr_entry) * msrs.nmsrs;
+       entries = vmalloc(size);
+       if (!entries)
+               goto out;
+
+       r = -EFAULT;
+       if (copy_from_user(entries, user_msrs->entries, size))
+               goto out_free;
+
+       r = n = __msr_io(kvm, &msrs, entries, do_msr);
+       if (r < 0)
+               goto out_free;
+
+       r = -EFAULT;
+       if (writeback && copy_to_user(user_msrs->entries, entries, size))
+               goto out_free;
+
+       r = n;
+
+out_free:
+       vfree(entries);
+out:
+       return r;
+}
+
+/*
+ * Translate a guest virtual address to a guest physical address.
+ */
+static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr)
+{
+       unsigned long vaddr = tr->linear_address;
+       struct kvm_vcpu *vcpu;
+       gpa_t gpa;
+
+       vcpu = vcpu_load(kvm, tr->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+       spin_lock(&kvm->lock);
+       gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr);
+       tr->physical_address = gpa;
+       tr->valid = gpa != UNMAPPED_GVA;
+       tr->writeable = 1;
+       tr->usermode = 0;
+       spin_unlock(&kvm->lock);
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq)
+{
+       struct kvm_vcpu *vcpu;
+
+       if (irq->vcpu < 0 || irq->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+       if (irq->irq < 0 || irq->irq >= 256)
+               return -EINVAL;
+       vcpu = vcpu_load(kvm, irq->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       set_bit(irq->irq, vcpu->irq_pending);
+       set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary);
+
+       vcpu_put(vcpu);
+
+       return 0;
+}
+
+static int kvm_dev_ioctl_debug_guest(struct kvm *kvm,
+                                    struct kvm_debug_guest *dbg)
+{
+       struct kvm_vcpu *vcpu;
+       int r;
+
+       if (dbg->vcpu < 0 || dbg->vcpu >= KVM_MAX_VCPUS)
+               return -EINVAL;
+       vcpu = vcpu_load(kvm, dbg->vcpu);
+       if (!vcpu)
+               return -ENOENT;
+
+       r = kvm_arch_ops->set_guest_debug(vcpu, dbg);
+
+       vcpu_put(vcpu);
+
+       return r;
+}
+
+static long kvm_dev_ioctl(struct file *filp,
+                         unsigned int ioctl, unsigned long arg)
+{
+       struct kvm *kvm = filp->private_data;
+       int r = -EINVAL;
+
+       switch (ioctl) {
+       case KVM_CREATE_VCPU: {
+               r = kvm_dev_ioctl_create_vcpu(kvm, arg);
+               if (r)
+                       goto out;
+               break;
+       }
+       case KVM_RUN: {
+               struct kvm_run kvm_run;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run))
+                       goto out;
+               r = kvm_dev_ioctl_run(kvm, &kvm_run);
+               if (r < 0)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_GET_REGS: {
+               struct kvm_regs kvm_regs;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+                       goto out;
+               r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_REGS: {
+               struct kvm_regs kvm_regs;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+                       goto out;
+               r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_GET_SREGS: {
+               struct kvm_sregs kvm_sregs;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+                       goto out;
+               r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_SREGS: {
+               struct kvm_sregs kvm_sregs;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+                       goto out;
+               r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_TRANSLATE: {
+               struct kvm_translation tr;
+
+               r = -EFAULT;
+               if (copy_from_user(&tr, (void *)arg, sizeof tr))
+                       goto out;
+               r = kvm_dev_ioctl_translate(kvm, &tr);
+               if (r)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user((void *)arg, &tr, sizeof tr))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_INTERRUPT: {
+               struct kvm_interrupt irq;
+
+               r = -EFAULT;
+               if (copy_from_user(&irq, (void *)arg, sizeof irq))
+                       goto out;
+               r = kvm_dev_ioctl_interrupt(kvm, &irq);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_DEBUG_GUEST: {
+               struct kvm_debug_guest dbg;
+
+               r = -EFAULT;
+               if (copy_from_user(&dbg, (void *)arg, sizeof dbg))
+                       goto out;
+               r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
+               if (r)
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_SET_MEMORY_REGION: {
+               struct kvm_memory_region kvm_mem;
+
+               r = -EFAULT;
+               if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
+                       goto out;
+               r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
+               if (r)
+                       goto out;
+               break;
+       }
+       case KVM_GET_DIRTY_LOG: {
+               struct kvm_dirty_log log;
+
+               r = -EFAULT;
+               if (copy_from_user(&log, (void *)arg, sizeof log))
+                       goto out;
+               r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
+               if (r)
+                       goto out;
+               break;
+       }
+       case KVM_GET_MSRS:
+               r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+               break;
+       case KVM_SET_MSRS:
+               r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+               break;
+       case KVM_GET_MSR_INDEX_LIST: {
+               struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+               struct kvm_msr_list msr_list;
+               unsigned n;
+
+               r = -EFAULT;
+               if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
+                       goto out;
+               n = msr_list.nmsrs;
+               msr_list.nmsrs = ARRAY_SIZE(msrs_to_save);
+               if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
+                       goto out;
+               r = -E2BIG;
+               if (n < ARRAY_SIZE(msrs_to_save))
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(user_msr_list->indices, &msrs_to_save,
+                                sizeof msrs_to_save))
+                       goto out;
+               r = 0;
+       }
+       default:
+               ;
+       }
+out:
+       return r;
+}
+
+static struct page *kvm_dev_nopage(struct vm_area_struct *vma,
+                                  unsigned long address,
+                                  int *type)
+{
+       struct kvm *kvm = vma->vm_file->private_data;
+       unsigned long pgoff;
+       struct kvm_memory_slot *slot;
+       struct page *page;
+
+       *type = VM_FAULT_MINOR;
+       pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+       slot = gfn_to_memslot(kvm, pgoff);
+       if (!slot)
+               return NOPAGE_SIGBUS;
+       page = gfn_to_page(slot, pgoff);
+       if (!page)
+               return NOPAGE_SIGBUS;
+       get_page(page);
+       return page;
+}
+
+static struct vm_operations_struct kvm_dev_vm_ops = {
+       .nopage = kvm_dev_nopage,
+};
+
+static int kvm_dev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       vma->vm_ops = &kvm_dev_vm_ops;
+       return 0;
+}
+
+static struct file_operations kvm_chardev_ops = {
+       .open           = kvm_dev_open,
+       .release        = kvm_dev_release,
+       .unlocked_ioctl = kvm_dev_ioctl,
+       .compat_ioctl   = kvm_dev_ioctl,
+       .mmap           = kvm_dev_mmap,
+};
+
+static struct miscdevice kvm_dev = {
+       MISC_DYNAMIC_MINOR,
+       "kvm",
+       &kvm_chardev_ops,
+};
+
+static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
+                       void *v)
+{
+       if (val == SYS_RESTART) {
+               /*
+                * Some (well, at least mine) BIOSes hang on reboot if
+                * in vmx root mode.
+                */
+               printk(KERN_INFO "kvm: exiting hardware virtualization\n");
+               on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_reboot_notifier = {
+       .notifier_call = kvm_reboot,
+       .priority = 0,
+};
+
+static __init void kvm_init_debug(void)
+{
+       struct kvm_stats_debugfs_item *p;
+
+       debugfs_dir = debugfs_create_dir("kvm", 0);
+       for (p = debugfs_entries; p->name; ++p)
+               p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
+                                              p->data);
+}
+
+static void kvm_exit_debug(void)
+{
+       struct kvm_stats_debugfs_item *p;
+
+       for (p = debugfs_entries; p->name; ++p)
+               debugfs_remove(p->dentry);
+       debugfs_remove(debugfs_dir);
+}
+
+hpa_t bad_page_address;
+
+int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
+{
+       int r;
+
+       kvm_arch_ops = ops;
+
+       if (!kvm_arch_ops->cpu_has_kvm_support()) {
+               printk(KERN_ERR "kvm: no hardware support\n");
+               return -EOPNOTSUPP;
+       }
+       if (kvm_arch_ops->disabled_by_bios()) {
+               printk(KERN_ERR "kvm: disabled by bios\n");
+               return -EOPNOTSUPP;
+       }
+
+       r = kvm_arch_ops->hardware_setup();
+       if (r < 0)
+           return r;
+
+       on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+       register_reboot_notifier(&kvm_reboot_notifier);
+
+       kvm_chardev_ops.owner = module;
+
+       r = misc_register(&kvm_dev);
+       if (r) {
+               printk (KERN_ERR "kvm: misc device register failed\n");
+               goto out_free;
+       }
+
+       return r;
+
+out_free:
+       unregister_reboot_notifier(&kvm_reboot_notifier);
+       on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       kvm_arch_ops->hardware_unsetup();
+       return r;
+}
+
+void kvm_exit_arch(void)
+{
+       misc_deregister(&kvm_dev);
+
+       unregister_reboot_notifier(&kvm_reboot_notifier);
+       on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       kvm_arch_ops->hardware_unsetup();
+}
+
+static __init int kvm_init(void)
+{
+       static struct page *bad_page;
+       int r = 0;
+
+       kvm_init_debug();
+
+       if ((bad_page = alloc_page(GFP_KERNEL)) == NULL) {
+               r = -ENOMEM;
+               goto out;
+       }
+
+       bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT;
+       memset(__va(bad_page_address), 0, PAGE_SIZE);
+
+       return r;
+
+out:
+       kvm_exit_debug();
+       return r;
+}
+
+static __exit void kvm_exit(void)
+{
+       kvm_exit_debug();
+       __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT));
+}
+
+module_init(kvm_init)
+module_exit(kvm_exit)
+
+EXPORT_SYMBOL_GPL(kvm_init_arch);
+EXPORT_SYMBOL_GPL(kvm_exit_arch);
diff --git a/drivers/kvm/kvm_svm.h b/drivers/kvm/kvm_svm.h
new file mode 100644 (file)
index 0000000..7d7f2aa
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __KVM_SVM_H
+#define __KVM_SVM_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <asm/msr.h>
+
+#include "svm.h"
+#include "kvm.h"
+
+static const u32 host_save_msrs[] = {
+#ifdef __x86_64__
+       MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
+       MSR_FS_BASE, MSR_GS_BASE,
+#endif
+       MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
+       MSR_IA32_DEBUGCTLMSR, /*MSR_IA32_LASTBRANCHFROMIP,
+       MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/
+};
+
+#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs))
+#define NUM_DB_REGS 4
+
+struct vcpu_svm {
+       struct vmcb *vmcb;
+       unsigned long vmcb_pa;
+       struct svm_cpu_data *svm_data;
+       uint64_t asid_generation;
+
+       unsigned long cr0;
+       unsigned long cr4;
+       unsigned long db_regs[NUM_DB_REGS];
+
+       u64 next_rip;
+
+       u64 host_msrs[NR_HOST_SAVE_MSRS];
+       unsigned long host_cr2;
+       unsigned long host_db_regs[NUM_DB_REGS];
+       unsigned long host_dr6;
+       unsigned long host_dr7;
+};
+
+#endif
+
diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h
new file mode 100644 (file)
index 0000000..87e12d2
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __KVM_VMX_H
+#define __KVM_VMX_H
+
+#ifdef __x86_64__
+/*
+ * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
+ * mechanism (cpu bug AA24)
+ */
+#define NR_BAD_MSRS 2
+#else
+#define NR_BAD_MSRS 0
+#endif
+
+#endif
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
new file mode 100644 (file)
index 0000000..4e29d9b
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * MMU support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Avi Kivity   <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+#include "vmx.h"
+#include "kvm.h"
+
+#define pgprintk(x...) do { } while (0)
+
+#define ASSERT(x)                                                      \
+       if (!(x)) {                                                     \
+               printk(KERN_WARNING "assertion failed %s:%d: %s\n",     \
+                      __FILE__, __LINE__, #x);                         \
+       }
+
+#define PT64_ENT_PER_PAGE 512
+#define PT32_ENT_PER_PAGE 1024
+
+#define PT_WRITABLE_SHIFT 1
+
+#define PT_PRESENT_MASK (1ULL << 0)
+#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT)
+#define PT_USER_MASK (1ULL << 2)
+#define PT_PWT_MASK (1ULL << 3)
+#define PT_PCD_MASK (1ULL << 4)
+#define PT_ACCESSED_MASK (1ULL << 5)
+#define PT_DIRTY_MASK (1ULL << 6)
+#define PT_PAGE_SIZE_MASK (1ULL << 7)
+#define PT_PAT_MASK (1ULL << 7)
+#define PT_GLOBAL_MASK (1ULL << 8)
+#define PT64_NX_MASK (1ULL << 63)
+
+#define PT_PAT_SHIFT 7
+#define PT_DIR_PAT_SHIFT 12
+#define PT_DIR_PAT_MASK (1ULL << PT_DIR_PAT_SHIFT)
+
+#define PT32_DIR_PSE36_SIZE 4
+#define PT32_DIR_PSE36_SHIFT 13
+#define PT32_DIR_PSE36_MASK (((1ULL << PT32_DIR_PSE36_SIZE) - 1) << PT32_DIR_PSE36_SHIFT)
+
+
+#define PT32_PTE_COPY_MASK \
+       (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
+       PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAT_MASK | \
+       PT_GLOBAL_MASK )
+
+#define PT32_NON_PTE_COPY_MASK \
+       (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
+       PT_ACCESSED_MASK | PT_DIRTY_MASK)
+
+
+#define PT64_PTE_COPY_MASK \
+       (PT64_NX_MASK | PT32_PTE_COPY_MASK)
+
+#define PT64_NON_PTE_COPY_MASK \
+       (PT64_NX_MASK | PT32_NON_PTE_COPY_MASK)
+
+
+
+#define PT_FIRST_AVAIL_BITS_SHIFT 9
+#define PT64_SECOND_AVAIL_BITS_SHIFT 52
+
+#define PT_SHADOW_PS_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+#define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+
+#define PT_SHADOW_WRITABLE_SHIFT (PT_FIRST_AVAIL_BITS_SHIFT + 1)
+#define PT_SHADOW_WRITABLE_MASK (1ULL << PT_SHADOW_WRITABLE_SHIFT)
+
+#define PT_SHADOW_USER_SHIFT (PT_SHADOW_WRITABLE_SHIFT + 1)
+#define PT_SHADOW_USER_MASK (1ULL << (PT_SHADOW_USER_SHIFT))
+
+#define PT_SHADOW_BITS_OFFSET (PT_SHADOW_WRITABLE_SHIFT - PT_WRITABLE_SHIFT)
+
+#define VALID_PAGE(x) ((x) != INVALID_PAGE)
+
+#define PT64_LEVEL_BITS 9
+
+#define PT64_LEVEL_SHIFT(level) \
+               ( PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS )
+
+#define PT64_LEVEL_MASK(level) \
+               (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level))
+
+#define PT64_INDEX(address, level)\
+       (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
+
+
+#define PT32_LEVEL_BITS 10
+
+#define PT32_LEVEL_SHIFT(level) \
+               ( PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS )
+
+#define PT32_LEVEL_MASK(level) \
+               (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level))
+
+#define PT32_INDEX(address, level)\
+       (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1))
+
+
+#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK)
+#define PT64_DIR_BASE_ADDR_MASK \
+       (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1))
+
+#define PT32_BASE_ADDR_MASK PAGE_MASK
+#define PT32_DIR_BASE_ADDR_MASK \
+       (PAGE_MASK & ~((1ULL << (PAGE_SHIFT + PT32_LEVEL_BITS)) - 1))
+
+
+#define PFERR_PRESENT_MASK (1U << 0)
+#define PFERR_WRITE_MASK (1U << 1)
+#define PFERR_USER_MASK (1U << 2)
+
+#define PT64_ROOT_LEVEL 4
+#define PT32_ROOT_LEVEL 2
+#define PT32E_ROOT_LEVEL 3
+
+#define PT_DIRECTORY_LEVEL 2
+#define PT_PAGE_TABLE_LEVEL 1
+
+static int is_write_protection(struct kvm_vcpu *vcpu)
+{
+       return vcpu->cr0 & CR0_WP_MASK;
+}
+
+static int is_cpuid_PSE36(void)
+{
+       return 1;
+}
+
+static int is_present_pte(unsigned long pte)
+{
+       return pte & PT_PRESENT_MASK;
+}
+
+static int is_writeble_pte(unsigned long pte)
+{
+       return pte & PT_WRITABLE_MASK;
+}
+
+static int is_io_pte(unsigned long pte)
+{
+       return pte & PT_SHADOW_IO_MARK;
+}
+
+static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa)
+{
+       struct kvm_mmu_page *page_head = page_header(page_hpa);
+
+       list_del(&page_head->link);
+       page_head->page_hpa = page_hpa;
+       list_add(&page_head->link, &vcpu->free_pages);
+}
+
+static int is_empty_shadow_page(hpa_t page_hpa)
+{
+       u32 *pos;
+       u32 *end;
+       for (pos = __va(page_hpa), end = pos + PAGE_SIZE / sizeof(u32);
+                     pos != end; pos++)
+               if (*pos != 0)
+                       return 0;
+       return 1;
+}
+
+static hpa_t kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, u64 *parent_pte)
+{
+       struct kvm_mmu_page *page;
+
+       if (list_empty(&vcpu->free_pages))
+               return INVALID_PAGE;
+
+       page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link);
+       list_del(&page->link);
+       list_add(&page->link, &vcpu->kvm->active_mmu_pages);
+       ASSERT(is_empty_shadow_page(page->page_hpa));
+       page->slot_bitmap = 0;
+       page->global = 1;
+       page->parent_pte = parent_pte;
+       return page->page_hpa;
+}
+
+static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa)
+{
+       int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT));
+       struct kvm_mmu_page *page_head = page_header(__pa(pte));
+
+       __set_bit(slot, &page_head->slot_bitmap);
+}
+
+hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+       hpa_t hpa = gpa_to_hpa(vcpu, gpa);
+
+       return is_error_hpa(hpa) ? bad_page_address | (gpa & ~PAGE_MASK): hpa;
+}
+
+hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+       struct kvm_memory_slot *slot;
+       struct page *page;
+
+       ASSERT((gpa & HPA_ERR_MASK) == 0);
+       slot = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
+       if (!slot)
+               return gpa | HPA_ERR_MASK;
+       page = gfn_to_page(slot, gpa >> PAGE_SHIFT);
+       return ((hpa_t)page_to_pfn(page) << PAGE_SHIFT)
+               | (gpa & (PAGE_SIZE-1));
+}
+
+hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva)
+{
+       gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
+
+       if (gpa == UNMAPPED_GVA)
+               return UNMAPPED_GVA;
+       return gpa_to_hpa(vcpu, gpa);
+}
+
+
+static void release_pt_page_64(struct kvm_vcpu *vcpu, hpa_t page_hpa,
+                              int level)
+{
+       ASSERT(vcpu);
+       ASSERT(VALID_PAGE(page_hpa));
+       ASSERT(level <= PT64_ROOT_LEVEL && level > 0);
+
+       if (level == 1)
+               memset(__va(page_hpa), 0, PAGE_SIZE);
+       else {
+               u64 *pos;
+               u64 *end;
+
+               for (pos = __va(page_hpa), end = pos + PT64_ENT_PER_PAGE;
+                    pos != end; pos++) {
+                       u64 current_ent = *pos;
+
+                       *pos = 0;
+                       if (is_present_pte(current_ent))
+                               release_pt_page_64(vcpu,
+                                                 current_ent &
+                                                 PT64_BASE_ADDR_MASK,
+                                                 level - 1);
+               }
+       }
+       kvm_mmu_free_page(vcpu, page_hpa);
+}
+
+static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
+{
+}
+
+static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p)
+{
+       int level = PT32E_ROOT_LEVEL;
+       hpa_t table_addr = vcpu->mmu.root_hpa;
+
+       for (; ; level--) {
+               u32 index = PT64_INDEX(v, level);
+               u64 *table;
+
+               ASSERT(VALID_PAGE(table_addr));
+               table = __va(table_addr);
+
+               if (level == 1) {
+                       mark_page_dirty(vcpu->kvm, v >> PAGE_SHIFT);
+                       page_header_update_slot(vcpu->kvm, table, v);
+                       table[index] = p | PT_PRESENT_MASK | PT_WRITABLE_MASK |
+                                                               PT_USER_MASK;
+                       return 0;
+               }
+
+               if (table[index] == 0) {
+                       hpa_t new_table = kvm_mmu_alloc_page(vcpu,
+                                                            &table[index]);
+
+                       if (!VALID_PAGE(new_table)) {
+                               pgprintk("nonpaging_map: ENOMEM\n");
+                               return -ENOMEM;
+                       }
+
+                       if (level == PT32E_ROOT_LEVEL)
+                               table[index] = new_table | PT_PRESENT_MASK;
+                       else
+                               table[index] = new_table | PT_PRESENT_MASK |
+                                               PT_WRITABLE_MASK | PT_USER_MASK;
+               }
+               table_addr = table[index] & PT64_BASE_ADDR_MASK;
+       }
+}
+
+static void nonpaging_flush(struct kvm_vcpu *vcpu)
+{
+       hpa_t root = vcpu->mmu.root_hpa;
+
+       ++kvm_stat.tlb_flush;
+       pgprintk("nonpaging_flush\n");
+       ASSERT(VALID_PAGE(root));
+       release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level);
+       root = kvm_mmu_alloc_page(vcpu, NULL);
+       ASSERT(VALID_PAGE(root));
+       vcpu->mmu.root_hpa = root;
+       if (is_paging(vcpu))
+               root |= (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK));
+       kvm_arch_ops->set_cr3(vcpu, root);
+       kvm_arch_ops->tlb_flush(vcpu);
+}
+
+static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
+{
+       return vaddr;
+}
+
+static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+                              u32 error_code)
+{
+       int ret;
+       gpa_t addr = gva;
+
+       ASSERT(vcpu);
+       ASSERT(VALID_PAGE(vcpu->mmu.root_hpa));
+
+       for (;;) {
+            hpa_t paddr;
+
+            paddr = gpa_to_hpa(vcpu , addr & PT64_BASE_ADDR_MASK);
+
+            if (is_error_hpa(paddr))
+                    return 1;
+
+            ret = nonpaging_map(vcpu, addr & PAGE_MASK, paddr);
+            if (ret) {
+                    nonpaging_flush(vcpu);
+                    continue;
+            }
+            break;
+       }
+       return ret;
+}
+
+static void nonpaging_inval_page(struct kvm_vcpu *vcpu, gva_t addr)
+{
+}
+
+static void nonpaging_free(struct kvm_vcpu *vcpu)
+{
+       hpa_t root;
+
+       ASSERT(vcpu);
+       root = vcpu->mmu.root_hpa;
+       if (VALID_PAGE(root))
+               release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level);
+       vcpu->mmu.root_hpa = INVALID_PAGE;
+}
+
+static int nonpaging_init_context(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmu *context = &vcpu->mmu;
+
+       context->new_cr3 = nonpaging_new_cr3;
+       context->page_fault = nonpaging_page_fault;
+       context->inval_page = nonpaging_inval_page;
+       context->gva_to_gpa = nonpaging_gva_to_gpa;
+       context->free = nonpaging_free;
+       context->root_level = PT32E_ROOT_LEVEL;
+       context->shadow_root_level = PT32E_ROOT_LEVEL;
+       context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL);
+       ASSERT(VALID_PAGE(context->root_hpa));
+       kvm_arch_ops->set_cr3(vcpu, context->root_hpa);
+       return 0;
+}
+
+
+static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmu_page *page, *npage;
+
+       list_for_each_entry_safe(page, npage, &vcpu->kvm->active_mmu_pages,
+                                link) {
+               if (page->global)
+                       continue;
+
+               if (!page->parent_pte)
+                       continue;
+
+               *page->parent_pte = 0;
+               release_pt_page_64(vcpu, page->page_hpa, 1);
+       }
+       ++kvm_stat.tlb_flush;
+       kvm_arch_ops->tlb_flush(vcpu);
+}
+
+static void paging_new_cr3(struct kvm_vcpu *vcpu)
+{
+       kvm_mmu_flush_tlb(vcpu);
+}
+
+static void mark_pagetable_nonglobal(void *shadow_pte)
+{
+       page_header(__pa(shadow_pte))->global = 0;
+}
+
+static inline void set_pte_common(struct kvm_vcpu *vcpu,
+                            u64 *shadow_pte,
+                            gpa_t gaddr,
+                            int dirty,
+                            u64 access_bits)
+{
+       hpa_t paddr;
+
+       *shadow_pte |= access_bits << PT_SHADOW_BITS_OFFSET;
+       if (!dirty)
+               access_bits &= ~PT_WRITABLE_MASK;
+
+       if (access_bits & PT_WRITABLE_MASK)
+               mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT);
+
+       *shadow_pte |= access_bits;
+
+       paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK);
+
+       if (!(*shadow_pte & PT_GLOBAL_MASK))
+               mark_pagetable_nonglobal(shadow_pte);
+
+       if (is_error_hpa(paddr)) {
+               *shadow_pte |= gaddr;
+               *shadow_pte |= PT_SHADOW_IO_MARK;
+               *shadow_pte &= ~PT_PRESENT_MASK;
+       } else {
+               *shadow_pte |= paddr;
+               page_header_update_slot(vcpu->kvm, shadow_pte, gaddr);
+       }
+}
+
+static void inject_page_fault(struct kvm_vcpu *vcpu,
+                             u64 addr,
+                             u32 err_code)
+{
+       kvm_arch_ops->inject_page_fault(vcpu, addr, err_code);
+}
+
+static inline int fix_read_pf(u64 *shadow_ent)
+{
+       if ((*shadow_ent & PT_SHADOW_USER_MASK) &&
+           !(*shadow_ent & PT_USER_MASK)) {
+               /*
+                * If supervisor write protect is disabled, we shadow kernel
+                * pages as user pages so we can trap the write access.
+                */
+               *shadow_ent |= PT_USER_MASK;
+               *shadow_ent &= ~PT_WRITABLE_MASK;
+
+               return 1;
+
+       }
+       return 0;
+}
+
+static int may_access(u64 pte, int write, int user)
+{
+
+       if (user && !(pte & PT_USER_MASK))
+               return 0;
+       if (write && !(pte & PT_WRITABLE_MASK))
+               return 0;
+       return 1;
+}
+
+/*
+ * Remove a shadow pte.
+ */
+static void paging_inval_page(struct kvm_vcpu *vcpu, gva_t addr)
+{
+       hpa_t page_addr = vcpu->mmu.root_hpa;
+       int level = vcpu->mmu.shadow_root_level;
+
+       ++kvm_stat.invlpg;
+
+       for (; ; level--) {
+               u32 index = PT64_INDEX(addr, level);
+               u64 *table = __va(page_addr);
+
+               if (level == PT_PAGE_TABLE_LEVEL ) {
+                       table[index] = 0;
+                       return;
+               }
+
+               if (!is_present_pte(table[index]))
+                       return;
+
+               page_addr = table[index] & PT64_BASE_ADDR_MASK;
+
+               if (level == PT_DIRECTORY_LEVEL &&
+                         (table[index] & PT_SHADOW_PS_MARK)) {
+                       table[index] = 0;
+                       release_pt_page_64(vcpu, page_addr, PT_PAGE_TABLE_LEVEL);
+
+                       kvm_arch_ops->tlb_flush(vcpu);
+                       return;
+               }
+       }
+}
+
+static void paging_free(struct kvm_vcpu *vcpu)
+{
+       nonpaging_free(vcpu);
+}
+
+#define PTTYPE 64
+#include "paging_tmpl.h"
+#undef PTTYPE
+
+#define PTTYPE 32
+#include "paging_tmpl.h"
+#undef PTTYPE
+
+static int paging64_init_context(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmu *context = &vcpu->mmu;
+
+       ASSERT(is_pae(vcpu));
+       context->new_cr3 = paging_new_cr3;
+       context->page_fault = paging64_page_fault;
+       context->inval_page = paging_inval_page;
+       context->gva_to_gpa = paging64_gva_to_gpa;
+       context->free = paging_free;
+       context->root_level = PT64_ROOT_LEVEL;
+       context->shadow_root_level = PT64_ROOT_LEVEL;
+       context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL);
+       ASSERT(VALID_PAGE(context->root_hpa));
+       kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
+                   (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+       return 0;
+}
+
+static int paging32_init_context(struct kvm_vcpu *vcpu)
+{
+       struct kvm_mmu *context = &vcpu->mmu;
+
+       context->new_cr3 = paging_new_cr3;
+       context->page_fault = paging32_page_fault;
+       context->inval_page = paging_inval_page;
+       context->gva_to_gpa = paging32_gva_to_gpa;
+       context->free = paging_free;
+       context->root_level = PT32_ROOT_LEVEL;
+       context->shadow_root_level = PT32E_ROOT_LEVEL;
+       context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL);
+       ASSERT(VALID_PAGE(context->root_hpa));
+       kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
+                   (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+       return 0;
+}
+
+static int paging32E_init_context(struct kvm_vcpu *vcpu)
+{
+       int ret;
+
+       if ((ret = paging64_init_context(vcpu)))
+               return ret;
+
+       vcpu->mmu.root_level = PT32E_ROOT_LEVEL;
+       vcpu->mmu.shadow_root_level = PT32E_ROOT_LEVEL;
+       return 0;
+}
+
+static int init_kvm_mmu(struct kvm_vcpu *vcpu)
+{
+       ASSERT(vcpu);
+       ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
+
+       if (!is_paging(vcpu))
+               return nonpaging_init_context(vcpu);
+       else if (kvm_arch_ops->is_long_mode(vcpu))
+               return paging64_init_context(vcpu);
+       else if (is_pae(vcpu))
+               return paging32E_init_context(vcpu);
+       else
+               return paging32_init_context(vcpu);
+}
+
+static void destroy_kvm_mmu(struct kvm_vcpu *vcpu)
+{
+       ASSERT(vcpu);
+       if (VALID_PAGE(vcpu->mmu.root_hpa)) {
+               vcpu->mmu.free(vcpu);
+               vcpu->mmu.root_hpa = INVALID_PAGE;
+       }
+}
+
+int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
+{
+       destroy_kvm_mmu(vcpu);
+       return init_kvm_mmu(vcpu);
+}
+
+static void free_mmu_pages(struct kvm_vcpu *vcpu)
+{
+       while (!list_empty(&vcpu->free_pages)) {
+               struct kvm_mmu_page *page;
+
+               page = list_entry(vcpu->free_pages.next,
+                                 struct kvm_mmu_page, link);
+               list_del(&page->link);
+               __free_page(pfn_to_page(page->page_hpa >> PAGE_SHIFT));
+               page->page_hpa = INVALID_PAGE;
+       }
+}
+
+static int alloc_mmu_pages(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       ASSERT(vcpu);
+
+       for (i = 0; i < KVM_NUM_MMU_PAGES; i++) {
+               struct page *page;
+               struct kvm_mmu_page *page_header = &vcpu->page_header_buf[i];
+
+               INIT_LIST_HEAD(&page_header->link);
+               if ((page = alloc_page(GFP_KVM_MMU)) == NULL)
+                       goto error_1;
+               page->private = (unsigned long)page_header;
+               page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT;
+               memset(__va(page_header->page_hpa), 0, PAGE_SIZE);
+               list_add(&page_header->link, &vcpu->free_pages);
+       }
+       return 0;
+
+error_1:
+       free_mmu_pages(vcpu);
+       return -ENOMEM;
+}
+
+int kvm_mmu_init(struct kvm_vcpu *vcpu)
+{
+       int r;
+
+       ASSERT(vcpu);
+       ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
+       ASSERT(list_empty(&vcpu->free_pages));
+
+       if ((r = alloc_mmu_pages(vcpu)))
+               return r;
+
+       if ((r = init_kvm_mmu(vcpu))) {
+               free_mmu_pages(vcpu);
+               return r;
+       }
+       return 0;
+}
+
+void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
+{
+       ASSERT(vcpu);
+
+       destroy_kvm_mmu(vcpu);
+       free_mmu_pages(vcpu);
+}
+
+void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
+{
+       struct kvm_mmu_page *page;
+
+       list_for_each_entry(page, &kvm->active_mmu_pages, link) {
+               int i;
+               u64 *pt;
+
+               if (!test_bit(slot, &page->slot_bitmap))
+                       continue;
+
+               pt = __va(page->page_hpa);
+               for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+                       /* avoid RMW */
+                       if (pt[i] & PT_WRITABLE_MASK)
+                               pt[i] &= ~PT_WRITABLE_MASK;
+
+       }
+}
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
new file mode 100644 (file)
index 0000000..765c2e1
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * MMU support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Avi Kivity   <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+/*
+ * We need the mmu code to access both 32-bit and 64-bit guest ptes,
+ * so the code in this file is compiled twice, once per pte size.
+ */
+
+#if PTTYPE == 64
+       #define pt_element_t u64
+       #define guest_walker guest_walker64
+       #define FNAME(name) paging##64_##name
+       #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK
+       #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK
+       #define PT_INDEX(addr, level) PT64_INDEX(addr, level)
+       #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
+       #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
+       #define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
+       #define PT_NON_PTE_COPY_MASK PT64_NON_PTE_COPY_MASK
+#elif PTTYPE == 32
+       #define pt_element_t u32
+       #define guest_walker guest_walker32
+       #define FNAME(name) paging##32_##name
+       #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK
+       #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK
+       #define PT_INDEX(addr, level) PT32_INDEX(addr, level)
+       #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
+       #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
+       #define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
+       #define PT_NON_PTE_COPY_MASK PT32_NON_PTE_COPY_MASK
+#else
+       #error Invalid PTTYPE value
+#endif
+
+/*
+ * The guest_walker structure emulates the behavior of the hardware page
+ * table walker.
+ */
+struct guest_walker {
+       int level;
+       pt_element_t *table;
+       pt_element_t inherited_ar;
+};
+
+static void FNAME(init_walker)(struct guest_walker *walker,
+                              struct kvm_vcpu *vcpu)
+{
+       hpa_t hpa;
+       struct kvm_memory_slot *slot;
+
+       walker->level = vcpu->mmu.root_level;
+       slot = gfn_to_memslot(vcpu->kvm,
+                             (vcpu->cr3 & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+       hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK);
+       walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0);
+
+       ASSERT((!kvm_arch_ops->is_long_mode(vcpu) && is_pae(vcpu)) ||
+              (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0);
+
+       walker->table = (pt_element_t *)( (unsigned long)walker->table |
+               (unsigned long)(vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) );
+       walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK;
+}
+
+static void FNAME(release_walker)(struct guest_walker *walker)
+{
+       kunmap_atomic(walker->table, KM_USER0);
+}
+
+static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
+                          u64 *shadow_pte, u64 access_bits)
+{
+       ASSERT(*shadow_pte == 0);
+       access_bits &= guest_pte;
+       *shadow_pte = (guest_pte & PT_PTE_COPY_MASK);
+       set_pte_common(vcpu, shadow_pte, guest_pte & PT_BASE_ADDR_MASK,
+                      guest_pte & PT_DIRTY_MASK, access_bits);
+}
+
+static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde,
+                          u64 *shadow_pte, u64 access_bits,
+                          int index)
+{
+       gpa_t gaddr;
+
+       ASSERT(*shadow_pte == 0);
+       access_bits &= guest_pde;
+       gaddr = (guest_pde & PT_DIR_BASE_ADDR_MASK) + PAGE_SIZE * index;
+       if (PTTYPE == 32 && is_cpuid_PSE36())
+               gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
+                       (32 - PT32_DIR_PSE36_SHIFT);
+       *shadow_pte = (guest_pde & (PT_NON_PTE_COPY_MASK | PT_GLOBAL_MASK)) |
+                         ((guest_pde & PT_DIR_PAT_MASK) >>
+                                   (PT_DIR_PAT_SHIFT - PT_PAT_SHIFT));
+       set_pte_common(vcpu, shadow_pte, gaddr,
+                      guest_pde & PT_DIRTY_MASK, access_bits);
+}
+
+/*
+ * Fetch a guest pte from a specific level in the paging hierarchy.
+ */
+static pt_element_t *FNAME(fetch_guest)(struct kvm_vcpu *vcpu,
+                                       struct guest_walker *walker,
+                                       int level,
+                                       gva_t addr)
+{
+
+       ASSERT(level > 0  && level <= walker->level);
+
+       for (;;) {
+               int index = PT_INDEX(addr, walker->level);
+               hpa_t paddr;
+
+               ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
+                      ((unsigned long)&walker->table[index] & PAGE_MASK));
+               if (level == walker->level ||
+                   !is_present_pte(walker->table[index]) ||
+                   (walker->level == PT_DIRECTORY_LEVEL &&
+                    (walker->table[index] & PT_PAGE_SIZE_MASK) &&
+                    (PTTYPE == 64 || is_pse(vcpu))))
+                       return &walker->table[index];
+               if (walker->level != 3 || kvm_arch_ops->is_long_mode(vcpu))
+                       walker->inherited_ar &= walker->table[index];
+               paddr = safe_gpa_to_hpa(vcpu, walker->table[index] & PT_BASE_ADDR_MASK);
+               kunmap_atomic(walker->table, KM_USER0);
+               walker->table = kmap_atomic(pfn_to_page(paddr >> PAGE_SHIFT),
+                                           KM_USER0);
+               --walker->level;
+       }
+}
+
+/*
+ * Fetch a shadow pte for a specific level in the paging hierarchy.
+ */
+static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+                             struct guest_walker *walker)
+{
+       hpa_t shadow_addr;
+       int level;
+       u64 *prev_shadow_ent = NULL;
+
+       shadow_addr = vcpu->mmu.root_hpa;
+       level = vcpu->mmu.shadow_root_level;
+
+       for (; ; level--) {
+               u32 index = SHADOW_PT_INDEX(addr, level);
+               u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
+               pt_element_t *guest_ent;
+
+               if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
+                       if (level == PT_PAGE_TABLE_LEVEL)
+                               return shadow_ent;
+                       shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
+                       prev_shadow_ent = shadow_ent;
+                       continue;
+               }
+
+               if (PTTYPE == 32 && level > PT32_ROOT_LEVEL) {
+                       ASSERT(level == PT32E_ROOT_LEVEL);
+                       guest_ent = FNAME(fetch_guest)(vcpu, walker,
+                                                      PT32_ROOT_LEVEL, addr);
+               } else
+                       guest_ent = FNAME(fetch_guest)(vcpu, walker,
+                                                      level, addr);
+
+               if (!is_present_pte(*guest_ent))
+                       return NULL;
+
+               /* Don't set accessed bit on PAE PDPTRs */
+               if (vcpu->mmu.root_level != 3 || walker->level != 3)
+                       *guest_ent |= PT_ACCESSED_MASK;
+
+               if (level == PT_PAGE_TABLE_LEVEL) {
+
+                       if (walker->level == PT_DIRECTORY_LEVEL) {
+                               if (prev_shadow_ent)
+                                       *prev_shadow_ent |= PT_SHADOW_PS_MARK;
+                               FNAME(set_pde)(vcpu, *guest_ent, shadow_ent,
+                                              walker->inherited_ar,
+                                         PT_INDEX(addr, PT_PAGE_TABLE_LEVEL));
+                       } else {
+                               ASSERT(walker->level == PT_PAGE_TABLE_LEVEL);
+                               FNAME(set_pte)(vcpu, *guest_ent, shadow_ent, walker->inherited_ar);
+                       }
+                       return shadow_ent;
+               }
+
+               shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent);
+               if (!VALID_PAGE(shadow_addr))
+                       return ERR_PTR(-ENOMEM);
+               if (!kvm_arch_ops->is_long_mode(vcpu) && level == 3)
+                       *shadow_ent = shadow_addr |
+                               (*guest_ent & (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK));
+               else {
+                       *shadow_ent = shadow_addr |
+                               (*guest_ent & PT_NON_PTE_COPY_MASK);
+                       *shadow_ent |= (PT_WRITABLE_MASK | PT_USER_MASK);
+               }
+               prev_shadow_ent = shadow_ent;
+       }
+}
+
+/*
+ * The guest faulted for write.  We need to
+ *
+ * - check write permissions
+ * - update the guest pte dirty bit
+ * - update our own dirty page tracking structures
+ */
+static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
+                              u64 *shadow_ent,
+                              struct guest_walker *walker,
+                              gva_t addr,
+                              int user)
+{
+       pt_element_t *guest_ent;
+       int writable_shadow;
+       gfn_t gfn;
+
+       if (is_writeble_pte(*shadow_ent))
+               return 0;
+
+       writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK;
+       if (user) {
+               /*
+                * User mode access.  Fail if it's a kernel page or a read-only
+                * page.
+                */
+               if (!(*shadow_ent & PT_SHADOW_USER_MASK) || !writable_shadow)
+                       return 0;
+               ASSERT(*shadow_ent & PT_USER_MASK);
+       } else
+               /*
+                * Kernel mode access.  Fail if it's a read-only page and
+                * supervisor write protection is enabled.
+                */
+               if (!writable_shadow) {
+                       if (is_write_protection(vcpu))
+                               return 0;
+                       *shadow_ent &= ~PT_USER_MASK;
+               }
+
+       guest_ent = FNAME(fetch_guest)(vcpu, walker, PT_PAGE_TABLE_LEVEL, addr);
+
+       if (!is_present_pte(*guest_ent)) {
+               *shadow_ent = 0;
+               return 0;
+       }
+
+       gfn = (*guest_ent & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+       mark_page_dirty(vcpu->kvm, gfn);
+       *shadow_ent |= PT_WRITABLE_MASK;
+       *guest_ent |= PT_DIRTY_MASK;
+
+       return 1;
+}
+
+/*
+ * Page fault handler.  There are several causes for a page fault:
+ *   - there is no shadow pte for the guest pte
+ *   - write access through a shadow pte marked read only so that we can set
+ *     the dirty bit
+ *   - write access to a shadow pte marked read only so we can update the page
+ *     dirty bitmap, when userspace requests it
+ *   - mmio access; in this case we will never install a present shadow pte
+ *   - normal guest page fault due to the guest pte marked not present, not
+ *     writable, or not executable
+ *
+ *  Returns: 1 if we need to emulate the instruction, 0 otherwise
+ */
+static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
+                              u32 error_code)
+{
+       int write_fault = error_code & PFERR_WRITE_MASK;
+       int pte_present = error_code & PFERR_PRESENT_MASK;
+       int user_fault = error_code & PFERR_USER_MASK;
+       struct guest_walker walker;
+       u64 *shadow_pte;
+       int fixed;
+
+       /*
+        * Look up the shadow pte for the faulting address.
+        */
+       for (;;) {
+               FNAME(init_walker)(&walker, vcpu);
+               shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
+               if (IS_ERR(shadow_pte)) {  /* must be -ENOMEM */
+                       nonpaging_flush(vcpu);
+                       FNAME(release_walker)(&walker);
+                       continue;
+               }
+               break;
+       }
+
+       /*
+        * The page is not mapped by the guest.  Let the guest handle it.
+        */
+       if (!shadow_pte) {
+               inject_page_fault(vcpu, addr, error_code);
+               FNAME(release_walker)(&walker);
+               return 0;
+       }
+
+       /*
+        * Update the shadow pte.
+        */
+       if (write_fault)
+               fixed = FNAME(fix_write_pf)(vcpu, shadow_pte, &walker, addr,
+                                           user_fault);
+       else
+               fixed = fix_read_pf(shadow_pte);
+
+       FNAME(release_walker)(&walker);
+
+       /*
+        * mmio: emulate if accessible, otherwise its a guest fault.
+        */
+       if (is_io_pte(*shadow_pte)) {
+               if (may_access(*shadow_pte, write_fault, user_fault))
+                       return 1;
+               pgprintk("%s: io work, no access\n", __FUNCTION__);
+               inject_page_fault(vcpu, addr,
+                                 error_code | PFERR_PRESENT_MASK);
+               return 0;
+       }
+
+       /*
+        * pte not present, guest page fault.
+        */
+       if (pte_present && !fixed) {
+               inject_page_fault(vcpu, addr, error_code);
+               return 0;
+       }
+
+       ++kvm_stat.pf_fixed;
+
+       return 0;
+}
+
+static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
+{
+       struct guest_walker walker;
+       pt_element_t guest_pte;
+       gpa_t gpa;
+
+       FNAME(init_walker)(&walker, vcpu);
+       guest_pte = *FNAME(fetch_guest)(vcpu, &walker, PT_PAGE_TABLE_LEVEL,
+                                       vaddr);
+       FNAME(release_walker)(&walker);
+
+       if (!is_present_pte(guest_pte))
+               return UNMAPPED_GVA;
+
+       if (walker.level == PT_DIRECTORY_LEVEL) {
+               ASSERT((guest_pte & PT_PAGE_SIZE_MASK));
+               ASSERT(PTTYPE == 64 || is_pse(vcpu));
+
+               gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr &
+                       (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK));
+
+               if (PTTYPE == 32 && is_cpuid_PSE36())
+                       gpa |= (guest_pte & PT32_DIR_PSE36_MASK) <<
+                                       (32 - PT32_DIR_PSE36_SHIFT);
+       } else {
+               gpa = (guest_pte & PT_BASE_ADDR_MASK);
+               gpa |= (vaddr & ~PAGE_MASK);
+       }
+
+       return gpa;
+}
+
+#undef pt_element_t
+#undef guest_walker
+#undef FNAME
+#undef PT_BASE_ADDR_MASK
+#undef PT_INDEX
+#undef SHADOW_PT_INDEX
+#undef PT_LEVEL_MASK
+#undef PT_PTE_COPY_MASK
+#undef PT_NON_PTE_COPY_MASK
+#undef PT_DIR_BASE_ADDR_MASK
diff --git a/drivers/kvm/segment_descriptor.h b/drivers/kvm/segment_descriptor.h
new file mode 100644 (file)
index 0000000..71fdf45
--- /dev/null
@@ -0,0 +1,17 @@
+struct segment_descriptor {
+       u16 limit_low;
+       u16 base_low;
+       u8  base_mid;
+       u8  type : 4;
+       u8  system : 1;
+       u8  dpl : 2;
+       u8  present : 1;
+       u8  limit_high : 4;
+       u8  avl : 1;
+       u8  long_mode : 1;
+       u8  default_op : 1;
+       u8  granularity : 1;
+       u8  base_high;
+} __attribute__((packed));
+
+
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
new file mode 100644 (file)
index 0000000..a33a89c
--- /dev/null
@@ -0,0 +1,1677 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * AMD SVM support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Avi Kivity   <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+#include <asm/desc.h>
+
+#include "kvm_svm.h"
+#include "x86_emulate.h"
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+#define IOPM_ALLOC_ORDER 2
+#define MSRPM_ALLOC_ORDER 1
+
+#define DB_VECTOR 1
+#define UD_VECTOR 6
+#define GP_VECTOR 13
+
+#define DR7_GD_MASK (1 << 13)
+#define DR6_BD_MASK (1 << 13)
+#define CR4_DE_MASK (1UL << 3)
+
+#define SEG_TYPE_LDT 2
+#define SEG_TYPE_BUSY_TSS16 3
+
+#define KVM_EFER_LMA (1 << 10)
+#define KVM_EFER_LME (1 << 8)
+
+unsigned long iopm_base;
+unsigned long msrpm_base;
+
+struct kvm_ldttss_desc {
+       u16 limit0;
+       u16 base0;
+       unsigned base1 : 8, type : 5, dpl : 2, p : 1;
+       unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
+       u32 base3;
+       u32 zero1;
+} __attribute__((packed));
+
+struct svm_cpu_data {
+       int cpu;
+
+       uint64_t asid_generation;
+       uint32_t max_asid;
+       uint32_t next_asid;
+       struct kvm_ldttss_desc *tss_desc;
+
+       struct page *save_area;
+};
+
+static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
+
+struct svm_init_data {
+       int cpu;
+       int r;
+};
+
+static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
+
+#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges))
+#define MSRS_RANGE_SIZE 2048
+#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
+
+#define MAX_INST_SIZE 15
+
+static unsigned get_addr_size(struct kvm_vcpu *vcpu)
+{
+       struct vmcb_save_area *sa = &vcpu->svm->vmcb->save;
+       u16 cs_attrib;
+
+       if (!(sa->cr0 & CR0_PE_MASK) || (sa->rflags & X86_EFLAGS_VM))
+               return 2;
+
+       cs_attrib = sa->cs.attrib;
+
+       return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 :
+                               (cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2;
+}
+
+static inline u8 pop_irq(struct kvm_vcpu *vcpu)
+{
+       int word_index = __ffs(vcpu->irq_summary);
+       int bit_index = __ffs(vcpu->irq_pending[word_index]);
+       int irq = word_index * BITS_PER_LONG + bit_index;
+
+       clear_bit(bit_index, &vcpu->irq_pending[word_index]);
+       if (!vcpu->irq_pending[word_index])
+               clear_bit(word_index, &vcpu->irq_summary);
+       return irq;
+}
+
+static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq)
+{
+       set_bit(irq, vcpu->irq_pending);
+       set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
+}
+
+static inline void clgi(void)
+{
+       asm volatile (SVM_CLGI);
+}
+
+static inline void stgi(void)
+{
+       asm volatile (SVM_STGI);
+}
+
+static inline void invlpga(unsigned long addr, u32 asid)
+{
+       asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid));
+}
+
+static inline unsigned long kvm_read_cr2(void)
+{
+       unsigned long cr2;
+
+       asm volatile ("mov %%cr2, %0" : "=r" (cr2));
+       return cr2;
+}
+
+static inline void kvm_write_cr2(unsigned long val)
+{
+       asm volatile ("mov %0, %%cr2" :: "r" (val));
+}
+
+static inline unsigned long read_dr6(void)
+{
+       unsigned long dr6;
+
+       asm volatile ("mov %%dr6, %0" : "=r" (dr6));
+       return dr6;
+}
+
+static inline void write_dr6(unsigned long val)
+{
+       asm volatile ("mov %0, %%dr6" :: "r" (val));
+}
+
+static inline unsigned long read_dr7(void)
+{
+       unsigned long dr7;
+
+       asm volatile ("mov %%dr7, %0" : "=r" (dr7));
+       return dr7;
+}
+
+static inline void write_dr7(unsigned long val)
+{
+       asm volatile ("mov %0, %%dr7" :: "r" (val));
+}
+
+static inline int svm_is_long_mode(struct kvm_vcpu *vcpu)
+{
+       return vcpu->svm->vmcb->save.efer & KVM_EFER_LMA;
+}
+
+static inline void force_new_asid(struct kvm_vcpu *vcpu)
+{
+       vcpu->svm->asid_generation--;
+}
+
+static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
+{
+       force_new_asid(vcpu);
+}
+
+static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+       if (!(efer & KVM_EFER_LMA))
+               efer &= ~KVM_EFER_LME;
+
+       vcpu->svm->vmcb->save.efer = efer | MSR_EFER_SVME_MASK;
+       vcpu->shadow_efer = efer;
+}
+
+static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
+{
+       vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
+                                               SVM_EVTINJ_VALID_ERR |
+                                               SVM_EVTINJ_TYPE_EXEPT |
+                                               GP_VECTOR;
+       vcpu->svm->vmcb->control.event_inj_err = error_code;
+}
+
+static void inject_ud(struct kvm_vcpu *vcpu)
+{
+       vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
+                                               SVM_EVTINJ_TYPE_EXEPT |
+                                               UD_VECTOR;
+}
+
+static void inject_db(struct kvm_vcpu *vcpu)
+{
+       vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
+                                               SVM_EVTINJ_TYPE_EXEPT |
+                                               DB_VECTOR;
+}
+
+static int is_page_fault(uint32_t info)
+{
+       info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
+       return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT);
+}
+
+static int is_external_interrupt(u32 info)
+{
+       info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
+       return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
+}
+
+static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       if (!vcpu->svm->next_rip) {
+               printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__);
+               return;
+       }
+       if (vcpu->svm->next_rip - vcpu->svm->vmcb->save.rip > 15) {
+               printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n",
+                      __FUNCTION__,
+                      vcpu->svm->vmcb->save.rip,
+                      vcpu->svm->next_rip);
+       }
+
+       vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip;
+       vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+}
+
+static int has_svm(void)
+{
+       uint32_t eax, ebx, ecx, edx;
+
+       if (current_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+               printk(KERN_INFO "has_svm: not amd\n");
+               return 0;
+       }
+
+       cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
+       if (eax < SVM_CPUID_FUNC) {
+               printk(KERN_INFO "has_svm: can't execute cpuid_8000000a\n");
+               return 0;
+       }
+
+       cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
+       if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) {
+               printk(KERN_DEBUG "has_svm: svm not available\n");
+               return 0;
+       }
+       return 1;
+}
+
+static void svm_hardware_disable(void *garbage)
+{
+       struct svm_cpu_data *svm_data
+               = per_cpu(svm_data, raw_smp_processor_id());
+
+       if (svm_data) {
+               uint64_t efer;
+
+               wrmsrl(MSR_VM_HSAVE_PA, 0);
+               rdmsrl(MSR_EFER, efer);
+               wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
+               per_cpu(svm_data, raw_smp_processor_id()) = 0;
+               __free_page(svm_data->save_area);
+               kfree(svm_data);
+       }
+}
+
+static void svm_hardware_enable(void *garbage)
+{
+
+       struct svm_cpu_data *svm_data;
+       uint64_t efer;
+#ifdef __x86_64__
+       struct desc_ptr gdt_descr;
+#else
+       struct Xgt_desc_struct gdt_descr;
+#endif
+       struct desc_struct *gdt;
+       int me = raw_smp_processor_id();
+
+       if (!has_svm()) {
+               printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me);
+               return;
+       }
+       svm_data = per_cpu(svm_data, me);
+
+       if (!svm_data) {
+               printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n",
+                      me);
+               return;
+       }
+
+       svm_data->asid_generation = 1;
+       svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
+       svm_data->next_asid = svm_data->max_asid + 1;
+
+       asm volatile ( "sgdt %0" : "=m"(gdt_descr) );
+       gdt = (struct desc_struct *)gdt_descr.address;
+       svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
+
+       rdmsrl(MSR_EFER, efer);
+       wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK);
+
+       wrmsrl(MSR_VM_HSAVE_PA,
+              page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
+}
+
+static int svm_cpu_init(int cpu)
+{
+       struct svm_cpu_data *svm_data;
+       int r;
+
+       svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
+       if (!svm_data)
+               return -ENOMEM;
+       svm_data->cpu = cpu;
+       svm_data->save_area = alloc_page(GFP_KERNEL);
+       r = -ENOMEM;
+       if (!svm_data->save_area)
+               goto err_1;
+
+       per_cpu(svm_data, cpu) = svm_data;
+
+       return 0;
+
+err_1:
+       kfree(svm_data);
+       return r;
+
+}
+
+static int set_msr_interception(u32 *msrpm, unsigned msr,
+                               int read, int write)
+{
+       int i;
+
+       for (i = 0; i < NUM_MSR_MAPS; i++) {
+               if (msr >= msrpm_ranges[i] &&
+                   msr < msrpm_ranges[i] + MSRS_IN_RANGE) {
+                       u32 msr_offset = (i * MSRS_IN_RANGE + msr -
+                                         msrpm_ranges[i]) * 2;
+
+                       u32 *base = msrpm + (msr_offset / 32);
+                       u32 msr_shift = msr_offset % 32;
+                       u32 mask = ((write) ? 0 : 2) | ((read) ? 0 : 1);
+                       *base = (*base & ~(0x3 << msr_shift)) |
+                               (mask << msr_shift);
+                       return 1;
+               }
+       }
+       printk(KERN_DEBUG "%s: not found 0x%x\n", __FUNCTION__, msr);
+       return 0;
+}
+
+static __init int svm_hardware_setup(void)
+{
+       int cpu;
+       struct page *iopm_pages;
+       struct page *msrpm_pages;
+       void *msrpm_va;
+       int r;
+
+
+       iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
+
+       if (!iopm_pages)
+               return -ENOMEM;
+       memset(page_address(iopm_pages), 0xff,
+                                       PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
+       iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
+
+
+       msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
+
+       r = -ENOMEM;
+       if (!msrpm_pages)
+               goto err_1;
+
+       msrpm_va = page_address(msrpm_pages);
+       memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
+       msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
+
+#ifdef __x86_64__
+       set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
+       set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
+       set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
+       set_msr_interception(msrpm_va, MSR_STAR, 1, 1);
+       set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1);
+       set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1);
+       set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1);
+#endif
+       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1);
+       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1);
+       set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1);
+
+       for_each_online_cpu(cpu) {
+               r = svm_cpu_init(cpu);
+               if (r)
+                       goto err_2;
+       }
+       return 0;
+
+err_2:
+       __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
+       msrpm_base = 0;
+err_1:
+       __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
+       iopm_base = 0;
+       return r;
+}
+
+static __exit void svm_hardware_unsetup(void)
+{
+       __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER);
+       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+       iopm_base = msrpm_base = 0;
+}
+
+static void init_seg(struct vmcb_seg *seg)
+{
+       seg->selector = 0;
+       seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK |
+               SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */
+       seg->limit = 0xffff;
+       seg->base = 0;
+}
+
+static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
+{
+       seg->selector = 0;
+       seg->attrib = SVM_SELECTOR_P_MASK | type;
+       seg->limit = 0xffff;
+       seg->base = 0;
+}
+
+static int svm_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+static void init_vmcb(struct vmcb *vmcb)
+{
+       struct vmcb_control_area *control = &vmcb->control;
+       struct vmcb_save_area *save = &vmcb->save;
+       u64 tsc;
+
+       control->intercept_cr_read =    INTERCEPT_CR0_MASK |
+                                       INTERCEPT_CR3_MASK |
+                                       INTERCEPT_CR4_MASK;
+
+       control->intercept_cr_write =   INTERCEPT_CR0_MASK |
+                                       INTERCEPT_CR3_MASK |
+                                       INTERCEPT_CR4_MASK;
+
+       control->intercept_dr_read =    INTERCEPT_DR0_MASK |
+                                       INTERCEPT_DR1_MASK |
+                                       INTERCEPT_DR2_MASK |
+                                       INTERCEPT_DR3_MASK;
+
+       control->intercept_dr_write =   INTERCEPT_DR0_MASK |
+                                       INTERCEPT_DR1_MASK |
+                                       INTERCEPT_DR2_MASK |
+                                       INTERCEPT_DR3_MASK |
+                                       INTERCEPT_DR5_MASK |
+                                       INTERCEPT_DR7_MASK;
+
+       control->intercept_exceptions = 1 << PF_VECTOR;
+
+
+       control->intercept =    (1ULL << INTERCEPT_INTR) |
+                               (1ULL << INTERCEPT_NMI) |
+               /*
+                * selective cr0 intercept bug?
+                *      0:   0f 22 d8                mov    %eax,%cr3
+                *      3:   0f 20 c0                mov    %cr0,%eax
+                *      6:   0d 00 00 00 80          or     $0x80000000,%eax
+                *      b:   0f 22 c0                mov    %eax,%cr0
+                * set cr3 ->interception
+                * get cr0 ->interception
+                * set cr0 -> no interception
+                */
+               /*              (1ULL << INTERCEPT_SELECTIVE_CR0) | */
+                               (1ULL << INTERCEPT_CPUID) |
+                               (1ULL << INTERCEPT_HLT) |
+                               (1ULL << INTERCEPT_INVLPG) |
+                               (1ULL << INTERCEPT_INVLPGA) |
+                               (1ULL << INTERCEPT_IOIO_PROT) |
+                               (1ULL << INTERCEPT_MSR_PROT) |
+                               (1ULL << INTERCEPT_TASK_SWITCH) |
+                               (1ULL << INTERCEPT_VMRUN) |
+                               (1ULL << INTERCEPT_VMMCALL) |
+                               (1ULL << INTERCEPT_VMLOAD) |
+                               (1ULL << INTERCEPT_VMSAVE) |
+                               (1ULL << INTERCEPT_STGI) |
+                               (1ULL << INTERCEPT_CLGI) |
+                               (1ULL << INTERCEPT_SKINIT);
+
+       control->iopm_base_pa = iopm_base;
+       control->msrpm_base_pa = msrpm_base;
+       rdtscll(tsc);
+       control->tsc_offset = -tsc;
+       control->int_ctl = V_INTR_MASKING_MASK;
+
+       init_seg(&save->es);
+       init_seg(&save->ss);
+       init_seg(&save->ds);
+       init_seg(&save->fs);
+       init_seg(&save->gs);
+
+       save->cs.selector = 0xf000;
+       /* Executable/Readable Code Segment */
+       save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
+               SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
+       save->cs.limit = 0xffff;
+       save->cs.base = 0xffff0000;
+
+       save->gdtr.limit = 0xffff;
+       save->idtr.limit = 0xffff;
+
+       init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
+       init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
+
+       save->efer = MSR_EFER_SVME_MASK;
+
+        save->dr6 = 0xffff0ff0;
+       save->dr7 = 0x400;
+       save->rflags = 2;
+       save->rip = 0x0000fff0;
+
+       /*
+        * cr0 val on cpu init should be 0x60000010, we enable cpu
+        * cache by default. the orderly way is to enable cache in bios.
+        */
+       save->cr0 = 0x00000010 | CR0_PG_MASK;
+       save->cr4 = CR4_PAE_MASK;
+       /* rdx = ?? */
+}
+
+static int svm_create_vcpu(struct kvm_vcpu *vcpu)
+{
+       struct page *page;
+       int r;
+
+       r = -ENOMEM;
+       vcpu->svm = kzalloc(sizeof *vcpu->svm, GFP_KERNEL);
+       if (!vcpu->svm)
+               goto out1;
+       page = alloc_page(GFP_KERNEL);
+       if (!page)
+               goto out2;
+
+       vcpu->svm->vmcb = page_address(page);
+       memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+       vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
+       vcpu->svm->cr0 = 0x00000010;
+       vcpu->svm->asid_generation = 0;
+       memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs));
+       init_vmcb(vcpu->svm->vmcb);
+
+       return 0;
+
+out2:
+       kfree(vcpu->svm);
+out1:
+       return r;
+}
+
+static void svm_free_vcpu(struct kvm_vcpu *vcpu)
+{
+       if (!vcpu->svm)
+               return;
+       if (vcpu->svm->vmcb)
+               __free_page(pfn_to_page(vcpu->svm->vmcb_pa >> PAGE_SHIFT));
+       kfree(vcpu->svm);
+}
+
+static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu)
+{
+       get_cpu();
+       return vcpu;
+}
+
+static void svm_vcpu_put(struct kvm_vcpu *vcpu)
+{
+       put_cpu();
+}
+
+static void svm_cache_regs(struct kvm_vcpu *vcpu)
+{
+       vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax;
+       vcpu->regs[VCPU_REGS_RSP] = vcpu->svm->vmcb->save.rsp;
+       vcpu->rip = vcpu->svm->vmcb->save.rip;
+}
+
+static void svm_decache_regs(struct kvm_vcpu *vcpu)
+{
+       vcpu->svm->vmcb->save.rax = vcpu->regs[VCPU_REGS_RAX];
+       vcpu->svm->vmcb->save.rsp = vcpu->regs[VCPU_REGS_RSP];
+       vcpu->svm->vmcb->save.rip = vcpu->rip;
+}
+
+static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
+{
+       return vcpu->svm->vmcb->save.rflags;
+}
+
+static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+       vcpu->svm->vmcb->save.rflags = rflags;
+}
+
+static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
+{
+       struct vmcb_save_area *save = &vcpu->svm->vmcb->save;
+
+       switch (seg) {
+       case VCPU_SREG_CS: return &save->cs;
+       case VCPU_SREG_DS: return &save->ds;
+       case VCPU_SREG_ES: return &save->es;
+       case VCPU_SREG_FS: return &save->fs;
+       case VCPU_SREG_GS: return &save->gs;
+       case VCPU_SREG_SS: return &save->ss;
+       case VCPU_SREG_TR: return &save->tr;
+       case VCPU_SREG_LDTR: return &save->ldtr;
+       }
+       BUG();
+       return 0;
+}
+
+static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+       struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+       return s->base;
+}
+
+static void svm_get_segment(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg)
+{
+       struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+       var->base = s->base;
+       var->limit = s->limit;
+       var->selector = s->selector;
+       var->type = s->attrib & SVM_SELECTOR_TYPE_MASK;
+       var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1;
+       var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
+       var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1;
+       var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
+       var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
+       var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
+       var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+       var->unusable = !var->present;
+}
+
+static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+{
+       struct vmcb_seg *s = svm_seg(vcpu, VCPU_SREG_CS);
+
+       *db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
+       *l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
+}
+
+static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       dt->limit = vcpu->svm->vmcb->save.ldtr.limit;
+       dt->base = vcpu->svm->vmcb->save.ldtr.base;
+}
+
+static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       vcpu->svm->vmcb->save.ldtr.limit = dt->limit;
+       vcpu->svm->vmcb->save.ldtr.base = dt->base ;
+}
+
+static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       dt->limit = vcpu->svm->vmcb->save.gdtr.limit;
+       dt->base = vcpu->svm->vmcb->save.gdtr.base;
+}
+
+static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       vcpu->svm->vmcb->save.gdtr.limit = dt->limit;
+       vcpu->svm->vmcb->save.gdtr.base = dt->base ;
+}
+
+static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+#ifdef __x86_64__
+       if (vcpu->shadow_efer & KVM_EFER_LME) {
+               if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
+                       vcpu->shadow_efer |= KVM_EFER_LMA;
+                       vcpu->svm->vmcb->save.efer |= KVM_EFER_LMA | KVM_EFER_LME;
+               }
+
+               if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK) ) {
+                       vcpu->shadow_efer &= ~KVM_EFER_LMA;
+                       vcpu->svm->vmcb->save.efer &= ~(KVM_EFER_LMA | KVM_EFER_LME);
+               }
+       }
+#endif
+       vcpu->svm->cr0 = cr0;
+       vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK;
+       vcpu->cr0 = cr0;
+}
+
+static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+       vcpu->cr4 = cr4;
+       vcpu->svm->vmcb->save.cr4 = cr4 | CR4_PAE_MASK;
+}
+
+static void svm_set_segment(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg)
+{
+       struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+       s->base = var->base;
+       s->limit = var->limit;
+       s->selector = var->selector;
+       if (var->unusable)
+               s->attrib = 0;
+       else {
+               s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
+               s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
+               s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
+               s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT;
+               s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
+               s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
+               s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
+               s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
+       }
+       if (seg == VCPU_SREG_CS)
+               vcpu->svm->vmcb->save.cpl
+                       = (vcpu->svm->vmcb->save.cs.attrib
+                          >> SVM_SELECTOR_DPL_SHIFT) & 3;
+
+}
+
+/* FIXME:
+
+       vcpu->svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
+       vcpu->svm->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK);
+
+*/
+
+static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
+{
+       return -EOPNOTSUPP;
+}
+
+static void load_host_msrs(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
+               wrmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+}
+
+static void save_host_msrs(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
+               rdmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+}
+
+static void new_asid(struct kvm_vcpu *vcpu, struct svm_cpu_data *svm_data)
+{
+       if (svm_data->next_asid > svm_data->max_asid) {
+               ++svm_data->asid_generation;
+               svm_data->next_asid = 1;
+               vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
+       }
+
+       vcpu->cpu = svm_data->cpu;
+       vcpu->svm->asid_generation = svm_data->asid_generation;
+       vcpu->svm->vmcb->control.asid = svm_data->next_asid++;
+}
+
+static void svm_invlpg(struct kvm_vcpu *vcpu, gva_t address)
+{
+       invlpga(address, vcpu->svm->vmcb->control.asid); // is needed?
+}
+
+static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr)
+{
+       return vcpu->svm->db_regs[dr];
+}
+
+static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
+                      int *exception)
+{
+       *exception = 0;
+
+       if (vcpu->svm->vmcb->save.dr7 & DR7_GD_MASK) {
+               vcpu->svm->vmcb->save.dr7 &= ~DR7_GD_MASK;
+               vcpu->svm->vmcb->save.dr6 |= DR6_BD_MASK;
+               *exception = DB_VECTOR;
+               return;
+       }
+
+       switch (dr) {
+       case 0 ... 3:
+               vcpu->svm->db_regs[dr] = value;
+               return;
+       case 4 ... 5:
+               if (vcpu->cr4 & CR4_DE_MASK) {
+                       *exception = UD_VECTOR;
+                       return;
+               }
+       case 7: {
+               if (value & ~((1ULL << 32) - 1)) {
+                       *exception = GP_VECTOR;
+                       return;
+               }
+               vcpu->svm->vmcb->save.dr7 = value;
+               return;
+       }
+       default:
+               printk(KERN_DEBUG "%s: unexpected dr %u\n",
+                      __FUNCTION__, dr);
+               *exception = UD_VECTOR;
+               return;
+       }
+}
+
+static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
+       u64 fault_address;
+       u32 error_code;
+       enum emulation_result er;
+
+       if (is_external_interrupt(exit_int_info))
+               push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
+
+       spin_lock(&vcpu->kvm->lock);
+
+       fault_address  = vcpu->svm->vmcb->control.exit_info_2;
+       error_code = vcpu->svm->vmcb->control.exit_info_1;
+       if (!vcpu->mmu.page_fault(vcpu, fault_address, error_code)) {
+               spin_unlock(&vcpu->kvm->lock);
+               return 1;
+       }
+       er = emulate_instruction(vcpu, kvm_run, fault_address, error_code);
+       spin_unlock(&vcpu->kvm->lock);
+
+       switch (er) {
+       case EMULATE_DONE:
+               return 1;
+       case EMULATE_DO_MMIO:
+               ++kvm_stat.mmio_exits;
+               kvm_run->exit_reason = KVM_EXIT_MMIO;
+               return 0;
+       case EMULATE_FAIL:
+               vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__);
+               break;
+       default:
+               BUG();
+       }
+
+       kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+       return 0;
+}
+
+static int io_get_override(struct kvm_vcpu *vcpu,
+                         struct vmcb_seg **seg,
+                         int *addr_override)
+{
+       u8 inst[MAX_INST_SIZE];
+       unsigned ins_length;
+       gva_t rip;
+       int i;
+
+       rip =  vcpu->svm->vmcb->save.rip;
+       ins_length = vcpu->svm->next_rip - rip;
+       rip += vcpu->svm->vmcb->save.cs.base;
+
+       if (ins_length > MAX_INST_SIZE)
+               printk(KERN_DEBUG
+                      "%s: inst length err, cs base 0x%llx rip 0x%llx "
+                      "next rip 0x%llx ins_length %u\n",
+                      __FUNCTION__,
+                      vcpu->svm->vmcb->save.cs.base,
+                      vcpu->svm->vmcb->save.rip,
+                      vcpu->svm->vmcb->control.exit_info_2,
+                      ins_length);
+
+       if (kvm_read_guest(vcpu, rip, ins_length, inst) != ins_length)
+               /* #PF */
+               return 0;
+
+       *addr_override = 0;
+       *seg = 0;
+       for (i = 0; i < ins_length; i++)
+               switch (inst[i]) {
+               case 0xf0:
+               case 0xf2:
+               case 0xf3:
+               case 0x66:
+                       continue;
+               case 0x67:
+                       *addr_override = 1;
+                       continue;
+               case 0x2e:
+                       *seg = &vcpu->svm->vmcb->save.cs;
+                       continue;
+               case 0x36:
+                       *seg = &vcpu->svm->vmcb->save.ss;
+                       continue;
+               case 0x3e:
+                       *seg = &vcpu->svm->vmcb->save.ds;
+                       continue;
+               case 0x26:
+                       *seg = &vcpu->svm->vmcb->save.es;
+                       continue;
+               case 0x64:
+                       *seg = &vcpu->svm->vmcb->save.fs;
+                       continue;
+               case 0x65:
+                       *seg = &vcpu->svm->vmcb->save.gs;
+                       continue;
+               default:
+                       return 1;
+               }
+       printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__);
+       return 0;
+}
+
+static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address)
+{
+       unsigned long addr_mask;
+       unsigned long *reg;
+       struct vmcb_seg *seg;
+       int addr_override;
+       struct vmcb_save_area *save_area = &vcpu->svm->vmcb->save;
+       u16 cs_attrib = save_area->cs.attrib;
+       unsigned addr_size = get_addr_size(vcpu);
+
+       if (!io_get_override(vcpu, &seg, &addr_override))
+               return 0;
+
+       if (addr_override)
+               addr_size = (addr_size == 2) ? 4: (addr_size >> 1);
+
+       if (ins) {
+               reg = &vcpu->regs[VCPU_REGS_RDI];
+               seg = &vcpu->svm->vmcb->save.es;
+       } else {
+               reg = &vcpu->regs[VCPU_REGS_RSI];
+               seg = (seg) ? seg : &vcpu->svm->vmcb->save.ds;
+       }
+
+       addr_mask = ~0ULL >> (64 - (addr_size * 8));
+
+       if ((cs_attrib & SVM_SELECTOR_L_MASK) &&
+           !(vcpu->svm->vmcb->save.rflags & X86_EFLAGS_VM)) {
+               *address = (*reg & addr_mask);
+               return addr_mask;
+       }
+
+       if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) {
+               svm_inject_gp(vcpu, 0);
+               return 0;
+       }
+
+       *address = (*reg & addr_mask) + seg->base;
+       return addr_mask;
+}
+
+static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug?
+       int _in = io_info & SVM_IOIO_TYPE_MASK;
+
+       ++kvm_stat.io_exits;
+
+       vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2;
+
+       kvm_run->exit_reason = KVM_EXIT_IO;
+       kvm_run->io.port = io_info >> 16;
+       kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+       kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT);
+       kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0;
+       kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0;
+
+       if (kvm_run->io.string) {
+               unsigned addr_mask;
+
+               addr_mask = io_adress(vcpu, _in, &kvm_run->io.address);
+               if (!addr_mask) {
+                       printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__);
+                       return 1;
+               }
+
+               if (kvm_run->io.rep) {
+                       kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
+                       kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags
+                                                  & X86_EFLAGS_DF) != 0;
+               }
+       } else {
+               kvm_run->io.value = vcpu->svm->vmcb->save.rax;
+       }
+       return 0;
+}
+
+
+static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       return 1;
+}
+
+static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1;
+       skip_emulated_instruction(vcpu);
+       if (vcpu->irq_summary && (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF))
+               return 1;
+
+       kvm_run->exit_reason = KVM_EXIT_HLT;
+       return 0;
+}
+
+static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       inject_ud(vcpu);
+       return 1;
+}
+
+static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       printk(KERN_DEBUG "%s: task swiche is unsupported\n", __FUNCTION__);
+       kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+       return 0;
+}
+
+static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+       kvm_run->exit_reason = KVM_EXIT_CPUID;
+       return 0;
+}
+
+static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE)
+               printk(KERN_ERR "%s: failed\n", __FUNCTION__);
+       return 1;
+}
+
+static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
+{
+       switch (ecx) {
+       case MSR_IA32_MC0_CTL:
+       case MSR_IA32_MCG_STATUS:
+       case MSR_IA32_MCG_CAP:
+       case MSR_IA32_MC0_MISC:
+       case MSR_IA32_MC0_MISC+4:
+       case MSR_IA32_MC0_MISC+8:
+       case MSR_IA32_MC0_MISC+12:
+       case MSR_IA32_MC0_MISC+16:
+       case MSR_IA32_UCODE_REV:
+               /* MTRR registers */
+       case 0xfe:
+       case 0x200 ... 0x2ff:
+               *data = 0;
+               break;
+       case MSR_IA32_TIME_STAMP_COUNTER: {
+               u64 tsc;
+
+               rdtscll(tsc);
+               *data = vcpu->svm->vmcb->control.tsc_offset + tsc;
+               break;
+       }
+       case MSR_EFER:
+               *data = vcpu->shadow_efer;
+               break;
+       case MSR_IA32_APICBASE:
+               *data = vcpu->apic_base;
+               break;
+#ifdef __x86_64__
+       case MSR_STAR:
+               *data = vcpu->svm->vmcb->save.star;
+               break;
+       case MSR_LSTAR:
+               *data = vcpu->svm->vmcb->save.lstar;
+               break;
+       case MSR_CSTAR:
+               *data = vcpu->svm->vmcb->save.cstar;
+               break;
+       case MSR_KERNEL_GS_BASE:
+               *data = vcpu->svm->vmcb->save.kernel_gs_base;
+               break;
+       case MSR_SYSCALL_MASK:
+               *data = vcpu->svm->vmcb->save.sfmask;
+               break;
+#endif
+       case MSR_IA32_SYSENTER_CS:
+               *data = vcpu->svm->vmcb->save.sysenter_cs;
+               break;
+       case MSR_IA32_SYSENTER_EIP:
+               *data = vcpu->svm->vmcb->save.sysenter_eip;
+               break;
+       case MSR_IA32_SYSENTER_ESP:
+               *data = vcpu->svm->vmcb->save.sysenter_esp;
+               break;
+       default:
+               printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", ecx);
+               return 1;
+       }
+       return 0;
+}
+
+static int rdmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+       u64 data;
+
+       if (svm_get_msr(vcpu, ecx, &data))
+               svm_inject_gp(vcpu, 0);
+       else {
+               vcpu->svm->vmcb->save.rax = data & 0xffffffff;
+               vcpu->regs[VCPU_REGS_RDX] = data >> 32;
+               vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+               skip_emulated_instruction(vcpu);
+       }
+       return 1;
+}
+
+static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
+{
+       switch (ecx) {
+#ifdef __x86_64__
+       case MSR_EFER:
+               set_efer(vcpu, data);
+               break;
+#endif
+       case MSR_IA32_MC0_STATUS:
+               printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n"
+                           , __FUNCTION__, data);
+               break;
+       case MSR_IA32_TIME_STAMP_COUNTER: {
+               u64 tsc;
+
+               rdtscll(tsc);
+               vcpu->svm->vmcb->control.tsc_offset = data - tsc;
+               break;
+       }
+       case MSR_IA32_UCODE_REV:
+       case MSR_IA32_UCODE_WRITE:
+       case 0x200 ... 0x2ff: /* MTRRs */
+               break;
+       case MSR_IA32_APICBASE:
+               vcpu->apic_base = data;
+               break;
+#ifdef __x86_64___
+       case MSR_STAR:
+               vcpu->svm->vmcb->save.star = data;
+               break;
+       case MSR_LSTAR:
+               vcpu->svm->vmcb->save.lstar = data;
+               break;
+       case MSR_CSTAR:
+               vcpu->svm->vmcb->save.cstar = data;
+               break;
+       case MSR_KERNEL_GS_BASE:
+               vcpu->svm->vmcb->save.kernel_gs_base = data;
+               break;
+       case MSR_SYSCALL_MASK:
+               vcpu->svm->vmcb->save.sfmask = data;
+               break;
+#endif
+       case MSR_IA32_SYSENTER_CS:
+               vcpu->svm->vmcb->save.sysenter_cs = data;
+               break;
+       case MSR_IA32_SYSENTER_EIP:
+               vcpu->svm->vmcb->save.sysenter_eip = data;
+               break;
+       case MSR_IA32_SYSENTER_ESP:
+               vcpu->svm->vmcb->save.sysenter_esp = data;
+               break;
+       default:
+               printk(KERN_ERR "kvm: unhandled wrmsr: %x\n", ecx);
+               return 1;
+       }
+       return 0;
+}
+
+static int wrmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+       u64 data = (vcpu->svm->vmcb->save.rax & -1u)
+               | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32);
+       vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+       if (svm_set_msr(vcpu, ecx, data))
+               svm_inject_gp(vcpu, 0);
+       else
+               skip_emulated_instruction(vcpu);
+       return 1;
+}
+
+static int msr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       if (vcpu->svm->vmcb->control.exit_info_1)
+               return wrmsr_interception(vcpu, kvm_run);
+       else
+               return rdmsr_interception(vcpu, kvm_run);
+}
+
+static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
+                                     struct kvm_run *kvm_run) = {
+       [SVM_EXIT_READ_CR0]                     = emulate_on_interception,
+       [SVM_EXIT_READ_CR3]                     = emulate_on_interception,
+       [SVM_EXIT_READ_CR4]                     = emulate_on_interception,
+       /* for now: */
+       [SVM_EXIT_WRITE_CR0]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_CR3]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_CR4]                    = emulate_on_interception,
+       [SVM_EXIT_READ_DR0]                     = emulate_on_interception,
+       [SVM_EXIT_READ_DR1]                     = emulate_on_interception,
+       [SVM_EXIT_READ_DR2]                     = emulate_on_interception,
+       [SVM_EXIT_READ_DR3]                     = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR0]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR1]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR2]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR3]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR5]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_DR7]                    = emulate_on_interception,
+       [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
+       [SVM_EXIT_INTR]                         = nop_on_interception,
+       [SVM_EXIT_NMI]                          = nop_on_interception,
+       [SVM_EXIT_SMI]                          = nop_on_interception,
+       [SVM_EXIT_INIT]                         = nop_on_interception,
+       /* [SVM_EXIT_CR0_SEL_WRITE]             = emulate_on_interception, */
+       [SVM_EXIT_CPUID]                        = cpuid_interception,
+       [SVM_EXIT_HLT]                          = halt_interception,
+       [SVM_EXIT_INVLPG]                       = emulate_on_interception,
+       [SVM_EXIT_INVLPGA]                      = invalid_op_interception,
+       [SVM_EXIT_IOIO]                         = io_interception,
+       [SVM_EXIT_MSR]                          = msr_interception,
+       [SVM_EXIT_TASK_SWITCH]                  = task_switch_interception,
+       [SVM_EXIT_VMRUN]                        = invalid_op_interception,
+       [SVM_EXIT_VMMCALL]                      = invalid_op_interception,
+       [SVM_EXIT_VMLOAD]                       = invalid_op_interception,
+       [SVM_EXIT_VMSAVE]                       = invalid_op_interception,
+       [SVM_EXIT_STGI]                         = invalid_op_interception,
+       [SVM_EXIT_CLGI]                         = invalid_op_interception,
+       [SVM_EXIT_SKINIT]                       = invalid_op_interception,
+};
+
+
+static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 exit_code = vcpu->svm->vmcb->control.exit_code;
+
+       kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
+
+       if (is_external_interrupt(vcpu->svm->vmcb->control.exit_int_info) &&
+           exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
+               printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
+                      "exit_code 0x%x\n",
+                      __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info,
+                      exit_code);
+
+       if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers)
+           || svm_exit_handlers[exit_code] == 0) {
+               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+               printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n",
+                      __FUNCTION__,
+                      exit_code,
+                      vcpu->svm->vmcb->save.rip,
+                      vcpu->cr0,
+                      vcpu->svm->vmcb->save.rflags);
+               return 0;
+       }
+
+       return svm_exit_handlers[exit_code](vcpu, kvm_run);
+}
+
+static void reload_tss(struct kvm_vcpu *vcpu)
+{
+       int cpu = raw_smp_processor_id();
+
+       struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
+       svm_data->tss_desc->type = 9; //available 32/64-bit TSS
+       load_TR_desc();
+}
+
+static void pre_svm_run(struct kvm_vcpu *vcpu)
+{
+       int cpu = raw_smp_processor_id();
+
+       struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
+
+       vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
+       if (vcpu->cpu != cpu ||
+           vcpu->svm->asid_generation != svm_data->asid_generation)
+               new_asid(vcpu, svm_data);
+}
+
+
+static inline void kvm_try_inject_irq(struct kvm_vcpu *vcpu)
+{
+       struct vmcb_control_area *control;
+
+       if (!vcpu->irq_summary)
+               return;
+
+       control = &vcpu->svm->vmcb->control;
+
+       control->int_vector = pop_irq(vcpu);
+       control->int_ctl &= ~V_INTR_PRIO_MASK;
+       control->int_ctl |= V_IRQ_MASK |
+               ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
+}
+
+static void kvm_reput_irq(struct kvm_vcpu *vcpu)
+{
+       struct vmcb_control_area *control = &vcpu->svm->vmcb->control;
+
+       if (control->int_ctl & V_IRQ_MASK) {
+               control->int_ctl &= ~V_IRQ_MASK;
+               push_irq(vcpu, control->int_vector);
+       }
+}
+
+static void save_db_regs(unsigned long *db_regs)
+{
+#ifdef __x86_64__
+       asm ("mov %%dr0, %%rax \n\t"
+            "mov %%rax, %[dr0] \n\t"
+            "mov %%dr1, %%rax \n\t"
+            "mov %%rax, %[dr1] \n\t"
+            "mov %%dr2, %%rax \n\t"
+            "mov %%rax, %[dr2] \n\t"
+            "mov %%dr3, %%rax \n\t"
+            "mov %%rax, %[dr3] \n\t"
+            : [dr0] "=m"(db_regs[0]),
+              [dr1] "=m"(db_regs[1]),
+              [dr2] "=m"(db_regs[2]),
+              [dr3] "=m"(db_regs[3])
+            : : "rax");
+#else
+       asm ("mov %%dr0, %%eax \n\t"
+            "mov %%eax, %[dr0] \n\t"
+            "mov %%dr1, %%eax \n\t"
+            "mov %%eax, %[dr1] \n\t"
+            "mov %%dr2, %%eax \n\t"
+            "mov %%eax, %[dr2] \n\t"
+            "mov %%dr3, %%eax \n\t"
+            "mov %%eax, %[dr3] \n\t"
+            : [dr0] "=m"(db_regs[0]),
+              [dr1] "=m"(db_regs[1]),
+              [dr2] "=m"(db_regs[2]),
+              [dr3] "=m"(db_regs[3])
+            : : "eax");
+#endif
+}
+
+static void load_db_regs(unsigned long *db_regs)
+{
+       asm volatile ("mov %[dr0], %%dr0 \n\t"
+            "mov %[dr1], %%dr1 \n\t"
+            "mov %[dr2], %%dr2 \n\t"
+            "mov %[dr3], %%dr3 \n\t"
+            :
+            : [dr0] "r"(db_regs[0]),
+              [dr1] "r"(db_regs[1]),
+              [dr2] "r"(db_regs[2]),
+              [dr3] "r"(db_regs[3])
+#ifdef __x86_64__
+            : "rax");
+#else
+            : "eax");
+#endif
+}
+
+static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u16 fs_selector;
+       u16 gs_selector;
+       u16 ldt_selector;
+
+again:
+       kvm_try_inject_irq(vcpu);
+
+       clgi();
+
+       pre_svm_run(vcpu);
+
+       save_host_msrs(vcpu);
+       fs_selector = read_fs();
+       gs_selector = read_gs();
+       ldt_selector = read_ldt();
+       vcpu->svm->host_cr2 = kvm_read_cr2();
+       vcpu->svm->host_dr6 = read_dr6();
+       vcpu->svm->host_dr7 = read_dr7();
+       vcpu->svm->vmcb->save.cr2 = vcpu->cr2;
+
+       if (vcpu->svm->vmcb->save.dr7 & 0xff) {
+               write_dr7(0);
+               save_db_regs(vcpu->svm->host_db_regs);
+               load_db_regs(vcpu->svm->db_regs);
+       }
+       asm volatile (
+#ifdef __x86_64__
+               "push %%rbx; push %%rcx; push %%rdx;"
+               "push %%rsi; push %%rdi; push %%rbp;"
+               "push %%r8;  push %%r9;  push %%r10; push %%r11;"
+               "push %%r12; push %%r13; push %%r14; push %%r15;"
+#else
+               "push %%ebx; push %%ecx; push %%edx;"
+               "push %%esi; push %%edi; push %%ebp;"
+#endif
+
+#ifdef __x86_64__
+               "mov %c[rbx](%[vcpu]), %%rbx \n\t"
+               "mov %c[rcx](%[vcpu]), %%rcx \n\t"
+               "mov %c[rdx](%[vcpu]), %%rdx \n\t"
+               "mov %c[rsi](%[vcpu]), %%rsi \n\t"
+               "mov %c[rdi](%[vcpu]), %%rdi \n\t"
+               "mov %c[rbp](%[vcpu]), %%rbp \n\t"
+               "mov %c[r8](%[vcpu]),  %%r8  \n\t"
+               "mov %c[r9](%[vcpu]),  %%r9  \n\t"
+               "mov %c[r10](%[vcpu]), %%r10 \n\t"
+               "mov %c[r11](%[vcpu]), %%r11 \n\t"
+               "mov %c[r12](%[vcpu]), %%r12 \n\t"
+               "mov %c[r13](%[vcpu]), %%r13 \n\t"
+               "mov %c[r14](%[vcpu]), %%r14 \n\t"
+               "mov %c[r15](%[vcpu]), %%r15 \n\t"
+#else
+               "mov %c[rbx](%[vcpu]), %%ebx \n\t"
+               "mov %c[rcx](%[vcpu]), %%ecx \n\t"
+               "mov %c[rdx](%[vcpu]), %%edx \n\t"
+               "mov %c[rsi](%[vcpu]), %%esi \n\t"
+               "mov %c[rdi](%[vcpu]), %%edi \n\t"
+               "mov %c[rbp](%[vcpu]), %%ebp \n\t"
+#endif
+
+#ifdef __x86_64__
+               /* Enter guest mode */
+               "push %%rax \n\t"
+               "mov %c[svm](%[vcpu]), %%rax \n\t"
+               "mov %c[vmcb](%%rax), %%rax \n\t"
+               SVM_VMLOAD "\n\t"
+               SVM_VMRUN "\n\t"
+               SVM_VMSAVE "\n\t"
+               "pop %%rax \n\t"
+#else
+               /* Enter guest mode */
+               "push %%eax \n\t"
+               "mov %c[svm](%[vcpu]), %%eax \n\t"
+               "mov %c[vmcb](%%eax), %%eax \n\t"
+               SVM_VMLOAD "\n\t"
+               SVM_VMRUN "\n\t"
+               SVM_VMSAVE "\n\t"
+               "pop %%eax \n\t"
+#endif
+
+               /* Save guest registers, load host registers */
+#ifdef __x86_64__
+               "mov %%rbx, %c[rbx](%[vcpu]) \n\t"
+               "mov %%rcx, %c[rcx](%[vcpu]) \n\t"
+               "mov %%rdx, %c[rdx](%[vcpu]) \n\t"
+               "mov %%rsi, %c[rsi](%[vcpu]) \n\t"
+               "mov %%rdi, %c[rdi](%[vcpu]) \n\t"
+               "mov %%rbp, %c[rbp](%[vcpu]) \n\t"
+               "mov %%r8,  %c[r8](%[vcpu]) \n\t"
+               "mov %%r9,  %c[r9](%[vcpu]) \n\t"
+               "mov %%r10, %c[r10](%[vcpu]) \n\t"
+               "mov %%r11, %c[r11](%[vcpu]) \n\t"
+               "mov %%r12, %c[r12](%[vcpu]) \n\t"
+               "mov %%r13, %c[r13](%[vcpu]) \n\t"
+               "mov %%r14, %c[r14](%[vcpu]) \n\t"
+               "mov %%r15, %c[r15](%[vcpu]) \n\t"
+
+               "pop  %%r15; pop  %%r14; pop  %%r13; pop  %%r12;"
+               "pop  %%r11; pop  %%r10; pop  %%r9;  pop  %%r8;"
+               "pop  %%rbp; pop  %%rdi; pop  %%rsi;"
+               "pop  %%rdx; pop  %%rcx; pop  %%rbx; \n\t"
+#else
+               "mov %%ebx, %c[rbx](%[vcpu]) \n\t"
+               "mov %%ecx, %c[rcx](%[vcpu]) \n\t"
+               "mov %%edx, %c[rdx](%[vcpu]) \n\t"
+               "mov %%esi, %c[rsi](%[vcpu]) \n\t"
+               "mov %%edi, %c[rdi](%[vcpu]) \n\t"
+               "mov %%ebp, %c[rbp](%[vcpu]) \n\t"
+
+               "pop  %%ebp; pop  %%edi; pop  %%esi;"
+               "pop  %%edx; pop  %%ecx; pop  %%ebx; \n\t"
+#endif
+               :
+               : [vcpu]"a"(vcpu),
+                 [svm]"i"(offsetof(struct kvm_vcpu, svm)),
+                 [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)),
+                 [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])),
+                 [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])),
+                 [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])),
+                 [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
+                 [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
+                 [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP]))
+#ifdef __x86_64__
+                 ,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
+                 [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
+                 [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
+                 [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])),
+                 [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])),
+                 [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])),
+                 [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])),
+                 [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15]))
+#endif
+               : "cc", "memory" );
+
+       if ((vcpu->svm->vmcb->save.dr7 & 0xff))
+               load_db_regs(vcpu->svm->host_db_regs);
+
+       vcpu->cr2 = vcpu->svm->vmcb->save.cr2;
+
+       write_dr6(vcpu->svm->host_dr6);
+       write_dr7(vcpu->svm->host_dr7);
+       kvm_write_cr2(vcpu->svm->host_cr2);
+
+       load_fs(fs_selector);
+       load_gs(gs_selector);
+       load_ldt(ldt_selector);
+       load_host_msrs(vcpu);
+
+       reload_tss(vcpu);
+
+       stgi();
+
+       kvm_reput_irq(vcpu);
+
+       vcpu->svm->next_rip = 0;
+
+       if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
+               kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
+               kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code;
+               return 0;
+       }
+
+       if (handle_exit(vcpu, kvm_run)) {
+               if (signal_pending(current)) {
+                       ++kvm_stat.signal_exits;
+                       return -EINTR;
+               }
+               kvm_resched(vcpu);
+               goto again;
+       }
+       return 0;
+}
+
+static void svm_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       force_new_asid(vcpu);
+}
+
+static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
+{
+       vcpu->svm->vmcb->save.cr3 = root;
+       force_new_asid(vcpu);
+}
+
+static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
+                                 unsigned long  addr,
+                                 uint32_t err_code)
+{
+       uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
+
+       ++kvm_stat.pf_guest;
+
+       if (is_page_fault(exit_int_info)) {
+
+               vcpu->svm->vmcb->control.event_inj_err = 0;
+               vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
+                                                       SVM_EVTINJ_VALID_ERR |
+                                                       SVM_EVTINJ_TYPE_EXEPT |
+                                                       DF_VECTOR;
+               return;
+       }
+       vcpu->cr2 = addr;
+       vcpu->svm->vmcb->save.cr2 = addr;
+       vcpu->svm->vmcb->control.event_inj =    SVM_EVTINJ_VALID |
+                                               SVM_EVTINJ_VALID_ERR |
+                                               SVM_EVTINJ_TYPE_EXEPT |
+                                               PF_VECTOR;
+       vcpu->svm->vmcb->control.event_inj_err = err_code;
+}
+
+
+static int is_disabled(void)
+{
+       return 0;
+}
+
+static struct kvm_arch_ops svm_arch_ops = {
+       .cpu_has_kvm_support = has_svm,
+       .disabled_by_bios = is_disabled,
+       .hardware_setup = svm_hardware_setup,
+       .hardware_unsetup = svm_hardware_unsetup,
+       .hardware_enable = svm_hardware_enable,
+       .hardware_disable = svm_hardware_disable,
+
+       .vcpu_create = svm_create_vcpu,
+       .vcpu_free = svm_free_vcpu,
+
+       .vcpu_load = svm_vcpu_load,
+       .vcpu_put = svm_vcpu_put,
+
+       .set_guest_debug = svm_guest_debug,
+       .get_msr = svm_get_msr,
+       .set_msr = svm_set_msr,
+       .get_segment_base = svm_get_segment_base,
+       .get_segment = svm_get_segment,
+       .set_segment = svm_set_segment,
+       .is_long_mode = svm_is_long_mode,
+       .get_cs_db_l_bits = svm_get_cs_db_l_bits,
+       .set_cr0 = svm_set_cr0,
+       .set_cr0_no_modeswitch = svm_set_cr0,
+       .set_cr3 = svm_set_cr3,
+       .set_cr4 = svm_set_cr4,
+       .set_efer = svm_set_efer,
+       .get_idt = svm_get_idt,
+       .set_idt = svm_set_idt,
+       .get_gdt = svm_get_gdt,
+       .set_gdt = svm_set_gdt,
+       .get_dr = svm_get_dr,
+       .set_dr = svm_set_dr,
+       .cache_regs = svm_cache_regs,
+       .decache_regs = svm_decache_regs,
+       .get_rflags = svm_get_rflags,
+       .set_rflags = svm_set_rflags,
+
+       .invlpg = svm_invlpg,
+       .tlb_flush = svm_flush_tlb,
+       .inject_page_fault = svm_inject_page_fault,
+
+       .inject_gp = svm_inject_gp,
+
+       .run = svm_vcpu_run,
+       .skip_emulated_instruction = skip_emulated_instruction,
+       .vcpu_setup = svm_vcpu_setup,
+};
+
+static int __init svm_init(void)
+{
+       kvm_emulator_want_group7_invlpg();
+       kvm_init_arch(&svm_arch_ops, THIS_MODULE);
+       return 0;
+}
+
+static void __exit svm_exit(void)
+{
+       kvm_exit_arch();
+}
+
+module_init(svm_init)
+module_exit(svm_exit)
diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h
new file mode 100644 (file)
index 0000000..df731c3
--- /dev/null
@@ -0,0 +1,315 @@
+#ifndef __SVM_H
+#define __SVM_H
+
+enum {
+       INTERCEPT_INTR,
+       INTERCEPT_NMI,
+       INTERCEPT_SMI,
+       INTERCEPT_INIT,
+       INTERCEPT_VINTR,
+       INTERCEPT_SELECTIVE_CR0,
+       INTERCEPT_STORE_IDTR,
+       INTERCEPT_STORE_GDTR,
+       INTERCEPT_STORE_LDTR,
+       INTERCEPT_STORE_TR,
+       INTERCEPT_LOAD_IDTR,
+       INTERCEPT_LOAD_GDTR,
+       INTERCEPT_LOAD_LDTR,
+       INTERCEPT_LOAD_TR,
+       INTERCEPT_RDTSC,
+       INTERCEPT_RDPMC,
+       INTERCEPT_PUSHF,
+       INTERCEPT_POPF,
+       INTERCEPT_CPUID,
+       INTERCEPT_RSM,
+       INTERCEPT_IRET,
+       INTERCEPT_INTn,
+       INTERCEPT_INVD,
+       INTERCEPT_PAUSE,
+       INTERCEPT_HLT,
+       INTERCEPT_INVLPG,
+       INTERCEPT_INVLPGA,
+       INTERCEPT_IOIO_PROT,
+       INTERCEPT_MSR_PROT,
+       INTERCEPT_TASK_SWITCH,
+       INTERCEPT_FERR_FREEZE,
+       INTERCEPT_SHUTDOWN,
+       INTERCEPT_VMRUN,
+       INTERCEPT_VMMCALL,
+       INTERCEPT_VMLOAD,
+       INTERCEPT_VMSAVE,
+       INTERCEPT_STGI,
+       INTERCEPT_CLGI,
+       INTERCEPT_SKINIT,
+       INTERCEPT_RDTSCP,
+       INTERCEPT_ICEBP,
+       INTERCEPT_WBINVD,
+};
+
+
+struct __attribute__ ((__packed__)) vmcb_control_area {
+       u16 intercept_cr_read;
+       u16 intercept_cr_write;
+       u16 intercept_dr_read;
+       u16 intercept_dr_write;
+       u32 intercept_exceptions;
+       u64 intercept;
+       u8 reserved_1[44];
+       u64 iopm_base_pa;
+       u64 msrpm_base_pa;
+       u64 tsc_offset;
+       u32 asid;
+       u8 tlb_ctl;
+       u8 reserved_2[3];
+       u32 int_ctl;
+       u32 int_vector;
+       u32 int_state;
+       u8 reserved_3[4];
+       u32 exit_code;
+       u32 exit_code_hi;
+       u64 exit_info_1;
+       u64 exit_info_2;
+       u32 exit_int_info;
+       u32 exit_int_info_err;
+       u64 nested_ctl;
+       u8 reserved_4[16];
+       u32 event_inj;
+       u32 event_inj_err;
+       u64 nested_cr3;
+       u64 lbr_ctl;
+       u8 reserved_5[832];
+};
+
+
+#define TLB_CONTROL_DO_NOTHING 0
+#define TLB_CONTROL_FLUSH_ALL_ASID 1
+
+#define V_TPR_MASK 0x0f
+
+#define V_IRQ_SHIFT 8
+#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
+
+#define V_INTR_PRIO_SHIFT 16
+#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
+
+#define V_IGN_TPR_SHIFT 20
+#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
+
+#define V_INTR_MASKING_SHIFT 24
+#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
+
+#define SVM_INTERRUPT_SHADOW_MASK 1
+
+#define SVM_IOIO_STR_SHIFT 2
+#define SVM_IOIO_REP_SHIFT 3
+#define SVM_IOIO_SIZE_SHIFT 4
+#define SVM_IOIO_ASIZE_SHIFT 7
+
+#define SVM_IOIO_TYPE_MASK 1
+#define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT)
+#define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT)
+#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
+#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
+
+struct __attribute__ ((__packed__)) vmcb_seg {
+       u16 selector;
+       u16 attrib;
+       u32 limit;
+       u64 base;
+};
+
+struct __attribute__ ((__packed__)) vmcb_save_area {
+       struct vmcb_seg es;
+       struct vmcb_seg cs;
+       struct vmcb_seg ss;
+       struct vmcb_seg ds;
+       struct vmcb_seg fs;
+       struct vmcb_seg gs;
+       struct vmcb_seg gdtr;
+       struct vmcb_seg ldtr;
+       struct vmcb_seg idtr;
+       struct vmcb_seg tr;
+       u8 reserved_1[43];
+       u8 cpl;
+       u8 reserved_2[4];
+       u64 efer;
+       u8 reserved_3[112];
+       u64 cr4;
+       u64 cr3;
+       u64 cr0;
+       u64 dr7;
+       u64 dr6;
+       u64 rflags;
+       u64 rip;
+       u8 reserved_4[88];
+       u64 rsp;
+       u8 reserved_5[24];
+       u64 rax;
+       u64 star;
+       u64 lstar;
+       u64 cstar;
+       u64 sfmask;
+       u64 kernel_gs_base;
+       u64 sysenter_cs;
+       u64 sysenter_esp;
+       u64 sysenter_eip;
+       u64 cr2;
+       u8 reserved_6[32];
+       u64 g_pat;
+       u64 dbgctl;
+       u64 br_from;
+       u64 br_to;
+       u64 last_excp_from;
+       u64 last_excp_to;
+};
+
+struct __attribute__ ((__packed__)) vmcb {
+       struct vmcb_control_area control;
+       struct vmcb_save_area save;
+};
+
+#define SVM_CPUID_FEATURE_SHIFT 2
+#define SVM_CPUID_FUNC 0x8000000a
+
+#define MSR_EFER_SVME_MASK (1ULL << 12)
+#define MSR_VM_HSAVE_PA 0xc0010117ULL
+
+#define SVM_SELECTOR_S_SHIFT 4
+#define SVM_SELECTOR_DPL_SHIFT 5
+#define SVM_SELECTOR_P_SHIFT 7
+#define SVM_SELECTOR_AVL_SHIFT 8
+#define SVM_SELECTOR_L_SHIFT 9
+#define SVM_SELECTOR_DB_SHIFT 10
+#define SVM_SELECTOR_G_SHIFT 11
+
+#define SVM_SELECTOR_TYPE_MASK (0xf)
+#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT)
+#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT)
+#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT)
+#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT)
+#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT)
+#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT)
+#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT)
+
+#define SVM_SELECTOR_WRITE_MASK (1 << 1)
+#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
+#define SVM_SELECTOR_CODE_MASK (1 << 3)
+
+#define INTERCEPT_CR0_MASK 1
+#define INTERCEPT_CR3_MASK (1 << 3)
+#define INTERCEPT_CR4_MASK (1 << 4)
+
+#define INTERCEPT_DR0_MASK 1
+#define INTERCEPT_DR1_MASK (1 << 1)
+#define INTERCEPT_DR2_MASK (1 << 2)
+#define INTERCEPT_DR3_MASK (1 << 3)
+#define INTERCEPT_DR4_MASK (1 << 4)
+#define INTERCEPT_DR5_MASK (1 << 5)
+#define INTERCEPT_DR6_MASK (1 << 6)
+#define INTERCEPT_DR7_MASK (1 << 7)
+
+#define SVM_EVTINJ_VEC_MASK 0xff
+
+#define SVM_EVTINJ_TYPE_SHIFT 8
+#define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_VALID (1 << 31)
+#define SVM_EVTINJ_VALID_ERR (1 << 11)
+
+#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+
+#define        SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
+#define        SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
+#define        SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT
+#define        SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT
+
+#define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
+#define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
+
+#define        SVM_EXIT_READ_CR0       0x000
+#define        SVM_EXIT_READ_CR3       0x003
+#define        SVM_EXIT_READ_CR4       0x004
+#define        SVM_EXIT_READ_CR8       0x008
+#define        SVM_EXIT_WRITE_CR0      0x010
+#define        SVM_EXIT_WRITE_CR3      0x013
+#define        SVM_EXIT_WRITE_CR4      0x014
+#define        SVM_EXIT_WRITE_CR8      0x018
+#define        SVM_EXIT_READ_DR0       0x020
+#define        SVM_EXIT_READ_DR1       0x021
+#define        SVM_EXIT_READ_DR2       0x022
+#define        SVM_EXIT_READ_DR3       0x023
+#define        SVM_EXIT_READ_DR4       0x024
+#define        SVM_EXIT_READ_DR5       0x025
+#define        SVM_EXIT_READ_DR6       0x026
+#define        SVM_EXIT_READ_DR7       0x027
+#define        SVM_EXIT_WRITE_DR0      0x030
+#define        SVM_EXIT_WRITE_DR1      0x031
+#define        SVM_EXIT_WRITE_DR2      0x032
+#define        SVM_EXIT_WRITE_DR3      0x033
+#define        SVM_EXIT_WRITE_DR4      0x034
+#define        SVM_EXIT_WRITE_DR5      0x035
+#define        SVM_EXIT_WRITE_DR6      0x036
+#define        SVM_EXIT_WRITE_DR7      0x037
+#define SVM_EXIT_EXCP_BASE      0x040
+#define SVM_EXIT_INTR          0x060
+#define SVM_EXIT_NMI           0x061
+#define SVM_EXIT_SMI           0x062
+#define SVM_EXIT_INIT          0x063
+#define SVM_EXIT_VINTR         0x064
+#define SVM_EXIT_CR0_SEL_WRITE 0x065
+#define SVM_EXIT_IDTR_READ     0x066
+#define SVM_EXIT_GDTR_READ     0x067
+#define SVM_EXIT_LDTR_READ     0x068
+#define SVM_EXIT_TR_READ       0x069
+#define SVM_EXIT_IDTR_WRITE    0x06a
+#define SVM_EXIT_GDTR_WRITE    0x06b
+#define SVM_EXIT_LDTR_WRITE    0x06c
+#define SVM_EXIT_TR_WRITE      0x06d
+#define SVM_EXIT_RDTSC         0x06e
+#define SVM_EXIT_RDPMC         0x06f
+#define SVM_EXIT_PUSHF         0x070
+#define SVM_EXIT_POPF          0x071
+#define SVM_EXIT_CPUID         0x072
+#define SVM_EXIT_RSM           0x073
+#define SVM_EXIT_IRET          0x074
+#define SVM_EXIT_SWINT         0x075
+#define SVM_EXIT_INVD          0x076
+#define SVM_EXIT_PAUSE         0x077
+#define SVM_EXIT_HLT           0x078
+#define SVM_EXIT_INVLPG                0x079
+#define SVM_EXIT_INVLPGA       0x07a
+#define SVM_EXIT_IOIO          0x07b
+#define SVM_EXIT_MSR           0x07c
+#define SVM_EXIT_TASK_SWITCH   0x07d
+#define SVM_EXIT_FERR_FREEZE   0x07e
+#define SVM_EXIT_SHUTDOWN      0x07f
+#define SVM_EXIT_VMRUN         0x080
+#define SVM_EXIT_VMMCALL       0x081
+#define SVM_EXIT_VMLOAD                0x082
+#define SVM_EXIT_VMSAVE                0x083
+#define SVM_EXIT_STGI          0x084
+#define SVM_EXIT_CLGI          0x085
+#define SVM_EXIT_SKINIT                0x086
+#define SVM_EXIT_RDTSCP                0x087
+#define SVM_EXIT_ICEBP         0x088
+#define SVM_EXIT_WBINVD                0x089
+#define SVM_EXIT_NPF           0x400
+
+#define SVM_EXIT_ERR           -1
+
+#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) // TS and MP
+
+#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
+#define SVM_VMRUN  ".byte 0x0f, 0x01, 0xd8"
+#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb"
+#define SVM_CLGI   ".byte 0x0f, 0x01, 0xdd"
+#define SVM_STGI   ".byte 0x0f, 0x01, 0xdc"
+#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf"
+
+#endif
+
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
new file mode 100644 (file)
index 0000000..bda7a7a
--- /dev/null
@@ -0,0 +1,2002 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ *   Avi Kivity   <avi@qumranet.com>
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "kvm.h"
+#include "vmx.h"
+#include "kvm_vmx.h"
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <asm/io.h>
+
+#include "segment_descriptor.h"
+
+#define MSR_IA32_FEATURE_CONTROL               0x03a
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+static DEFINE_PER_CPU(struct vmcs *, vmxarea);
+static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
+
+#ifdef __x86_64__
+#define HOST_IS_64 1
+#else
+#define HOST_IS_64 0
+#endif
+
+static struct vmcs_descriptor {
+       int size;
+       int order;
+       u32 revision_id;
+} vmcs_descriptor;
+
+#define VMX_SEGMENT_FIELD(seg)                                 \
+       [VCPU_SREG_##seg] = {                                   \
+               .selector = GUEST_##seg##_SELECTOR,             \
+               .base = GUEST_##seg##_BASE,                     \
+               .limit = GUEST_##seg##_LIMIT,                   \
+               .ar_bytes = GUEST_##seg##_AR_BYTES,             \
+       }
+
+static struct kvm_vmx_segment_field {
+       unsigned selector;
+       unsigned base;
+       unsigned limit;
+       unsigned ar_bytes;
+} kvm_vmx_segment_fields[] = {
+       VMX_SEGMENT_FIELD(CS),
+       VMX_SEGMENT_FIELD(DS),
+       VMX_SEGMENT_FIELD(ES),
+       VMX_SEGMENT_FIELD(FS),
+       VMX_SEGMENT_FIELD(GS),
+       VMX_SEGMENT_FIELD(SS),
+       VMX_SEGMENT_FIELD(TR),
+       VMX_SEGMENT_FIELD(LDTR),
+};
+
+static const u32 vmx_msr_index[] = {
+#ifdef __x86_64__
+       MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
+#endif
+       MSR_EFER, MSR_K6_STAR,
+};
+#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index))
+
+struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr);
+
+static inline int is_page_fault(u32 intr_info)
+{
+       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+                            INTR_INFO_VALID_MASK)) ==
+               (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
+}
+
+static inline int is_external_interrupt(u32 intr_info)
+{
+       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+               == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+}
+
+static void vmcs_clear(struct vmcs *vmcs)
+{
+       u64 phys_addr = __pa(vmcs);
+       u8 error;
+
+       asm volatile (ASM_VMX_VMCLEAR_RAX "; setna %0"
+                     : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+                     : "cc", "memory");
+       if (error)
+               printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n",
+                      vmcs, phys_addr);
+}
+
+static void __vcpu_clear(void *arg)
+{
+       struct kvm_vcpu *vcpu = arg;
+       int cpu = smp_processor_id();
+
+       if (vcpu->cpu == cpu)
+               vmcs_clear(vcpu->vmcs);
+       if (per_cpu(current_vmcs, cpu) == vcpu->vmcs)
+               per_cpu(current_vmcs, cpu) = NULL;
+}
+
+static unsigned long vmcs_readl(unsigned long field)
+{
+       unsigned long value;
+
+       asm volatile (ASM_VMX_VMREAD_RDX_RAX
+                     : "=a"(value) : "d"(field) : "cc");
+       return value;
+}
+
+static u16 vmcs_read16(unsigned long field)
+{
+       return vmcs_readl(field);
+}
+
+static u32 vmcs_read32(unsigned long field)
+{
+       return vmcs_readl(field);
+}
+
+static u64 vmcs_read64(unsigned long field)
+{
+#ifdef __x86_64__
+       return vmcs_readl(field);
+#else
+       return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
+#endif
+}
+
+static void vmcs_writel(unsigned long field, unsigned long value)
+{
+       u8 error;
+
+       asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0"
+                      : "=q"(error) : "a"(value), "d"(field) : "cc" );
+       if (error)
+               printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n",
+                      field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
+}
+
+static void vmcs_write16(unsigned long field, u16 value)
+{
+       vmcs_writel(field, value);
+}
+
+static void vmcs_write32(unsigned long field, u32 value)
+{
+       vmcs_writel(field, value);
+}
+
+static void vmcs_write64(unsigned long field, u64 value)
+{
+#ifdef __x86_64__
+       vmcs_writel(field, value);
+#else
+       vmcs_writel(field, value);
+       asm volatile ("");
+       vmcs_writel(field+1, value >> 32);
+#endif
+}
+
+/*
+ * Switches to specified vcpu, until a matching vcpu_put(), but assumes
+ * vcpu mutex is already taken.
+ */
+static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu)
+{
+       u64 phys_addr = __pa(vcpu->vmcs);
+       int cpu;
+
+       cpu = get_cpu();
+
+       if (vcpu->cpu != cpu) {
+               smp_call_function(__vcpu_clear, vcpu, 0, 1);
+               vcpu->launched = 0;
+       }
+
+       if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
+               u8 error;
+
+               per_cpu(current_vmcs, cpu) = vcpu->vmcs;
+               asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0"
+                             : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+                             : "cc");
+               if (error)
+                       printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
+                              vcpu->vmcs, phys_addr);
+       }
+
+       if (vcpu->cpu != cpu) {
+               struct descriptor_table dt;
+               unsigned long sysenter_esp;
+
+               vcpu->cpu = cpu;
+               /*
+                * Linux uses per-cpu TSS and GDT, so set these when switching
+                * processors.
+                */
+               vmcs_writel(HOST_TR_BASE, read_tr_base()); /* 22.2.4 */
+               get_gdt(&dt);
+               vmcs_writel(HOST_GDTR_BASE, dt.base);   /* 22.2.4 */
+
+               rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
+               vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+       }
+       return vcpu;
+}
+
+static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
+{
+       put_cpu();
+}
+
+static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
+{
+       return vmcs_readl(GUEST_RFLAGS);
+}
+
+static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+       vmcs_writel(GUEST_RFLAGS, rflags);
+}
+
+static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       unsigned long rip;
+       u32 interruptibility;
+
+       rip = vmcs_readl(GUEST_RIP);
+       rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+       vmcs_writel(GUEST_RIP, rip);
+
+       /*
+        * We emulated an instruction, so temporary interrupt blocking
+        * should be removed, if set.
+        */
+       interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+       if (interruptibility & 3)
+               vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
+                            interruptibility & ~3);
+}
+
+static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
+{
+       printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
+              vmcs_readl(GUEST_RIP));
+       vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                    GP_VECTOR |
+                    INTR_TYPE_EXCEPTION |
+                    INTR_INFO_DELIEVER_CODE_MASK |
+                    INTR_INFO_VALID_MASK);
+}
+
+/*
+ * reads and returns guest's timestamp counter "register"
+ * guest_tsc = host_tsc + tsc_offset    -- 21.3
+ */
+static u64 guest_read_tsc(void)
+{
+       u64 host_tsc, tsc_offset;
+
+       rdtscll(host_tsc);
+       tsc_offset = vmcs_read64(TSC_OFFSET);
+       return host_tsc + tsc_offset;
+}
+
+/*
+ * writes 'guest_tsc' into guest's timestamp counter "register"
+ * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc
+ */
+static void guest_write_tsc(u64 guest_tsc)
+{
+       u64 host_tsc;
+
+       rdtscll(host_tsc);
+       vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc);
+}
+
+static void reload_tss(void)
+{
+#ifndef __x86_64__
+
+       /*
+        * VT restores TR but not its size.  Useless.
+        */
+       struct descriptor_table gdt;
+       struct segment_descriptor *descs;
+
+       get_gdt(&gdt);
+       descs = (void *)gdt.base;
+       descs[GDT_ENTRY_TSS].type = 9; /* available TSS */
+       load_TR_desc();
+#endif
+}
+
+/*
+ * Reads an msr value (of 'msr_index') into 'pdata'.
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+       u64 data;
+       struct vmx_msr_entry *msr;
+
+       if (!pdata) {
+               printk(KERN_ERR "BUG: get_msr called with NULL pdata\n");
+               return -EINVAL;
+       }
+
+       switch (msr_index) {
+#ifdef __x86_64__
+       case MSR_FS_BASE:
+               data = vmcs_readl(GUEST_FS_BASE);
+               break;
+       case MSR_GS_BASE:
+               data = vmcs_readl(GUEST_GS_BASE);
+               break;
+       case MSR_EFER:
+               data = vcpu->shadow_efer;
+               break;
+#endif
+       case MSR_IA32_TIME_STAMP_COUNTER:
+               data = guest_read_tsc();
+               break;
+       case MSR_IA32_SYSENTER_CS:
+               data = vmcs_read32(GUEST_SYSENTER_CS);
+               break;
+       case MSR_IA32_SYSENTER_EIP:
+               data = vmcs_read32(GUEST_SYSENTER_EIP);
+               break;
+       case MSR_IA32_SYSENTER_ESP:
+               data = vmcs_read32(GUEST_SYSENTER_ESP);
+               break;
+       case MSR_IA32_MC0_CTL:
+       case MSR_IA32_MCG_STATUS:
+       case MSR_IA32_MCG_CAP:
+       case MSR_IA32_MC0_MISC:
+       case MSR_IA32_MC0_MISC+4:
+       case MSR_IA32_MC0_MISC+8:
+       case MSR_IA32_MC0_MISC+12:
+       case MSR_IA32_MC0_MISC+16:
+       case MSR_IA32_UCODE_REV:
+               /* MTRR registers */
+       case 0xfe:
+       case 0x200 ... 0x2ff:
+               data = 0;
+               break;
+       case MSR_IA32_APICBASE:
+               data = vcpu->apic_base;
+               break;
+       default:
+               msr = find_msr_entry(vcpu, msr_index);
+               if (!msr) {
+                       printk(KERN_ERR "kvm: unhandled rdmsr: %x\n", msr_index);
+                       return 1;
+               }
+               data = msr->data;
+               break;
+       }
+
+       *pdata = data;
+       return 0;
+}
+
+/*
+ * Writes msr value into into the appropriate "register".
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+       struct vmx_msr_entry *msr;
+       switch (msr_index) {
+#ifdef __x86_64__
+       case MSR_FS_BASE:
+               vmcs_writel(GUEST_FS_BASE, data);
+               break;
+       case MSR_GS_BASE:
+               vmcs_writel(GUEST_GS_BASE, data);
+               break;
+#endif
+       case MSR_IA32_SYSENTER_CS:
+               vmcs_write32(GUEST_SYSENTER_CS, data);
+               break;
+       case MSR_IA32_SYSENTER_EIP:
+               vmcs_write32(GUEST_SYSENTER_EIP, data);
+               break;
+       case MSR_IA32_SYSENTER_ESP:
+               vmcs_write32(GUEST_SYSENTER_ESP, data);
+               break;
+#ifdef __x86_64
+       case MSR_EFER:
+               set_efer(vcpu, data);
+               break;
+       case MSR_IA32_MC0_STATUS:
+               printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n"
+                           , __FUNCTION__, data);
+               break;
+#endif
+       case MSR_IA32_TIME_STAMP_COUNTER: {
+               guest_write_tsc(data);
+               break;
+       }
+       case MSR_IA32_UCODE_REV:
+       case MSR_IA32_UCODE_WRITE:
+       case 0x200 ... 0x2ff: /* MTRRs */
+               break;
+       case MSR_IA32_APICBASE:
+               vcpu->apic_base = data;
+               break;
+       default:
+               msr = find_msr_entry(vcpu, msr_index);
+               if (!msr) {
+                       printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr_index);
+                       return 1;
+               }
+               msr->data = data;
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Sync the rsp and rip registers into the vcpu structure.  This allows
+ * registers to be accessed by indexing vcpu->regs.
+ */
+static void vcpu_load_rsp_rip(struct kvm_vcpu *vcpu)
+{
+       vcpu->regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
+       vcpu->rip = vmcs_readl(GUEST_RIP);
+}
+
+/*
+ * Syncs rsp and rip back into the vmcs.  Should be called after possible
+ * modification.
+ */
+static void vcpu_put_rsp_rip(struct kvm_vcpu *vcpu)
+{
+       vmcs_writel(GUEST_RSP, vcpu->regs[VCPU_REGS_RSP]);
+       vmcs_writel(GUEST_RIP, vcpu->rip);
+}
+
+static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
+{
+       unsigned long dr7 = 0x400;
+       u32 exception_bitmap;
+       int old_singlestep;
+
+       exception_bitmap = vmcs_read32(EXCEPTION_BITMAP);
+       old_singlestep = vcpu->guest_debug.singlestep;
+
+       vcpu->guest_debug.enabled = dbg->enabled;
+       if (vcpu->guest_debug.enabled) {
+               int i;
+
+               dr7 |= 0x200;  /* exact */
+               for (i = 0; i < 4; ++i) {
+                       if (!dbg->breakpoints[i].enabled)
+                               continue;
+                       vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
+                       dr7 |= 2 << (i*2);    /* global enable */
+                       dr7 |= 0 << (i*4+16); /* execution breakpoint */
+               }
+
+               exception_bitmap |= (1u << 1);  /* Trap debug exceptions */
+
+               vcpu->guest_debug.singlestep = dbg->singlestep;
+       } else {
+               exception_bitmap &= ~(1u << 1); /* Ignore debug exceptions */
+               vcpu->guest_debug.singlestep = 0;
+       }
+
+       if (old_singlestep && !vcpu->guest_debug.singlestep) {
+               unsigned long flags;
+
+               flags = vmcs_readl(GUEST_RFLAGS);
+               flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+               vmcs_writel(GUEST_RFLAGS, flags);
+       }
+
+       vmcs_write32(EXCEPTION_BITMAP, exception_bitmap);
+       vmcs_writel(GUEST_DR7, dr7);
+
+       return 0;
+}
+
+static __init int cpu_has_kvm_support(void)
+{
+       unsigned long ecx = cpuid_ecx(1);
+       return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
+}
+
+static __init int vmx_disabled_by_bios(void)
+{
+       u64 msr;
+
+       rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
+       return (msr & 5) == 1; /* locked but not enabled */
+}
+
+static __init void hardware_enable(void *garbage)
+{
+       int cpu = raw_smp_processor_id();
+       u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
+       u64 old;
+
+       rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
+       if ((old & 5) == 0)
+               /* enable and lock */
+               wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5);
+       write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */
+       asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr)
+                     : "memory", "cc");
+}
+
+static void hardware_disable(void *garbage)
+{
+       asm volatile (ASM_VMX_VMXOFF : : : "cc");
+}
+
+static __init void setup_vmcs_descriptor(void)
+{
+       u32 vmx_msr_low, vmx_msr_high;
+
+       rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
+       vmcs_descriptor.size = vmx_msr_high & 0x1fff;
+       vmcs_descriptor.order = get_order(vmcs_descriptor.size);
+       vmcs_descriptor.revision_id = vmx_msr_low;
+};
+
+static struct vmcs *alloc_vmcs_cpu(int cpu)
+{
+       int node = cpu_to_node(cpu);
+       struct page *pages;
+       struct vmcs *vmcs;
+
+       pages = alloc_pages_node(node, GFP_KERNEL, vmcs_descriptor.order);
+       if (!pages)
+               return NULL;
+       vmcs = page_address(pages);
+       memset(vmcs, 0, vmcs_descriptor.size);
+       vmcs->revision_id = vmcs_descriptor.revision_id; /* vmcs revision id */
+       return vmcs;
+}
+
+static struct vmcs *alloc_vmcs(void)
+{
+       return alloc_vmcs_cpu(smp_processor_id());
+}
+
+static void free_vmcs(struct vmcs *vmcs)
+{
+       free_pages((unsigned long)vmcs, vmcs_descriptor.order);
+}
+
+static __exit void free_kvm_area(void)
+{
+       int cpu;
+
+       for_each_online_cpu(cpu)
+               free_vmcs(per_cpu(vmxarea, cpu));
+}
+
+extern struct vmcs *alloc_vmcs_cpu(int cpu);
+
+static __init int alloc_kvm_area(void)
+{
+       int cpu;
+
+       for_each_online_cpu(cpu) {
+               struct vmcs *vmcs;
+
+               vmcs = alloc_vmcs_cpu(cpu);
+               if (!vmcs) {
+                       free_kvm_area();
+                       return -ENOMEM;
+               }
+
+               per_cpu(vmxarea, cpu) = vmcs;
+       }
+       return 0;
+}
+
+static __init int hardware_setup(void)
+{
+       setup_vmcs_descriptor();
+       return alloc_kvm_area();
+}
+
+static __exit void hardware_unsetup(void)
+{
+       free_kvm_area();
+}
+
+static void update_exception_bitmap(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->rmode.active)
+               vmcs_write32(EXCEPTION_BITMAP, ~0);
+       else
+               vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
+}
+
+static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+       if (vmcs_readl(sf->base) == save->base) {
+               vmcs_write16(sf->selector, save->selector);
+               vmcs_writel(sf->base, save->base);
+               vmcs_write32(sf->limit, save->limit);
+               vmcs_write32(sf->ar_bytes, save->ar);
+       } else {
+               u32 dpl = (vmcs_read16(sf->selector) & SELECTOR_RPL_MASK)
+                       << AR_DPL_SHIFT;
+               vmcs_write32(sf->ar_bytes, 0x93 | dpl);
+       }
+}
+
+static void enter_pmode(struct kvm_vcpu *vcpu)
+{
+       unsigned long flags;
+
+       vcpu->rmode.active = 0;
+
+       vmcs_writel(GUEST_TR_BASE, vcpu->rmode.tr.base);
+       vmcs_write32(GUEST_TR_LIMIT, vcpu->rmode.tr.limit);
+       vmcs_write32(GUEST_TR_AR_BYTES, vcpu->rmode.tr.ar);
+
+       flags = vmcs_readl(GUEST_RFLAGS);
+       flags &= ~(IOPL_MASK | X86_EFLAGS_VM);
+       flags |= (vcpu->rmode.save_iopl << IOPL_SHIFT);
+       vmcs_writel(GUEST_RFLAGS, flags);
+
+       vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~CR4_VME_MASK) |
+                       (vmcs_readl(CR4_READ_SHADOW) & CR4_VME_MASK));
+
+       update_exception_bitmap(vcpu);
+
+       fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->rmode.es);
+       fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->rmode.ds);
+       fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->rmode.gs);
+       fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->rmode.fs);
+
+       vmcs_write16(GUEST_SS_SELECTOR, 0);
+       vmcs_write32(GUEST_SS_AR_BYTES, 0x93);
+
+       vmcs_write16(GUEST_CS_SELECTOR,
+                    vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK);
+       vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
+}
+
+static int rmode_tss_base(struct kvm* kvm)
+{
+       gfn_t base_gfn = kvm->memslots[0].base_gfn + kvm->memslots[0].npages - 3;
+       return base_gfn << PAGE_SHIFT;
+}
+
+static void fix_rmode_seg(int seg, struct kvm_save_segment *save)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+       save->selector = vmcs_read16(sf->selector);
+       save->base = vmcs_readl(sf->base);
+       save->limit = vmcs_read32(sf->limit);
+       save->ar = vmcs_read32(sf->ar_bytes);
+       vmcs_write16(sf->selector, vmcs_readl(sf->base) >> 4);
+       vmcs_write32(sf->limit, 0xffff);
+       vmcs_write32(sf->ar_bytes, 0xf3);
+}
+
+static void enter_rmode(struct kvm_vcpu *vcpu)
+{
+       unsigned long flags;
+
+       vcpu->rmode.active = 1;
+
+       vcpu->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
+       vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
+
+       vcpu->rmode.tr.limit = vmcs_read32(GUEST_TR_LIMIT);
+       vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
+
+       vcpu->rmode.tr.ar = vmcs_read32(GUEST_TR_AR_BYTES);
+       vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+       flags = vmcs_readl(GUEST_RFLAGS);
+       vcpu->rmode.save_iopl = (flags & IOPL_MASK) >> IOPL_SHIFT;
+
+       flags |= IOPL_MASK | X86_EFLAGS_VM;
+
+       vmcs_writel(GUEST_RFLAGS, flags);
+       vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | CR4_VME_MASK);
+       update_exception_bitmap(vcpu);
+
+       vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
+       vmcs_write32(GUEST_SS_LIMIT, 0xffff);
+       vmcs_write32(GUEST_SS_AR_BYTES, 0xf3);
+
+       vmcs_write32(GUEST_CS_AR_BYTES, 0xf3);
+       vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4);
+
+       fix_rmode_seg(VCPU_SREG_ES, &vcpu->rmode.es);
+       fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds);
+       fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
+       fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
+}
+
+#ifdef __x86_64__
+
+static void enter_lmode(struct kvm_vcpu *vcpu)
+{
+       u32 guest_tr_ar;
+
+       guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
+       if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+               printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
+                      __FUNCTION__);
+               vmcs_write32(GUEST_TR_AR_BYTES,
+                            (guest_tr_ar & ~AR_TYPE_MASK)
+                            | AR_TYPE_BUSY_64_TSS);
+       }
+
+       vcpu->shadow_efer |= EFER_LMA;
+
+       find_msr_entry(vcpu, MSR_EFER)->data |= EFER_LMA | EFER_LME;
+       vmcs_write32(VM_ENTRY_CONTROLS,
+                    vmcs_read32(VM_ENTRY_CONTROLS)
+                    | VM_ENTRY_CONTROLS_IA32E_MASK);
+}
+
+static void exit_lmode(struct kvm_vcpu *vcpu)
+{
+       vcpu->shadow_efer &= ~EFER_LMA;
+
+       vmcs_write32(VM_ENTRY_CONTROLS,
+                    vmcs_read32(VM_ENTRY_CONTROLS)
+                    & ~VM_ENTRY_CONTROLS_IA32E_MASK);
+}
+
+#endif
+
+static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       if (vcpu->rmode.active && (cr0 & CR0_PE_MASK))
+               enter_pmode(vcpu);
+
+       if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
+               enter_rmode(vcpu);
+
+#ifdef __x86_64__
+       if (vcpu->shadow_efer & EFER_LME) {
+               if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK))
+                       enter_lmode(vcpu);
+               if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK))
+                       exit_lmode(vcpu);
+       }
+#endif
+
+       vmcs_writel(CR0_READ_SHADOW, cr0);
+       vmcs_writel(GUEST_CR0,
+                   (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
+       vcpu->cr0 = cr0;
+}
+
+/*
+ * Used when restoring the VM to avoid corrupting segment registers
+ */
+static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0);
+       update_exception_bitmap(vcpu);
+       vmcs_writel(CR0_READ_SHADOW, cr0);
+       vmcs_writel(GUEST_CR0,
+                   (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
+       vcpu->cr0 = cr0;
+}
+
+static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+       vmcs_writel(GUEST_CR3, cr3);
+}
+
+static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+       vmcs_writel(CR4_READ_SHADOW, cr4);
+       vmcs_writel(GUEST_CR4, cr4 | (vcpu->rmode.active ?
+                   KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON));
+       vcpu->cr4 = cr4;
+}
+
+#ifdef __x86_64__
+
+static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+       struct vmx_msr_entry *msr = find_msr_entry(vcpu, MSR_EFER);
+
+       vcpu->shadow_efer = efer;
+       if (efer & EFER_LMA) {
+               vmcs_write32(VM_ENTRY_CONTROLS,
+                                    vmcs_read32(VM_ENTRY_CONTROLS) |
+                                    VM_ENTRY_CONTROLS_IA32E_MASK);
+               msr->data = efer;
+
+       } else {
+               vmcs_write32(VM_ENTRY_CONTROLS,
+                                    vmcs_read32(VM_ENTRY_CONTROLS) &
+                                    ~VM_ENTRY_CONTROLS_IA32E_MASK);
+
+               msr->data = efer & ~EFER_LME;
+       }
+}
+
+#endif
+
+static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+       return vmcs_readl(sf->base);
+}
+
+static void vmx_get_segment(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+       u32 ar;
+
+       var->base = vmcs_readl(sf->base);
+       var->limit = vmcs_read32(sf->limit);
+       var->selector = vmcs_read16(sf->selector);
+       ar = vmcs_read32(sf->ar_bytes);
+       if (ar & AR_UNUSABLE_MASK)
+               ar = 0;
+       var->type = ar & 15;
+       var->s = (ar >> 4) & 1;
+       var->dpl = (ar >> 5) & 3;
+       var->present = (ar >> 7) & 1;
+       var->avl = (ar >> 12) & 1;
+       var->l = (ar >> 13) & 1;
+       var->db = (ar >> 14) & 1;
+       var->g = (ar >> 15) & 1;
+       var->unusable = (ar >> 16) & 1;
+}
+
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+       u32 ar;
+
+       vmcs_writel(sf->base, var->base);
+       vmcs_write32(sf->limit, var->limit);
+       vmcs_write16(sf->selector, var->selector);
+       if (var->unusable)
+               ar = 1 << 16;
+       else {
+               ar = var->type & 15;
+               ar |= (var->s & 1) << 4;
+               ar |= (var->dpl & 3) << 5;
+               ar |= (var->present & 1) << 7;
+               ar |= (var->avl & 1) << 12;
+               ar |= (var->l & 1) << 13;
+               ar |= (var->db & 1) << 14;
+               ar |= (var->g & 1) << 15;
+       }
+       vmcs_write32(sf->ar_bytes, ar);
+}
+
+static int vmx_is_long_mode(struct kvm_vcpu *vcpu)
+{
+       return vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_CONTROLS_IA32E_MASK;
+}
+
+static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+{
+       u32 ar = vmcs_read32(GUEST_CS_AR_BYTES);
+
+       *db = (ar >> 14) & 1;
+       *l = (ar >> 13) & 1;
+}
+
+static void vmx_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       dt->limit = vmcs_read32(GUEST_IDTR_LIMIT);
+       dt->base = vmcs_readl(GUEST_IDTR_BASE);
+}
+
+static void vmx_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       vmcs_write32(GUEST_IDTR_LIMIT, dt->limit);
+       vmcs_writel(GUEST_IDTR_BASE, dt->base);
+}
+
+static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       dt->limit = vmcs_read32(GUEST_GDTR_LIMIT);
+       dt->base = vmcs_readl(GUEST_GDTR_BASE);
+}
+
+static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+       vmcs_write32(GUEST_GDTR_LIMIT, dt->limit);
+       vmcs_writel(GUEST_GDTR_BASE, dt->base);
+}
+
+static int init_rmode_tss(struct kvm* kvm)
+{
+       struct page *p1, *p2, *p3;
+       gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
+       char *page;
+
+       p1 = _gfn_to_page(kvm, fn++);
+       p2 = _gfn_to_page(kvm, fn++);
+       p3 = _gfn_to_page(kvm, fn);
+
+       if (!p1 || !p2 || !p3) {
+               kvm_printf(kvm,"%s: gfn_to_page failed\n", __FUNCTION__);
+               return 0;
+       }
+
+       page = kmap_atomic(p1, KM_USER0);
+       memset(page, 0, PAGE_SIZE);
+       *(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
+       kunmap_atomic(page, KM_USER0);
+
+       page = kmap_atomic(p2, KM_USER0);
+       memset(page, 0, PAGE_SIZE);
+       kunmap_atomic(page, KM_USER0);
+
+       page = kmap_atomic(p3, KM_USER0);
+       memset(page, 0, PAGE_SIZE);
+       *(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0;
+       kunmap_atomic(page, KM_USER0);
+
+       return 1;
+}
+
+static void vmcs_write32_fixedbits(u32 msr, u32 vmcs_field, u32 val)
+{
+       u32 msr_high, msr_low;
+
+       rdmsr(msr, msr_low, msr_high);
+
+       val &= msr_high;
+       val |= msr_low;
+       vmcs_write32(vmcs_field, val);
+}
+
+static void seg_setup(int seg)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+       vmcs_write16(sf->selector, 0);
+       vmcs_writel(sf->base, 0);
+       vmcs_write32(sf->limit, 0xffff);
+       vmcs_write32(sf->ar_bytes, 0x93);
+}
+
+/*
+ * Sets up the vmcs for emulated real mode.
+ */
+static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       u32 host_sysenter_cs;
+       u32 junk;
+       unsigned long a;
+       struct descriptor_table dt;
+       int i;
+       int ret = 0;
+       int nr_good_msrs;
+       extern asmlinkage void kvm_vmx_return(void);
+
+       if (!init_rmode_tss(vcpu->kvm)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memset(vcpu->regs, 0, sizeof(vcpu->regs));
+       vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val();
+       vcpu->cr8 = 0;
+       vcpu->apic_base = 0xfee00000 |
+                       /*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
+                       MSR_IA32_APICBASE_ENABLE;
+
+       fx_init(vcpu);
+
+       /*
+        * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
+        * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4.  Sigh.
+        */
+       vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
+       vmcs_writel(GUEST_CS_BASE, 0x000f0000);
+       vmcs_write32(GUEST_CS_LIMIT, 0xffff);
+       vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
+
+       seg_setup(VCPU_SREG_DS);
+       seg_setup(VCPU_SREG_ES);
+       seg_setup(VCPU_SREG_FS);
+       seg_setup(VCPU_SREG_GS);
+       seg_setup(VCPU_SREG_SS);
+
+       vmcs_write16(GUEST_TR_SELECTOR, 0);
+       vmcs_writel(GUEST_TR_BASE, 0);
+       vmcs_write32(GUEST_TR_LIMIT, 0xffff);
+       vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+       vmcs_write16(GUEST_LDTR_SELECTOR, 0);
+       vmcs_writel(GUEST_LDTR_BASE, 0);
+       vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
+       vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
+
+       vmcs_write32(GUEST_SYSENTER_CS, 0);
+       vmcs_writel(GUEST_SYSENTER_ESP, 0);
+       vmcs_writel(GUEST_SYSENTER_EIP, 0);
+
+       vmcs_writel(GUEST_RFLAGS, 0x02);
+       vmcs_writel(GUEST_RIP, 0xfff0);
+       vmcs_writel(GUEST_RSP, 0);
+
+       vmcs_writel(GUEST_CR3, 0);
+
+       //todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0
+       vmcs_writel(GUEST_DR7, 0x400);
+
+       vmcs_writel(GUEST_GDTR_BASE, 0);
+       vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
+
+       vmcs_writel(GUEST_IDTR_BASE, 0);
+       vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
+
+       vmcs_write32(GUEST_ACTIVITY_STATE, 0);
+       vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
+       vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
+
+       /* I/O */
+       vmcs_write64(IO_BITMAP_A, 0);
+       vmcs_write64(IO_BITMAP_B, 0);
+
+       guest_write_tsc(0);
+
+       vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
+
+       /* Special registers */
+       vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+
+       /* Control */
+       vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS_MSR,
+                              PIN_BASED_VM_EXEC_CONTROL,
+                              PIN_BASED_EXT_INTR_MASK   /* 20.6.1 */
+                              | PIN_BASED_NMI_EXITING   /* 20.6.1 */
+                       );
+       vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS_MSR,
+                              CPU_BASED_VM_EXEC_CONTROL,
+                              CPU_BASED_HLT_EXITING         /* 20.6.2 */
+                              | CPU_BASED_CR8_LOAD_EXITING    /* 20.6.2 */
+                              | CPU_BASED_CR8_STORE_EXITING   /* 20.6.2 */
+                              | CPU_BASED_UNCOND_IO_EXITING   /* 20.6.2 */
+                              | CPU_BASED_INVDPG_EXITING
+                              | CPU_BASED_MOV_DR_EXITING
+                              | CPU_BASED_USE_TSC_OFFSETING   /* 21.3 */
+                       );
+
+       vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
+       vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
+       vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
+       vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
+
+       vmcs_writel(HOST_CR0, read_cr0());  /* 22.2.3 */
+       vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
+       vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
+
+       vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
+       vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+       vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+       vmcs_write16(HOST_FS_SELECTOR, read_fs());    /* 22.2.4 */
+       vmcs_write16(HOST_GS_SELECTOR, read_gs());    /* 22.2.4 */
+       vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+#ifdef __x86_64__
+       rdmsrl(MSR_FS_BASE, a);
+       vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
+       rdmsrl(MSR_GS_BASE, a);
+       vmcs_writel(HOST_GS_BASE, a); /* 22.2.4 */
+#else
+       vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */
+       vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
+#endif
+
+       vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8);  /* 22.2.4 */
+
+       get_idt(&dt);
+       vmcs_writel(HOST_IDTR_BASE, dt.base);   /* 22.2.4 */
+
+
+       vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); /* 22.2.5 */
+
+       rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
+       vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
+       rdmsrl(MSR_IA32_SYSENTER_ESP, a);
+       vmcs_writel(HOST_IA32_SYSENTER_ESP, a);   /* 22.2.3 */
+       rdmsrl(MSR_IA32_SYSENTER_EIP, a);
+       vmcs_writel(HOST_IA32_SYSENTER_EIP, a);   /* 22.2.3 */
+
+       ret = -ENOMEM;
+       vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!vcpu->guest_msrs)
+               goto out;
+       vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!vcpu->host_msrs)
+               goto out_free_guest_msrs;
+
+       for (i = 0; i < NR_VMX_MSR; ++i) {
+               u32 index = vmx_msr_index[i];
+               u32 data_low, data_high;
+               u64 data;
+               int j = vcpu->nmsrs;
+
+               if (rdmsr_safe(index, &data_low, &data_high) < 0)
+                       continue;
+               data = data_low | ((u64)data_high << 32);
+               vcpu->host_msrs[j].index = index;
+               vcpu->host_msrs[j].reserved = 0;
+               vcpu->host_msrs[j].data = data;
+               vcpu->guest_msrs[j] = vcpu->host_msrs[j];
+               ++vcpu->nmsrs;
+       }
+       printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs);
+
+       nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS;
+       vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
+                   virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+       vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
+                   virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+       vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
+                   virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS));
+       vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS_MSR, VM_EXIT_CONTROLS,
+                              (HOST_IS_64 << 9));  /* 22.2,1, 20.7.1 */
+       vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
+       vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs);  /* 22.2.2 */
+       vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+
+
+       /* 22.2.1, 20.8.1 */
+       vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS_MSR,
+                               VM_ENTRY_CONTROLS, 0);
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);  /* 22.2.1 */
+
+       vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0);
+       vmcs_writel(TPR_THRESHOLD, 0);
+
+       vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
+       vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
+
+       vcpu->cr0 = 0x60000010;
+       vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode
+       vmx_set_cr4(vcpu, 0);
+#ifdef __x86_64__
+       vmx_set_efer(vcpu, 0);
+#endif
+
+       return 0;
+
+out_free_guest_msrs:
+       kfree(vcpu->guest_msrs);
+out:
+       return ret;
+}
+
+static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)
+{
+       u16 ent[2];
+       u16 cs;
+       u16 ip;
+       unsigned long flags;
+       unsigned long ss_base = vmcs_readl(GUEST_SS_BASE);
+       u16 sp =  vmcs_readl(GUEST_RSP);
+       u32 ss_limit = vmcs_read32(GUEST_SS_LIMIT);
+
+       if (sp > ss_limit || sp - 6 > sp) {
+               vcpu_printf(vcpu, "%s: #SS, rsp 0x%lx ss 0x%lx limit 0x%x\n",
+                           __FUNCTION__,
+                           vmcs_readl(GUEST_RSP),
+                           vmcs_readl(GUEST_SS_BASE),
+                           vmcs_read32(GUEST_SS_LIMIT));
+               return;
+       }
+
+       if (kvm_read_guest(vcpu, irq * sizeof(ent), sizeof(ent), &ent) !=
+                                                               sizeof(ent)) {
+               vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__);
+               return;
+       }
+
+       flags =  vmcs_readl(GUEST_RFLAGS);
+       cs =  vmcs_readl(GUEST_CS_BASE) >> 4;
+       ip =  vmcs_readl(GUEST_RIP);
+
+
+       if (kvm_write_guest(vcpu, ss_base + sp - 2, 2, &flags) != 2 ||
+           kvm_write_guest(vcpu, ss_base + sp - 4, 2, &cs) != 2 ||
+           kvm_write_guest(vcpu, ss_base + sp - 6, 2, &ip) != 2) {
+               vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__);
+               return;
+       }
+
+       vmcs_writel(GUEST_RFLAGS, flags &
+                   ~( X86_EFLAGS_IF | X86_EFLAGS_AC | X86_EFLAGS_TF));
+       vmcs_write16(GUEST_CS_SELECTOR, ent[1]) ;
+       vmcs_writel(GUEST_CS_BASE, ent[1] << 4);
+       vmcs_writel(GUEST_RIP, ent[0]);
+       vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6));
+}
+
+static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
+{
+       int word_index = __ffs(vcpu->irq_summary);
+       int bit_index = __ffs(vcpu->irq_pending[word_index]);
+       int irq = word_index * BITS_PER_LONG + bit_index;
+
+       clear_bit(bit_index, &vcpu->irq_pending[word_index]);
+       if (!vcpu->irq_pending[word_index])
+               clear_bit(word_index, &vcpu->irq_summary);
+
+       if (vcpu->rmode.active) {
+               inject_rmode_irq(vcpu, irq);
+               return;
+       }
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                       irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+}
+
+static void kvm_try_inject_irq(struct kvm_vcpu *vcpu)
+{
+       if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)
+           && (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0)
+               /*
+                * Interrupts enabled, and not blocked by sti or mov ss. Good.
+                */
+               kvm_do_inject_irq(vcpu);
+       else
+               /*
+                * Interrupts blocked.  Wait for unblock.
+                */
+               vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
+                            vmcs_read32(CPU_BASED_VM_EXEC_CONTROL)
+                            | CPU_BASED_VIRTUAL_INTR_PENDING);
+}
+
+static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu)
+{
+       struct kvm_guest_debug *dbg = &vcpu->guest_debug;
+
+       set_debugreg(dbg->bp[0], 0);
+       set_debugreg(dbg->bp[1], 1);
+       set_debugreg(dbg->bp[2], 2);
+       set_debugreg(dbg->bp[3], 3);
+
+       if (dbg->singlestep) {
+               unsigned long flags;
+
+               flags = vmcs_readl(GUEST_RFLAGS);
+               flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
+               vmcs_writel(GUEST_RFLAGS, flags);
+       }
+}
+
+static int handle_rmode_exception(struct kvm_vcpu *vcpu,
+                                 int vec, u32 err_code)
+{
+       if (!vcpu->rmode.active)
+               return 0;
+
+       if (vec == GP_VECTOR && err_code == 0)
+               if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE)
+                       return 1;
+       return 0;
+}
+
+static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 intr_info, error_code;
+       unsigned long cr2, rip;
+       u32 vect_info;
+       enum emulation_result er;
+
+       vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+       intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+       if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+                                               !is_page_fault(intr_info)) {
+               printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
+                      "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info);
+       }
+
+       if (is_external_interrupt(vect_info)) {
+               int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
+               set_bit(irq, vcpu->irq_pending);
+               set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
+       }
+
+       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
+               asm ("int $2");
+               return 1;
+       }
+       error_code = 0;
+       rip = vmcs_readl(GUEST_RIP);
+       if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
+               error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+       if (is_page_fault(intr_info)) {
+               cr2 = vmcs_readl(EXIT_QUALIFICATION);
+
+               spin_lock(&vcpu->kvm->lock);
+               if (!vcpu->mmu.page_fault(vcpu, cr2, error_code)) {
+                       spin_unlock(&vcpu->kvm->lock);
+                       return 1;
+               }
+
+               er = emulate_instruction(vcpu, kvm_run, cr2, error_code);
+               spin_unlock(&vcpu->kvm->lock);
+
+               switch (er) {
+               case EMULATE_DONE:
+                       return 1;
+               case EMULATE_DO_MMIO:
+                       ++kvm_stat.mmio_exits;
+                       kvm_run->exit_reason = KVM_EXIT_MMIO;
+                       return 0;
+                case EMULATE_FAIL:
+                       vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       if (vcpu->rmode.active &&
+           handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
+                                                               error_code))
+               return 1;
+
+       if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) {
+               kvm_run->exit_reason = KVM_EXIT_DEBUG;
+               return 0;
+       }
+       kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
+       kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK;
+       kvm_run->ex.error_code = error_code;
+       return 0;
+}
+
+static int handle_external_interrupt(struct kvm_vcpu *vcpu,
+                                    struct kvm_run *kvm_run)
+{
+       ++kvm_stat.irq_exits;
+       return 1;
+}
+
+
+static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
+{
+       u64 inst;
+       gva_t rip;
+       int countr_size;
+       int i, n;
+
+       if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) {
+               countr_size = 2;
+       } else {
+               u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
+
+               countr_size = (cs_ar & AR_L_MASK) ? 8:
+                             (cs_ar & AR_DB_MASK) ? 4: 2;
+       }
+
+       rip =  vmcs_readl(GUEST_RIP);
+       if (countr_size != 8)
+               rip += vmcs_readl(GUEST_CS_BASE);
+
+       n = kvm_read_guest(vcpu, rip, sizeof(inst), &inst);
+
+       for (i = 0; i < n; i++) {
+               switch (((u8*)&inst)[i]) {
+               case 0xf0:
+               case 0xf2:
+               case 0xf3:
+               case 0x2e:
+               case 0x36:
+               case 0x3e:
+               case 0x26:
+               case 0x64:
+               case 0x65:
+               case 0x66:
+                       break;
+               case 0x67:
+                       countr_size = (countr_size == 2) ? 4: (countr_size >> 1);
+               default:
+                       goto done;
+               }
+       }
+       return 0;
+done:
+       countr_size *= 8;
+       *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
+       return 1;
+}
+
+static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u64 exit_qualification;
+
+       ++kvm_stat.io_exits;
+       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       kvm_run->exit_reason = KVM_EXIT_IO;
+       if (exit_qualification & 8)
+               kvm_run->io.direction = KVM_EXIT_IO_IN;
+       else
+               kvm_run->io.direction = KVM_EXIT_IO_OUT;
+       kvm_run->io.size = (exit_qualification & 7) + 1;
+       kvm_run->io.string = (exit_qualification & 16) != 0;
+       kvm_run->io.string_down
+               = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
+       kvm_run->io.rep = (exit_qualification & 32) != 0;
+       kvm_run->io.port = exit_qualification >> 16;
+       if (kvm_run->io.string) {
+               if (!get_io_count(vcpu, &kvm_run->io.count))
+                       return 1;
+               kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS);
+       } else
+               kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */
+       return 0;
+}
+
+static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u64 address = vmcs_read64(EXIT_QUALIFICATION);
+       int instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+       spin_lock(&vcpu->kvm->lock);
+       vcpu->mmu.inval_page(vcpu, address);
+       spin_unlock(&vcpu->kvm->lock);
+       vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP) + instruction_length);
+       return 1;
+}
+
+static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u64 exit_qualification;
+       int cr;
+       int reg;
+
+       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       cr = exit_qualification & 15;
+       reg = (exit_qualification >> 8) & 15;
+       switch ((exit_qualification >> 4) & 3) {
+       case 0: /* mov to cr */
+               switch (cr) {
+               case 0:
+                       vcpu_load_rsp_rip(vcpu);
+                       set_cr0(vcpu, vcpu->regs[reg]);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               case 3:
+                       vcpu_load_rsp_rip(vcpu);
+                       set_cr3(vcpu, vcpu->regs[reg]);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               case 4:
+                       vcpu_load_rsp_rip(vcpu);
+                       set_cr4(vcpu, vcpu->regs[reg]);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               case 8:
+                       vcpu_load_rsp_rip(vcpu);
+                       set_cr8(vcpu, vcpu->regs[reg]);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               };
+               break;
+       case 1: /*mov from cr*/
+               switch (cr) {
+               case 3:
+                       vcpu_load_rsp_rip(vcpu);
+                       vcpu->regs[reg] = vcpu->cr3;
+                       vcpu_put_rsp_rip(vcpu);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               case 8:
+                       printk(KERN_DEBUG "handle_cr: read CR8 "
+                              "cpu erratum AA15\n");
+                       vcpu_load_rsp_rip(vcpu);
+                       vcpu->regs[reg] = vcpu->cr8;
+                       vcpu_put_rsp_rip(vcpu);
+                       skip_emulated_instruction(vcpu);
+                       return 1;
+               }
+               break;
+       case 3: /* lmsw */
+               lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
+
+               skip_emulated_instruction(vcpu);
+               return 1;
+       default:
+               break;
+       }
+       kvm_run->exit_reason = 0;
+       printk(KERN_ERR "kvm: unhandled control register: op %d cr %d\n",
+              (int)(exit_qualification >> 4) & 3, cr);
+       return 0;
+}
+
+static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u64 exit_qualification;
+       unsigned long val;
+       int dr, reg;
+
+       /*
+        * FIXME: this code assumes the host is debugging the guest.
+        *        need to deal with guest debugging itself too.
+        */
+       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       dr = exit_qualification & 7;
+       reg = (exit_qualification >> 8) & 15;
+       vcpu_load_rsp_rip(vcpu);
+       if (exit_qualification & 16) {
+               /* mov from dr */
+               switch (dr) {
+               case 6:
+                       val = 0xffff0ff0;
+                       break;
+               case 7:
+                       val = 0x400;
+                       break;
+               default:
+                       val = 0;
+               }
+               vcpu->regs[reg] = val;
+       } else {
+               /* mov to dr */
+       }
+       vcpu_put_rsp_rip(vcpu);
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
+static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       kvm_run->exit_reason = KVM_EXIT_CPUID;
+       return 0;
+}
+
+static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+       u64 data;
+
+       if (vmx_get_msr(vcpu, ecx, &data)) {
+               vmx_inject_gp(vcpu, 0);
+               return 1;
+       }
+
+       /* FIXME: handling of bits 32:63 of rax, rdx */
+       vcpu->regs[VCPU_REGS_RAX] = data & -1u;
+       vcpu->regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
+static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+       u64 data = (vcpu->regs[VCPU_REGS_RAX] & -1u)
+               | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32);
+
+       if (vmx_set_msr(vcpu, ecx, data) != 0) {
+               vmx_inject_gp(vcpu, 0);
+               return 1;
+       }
+
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
+static int handle_interrupt_window(struct kvm_vcpu *vcpu,
+                                  struct kvm_run *kvm_run)
+{
+       /* Turn off interrupt window reporting. */
+       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
+                    vmcs_read32(CPU_BASED_VM_EXEC_CONTROL)
+                    & ~CPU_BASED_VIRTUAL_INTR_PENDING);
+       return 1;
+}
+
+static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       skip_emulated_instruction(vcpu);
+       if (vcpu->irq_summary && (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF))
+               return 1;
+
+       kvm_run->exit_reason = KVM_EXIT_HLT;
+       return 0;
+}
+
+/*
+ * The exit handlers return 1 if the exit was handled fully and guest execution
+ * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
+ * to be done to userspace and return 0.
+ */
+static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
+                                     struct kvm_run *kvm_run) = {
+       [EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
+       [EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
+       [EXIT_REASON_IO_INSTRUCTION]          = handle_io,
+       [EXIT_REASON_INVLPG]                  = handle_invlpg,
+       [EXIT_REASON_CR_ACCESS]               = handle_cr,
+       [EXIT_REASON_DR_ACCESS]               = handle_dr,
+       [EXIT_REASON_CPUID]                   = handle_cpuid,
+       [EXIT_REASON_MSR_READ]                = handle_rdmsr,
+       [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
+       [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
+       [EXIT_REASON_HLT]                     = handle_halt,
+};
+
+static const int kvm_vmx_max_exit_handlers =
+       sizeof(kvm_vmx_exit_handlers) / sizeof(*kvm_vmx_exit_handlers);
+
+/*
+ * The guest has exited.  See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+       u32 vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+       u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
+
+       if ( (vectoring_info & VECTORING_INFO_VALID_MASK) &&
+                               exit_reason != EXIT_REASON_EXCEPTION_NMI )
+               printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
+                      "exit reason is 0x%x\n", __FUNCTION__, exit_reason);
+       kvm_run->instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+       if (exit_reason < kvm_vmx_max_exit_handlers
+           && kvm_vmx_exit_handlers[exit_reason])
+               return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
+       else {
+               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+               kvm_run->hw.hardware_exit_reason = exit_reason;
+       }
+       return 0;
+}
+
+static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u8 fail;
+       u16 fs_sel, gs_sel, ldt_sel;
+       int fs_gs_ldt_reload_needed;
+
+again:
+       /*
+        * Set host fs and gs selectors.  Unfortunately, 22.2.3 does not
+        * allow segment selectors with cpl > 0 or ti == 1.
+        */
+       fs_sel = read_fs();
+       gs_sel = read_gs();
+       ldt_sel = read_ldt();
+       fs_gs_ldt_reload_needed = (fs_sel & 7) | (gs_sel & 7) | ldt_sel;
+       if (!fs_gs_ldt_reload_needed) {
+               vmcs_write16(HOST_FS_SELECTOR, fs_sel);
+               vmcs_write16(HOST_GS_SELECTOR, gs_sel);
+       } else {
+               vmcs_write16(HOST_FS_SELECTOR, 0);
+               vmcs_write16(HOST_GS_SELECTOR, 0);
+       }
+
+#ifdef __x86_64__
+       vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
+       vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
+#else
+       vmcs_writel(HOST_FS_BASE, segment_base(fs_sel));
+       vmcs_writel(HOST_GS_BASE, segment_base(gs_sel));
+#endif
+
+       if (vcpu->irq_summary &&
+           !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK))
+               kvm_try_inject_irq(vcpu);
+
+       if (vcpu->guest_debug.enabled)
+               kvm_guest_debug_pre(vcpu);
+
+       fx_save(vcpu->host_fx_image);
+       fx_restore(vcpu->guest_fx_image);
+
+       save_msrs(vcpu->host_msrs, vcpu->nmsrs);
+       load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+
+       asm (
+               /* Store host registers */
+               "pushf \n\t"
+#ifdef __x86_64__
+               "push %%rax; push %%rbx; push %%rdx;"
+               "push %%rsi; push %%rdi; push %%rbp;"
+               "push %%r8;  push %%r9;  push %%r10; push %%r11;"
+               "push %%r12; push %%r13; push %%r14; push %%r15;"
+               "push %%rcx \n\t"
+               ASM_VMX_VMWRITE_RSP_RDX "\n\t"
+#else
+               "pusha; push %%ecx \n\t"
+               ASM_VMX_VMWRITE_RSP_RDX "\n\t"
+#endif
+               /* Check if vmlaunch of vmresume is needed */
+               "cmp $0, %1 \n\t"
+               /* Load guest registers.  Don't clobber flags. */
+#ifdef __x86_64__
+               "mov %c[cr2](%3), %%rax \n\t"
+               "mov %%rax, %%cr2 \n\t"
+               "mov %c[rax](%3), %%rax \n\t"
+               "mov %c[rbx](%3), %%rbx \n\t"
+               "mov %c[rdx](%3), %%rdx \n\t"
+               "mov %c[rsi](%3), %%rsi \n\t"
+               "mov %c[rdi](%3), %%rdi \n\t"
+               "mov %c[rbp](%3), %%rbp \n\t"
+               "mov %c[r8](%3),  %%r8  \n\t"
+               "mov %c[r9](%3),  %%r9  \n\t"
+               "mov %c[r10](%3), %%r10 \n\t"
+               "mov %c[r11](%3), %%r11 \n\t"
+               "mov %c[r12](%3), %%r12 \n\t"
+               "mov %c[r13](%3), %%r13 \n\t"
+               "mov %c[r14](%3), %%r14 \n\t"
+               "mov %c[r15](%3), %%r15 \n\t"
+               "mov %c[rcx](%3), %%rcx \n\t" /* kills %3 (rcx) */
+#else
+               "mov %c[cr2](%3), %%eax \n\t"
+               "mov %%eax,   %%cr2 \n\t"
+               "mov %c[rax](%3), %%eax \n\t"
+               "mov %c[rbx](%3), %%ebx \n\t"
+               "mov %c[rdx](%3), %%edx \n\t"
+               "mov %c[rsi](%3), %%esi \n\t"
+               "mov %c[rdi](%3), %%edi \n\t"
+               "mov %c[rbp](%3), %%ebp \n\t"
+               "mov %c[rcx](%3), %%ecx \n\t" /* kills %3 (ecx) */
+#endif
+               /* Enter guest mode */
+               "jne launched \n\t"
+               ASM_VMX_VMLAUNCH "\n\t"
+               "jmp kvm_vmx_return \n\t"
+               "launched: " ASM_VMX_VMRESUME "\n\t"
+               ".globl kvm_vmx_return \n\t"
+               "kvm_vmx_return: "
+               /* Save guest registers, load host registers, keep flags */
+#ifdef __x86_64__
+               "xchg %3,     0(%%rsp) \n\t"
+               "mov %%rax, %c[rax](%3) \n\t"
+               "mov %%rbx, %c[rbx](%3) \n\t"
+               "pushq 0(%%rsp); popq %c[rcx](%3) \n\t"
+               "mov %%rdx, %c[rdx](%3) \n\t"
+               "mov %%rsi, %c[rsi](%3) \n\t"
+               "mov %%rdi, %c[rdi](%3) \n\t"
+               "mov %%rbp, %c[rbp](%3) \n\t"
+               "mov %%r8,  %c[r8](%3) \n\t"
+               "mov %%r9,  %c[r9](%3) \n\t"
+               "mov %%r10, %c[r10](%3) \n\t"
+               "mov %%r11, %c[r11](%3) \n\t"
+               "mov %%r12, %c[r12](%3) \n\t"
+               "mov %%r13, %c[r13](%3) \n\t"
+               "mov %%r14, %c[r14](%3) \n\t"
+               "mov %%r15, %c[r15](%3) \n\t"
+               "mov %%cr2, %%rax   \n\t"
+               "mov %%rax, %c[cr2](%3) \n\t"
+               "mov 0(%%rsp), %3 \n\t"
+
+               "pop  %%rcx; pop  %%r15; pop  %%r14; pop  %%r13; pop  %%r12;"
+               "pop  %%r11; pop  %%r10; pop  %%r9;  pop  %%r8;"
+               "pop  %%rbp; pop  %%rdi; pop  %%rsi;"
+               "pop  %%rdx; pop  %%rbx; pop  %%rax \n\t"
+#else
+               "xchg %3, 0(%%esp) \n\t"
+               "mov %%eax, %c[rax](%3) \n\t"
+               "mov %%ebx, %c[rbx](%3) \n\t"
+               "pushl 0(%%esp); popl %c[rcx](%3) \n\t"
+               "mov %%edx, %c[rdx](%3) \n\t"
+               "mov %%esi, %c[rsi](%3) \n\t"
+               "mov %%edi, %c[rdi](%3) \n\t"
+               "mov %%ebp, %c[rbp](%3) \n\t"
+               "mov %%cr2, %%eax  \n\t"
+               "mov %%eax, %c[cr2](%3) \n\t"
+               "mov 0(%%esp), %3 \n\t"
+
+               "pop %%ecx; popa \n\t"
+#endif
+               "setbe %0 \n\t"
+               "popf \n\t"
+             : "=g" (fail)
+             : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP),
+               "c"(vcpu),
+               [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])),
+               [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])),
+               [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])),
+               [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])),
+               [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
+               [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
+               [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])),
+#ifdef __x86_64__
+               [r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
+               [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
+               [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
+               [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])),
+               [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])),
+               [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])),
+               [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])),
+               [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])),
+#endif
+               [cr2]"i"(offsetof(struct kvm_vcpu, cr2))
+             : "cc", "memory" );
+
+       ++kvm_stat.exits;
+
+       save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+       load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
+
+       fx_save(vcpu->guest_fx_image);
+       fx_restore(vcpu->host_fx_image);
+
+#ifndef __x86_64__
+       asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
+#endif
+
+       kvm_run->exit_type = 0;
+       if (fail) {
+               kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
+               kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR);
+       } else {
+               if (fs_gs_ldt_reload_needed) {
+                       load_ldt(ldt_sel);
+                       load_fs(fs_sel);
+                       /*
+                        * If we have to reload gs, we must take care to
+                        * preserve our gs base.
+                        */
+                       local_irq_disable();
+                       load_gs(gs_sel);
+#ifdef __x86_64__
+                       wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+#endif
+                       local_irq_enable();
+
+                       reload_tss();
+               }
+               vcpu->launched = 1;
+               kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
+               if (kvm_handle_exit(kvm_run, vcpu)) {
+                       /* Give scheduler a change to reschedule. */
+                       if (signal_pending(current)) {
+                               ++kvm_stat.signal_exits;
+                               return -EINTR;
+                       }
+                       kvm_resched(vcpu);
+                       goto again;
+               }
+       }
+       return 0;
+}
+
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3));
+}
+
+static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
+                                 unsigned long addr,
+                                 u32 err_code)
+{
+       u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+
+       ++kvm_stat.pf_guest;
+
+       if (is_page_fault(vect_info)) {
+               printk(KERN_DEBUG "inject_page_fault: "
+                      "double fault 0x%lx @ 0x%lx\n",
+                      addr, vmcs_readl(GUEST_RIP));
+               vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0);
+               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                            DF_VECTOR |
+                            INTR_TYPE_EXCEPTION |
+                            INTR_INFO_DELIEVER_CODE_MASK |
+                            INTR_INFO_VALID_MASK);
+               return;
+       }
+       vcpu->cr2 = addr;
+       vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code);
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                    PF_VECTOR |
+                    INTR_TYPE_EXCEPTION |
+                    INTR_INFO_DELIEVER_CODE_MASK |
+                    INTR_INFO_VALID_MASK);
+
+}
+
+static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->vmcs) {
+               on_each_cpu(__vcpu_clear, vcpu, 0, 1);
+               free_vmcs(vcpu->vmcs);
+               vcpu->vmcs = NULL;
+       }
+}
+
+static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
+{
+       vmx_free_vmcs(vcpu);
+}
+
+static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
+{
+       struct vmcs *vmcs;
+
+       vmcs = alloc_vmcs();
+       if (!vmcs)
+               return -ENOMEM;
+       vmcs_clear(vmcs);
+       vcpu->vmcs = vmcs;
+       vcpu->launched = 0;
+       return 0;
+}
+
+static struct kvm_arch_ops vmx_arch_ops = {
+       .cpu_has_kvm_support = cpu_has_kvm_support,
+       .disabled_by_bios = vmx_disabled_by_bios,
+       .hardware_setup = hardware_setup,
+       .hardware_unsetup = hardware_unsetup,
+       .hardware_enable = hardware_enable,
+       .hardware_disable = hardware_disable,
+
+       .vcpu_create = vmx_create_vcpu,
+       .vcpu_free = vmx_free_vcpu,
+
+       .vcpu_load = vmx_vcpu_load,
+       .vcpu_put = vmx_vcpu_put,
+
+       .set_guest_debug = set_guest_debug,
+       .get_msr = vmx_get_msr,
+       .set_msr = vmx_set_msr,
+       .get_segment_base = vmx_get_segment_base,
+       .get_segment = vmx_get_segment,
+       .set_segment = vmx_set_segment,
+       .is_long_mode = vmx_is_long_mode,
+       .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+       .set_cr0 = vmx_set_cr0,
+       .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch,
+       .set_cr3 = vmx_set_cr3,
+       .set_cr4 = vmx_set_cr4,
+#ifdef __x86_64__
+       .set_efer = vmx_set_efer,
+#endif
+       .get_idt = vmx_get_idt,
+       .set_idt = vmx_set_idt,
+       .get_gdt = vmx_get_gdt,
+       .set_gdt = vmx_set_gdt,
+       .cache_regs = vcpu_load_rsp_rip,
+       .decache_regs = vcpu_put_rsp_rip,
+       .get_rflags = vmx_get_rflags,
+       .set_rflags = vmx_set_rflags,
+
+       .tlb_flush = vmx_flush_tlb,
+       .inject_page_fault = vmx_inject_page_fault,
+
+       .inject_gp = vmx_inject_gp,
+
+       .run = vmx_vcpu_run,
+       .skip_emulated_instruction = skip_emulated_instruction,
+       .vcpu_setup = vmx_vcpu_setup,
+};
+
+static int __init vmx_init(void)
+{
+       kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
+       return 0;
+}
+
+static void __exit vmx_exit(void)
+{
+       kvm_exit_arch();
+}
+
+module_init(vmx_init)
+module_exit(vmx_exit)
diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h
new file mode 100644 (file)
index 0000000..7972783
--- /dev/null
@@ -0,0 +1,296 @@
+#ifndef VMX_H
+#define VMX_H
+
+/*
+ * vmx.h: VMX Architecture related definitions
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * A few random additions are:
+ * Copyright (C) 2006 Qumranet
+ *    Avi Kivity <avi@qumranet.com>
+ *    Yaniv Kamay <yaniv@qumranet.com>
+ *
+ */
+
+#define CPU_BASED_VIRTUAL_INTR_PENDING  0x00000004
+#define CPU_BASED_USE_TSC_OFFSETING     0x00000008
+#define CPU_BASED_HLT_EXITING           0x00000080
+#define CPU_BASED_INVDPG_EXITING        0x00000200
+#define CPU_BASED_MWAIT_EXITING         0x00000400
+#define CPU_BASED_RDPMC_EXITING         0x00000800
+#define CPU_BASED_RDTSC_EXITING         0x00001000
+#define CPU_BASED_CR8_LOAD_EXITING      0x00080000
+#define CPU_BASED_CR8_STORE_EXITING     0x00100000
+#define CPU_BASED_TPR_SHADOW            0x00200000
+#define CPU_BASED_MOV_DR_EXITING        0x00800000
+#define CPU_BASED_UNCOND_IO_EXITING     0x01000000
+#define CPU_BASED_ACTIVATE_IO_BITMAP    0x02000000
+#define CPU_BASED_MSR_BITMAPS           0x10000000
+#define CPU_BASED_MONITOR_EXITING       0x20000000
+#define CPU_BASED_PAUSE_EXITING         0x40000000
+
+#define PIN_BASED_EXT_INTR_MASK 0x1
+#define PIN_BASED_NMI_EXITING   0x8
+
+#define VM_EXIT_ACK_INTR_ON_EXIT        0x00008000
+#define VM_EXIT_HOST_ADD_SPACE_SIZE     0x00000200
+
+
+/* VMCS Encodings */
+enum vmcs_field {
+       GUEST_ES_SELECTOR               = 0x00000800,
+       GUEST_CS_SELECTOR               = 0x00000802,
+       GUEST_SS_SELECTOR               = 0x00000804,
+       GUEST_DS_SELECTOR               = 0x00000806,
+       GUEST_FS_SELECTOR               = 0x00000808,
+       GUEST_GS_SELECTOR               = 0x0000080a,
+       GUEST_LDTR_SELECTOR             = 0x0000080c,
+       GUEST_TR_SELECTOR               = 0x0000080e,
+       HOST_ES_SELECTOR                = 0x00000c00,
+       HOST_CS_SELECTOR                = 0x00000c02,
+       HOST_SS_SELECTOR                = 0x00000c04,
+       HOST_DS_SELECTOR                = 0x00000c06,
+       HOST_FS_SELECTOR                = 0x00000c08,
+       HOST_GS_SELECTOR                = 0x00000c0a,
+       HOST_TR_SELECTOR                = 0x00000c0c,
+       IO_BITMAP_A                     = 0x00002000,
+       IO_BITMAP_A_HIGH                = 0x00002001,
+       IO_BITMAP_B                     = 0x00002002,
+       IO_BITMAP_B_HIGH                = 0x00002003,
+       MSR_BITMAP                      = 0x00002004,
+       MSR_BITMAP_HIGH                 = 0x00002005,
+       VM_EXIT_MSR_STORE_ADDR          = 0x00002006,
+       VM_EXIT_MSR_STORE_ADDR_HIGH     = 0x00002007,
+       VM_EXIT_MSR_LOAD_ADDR           = 0x00002008,
+       VM_EXIT_MSR_LOAD_ADDR_HIGH      = 0x00002009,
+       VM_ENTRY_MSR_LOAD_ADDR          = 0x0000200a,
+       VM_ENTRY_MSR_LOAD_ADDR_HIGH     = 0x0000200b,
+       TSC_OFFSET                      = 0x00002010,
+       TSC_OFFSET_HIGH                 = 0x00002011,
+       VIRTUAL_APIC_PAGE_ADDR          = 0x00002012,
+       VIRTUAL_APIC_PAGE_ADDR_HIGH     = 0x00002013,
+       VMCS_LINK_POINTER               = 0x00002800,
+       VMCS_LINK_POINTER_HIGH          = 0x00002801,
+       GUEST_IA32_DEBUGCTL             = 0x00002802,
+       GUEST_IA32_DEBUGCTL_HIGH        = 0x00002803,
+       PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
+       CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
+       EXCEPTION_BITMAP                = 0x00004004,
+       PAGE_FAULT_ERROR_CODE_MASK      = 0x00004006,
+       PAGE_FAULT_ERROR_CODE_MATCH     = 0x00004008,
+       CR3_TARGET_COUNT                = 0x0000400a,
+       VM_EXIT_CONTROLS                = 0x0000400c,
+       VM_EXIT_MSR_STORE_COUNT         = 0x0000400e,
+       VM_EXIT_MSR_LOAD_COUNT          = 0x00004010,
+       VM_ENTRY_CONTROLS               = 0x00004012,
+       VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
+       VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
+       VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
+       VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
+       TPR_THRESHOLD                   = 0x0000401c,
+       SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
+       VM_INSTRUCTION_ERROR            = 0x00004400,
+       VM_EXIT_REASON                  = 0x00004402,
+       VM_EXIT_INTR_INFO               = 0x00004404,
+       VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
+       IDT_VECTORING_INFO_FIELD        = 0x00004408,
+       IDT_VECTORING_ERROR_CODE        = 0x0000440a,
+       VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
+       VMX_INSTRUCTION_INFO            = 0x0000440e,
+       GUEST_ES_LIMIT                  = 0x00004800,
+       GUEST_CS_LIMIT                  = 0x00004802,
+       GUEST_SS_LIMIT                  = 0x00004804,
+       GUEST_DS_LIMIT                  = 0x00004806,
+       GUEST_FS_LIMIT                  = 0x00004808,
+       GUEST_GS_LIMIT                  = 0x0000480a,
+       GUEST_LDTR_LIMIT                = 0x0000480c,
+       GUEST_TR_LIMIT                  = 0x0000480e,
+       GUEST_GDTR_LIMIT                = 0x00004810,
+       GUEST_IDTR_LIMIT                = 0x00004812,
+       GUEST_ES_AR_BYTES               = 0x00004814,
+       GUEST_CS_AR_BYTES               = 0x00004816,
+       GUEST_SS_AR_BYTES               = 0x00004818,
+       GUEST_DS_AR_BYTES               = 0x0000481a,
+       GUEST_FS_AR_BYTES               = 0x0000481c,
+       GUEST_GS_AR_BYTES               = 0x0000481e,
+       GUEST_LDTR_AR_BYTES             = 0x00004820,
+       GUEST_TR_AR_BYTES               = 0x00004822,
+       GUEST_INTERRUPTIBILITY_INFO     = 0x00004824,
+       GUEST_ACTIVITY_STATE            = 0X00004826,
+       GUEST_SYSENTER_CS               = 0x0000482A,
+       HOST_IA32_SYSENTER_CS           = 0x00004c00,
+       CR0_GUEST_HOST_MASK             = 0x00006000,
+       CR4_GUEST_HOST_MASK             = 0x00006002,
+       CR0_READ_SHADOW                 = 0x00006004,
+       CR4_READ_SHADOW                 = 0x00006006,
+       CR3_TARGET_VALUE0               = 0x00006008,
+       CR3_TARGET_VALUE1               = 0x0000600a,
+       CR3_TARGET_VALUE2               = 0x0000600c,
+       CR3_TARGET_VALUE3               = 0x0000600e,
+       EXIT_QUALIFICATION              = 0x00006400,
+       GUEST_LINEAR_ADDRESS            = 0x0000640a,
+       GUEST_CR0                       = 0x00006800,
+       GUEST_CR3                       = 0x00006802,
+       GUEST_CR4                       = 0x00006804,
+       GUEST_ES_BASE                   = 0x00006806,
+       GUEST_CS_BASE                   = 0x00006808,
+       GUEST_SS_BASE                   = 0x0000680a,
+       GUEST_DS_BASE                   = 0x0000680c,
+       GUEST_FS_BASE                   = 0x0000680e,
+       GUEST_GS_BASE                   = 0x00006810,
+       GUEST_LDTR_BASE                 = 0x00006812,
+       GUEST_TR_BASE                   = 0x00006814,
+       GUEST_GDTR_BASE                 = 0x00006816,
+       GUEST_IDTR_BASE                 = 0x00006818,
+       GUEST_DR7                       = 0x0000681a,
+       GUEST_RSP                       = 0x0000681c,
+       GUEST_RIP                       = 0x0000681e,
+       GUEST_RFLAGS                    = 0x00006820,
+       GUEST_PENDING_DBG_EXCEPTIONS    = 0x00006822,
+       GUEST_SYSENTER_ESP              = 0x00006824,
+       GUEST_SYSENTER_EIP              = 0x00006826,
+       HOST_CR0                        = 0x00006c00,
+       HOST_CR3                        = 0x00006c02,
+       HOST_CR4                        = 0x00006c04,
+       HOST_FS_BASE                    = 0x00006c06,
+       HOST_GS_BASE                    = 0x00006c08,
+       HOST_TR_BASE                    = 0x00006c0a,
+       HOST_GDTR_BASE                  = 0x00006c0c,
+       HOST_IDTR_BASE                  = 0x00006c0e,
+       HOST_IA32_SYSENTER_ESP          = 0x00006c10,
+       HOST_IA32_SYSENTER_EIP          = 0x00006c12,
+       HOST_RSP                        = 0x00006c14,
+       HOST_RIP                        = 0x00006c16,
+};
+
+#define VMX_EXIT_REASONS_FAILED_VMENTRY         0x80000000
+
+#define EXIT_REASON_EXCEPTION_NMI       0
+#define EXIT_REASON_EXTERNAL_INTERRUPT  1
+
+#define EXIT_REASON_PENDING_INTERRUPT   7
+
+#define EXIT_REASON_TASK_SWITCH         9
+#define EXIT_REASON_CPUID               10
+#define EXIT_REASON_HLT                 12
+#define EXIT_REASON_INVLPG              14
+#define EXIT_REASON_RDPMC               15
+#define EXIT_REASON_RDTSC               16
+#define EXIT_REASON_VMCALL              18
+#define EXIT_REASON_VMCLEAR             19
+#define EXIT_REASON_VMLAUNCH            20
+#define EXIT_REASON_VMPTRLD             21
+#define EXIT_REASON_VMPTRST             22
+#define EXIT_REASON_VMREAD              23
+#define EXIT_REASON_VMRESUME            24
+#define EXIT_REASON_VMWRITE             25
+#define EXIT_REASON_VMOFF               26
+#define EXIT_REASON_VMON                27
+#define EXIT_REASON_CR_ACCESS           28
+#define EXIT_REASON_DR_ACCESS           29
+#define EXIT_REASON_IO_INSTRUCTION      30
+#define EXIT_REASON_MSR_READ            31
+#define EXIT_REASON_MSR_WRITE           32
+#define EXIT_REASON_MWAIT_INSTRUCTION   36
+
+/*
+ * Interruption-information format
+ */
+#define INTR_INFO_VECTOR_MASK           0xff            /* 7:0 */
+#define INTR_INFO_INTR_TYPE_MASK        0x700           /* 10:8 */
+#define INTR_INFO_DELIEVER_CODE_MASK    0x800           /* 11 */
+#define INTR_INFO_VALID_MASK            0x80000000      /* 31 */
+
+#define VECTORING_INFO_VECTOR_MASK             INTR_INFO_VECTOR_MASK
+#define VECTORING_INFO_TYPE_MASK               INTR_INFO_INTR_TYPE_MASK
+#define VECTORING_INFO_DELIEVER_CODE_MASK      INTR_INFO_DELIEVER_CODE_MASK
+#define VECTORING_INFO_VALID_MASK              INTR_INFO_VALID_MASK
+
+#define INTR_TYPE_EXT_INTR              (0 << 8) /* external interrupt */
+#define INTR_TYPE_EXCEPTION             (3 << 8) /* processor exception */
+
+/*
+ * Exit Qualifications for MOV for Control Register Access
+ */
+#define CONTROL_REG_ACCESS_NUM          0x7     /* 2:0, number of control register */
+#define CONTROL_REG_ACCESS_TYPE         0x30    /* 5:4, access type */
+#define CONTROL_REG_ACCESS_REG          0xf00   /* 10:8, general purpose register */
+#define LMSW_SOURCE_DATA_SHIFT 16
+#define LMSW_SOURCE_DATA  (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw source */
+#define REG_EAX                         (0 << 8)
+#define REG_ECX                         (1 << 8)
+#define REG_EDX                         (2 << 8)
+#define REG_EBX                         (3 << 8)
+#define REG_ESP                         (4 << 8)
+#define REG_EBP                         (5 << 8)
+#define REG_ESI                         (6 << 8)
+#define REG_EDI                         (7 << 8)
+#define REG_R8                         (8 << 8)
+#define REG_R9                         (9 << 8)
+#define REG_R10                        (10 << 8)
+#define REG_R11                        (11 << 8)
+#define REG_R12                        (12 << 8)
+#define REG_R13                        (13 << 8)
+#define REG_R14                        (14 << 8)
+#define REG_R15                        (15 << 8)
+
+/*
+ * Exit Qualifications for MOV for Debug Register Access
+ */
+#define DEBUG_REG_ACCESS_NUM            0x7     /* 2:0, number of debug register */
+#define DEBUG_REG_ACCESS_TYPE           0x10    /* 4, direction of access */
+#define TYPE_MOV_TO_DR                  (0 << 4)
+#define TYPE_MOV_FROM_DR                (1 << 4)
+#define DEBUG_REG_ACCESS_REG            0xf00   /* 11:8, general purpose register */
+
+
+/* segment AR */
+#define SEGMENT_AR_L_MASK (1 << 13)
+
+/* entry controls */
+#define VM_ENTRY_CONTROLS_IA32E_MASK (1 << 9)
+
+#define AR_TYPE_ACCESSES_MASK 1
+#define AR_TYPE_READABLE_MASK (1 << 1)
+#define AR_TYPE_WRITEABLE_MASK (1 << 2)
+#define AR_TYPE_CODE_MASK (1 << 3)
+#define AR_TYPE_MASK 0x0f
+#define AR_TYPE_BUSY_64_TSS 11
+#define AR_TYPE_BUSY_32_TSS 11
+#define AR_TYPE_BUSY_16_TSS 3
+#define AR_TYPE_LDT 2
+
+#define AR_UNUSABLE_MASK (1 << 16)
+#define AR_S_MASK (1 << 4)
+#define AR_P_MASK (1 << 7)
+#define AR_L_MASK (1 << 13)
+#define AR_DB_MASK (1 << 14)
+#define AR_G_MASK (1 << 15)
+#define AR_DPL_SHIFT 5
+#define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3)
+
+#define AR_RESERVD_MASK 0xfffe0f00
+
+#define CR4_VMXE 0x2000
+
+#define MSR_IA32_VMX_BASIC_MSR                 0x480
+#define MSR_IA32_FEATURE_CONTROL               0x03a
+#define MSR_IA32_VMX_PINBASED_CTLS_MSR         0x481
+#define MSR_IA32_VMX_PROCBASED_CTLS_MSR                0x482
+#define MSR_IA32_VMX_EXIT_CTLS_MSR             0x483
+#define MSR_IA32_VMX_ENTRY_CTLS_MSR            0x484
+
+#endif
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
new file mode 100644 (file)
index 0000000..7e838bf
--- /dev/null
@@ -0,0 +1,1409 @@
+/******************************************************************************
+ * x86_emulate.c
+ *
+ * Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
+ *
+ * Copyright (c) 2005 Keir Fraser
+ *
+ * Linux coding style, mod r/m decoder, segment base fixes, real-mode
+ * privieged instructions:
+ *
+ * Copyright (C) 2006 Qumranet
+ *
+ *   Avi Kivity <avi@qumranet.com>
+ *   Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
+ */
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <stdint.h>
+#include <public/xen.h>
+#define DPRINTF(_f, _a ...) printf( _f , ## _a )
+#else
+#include "kvm.h"
+#define DPRINTF(x...) do {} while (0)
+#endif
+#include "x86_emulate.h"
+#include <linux/module.h>
+
+/*
+ * Opcode effective-address decode tables.
+ * Note that we only emulate instructions that have at least one memory
+ * operand (excluding implicit stack references). We assume that stack
+ * references and instruction fetches will never occur in special memory
+ * areas that require emulation. So, for example, 'mov <imm>,<reg>' need
+ * not be handled.
+ */
+
+/* Operand sizes: 8-bit operands or specified/overridden size. */
+#define ByteOp      (1<<0)     /* 8-bit operands. */
+/* Destination operand type. */
+#define ImplicitOps (1<<1)     /* Implicit in opcode. No generic decode. */
+#define DstReg      (2<<1)     /* Register operand. */
+#define DstMem      (3<<1)     /* Memory operand. */
+#define DstMask     (3<<1)
+/* Source operand type. */
+#define SrcNone     (0<<3)     /* No source operand. */
+#define SrcImplicit (0<<3)     /* Source operand is implicit in the opcode. */
+#define SrcReg      (1<<3)     /* Register operand. */
+#define SrcMem      (2<<3)     /* Memory operand. */
+#define SrcMem16    (3<<3)     /* Memory operand (16-bit). */
+#define SrcMem32    (4<<3)     /* Memory operand (32-bit). */
+#define SrcImm      (5<<3)     /* Immediate operand. */
+#define SrcImmByte  (6<<3)     /* 8-bit sign-extended immediate operand. */
+#define SrcMask     (7<<3)
+/* Generic ModRM decode. */
+#define ModRM       (1<<6)
+/* Destination is only written; never read. */
+#define Mov         (1<<7)
+
+static u8 opcode_table[256] = {
+       /* 0x00 - 0x07 */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x08 - 0x0F */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x10 - 0x17 */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x18 - 0x1F */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x20 - 0x27 */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x28 - 0x2F */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x30 - 0x37 */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x38 - 0x3F */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+       0, 0, 0, 0,
+       /* 0x40 - 0x4F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x50 - 0x5F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x60 - 0x6F */
+       0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x70 - 0x7F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x80 - 0x87 */
+       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+       /* 0x88 - 0x8F */
+       ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
+       ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       0, 0, 0, DstMem | SrcNone | ModRM | Mov,
+       /* 0x90 - 0x9F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xA0 - 0xA7 */
+       ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov,
+       ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov,
+       ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+       ByteOp | ImplicitOps, ImplicitOps,
+       /* 0xA8 - 0xAF */
+       0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+       ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+       ByteOp | ImplicitOps, ImplicitOps,
+       /* 0xB0 - 0xBF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xC0 - 0xC7 */
+       ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0,
+       0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov,
+           DstMem | SrcImm | ModRM | Mov,
+       /* 0xC8 - 0xCF */
+       0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xD0 - 0xD7 */
+       ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
+       ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
+       0, 0, 0, 0,
+       /* 0xD8 - 0xDF */
+       0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xE0 - 0xEF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xF0 - 0xF7 */
+       0, 0, 0, 0,
+       0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
+       /* 0xF8 - 0xFF */
+       0, 0, 0, 0,
+       0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
+};
+
+static u8 twobyte_table[256] = {
+       /* 0x00 - 0x0F */
+       0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
+       0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+       /* 0x10 - 0x1F */
+       0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x20 - 0x2F */
+       ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x30 - 0x3F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x40 - 0x47 */
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       /* 0x48 - 0x4F */
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       /* 0x50 - 0x5F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x60 - 0x6F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x70 - 0x7F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x80 - 0x8F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0x90 - 0x9F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xA0 - 0xA7 */
+       0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0,
+       /* 0xA8 - 0xAF */
+       0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0,
+       /* 0xB0 - 0xB7 */
+       ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
+           DstMem | SrcReg | ModRM,
+       0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
+           DstReg | SrcMem16 | ModRM | Mov,
+       /* 0xB8 - 0xBF */
+       0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM,
+       0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
+           DstReg | SrcMem16 | ModRM | Mov,
+       /* 0xC0 - 0xCF */
+       0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xD0 - 0xDF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xE0 - 0xEF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xF0 - 0xFF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Tell the emulator that of the Group 7 instructions (sgdt, lidt, etc.) we
+ * are interested only in invlpg and not in any of the rest.
+ *
+ * invlpg is a special instruction in that the data it references may not
+ * be mapped.
+ */
+void kvm_emulator_want_group7_invlpg(void)
+{
+       twobyte_table[1] &= ~SrcMem;
+}
+EXPORT_SYMBOL_GPL(kvm_emulator_want_group7_invlpg);
+
+/* Type, address-of, and value of an instruction's operand. */
+struct operand {
+       enum { OP_REG, OP_MEM, OP_IMM } type;
+       unsigned int bytes;
+       unsigned long val, orig_val, *ptr;
+};
+
+/* EFLAGS bit definitions. */
+#define EFLG_OF (1<<11)
+#define EFLG_DF (1<<10)
+#define EFLG_SF (1<<7)
+#define EFLG_ZF (1<<6)
+#define EFLG_AF (1<<4)
+#define EFLG_PF (1<<2)
+#define EFLG_CF (1<<0)
+
+/*
+ * Instruction emulation:
+ * Most instructions are emulated directly via a fragment of inline assembly
+ * code. This allows us to save/restore EFLAGS and thus very easily pick up
+ * any modified flags.
+ */
+
+#if defined(__x86_64__)
+#define _LO32 "k"              /* force 32-bit operand */
+#define _STK  "%%rsp"          /* stack pointer */
+#elif defined(__i386__)
+#define _LO32 ""               /* force 32-bit operand */
+#define _STK  "%%esp"          /* stack pointer */
+#endif
+
+/*
+ * These EFLAGS bits are restored from saved value during emulation, and
+ * any changes are written back to the saved value after emulation.
+ */
+#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF)
+
+/* Before executing instruction: restore necessary bits in EFLAGS. */
+#define _PRE_EFLAGS(_sav, _msk, _tmp) \
+       /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */        \
+       "push %"_sav"; "                                        \
+       "movl %"_msk",%"_LO32 _tmp"; "                          \
+       "andl %"_LO32 _tmp",("_STK"); "                         \
+       "pushf; "                                               \
+       "notl %"_LO32 _tmp"; "                                  \
+       "andl %"_LO32 _tmp",("_STK"); "                         \
+       "pop  %"_tmp"; "                                        \
+       "orl  %"_LO32 _tmp",("_STK"); "                         \
+       "popf; "                                                \
+       /* _sav &= ~msk; */                                     \
+       "movl %"_msk",%"_LO32 _tmp"; "                          \
+       "notl %"_LO32 _tmp"; "                                  \
+       "andl %"_LO32 _tmp",%"_sav"; "
+
+/* After executing instruction: write-back necessary bits in EFLAGS. */
+#define _POST_EFLAGS(_sav, _msk, _tmp) \
+       /* _sav |= EFLAGS & _msk; */            \
+       "pushf; "                               \
+       "pop  %"_tmp"; "                        \
+       "andl %"_msk",%"_LO32 _tmp"; "          \
+       "orl  %"_LO32 _tmp",%"_sav"; "
+
+/* Raw emulation: instruction has two explicit operands. */
+#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+       do {                                                                \
+               unsigned long _tmp;                                         \
+                                                                           \
+               switch ((_dst).bytes) {                                     \
+               case 2:                                                     \
+                       __asm__ __volatile__ (                              \
+                               _PRE_EFLAGS("0","4","2")                    \
+                               _op"w %"_wx"3,%1; "                         \
+                               _POST_EFLAGS("0","4","2")                   \
+                               : "=m" (_eflags), "=m" ((_dst).val),        \
+                                 "=&r" (_tmp)                              \
+                               : _wy ((_src).val), "i" (EFLAGS_MASK) );    \
+                       break;                                              \
+               case 4:                                                     \
+                       __asm__ __volatile__ (                              \
+                               _PRE_EFLAGS("0","4","2")                    \
+                               _op"l %"_lx"3,%1; "                         \
+                               _POST_EFLAGS("0","4","2")                   \
+                               : "=m" (_eflags), "=m" ((_dst).val),        \
+                                 "=&r" (_tmp)                              \
+                               : _ly ((_src).val), "i" (EFLAGS_MASK) );    \
+                       break;                                              \
+               case 8:                                                     \
+                       __emulate_2op_8byte(_op, _src, _dst,                \
+                                           _eflags, _qx, _qy);             \
+                       break;                                              \
+               }                                                           \
+       } while (0)
+
+#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+       do {                                                                 \
+               unsigned long _tmp;                                          \
+               switch ( (_dst).bytes )                                      \
+               {                                                            \
+               case 1:                                                      \
+                       __asm__ __volatile__ (                               \
+                               _PRE_EFLAGS("0","4","2")                     \
+                               _op"b %"_bx"3,%1; "                          \
+                               _POST_EFLAGS("0","4","2")                    \
+                               : "=m" (_eflags), "=m" ((_dst).val),         \
+                                 "=&r" (_tmp)                               \
+                               : _by ((_src).val), "i" (EFLAGS_MASK) );     \
+                       break;                                               \
+               default:                                                     \
+                       __emulate_2op_nobyte(_op, _src, _dst, _eflags,       \
+                                            _wx, _wy, _lx, _ly, _qx, _qy);  \
+                       break;                                               \
+               }                                                            \
+       } while (0)
+
+/* Source operand is byte-sized and may be restricted to just %cl. */
+#define emulate_2op_SrcB(_op, _src, _dst, _eflags)                      \
+       __emulate_2op(_op, _src, _dst, _eflags,                         \
+                     "b", "c", "b", "c", "b", "c", "b", "c")
+
+/* Source operand is byte, word, long or quad sized. */
+#define emulate_2op_SrcV(_op, _src, _dst, _eflags)                      \
+       __emulate_2op(_op, _src, _dst, _eflags,                         \
+                     "b", "q", "w", "r", _LO32, "r", "", "r")
+
+/* Source operand is word, long or quad sized. */
+#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags)               \
+       __emulate_2op_nobyte(_op, _src, _dst, _eflags,                  \
+                            "w", "r", _LO32, "r", "", "r")
+
+/* Instruction has only one explicit operand (no source operand). */
+#define emulate_1op(_op, _dst, _eflags)                                    \
+       do {                                                            \
+               unsigned long _tmp;                                     \
+                                                                       \
+               switch ( (_dst).bytes )                                 \
+               {                                                       \
+               case 1:                                                 \
+                       __asm__ __volatile__ (                          \
+                               _PRE_EFLAGS("0","3","2")                \
+                               _op"b %1; "                             \
+                               _POST_EFLAGS("0","3","2")               \
+                               : "=m" (_eflags), "=m" ((_dst).val),    \
+                                 "=&r" (_tmp)                          \
+                               : "i" (EFLAGS_MASK) );                  \
+                       break;                                          \
+               case 2:                                                 \
+                       __asm__ __volatile__ (                          \
+                               _PRE_EFLAGS("0","3","2")                \
+                               _op"w %1; "                             \
+                               _POST_EFLAGS("0","3","2")               \
+                               : "=m" (_eflags), "=m" ((_dst).val),    \
+                                 "=&r" (_tmp)                          \
+                               : "i" (EFLAGS_MASK) );                  \
+                       break;                                          \
+               case 4:                                                 \
+                       __asm__ __volatile__ (                          \
+                               _PRE_EFLAGS("0","3","2")                \
+                               _op"l %1; "                             \
+                               _POST_EFLAGS("0","3","2")               \
+                               : "=m" (_eflags), "=m" ((_dst).val),    \
+                                 "=&r" (_tmp)                          \
+                               : "i" (EFLAGS_MASK) );                  \
+                       break;                                          \
+               case 8:                                                 \
+                       __emulate_1op_8byte(_op, _dst, _eflags);        \
+                       break;                                          \
+               }                                                       \
+       } while (0)
+
+/* Emulate an instruction with quadword operands (x86/64 only). */
+#if defined(__x86_64__)
+#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)           \
+       do {                                                              \
+               __asm__ __volatile__ (                                    \
+                       _PRE_EFLAGS("0","4","2")                          \
+                       _op"q %"_qx"3,%1; "                               \
+                       _POST_EFLAGS("0","4","2")                         \
+                       : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
+                       : _qy ((_src).val), "i" (EFLAGS_MASK) );          \
+       } while (0)
+
+#define __emulate_1op_8byte(_op, _dst, _eflags)                           \
+       do {                                                              \
+               __asm__ __volatile__ (                                    \
+                       _PRE_EFLAGS("0","3","2")                          \
+                       _op"q %1; "                                       \
+                       _POST_EFLAGS("0","3","2")                         \
+                       : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
+                       : "i" (EFLAGS_MASK) );                            \
+       } while (0)
+
+#elif defined(__i386__)
+#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
+#define __emulate_1op_8byte(_op, _dst, _eflags)
+#endif                         /* __i386__ */
+
+/* Fetch next part of the instruction being emulated. */
+#define insn_fetch(_type, _size, _eip)                                  \
+({     unsigned long _x;                                               \
+       rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,  \
+                                                  (_size), ctxt);       \
+       if ( rc != 0 )                                                  \
+               goto done;                                              \
+       (_eip) += (_size);                                              \
+       (_type)_x;                                                      \
+})
+
+/* Access/update address held in a register, based on addressing mode. */
+#define register_address(base, reg)                                     \
+       ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) :        \
+                  ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
+
+#define register_address_increment(reg, inc)                            \
+       do {                                                            \
+               /* signed type ensures sign extension to long */        \
+               int _inc = (inc);                                       \
+               if ( ad_bytes == sizeof(unsigned long) )                \
+                       (reg) += _inc;                                  \
+               else                                                    \
+                       (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \
+                          (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \
+       } while (0)
+
+void *decode_register(u8 modrm_reg, unsigned long *regs,
+                     int highbyte_regs)
+{
+       void *p;
+
+       p = &regs[modrm_reg];
+       if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)
+               p = (unsigned char *)&regs[modrm_reg & 3] + 1;
+       return p;
+}
+
+static int read_descriptor(struct x86_emulate_ctxt *ctxt,
+                          struct x86_emulate_ops *ops,
+                          void *ptr,
+                          u16 *size, unsigned long *address, int op_bytes)
+{
+       int rc;
+
+       if (op_bytes == 2)
+               op_bytes = 3;
+       *address = 0;
+       rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt);
+       if (rc)
+               return rc;
+       rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt);
+       return rc;
+}
+
+int
+x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+{
+       u8 b, d, sib, twobyte = 0, rex_prefix = 0;
+       u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
+       unsigned long *override_base = NULL;
+       unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
+       int rc = 0;
+       struct operand src, dst;
+       unsigned long cr2 = ctxt->cr2;
+       int mode = ctxt->mode;
+       unsigned long modrm_ea;
+       int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+
+       /* Shadow copy of register state. Committed on successful emulation. */
+       unsigned long _regs[NR_VCPU_REGS];
+       unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;
+       unsigned long modrm_val = 0;
+
+       memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
+
+       switch (mode) {
+       case X86EMUL_MODE_REAL:
+       case X86EMUL_MODE_PROT16:
+               op_bytes = ad_bytes = 2;
+               break;
+       case X86EMUL_MODE_PROT32:
+               op_bytes = ad_bytes = 4;
+               break;
+#ifdef __x86_64__
+       case X86EMUL_MODE_PROT64:
+               op_bytes = 4;
+               ad_bytes = 8;
+               break;
+#endif
+       default:
+               return -1;
+       }
+
+       /* Legacy prefixes. */
+       for (i = 0; i < 8; i++) {
+               switch (b = insn_fetch(u8, 1, _eip)) {
+               case 0x66:      /* operand-size override */
+                       op_bytes ^= 6;  /* switch between 2/4 bytes */
+                       break;
+               case 0x67:      /* address-size override */
+                       if (mode == X86EMUL_MODE_PROT64)
+                               ad_bytes ^= 12; /* switch between 4/8 bytes */
+                       else
+                               ad_bytes ^= 6;  /* switch between 2/4 bytes */
+                       break;
+               case 0x2e:      /* CS override */
+                       override_base = &ctxt->cs_base;
+                       break;
+               case 0x3e:      /* DS override */
+                       override_base = &ctxt->ds_base;
+                       break;
+               case 0x26:      /* ES override */
+                       override_base = &ctxt->es_base;
+                       break;
+               case 0x64:      /* FS override */
+                       override_base = &ctxt->fs_base;
+                       break;
+               case 0x65:      /* GS override */
+                       override_base = &ctxt->gs_base;
+                       break;
+               case 0x36:      /* SS override */
+                       override_base = &ctxt->ss_base;
+                       break;
+               case 0xf0:      /* LOCK */
+                       lock_prefix = 1;
+                       break;
+               case 0xf3:      /* REP/REPE/REPZ */
+                       rep_prefix = 1;
+                       break;
+               case 0xf2:      /* REPNE/REPNZ */
+                       break;
+               default:
+                       goto done_prefixes;
+               }
+       }
+
+done_prefixes:
+
+       /* REX prefix. */
+       if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) {
+               rex_prefix = b;
+               if (b & 8)
+                       op_bytes = 8;   /* REX.W */
+               modrm_reg = (b & 4) << 1;       /* REX.R */
+               index_reg = (b & 2) << 2; /* REX.X */
+               modrm_rm = base_reg = (b & 1) << 3; /* REG.B */
+               b = insn_fetch(u8, 1, _eip);
+       }
+
+       /* Opcode byte(s). */
+       d = opcode_table[b];
+       if (d == 0) {
+               /* Two-byte opcode? */
+               if (b == 0x0f) {
+                       twobyte = 1;
+                       b = insn_fetch(u8, 1, _eip);
+                       d = twobyte_table[b];
+               }
+
+               /* Unrecognised? */
+               if (d == 0)
+                       goto cannot_emulate;
+       }
+
+       /* ModRM and SIB bytes. */
+       if (d & ModRM) {
+               modrm = insn_fetch(u8, 1, _eip);
+               modrm_mod |= (modrm & 0xc0) >> 6;
+               modrm_reg |= (modrm & 0x38) >> 3;
+               modrm_rm |= (modrm & 0x07);
+               modrm_ea = 0;
+               use_modrm_ea = 1;
+
+               if (modrm_mod == 3) {
+                       modrm_val = *(unsigned long *)
+                               decode_register(modrm_rm, _regs, d & ByteOp);
+                       goto modrm_done;
+               }
+
+               if (ad_bytes == 2) {
+                       unsigned bx = _regs[VCPU_REGS_RBX];
+                       unsigned bp = _regs[VCPU_REGS_RBP];
+                       unsigned si = _regs[VCPU_REGS_RSI];
+                       unsigned di = _regs[VCPU_REGS_RDI];
+
+                       /* 16-bit ModR/M decode. */
+                       switch (modrm_mod) {
+                       case 0:
+                               if (modrm_rm == 6)
+                                       modrm_ea += insn_fetch(u16, 2, _eip);
+                               break;
+                       case 1:
+                               modrm_ea += insn_fetch(s8, 1, _eip);
+                               break;
+                       case 2:
+                               modrm_ea += insn_fetch(u16, 2, _eip);
+                               break;
+                       }
+                       switch (modrm_rm) {
+                       case 0:
+                               modrm_ea += bx + si;
+                               break;
+                       case 1:
+                               modrm_ea += bx + di;
+                               break;
+                       case 2:
+                               modrm_ea += bp + si;
+                               break;
+                       case 3:
+                               modrm_ea += bp + di;
+                               break;
+                       case 4:
+                               modrm_ea += si;
+                               break;
+                       case 5:
+                               modrm_ea += di;
+                               break;
+                       case 6:
+                               if (modrm_mod != 0)
+                                       modrm_ea += bp;
+                               break;
+                       case 7:
+                               modrm_ea += bx;
+                               break;
+                       }
+                       if (modrm_rm == 2 || modrm_rm == 3 ||
+                           (modrm_rm == 6 && modrm_mod != 0))
+                               if (!override_base)
+                                       override_base = &ctxt->ss_base;
+                       modrm_ea = (u16)modrm_ea;
+               } else {
+                       /* 32/64-bit ModR/M decode. */
+                       switch (modrm_rm) {
+                       case 4:
+                       case 12:
+                               sib = insn_fetch(u8, 1, _eip);
+                               index_reg |= (sib >> 3) & 7;
+                               base_reg |= sib & 7;
+                               scale = sib >> 6;
+
+                               switch (base_reg) {
+                               case 5:
+                                       if (modrm_mod != 0)
+                                               modrm_ea += _regs[base_reg];
+                                       else
+                                               modrm_ea += insn_fetch(s32, 4, _eip);
+                                       break;
+                               default:
+                                       modrm_ea += _regs[base_reg];
+                               }
+                               switch (index_reg) {
+                               case 4:
+                                       break;
+                               default:
+                                       modrm_ea += _regs[index_reg] << scale;
+
+                               }
+                               break;
+                       case 5:
+                               if (modrm_mod != 0)
+                                       modrm_ea += _regs[modrm_rm];
+                               else if (mode == X86EMUL_MODE_PROT64)
+                                       rip_relative = 1;
+                               break;
+                       default:
+                               modrm_ea += _regs[modrm_rm];
+                               break;
+                       }
+                       switch (modrm_mod) {
+                       case 0:
+                               if (modrm_rm == 5)
+                                       modrm_ea += insn_fetch(s32, 4, _eip);
+                               break;
+                       case 1:
+                               modrm_ea += insn_fetch(s8, 1, _eip);
+                               break;
+                       case 2:
+                               modrm_ea += insn_fetch(s32, 4, _eip);
+                               break;
+                       }
+               }
+               if (!override_base)
+                       override_base = &ctxt->ds_base;
+               if (mode == X86EMUL_MODE_PROT64 &&
+                   override_base != &ctxt->fs_base &&
+                   override_base != &ctxt->gs_base)
+                       override_base = NULL;
+
+               if (override_base)
+                       modrm_ea += *override_base;
+
+               if (rip_relative) {
+                       modrm_ea += _eip;
+                       switch (d & SrcMask) {
+                       case SrcImmByte:
+                               modrm_ea += 1;
+                               break;
+                       case SrcImm:
+                               if (d & ByteOp)
+                                       modrm_ea += 1;
+                               else
+                                       if (op_bytes == 8)
+                                               modrm_ea += 4;
+                                       else
+                                               modrm_ea += op_bytes;
+                       }
+               }
+               if (ad_bytes != 8)
+                       modrm_ea = (u32)modrm_ea;
+               cr2 = modrm_ea;
+       modrm_done:
+               ;
+       }
+
+       /* Decode and fetch the destination operand: register or memory. */
+       switch (d & DstMask) {
+       case ImplicitOps:
+               /* Special instructions do their own operand decoding. */
+               goto special_insn;
+       case DstReg:
+               dst.type = OP_REG;
+               if ((d & ByteOp)
+                   && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
+                       dst.ptr = decode_register(modrm_reg, _regs,
+                                                 (rex_prefix == 0));
+                       dst.val = *(u8 *) dst.ptr;
+                       dst.bytes = 1;
+               } else {
+                       dst.ptr = decode_register(modrm_reg, _regs, 0);
+                       switch ((dst.bytes = op_bytes)) {
+                       case 2:
+                               dst.val = *(u16 *)dst.ptr;
+                               break;
+                       case 4:
+                               dst.val = *(u32 *)dst.ptr;
+                               break;
+                       case 8:
+                               dst.val = *(u64 *)dst.ptr;
+                               break;
+                       }
+               }
+               break;
+       case DstMem:
+               dst.type = OP_MEM;
+               dst.ptr = (unsigned long *)cr2;
+               dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+               if (!(d & Mov) && /* optimisation - avoid slow emulated read */
+                   ((rc = ops->read_emulated((unsigned long)dst.ptr,
+                                             &dst.val, dst.bytes, ctxt)) != 0))
+                       goto done;
+               break;
+       }
+       dst.orig_val = dst.val;
+
+       /*
+        * Decode and fetch the source operand: register, memory
+        * or immediate.
+        */
+       switch (d & SrcMask) {
+       case SrcNone:
+               break;
+       case SrcReg:
+               src.type = OP_REG;
+               if (d & ByteOp) {
+                       src.ptr = decode_register(modrm_reg, _regs,
+                                                 (rex_prefix == 0));
+                       src.val = src.orig_val = *(u8 *) src.ptr;
+                       src.bytes = 1;
+               } else {
+                       src.ptr = decode_register(modrm_reg, _regs, 0);
+                       switch ((src.bytes = op_bytes)) {
+                       case 2:
+                               src.val = src.orig_val = *(u16 *) src.ptr;
+                               break;
+                       case 4:
+                               src.val = src.orig_val = *(u32 *) src.ptr;
+                               break;
+                       case 8:
+                               src.val = src.orig_val = *(u64 *) src.ptr;
+                               break;
+                       }
+               }
+               break;
+       case SrcMem16:
+               src.bytes = 2;
+               goto srcmem_common;
+       case SrcMem32:
+               src.bytes = 4;
+               goto srcmem_common;
+       case SrcMem:
+               src.bytes = (d & ByteOp) ? 1 : op_bytes;
+             srcmem_common:
+               src.type = OP_MEM;
+               src.ptr = (unsigned long *)cr2;
+               if ((rc = ops->read_emulated((unsigned long)src.ptr,
+                                            &src.val, src.bytes, ctxt)) != 0)
+                       goto done;
+               src.orig_val = src.val;
+               break;
+       case SrcImm:
+               src.type = OP_IMM;
+               src.ptr = (unsigned long *)_eip;
+               src.bytes = (d & ByteOp) ? 1 : op_bytes;
+               if (src.bytes == 8)
+                       src.bytes = 4;
+               /* NB. Immediates are sign-extended as necessary. */
+               switch (src.bytes) {
+               case 1:
+                       src.val = insn_fetch(s8, 1, _eip);
+                       break;
+               case 2:
+                       src.val = insn_fetch(s16, 2, _eip);
+                       break;
+               case 4:
+                       src.val = insn_fetch(s32, 4, _eip);
+                       break;
+               }
+               break;
+       case SrcImmByte:
+               src.type = OP_IMM;
+               src.ptr = (unsigned long *)_eip;
+               src.bytes = 1;
+               src.val = insn_fetch(s8, 1, _eip);
+               break;
+       }
+
+       if (twobyte)
+               goto twobyte_insn;
+
+       switch (b) {
+       case 0x00 ... 0x05:
+             add:              /* add */
+               emulate_2op_SrcV("add", src, dst, _eflags);
+               break;
+       case 0x08 ... 0x0d:
+             or:               /* or */
+               emulate_2op_SrcV("or", src, dst, _eflags);
+               break;
+       case 0x10 ... 0x15:
+             adc:              /* adc */
+               emulate_2op_SrcV("adc", src, dst, _eflags);
+               break;
+       case 0x18 ... 0x1d:
+             sbb:              /* sbb */
+               emulate_2op_SrcV("sbb", src, dst, _eflags);
+               break;
+       case 0x20 ... 0x25:
+             and:              /* and */
+               emulate_2op_SrcV("and", src, dst, _eflags);
+               break;
+       case 0x28 ... 0x2d:
+             sub:              /* sub */
+               emulate_2op_SrcV("sub", src, dst, _eflags);
+               break;
+       case 0x30 ... 0x35:
+             xor:              /* xor */
+               emulate_2op_SrcV("xor", src, dst, _eflags);
+               break;
+       case 0x38 ... 0x3d:
+             cmp:              /* cmp */
+               emulate_2op_SrcV("cmp", src, dst, _eflags);
+               break;
+       case 0x63:              /* movsxd */
+               if (mode != X86EMUL_MODE_PROT64)
+                       goto cannot_emulate;
+               dst.val = (s32) src.val;
+               break;
+       case 0x80 ... 0x83:     /* Grp1 */
+               switch (modrm_reg) {
+               case 0:
+                       goto add;
+               case 1:
+                       goto or;
+               case 2:
+                       goto adc;
+               case 3:
+                       goto sbb;
+               case 4:
+                       goto and;
+               case 5:
+                       goto sub;
+               case 6:
+                       goto xor;
+               case 7:
+                       goto cmp;
+               }
+               break;
+       case 0x84 ... 0x85:
+             test:             /* test */
+               emulate_2op_SrcV("test", src, dst, _eflags);
+               break;
+       case 0x86 ... 0x87:     /* xchg */
+               /* Write back the register source. */
+               switch (dst.bytes) {
+               case 1:
+                       *(u8 *) src.ptr = (u8) dst.val;
+                       break;
+               case 2:
+                       *(u16 *) src.ptr = (u16) dst.val;
+                       break;
+               case 4:
+                       *src.ptr = (u32) dst.val;
+                       break;  /* 64b reg: zero-extend */
+               case 8:
+                       *src.ptr = dst.val;
+                       break;
+               }
+               /*
+                * Write back the memory destination with implicit LOCK
+                * prefix.
+                */
+               dst.val = src.val;
+               lock_prefix = 1;
+               break;
+       case 0xa0 ... 0xa1:     /* mov */
+               dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+               dst.val = src.val;
+               _eip += ad_bytes;       /* skip src displacement */
+               break;
+       case 0xa2 ... 0xa3:     /* mov */
+               dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
+               _eip += ad_bytes;       /* skip dst displacement */
+               break;
+       case 0x88 ... 0x8b:     /* mov */
+       case 0xc6 ... 0xc7:     /* mov (sole member of Grp11) */
+               dst.val = src.val;
+               break;
+       case 0x8f:              /* pop (sole member of Grp1a) */
+               /* 64-bit mode: POP always pops a 64-bit operand. */
+               if (mode == X86EMUL_MODE_PROT64)
+                       dst.bytes = 8;
+               if ((rc = ops->read_std(register_address(ctxt->ss_base,
+                                                        _regs[VCPU_REGS_RSP]),
+                                       &dst.val, dst.bytes, ctxt)) != 0)
+                       goto done;
+               register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
+               break;
+       case 0xc0 ... 0xc1:
+             grp2:             /* Grp2 */
+               switch (modrm_reg) {
+               case 0: /* rol */
+                       emulate_2op_SrcB("rol", src, dst, _eflags);
+                       break;
+               case 1: /* ror */
+                       emulate_2op_SrcB("ror", src, dst, _eflags);
+                       break;
+               case 2: /* rcl */
+                       emulate_2op_SrcB("rcl", src, dst, _eflags);
+                       break;
+               case 3: /* rcr */
+                       emulate_2op_SrcB("rcr", src, dst, _eflags);
+                       break;
+               case 4: /* sal/shl */
+               case 6: /* sal/shl */
+                       emulate_2op_SrcB("sal", src, dst, _eflags);
+                       break;
+               case 5: /* shr */
+                       emulate_2op_SrcB("shr", src, dst, _eflags);
+                       break;
+               case 7: /* sar */
+                       emulate_2op_SrcB("sar", src, dst, _eflags);
+                       break;
+               }
+               break;
+       case 0xd0 ... 0xd1:     /* Grp2 */
+               src.val = 1;
+               goto grp2;
+       case 0xd2 ... 0xd3:     /* Grp2 */
+               src.val = _regs[VCPU_REGS_RCX];
+               goto grp2;
+       case 0xf6 ... 0xf7:     /* Grp3 */
+               switch (modrm_reg) {
+               case 0 ... 1:   /* test */
+                       /*
+                        * Special case in Grp3: test has an immediate
+                        * source operand.
+                        */
+                       src.type = OP_IMM;
+                       src.ptr = (unsigned long *)_eip;
+                       src.bytes = (d & ByteOp) ? 1 : op_bytes;
+                       if (src.bytes == 8)
+                               src.bytes = 4;
+                       switch (src.bytes) {
+                       case 1:
+                               src.val = insn_fetch(s8, 1, _eip);
+                               break;
+                       case 2:
+                               src.val = insn_fetch(s16, 2, _eip);
+                               break;
+                       case 4:
+                               src.val = insn_fetch(s32, 4, _eip);
+                               break;
+                       }
+                       goto test;
+               case 2: /* not */
+                       dst.val = ~dst.val;
+                       break;
+               case 3: /* neg */
+                       emulate_1op("neg", dst, _eflags);
+                       break;
+               default:
+                       goto cannot_emulate;
+               }
+               break;
+       case 0xfe ... 0xff:     /* Grp4/Grp5 */
+               switch (modrm_reg) {
+               case 0: /* inc */
+                       emulate_1op("inc", dst, _eflags);
+                       break;
+               case 1: /* dec */
+                       emulate_1op("dec", dst, _eflags);
+                       break;
+               case 6: /* push */
+                       /* 64-bit mode: PUSH always pushes a 64-bit operand. */
+                       if (mode == X86EMUL_MODE_PROT64) {
+                               dst.bytes = 8;
+                               if ((rc = ops->read_std((unsigned long)dst.ptr,
+                                                       &dst.val, 8,
+                                                       ctxt)) != 0)
+                                       goto done;
+                       }
+                       register_address_increment(_regs[VCPU_REGS_RSP],
+                                                  -dst.bytes);
+                       if ((rc = ops->write_std(
+                                    register_address(ctxt->ss_base,
+                                                     _regs[VCPU_REGS_RSP]),
+                                    dst.val, dst.bytes, ctxt)) != 0)
+                               goto done;
+                       dst.val = dst.orig_val; /* skanky: disable writeback */
+                       break;
+               default:
+                       goto cannot_emulate;
+               }
+               break;
+       }
+
+writeback:
+       if ((d & Mov) || (dst.orig_val != dst.val)) {
+               switch (dst.type) {
+               case OP_REG:
+                       /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
+                       switch (dst.bytes) {
+                       case 1:
+                               *(u8 *)dst.ptr = (u8)dst.val;
+                               break;
+                       case 2:
+                               *(u16 *)dst.ptr = (u16)dst.val;
+                               break;
+                       case 4:
+                               *dst.ptr = (u32)dst.val;
+                               break;  /* 64b: zero-ext */
+                       case 8:
+                               *dst.ptr = dst.val;
+                               break;
+                       }
+                       break;
+               case OP_MEM:
+                       if (lock_prefix)
+                               rc = ops->cmpxchg_emulated((unsigned long)dst.
+                                                          ptr, dst.orig_val,
+                                                          dst.val, dst.bytes,
+                                                          ctxt);
+                       else
+                               rc = ops->write_emulated((unsigned long)dst.ptr,
+                                                        dst.val, dst.bytes,
+                                                        ctxt);
+                       if (rc != 0)
+                               goto done;
+               default:
+                       break;
+               }
+       }
+
+       /* Commit shadow register state. */
+       memcpy(ctxt->vcpu->regs, _regs, sizeof _regs);
+       ctxt->eflags = _eflags;
+       ctxt->vcpu->rip = _eip;
+
+done:
+       return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
+
+special_insn:
+       if (twobyte)
+               goto twobyte_special_insn;
+       if (rep_prefix) {
+               if (_regs[VCPU_REGS_RCX] == 0) {
+                       ctxt->vcpu->rip = _eip;
+                       goto done;
+               }
+               _regs[VCPU_REGS_RCX]--;
+               _eip = ctxt->vcpu->rip;
+       }
+       switch (b) {
+       case 0xa4 ... 0xa5:     /* movs */
+               dst.type = OP_MEM;
+               dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+               dst.ptr = (unsigned long *)register_address(ctxt->es_base,
+                                                       _regs[VCPU_REGS_RDI]);
+               if ((rc = ops->read_emulated(register_address(
+                     override_base ? *override_base : ctxt->ds_base,
+                     _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0)
+                       goto done;
+               register_address_increment(_regs[VCPU_REGS_RSI],
+                            (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+               register_address_increment(_regs[VCPU_REGS_RDI],
+                            (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+               break;
+       case 0xa6 ... 0xa7:     /* cmps */
+               DPRINTF("Urk! I don't handle CMPS.\n");
+               goto cannot_emulate;
+       case 0xaa ... 0xab:     /* stos */
+               dst.type = OP_MEM;
+               dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+               dst.ptr = (unsigned long *)cr2;
+               dst.val = _regs[VCPU_REGS_RAX];
+               register_address_increment(_regs[VCPU_REGS_RDI],
+                            (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+               break;
+       case 0xac ... 0xad:     /* lods */
+               dst.type = OP_REG;
+               dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+               dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+               if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0)
+                       goto done;
+               register_address_increment(_regs[VCPU_REGS_RSI],
+                          (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+               break;
+       case 0xae ... 0xaf:     /* scas */
+               DPRINTF("Urk! I don't handle SCAS.\n");
+               goto cannot_emulate;
+       }
+       goto writeback;
+
+twobyte_insn:
+       switch (b) {
+       case 0x01: /* lgdt, lidt, lmsw */
+               switch (modrm_reg) {
+                       u16 size;
+                       unsigned long address;
+
+               case 2: /* lgdt */
+                       rc = read_descriptor(ctxt, ops, src.ptr,
+                                            &size, &address, op_bytes);
+                       if (rc)
+                               goto done;
+                       realmode_lgdt(ctxt->vcpu, size, address);
+                       break;
+               case 3: /* lidt */
+                       rc = read_descriptor(ctxt, ops, src.ptr,
+                                            &size, &address, op_bytes);
+                       if (rc)
+                               goto done;
+                       realmode_lidt(ctxt->vcpu, size, address);
+                       break;
+               case 4: /* smsw */
+                       if (modrm_mod != 3)
+                               goto cannot_emulate;
+                       *(u16 *)&_regs[modrm_rm]
+                               = realmode_get_cr(ctxt->vcpu, 0);
+                       break;
+               case 6: /* lmsw */
+                       if (modrm_mod != 3)
+                               goto cannot_emulate;
+                       realmode_lmsw(ctxt->vcpu, (u16)modrm_val, &_eflags);
+                       break;
+               case 7: /* invlpg*/
+                       emulate_invlpg(ctxt->vcpu, cr2);
+                       break;
+               default:
+                       goto cannot_emulate;
+               }
+               break;
+       case 0x21: /* mov from dr to reg */
+               if (modrm_mod != 3)
+                       goto cannot_emulate;
+               rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]);
+               break;
+       case 0x23: /* mov from reg to dr */
+               if (modrm_mod != 3)
+                       goto cannot_emulate;
+               rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]);
+               break;
+       case 0x40 ... 0x4f:     /* cmov */
+               dst.val = dst.orig_val = src.val;
+               d &= ~Mov;      /* default to no move */
+               /*
+                * First, assume we're decoding an even cmov opcode
+                * (lsb == 0).
+                */
+               switch ((b & 15) >> 1) {
+               case 0: /* cmovo */
+                       d |= (_eflags & EFLG_OF) ? Mov : 0;
+                       break;
+               case 1: /* cmovb/cmovc/cmovnae */
+                       d |= (_eflags & EFLG_CF) ? Mov : 0;
+                       break;
+               case 2: /* cmovz/cmove */
+                       d |= (_eflags & EFLG_ZF) ? Mov : 0;
+                       break;
+               case 3: /* cmovbe/cmovna */
+                       d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0;
+                       break;
+               case 4: /* cmovs */
+                       d |= (_eflags & EFLG_SF) ? Mov : 0;
+                       break;
+               case 5: /* cmovp/cmovpe */
+                       d |= (_eflags & EFLG_PF) ? Mov : 0;
+                       break;
+               case 7: /* cmovle/cmovng */
+                       d |= (_eflags & EFLG_ZF) ? Mov : 0;
+                       /* fall through */
+               case 6: /* cmovl/cmovnge */
+                       d |= (!(_eflags & EFLG_SF) !=
+                             !(_eflags & EFLG_OF)) ? Mov : 0;
+                       break;
+               }
+               /* Odd cmov opcodes (lsb == 1) have inverted sense. */
+               d ^= (b & 1) ? Mov : 0;
+               break;
+       case 0xb0 ... 0xb1:     /* cmpxchg */
+               /*
+                * Save real source value, then compare EAX against
+                * destination.
+                */
+               src.orig_val = src.val;
+               src.val = _regs[VCPU_REGS_RAX];
+               emulate_2op_SrcV("cmp", src, dst, _eflags);
+               /* Always write back. The question is: where to? */
+               d |= Mov;
+               if (_eflags & EFLG_ZF) {
+                       /* Success: write back to memory. */
+                       dst.val = src.orig_val;
+               } else {
+                       /* Failure: write the value we saw to EAX. */
+                       dst.type = OP_REG;
+                       dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+               }
+               break;
+       case 0xa3:
+             bt:               /* bt */
+               src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+               emulate_2op_SrcV_nobyte("bt", src, dst, _eflags);
+               break;
+       case 0xb3:
+             btr:              /* btr */
+               src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+               emulate_2op_SrcV_nobyte("btr", src, dst, _eflags);
+               break;
+       case 0xab:
+             bts:              /* bts */
+               src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+               emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
+               break;
+       case 0xb6 ... 0xb7:     /* movzx */
+               dst.bytes = op_bytes;
+               dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val;
+               break;
+       case 0xbb:
+             btc:              /* btc */
+               src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+               emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
+               break;
+       case 0xba:              /* Grp8 */
+               switch (modrm_reg & 3) {
+               case 0:
+                       goto bt;
+               case 1:
+                       goto bts;
+               case 2:
+                       goto btr;
+               case 3:
+                       goto btc;
+               }
+               break;
+       case 0xbe ... 0xbf:     /* movsx */
+               dst.bytes = op_bytes;
+               dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
+               break;
+       }
+       goto writeback;
+
+twobyte_special_insn:
+       /* Disable writeback. */
+       dst.orig_val = dst.val;
+       switch (b) {
+       case 0x0d:              /* GrpP (prefetch) */
+       case 0x18:              /* Grp16 (prefetch/nop) */
+               break;
+       case 0x06:
+               emulate_clts(ctxt->vcpu);
+               break;
+       case 0x20: /* mov cr, reg */
+               if (modrm_mod != 3)
+                       goto cannot_emulate;
+               _regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg);
+               break;
+       case 0x22: /* mov reg, cr */
+               if (modrm_mod != 3)
+                       goto cannot_emulate;
+               realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
+               break;
+       case 0xc7:              /* Grp9 (cmpxchg8b) */
+#if defined(__i386__)
+               {
+                       unsigned long old_lo, old_hi;
+                       if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4,
+                                                     ctxt)) != 0)
+                           || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4,
+                                                        ctxt)) != 0))
+                               goto done;
+                       if ((old_lo != _regs[VCPU_REGS_RAX])
+                           || (old_hi != _regs[VCPU_REGS_RDI])) {
+                               _regs[VCPU_REGS_RAX] = old_lo;
+                               _regs[VCPU_REGS_RDX] = old_hi;
+                               _eflags &= ~EFLG_ZF;
+                       } else if (ops->cmpxchg8b_emulated == NULL) {
+                               rc = X86EMUL_UNHANDLEABLE;
+                               goto done;
+                       } else {
+                               if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo,
+                                                         old_hi,
+                                                         _regs[VCPU_REGS_RBX],
+                                                         _regs[VCPU_REGS_RCX],
+                                                         ctxt)) != 0)
+                                       goto done;
+                               _eflags |= EFLG_ZF;
+                       }
+                       break;
+               }
+#elif defined(__x86_64__)
+               {
+                       unsigned long old, new;
+                       if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
+                               goto done;
+                       if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) ||
+                           ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) {
+                               _regs[VCPU_REGS_RAX] = (u32) (old >> 0);
+                               _regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+                               _eflags &= ~EFLG_ZF;
+                       } else {
+                               new = (_regs[VCPU_REGS_RCX] << 32) | (u32) _regs[VCPU_REGS_RBX];
+                               if ((rc = ops->cmpxchg_emulated(cr2, old,
+                                                         new, 8, ctxt)) != 0)
+                                       goto done;
+                               _eflags |= EFLG_ZF;
+                       }
+                       break;
+               }
+#endif
+       }
+       goto writeback;
+
+cannot_emulate:
+       DPRINTF("Cannot emulate %02x\n", b);
+       return -1;
+}
+
+#ifdef __XEN__
+
+#include <asm/mm.h>
+#include <asm/uaccess.h>
+
+int
+x86_emulate_read_std(unsigned long addr,
+                    unsigned long *val,
+                    unsigned int bytes, struct x86_emulate_ctxt *ctxt)
+{
+       unsigned int rc;
+
+       *val = 0;
+
+       if ((rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0) {
+               propagate_page_fault(addr + bytes - rc, 0);     /* read fault */
+               return X86EMUL_PROPAGATE_FAULT;
+       }
+
+       return X86EMUL_CONTINUE;
+}
+
+int
+x86_emulate_write_std(unsigned long addr,
+                     unsigned long val,
+                     unsigned int bytes, struct x86_emulate_ctxt *ctxt)
+{
+       unsigned int rc;
+
+       if ((rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0) {
+               propagate_page_fault(addr + bytes - rc, PGERR_write_access);
+               return X86EMUL_PROPAGATE_FAULT;
+       }
+
+       return X86EMUL_CONTINUE;
+}
+
+#endif
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
new file mode 100644 (file)
index 0000000..658b58d
--- /dev/null
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * x86_emulate.h
+ *
+ * Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
+ *
+ * Copyright (c) 2005 Keir Fraser
+ *
+ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
+ */
+
+#ifndef __X86_EMULATE_H__
+#define __X86_EMULATE_H__
+
+struct x86_emulate_ctxt;
+
+/*
+ * x86_emulate_ops:
+ *
+ * These operations represent the instruction emulator's interface to memory.
+ * There are two categories of operation: those that act on ordinary memory
+ * regions (*_std), and those that act on memory regions known to require
+ * special treatment or emulation (*_emulated).
+ *
+ * The emulator assumes that an instruction accesses only one 'emulated memory'
+ * location, that this location is the given linear faulting address (cr2), and
+ * that this is one of the instruction's data operands. Instruction fetches and
+ * stack operations are assumed never to access emulated memory. The emulator
+ * automatically deduces which operand of a string-move operation is accessing
+ * emulated memory, and assumes that the other operand accesses normal memory.
+ *
+ * NOTES:
+ *  1. The emulator isn't very smart about emulated vs. standard memory.
+ *     'Emulated memory' access addresses should be checked for sanity.
+ *     'Normal memory' accesses may fault, and the caller must arrange to
+ *     detect and handle reentrancy into the emulator via recursive faults.
+ *     Accesses may be unaligned and may cross page boundaries.
+ *  2. If the access fails (cannot emulate, or a standard access faults) then
+ *     it is up to the memop to propagate the fault to the guest VM via
+ *     some out-of-band mechanism, unknown to the emulator. The memop signals
+ *     failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will
+ *     then immediately bail.
+ *  3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
+ *     cmpxchg8b_emulated need support 8-byte accesses.
+ *  4. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
+ */
+/* Access completed successfully: continue emulation as normal. */
+#define X86EMUL_CONTINUE        0
+/* Access is unhandleable: bail from emulation and return error to caller. */
+#define X86EMUL_UNHANDLEABLE    1
+/* Terminate emulation but return success to the caller. */
+#define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */
+#define X86EMUL_RETRY_INSTR     2 /* retry the instruction for some reason */
+#define X86EMUL_CMPXCHG_FAILED  2 /* cmpxchg did not see expected value */
+struct x86_emulate_ops {
+       /*
+        * read_std: Read bytes of standard (non-emulated/special) memory.
+        *           Used for instruction fetch, stack operations, and others.
+        *  @addr:  [IN ] Linear address from which to read.
+        *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+        *  @bytes: [IN ] Number of bytes to read from memory.
+        */
+       int (*read_std)(unsigned long addr,
+                       unsigned long *val,
+                       unsigned int bytes, struct x86_emulate_ctxt * ctxt);
+
+       /*
+        * write_std: Write bytes of standard (non-emulated/special) memory.
+        *            Used for stack operations, and others.
+        *  @addr:  [IN ] Linear address to which to write.
+        *  @val:   [IN ] Value to write to memory (low-order bytes used as
+        *                required).
+        *  @bytes: [IN ] Number of bytes to write to memory.
+        */
+       int (*write_std)(unsigned long addr,
+                        unsigned long val,
+                        unsigned int bytes, struct x86_emulate_ctxt * ctxt);
+
+       /*
+        * read_emulated: Read bytes from emulated/special memory area.
+        *  @addr:  [IN ] Linear address from which to read.
+        *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+        *  @bytes: [IN ] Number of bytes to read from memory.
+        */
+       int (*read_emulated) (unsigned long addr,
+                             unsigned long *val,
+                             unsigned int bytes,
+                             struct x86_emulate_ctxt * ctxt);
+
+       /*
+        * write_emulated: Read bytes from emulated/special memory area.
+        *  @addr:  [IN ] Linear address to which to write.
+        *  @val:   [IN ] Value to write to memory (low-order bytes used as
+        *                required).
+        *  @bytes: [IN ] Number of bytes to write to memory.
+        */
+       int (*write_emulated) (unsigned long addr,
+                              unsigned long val,
+                              unsigned int bytes,
+                              struct x86_emulate_ctxt * ctxt);
+
+       /*
+        * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
+        *                   emulated/special memory area.
+        *  @addr:  [IN ] Linear address to access.
+        *  @old:   [IN ] Value expected to be current at @addr.
+        *  @new:   [IN ] Value to write to @addr.
+        *  @bytes: [IN ] Number of bytes to access using CMPXCHG.
+        */
+       int (*cmpxchg_emulated) (unsigned long addr,
+                                unsigned long old,
+                                unsigned long new,
+                                unsigned int bytes,
+                                struct x86_emulate_ctxt * ctxt);
+
+       /*
+        * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an
+        *                     emulated/special memory area.
+        *  @addr:  [IN ] Linear address to access.
+        *  @old:   [IN ] Value expected to be current at @addr.
+        *  @new:   [IN ] Value to write to @addr.
+        * NOTES:
+        *  1. This function is only ever called when emulating a real CMPXCHG8B.
+        *  2. This function is *never* called on x86/64 systems.
+        *  2. Not defining this function (i.e., specifying NULL) is equivalent
+        *     to defining a function that always returns X86EMUL_UNHANDLEABLE.
+        */
+       int (*cmpxchg8b_emulated) (unsigned long addr,
+                                  unsigned long old_lo,
+                                  unsigned long old_hi,
+                                  unsigned long new_lo,
+                                  unsigned long new_hi,
+                                  struct x86_emulate_ctxt * ctxt);
+};
+
+struct cpu_user_regs;
+
+struct x86_emulate_ctxt {
+       /* Register state before/after emulation. */
+       struct kvm_vcpu *vcpu;
+
+       /* Linear faulting address (if emulating a page-faulting instruction). */
+       unsigned long eflags;
+       unsigned long cr2;
+
+       /* Emulated execution mode, represented by an X86EMUL_MODE value. */
+       int mode;
+
+       unsigned long cs_base;
+       unsigned long ds_base;
+       unsigned long es_base;
+       unsigned long ss_base;
+       unsigned long gs_base;
+       unsigned long fs_base;
+};
+
+/* Execution mode, passed to the emulator. */
+#define X86EMUL_MODE_REAL     0        /* Real mode.             */
+#define X86EMUL_MODE_PROT16   2        /* 16-bit protected mode. */
+#define X86EMUL_MODE_PROT32   4        /* 32-bit protected mode. */
+#define X86EMUL_MODE_PROT64   8        /* 64-bit (long) mode.    */
+
+/* Host execution mode. */
+#if defined(__i386__)
+#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
+#elif defined(__x86_64__)
+#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
+#endif
+
+/*
+ * x86_emulate_memop: Emulate an instruction that faulted attempting to
+ *                    read/write a 'special' memory area.
+ * Returns -1 on failure, 0 on success.
+ */
+int x86_emulate_memop(struct x86_emulate_ctxt *ctxt,
+                     struct x86_emulate_ops *ops);
+
+/*
+ * Given the 'reg' portion of a ModRM byte, and a register block, return a
+ * pointer into the block that addresses the relevant register.
+ * @highbyte_regs specifies whether to decode AH,CH,DH,BH.
+ */
+void *decode_register(u8 modrm_reg, unsigned long *regs,
+                     int highbyte_regs);
+
+#endif                         /* __X86_EMULATE_H__ */
index 9c39b98..176142c 100644 (file)
@@ -76,6 +76,12 @@ config LEDS_NET48XX
          This option enables support for the Soekris net4801 and net4826 error
          LED.
 
+config LEDS_WRAP
+       tristate "LED Support for the WRAP series LEDs"
+       depends on LEDS_CLASS && SCx200_GPIO
+       help
+         This option enables support for the PCEngines WRAP programmable LEDs.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
index 6aa2aed..500de3d 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_LEDS_TOSA)                       += leds-tosa.o
 obj-$(CONFIG_LEDS_S3C24XX)             += leds-s3c24xx.o
 obj-$(CONFIG_LEDS_AMS_DELTA)           += leds-ams-delta.o
 obj-$(CONFIG_LEDS_NET48XX)             += leds-net48xx.o
+obj-$(CONFIG_LEDS_WRAP)                        += leds-wrap.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
new file mode 100644 (file)
index 0000000..27fb2d8
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * LEDs driver for PCEngines WRAP
+ *
+ * Copyright (C) 2006 Kristian Kielhofner <kris@krisk.org>
+ *
+ * Based on leds-net48xx.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <linux/scx200_gpio.h>
+
+#define DRVNAME "wrap-led"
+#define WRAP_ERROR_LED_GPIO    3
+#define        WRAP_EXTRA_LED_GPIO     18
+
+static struct platform_device *pdev;
+
+static void wrap_error_led_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       if (value)
+               scx200_gpio_set_low(WRAP_ERROR_LED_GPIO);
+       else
+               scx200_gpio_set_high(WRAP_ERROR_LED_GPIO);
+}
+
+static void wrap_extra_led_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       if (value)
+               scx200_gpio_set_low(WRAP_EXTRA_LED_GPIO);
+       else
+               scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO);
+}
+
+static struct led_classdev wrap_error_led = {
+       .name           = "wrap:error",
+       .brightness_set = wrap_error_led_set,
+};
+
+static struct led_classdev wrap_extra_led = {
+       .name           = "wrap:extra",
+       .brightness_set = wrap_extra_led_set,
+};
+
+#ifdef CONFIG_PM
+static int wrap_led_suspend(struct platform_device *dev,
+               pm_message_t state)
+{
+       led_classdev_suspend(&wrap_error_led);
+       led_classdev_suspend(&wrap_extra_led);
+       return 0;
+}
+
+static int wrap_led_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&wrap_error_led);
+       led_classdev_resume(&wrap_extra_led);
+       return 0;
+}
+#else
+#define wrap_led_suspend NULL
+#define wrap_led_resume NULL
+#endif
+
+static int wrap_led_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = led_classdev_register(&pdev->dev, &wrap_error_led);
+       if (ret == 0) {
+               ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
+               if (ret < 0)
+                       led_classdev_unregister(&wrap_error_led);
+       }
+       return ret;
+}
+
+static int wrap_led_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&wrap_error_led);
+       led_classdev_unregister(&wrap_extra_led);
+       return 0;
+}
+
+static struct platform_driver wrap_led_driver = {
+       .probe          = wrap_led_probe,
+       .remove         = wrap_led_remove,
+       .suspend        = wrap_led_suspend,
+       .resume         = wrap_led_resume,
+       .driver         = {
+               .name           = DRVNAME,
+               .owner          = THIS_MODULE,
+       },
+};
+
+static int __init wrap_led_init(void)
+{
+       int ret;
+
+       if (!scx200_gpio_present()) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       ret = platform_driver_register(&wrap_led_driver);
+       if (ret < 0)
+               goto out;
+
+       pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+       if (IS_ERR(pdev)) {
+               ret = PTR_ERR(pdev);
+               platform_driver_unregister(&wrap_led_driver);
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+static void __exit wrap_led_exit(void)
+{
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&wrap_led_driver);
+}
+
+module_init(wrap_led_init);
+module_exit(wrap_led_exit);
+
+MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
+MODULE_DESCRIPTION("PCEngines WRAP LED driver");
+MODULE_LICENSE("GPL");
+
index 92ccee8..a9e747c 100644 (file)
@@ -162,7 +162,6 @@ config INPUT_ADBHID
 
 config MAC_EMUMOUSEBTN
        bool "Support for mouse button 2+3 emulation"
-       depends on INPUT_ADBHID
        help
          This provides generic support for emulating the 2nd and 3rd mouse
          button with keypresses.  If you say Y here, the emulation is still
index be0bd34..d43ea81 100644 (file)
@@ -267,12 +267,12 @@ adb_probe_task(void *x)
 }
 
 static void
-__adb_probe_task(void *data)
+__adb_probe_task(struct work_struct *bullshit)
 {
        adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL);
 }
 
-static DECLARE_WORK(adb_reset_work, __adb_probe_task, NULL);
+static DECLARE_WORK(adb_reset_work, __adb_probe_task);
 
 int
 adb_reset_bus(void)
index 5066e7a..1c7d6f2 100644 (file)
@@ -689,7 +689,6 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
        if (!hid || !input_dev) {
                err = -ENOMEM;
                goto fail;
-
        }
 
        sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
@@ -807,7 +806,9 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
 
        input_dev->keycode = hid->keycode;
 
-       input_register_device(input_dev);
+       err = input_register_device(input_dev);
+       if (err)
+               goto fail;
 
        if (default_id == ADB_KEYBOARD) {
                /* HACK WARNING!! This should go away as soon there is an utility
@@ -820,7 +821,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
        return 0;
 
  fail: input_free_device(input_dev);
-       kfree(hid);
+       if (hid) {
+               kfree(hid->keycode);
+               kfree(hid);
+       }
        adbhid[id] = NULL;
        return err;
 }
index 1293876..8862a83 100644 (file)
@@ -529,7 +529,8 @@ static int __init apm_emu_init(void)
        if (apm_proc)
                apm_proc->owner = THIS_MODULE;
 
-       misc_register(&apm_device);
+       if (misc_register(&apm_device) != 0)
+               printk(KERN_INFO "Could not create misc. device for apm\n");
 
        pmu_register_sleep_notifier(&apm_sleep_notifier);
 
index 6b129ee..ee6b4ca 100644 (file)
@@ -106,6 +106,8 @@ EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
 
 static int emumousebtn_input_register(void)
 {
+       int ret;
+
        emumousebtn = input_allocate_device();
        if (!emumousebtn)
                return -ENOMEM;
@@ -120,9 +122,11 @@ static int emumousebtn_input_register(void)
        emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
        emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
 
-       input_register_device(emumousebtn);
+       ret = input_register_device(emumousebtn);
+       if (ret)
+               input_free_device(emumousebtn);
 
-       return 0;
+       return ret;
 }
 
 int __init mac_hid_init(void)
index f1b6f56..5ed41fe 100644 (file)
@@ -48,7 +48,8 @@ struct rackmeter_dma {
 } ____cacheline_aligned;
 
 struct rackmeter_cpu {
-       struct work_struct      sniffer;
+       struct delayed_work     sniffer;
+       struct rackmeter        *rm;
        cputime64_t             prev_wall;
        cputime64_t             prev_idle;
        int                     zero;
@@ -208,11 +209,12 @@ static void rackmeter_setup_dbdma(struct rackmeter *rm)
        rackmeter_do_pause(rm, 0);
 }
 
-static void rackmeter_do_timer(void *data)
+static void rackmeter_do_timer(struct work_struct *work)
 {
-       struct rackmeter *rm = data;
+       struct rackmeter_cpu *rcpu =
+               container_of(work, struct rackmeter_cpu, sniffer.work);
+       struct rackmeter *rm = rcpu->rm;
        unsigned int cpu = smp_processor_id();
-       struct rackmeter_cpu *rcpu = &rm->cpu[cpu];
        cputime64_t cur_jiffies, total_idle_ticks;
        unsigned int total_ticks, idle_ticks;
        int i, offset, load, cumm, pause;
@@ -263,8 +265,10 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
         * on those machines yet
         */
 
-       INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm);
-       INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm);
+       rm->cpu[0].rm = rm;
+       INIT_DELAYED_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer);
+       rm->cpu[1].rm = rm;
+       INIT_DELAYED_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer);
 
        for_each_online_cpu(cpu) {
                struct rackmeter_cpu *rcpu;
index 4f724cd..6dde27a 100644 (file)
@@ -601,7 +601,7 @@ core_initcall(smu_late_init);
  * sysfs visibility
  */
 
-static void smu_expose_childs(void *unused)
+static void smu_expose_childs(struct work_struct *unused)
 {
        struct device_node *np;
 
@@ -611,7 +611,7 @@ static void smu_expose_childs(void *unused)
                                                  &smu->of_dev->dev);
 }
 
-static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
+static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs);
 
 static int smu_platform_probe(struct of_device* dev,
                              const struct of_device_id *match)
index 13b953a..3d3bf16 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/moduleparam.h>
+#include <linux/freezer.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
index e63ea1c..c8558d4 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/syscalls.h>
 #include <linux/cpu.h>
 #include <asm/prom.h>
index ab3faa7..e947af9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <asm/prom.h>
 
index c92c152..4540ade 100644 (file)
@@ -215,6 +215,7 @@ config DM_CRYPT
        tristate "Crypt target support"
        depends on BLK_DEV_DM && EXPERIMENTAL
        select CRYPTO
+       select CRYPTO_CBC
        ---help---
          This device-mapper target allows you to create a device that
          transparently encrypts the data on it. You'll need to activate
index d6f6147..5432d07 100644 (file)
@@ -212,8 +212,8 @@ char *file_path(struct file *file, char *buf, int count)
        if (!buf)
                return NULL;
 
-       d = file->f_dentry;
-       v = file->f_vfsmnt;
+       d = file->f_path.dentry;
+       v = file->f_path.mnt;
 
        buf = d_path(d, v, buf, count);
 
@@ -349,7 +349,7 @@ static struct page *read_page(struct file *file, unsigned long index,
                              unsigned long count)
 {
        struct page *page = NULL;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct buffer_head *bh;
        sector_t block;
 
@@ -662,7 +662,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
        bitmap_file_unmap(bitmap);
 
        if (file) {
-               struct inode *inode = file->f_dentry->d_inode;
+               struct inode *inode = file->f_path.dentry->d_inode;
                invalidate_inode_pages(inode->i_mapping);
                fput(file);
        }
index bbf4615..da43496 100644 (file)
@@ -44,6 +44,20 @@ static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
        bl->tail = bl2->tail;
 }
 
+static inline void bio_list_merge_head(struct bio_list *bl,
+                                      struct bio_list *bl2)
+{
+       if (!bl2->head)
+               return;
+
+       if (bl->head)
+               bl2->tail->bi_next = bl->head;
+       else
+               bl->tail = bl2->tail;
+
+       bl->head = bl2->head;
+}
+
 static inline struct bio *bio_list_pop(struct bio_list *bl)
 {
        struct bio *bio = bl->head;
index 08a40f4..4c2471e 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
+#include <asm/unaligned.h>
 
 #include "dm.h"
 
@@ -85,7 +86,10 @@ struct crypt_config {
         */
        struct crypt_iv_operations *iv_gen_ops;
        char *iv_mode;
-       struct crypto_cipher *iv_gen_private;
+       union {
+               struct crypto_cipher *essiv_tfm;
+               int benbi_shift;
+       } iv_gen_private;
        sector_t iv_offset;
        unsigned int iv_size;
 
@@ -101,7 +105,7 @@ struct crypt_config {
 #define MIN_POOL_PAGES 32
 #define MIN_BIO_PAGES  8
 
-static kmem_cache_t *_crypt_io_pool;
+static struct kmem_cache *_crypt_io_pool;
 
 /*
  * Different IV generation algorithms:
@@ -113,6 +117,9 @@ static kmem_cache_t *_crypt_io_pool;
  *        encrypted with the bulk cipher using a salt as key. The salt
  *        should be derived from the bulk cipher's key via hashing.
  *
+ * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
+ *        (needed for LRW-32-AES and possible other narrow block modes)
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -191,21 +198,61 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
        }
        kfree(salt);
 
-       cc->iv_gen_private = essiv_tfm;
+       cc->iv_gen_private.essiv_tfm = essiv_tfm;
        return 0;
 }
 
 static void crypt_iv_essiv_dtr(struct crypt_config *cc)
 {
-       crypto_free_cipher(cc->iv_gen_private);
-       cc->iv_gen_private = NULL;
+       crypto_free_cipher(cc->iv_gen_private.essiv_tfm);
+       cc->iv_gen_private.essiv_tfm = NULL;
 }
 
 static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
 {
        memset(iv, 0, cc->iv_size);
        *(u64 *)iv = cpu_to_le64(sector);
-       crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv);
+       crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv);
+       return 0;
+}
+
+static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
+                             const char *opts)
+{
+       unsigned int bs = crypto_blkcipher_blocksize(cc->tfm);
+       int log = ilog2(bs);
+
+       /* we need to calculate how far we must shift the sector count
+        * to get the cipher block count, we use this shift in _gen */
+
+       if (1 << log != bs) {
+               ti->error = "cypher blocksize is not a power of 2";
+               return -EINVAL;
+       }
+
+       if (log > 9) {
+               ti->error = "cypher blocksize is > 512";
+               return -EINVAL;
+       }
+
+       cc->iv_gen_private.benbi_shift = 9 - log;
+
+       return 0;
+}
+
+static void crypt_iv_benbi_dtr(struct crypt_config *cc)
+{
+}
+
+static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+       __be64 val;
+
+       memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
+
+       val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1);
+       put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
+
        return 0;
 }
 
@@ -219,13 +266,18 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
        .generator = crypt_iv_essiv_gen
 };
 
+static struct crypt_iv_operations crypt_iv_benbi_ops = {
+       .ctr       = crypt_iv_benbi_ctr,
+       .dtr       = crypt_iv_benbi_dtr,
+       .generator = crypt_iv_benbi_gen
+};
 
 static int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                           struct scatterlist *in, unsigned int length,
                           int write, sector_t sector)
 {
-       u8 iv[cc->iv_size];
+       u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64))));
        struct blkcipher_desc desc = {
                .tfm = cc->tfm,
                .info = iv,
@@ -458,11 +510,11 @@ static void dec_pending(struct crypt_io *io, int error)
  * interrupt context.
  */
 static struct workqueue_struct *_kcryptd_workqueue;
-static void kcryptd_do_work(void *data);
+static void kcryptd_do_work(struct work_struct *work);
 
 static void kcryptd_queue_io(struct crypt_io *io)
 {
-       INIT_WORK(&io->work, kcryptd_do_work, io);
+       INIT_WORK(&io->work, kcryptd_do_work);
        queue_work(_kcryptd_workqueue, &io->work);
 }
 
@@ -618,9 +670,9 @@ static void process_read_endio(struct crypt_io *io)
        dec_pending(io, crypt_convert(cc, &ctx));
 }
 
-static void kcryptd_do_work(void *data)
+static void kcryptd_do_work(struct work_struct *work)
 {
-       struct crypt_io *io = data;
+       struct crypt_io *io = container_of(work, struct crypt_io, work);
 
        if (io->post_process)
                process_read_endio(io);
@@ -768,7 +820,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        cc->tfm = tfm;
 
        /*
-        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>".
+        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi".
         * See comments at iv code
         */
 
@@ -778,6 +830,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                cc->iv_gen_ops = &crypt_iv_plain_ops;
        else if (strcmp(ivmode, "essiv") == 0)
                cc->iv_gen_ops = &crypt_iv_essiv_ops;
+       else if (strcmp(ivmode, "benbi") == 0)
+               cc->iv_gen_ops = &crypt_iv_benbi_ops;
        else {
                ti->error = "Invalid IV mode";
                goto bad2;
@@ -908,7 +962,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
        atomic_set(&io->pending, 0);
        kcryptd_queue_io(io);
 
-       return 0;
+       return DM_MAPIO_SUBMITTED;
 }
 
 static int crypt_status(struct dm_target *ti, status_type_t type,
index 2b2d45d..265c467 100644 (file)
@@ -40,7 +40,7 @@ static inline void free_bio(struct bio *bio)
 
 static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
 {
-       struct path *path = bio->bi_private;
+       struct dm_path *path = bio->bi_private;
 
        if (bio->bi_size)
                return 1;
@@ -61,7 +61,7 @@ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
        return 0;
 }
 
-static struct bio *get_failover_bio(struct path *path, unsigned data_size)
+static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size)
 {
        struct bio *bio;
        struct page *page;
@@ -96,7 +96,7 @@ static struct bio *get_failover_bio(struct path *path, unsigned data_size)
 }
 
 static struct request *get_failover_req(struct emc_handler *h,
-                                       struct bio *bio, struct path *path)
+                                       struct bio *bio, struct dm_path *path)
 {
        struct request *rq;
        struct block_device *bdev = bio->bi_bdev;
@@ -133,7 +133,7 @@ static struct request *get_failover_req(struct emc_handler *h,
 }
 
 static struct request *emc_trespass_get(struct emc_handler *h,
-                                       struct path *path)
+                                       struct dm_path *path)
 {
        struct bio *bio;
        struct request *rq;
@@ -191,7 +191,7 @@ static struct request *emc_trespass_get(struct emc_handler *h,
 }
 
 static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed,
-                       struct path *path)
+                       struct dm_path *path)
 {
        struct request *rq;
        struct request_queue *q = bdev_get_queue(path->dev->bdev);
index 15f5629..32eff28 100644 (file)
@@ -32,7 +32,7 @@ struct hw_handler_type {
        void (*destroy) (struct hw_handler *hwh);
 
        void (*pg_init) (struct hw_handler *hwh, unsigned bypassed,
-                        struct path *path);
+                        struct dm_path *path);
        unsigned (*error) (struct hw_handler *hwh, struct bio *bio);
        int (*status) (struct hw_handler *hwh, status_type_t type,
                       char *result, unsigned int maxlen);
index da663d2..4eb73d3 100644 (file)
@@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages)
  *---------------------------------------------------------------*/
 static inline void bio_set_region(struct bio *bio, unsigned region)
 {
-       bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region;
+       bio->bi_io_vec[bio->bi_max_vecs].bv_len = region;
 }
 
 static inline unsigned bio_get_region(struct bio *bio)
 {
-       return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len;
+       return bio->bi_io_vec[bio->bi_max_vecs].bv_len;
 }
 
 /*-----------------------------------------------------------------
@@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error)
                zero_fill_bio(bio);
 
        dec_count(io, bio_get_region(bio), error);
+       bio->bi_max_vecs++;
        bio_put(bio);
 
        return 0;
@@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
 
        while (remaining) {
                /*
-                * Allocate a suitably sized bio, we add an extra
-                * bvec for bio_get/set_region().
+                * Allocate a suitably sized-bio: we add an extra
+                * bvec for bio_get/set_region() and decrement bi_max_vecs
+                * to hide it from bio_add_page().
                 */
-               num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2;
+               num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
                bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios);
                bio->bi_sector = where->sector + (where->count - remaining);
                bio->bi_bdev = where->bdev;
                bio->bi_end_io = endio;
                bio->bi_private = io;
                bio->bi_destructor = dm_bio_destructor;
+               bio->bi_max_vecs--;
                bio_set_region(bio, region);
 
                /*
@@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
        }
 
        /*
-        * Drop the extra refence that we were holding to avoid
+        * Drop the extra reference that we were holding to avoid
         * the io being completed too early.
         */
        dec_count(io, 0, 0);
index 4510ad8..cd6a184 100644 (file)
@@ -765,7 +765,7 @@ out:
 static int do_suspend(struct dm_ioctl *param)
 {
        int r = 0;
-       int do_lockfs = 1;
+       unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
        struct mapped_device *md;
 
        md = find_device(param);
@@ -773,10 +773,12 @@ static int do_suspend(struct dm_ioctl *param)
                return -ENXIO;
 
        if (param->flags & DM_SKIP_LOCKFS_FLAG)
-               do_lockfs = 0;
+               suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
+       if (param->flags & DM_NOFLUSH_FLAG)
+               suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
 
        if (!dm_suspended(md))
-               r = dm_suspend(md, do_lockfs);
+               r = dm_suspend(md, suspend_flags);
 
        if (!r)
                r = __dev_status(md, param);
@@ -788,7 +790,7 @@ static int do_suspend(struct dm_ioctl *param)
 static int do_resume(struct dm_ioctl *param)
 {
        int r = 0;
-       int do_lockfs = 1;
+       unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
        struct hash_cell *hc;
        struct mapped_device *md;
        struct dm_table *new_map;
@@ -814,9 +816,11 @@ static int do_resume(struct dm_ioctl *param)
        if (new_map) {
                /* Suspend if it isn't already suspended */
                if (param->flags & DM_SKIP_LOCKFS_FLAG)
-                       do_lockfs = 0;
+                       suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
+               if (param->flags & DM_NOFLUSH_FLAG)
+                       suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
                if (!dm_suspended(md))
-                       dm_suspend(md, do_lockfs);
+                       dm_suspend(md, suspend_flags);
 
                r = dm_swap_table(md, new_map);
                if (r) {
index 0023490..17753d8 100644 (file)
@@ -77,7 +77,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio,
        bio->bi_bdev = lc->dev->bdev;
        bio->bi_sector = lc->start + (bio->bi_sector - ti->begin);
 
-       return 1;
+       return DM_MAPIO_REMAPPED;
 }
 
 static int linear_status(struct dm_target *ti, status_type_t type,
@@ -108,7 +108,7 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode,
        struct dentry fake_dentry = {};
 
        fake_file.f_mode = lc->dev->mode;
-       fake_file.f_dentry = &fake_dentry;
+       fake_file.f_path.dentry = &fake_dentry;
        fake_dentry.d_inode = bdev->bd_inode;
 
        return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
index 64b764b..6a92613 100644 (file)
@@ -466,6 +466,7 @@ static int disk_resume(struct dirty_log *log)
        /* copy clean across to sync */
        memcpy(lc->sync_bits, lc->clean_bits, size);
        lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count);
+       lc->sync_search = 0;
 
        /* set the correct number of regions in the header */
        lc->header.nr_regions = lc->region_count;
@@ -480,6 +481,13 @@ static uint32_t core_get_region_size(struct dirty_log *log)
        return lc->region_size;
 }
 
+static int core_resume(struct dirty_log *log)
+{
+       struct log_c *lc = (struct log_c *) log->context;
+       lc->sync_search = 0;
+       return 0;
+}
+
 static int core_is_clean(struct dirty_log *log, region_t region)
 {
        struct log_c *lc = (struct log_c *) log->context;
@@ -549,16 +557,19 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
        return 1;
 }
 
-static void core_complete_resync_work(struct dirty_log *log, region_t region,
-                                     int success)
+static void core_set_region_sync(struct dirty_log *log, region_t region,
+                                int in_sync)
 {
        struct log_c *lc = (struct log_c *) log->context;
 
        log_clear_bit(lc, lc->recovering_bits, region);
-       if (success) {
+       if (in_sync) {
                log_set_bit(lc, lc->sync_bits, region);
                 lc->sync_count++;
-        }
+        } else if (log_test_bit(lc->sync_bits, region)) {
+               lc->sync_count--;
+               log_clear_bit(lc, lc->sync_bits, region);
+       }
 }
 
 static region_t core_get_sync_count(struct dirty_log *log)
@@ -618,6 +629,7 @@ static struct dirty_log_type _core_type = {
        .module = THIS_MODULE,
        .ctr = core_ctr,
        .dtr = core_dtr,
+       .resume = core_resume,
        .get_region_size = core_get_region_size,
        .is_clean = core_is_clean,
        .in_sync = core_in_sync,
@@ -625,7 +637,7 @@ static struct dirty_log_type _core_type = {
        .mark_region = core_mark_region,
        .clear_region = core_clear_region,
        .get_resync_work = core_get_resync_work,
-       .complete_resync_work = core_complete_resync_work,
+       .set_region_sync = core_set_region_sync,
        .get_sync_count = core_get_sync_count,
        .status = core_status,
 };
@@ -644,7 +656,7 @@ static struct dirty_log_type _disk_type = {
        .mark_region = core_mark_region,
        .clear_region = core_clear_region,
        .get_resync_work = core_get_resync_work,
-       .complete_resync_work = core_complete_resync_work,
+       .set_region_sync = core_set_region_sync,
        .get_sync_count = core_get_sync_count,
        .status = disk_status,
 };
index 5ae5309..86a301c 100644 (file)
@@ -90,12 +90,12 @@ struct dirty_log_type {
        int (*get_resync_work)(struct dirty_log *log, region_t *region);
 
        /*
-        * This notifies the log that the resync of an area has
-        * been completed.  The log should then mark this region
-        * as CLEAN.
+        * This notifies the log that the resync status of a region
+        * has changed.  It also clears the region from the recovering
+        * list (if present).
         */
-       void (*complete_resync_work)(struct dirty_log *log,
-                                    region_t region, int success);
+       void (*set_region_sync)(struct dirty_log *log,
+                               region_t region, int in_sync);
 
         /*
         * Returns the number of regions that are in sync.
index d754e0b..3aa0135 100644 (file)
@@ -31,7 +31,7 @@ struct pgpath {
        struct priority_group *pg;      /* Owning PG */
        unsigned fail_count;            /* Cumulative failure count */
 
-       struct path path;
+       struct dm_path path;
 };
 
 #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -101,11 +101,11 @@ typedef int (*action_fn) (struct pgpath *pgpath);
 
 #define MIN_IOS 256    /* Mempool size */
 
-static kmem_cache_t *_mpio_cache;
+static struct kmem_cache *_mpio_cache;
 
 struct workqueue_struct *kmultipathd;
-static void process_queued_ios(void *data);
-static void trigger_event(void *data);
+static void process_queued_ios(struct work_struct *work);
+static void trigger_event(struct work_struct *work);
 
 
 /*-----------------------------------------------
@@ -173,8 +173,8 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
                INIT_LIST_HEAD(&m->priority_groups);
                spin_lock_init(&m->lock);
                m->queue_io = 1;
-               INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
-               INIT_WORK(&m->trigger_event, trigger_event, m);
+               INIT_WORK(&m->process_queued_ios, process_queued_ios);
+               INIT_WORK(&m->trigger_event, trigger_event);
                m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
                if (!m->mpio_pool) {
                        kfree(m);
@@ -229,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
 
 static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
 {
-       struct path *path;
+       struct dm_path *path;
 
        path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
        if (!path)
@@ -282,10 +282,27 @@ failed:
        m->current_pg = NULL;
 }
 
+/*
+ * Check whether bios must be queued in the device-mapper core rather
+ * than here in the target.
+ *
+ * m->lock must be held on entry.
+ *
+ * If m->queue_if_no_path and m->saved_queue_if_no_path hold the
+ * same value then we are not between multipath_presuspend()
+ * and multipath_resume() calls and we have no need to check
+ * for the DMF_NOFLUSH_SUSPENDING flag.
+ */
+static int __must_push_back(struct multipath *m)
+{
+       return (m->queue_if_no_path != m->saved_queue_if_no_path &&
+               dm_noflush_suspending(m->ti));
+}
+
 static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
                  unsigned was_queued)
 {
-       int r = 1;
+       int r = DM_MAPIO_REMAPPED;
        unsigned long flags;
        struct pgpath *pgpath;
 
@@ -310,11 +327,13 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
                    !m->queue_io)
                        queue_work(kmultipathd, &m->process_queued_ios);
                pgpath = NULL;
-               r = 0;
-       } else if (!pgpath)
-               r = -EIO;               /* Failed */
-       else
+               r = DM_MAPIO_SUBMITTED;
+       } else if (pgpath)
                bio->bi_bdev = pgpath->path.dev->bdev;
+       else if (__must_push_back(m))
+               r = DM_MAPIO_REQUEUE;
+       else
+               r = -EIO;       /* Failed */
 
        mpio->pgpath = pgpath;
 
@@ -372,16 +391,19 @@ static void dispatch_queued_ios(struct multipath *m)
                r = map_io(m, bio, mpio, 1);
                if (r < 0)
                        bio_endio(bio, bio->bi_size, r);
-               else if (r == 1)
+               else if (r == DM_MAPIO_REMAPPED)
                        generic_make_request(bio);
+               else if (r == DM_MAPIO_REQUEUE)
+                       bio_endio(bio, bio->bi_size, -EIO);
 
                bio = next;
        }
 }
 
-static void process_queued_ios(void *data)
+static void process_queued_ios(struct work_struct *work)
 {
-       struct multipath *m = (struct multipath *) data;
+       struct multipath *m =
+               container_of(work, struct multipath, process_queued_ios);
        struct hw_handler *hwh = &m->hw_handler;
        struct pgpath *pgpath = NULL;
        unsigned init_required = 0, must_queue = 1;
@@ -421,9 +443,10 @@ out:
  * An event is triggered whenever a path is taken out of use.
  * Includes path failure and PG bypass.
  */
-static void trigger_event(void *data)
+static void trigger_event(struct work_struct *work)
 {
-       struct multipath *m = (struct multipath *) data;
+       struct multipath *m =
+               container_of(work, struct multipath, trigger_event);
 
        dm_table_event(m->ti->table);
 }
@@ -781,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
        map_context->ptr = mpio;
        bio->bi_rw |= (1 << BIO_RW_FAILFAST);
        r = map_io(m, bio, mpio, 0);
-       if (r < 0)
+       if (r < 0 || r == DM_MAPIO_REQUEUE)
                mempool_free(mpio, m->mpio_pool);
 
        return r;
@@ -955,7 +978,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
 /*
  * pg_init must call this when it has completed its initialisation
  */
-void dm_pg_init_complete(struct path *path, unsigned err_flags)
+void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
 {
        struct pgpath *pgpath = path_to_pgpath(path);
        struct priority_group *pg = pgpath->pg;
@@ -1005,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio,
 
        spin_lock_irqsave(&m->lock, flags);
        if (!m->nr_valid_paths) {
-               if (!m->queue_if_no_path) {
+               if (__must_push_back(m)) {
+                       spin_unlock_irqrestore(&m->lock, flags);
+                       return DM_ENDIO_REQUEUE;
+               } else if (!m->queue_if_no_path) {
                        spin_unlock_irqrestore(&m->lock, flags);
                        return -EIO;
                } else {
@@ -1040,7 +1066,7 @@ static int do_end_io(struct multipath *m, struct bio *bio,
                queue_work(kmultipathd, &m->process_queued_ios);
        spin_unlock_irqrestore(&m->lock, flags);
 
-       return 1;       /* io not complete */
+       return DM_ENDIO_INCOMPLETE;     /* io not complete */
 }
 
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
@@ -1058,7 +1084,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio,
                if (ps->type->end_io)
                        ps->type->end_io(ps, &pgpath->path);
        }
-       if (r <= 0)
+       if (r != DM_ENDIO_INCOMPLETE)
                mempool_free(mpio, m->mpio_pool);
 
        return r;
@@ -1270,7 +1296,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
        struct dentry fake_dentry = {};
        int r = 0;
 
-       fake_file.f_dentry = &fake_dentry;
+       fake_file.f_path.dentry = &fake_dentry;
 
        spin_lock_irqsave(&m->lock, flags);
 
index 8a4bf2b..b9cdcbb 100644 (file)
@@ -11,7 +11,7 @@
 
 struct dm_dev;
 
-struct path {
+struct dm_path {
        struct dm_dev *dev;     /* Read-only */
        unsigned is_active;     /* Read-only */
 
@@ -20,6 +20,6 @@ struct path {
 };
 
 /* Callback for hwh_pg_init_fn to use when complete */
-void dm_pg_init_complete(struct path *path, unsigned err_flags);
+void dm_pg_init_complete(struct dm_path *path, unsigned err_flags);
 
 #endif
index 732d06a..27357b8 100644 (file)
@@ -44,7 +44,7 @@ struct path_selector_type {
         * Add an opaque path object, along with some selector specific
         * path args (eg, path priority).
         */
-       int (*add_path) (struct path_selector *ps, struct path *path,
+       int (*add_path) (struct path_selector *ps, struct dm_path *path,
                         int argc, char **argv, char **error);
 
        /*
@@ -55,27 +55,27 @@ struct path_selector_type {
         * calling the function again.  0 means don't call it again unless
         * the path fails.
         */
-       struct path *(*select_path) (struct path_selector *ps,
+       struct dm_path *(*select_path) (struct path_selector *ps,
                                     unsigned *repeat_count);
 
        /*
         * Notify the selector that a path has failed.
         */
-       void (*fail_path) (struct path_selector *ps, struct path *p);
+       void (*fail_path) (struct path_selector *ps, struct dm_path *p);
 
        /*
         * Ask selector to reinstate a path.
         */
-       int (*reinstate_path) (struct path_selector *ps, struct path *p);
+       int (*reinstate_path) (struct path_selector *ps, struct dm_path *p);
 
        /*
         * Table content based on parameters added in ps_add_path_fn
         * or path selector status
         */
-       int (*status) (struct path_selector *ps, struct path *path,
+       int (*status) (struct path_selector *ps, struct dm_path *path,
                       status_type_t type, char *result, unsigned int maxlen);
 
-       int (*end_io) (struct path_selector *ps, struct path *path);
+       int (*end_io) (struct path_selector *ps, struct dm_path *path);
 };
 
 /* Register a path selector */
index 48a653b..23a6426 100644 (file)
@@ -344,6 +344,17 @@ static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list)
        }
 }
 
+static void complete_resync_work(struct region *reg, int success)
+{
+       struct region_hash *rh = reg->rh;
+
+       rh->log->type->set_region_sync(rh->log, reg->key, success);
+       dispatch_bios(rh->ms, &reg->delayed_bios);
+       if (atomic_dec_and_test(&rh->recovery_in_flight))
+               wake_up_all(&_kmirrord_recovery_stopped);
+       up(&rh->recovery_count);
+}
+
 static void rh_update_states(struct region_hash *rh)
 {
        struct region *reg, *next;
@@ -383,11 +394,7 @@ static void rh_update_states(struct region_hash *rh)
         */
        list_for_each_entry_safe (reg, next, &recovered, list) {
                rh->log->type->clear_region(rh->log, reg->key);
-               rh->log->type->complete_resync_work(rh->log, reg->key, 1);
-               dispatch_bios(rh->ms, &reg->delayed_bios);
-               if (atomic_dec_and_test(&rh->recovery_in_flight))
-                       wake_up_all(&_kmirrord_recovery_stopped);
-               up(&rh->recovery_count);
+               complete_resync_work(reg, 1);
                mempool_free(reg, rh->region_pool);
        }
 
@@ -883,7 +890,7 @@ static void do_mirror(struct mirror_set *ms)
        do_writes(ms, &writes);
 }
 
-static void do_work(void *ignored)
+static void do_work(struct work_struct *ignored)
 {
        struct mirror_set *ms;
 
@@ -1137,7 +1144,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
 
        if (rw == WRITE) {
                queue_bio(ms, bio, rw);
-               return 0;
+               return DM_MAPIO_SUBMITTED;
        }
 
        r = ms->rh.log->type->in_sync(ms->rh.log,
@@ -1146,7 +1153,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
                return r;
 
        if (r == -EWOULDBLOCK)  /* FIXME: ugly */
-               r = 0;
+               r = DM_MAPIO_SUBMITTED;
 
        /*
         * We don't want to fast track a recovery just for a read
@@ -1159,7 +1166,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
        if (!r) {
                /* Pass this io over to the daemon */
                queue_bio(ms, bio, rw);
-               return 0;
+               return DM_MAPIO_SUBMITTED;
        }
 
        m = choose_mirror(ms, bio->bi_sector);
@@ -1167,7 +1174,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
                return -EIO;
 
        map_bio(ms, m, bio);
-       return 1;
+       return DM_MAPIO_REMAPPED;
 }
 
 static int mirror_end_io(struct dm_target *ti, struct bio *bio,
@@ -1269,7 +1276,7 @@ static int __init dm_mirror_init(void)
                dm_dirty_log_exit();
                return r;
        }
-       INIT_WORK(&_kmirrord_work, do_work, NULL);
+       INIT_WORK(&_kmirrord_work, do_work);
 
        r = dm_register_target(&mirror_target);
        if (r < 0) {
index 6f9fcd4..a348a97 100644 (file)
@@ -21,7 +21,7 @@
  *---------------------------------------------------------------*/
 struct path_info {
        struct list_head list;
-       struct path *path;
+       struct dm_path *path;
        unsigned repeat_count;
 };
 
@@ -80,7 +80,7 @@ static void rr_destroy(struct path_selector *ps)
        ps->context = NULL;
 }
 
-static int rr_status(struct path_selector *ps, struct path *path,
+static int rr_status(struct path_selector *ps, struct dm_path *path,
                     status_type_t type, char *result, unsigned int maxlen)
 {
        struct path_info *pi;
@@ -106,7 +106,7 @@ static int rr_status(struct path_selector *ps, struct path *path,
  * Called during initialisation to register each path with an
  * optional repeat_count.
  */
-static int rr_add_path(struct path_selector *ps, struct path *path,
+static int rr_add_path(struct path_selector *ps, struct dm_path *path,
                       int argc, char **argv, char **error)
 {
        struct selector *s = (struct selector *) ps->context;
@@ -141,7 +141,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path,
        return 0;
 }
 
-static void rr_fail_path(struct path_selector *ps, struct path *p)
+static void rr_fail_path(struct path_selector *ps, struct dm_path *p)
 {
        struct selector *s = (struct selector *) ps->context;
        struct path_info *pi = p->pscontext;
@@ -149,7 +149,7 @@ static void rr_fail_path(struct path_selector *ps, struct path *p)
        list_move(&pi->list, &s->invalid_paths);
 }
 
-static int rr_reinstate_path(struct path_selector *ps, struct path *p)
+static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p)
 {
        struct selector *s = (struct selector *) ps->context;
        struct path_info *pi = p->pscontext;
@@ -159,7 +159,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct path *p)
        return 0;
 }
 
-static struct path *rr_select_path(struct path_selector *ps,
+static struct dm_path *rr_select_path(struct path_selector *ps,
                                   unsigned *repeat_count)
 {
        struct selector *s = (struct selector *) ps->context;
index 5281e00..0821a2b 100644 (file)
@@ -39,8 +39,8 @@
  */
 #define SNAPSHOT_PAGES 256
 
-struct workqueue_struct *ksnapd;
-static void flush_queued_bios(void *data);
+static struct workqueue_struct *ksnapd;
+static void flush_queued_bios(struct work_struct *work);
 
 struct pending_exception {
        struct exception e;
@@ -88,8 +88,8 @@ struct pending_exception {
  * Hash table mapping origin volumes to lists of snapshots and
  * a lock to protect it
  */
-static kmem_cache_t *exception_cache;
-static kmem_cache_t *pending_cache;
+static struct kmem_cache *exception_cache;
+static struct kmem_cache *pending_cache;
 static mempool_t *pending_pool;
 
 /*
@@ -228,7 +228,7 @@ static int init_exception_table(struct exception_table *et, uint32_t size)
        return 0;
 }
 
-static void exit_exception_table(struct exception_table *et, kmem_cache_t *mem)
+static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem)
 {
        struct list_head *slot;
        struct exception *ex, *next;
@@ -528,7 +528,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        bio_list_init(&s->queued_bios);
-       INIT_WORK(&s->queued_bios_work, flush_queued_bios, s);
+       INIT_WORK(&s->queued_bios_work, flush_queued_bios);
 
        /* Add snapshot to the list of snapshots for this origin */
        /* Exceptions aren't triggered till snapshot_resume() is called */
@@ -564,6 +564,17 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        return r;
 }
 
+static void __free_exceptions(struct dm_snapshot *s)
+{
+       kcopyd_client_destroy(s->kcopyd_client);
+       s->kcopyd_client = NULL;
+
+       exit_exception_table(&s->pending, pending_cache);
+       exit_exception_table(&s->complete, exception_cache);
+
+       s->store.destroy(&s->store);
+}
+
 static void snapshot_dtr(struct dm_target *ti)
 {
        struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
@@ -574,13 +585,7 @@ static void snapshot_dtr(struct dm_target *ti)
        /* After this returns there can be no new kcopyd jobs. */
        unregister_snapshot(s);
 
-       kcopyd_client_destroy(s->kcopyd_client);
-
-       exit_exception_table(&s->pending, pending_cache);
-       exit_exception_table(&s->complete, exception_cache);
-
-       /* Deallocate memory used */
-       s->store.destroy(&s->store);
+       __free_exceptions(s);
 
        dm_put_device(ti, s->origin);
        dm_put_device(ti, s->cow);
@@ -603,9 +608,10 @@ static void flush_bios(struct bio *bio)
        }
 }
 
-static void flush_queued_bios(void *data)
+static void flush_queued_bios(struct work_struct *work)
 {
-       struct dm_snapshot *s = (struct dm_snapshot *) data;
+       struct dm_snapshot *s =
+               container_of(work, struct dm_snapshot, queued_bios_work);
        struct bio *queued_bios;
        unsigned long flags;
 
@@ -867,7 +873,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
 {
        struct exception *e;
        struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
-       int r = 1;
+       int r = DM_MAPIO_REMAPPED;
        chunk_t chunk;
        struct pending_exception *pe = NULL;
 
@@ -913,7 +919,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
                remap_exception(s, &pe->e, bio);
                bio_list_add(&pe->snapshot_bios, bio);
 
-               r = 0;
+               r = DM_MAPIO_SUBMITTED;
 
                if (!pe->started) {
                        /* this is protected by snap->lock */
@@ -991,7 +997,7 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
  *---------------------------------------------------------------*/
 static int __origin_write(struct list_head *snapshots, struct bio *bio)
 {
-       int r = 1, first = 0;
+       int r = DM_MAPIO_REMAPPED, first = 0;
        struct dm_snapshot *snap;
        struct exception *e;
        struct pending_exception *pe, *next_pe, *primary_pe = NULL;
@@ -1049,7 +1055,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
 
                        bio_list_add(&primary_pe->origin_bios, bio);
 
-                       r = 0;
+                       r = DM_MAPIO_SUBMITTED;
                }
 
                if (!pe->primary_pe) {
@@ -1098,7 +1104,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
 static int do_origin(struct dm_dev *origin, struct bio *bio)
 {
        struct origin *o;
-       int r = 1;
+       int r = DM_MAPIO_REMAPPED;
 
        down_read(&_origins_lock);
        o = __lookup_origin(origin->bdev);
@@ -1155,7 +1161,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
                return -EOPNOTSUPP;
 
        /* Only tell snapshots if this is a write */
-       return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
+       return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
 }
 
 #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
index 6c29fce..51f5e07 100644 (file)
@@ -186,7 +186,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
        bio->bi_bdev = sc->stripe[stripe].dev->bdev;
        bio->bi_sector = sc->stripe[stripe].physical_start +
            (chunk << sc->chunk_shift) + (offset & sc->chunk_mask);
-       return 1;
+       return DM_MAPIO_REMAPPED;
 }
 
 static int stripe_status(struct dm_target *ti,
index ea569f7..f314d7d 100644 (file)
@@ -46,7 +46,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio,
        bio_endio(bio, bio->bi_size, 0);
 
        /* accepted bio, don't make new request */
-       return 0;
+       return DM_MAPIO_SUBMITTED;
 }
 
 static struct target_type zero_target = {
index fc4f743..fe7c56e 100644 (file)
@@ -68,10 +68,12 @@ union map_info *dm_get_mapinfo(struct bio *bio)
 #define DMF_FROZEN 2
 #define DMF_FREEING 3
 #define DMF_DELETING 4
+#define DMF_NOFLUSH_SUSPENDING 5
 
 struct mapped_device {
        struct rw_semaphore io_lock;
        struct semaphore suspend_lock;
+       spinlock_t pushback_lock;
        rwlock_t map_lock;
        atomic_t holders;
        atomic_t open_count;
@@ -89,7 +91,8 @@ struct mapped_device {
         */
        atomic_t pending;
        wait_queue_head_t wait;
-       struct bio_list deferred;
+       struct bio_list deferred;
+       struct bio_list pushback;
 
        /*
         * The current mapping.
@@ -121,8 +124,8 @@ struct mapped_device {
 };
 
 #define MIN_IOS 256
-static kmem_cache_t *_io_cache;
-static kmem_cache_t *_tio_cache;
+static struct kmem_cache *_io_cache;
+static struct kmem_cache *_tio_cache;
 
 static int __init local_init(void)
 {
@@ -444,23 +447,50 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo)
  *   you this clearly demarcated crap.
  *---------------------------------------------------------------*/
 
+static int __noflush_suspending(struct mapped_device *md)
+{
+       return test_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+}
+
 /*
  * Decrements the number of outstanding ios that a bio has been
  * cloned into, completing the original io if necc.
  */
 static void dec_pending(struct dm_io *io, int error)
 {
-       if (error)
+       unsigned long flags;
+
+       /* Push-back supersedes any I/O errors */
+       if (error && !(io->error > 0 && __noflush_suspending(io->md)))
                io->error = error;
 
        if (atomic_dec_and_test(&io->io_count)) {
+               if (io->error == DM_ENDIO_REQUEUE) {
+                       /*
+                        * Target requested pushing back the I/O.
+                        * This must be handled before the sleeper on
+                        * suspend queue merges the pushback list.
+                        */
+                       spin_lock_irqsave(&io->md->pushback_lock, flags);
+                       if (__noflush_suspending(io->md))
+                               bio_list_add(&io->md->pushback, io->bio);
+                       else
+                               /* noflush suspend was interrupted. */
+                               io->error = -EIO;
+                       spin_unlock_irqrestore(&io->md->pushback_lock, flags);
+               }
+
                if (end_io_acct(io))
                        /* nudge anyone waiting on suspend queue */
                        wake_up(&io->md->wait);
 
-               blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE);
+               if (io->error != DM_ENDIO_REQUEUE) {
+                       blk_add_trace_bio(io->md->queue, io->bio,
+                                         BLK_TA_COMPLETE);
+
+                       bio_endio(io->bio, io->bio->bi_size, io->error);
+               }
 
-               bio_endio(io->bio, io->bio->bi_size, io->error);
                free_io(io->md, io);
        }
 }
@@ -480,12 +510,19 @@ static int clone_endio(struct bio *bio, unsigned int done, int error)
 
        if (endio) {
                r = endio(tio->ti, bio, error, &tio->info);
-               if (r < 0)
+               if (r < 0 || r == DM_ENDIO_REQUEUE)
+                       /*
+                        * error and requeue request are handled
+                        * in dec_pending().
+                        */
                        error = r;
-
-               else if (r > 0)
-                       /* the target wants another shot at the io */
+               else if (r == DM_ENDIO_INCOMPLETE)
+                       /* The target will handle the io */
                        return 1;
+               else if (r) {
+                       DMWARN("unimplemented target endio return value: %d", r);
+                       BUG();
+               }
        }
 
        dec_pending(tio->io, error);
@@ -543,7 +580,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
        atomic_inc(&tio->io->io_count);
        sector = clone->bi_sector;
        r = ti->type->map(ti, clone, &tio->info);
-       if (r > 0) {
+       if (r == DM_MAPIO_REMAPPED) {
                /* the bio has been remapped so dispatch it */
 
                blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone,
@@ -551,10 +588,8 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
                                    clone->bi_sector);
 
                generic_make_request(clone);
-       }
-
-       else if (r < 0) {
-               /* error the io and bail out */
+       } else if (r < 0 || r == DM_MAPIO_REQUEUE) {
+               /* error the io and bail out, or requeue it if needed */
                md = tio->io->md;
                dec_pending(tio->io, r);
                /*
@@ -563,6 +598,9 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
                clone->bi_private = md->bs;
                bio_put(clone);
                free_tio(md, tio);
+       } else if (r) {
+               DMWARN("unimplemented target map return value: %d", r);
+               BUG();
        }
 }
 
@@ -948,6 +986,7 @@ static struct mapped_device *alloc_dev(int minor)
        memset(md, 0, sizeof(*md));
        init_rwsem(&md->io_lock);
        init_MUTEX(&md->suspend_lock);
+       spin_lock_init(&md->pushback_lock);
        rwlock_init(&md->map_lock);
        atomic_set(&md->holders, 1);
        atomic_set(&md->open_count, 0);
@@ -966,8 +1005,8 @@ static struct mapped_device *alloc_dev(int minor)
        md->queue->issue_flush_fn = dm_flush_all;
 
        md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
-       if (!md->io_pool)
-               goto bad2;
+       if (!md->io_pool)
+               goto bad2;
 
        md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache);
        if (!md->tio_pool)
@@ -1275,12 +1314,15 @@ static void unlock_fs(struct mapped_device *md)
  * dm_bind_table, dm_suspend must be called to flush any in
  * flight bios and ensure that any further io gets deferred.
  */
-int dm_suspend(struct mapped_device *md, int do_lockfs)
+int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
 {
        struct dm_table *map = NULL;
+       unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);
        struct bio *def;
        int r = -EINVAL;
+       int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0;
+       int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0;
 
        down(&md->suspend_lock);
 
@@ -1289,6 +1331,13 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
 
        map = dm_get_table(md);
 
+       /*
+        * DMF_NOFLUSH_SUSPENDING must be set before presuspend.
+        * This flag is cleared before dm_suspend returns.
+        */
+       if (noflush)
+               set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+
        /* This does not get reverted if there's an error later. */
        dm_table_presuspend_targets(map);
 
@@ -1296,11 +1345,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
        if (!md->suspended_bdev) {
                DMWARN("bdget failed in dm_suspend");
                r = -ENOMEM;
-               goto out;
+               goto flush_and_out;
        }
 
-       /* Flush I/O to the device. */
-       if (do_lockfs) {
+       /*
+        * Flush I/O to the device.
+        * noflush supersedes do_lockfs, because lock_fs() needs to flush I/Os.
+        */
+       if (do_lockfs && !noflush) {
                r = lock_fs(md);
                if (r)
                        goto out;
@@ -1336,6 +1388,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
        down_write(&md->io_lock);
        remove_wait_queue(&md->wait, &wait);
 
+       if (noflush) {
+               spin_lock_irqsave(&md->pushback_lock, flags);
+               clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+               bio_list_merge_head(&md->deferred, &md->pushback);
+               bio_list_init(&md->pushback);
+               spin_unlock_irqrestore(&md->pushback_lock, flags);
+       }
+
        /* were we interrupted ? */
        r = -EINTR;
        if (atomic_read(&md->pending)) {
@@ -1344,7 +1404,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
                __flush_deferred_io(md, def);
                up_write(&md->io_lock);
                unlock_fs(md);
-               goto out;
+               goto out; /* pushback list is already flushed, so skip flush */
        }
        up_write(&md->io_lock);
 
@@ -1354,6 +1414,25 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
 
        r = 0;
 
+flush_and_out:
+       if (r && noflush) {
+               /*
+                * Because there may be already I/Os in the pushback list,
+                * flush them before return.
+                */
+               down_write(&md->io_lock);
+
+               spin_lock_irqsave(&md->pushback_lock, flags);
+               clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+               bio_list_merge_head(&md->deferred, &md->pushback);
+               bio_list_init(&md->pushback);
+               spin_unlock_irqrestore(&md->pushback_lock, flags);
+
+               def = bio_list_get(&md->deferred);
+               __flush_deferred_io(md, def);
+               up_write(&md->io_lock);
+       }
+
 out:
        if (r && md->suspended_bdev) {
                bdput(md->suspended_bdev);
@@ -1440,6 +1519,17 @@ int dm_suspended(struct mapped_device *md)
        return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+int dm_noflush_suspending(struct dm_target *ti)
+{
+       struct mapped_device *md = dm_table_get_md(ti->table);
+       int r = __noflush_suspending(md);
+
+       dm_put(md);
+
+       return r;
+}
+EXPORT_SYMBOL_GPL(dm_noflush_suspending);
+
 static struct block_device_operations dm_blk_dops = {
        .open = dm_blk_open,
        .release = dm_blk_close,
index a48ec5e..2f796b1 100644 (file)
 
 #define SECTOR_SHIFT 9
 
+/*
+ * Definitions of return values from target end_io function.
+ */
+#define DM_ENDIO_INCOMPLETE    1
+#define DM_ENDIO_REQUEUE       2
+
+/*
+ * Definitions of return values from target map function.
+ */
+#define DM_MAPIO_SUBMITTED     0
+#define DM_MAPIO_REMAPPED      1
+#define DM_MAPIO_REQUEUE       DM_ENDIO_REQUEUE
+
+/*
+ * Suspend feature flags
+ */
+#define DM_SUSPEND_LOCKFS_FLAG         (1 << 0)
+#define DM_SUSPEND_NOFLUSH_FLAG                (1 << 1)
+
 /*
  * List of devices that a metadevice uses and should open/close.
  */
index f1db6ef..b46f6c5 100644 (file)
@@ -203,7 +203,7 @@ struct kcopyd_job {
 /* FIXME: this should scale with the number of pages */
 #define MIN_JOBS 512
 
-static kmem_cache_t *_job_cache;
+static struct kmem_cache *_job_cache;
 static mempool_t *_job_pool;
 
 /*
@@ -417,7 +417,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
 /*
  * kcopyd does this every time it's woken up.
  */
-static void do_work(void *ignored)
+static void do_work(struct work_struct *ignored)
 {
        /*
         * The order that these are called is *very* important.
@@ -628,7 +628,7 @@ static int kcopyd_init(void)
        }
 
        kcopyd_clients++;
-       INIT_WORK(&_kcopyd_work, do_work, NULL);
+       INIT_WORK(&_kcopyd_work, do_work);
        mutex_unlock(&kcopyd_init_lock);
        return 0;
 }
index 8cbf9c9..21e2a7b 100644 (file)
 #include <linux/raid/bitmap.h>
 #include <linux/sysctl.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
-#include <linux/suspend.h>
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/ctype.h>
+#include <linux/freezer.h>
 
 #include <linux/init.h>
 
@@ -1413,7 +1413,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
        struct block_device *bdev;
        char b[BDEVNAME_SIZE];
 
-       bdev = open_partition_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+       bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
        if (IS_ERR(bdev)) {
                printk(KERN_ERR "md: could not open %s.\n",
                        __bdevname(dev, b));
@@ -1423,7 +1423,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
        if (err) {
                printk(KERN_ERR "md: could not bd_claim %s.\n",
                        bdevname(bdev, b));
-               blkdev_put_partition(bdev);
+               blkdev_put(bdev);
                return err;
        }
        rdev->bdev = bdev;
@@ -1437,7 +1437,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
        if (!bdev)
                MD_BUG();
        bd_release(bdev);
-       blkdev_put_partition(bdev);
+       blkdev_put(bdev);
 }
 
 void md_autodetect_dev(dev_t dev);
@@ -3314,6 +3314,10 @@ static int do_md_stop(mddev_t * mddev, int mode)
 
                        module_put(mddev->pers->owner);
                        mddev->pers = NULL;
+
+                       set_capacity(disk, 0);
+                       mddev->changed = 1;
+
                        if (mddev->ro)
                                mddev->ro = 0;
                }
@@ -3333,7 +3337,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
        if (mode == 0) {
                mdk_rdev_t *rdev;
                struct list_head *tmp;
-               struct gendisk *disk;
+
                printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
 
                bitmap_destroy(mddev);
@@ -3358,10 +3362,6 @@ static int do_md_stop(mddev_t * mddev, int mode)
                mddev->raid_disks = 0;
                mddev->recovery_cp = 0;
 
-               disk = mddev->gendisk;
-               if (disk)
-                       set_capacity(disk, 0);
-               mddev->changed = 1;
        } else if (mddev->pers)
                printk(KERN_INFO "md: %s switched to read-only mode.\n",
                        mdname(mddev));
@@ -3371,6 +3371,7 @@ out:
        return err;
 }
 
+#ifndef MODULE
 static void autorun_array(mddev_t *mddev)
 {
        mdk_rdev_t *rdev;
@@ -3485,6 +3486,7 @@ static void autorun_devices(int part)
        }
        printk(KERN_INFO "md: ... autorun DONE.\n");
 }
+#endif /* !MODULE */
 
 static int get_version(void __user * arg)
 {
@@ -3722,6 +3724,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                if (err)
                        export_rdev(rdev);
 
+               md_update_sb(mddev, 1);
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                md_wakeup_thread(mddev->thread);
                return err;
@@ -4423,7 +4426,7 @@ static int md_open(struct inode *inode, struct file *file)
        mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
        int err;
 
-       if ((err = mddev_lock(mddev)))
+       if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
                goto out;
 
        err = 0;
@@ -4846,8 +4849,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
                                chunk_kb ? "KB" : "B");
                        if (bitmap->file) {
                                seq_printf(seq, ", file: ");
-                               seq_path(seq, bitmap->file->f_vfsmnt,
-                                        bitmap->file->f_dentry," \t\n");
+                               seq_path(seq, bitmap->file->f_path.mnt,
+                                        bitmap->file->f_path.dentry," \t\n");
                        }
 
                        seq_printf(seq, "\n");
@@ -5273,7 +5276,6 @@ void md_do_sync(mddev_t *mddev)
        mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
 
        if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
-           test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
            !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
            mddev->curr_resync > 2) {
                if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
@@ -5297,6 +5299,7 @@ void md_do_sync(mddev_t *mddev)
                                        rdev->recovery_offset = mddev->curr_resync;
                }
        }
+       set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
  skip:
        mddev->curr_resync = 0;
@@ -5593,7 +5596,7 @@ static void autostart_arrays(int part)
        autorun_devices(part);
 }
 
-#endif
+#endif /* !MODULE */
 
 static __exit void md_exit(void)
 {
index 656fae9..b3c5e12 100644 (file)
@@ -1951,6 +1951,7 @@ static int run(mddev_t *mddev)
                    !test_bit(In_sync, &disk->rdev->flags)) {
                        disk->head_position = 0;
                        mddev->degraded++;
+                       conf->fullsync = 1;
                }
        }
        if (mddev->degraded == conf->raid_disks) {
index 69c3e20..377f8bc 100644 (file)
@@ -134,6 +134,8 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
                        if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
                                list_add_tail(&sh->lru, &conf->inactive_list);
                                wake_up(&conf->wait_for_stripe);
+                               if (conf->retry_read_aligned)
+                                       md_wakeup_thread(conf->mddev->thread);
                        }
                }
        }
@@ -348,7 +350,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
 
 static int grow_stripes(raid5_conf_t *conf, int num)
 {
-       kmem_cache_t *sc;
+       struct kmem_cache *sc;
        int devs = conf->raid_disks;
 
        sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev));
@@ -397,7 +399,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
        LIST_HEAD(newstripes);
        struct disk_info *ndisks;
        int err = 0;
-       kmem_cache_t *sc;
+       struct kmem_cache *sc;
        int i;
 
        if (newsize <= conf->pool_size)
@@ -542,35 +544,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
        }
 
        if (uptodate) {
-#if 0
-               struct bio *bio;
-               unsigned long flags;
-               spin_lock_irqsave(&conf->device_lock, flags);
-               /* we can return a buffer if we bypassed the cache or
-                * if the top buffer is not in highmem.  If there are
-                * multiple buffers, leave the extra work to
-                * handle_stripe
-                */
-               buffer = sh->bh_read[i];
-               if (buffer &&
-                   (!PageHighMem(buffer->b_page)
-                    || buffer->b_page == bh->b_page )
-                       ) {
-                       sh->bh_read[i] = buffer->b_reqnext;
-                       buffer->b_reqnext = NULL;
-               } else
-                       buffer = NULL;
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (sh->bh_page[i]==bh->b_page)
-                       set_buffer_uptodate(bh);
-               if (buffer) {
-                       if (buffer->b_page != bh->b_page)
-                               memcpy(buffer->b_data, bh->b_data, bh->b_size);
-                       buffer->b_end_io(buffer, 1);
-               }
-#else
                set_bit(R5_UPTODATE, &sh->dev[i].flags);
-#endif
                if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
                        rdev = conf->disks[i].rdev;
                        printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
@@ -616,14 +590,6 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
                }
        }
        rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-#if 0
-       /* must restore b_page before unlocking buffer... */
-       if (sh->bh_page[i] != bh->b_page) {
-               bh->b_page = sh->bh_page[i];
-               bh->b_data = page_address(bh->b_page);
-               clear_buffer_uptodate(bh);
-       }
-#endif
        clear_bit(R5_LOCKED, &sh->dev[i].flags);
        set_bit(STRIPE_HANDLE, &sh->state);
        release_stripe(sh);
@@ -821,7 +787,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
 static sector_t compute_blocknr(struct stripe_head *sh, int i)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int raid_disks = sh->disks, data_disks = raid_disks - 1;
+       int raid_disks = sh->disks;
+       int data_disks = raid_disks - conf->max_degraded;
        sector_t new_sector = sh->sector, check;
        int sectors_per_chunk = conf->chunk_size >> 9;
        sector_t stripe;
@@ -857,7 +824,6 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
                }
                break;
        case 6:
-               data_disks = raid_disks - 2;
                if (i == raid6_next_disk(sh->pd_idx, raid_disks))
                        return 0; /* It is the Q disk */
                switch (conf->algorithm) {
@@ -1353,8 +1319,10 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
        int pd_idx, dd_idx;
        int chunk_offset = sector_div(stripe, sectors_per_chunk);
 
-       raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk
-                            + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf);
+       raid5_compute_sector(stripe * (disks - conf->max_degraded)
+                            *sectors_per_chunk + chunk_offset,
+                            disks, disks - conf->max_degraded,
+                            &dd_idx, &pd_idx, conf);
        return pd_idx;
 }
 
@@ -1615,15 +1583,6 @@ static void handle_stripe5(struct stripe_head *sh)
                                } else if (test_bit(R5_Insync, &dev->flags)) {
                                        set_bit(R5_LOCKED, &dev->flags);
                                        set_bit(R5_Wantread, &dev->flags);
-#if 0
-                                       /* if I am just reading this block and we don't have
-                                          a failed drive, or any pending writes then sidestep the cache */
-                                       if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
-                                           ! syncing && !failed && !to_write) {
-                                               sh->bh_cache[i]->b_page =  sh->bh_read[i]->b_page;
-                                               sh->bh_cache[i]->b_data =  sh->bh_read[i]->b_data;
-                                       }
-#endif
                                        locked++;
                                        PRINTK("Reading block %d (sync=%d)\n", 
                                                i, syncing);
@@ -1641,9 +1600,6 @@ static void handle_stripe5(struct stripe_head *sh)
                        dev = &sh->dev[i];
                        if ((dev->towrite || i == sh->pd_idx) &&
                            (!test_bit(R5_LOCKED, &dev->flags) 
-#if 0
-|| sh->bh_page[i]!=bh->b_page
-#endif
                                    ) &&
                            !test_bit(R5_UPTODATE, &dev->flags)) {
                                if (test_bit(R5_Insync, &dev->flags)
@@ -1655,9 +1611,6 @@ static void handle_stripe5(struct stripe_head *sh)
                        /* Would I have to read this buffer for reconstruct_write */
                        if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
                            (!test_bit(R5_LOCKED, &dev->flags) 
-#if 0
-|| sh->bh_page[i] != bh->b_page
-#endif
                                    ) &&
                            !test_bit(R5_UPTODATE, &dev->flags)) {
                                if (test_bit(R5_Insync, &dev->flags)) rcw++;
@@ -1865,7 +1818,9 @@ static void handle_stripe5(struct stripe_head *sh)
                return_bi = bi->bi_next;
                bi->bi_next = NULL;
                bi->bi_size = 0;
-               bi->bi_end_io(bi, bytes, 0);
+               bi->bi_end_io(bi, bytes,
+                             test_bit(BIO_UPTODATE, &bi->bi_flags)
+                               ? 0 : -EIO);
        }
        for (i=disks; i-- ;) {
                int rw;
@@ -2193,15 +2148,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                                } else if (test_bit(R5_Insync, &dev->flags)) {
                                        set_bit(R5_LOCKED, &dev->flags);
                                        set_bit(R5_Wantread, &dev->flags);
-#if 0
-                                       /* if I am just reading this block and we don't have
-                                          a failed drive, or any pending writes then sidestep the cache */
-                                       if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
-                                           ! syncing && !failed && !to_write) {
-                                               sh->bh_cache[i]->b_page =  sh->bh_read[i]->b_page;
-                                               sh->bh_cache[i]->b_data =  sh->bh_read[i]->b_data;
-                                       }
-#endif
                                        locked++;
                                        PRINTK("Reading block %d (sync=%d)\n",
                                                i, syncing);
@@ -2220,9 +2166,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                        if (!test_bit(R5_OVERWRITE, &dev->flags)
                            && i != pd_idx && i != qd_idx
                            && (!test_bit(R5_LOCKED, &dev->flags)
-#if 0
-                               || sh->bh_page[i] != bh->b_page
-#endif
                                    ) &&
                            !test_bit(R5_UPTODATE, &dev->flags)) {
                                if (test_bit(R5_Insync, &dev->flags)) rcw++;
@@ -2418,7 +2361,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                return_bi = bi->bi_next;
                bi->bi_next = NULL;
                bi->bi_size = 0;
-               bi->bi_end_io(bi, bytes, 0);
+               bi->bi_end_io(bi, bytes,
+                             test_bit(BIO_UPTODATE, &bi->bi_flags)
+                               ? 0 : -EIO);
        }
        for (i=disks; i-- ;) {
                int rw;
@@ -2611,6 +2556,180 @@ static int raid5_congested(void *data, int bits)
        return 0;
 }
 
+/* We want read requests to align with chunks where possible,
+ * but write requests don't need to.
+ */
+static int raid5_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec)
+{
+       mddev_t *mddev = q->queuedata;
+       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       int max;
+       unsigned int chunk_sectors = mddev->chunk_size >> 9;
+       unsigned int bio_sectors = bio->bi_size >> 9;
+
+       if (bio_data_dir(bio))
+               return biovec->bv_len; /* always allow writes to be mergeable */
+
+       max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
+       if (max < 0) max = 0;
+       if (max <= biovec->bv_len && bio_sectors == 0)
+               return biovec->bv_len;
+       else
+               return max;
+}
+
+
+static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
+{
+       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       unsigned int chunk_sectors = mddev->chunk_size >> 9;
+       unsigned int bio_sectors = bio->bi_size >> 9;
+
+       return  chunk_sectors >=
+               ((sector & (chunk_sectors - 1)) + bio_sectors);
+}
+
+/*
+ *  add bio to the retry LIFO  ( in O(1) ... we are in interrupt )
+ *  later sampled by raid5d.
+ */
+static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&conf->device_lock, flags);
+
+       bi->bi_next = conf->retry_read_aligned_list;
+       conf->retry_read_aligned_list = bi;
+
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+       md_wakeup_thread(conf->mddev->thread);
+}
+
+
+static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+{
+       struct bio *bi;
+
+       bi = conf->retry_read_aligned;
+       if (bi) {
+               conf->retry_read_aligned = NULL;
+               return bi;
+       }
+       bi = conf->retry_read_aligned_list;
+       if(bi) {
+               conf->retry_read_aligned = bi->bi_next;
+               bi->bi_next = NULL;
+               bi->bi_phys_segments = 1; /* biased count of active stripes */
+               bi->bi_hw_segments = 0; /* count of processed stripes */
+       }
+
+       return bi;
+}
+
+
+/*
+ *  The "raid5_align_endio" should check if the read succeeded and if it
+ *  did, call bio_endio on the original bio (having bio_put the new bio
+ *  first).
+ *  If the read failed..
+ */
+static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error)
+{
+       struct bio* raid_bi  = bi->bi_private;
+       mddev_t *mddev;
+       raid5_conf_t *conf;
+       int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+       mdk_rdev_t *rdev;
+
+       if (bi->bi_size)
+               return 1;
+       bio_put(bi);
+
+       mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata;
+       conf = mddev_to_conf(mddev);
+       rdev = (void*)raid_bi->bi_next;
+       raid_bi->bi_next = NULL;
+
+       rdev_dec_pending(rdev, conf->mddev);
+
+       if (!error && uptodate) {
+               bio_endio(raid_bi, bytes, 0);
+               if (atomic_dec_and_test(&conf->active_aligned_reads))
+                       wake_up(&conf->wait_for_stripe);
+               return 0;
+       }
+
+
+       PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+
+       add_bio_to_retry(raid_bi, conf);
+       return 0;
+}
+
+static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio)
+{
+       mddev_t *mddev = q->queuedata;
+       raid5_conf_t *conf = mddev_to_conf(mddev);
+       const unsigned int raid_disks = conf->raid_disks;
+       const unsigned int data_disks = raid_disks - conf->max_degraded;
+       unsigned int dd_idx, pd_idx;
+       struct bio* align_bi;
+       mdk_rdev_t *rdev;
+
+       if (!in_chunk_boundary(mddev, raid_bio)) {
+               printk("chunk_aligned_read : non aligned\n");
+               return 0;
+       }
+       /*
+        * use bio_clone to make a copy of the bio
+        */
+       align_bi = bio_clone(raid_bio, GFP_NOIO);
+       if (!align_bi)
+               return 0;
+       /*
+        *   set bi_end_io to a new function, and set bi_private to the
+        *     original bio.
+        */
+       align_bi->bi_end_io  = raid5_align_endio;
+       align_bi->bi_private = raid_bio;
+       /*
+        *      compute position
+        */
+       align_bi->bi_sector =  raid5_compute_sector(raid_bio->bi_sector,
+                                       raid_disks,
+                                       data_disks,
+                                       &dd_idx,
+                                       &pd_idx,
+                                       conf);
+
+       rcu_read_lock();
+       rdev = rcu_dereference(conf->disks[dd_idx].rdev);
+       if (rdev && test_bit(In_sync, &rdev->flags)) {
+               atomic_inc(&rdev->nr_pending);
+               rcu_read_unlock();
+               raid_bio->bi_next = (void*)rdev;
+               align_bi->bi_bdev =  rdev->bdev;
+               align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
+               align_bi->bi_sector += rdev->data_offset;
+
+               spin_lock_irq(&conf->device_lock);
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   conf->quiesce == 0,
+                                   conf->device_lock, /* nothing */);
+               atomic_inc(&conf->active_aligned_reads);
+               spin_unlock_irq(&conf->device_lock);
+
+               generic_make_request(align_bi);
+               return 1;
+       } else {
+               rcu_read_unlock();
+               bio_put(align_bi);
+               return 0;
+       }
+}
+
+
 static int make_request(request_queue_t *q, struct bio * bi)
 {
        mddev_t *mddev = q->queuedata;
@@ -2632,6 +2751,11 @@ static int make_request(request_queue_t *q, struct bio * bi)
        disk_stat_inc(mddev->gendisk, ios[rw]);
        disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
 
+       if (bio_data_dir(bi) == READ &&
+            mddev->reshape_position == MaxSector &&
+            chunk_aligned_read(q,bi))
+               return 0;
+
        logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
        last_sector = bi->bi_sector + (bi->bi_size>>9);
        bi->bi_next = NULL;
@@ -2739,7 +2863,9 @@ static int make_request(request_queue_t *q, struct bio * bi)
                if ( rw == WRITE )
                        md_write_end(mddev);
                bi->bi_size = 0;
-               bi->bi_end_io(bi, bytes, 0);
+               bi->bi_end_io(bi, bytes,
+                             test_bit(BIO_UPTODATE, &bi->bi_flags)
+                               ? 0 : -EIO);
        }
        return 0;
 }
@@ -2950,6 +3076,74 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
        return STRIPE_SECTORS;
 }
 
+static int  retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+{
+       /* We may not be able to submit a whole bio at once as there
+        * may not be enough stripe_heads available.
+        * We cannot pre-allocate enough stripe_heads as we may need
+        * more than exist in the cache (if we allow ever large chunks).
+        * So we do one stripe head at a time and record in
+        * ->bi_hw_segments how many have been done.
+        *
+        * We *know* that this entire raid_bio is in one chunk, so
+        * it will be only one 'dd_idx' and only need one call to raid5_compute_sector.
+        */
+       struct stripe_head *sh;
+       int dd_idx, pd_idx;
+       sector_t sector, logical_sector, last_sector;
+       int scnt = 0;
+       int remaining;
+       int handled = 0;
+
+       logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+       sector = raid5_compute_sector(  logical_sector,
+                                       conf->raid_disks,
+                                       conf->raid_disks - conf->max_degraded,
+                                       &dd_idx,
+                                       &pd_idx,
+                                       conf);
+       last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9);
+
+       for (; logical_sector < last_sector;
+            logical_sector += STRIPE_SECTORS, scnt++) {
+
+               if (scnt < raid_bio->bi_hw_segments)
+                       /* already done this stripe */
+                       continue;
+
+               sh = get_active_stripe(conf, sector, conf->raid_disks, pd_idx, 1);
+
+               if (!sh) {
+                       /* failed to get a stripe - must wait */
+                       raid_bio->bi_hw_segments = scnt;
+                       conf->retry_read_aligned = raid_bio;
+                       return handled;
+               }
+
+               set_bit(R5_ReadError, &sh->dev[dd_idx].flags);
+               add_stripe_bio(sh, raid_bio, dd_idx, 0);
+               handle_stripe(sh, NULL);
+               release_stripe(sh);
+               handled++;
+       }
+       spin_lock_irq(&conf->device_lock);
+       remaining = --raid_bio->bi_phys_segments;
+       spin_unlock_irq(&conf->device_lock);
+       if (remaining == 0) {
+               int bytes = raid_bio->bi_size;
+
+               raid_bio->bi_size = 0;
+               raid_bio->bi_end_io(raid_bio, bytes,
+                             test_bit(BIO_UPTODATE, &raid_bio->bi_flags)
+                               ? 0 : -EIO);
+       }
+       if (atomic_dec_and_test(&conf->active_aligned_reads))
+               wake_up(&conf->wait_for_stripe);
+       return handled;
+}
+
+
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -2971,6 +3165,7 @@ static void raid5d (mddev_t *mddev)
        spin_lock_irq(&conf->device_lock);
        while (1) {
                struct list_head *first;
+               struct bio *bio;
 
                if (conf->seq_flush != conf->seq_write) {
                        int seq = conf->seq_flush;
@@ -2987,6 +3182,16 @@ static void raid5d (mddev_t *mddev)
                    !list_empty(&conf->delayed_list))
                        raid5_activate_delayed(conf);
 
+               while ((bio = remove_bio_from_retry(conf))) {
+                       int ok;
+                       spin_unlock_irq(&conf->device_lock);
+                       ok = retry_aligned_read(conf, bio);
+                       spin_lock_irq(&conf->device_lock);
+                       if (!ok)
+                               break;
+                       handled++;
+               }
+
                if (list_empty(&conf->handle_list))
                        break;
 
@@ -3174,6 +3379,7 @@ static int run(mddev_t *mddev)
        INIT_LIST_HEAD(&conf->inactive_list);
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
+       atomic_set(&conf->active_aligned_reads, 0);
 
        PRINTK("raid5: run(%s) called.\n", mdname(mddev));
 
@@ -3320,6 +3526,8 @@ static int run(mddev_t *mddev)
        mddev->array_size =  mddev->size * (conf->previous_raid_disks -
                                            conf->max_degraded);
 
+       blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
+
        return 0;
 abort:
        if (conf) {
@@ -3694,7 +3902,8 @@ static void raid5_quiesce(mddev_t *mddev, int state)
                spin_lock_irq(&conf->device_lock);
                conf->quiesce = 1;
                wait_event_lock_irq(conf->wait_for_stripe,
-                                   atomic_read(&conf->active_stripes) == 0,
+                                   atomic_read(&conf->active_stripes) == 0 &&
+                                   atomic_read(&conf->active_aligned_reads) == 0,
                                    conf->device_lock, /* nothing */);
                spin_unlock_irq(&conf->device_lock);
                break;
index 9f7e1fe..87410db 100644 (file)
@@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig"
 
 config VIDEO_TUNER
        tristate
+       depends on I2C
 
 config VIDEO_BUF
        tristate
@@ -82,6 +83,7 @@ config VIDEO_IR
 
 config VIDEO_TVEEPROM
        tristate
+       depends on I2C
 
 config USB_DABUSB
        tristate "DABUSB driver"
index db75344..f51e02f 100644 (file)
@@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_norwood);
+
+/* From reading the following remotes:
+ * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
+ * Hauppauge (from NOVA-CI-s box product)
+ * This is a "middle of the road" approach, differences are noted
+ */
+IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
+       [ 0x00 ] = KEY_0,
+       [ 0x01 ] = KEY_1,
+       [ 0x02 ] = KEY_2,
+       [ 0x03 ] = KEY_3,
+       [ 0x04 ] = KEY_4,
+       [ 0x05 ] = KEY_5,
+       [ 0x06 ] = KEY_6,
+       [ 0x07 ] = KEY_7,
+       [ 0x08 ] = KEY_8,
+       [ 0x09 ] = KEY_9,
+       [ 0x0a ] = KEY_ENTER,
+       [ 0x0b ] = KEY_RED,
+       [ 0x0c ] = KEY_POWER,             /* RADIO on Hauppauge */
+       [ 0x0d ] = KEY_MUTE,
+       [ 0x0f ] = KEY_A,                 /* TV on Hauppauge */
+       [ 0x10 ] = KEY_VOLUMEUP,
+       [ 0x11 ] = KEY_VOLUMEDOWN,
+       [ 0x14 ] = KEY_B,
+       [ 0x1c ] = KEY_UP,
+       [ 0x1d ] = KEY_DOWN,
+       [ 0x1e ] = KEY_OPTION,            /* RESERVED on Hauppauge */
+       [ 0x1f ] = KEY_BREAK,
+       [ 0x20 ] = KEY_CHANNELUP,
+       [ 0x21 ] = KEY_CHANNELDOWN,
+       [ 0x22 ] = KEY_PREVIOUS,          /* Prev. Ch on Zenith, SOURCE on Hauppauge */
+       [ 0x24 ] = KEY_RESTART,
+       [ 0x25 ] = KEY_OK,
+       [ 0x26 ] = KEY_CYCLEWINDOWS,      /* MINIMIZE on Hauppauge */
+       [ 0x28 ] = KEY_ENTER,             /* VCR mode on Zenith */
+       [ 0x29 ] = KEY_PAUSE,
+       [ 0x2b ] = KEY_RIGHT,
+       [ 0x2c ] = KEY_LEFT,
+       [ 0x2e ] = KEY_MENU,              /* FULL SCREEN on Hauppauge */
+       [ 0x30 ] = KEY_SLOW,
+       [ 0x31 ] = KEY_PREVIOUS,          /* VCR mode on Zenith */
+       [ 0x32 ] = KEY_REWIND,
+       [ 0x34 ] = KEY_FASTFORWARD,
+       [ 0x35 ] = KEY_PLAY,
+       [ 0x36 ] = KEY_STOP,
+       [ 0x37 ] = KEY_RECORD,
+       [ 0x38 ] = KEY_TUNER,             /* TV/VCR on Zenith */
+       [ 0x3a ] = KEY_C,
+       [ 0x3c ] = KEY_EXIT,
+       [ 0x3d ] = KEY_POWER2,
+       [ 0x3e ] = KEY_TUNER,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
index 5297a36..8c85efc 100644 (file)
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                saa7146_write(dev, I2C_TRANSFER, *dword);
 
                dev->i2c_op = 1;
+               SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
                SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
 
-               wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
-               if (signal_pending (current)) {
-                       /* a signal arrived */
-                       return -ERESTARTSYS;
+               timeout = HZ/100 + 1; /* 10ms */
+               timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+               if (timeout == -ERESTARTSYS || dev->i2c_op) {
+                       SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+                       SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+                       if (timeout == -ERESTARTSYS)
+                               /* a signal arrived */
+                               return -ERESTARTSYS;
+
+                       printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
+                       return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
        } else {
index a0dcd59..7987595 100644 (file)
@@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP
        select DVB_STV0297 if !DVB_FE_CUSTOMISE
        select DVB_BCM3510 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
        help
          Support for the digital TV receiver chip made by B2C2 Inc. included in
          Technisats PCI cards and USB boxes.
index b8ba878..c2b35e3 100644 (file)
@@ -14,7 +14,7 @@
 #include "stv0297.h"
 #include "mt312.h"
 #include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
 #include "dvb-pll.h"
 
 /* lnb control */
@@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
        return request_firmware(fw, name, fc->dev);
 }
 
-static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
-{
-       struct flexcop_device *fc = fe->dvb->priv;
-       return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
-}
-
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
        .demod_address       = 0x59,
        .demod_chip          = LGDT3303,
@@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        /* try the air atsc 3nd generation (lgdt3303) */
        if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC3;
-               fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+               dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap);
                info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
        } else
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
index 0689324..6e16680 100644 (file)
@@ -63,7 +63,7 @@ struct flexcop_pci {
 
        unsigned long last_irq;
 
-       struct work_struct irq_check_work;
+       struct delayed_work irq_check_work;
 
        struct flexcop_device *fc_dev;
 };
@@ -97,9 +97,10 @@ static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
        return 0;
 }
 
-static void flexcop_pci_irq_check_work(void *data)
+static void flexcop_pci_irq_check_work(struct work_struct *work)
 {
-       struct flexcop_pci *fc_pci = data;
+       struct flexcop_pci *fc_pci =
+               container_of(work, struct flexcop_pci, irq_check_work.work);
        struct flexcop_device *fc = fc_pci->fc_dev;
 
        flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
@@ -371,7 +372,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
                goto err_fc_exit;
 
-       INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
+       INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work);
 
        return ret;
 
index ae2ff5d..dd66b60 100644 (file)
@@ -1,13 +1,13 @@
 config DVB_BT8XX
        tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
-       select DVB_PLL
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_SP887X if !DVB_FE_CUSTOMISE
        select DVB_NXT6000 if !DVB_FE_CUSTOMISE
        select DVB_CX24110 if !DVB_FE_CUSTOMISE
        select DVB_OR51211 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
index 14e69a7..80a85cb 100644 (file)
@@ -34,7 +34,6 @@
 #include "dvb_frontend.h"
 #include "dvb-bt8xx.h"
 #include "bt878.h"
-#include "dvb-pll.h"
 
 static int debug;
 
@@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = {
        .demod_init = digitv_alps_tded4_demod_init,
 };
 
-static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
-       struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-       return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
-}
-
 static struct lgdt330x_config tdvs_tua6034_config = {
        .demod_address    = 0x0e,
        .demod_chip       = LGDT3303,
@@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                lgdt330x_reset(card);
                card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
                if (card->fe != NULL) {
-                       card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
+                       dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter);
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
                }
                break;
index 4745a90..e75f417 100644 (file)
@@ -37,7 +37,7 @@
 #include "cx24110.h"
 #include "or51211.h"
 #include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
 #include "zl10353.h"
 
 struct dvb_bt8xx_card {
index 8a7dd50..d64b96c 100644 (file)
@@ -128,7 +128,7 @@ struct cinergyt2 {
 
        struct dvbt_set_parameters_msg param;
        struct dvbt_get_status_msg status;
-       struct work_struct query_work;
+       struct delayed_work query_work;
 
        wait_queue_head_t poll_wq;
        int pending_fe_events;
@@ -142,7 +142,7 @@ struct cinergyt2 {
 #ifdef ENABLE_RC
        struct input_dev *rc_input_dev;
        char phys[64];
-       struct work_struct rc_query_work;
+       struct delayed_work rc_query_work;
        int rc_input_event;
        u32 rc_last_code;
        unsigned long last_event_jiffies;
@@ -287,7 +287,7 @@ static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
        int i;
 
        cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
-                                             SLAB_KERNEL, &cinergyt2->streambuf_dmahandle);
+                                             GFP_KERNEL, &cinergyt2->streambuf_dmahandle);
        if (!cinergyt2->streambuf) {
                dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n");
                return -ENOMEM;
@@ -723,9 +723,10 @@ static struct dvb_device cinergyt2_fe_template = {
 
 #ifdef ENABLE_RC
 
-static void cinergyt2_query_rc (void *data)
+static void cinergyt2_query_rc (struct work_struct *work)
 {
-       struct cinergyt2 *cinergyt2 = data;
+       struct cinergyt2 *cinergyt2 =
+               container_of(work, struct cinergyt2, rc_query_work.work);
        char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
        struct cinergyt2_rc_event rc_events[12];
        int n, len, i;
@@ -745,6 +746,7 @@ static void cinergyt2_query_rc (void *data)
                                dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
                                input_report_key(cinergyt2->rc_input_dev,
                                                 cinergyt2->rc_input_event, 0);
+                               input_sync(cinergyt2->rc_input_dev);
                                cinergyt2->rc_input_event = KEY_MAX;
                        }
                        cinergyt2->rc_last_code = ~0;
@@ -782,6 +784,7 @@ static void cinergyt2_query_rc (void *data)
                        dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
                        input_report_key(cinergyt2->rc_input_dev,
                                         cinergyt2->rc_input_event, 1);
+                       input_sync(cinergyt2->rc_input_dev);
                        cinergyt2->rc_last_code = rc_events[n].value;
                }
        }
@@ -797,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
 {
        struct input_dev *input_dev;
        int i;
+       int err;
 
-       cinergyt2->rc_input_dev = input_dev = input_allocate_device();
+       input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
@@ -806,7 +810,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
        strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
        cinergyt2->rc_input_event = KEY_MAX;
        cinergyt2->rc_last_code = ~0;
-       INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
+       INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc);
 
        input_dev->name = DRIVER_NAME " remote control";
        input_dev->phys = cinergyt2->phys;
@@ -816,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
        input_dev->keycodesize = 0;
        input_dev->keycodemax = 0;
 
-       input_register_device(cinergyt2->rc_input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       cinergyt2->rc_input_dev = input_dev;
        schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
 
        return 0;
@@ -847,9 +857,10 @@ static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { }
 
 #endif /* ENABLE_RC */
 
-static void cinergyt2_query (void *data)
+static void cinergyt2_query (struct work_struct *work)
 {
-       struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
+       struct cinergyt2 *cinergyt2 =
+               container_of(work, struct cinergyt2, query_work.work);
        char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
        struct dvbt_get_status_msg *s = &cinergyt2->status;
        uint8_t lock_bits;
@@ -893,7 +904,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
 
        mutex_init(&cinergyt2->sem);
        init_waitqueue_head (&cinergyt2->poll_wq);
-       INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2);
+       INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query);
 
        cinergyt2->udev = interface_to_usbdev(intf);
        cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
index a2ab2ee..e859722 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/list.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/jiffies.h>
 #include <asm/processor.h>
 
index 8859ab7..ebf4dc5 100644 (file)
@@ -127,6 +127,7 @@ struct dvb_net_priv {
        int in_use;
        struct net_device_stats stats;
        u16 pid;
+       struct net_device *net;
        struct dvb_net *host;
        struct dmx_demux *demux;
        struct dmx_section_feed *secfeed;
@@ -1123,10 +1124,11 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
 }
 
 
-static void wq_set_multicast_list (void *data)
+static void wq_set_multicast_list (struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct dvb_net_priv *priv = dev->priv;
+       struct dvb_net_priv *priv =
+               container_of(work, struct dvb_net_priv, set_multicast_list_wq);
+       struct net_device *dev = priv->net;
 
        dvb_net_feed_stop(dev);
        priv->rx_mode = RX_MODE_UNI;
@@ -1167,9 +1169,11 @@ static void dvb_net_set_multicast_list (struct net_device *dev)
 }
 
 
-static void wq_restart_net_feed (void *data)
+static void wq_restart_net_feed (struct work_struct *work)
 {
-       struct net_device *dev = data;
+       struct dvb_net_priv *priv =
+               container_of(work, struct dvb_net_priv, restart_net_feed_wq);
+       struct net_device *dev = priv->net;
 
        if (netif_running(dev)) {
                dvb_net_feed_stop(dev);
@@ -1276,6 +1280,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
        dvbnet->device[if_num] = net;
 
        priv = net->priv;
+       priv->net = net;
        priv->demux = dvbnet->demux;
        priv->pid = pid;
        priv->rx_mode = RX_MODE_UNI;
@@ -1284,8 +1289,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
        priv->feedtype = feedtype;
        reset_ule(priv);
 
-       INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);
-       INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);
+       INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list);
+       INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed);
        mutex_init(&priv->mutex);
 
        net->base_addr = pid;
index a263b3f..ad52143 100644 (file)
@@ -69,6 +69,8 @@ config DVB_USB_DIBUSB_MC
 config DVB_USB_DIB0700
        tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
        depends on DVB_USB
+       select DVB_DIB7000P
+       select DVB_DIB7000M
        select DVB_DIB3000MC
        select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        help
@@ -96,6 +98,7 @@ config DVB_USB_CXUSB
        depends on DVB_USB
        select DVB_CX22702 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        help
@@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2
        help
          Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
 
+config DVB_USB_TTUSB2
+       tristate "Pinnacle 400e DVB-S USB2.0 support"
+       depends on DVB_USB
+       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_TDA826X if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
+         firmware protocol used by this module is similar to the one used by the
+         old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
+
 config DVB_USB_DTT200U
        tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
        depends on DVB_USB
index e239107..154d593 100644 (file)
@@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
 dvb-usb-cxusb-objs = cxusb.o
 obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
 
+dvb-usb-ttusb2-objs = ttusb2.o
+obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
+
 dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
 obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
 
index 2ed3eb6..a6c5f19 100644 (file)
@@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = {
                {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 32,
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-
-       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
-
-       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+
+                       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
+                       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                                       .stream = {
+                                               .type = USB_BULK,
+                               .count = 7,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
 
                        .size_of_priv     = sizeof(struct dibusb_state),
                },
index 43f3906..15d12fc 100644 (file)
  * TODO: Use the cx25840-driver for the analogue part
  *
  * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
- * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
+ * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
  * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
  *
- *     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 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.
  *
  * see Documentation/dvb/README.dvb-usb for more information
  */
 
 #include "cx22702.h"
 #include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
 
 /* debug */
 int dvb_usb_cxusb_debug;
-module_param_named(debug,dvb_usb_cxusb_debug, int, 0644);
+module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
 static int cxusb_ctrl_msg(struct dvb_usb_device *d,
-               u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+                         u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
        int wo = (rbuf == NULL || rlen == 0); /* write-only */
        u8 sndbuf[1+wlen];
-       memset(sndbuf,0,1+wlen);
+       memset(sndbuf, 0, 1+wlen);
 
        sndbuf[0] = cmd;
-       memcpy(&sndbuf[1],wbuf,wlen);
+       memcpy(&sndbuf[1], wbuf, wlen);
        if (wo)
-               dvb_usb_generic_write(d,sndbuf,1+wlen);
+               dvb_usb_generic_write(d, sndbuf, 1+wlen);
        else
-               dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0);
+               dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
 
        return 0;
 }
@@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
 static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
 {
        struct cxusb_state *st = d->priv;
-       u8 o[2],i;
+       u8 o[2], i;
 
        if (st->gpio_write_state[GPIO_TUNER] == onoff)
                return;
 
        o[0] = GPIO_TUNER;
        o[1] = onoff;
-       cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
+       cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
 
        if (i != 0x01)
                deb_info("gpio_write failed.\n");
@@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
 }
 
 /* I2C */
-static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                         int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
        int i;
@@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
 
                if (d->udev->descriptor.idVendor == USB_VID_MEDION)
                        switch (msg[i].addr) {
-                               case 0x63:
-                                       cxusb_gpio_tuner(d,0);
-                                       break;
-                               default:
-                                       cxusb_gpio_tuner(d,1);
-                                       break;
+                       case 0x63:
+                               cxusb_gpio_tuner(d, 0);
+                               break;
+                       default:
+                               cxusb_gpio_tuner(d, 1);
+                               break;
                        }
 
                /* read request */
@@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
                        obuf[0] = msg[i].len;
                        obuf[1] = msg[i+1].len;
                        obuf[2] = msg[i].addr;
-                       memcpy(&obuf[3],msg[i].buf,msg[i].len);
+                       memcpy(&obuf[3], msg[i].buf, msg[i].len);
 
                        if (cxusb_ctrl_msg(d, CMD_I2C_READ,
-                                               obuf, 3+msg[i].len,
-                                               ibuf, 1+msg[i+1].len) < 0)
+                                          obuf, 3+msg[i].len,
+                                          ibuf, 1+msg[i+1].len) < 0)
                                break;
 
                        if (ibuf[0] != 0x08)
                                deb_i2c("i2c read may have failed\n");
 
-                       memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
+                       memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
 
                        i++;
                } else { /* write */
                        u8 obuf[2+msg[i].len], ibuf;
                        obuf[0] = msg[i].addr;
                        obuf[1] = msg[i].len;
-                       memcpy(&obuf[2],msg[i].buf,msg[i].len);
+                       memcpy(&obuf[2], msg[i].buf, msg[i].len);
 
-                       if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
+                       if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
+                                          2+msg[i].len, &ibuf,1) < 0)
                                break;
                        if (ibuf != 0x08)
                                deb_i2c("i2c write may have failed\n");
@@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
-                                         struct dvb_frontend_parameters *fep)
-{
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep);
-}
-
 static struct cx22702_config cxusb_cx22702_config = {
        .demod_address = 0x63,
-
        .output_mode = CX22702_PARALLEL_OUTPUT,
 };
 
@@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       adap->pll_addr = 0x61;
-       adap->pll_desc = &dvb_pll_thomson_dtt7579;
-       adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+       dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+                  NULL, &dvb_pll_thomson_dtt7579);
        return 0;
 }
 
 static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       adap->pll_addr = 0x61;
-       adap->pll_desc = &dvb_pll_lg_z201;
-       adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+       dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201);
        return 0;
 }
 
 static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       adap->pll_addr = 0x60;
-       adap->pll_desc = &dvb_pll_thomson_dtt7579;
-       adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+       dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+                  NULL, &dvb_pll_thomson_dtt7579);
        return 0;
 }
 
-static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap)
+static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
+       dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap);
        return 0;
 }
 
@@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
 
        cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
 
-       if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL)
+       if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+                                  &adap->dev->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
 
        cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL)
+       if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
+                                  &adap->dev->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 
        cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL)
+       if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+                                  &adap->dev->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
 
        cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) ||
-               ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL))
+       if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+                                   &adap->dev->i2c_adap)) != NULL) ||
+               ((adap->fe = dvb_attach(zl10353_attach,
+                                       &cxusb_zl10353_dee1601_config,
+                                       &adap->dev->i2c_adap)) != NULL))
                return 0;
 
        return -EIO;
@@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
  */
 
 #define BLUEBIRD_01_ID_OFFSET 6638
-static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
+static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
+                                                 const struct firmware *fw)
 {
        if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
                return -EINVAL;
@@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
        if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
            fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
 
-               fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
-               fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
+               fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
+                       udev->descriptor.idProduct + 1;
+               fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
+                       udev->descriptor.idProduct >> 8;
 
-               return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
+               return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
        }
 
        return -EINVAL;
@@ -488,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
+                      const struct usb_device_id *id)
 {
        if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
                dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
@@ -502,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf,
 }
 
 static struct usb_device_id cxusb_table [] = {
-               { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
-               { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
-               {}              /* Terminating entry */
+       { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
+       {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
 
@@ -529,20 +528,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = cxusb_streaming_ctrl,
-       .frontend_attach  = cxusb_cx22702_frontend_attach,
-       .tuner_attach     = cxusb_fmd1216me_tuner_attach,
-       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-               .count = 5,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                       .streaming_ctrl   = cxusb_streaming_ctrl,
+                       .frontend_attach  = cxusb_cx22702_frontend_attach,
+                       .tuner_attach     = cxusb_fmd1216me_tuner_attach,
+                       /* parameter for the MPEG2-data transfer */
+                                       .stream = {
+                                               .type = USB_BULK,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
 
                },
        },
@@ -575,21 +574,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = cxusb_streaming_ctrl,
-       .frontend_attach  = cxusb_lgdt3303_frontend_attach,
-       .tuner_attach     = cxusb_lgdt3303_tuner_attach,
-
-       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-               .count = 5,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                       .streaming_ctrl   = cxusb_streaming_ctrl,
+                       .frontend_attach  = cxusb_lgdt3303_frontend_attach,
+                       .tuner_attach     = cxusb_lgh064f_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                                       .stream = {
+                                               .type = USB_BULK,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
                },
        },
 
@@ -627,20 +626,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = cxusb_streaming_ctrl,
-       .frontend_attach  = cxusb_dee1601_frontend_attach,
-       .tuner_attach     = cxusb_dee1601_tuner_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .streaming_ctrl   = cxusb_streaming_ctrl,
+                       .frontend_attach  = cxusb_dee1601_frontend_attach,
+                       .tuner_attach     = cxusb_dee1601_tuner_attach,
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 5,
-               .endpoint = 0x04,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                               .count = 5,
+                               .endpoint = 0x04,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
                },
        },
 
@@ -686,21 +685,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
        .num_adapters = 2,
        .adapter = {
                {
-       .streaming_ctrl   = cxusb_streaming_ctrl,
-       .frontend_attach  = cxusb_mt352_frontend_attach,
-       .tuner_attach     = cxusb_lgz201_tuner_attach,
+                       .streaming_ctrl   = cxusb_streaming_ctrl,
+                       .frontend_attach  = cxusb_mt352_frontend_attach,
+                       .tuner_attach     = cxusb_lgz201_tuner_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 5,
-               .endpoint = 0x04,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                               .count = 5,
+                               .endpoint = 0x04,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
                },
        },
        .power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -736,21 +735,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = cxusb_streaming_ctrl,
-       .frontend_attach  = cxusb_mt352_frontend_attach,
-       .tuner_attach     = cxusb_dtt7579_tuner_attach,
+                       .streaming_ctrl   = cxusb_streaming_ctrl,
+                       .frontend_attach  = cxusb_mt352_frontend_attach,
+                       .tuner_attach     = cxusb_dtt7579_tuner_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 5,
-               .endpoint = 0x04,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                               .count = 5,
+                               .endpoint = 0x04,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
                },
        },
        .power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -776,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
 static struct usb_driver cxusb_driver = {
        .name           = "dvb_usb_cxusb",
        .probe          = cxusb_probe,
-       .disconnect = dvb_usb_device_exit,
+       .disconnect     = dvb_usb_device_exit,
        .id_table       = cxusb_table,
 };
 
@@ -802,7 +801,7 @@ module_init (cxusb_module_init);
 module_exit (cxusb_module_exit);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
 MODULE_VERSION("1.0-alpha");
index ac84347..cda3ade 100644 (file)
@@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug;
 #define REQUEST_I2C_WRITE    0x3
 #define REQUEST_POLL_RC      0x4
 #define REQUEST_JUMPRAM      0x8
+#define REQUEST_SET_CLOCK    0xB
 #define REQUEST_SET_GPIO     0xC
 #define REQUEST_ENABLE_VIDEO 0xF
        // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
        // 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
        // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
+#define REQUEST_GET_VERSION  0x15
 
 struct dib0700_state {
        u8 channel_state;
        u16 mt2060_if1[2];
+
+       u8 is_dib7000pc;
 };
 
 extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
+extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
 extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
 extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
index dca6c69..6a4d150 100644 (file)
@@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = {
 int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
                        struct dvb_usb_device_description **desc, int *cold)
 {
-       u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
-       *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-               buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
+       u8 b[16];
+       s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
+               REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
+
+       deb_info("FW GET_VERSION length: %d\n",ret);
+
+       *cold = ret <= 0;
 
        deb_info("cold: %d\n", *cold);
        return 0;
 }
 
+static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
+       u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
+       u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
+{
+       u8 b[10];
+       b[0] = REQUEST_SET_CLOCK;
+       b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
+       b[2] = (pll_prediv >> 8)  & 0xff; // MSB
+       b[3] =  pll_prediv        & 0xff; // LSB
+       b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
+       b[5] =  pll_loopdiv       & 0xff; // LSB
+       b[6] = (free_div >> 8)    & 0xff; // MSB
+       b[7] =  free_div          & 0xff; // LSB
+       b[8] = (dsuScaler >> 8)   & 0xff; // MSB
+       b[9] =  dsuScaler         & 0xff; // LSB
+
+       return dib0700_ctrl_wr(d, b, 10);
+}
+
+int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
+{
+       switch (clk_MHz) {
+               case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
+               default: return -EINVAL;
+       }
+       return 0;
+}
+
 static int dib0700_jumpram(struct usb_device *udev, u32 address)
 {
        int ret, actlen;
@@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
                /* start the firmware */
                if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
                        info("firmware started successfully.");
-                       msleep(100);
+                       msleep(500);
                }
        } else
                ret = -EIO;
index e473bfe..2208757 100644 (file)
@@ -9,6 +9,8 @@
 #include "dib0700.h"
 
 #include "dib3000mc.h"
+#include "dib7000m.h"
+#include "dib7000p.h"
 #include "mt2060.h"
 
 static int force_lna_activation;
@@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
 }
 
 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
-/*
-static struct mt2060_config stk7000p_mt2060_config = {
-       0x60
+static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
+       BAND_UHF | BAND_VHF,       // band_caps
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+       712,  // inv_gain
+       41,  // time_stabiliz
+
+       0,  // alpha_level
+       118,  // thlock
+
+       0,     // wbd_inv
+       4095,  // wbd_ref
+       0,     // wbd_sel
+       0,     // wbd_alpha
+
+       42598,  // agc1_max
+       17694,  // agc1_min
+       45875,  // agc2_max
+       2621,  // agc2_min
+       0,  // agc1_pt1
+       76,  // agc1_pt2
+       139,  // agc1_pt3
+       52,  // agc1_slope1
+       59,  // agc1_slope2
+       107,  // agc2_pt1
+       172,  // agc2_pt2
+       57,  // agc2_slope1
+       70,  // agc2_slope2
+
+       21,  // alpha_mant
+       25,  // alpha_exp
+       28,  // beta_mant
+       48,  // beta_exp
+
+       1,  // perform_agc_softsplit
+       {  0,     // split_min
+          107,   // split_max
+          51800, // global_split_min
+          24700  // global_split_max
+       },
+};
+
+static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
+       BAND_UHF | BAND_VHF,
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+       712, // inv_gain
+       41,  // time_stabiliz
+
+       0,   // alpha_level
+       118, // thlock
+
+       0,    // wbd_inv
+       4095, // wbd_ref
+       0,    // wbd_sel
+       0,    // wbd_alpha
+
+       42598, // agc1_max
+       16384, // agc1_min
+       42598, // agc2_max
+           0, // agc2_min
+
+         0,   // agc1_pt1
+       137,   // agc1_pt2
+       255,   // agc1_pt3
+
+         0,   // agc1_slope1
+       255,   // agc1_slope2
+
+       0,     // agc2_pt1
+       0,     // agc2_pt2
+
+        0,    // agc2_slope1
+       41,    // agc2_slope2
+
+       15, // alpha_mant
+       25, // alpha_exp
+
+       28, // beta_mant
+       48, // beta_exp
+
+       0, // perform_agc_softsplit
+};
+
+static struct dibx000_bandwidth_config stk7700p_pll_config = {
+       60000, 30000, // internal, sampling
+       1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
+       0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
+       (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
+       60258167, // ifreq
+       20452225, // timf
+};
+
+static struct dib7000m_config stk7700p_dib7000m_config = {
+       .dvbt_mode = 1,
+       .output_mpeg2_in_188_bytes = 1,
+       .quartz_direct = 1,
+
+       .agc_config_count = 1,
+       .agc = &stk7700p_7000m_mt2060_agc_config,
+       .bw  = &stk7700p_pll_config,
+
+       .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+static struct dib7000p_config stk7700p_dib7000p_config = {
+       .output_mpeg2_in_188_bytes = 1,
+
+       .agc = &stk7700p_7000p_mt2060_agc_config,
+       .bw  = &stk7700p_pll_config,
+
+       .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
 };
-*/
 
 static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
 {
+       struct dib0700_state *st = adap->dev->priv;
        /* unless there is no real power management in DVB - we leave the device on GPIO6 */
-       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
-       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
+
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(50);
+
+       dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO9,  GPIO_OUT, 1);
+
        dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
+
+       dib0700_set_gpio(adap->dev,  GPIO0, GPIO_OUT, 1);
+
+       st->mt2060_if1[0] = 1220;
+
+       if (dib7000pc_detection(&adap->dev->i2c_adap)) {
+               adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+               st->is_dib7000pc = 1;
+       } else
+               adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
 
-//     adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18);
-       return 0;
+       return adap->fe == NULL ? -ENODEV : 0;
 }
 
+static struct mt2060_config stk7700p_mt2060_config = {
+       0x60
+};
+
 static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
 {
-//     tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1);
-//     return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1);
-       return 0;
+       struct dib0700_state *st = adap->dev->priv;
+       struct i2c_adapter *tun_i2c;
+
+       if (st->is_dib7000pc)
+               tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+       else
+               tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+
+       return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+               st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
 }
 
 struct usb_device_id dib0700_usb_id_table[] = {
                { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
+               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
+
                { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
                { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
                { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
                { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
+               { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
+               { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+               { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
                { }             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -167,20 +321,32 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 3,
+               .num_device_descs = 6,
                .devices = {
                        {   "DiBcom STK7700P reference design",
-                               { &dib0700_usb_id_table[0], NULL },
+                               { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
                                { NULL },
                        },
                        {   "Hauppauge Nova-T Stick",
-                               { &dib0700_usb_id_table[3], NULL },
+                               { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
                                { NULL },
                        },
                        {   "AVerMedia AVerTV DVB-T Volar",
-                               { &dib0700_usb_id_table[4], NULL },
+                               { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
                                { NULL },
                        },
+                       {   "Compro Videomate U500",
+                               { &dib0700_usb_id_table[6], NULL },
+                               { NULL },
+                       },
+                       {   "Uniwill STK7700P based (Hama and others)",
+                               { &dib0700_usb_id_table[7], NULL },
+                               { NULL },
+                       },
+                       {   "Leadtek Winfast DTV Dongle (STK7700P based)",
+                               { &dib0700_usb_id_table[8], NULL },
+                               { NULL },
+                       }
                }
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -202,7 +368,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                .num_device_descs = 1,
                .devices = {
                        {   "Hauppauge Nova-T 500 Dual DVB-T",
-                               { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL },
+                               { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
                                { NULL },
                        },
                }
index 4fe363e..7a6ae8f 100644 (file)
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 16,
 
-       .streaming_ctrl   = dibusb_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_tuner_probe_and_attach,
+                       .streaming_ctrl   = dibusb_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
+                       .tuner_attach     = dibusb_tuner_probe_and_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
        },
@@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
                        .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
                        .pid_filter_count = 16,
 
-       .streaming_ctrl   = dibusb_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_tuner_probe_and_attach,
+                       .streaming_ctrl   = dibusb_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
+                       .tuner_attach     = dibusb_tuner_probe_and_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct dibusb_state),
                },
        },
@@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 16,
 
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_thomson_tuner_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
+                       .tuner_attach     = dibusb_thomson_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
        },
@@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 16,
 
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_tuner_probe_and_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mb_frontend_attach,
+                       .tuner_attach     = dibusb_tuner_probe_and_attach,
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
        },
index a0fd37e..e7ea3e7 100644 (file)
@@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
                {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 32,
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
+                       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
 
        /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
        },
index 8fb3437..4a198d4 100644 (file)
@@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .frontend_attach  = digitv_frontend_attach,
-       .tuner_attach     = digitv_tuner_attach,
+                       .frontend_attach  = digitv_frontend_attach,
+                       .tuner_attach     = digitv_tuner_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                }
        },
        .identify_state   = digitv_identify_state,
index fa43a41..7dbe143 100644 (file)
@@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
                        .pid_filter_count = 15,
 
-       .streaming_ctrl  = dtt200u_streaming_ctrl,
-       .pid_filter      = dtt200u_pid_filter,
-       .frontend_attach = dtt200u_frontend_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .streaming_ctrl  = dtt200u_streaming_ctrl,
+                       .pid_filter      = dtt200u_pid_filter,
+                       .frontend_attach = dtt200u_frontend_attach,
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                }
        },
        .power_ctrl      = dtt200u_power_ctrl,
index 4d6b069..299382d 100644 (file)
@@ -33,6 +33,7 @@
 #define USB_VID_VISIONPLUS                     0x13d3
 #define USB_VID_TWINHAN                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC              0x05d8
+#define USB_VID_UNIWILL                                0x1584
 #define USB_VID_WIDEVIEW                       0x14aa
 
 /* Product IDs */
@@ -46,6 +47,7 @@
 #define USB_PID_COMPRO_DVBU2000_WARM                   0xd001
 #define USB_PID_COMPRO_DVBU2000_UNK_COLD               0x010c
 #define USB_PID_COMPRO_DVBU2000_UNK_WARM               0x010d
+#define USB_PID_COMPRO_VIDEOMATE_U500                  0x1e78
 #define USB_PID_DIBCOM_HOOK_DEFAULT                    0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM             0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD                    0x0bb8
@@ -53,7 +55,9 @@
 #define USB_PID_DIBCOM_MOD3001_COLD                    0x0bc6
 #define USB_PID_DIBCOM_MOD3001_WARM                    0x0bc7
 #define USB_PID_DIBCOM_STK7700P                                0x1e14
+#define USB_PID_DIBCOM_STK7700P_PC                     0x1e78
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD                        0x2131
+#define USB_PID_UNIWILL_STK7700P                       0x6003
 #define USB_PID_GRANDTEC_DVBT_USB_COLD                 0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
 #define USB_PID_KWORLD_VSTREAM_COLD                    0x17de
 #define USB_PID_HAUPPAUGE_NOVA_T_500                   0x9941
 #define USB_PID_HAUPPAUGE_NOVA_T_500_2                 0x9950
 #define USB_PID_HAUPPAUGE_NOVA_T_STICK                 0x7050
-#define USB_PID_AVERMEDIA_VOLAR                                0x1234
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2               0x7060
+#define USB_PID_AVERMEDIA_VOLAR                                0xa807
+#define USB_PID_AVERMEDIA_VOLAR_2                      0xb808
 #define USB_PID_NEBULA_DIGITV                          0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT                    0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD             0xd500
 #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM             0xdb51
 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD             0xdb58
 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM             0xdb59
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD        0xdb54
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM        0xdb55
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD                0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM                0xdb55
 #define USB_PID_MEDION_MD95700                         0x0932
 #define USB_PID_KYE_DVB_T_COLD                         0x701e
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
 #define USB_PID_GRANDTEC_DVBT_USB2_WARM                        0x0bc7
 #define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
 #define USB_PID_GENPIX_8PSK_COLD                       0x0200
 #define USB_PID_GENPIX_8PSK_WARM                       0x0201
 
+
 #endif
index 0a3a0b6..19ff597 100644 (file)
  *
  * TODO: Fix the repeat rate of the input device.
  */
-static void dvb_usb_read_remote_control(void *data)
+static void dvb_usb_read_remote_control(struct work_struct *work)
 {
-       struct dvb_usb_device *d = data;
+       struct dvb_usb_device *d =
+               container_of(work, struct dvb_usb_device, rc_query_work.work);
        u32 event;
        int state;
 
@@ -89,7 +90,9 @@ schedule:
 
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
+       struct input_dev *input_dev;
        int i;
+       int err;
 
        if (d->props.rc_key_map == NULL ||
                d->props.rc_query == NULL ||
@@ -99,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
        strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-       d->rc_input_dev = input_allocate_device();
-       if (!d->rc_input_dev)
+       input_dev = input_allocate_device();
+       if (!input_dev)
                return -ENOMEM;
 
-       d->rc_input_dev->evbit[0] = BIT(EV_KEY);
-       d->rc_input_dev->keycodesize = sizeof(unsigned char);
-       d->rc_input_dev->keycodemax = KEY_MAX;
-       d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
-       d->rc_input_dev->phys = d->rc_phys;
-       usb_to_input_id(d->udev, &d->rc_input_dev->id);
-       d->rc_input_dev->cdev.dev = &d->udev->dev;
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodemax = KEY_MAX;
+       input_dev->name = "IR-receiver inside an USB DVB receiver";
+       input_dev->phys = d->rc_phys;
+       usb_to_input_id(d->udev, &input_dev->id);
+       input_dev->cdev.dev = &d->udev->dev;
 
        /* set the bits for the keys */
        deb_rc("key map size: %d\n", d->props.rc_key_map_size);
        for (i = 0; i < d->props.rc_key_map_size; i++) {
-               deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
-               set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
+               deb_rc("setting bit for event %d item %d\n",
+                       d->props.rc_key_map[i].event, i);
+               set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
        }
 
        /* Start the remote-control polling. */
@@ -123,12 +127,18 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
                d->props.rc_interval = 100; /* default */
 
        /* setting these two values to non-zero, we have to manage key repeats */
-       d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
-       d->rc_input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
+       input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+       input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
 
-       input_register_device(d->rc_input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       d->rc_input_dev = input_dev;
 
-       INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
+       INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
 
        info("schedule remote query interval to %d msecs.", d->props.rc_interval);
        schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
index 376c45a..0d72173 100644 (file)
@@ -369,7 +369,7 @@ struct dvb_usb_device {
        /* remote control */
        struct input_dev *rc_input_dev;
        char rc_phys[64];
-       struct work_struct rc_query_work;
+       struct delayed_work rc_query_work;
        u32 last_event;
        int last_state;
 
index 7375eb2..518d67f 100644 (file)
@@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = gp8psk_streaming_ctrl,
-       .frontend_attach  = gp8psk_frontend_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .streaming_ctrl   = gp8psk_streaming_ctrl,
+                       .frontend_attach  = gp8psk_frontend_attach,
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x82,
-               .u = {
-                       .bulk = {
-                               .buffersize = 8192,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
                }
        },
        .power_ctrl       = gp8psk_power_ctrl,
index a58874c..d48622e 100644 (file)
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = {
                        .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
                        .pid_filter_count = 32,
 
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .pid_filter       = dibusb_pid_filter,
-       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
-
-       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .pid_filter       = dibusb_pid_filter,
+                       .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+                       .frontend_attach  = dibusb_dib3000mc_frontend_attach,
+                       .tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                                       .stream = {
+                                               .type = USB_BULK,
+                               .count = 7,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
 
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
new file mode 100644 (file)
index 0000000..95d2997
--- /dev/null
@@ -0,0 +1,270 @@
+/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
+ * (e.g. Pinnacle 400e DVB-S USB2.0).
+ *
+ * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
+ *
+ * TDA8263 + TDA10086
+ *
+ * I2C addresses:
+ * 0x08 - LNBP21PD   - LNB power supply
+ * 0x0e - TDA10086   - Demodulator
+ * 0x50 - FX2 eeprom
+ * 0x60 - TDA8263    - Tuner
+ * 0x78 ???
+ *
+ * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
+ * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
+ * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#define DVB_USB_LOG_PREFIX "ttusb2"
+#include "dvb-usb.h"
+
+#include "ttusb2.h"
+
+#include "tda826x.h"
+#include "tda10086.h"
+#include "lnbp21.h"
+
+/* debug */
+static int dvb_usb_ttusb2_debug;
+#define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
+module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+
+struct ttusb2_state {
+       u8 id;
+};
+
+static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
+               u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+       struct ttusb2_state *st = d->priv;
+       u8 s[wlen+4],r[64] = { 0 };
+       int ret = 0;
+
+       memset(s,0,wlen+4);
+
+       s[0] = 0xaa;
+       s[1] = ++st->id;
+       s[2] = cmd;
+       s[3] = wlen;
+       memcpy(&s[4],wbuf,wlen);
+
+       ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
+
+       if (ret  != 0 ||
+               r[0] != 0x55 ||
+               r[1] != s[1] ||
+               r[2] != cmd ||
+               (rlen > 0 && r[3] != rlen)) {
+               warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
+               return -EIO;
+       }
+
+       if (rlen > 0)
+               memcpy(rbuf, &r[4], rlen);
+
+       return 0;
+}
+
+static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       static u8 obuf[60], ibuf[60];
+       int i,read;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       if (num > 2)
+               warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+       for (i = 0; i < num; i++) {
+               read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+
+               obuf[0] = (msg[i].addr << 1) | read;
+               obuf[1] = msg[i].len;
+
+               /* read request */
+               if (read)
+                       obuf[2] = msg[i+1].len;
+               else
+                       obuf[2] = 0;
+
+               memcpy(&obuf[3],msg[i].buf,msg[i].len);
+
+               if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
+                       err("i2c transfer failed.");
+                       break;
+               }
+
+               if (read) {
+                       memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+                       i++;
+               }
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+}
+
+static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm ttusb2_i2c_algo = {
+       .master_xfer   = ttusb2_i2c_xfer,
+       .functionality = ttusb2_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int ttusb2_identify_state (struct usb_device *udev, struct
+               dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
+               int *cold)
+{
+       *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+       return 0;
+}
+
+static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       u8 b = onoff;
+       ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
+       return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
+}
+
+
+static struct tda10086_config tda10086_config = {
+       .demod_address = 0x0e,
+       .invert = 0,
+};
+
+static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       if (usb_set_interface(adap->dev->udev,0,3) < 0)
+               err("set interface to alts=3 failed");
+
+       if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+               deb_info("TDA10086 attach failed\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+               deb_info("TDA8263 attach failed\n");
+               return -ENODEV;
+       }
+
+       if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+               deb_info("LNBP21 attach failed\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties ttusb2_properties;
+
+static int ttusb2_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id ttusb2_table [] = {
+               { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+               {}              /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, ttusb2_table);
+
+static struct dvb_usb_device_properties ttusb2_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-pctv-400e-01.fw",
+
+       .size_of_priv = sizeof(struct ttusb2_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
+
+                       .frontend_attach  = ttusb2_frontend_attach,
+                       .tuner_attach     = ttusb2_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_ISOC,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .isoc = {
+                                               .framesperurb = 4,
+                                               .framesize = 940,
+                                               .interval = 1,
+                                       }
+                               }
+                       }
+               }
+       },
+
+       .power_ctrl       = ttusb2_power_ctrl,
+       .identify_state   = ttusb2_identify_state,
+
+       .i2c_algo         = &ttusb2_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "Pinnacle 400e DVB-S USB2.0",
+                       { &ttusb2_table[0], NULL },
+                       { NULL },
+               },
+       }
+};
+
+static struct usb_driver ttusb2_driver = {
+       .name           = "dvb_usb_ttusb2",
+       .probe          = ttusb2_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table       = ttusb2_table,
+};
+
+/* module stuff */
+static int __init ttusb2_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&ttusb2_driver))) {
+               err("usb_register failed. Error number %d",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit ttusb2_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&ttusb2_driver);
+}
+
+module_init (ttusb2_module_init);
+module_exit (ttusb2_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h
new file mode 100644 (file)
index 0000000..52a63af
--- /dev/null
@@ -0,0 +1,70 @@
+/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
+ * (e.g. Pinnacle 400e DVB-S USB2.0).
+ *
+ * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
+ * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
+ * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de>
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_TTUSB2_H_
+#define _DVB_USB_TTUSB2_H_
+
+/* TTUSB protocol
+ *
+ * always to messages (out/in)
+ * out message:
+ * 0xaa <id> <cmdbyte> <datalen> <data...>
+ *
+ * in message (complete block is always 0x40 bytes long)
+ * 0x55 <id> <cmdbyte> <datalen> <data...>
+ *
+ * id is incremented for each transaction
+ */
+
+#define CMD_DSP_DOWNLOAD    0x13
+/* out data: <byte>[28]
+ * last block must be empty */
+
+#define CMD_DSP_BOOT        0x14
+/* out data: nothing */
+
+#define CMD_POWER           0x15
+/* out data: <on=1/off=0> */
+
+#define CMD_LNB             0x16
+/* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */
+
+#define CMD_GET_VERSION     0x17
+/* in  data: <version_byte>[5] */
+
+#define CMD_DISEQC          0x18
+/* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */
+
+#define CMD_PID_ENABLE      0x22
+/* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */
+
+#define CMD_PID_DISABLE     0x23
+/* out data: <index> */
+
+#define CMD_FILTER_ENABLE   0x24
+/* out data: <index> <pid_idx> <filter>[12] <mask>[12] */
+
+#define CMD_FILTER_DISABLE  0x25
+/* out data: <index> */
+
+#define CMD_GET_DSP_VERSION 0x26
+/* in  data: <version_byte>[28] */
+
+#define CMD_I2C_XFER        0x31
+/* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen]
+ * in  data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */
+
+#define CMD_I2C_BITRATE     0x32
+/* out data: <default=0> */
+
+#endif
index f9941ea..f77b48f 100644 (file)
@@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
-       .frontend_attach  = umt_mt352_frontend_attach,
-       .tuner_attach     = umt_tuner_attach,
+                       .streaming_ctrl   = dibusb2_0_streaming_ctrl,
+                       .frontend_attach  = umt_mt352_frontend_attach,
+                       .tuner_attach     = umt_tuner_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 20,
-               .endpoint = 0x06,
-               .u = {
-                       .bulk = {
-                               .buffersize = 512,
-                       }
-               }
-       },
+                               .count = 20,
+                               .endpoint = 0x06,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 512,
+                                       }
+                               }
+                       },
 
                        .size_of_priv     = sizeof(struct dibusb_state),
                }
index 78035ee..397f51a 100644 (file)
@@ -116,7 +116,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num,
        for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
                deb_mem("allocating buffer %d\n",stream->buf_num);
                if (( stream->buf_list[stream->buf_num] =
-                                       usb_buffer_alloc(stream->udev, size, SLAB_ATOMIC,
+                                       usb_buffer_alloc(stream->udev, size, GFP_ATOMIC,
                                        &stream->dma_addr[stream->buf_num]) ) == NULL) {
                        deb_mem("not enough memory for urb-buffer allocation.\n");
                        usb_free_stream_buffers(stream);
index 02bd61a..16533b3 100644 (file)
@@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = {
                        .caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
 
                        .streaming_ctrl   = vp702x_streaming_ctrl,
-       .frontend_attach  = vp702x_frontend_attach,
+                       .frontend_attach  = vp702x_frontend_attach,
 
-       /* parameter for the MPEG2-data transfer */
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
                                .count = 10,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                        .size_of_priv     = sizeof(struct vp702x_state),
                }
-               },
+       },
        .read_mac_address = vp702x_read_mac_addr,
 
        .rc_key_map       = vp702x_rc_keys,
index b4cf002..69a46b3 100644 (file)
@@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = {
        { 0x00, 0x00, KEY_TAB }, /* Tab */
        { 0x00, 0x48, KEY_INFO }, /* Preview */
        { 0x00, 0x04, KEY_LIST }, /* RecordList */
-       { 0x00, 0x0f, KEY_TEXT } /* Teletext */
+       { 0x00, 0x0f, KEY_TEXT }, /* Teletext */
+       { 0x00, 0x41, KEY_PREVIOUSSONG },
+       { 0x00, 0x42, KEY_NEXTSONG },
+       { 0x00, 0x4b, KEY_UP },
+       { 0x00, 0x51, KEY_DOWN },
+       { 0x00, 0x4e, KEY_LEFT },
+       { 0x00, 0x52, KEY_RIGHT },
+       { 0x00, 0x4f, KEY_ENTER },
+       { 0x00, 0x13, KEY_CANCEL },
+       { 0x00, 0x4a, KEY_CLEAR },
+       { 0x00, 0x54, KEY_PRINT }, /* Capture */
+       { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */
+       { 0x00, 0x08, KEY_VIDEO }, /* A/V */
+       { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */
+       { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */
+       { 0x00, 0x18, KEY_RED},
+       { 0x00, 0x53, KEY_GREEN},
+       { 0x00, 0x5e, KEY_YELLOW},
+       { 0x00, 0x5f, KEY_BLUE}
 };
 
 static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@@ -217,18 +235,18 @@ static struct dvb_usb_device_properties vp7045_properties = {
        .num_adapters = 1,
        .adapter = {
                {
-       .frontend_attach  = vp7045_frontend_attach,
-       /* parameter for the MPEG2-data transfer */
+                       .frontend_attach  = vp7045_frontend_attach,
+                       /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-               .count = 7,
-               .endpoint = 0x02,
-               .u = {
-                       .bulk = {
-                               .buffersize = 4096,
-                       }
-               }
-       },
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
                }
        },
        .power_ctrl       = vp7045_power_ctrl,
index aebb8d6..af314bb 100644 (file)
@@ -172,6 +172,22 @@ config DVB_DIB3000MC
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
 
+config DVB_DIB7000M
+       tristate "DiBcom 7000MA/MB/PA/PB/MC"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+         to support this frontend.
+
+config DVB_DIB7000P
+       tristate "DiBcom 7000PC"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+         to support this frontend.
+
 comment "DVB-C (cable) frontends"
        depends on DVB_CORE
 
@@ -281,6 +297,14 @@ config DVB_TUNER_MT2060
        help
          A driver for the silicon IF tuner MT2060 from Microtune.
 
+config DVB_TUNER_LGH06XF
+       tristate "LG TDVS-H06xF ATSC tuner"
+       depends on DVB_CORE && I2C
+       select DVB_PLL
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the LG TDVS-H06xF ATSC tuner family.
+
 comment "Miscellaneous devices"
        depends on DVB_CORE
 
index dce9cf0..3fa6e5d 100644 (file)
@@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o
 obj-$(CONFIG_DVB_L64781) += l64781.o
 obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
 obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
 obj-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
 obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
 obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
index 3561a77..5da6617 100644 (file)
@@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000
 
 
        /* a channel for autosearch */
-       reg = 0;
-       if (chan->nfft == -1 && chan->guard == -1) reg = 7;
-       if (chan->nfft == -1 && chan->guard != -1) reg = 2;
-       if (chan->nfft != -1 && chan->guard == -1) reg = 3;
-
        fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
        fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
        fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
 
-       dib3000mc_set_channel_cfg(state, &fchan, reg);
+       dib3000mc_set_channel_cfg(state, &fchan, 7);
 
        reg = dib3000mc_read_word(state, 0);
        dib3000mc_write_word(state, 0, reg | (1 << 8));
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
new file mode 100644 (file)
index 0000000..f5d40aa
--- /dev/null
@@ -0,0 +1,1191 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB7000M and
+ *              first generation DiB7000P-demodulator-family.
+ *
+ * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib7000m.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0)
+
+struct dib7000m_state {
+       struct dvb_frontend demod;
+    struct dib7000m_config cfg;
+
+       u8 i2c_addr;
+       struct i2c_adapter   *i2c_adap;
+
+       struct dibx000_i2c_master i2c_master;
+
+/* offset is 1 in case of the 7000MC */
+       u8 reg_offs;
+
+       u16 wbd_ref;
+
+       u8 current_band;
+       fe_bandwidth_t current_bandwidth;
+       struct dibx000_agc_config *current_agc;
+       u32 timf;
+
+       u16 revision;
+};
+
+enum dib7000m_power_mode {
+       DIB7000M_POWER_ALL = 0,
+
+       DIB7000M_POWER_NO,
+       DIB7000M_POWER_INTERF_ANALOG_AGC,
+       DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
+       DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
+       DIB7000M_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+{
+       u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[2] = {
+               { .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+               dprintk("i2c read error on %d\n",reg);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
+{
+       int    ret = 0;
+       u16 outreg, fifo_threshold, smo_mode,
+               sram = 0x0005; /* by default SRAM output is disabled */
+
+       outreg = 0;
+       fifo_threshold = 1792;
+       smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
+
+       dprintk("-I-  Setting output mode for demod %p to %d\n",
+                       &state->demod, mode);
+
+       switch (mode) {
+               case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+                       outreg = (1 << 10);  /* 0x0400 */
+                       break;
+               case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+                       outreg = (1 << 10) | (1 << 6); /* 0x0440 */
+                       break;
+               case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+                       outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
+                       break;
+               case OUTMODE_DIVERSITY:
+                       if (state->cfg.hostbus_diversity)
+                               outreg = (1 << 10) | (4 << 6); /* 0x0500 */
+                       else
+                               sram   |= 0x0c00;
+                       break;
+               case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+                       smo_mode |= (3 << 1);
+                       fifo_threshold = 512;
+                       outreg = (1 << 10) | (5 << 6);
+                       break;
+               case OUTMODE_HIGH_Z:  // disable
+                       outreg = 0;
+                       break;
+               default:
+                       dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+                       break;
+       }
+
+       if (state->cfg.output_mpeg2_in_188_bytes)
+               smo_mode |= (1 << 5) ;
+
+       ret |= dib7000m_write_word(state,  294 + state->reg_offs, smo_mode);
+       ret |= dib7000m_write_word(state,  295 + state->reg_offs, fifo_threshold); /* synchronous fread */
+       ret |= dib7000m_write_word(state, 1795, outreg);
+       ret |= dib7000m_write_word(state, 1805, sram);
+
+       return ret;
+}
+
+static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
+{
+       /* by default everything is going to be powered off */
+       u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906  = 0x3fff;
+
+       /* now, depending on the requested mode, we power on */
+       switch (mode) {
+               /* power up everything in the demod */
+               case DIB7000M_POWER_ALL:
+                       reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
+                       break;
+
+               /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
+               case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
+                       reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
+                       break;
+
+               case DIB7000M_POWER_INTERF_ANALOG_AGC:
+                       reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
+                       reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
+                       reg_906 &= ~((1 << 0));
+                       break;
+
+               case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
+                       reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
+                       break;
+
+               case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
+                       reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
+                       break;
+               case DIB7000M_POWER_NO:
+                       break;
+       }
+
+       /* always power down unused parts */
+       if (!state->cfg.mobile_mode)
+               reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
+
+       /* P_sdio_select_clk = 0 on MC */
+       if (state->revision != 0x4000)
+               reg_906 <<= 1;
+
+       dib7000m_write_word(state,  903,  reg_903);
+       dib7000m_write_word(state,  904,  reg_904);
+       dib7000m_write_word(state,  905,  reg_905);
+       dib7000m_write_word(state,  906,  reg_906);
+
+       return 0;
+}
+
+static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
+{
+       int ret = 0;
+       u16 reg_913 = dib7000m_read_word(state, 913),
+              reg_914 = dib7000m_read_word(state, 914);
+
+       switch (no) {
+               case DIBX000_SLOW_ADC_ON:
+                       reg_914 |= (1 << 1) | (1 << 0);
+                       ret |= dib7000m_write_word(state, 914, reg_914);
+                       reg_914 &= ~(1 << 1);
+                       break;
+
+               case DIBX000_SLOW_ADC_OFF:
+                       reg_914 |=  (1 << 1) | (1 << 0);
+                       break;
+
+               case DIBX000_ADC_ON:
+                       if (state->revision == 0x4000) { // workaround for PA/MA
+                               // power-up ADC
+                               dib7000m_write_word(state, 913, 0);
+                               dib7000m_write_word(state, 914, reg_914 & 0x3);
+                               // power-down bandgag
+                               dib7000m_write_word(state, 913, (1 << 15));
+                               dib7000m_write_word(state, 914, reg_914 & 0x3);
+                       }
+
+                       reg_913 &= 0x0fff;
+                       reg_914 &= 0x0003;
+                       break;
+
+               case DIBX000_ADC_OFF: // leave the VBG voltage on
+                       reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
+                       reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+                       break;
+
+               case DIBX000_VBG_ENABLE:
+                       reg_913 &= ~(1 << 15);
+                       break;
+
+               case DIBX000_VBG_DISABLE:
+                       reg_913 |= (1 << 15);
+                       break;
+
+               default:
+                       break;
+       }
+
+//     dprintk("-D-  913: %x, 914: %x\n", reg_913, reg_914);
+
+       ret |= dib7000m_write_word(state, 913, reg_913);
+       ret |= dib7000m_write_word(state, 914, reg_914);
+
+       return ret;
+}
+
+static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx)
+{
+       struct dib7000m_state *state = demod->demodulator_priv;
+       u32 timf;
+
+       // store the current bandwidth for later use
+       state->current_bandwidth = bw_idx;
+
+       if (state->timf == 0) {
+               dprintk("-D-  Using default timf\n");
+               timf = state->cfg.bw->timf;
+       } else {
+               dprintk("-D-  Using updated timf\n");
+               timf = state->timf;
+       }
+
+       timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80;
+
+       dib7000m_write_word(state, 23, (timf >> 16) & 0xffff);
+       dib7000m_write_word(state, 24, (timf      ) & 0xffff);
+
+       return 0;
+}
+
+static int dib7000m_sad_calib(struct dib7000m_state *state)
+{
+
+/* internal */
+//     dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+       dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
+       dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
+
+       /* do the calibration */
+       dib7000m_write_word(state, 929, (1 << 0));
+       dib7000m_write_word(state, 929, (0 << 0));
+
+       msleep(1);
+
+       return 0;
+}
+
+static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
+{
+       dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
+       dib7000m_write_word(state, 19,  (bw->internal*1000)        & 0xffff);
+       dib7000m_write_word(state, 21,  (bw->ifreq          >> 16) & 0xffff);
+       dib7000m_write_word(state, 22,   bw->ifreq                 & 0xffff);
+
+       dib7000m_write_word(state, 928, bw->sad_cfg);
+}
+
+static void dib7000m_reset_pll(struct dib7000m_state *state)
+{
+       const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+       u16 reg_907,reg_910;
+
+       /* default */
+       reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
+               (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
+               (bw->enable_refdiv << 1) | (0 << 0);
+       reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
+
+       // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
+       // this is only working only for 30 MHz crystals
+       if (!state->cfg.quartz_direct) {
+               reg_910 |= (1 << 5);  // forcing the predivider to 1
+
+               // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
+               if(state->cfg.input_clk_is_div_2)
+                       reg_907 |= (16 << 9);
+               else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
+                       reg_907 |= (8 << 9);
+       } else {
+               reg_907 |= (bw->pll_ratio & 0x3f) << 9;
+               reg_910 |= (bw->pll_prediv << 5);
+       }
+
+       dib7000m_write_word(state, 910, reg_910); // pll cfg
+       dib7000m_write_word(state, 907, reg_907); // clk cfg0
+       dib7000m_write_word(state, 908, 0x0006);  // clk_cfg1
+
+       dib7000m_reset_pll_common(state, bw);
+}
+
+static void dib7000mc_reset_pll(struct dib7000m_state *state)
+{
+       const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+
+       // clk_cfg0
+       dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
+
+       // clk_cfg1
+       //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
+       dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) |
+                       (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
+                       (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0));
+
+       // smpl_cfg
+       dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
+
+       dib7000m_reset_pll_common(state, bw);
+}
+
+static int dib7000m_reset_gpio(struct dib7000m_state *st)
+{
+       /* reset the GPIOs */
+       dprintk("-D-  gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",
+               st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos);
+
+       dib7000m_write_word(st, 773, st->cfg.gpio_dir);
+       dib7000m_write_word(st, 774, st->cfg.gpio_val);
+
+       /* TODO 782 is P_gpio_od */
+
+       dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
+
+       dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
+       return 0;
+}
+
+static int dib7000m_demod_reset(struct dib7000m_state *state)
+{
+       dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+       /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
+       dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+       /* restart all parts */
+       dib7000m_write_word(state,  898, 0xffff);
+       dib7000m_write_word(state,  899, 0xffff);
+       dib7000m_write_word(state,  900, 0xff0f);
+       dib7000m_write_word(state,  901, 0xfffc);
+
+       dib7000m_write_word(state,  898, 0);
+       dib7000m_write_word(state,  899, 0);
+       dib7000m_write_word(state,  900, 0);
+       dib7000m_write_word(state,  901, 0);
+
+       if (state->revision == 0x4000)
+               dib7000m_reset_pll(state);
+       else
+               dib7000mc_reset_pll(state);
+
+       if (dib7000m_reset_gpio(state) != 0)
+               dprintk("-E-  GPIO reset was not successful.\n");
+
+       if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+               dprintk("-E-  OUTPUT_MODE could not be resetted.\n");
+
+       /* unforce divstr regardless whether i2c enumeration was done or not */
+       dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
+
+       dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+
+       dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+       dib7000m_sad_calib(state);
+       dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+
+       dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
+
+       return 0;
+}
+
+static void dib7000m_restart_agc(struct dib7000m_state *state)
+{
+       // P_restart_iqc & P_restart_agc
+       dib7000m_write_word(state, 898, 0x0c00);
+       dib7000m_write_word(state, 898, 0x0000);
+}
+
+static int dib7000m_agc_soft_split(struct dib7000m_state *state)
+{
+       u16 agc,split_offset;
+
+       if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
+               return 0;
+
+       // n_agc_global
+       agc = dib7000m_read_word(state, 390);
+
+       if (agc > state->current_agc->split.min_thres)
+               split_offset = state->current_agc->split.min;
+       else if (agc < state->current_agc->split.max_thres)
+               split_offset = state->current_agc->split.max;
+       else
+               split_offset = state->current_agc->split.max *
+                       (agc - state->current_agc->split.min_thres) /
+                       (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
+
+       dprintk("AGC split_offset: %d\n",split_offset);
+
+       // P_agc_force_split and P_agc_split_offset
+       return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
+}
+
+static int dib7000m_update_lna(struct dib7000m_state *state)
+{
+       int i;
+       u16 dyn_gain;
+
+       // when there is no LNA to program return immediatly
+       if (state->cfg.update_lna == NULL)
+               return 0;
+
+       msleep(60);
+       for (i = 0; i < 20; i++) {
+               // read dyn_gain here (because it is demod-dependent and not tuner)
+               dyn_gain = dib7000m_read_word(state, 390);
+
+               dprintk("agc global: %d\n", dyn_gain);
+
+               if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+                       dib7000m_restart_agc(state);
+                       msleep(60);
+               } else
+                       break;
+       }
+       return 0;
+}
+
+static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
+{
+       struct dibx000_agc_config *agc = NULL;
+       int i;
+       if (state->current_band == band)
+               return;
+       state->current_band = band;
+
+       for (i = 0; i < state->cfg.agc_config_count; i++)
+               if (state->cfg.agc[i].band_caps & band) {
+                       agc = &state->cfg.agc[i];
+                       break;
+               }
+
+       if (agc == NULL) {
+               dprintk("-E-  No valid AGC configuration found for band 0x%02x\n",band);
+               return;
+       }
+
+       state->current_agc = agc;
+
+       /* AGC */
+       dib7000m_write_word(state, 72 ,  agc->setup);
+       dib7000m_write_word(state, 73 ,  agc->inv_gain);
+       dib7000m_write_word(state, 74 ,  agc->time_stabiliz);
+       dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
+
+       // Demod AGC loop configuration
+       dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
+       dib7000m_write_word(state, 99, (agc->beta_mant  << 6) | agc->beta_exp);
+
+       dprintk("-D-  WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
+               state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+       /* AGC continued */
+       if (state->wbd_ref != 0)
+               dib7000m_write_word(state, 102, state->wbd_ref);
+       else // use default
+               dib7000m_write_word(state, 102, agc->wbd_ref);
+
+       dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
+       dib7000m_write_word(state, 104,  agc->agc1_max);
+       dib7000m_write_word(state, 105,  agc->agc1_min);
+       dib7000m_write_word(state, 106,  agc->agc2_max);
+       dib7000m_write_word(state, 107,  agc->agc2_min);
+       dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
+       dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+       dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+       dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+       if (state->revision > 0x4000) { // settings for the MC
+               dib7000m_write_word(state, 71,   agc->agc1_pt3);
+//             dprintk("-D-  929: %x %d %d\n",
+//                     (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
+               dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
+       } else {
+               // wrong default values
+               u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
+               for (i = 0; i < 9; i++)
+                       dib7000m_write_word(state, 88 + i, b[i]);
+       }
+}
+
+static void dib7000m_update_timf_freq(struct dib7000m_state *state)
+{
+       u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
+       state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+       dib7000m_write_word(state, 23, (u16) (timf >> 16));
+       dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
+       dprintk("-D-  Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+}
+
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+{
+       u16 value, est[4];
+
+       dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz));
+
+       /* nfft, guard, qam, alpha */
+       dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+       dib7000m_write_word(state, 5, (seq << 4));
+
+       /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
+       value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
+       if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
+               value |= (ch->vit_code_rate_hp << 1);
+       else
+               value |= (ch->vit_code_rate_lp << 1);
+       dib7000m_write_word(state, 267 + state->reg_offs, value);
+
+       /* offset loop parameters */
+
+       /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
+       dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
+
+       /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+       dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+       /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
+       dib7000m_write_word(state, 32, (0 << 4) | 0x3);
+
+       /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
+       dib7000m_write_word(state, 33, (0 << 4) | 0x5);
+
+       /* P_dvsy_sync_wait */
+       switch (ch->nfft) {
+               case 1: value = 256; break;
+               case 2: value = 128; break;
+               case 0:
+               default: value = 64; break;
+       }
+       value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
+       value <<= 4;
+
+       /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
+       /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+       if (ch->intlv_native || state->revision > 0x4000)
+               value |= (1 << 2) | (2 << 0);
+       else
+               value |= 0;
+       dib7000m_write_word(state, 266 + state->reg_offs, value);
+
+       /* channel estimation fine configuration */
+       switch (ch->nqam) {
+               case 2:
+                       est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
+                       est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
+                       est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+                       est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
+                       break;
+               case 1:
+                       est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
+                       est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
+                       est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+                       est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
+                       break;
+               default:
+                       est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
+                       est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
+                       est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
+                       est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
+                       break;
+       }
+       for (value = 0; value < 4; value++)
+               dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
+
+       // set power-up level: interf+analog+AGC
+       dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
+       dib7000m_set_adc_state(state, DIBX000_ADC_ON);
+
+       msleep(7);
+
+       //AGC initialization
+       if (state->cfg.agc_control)
+               state->cfg.agc_control(&state->demod, 1);
+
+       dib7000m_restart_agc(state);
+
+       // wait AGC rough lock time
+       msleep(5);
+
+       dib7000m_update_lna(state);
+       dib7000m_agc_soft_split(state);
+
+       // wait AGC accurate lock time
+       msleep(7);
+
+       if (state->cfg.agc_control)
+               state->cfg.agc_control(&state->demod, 0);
+
+       // set power-up level: autosearch
+       dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
+}
+
+static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+       struct dib7000m_state *state = demod->demodulator_priv;
+       struct dibx000_ofdm_channel auto_ch;
+       int ret = 0;
+       u32 value;
+
+       INIT_OFDM_CHANNEL(&auto_ch);
+       auto_ch.RF_kHz           = ch->RF_kHz;
+       auto_ch.Bw               = ch->Bw;
+       auto_ch.nqam             = 2;
+       auto_ch.guard            = 0;
+       auto_ch.nfft             = 1;
+       auto_ch.vit_alpha        = 1;
+       auto_ch.vit_select_hp    = 1;
+       auto_ch.vit_code_rate_hp = 2;
+       auto_ch.vit_code_rate_lp = 3;
+       auto_ch.vit_hrch         = 0;
+       auto_ch.intlv_native     = 1;
+
+       dib7000m_set_channel(state, &auto_ch, 7);
+
+       // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
+       value = 30 * state->cfg.bw->internal;
+       ret |= dib7000m_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
+       ret |= dib7000m_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
+       value = 100 * state->cfg.bw->internal;
+       ret |= dib7000m_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
+       ret |= dib7000m_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
+       value = 500 * state->cfg.bw->internal;
+       ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
+       ret |= dib7000m_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
+
+       // start search
+       value = dib7000m_read_word(state, 0);
+       ret |= dib7000m_write_word(state, 0, value | (1 << 9));
+
+       /* clear n_irq_pending */
+       if (state->revision == 0x4000)
+               dib7000m_write_word(state, 1793, 0);
+       else
+               dib7000m_read_word(state, 537);
+
+       ret |= dib7000m_write_word(state, 0, (u16) value);
+
+       return ret;
+}
+
+static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
+{
+       u16 irq_pending = dib7000m_read_word(state, reg);
+
+       if (irq_pending & 0x1) { // failed
+               dprintk("#\n");
+               return 1;
+       }
+
+       if (irq_pending & 0x2) { // succeeded
+               dprintk("!\n");
+               return 2;
+       }
+       return 0; // still pending
+}
+
+static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
+{
+       struct dib7000m_state *state = demod->demodulator_priv;
+       if (state->revision == 0x4000)
+               return dib7000m_autosearch_irq(state, 1793);
+       else
+               return dib7000m_autosearch_irq(state, 537);
+}
+
+static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+       struct dib7000m_state *state = demod->demodulator_priv;
+       int ret = 0;
+       u16 value;
+
+       // we are already tuned - just resuming from suspend
+       if (ch != NULL)
+               dib7000m_set_channel(state, ch, 0);
+       else
+               return -EINVAL;
+
+       // restart demod
+       ret |= dib7000m_write_word(state, 898, 0x4000);
+       ret |= dib7000m_write_word(state, 898, 0x0000);
+       msleep(45);
+
+       ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
+       /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+       ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+       // never achieved a lock with that bandwidth so far - wait for timfreq to update
+       if (state->timf == 0)
+               msleep(200);
+
+       //dump_reg(state);
+       /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+       value = (6 << 8) | 0x80;
+       switch (ch->nfft) {
+               case 0: value |= (7 << 12); break;
+               case 1: value |= (9 << 12); break;
+               case 2: value |= (8 << 12); break;
+       }
+       ret |= dib7000m_write_word(state, 26, value);
+
+       /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+       value = (0 << 4);
+       switch (ch->nfft) {
+               case 0: value |= 0x6; break;
+               case 1: value |= 0x8; break;
+               case 2: value |= 0x7; break;
+       }
+       ret |= dib7000m_write_word(state, 32, value);
+
+       /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+       value = (0 << 4);
+       switch (ch->nfft) {
+               case 0: value |= 0x6; break;
+               case 1: value |= 0x8; break;
+               case 2: value |= 0x7; break;
+       }
+       ret |= dib7000m_write_word(state, 33,  value);
+
+       // we achieved a lock - it's time to update the osc freq
+       if ((dib7000m_read_word(state, 535) >> 6)  & 0x1)
+               dib7000m_update_timf_freq(state);
+
+       return ret;
+}
+
+static int dib7000m_init(struct dvb_frontend *demod)
+{
+       struct dib7000m_state *state = demod->demodulator_priv;
+       int ret = 0;
+       u8 o = state->reg_offs;
+
+       dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+       if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
+               dprintk("-E-  could not start Slow ADC\n");
+
+       if (state->cfg.dvbt_mode)
+               dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
+
+       if (state->cfg.mobile_mode)
+               ret |= dib7000m_write_word(state, 261 + o, 2);
+       else
+               ret |= dib7000m_write_word(state, 224 + o, 1);
+
+       ret |= dib7000m_write_word(state, 173 + o, 0);
+       ret |= dib7000m_write_word(state, 174 + o, 0);
+       ret |= dib7000m_write_word(state, 175 + o, 0);
+       ret |= dib7000m_write_word(state, 176 + o, 0);
+       ret |= dib7000m_write_word(state, 177 + o, 0);
+       ret |= dib7000m_write_word(state, 178 + o, 0);
+       ret |= dib7000m_write_word(state, 179 + o, 0);
+       ret |= dib7000m_write_word(state, 180 + o, 0);
+
+       // P_corm_thres Lock algorithms configuration
+       ret |= dib7000m_write_word(state, 26, 0x6680);
+
+       // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
+       ret |= dib7000m_write_word(state, 170 + o, 0x0410);
+       // P_fft_nb_to_cut
+       ret |= dib7000m_write_word(state, 182 + o, 8192);
+       // P_pha3_thres
+       ret |= dib7000m_write_word(state, 195 + o, 0x0ccd);
+       // P_cti_use_cpe, P_cti_use_prog
+       ret |= dib7000m_write_word(state, 196 + o,     0);
+       // P_cspu_regul, P_cspu_win_cut
+       ret |= dib7000m_write_word(state, 205 + o, 0x200f);
+       // P_adp_regul_cnt
+       ret |= dib7000m_write_word(state, 214 + o, 0x023d);
+       // P_adp_noise_cnt
+       ret |= dib7000m_write_word(state, 215 + o, 0x00a4);
+       // P_adp_regul_ext
+       ret |= dib7000m_write_word(state, 216 + o, 0x00a4);
+       // P_adp_noise_ext
+       ret |= dib7000m_write_word(state, 217 + o, 0x7ff0);
+       // P_adp_fil
+       ret |= dib7000m_write_word(state, 218 + o, 0x3ccc);
+
+       // P_2d_byp_ti_num
+       ret |= dib7000m_write_word(state, 226 + o, 0);
+
+       // P_fec_*
+       ret |= dib7000m_write_word(state, 281 + o, 0x0010);
+       // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+       ret |= dib7000m_write_word(state, 294 + o,0x0062);
+
+       // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
+       if(state->cfg.tuner_is_baseband)
+               ret |= dib7000m_write_word(state, 36, 0x0755);
+       else
+               ret |= dib7000m_write_word(state, 36, 0x1f55);
+
+       // auto search configuration
+       ret |= dib7000m_write_word(state, 2,  0x0004);
+       ret |= dib7000m_write_word(state, 3,  0x1000);
+       ret |= dib7000m_write_word(state, 4,  0x0814);
+       ret |= dib7000m_write_word(state, 6,  0x001b);
+       ret |= dib7000m_write_word(state, 7,  0x7740);
+       ret |= dib7000m_write_word(state, 8,  0x005b);
+       ret |= dib7000m_write_word(state, 9,  0x8d80);
+       ret |= dib7000m_write_word(state, 10, 0x01c9);
+       ret |= dib7000m_write_word(state, 11, 0xc380);
+       ret |= dib7000m_write_word(state, 12, 0x0000);
+       ret |= dib7000m_write_word(state, 13, 0x0080);
+       ret |= dib7000m_write_word(state, 14, 0x0000);
+       ret |= dib7000m_write_word(state, 15, 0x0090);
+       ret |= dib7000m_write_word(state, 16, 0x0001);
+       ret |= dib7000m_write_word(state, 17, 0xd4c0);
+       ret |= dib7000m_write_word(state, 263 + o,0x0001);
+
+       // P_divclksel=3 P_divbitsel=1
+       if (state->revision == 0x4000)
+               dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
+       else
+               dib7000m_write_word(state, 909, (3 << 4) | 1);
+
+       // Tuner IO bank: max drive (14mA)
+       ret |= dib7000m_write_word(state, 912 ,0x2c8a);
+
+       ret |= dib7000m_write_word(state, 1817, 1);
+
+       return ret;
+}
+
+static int dib7000m_sleep(struct dvb_frontend *demod)
+{
+       struct dib7000m_state *st = demod->demodulator_priv;
+       dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
+       return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) |
+               dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
+               dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
+}
+
+static int dib7000m_identify(struct dib7000m_state *state)
+{
+       u16 value;
+       if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
+               dprintk("-E-  DiB7000M: wrong Vendor ID (read=0x%x)\n",value);
+               return -EREMOTEIO;
+       }
+
+       state->revision = dib7000m_read_word(state, 897);
+       if (state->revision != 0x4000 &&
+               state->revision != 0x4001 &&
+               state->revision != 0x4002) {
+               dprintk("-E-  DiB7000M: wrong Device ID (%x)\n",value);
+               return -EREMOTEIO;
+       }
+
+       /* protect this driver to be used with 7000PC */
+       if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
+               dprintk("-E-  DiB7000M: this driver does not work with DiB7000PC\n");
+               return -EREMOTEIO;
+       }
+
+       switch (state->revision) {
+               case 0x4000: dprintk("-I-  found DiB7000MA/PA/MB/PB\n"); break;
+               case 0x4001: state->reg_offs = 1; dprintk("-I-  found DiB7000HC\n"); break;
+               case 0x4002: state->reg_offs = 1; dprintk("-I-  found DiB7000MC\n"); break;
+       }
+
+       return 0;
+}
+
+
+static int dib7000m_get_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       u16 tps = dib7000m_read_word(state,480);
+
+       fep->inversion = INVERSION_AUTO;
+
+       fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+       switch ((tps >> 8) & 0x3) {
+               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+               /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+       }
+
+       switch (tps & 0x3) {
+               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+       }
+
+       switch ((tps >> 14) & 0x3) {
+               case 0: fep->u.ofdm.constellation = QPSK; break;
+               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 2:
+               default: fep->u.ofdm.constellation = QAM_64; break;
+       }
+
+       /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+       /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       switch ((tps >> 5) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+       }
+
+       switch ((tps >> 2) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+       }
+
+       /* native interleaver: (dib7000m_read_word(state, 481) >>  5) & 0x1 */
+
+       return 0;
+}
+
+static int dib7000m_set_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       struct dibx000_ofdm_channel ch;
+
+       INIT_OFDM_CHANNEL(&ch);
+       FEP2DIB(fep,&ch);
+
+       state->current_bandwidth = fep->u.ofdm.bandwidth;
+       dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, fep);
+
+       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
+               fep->u.ofdm.constellation     == QAM_AUTO ||
+               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+               int i = 800, found;
+
+               dib7000m_autosearch_start(fe, &ch);
+               do {
+                       msleep(1);
+                       found = dib7000m_autosearch_is_irq(fe);
+               } while (found == 0 && i--);
+
+               dprintk("autosearch returns: %d\n",found);
+               if (found == 0 || found == 1)
+                       return 0; // no channel found
+
+               dib7000m_get_frontend(fe, fep);
+               FEP2DIB(fep, &ch);
+       }
+
+       /* make this a config parameter */
+       dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+       return dib7000m_tune(fe, &ch);
+}
+
+static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       u16 lock = dib7000m_read_word(state, 535);
+
+       *stat = 0;
+
+       if (lock & 0x8000)
+               *stat |= FE_HAS_SIGNAL;
+       if (lock & 0x3000)
+               *stat |= FE_HAS_CARRIER;
+       if (lock & 0x0100)
+               *stat |= FE_HAS_VITERBI;
+       if (lock & 0x0010)
+               *stat |= FE_HAS_SYNC;
+       if (lock & 0x0008)
+               *stat |= FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
+       return 0;
+}
+
+static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       *unc = dib7000m_read_word(state, 534);
+       return 0;
+}
+
+static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct dib7000m_state *state = fe->demodulator_priv;
+       u16 val = dib7000m_read_word(state, 390);
+       *strength = 65535 - val;
+       return 0;
+}
+
+static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+       *snr = 0x0000;
+       return 0;
+}
+
+static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void dib7000m_release(struct dvb_frontend *demod)
+{
+       struct dib7000m_state *st = demod->demodulator_priv;
+       dibx000_exit_i2c_master(&st->i2c_master);
+       kfree(st);
+}
+
+struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+       struct dib7000m_state *st = demod->demodulator_priv;
+       return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000m_get_i2c_master);
+
+int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[])
+{
+       struct dib7000m_state st = { .i2c_adap = i2c };
+       int k = 0;
+       u8 new_addr = 0;
+
+       for (k = no_of_demods-1; k >= 0; k--) {
+               st.cfg = cfg[k];
+
+               /* designated i2c address */
+               new_addr          = (0x40 + k) << 1;
+               st.i2c_addr = new_addr;
+               if (dib7000m_identify(&st) != 0) {
+                       st.i2c_addr = default_addr;
+                       if (dib7000m_identify(&st) != 0) {
+                               dprintk("DiB7000M #%d: not identified\n", k);
+                               return -EIO;
+                       }
+               }
+
+               /* start diversity to pull_down div_str - just for i2c-enumeration */
+               dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
+
+               dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
+
+               /* set new i2c address and force divstart */
+               dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
+
+               dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+       }
+
+       for (k = 0; k < no_of_demods; k++) {
+               st.cfg = cfg[k];
+               st.i2c_addr = (0x40 + k) << 1;
+
+               // unforce divstr
+               dib7000m_write_word(&st,1794, st.i2c_addr << 2);
+
+               /* deactivate div - it was just for i2c-enumeration */
+               dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(dib7000m_i2c_enumeration);
+
+static struct dvb_frontend_ops dib7000m_ops;
+struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
+{
+       struct dvb_frontend *demod;
+       struct dib7000m_state *st;
+       st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
+       if (st == NULL)
+               return NULL;
+
+       memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
+       st->i2c_adap = i2c_adap;
+       st->i2c_addr = i2c_addr;
+
+       demod                   = &st->demod;
+       demod->demodulator_priv = st;
+       memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+
+       if (dib7000m_identify(st) != 0)
+               goto error;
+
+       if (st->revision == 0x4000)
+               dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
+       else
+               dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
+
+       dib7000m_demod_reset(st);
+
+       return demod;
+
+error:
+       kfree(st);
+       return NULL;
+}
+EXPORT_SYMBOL(dib7000m_attach);
+
+static struct dvb_frontend_ops dib7000m_ops = {
+       .info = {
+               .name = "DiBcom 7000MA/MB/PA/PB/MC",
+               .type = FE_OFDM,
+               .frequency_min      = 44250000,
+               .frequency_max      = 867250000,
+               .frequency_stepsize = 62500,
+               .caps = FE_CAN_INVERSION_AUTO |
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_HIERARCHY_AUTO,
+       },
+
+       .release              = dib7000m_release,
+
+       .init                 = dib7000m_init,
+       .sleep                = dib7000m_sleep,
+
+       .set_frontend         = dib7000m_set_frontend,
+       .get_tune_settings    = dib7000m_fe_get_tune_settings,
+       .get_frontend         = dib7000m_get_frontend,
+
+       .read_status          = dib7000m_read_status,
+       .read_ber             = dib7000m_read_ber,
+       .read_signal_strength = dib7000m_read_signal_strength,
+       .read_snr             = dib7000m_read_snr,
+       .read_ucblocks        = dib7000m_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h
new file mode 100644 (file)
index 0000000..597e9cc
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef DIB7000M_H
+#define DIB7000M_H
+
+#include "dibx000_common.h"
+
+struct dib7000m_config {
+       u8 dvbt_mode;
+       u8 output_mpeg2_in_188_bytes;
+       u8 hostbus_diversity;
+       u8 tuner_is_baseband;
+       u8 mobile_mode;
+       int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+       u8 agc_config_count;
+       struct dibx000_agc_config *agc;
+
+       struct dibx000_bandwidth_config *bw;
+
+#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
+       u16 gpio_dir;
+#define DIB7000M_GPIO_DEFAULT_VALUES     0x0000
+       u16 gpio_val;
+#define DIB7000M_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
+#define DIB7000M_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
+#define DIB7000M_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
+#define DIB7000M_GPIO_PWM_POS3(v)         (v & 0xf)
+#define DIB7000M_GPIO_DEFAULT_PWM_POS    0xffff
+       u16 gpio_pwm_pos;
+
+       u16 pwm_freq_div;
+
+       u8 quartz_direct;
+
+       u8 input_clk_is_div_2;
+
+       int (*agc_control) (struct dvb_frontend *, u8 before);
+};
+
+#define DEFAULT_DIB7000M_I2C_ADDRESS 18
+
+extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg);
+extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+
+/* TODO
+extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
+extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
+extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
+extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
+*/
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
new file mode 100644 (file)
index 0000000..0349a4b
--- /dev/null
@@ -0,0 +1,1019 @@
+/*
+ * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
+ *
+ * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib7000p.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0)
+
+struct dib7000p_state {
+       struct dvb_frontend demod;
+    struct dib7000p_config cfg;
+
+       u8 i2c_addr;
+       struct i2c_adapter   *i2c_adap;
+
+       struct dibx000_i2c_master i2c_master;
+
+       u16 wbd_ref;
+
+       u8 current_band;
+       fe_bandwidth_t current_bandwidth;
+       struct dibx000_agc_config *current_agc;
+       u32 timf;
+
+       u16 gpio_dir;
+       u16 gpio_val;
+};
+
+enum dib7000p_power_mode {
+       DIB7000P_POWER_ALL = 0,
+       DIB7000P_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+{
+       u8 wb[2] = { reg >> 8, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[2] = {
+               { .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+               dprintk("i2c read error on %d\n",reg);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
+{
+       int    ret = 0;
+       u16 outreg, fifo_threshold, smo_mode;
+
+       outreg = 0;
+       fifo_threshold = 1792;
+       smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1);
+
+       dprintk("-I-  Setting output mode for demod %p to %d\n",
+                       &state->demod, mode);
+
+       switch (mode) {
+               case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+                       outreg = (1 << 10);  /* 0x0400 */
+                       break;
+               case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+                       outreg = (1 << 10) | (1 << 6); /* 0x0440 */
+                       break;
+               case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+                       outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
+                       break;
+               case OUTMODE_DIVERSITY:
+                       if (state->cfg.hostbus_diversity)
+                               outreg = (1 << 10) | (4 << 6); /* 0x0500 */
+                       else
+                               outreg = (1 << 11);
+                       break;
+               case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+                       smo_mode |= (3 << 1);
+                       fifo_threshold = 512;
+                       outreg = (1 << 10) | (5 << 6);
+                       break;
+               case OUTMODE_HIGH_Z:  // disable
+                       outreg = 0;
+                       break;
+               default:
+                       dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+                       break;
+       }
+
+       if (state->cfg.output_mpeg2_in_188_bytes)
+               smo_mode |= (1 << 5) ;
+
+       ret |= dib7000p_write_word(state,  235, smo_mode);
+       ret |= dib7000p_write_word(state,  236, fifo_threshold); /* synchronous fread */
+       ret |= dib7000p_write_word(state, 1286, outreg);         /* P_Div_active */
+
+       return ret;
+}
+
+static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
+{
+       /* by default everything is powered off */
+       u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899  = 0x0003,
+               reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
+
+       /* now, depending on the requested mode, we power on */
+       switch (mode) {
+               /* power up everything in the demod */
+               case DIB7000P_POWER_ALL:
+                       reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
+                       break;
+               /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
+               case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
+                       reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
+                       break;
+/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
+       }
+
+       dib7000p_write_word(state,  774,  reg_774);
+       dib7000p_write_word(state,  775,  reg_775);
+       dib7000p_write_word(state,  776,  reg_776);
+       dib7000p_write_word(state,  899,  reg_899);
+       dib7000p_write_word(state, 1280, reg_1280);
+
+       return 0;
+}
+
+static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
+{
+       u16 reg_908 = dib7000p_read_word(state, 908),
+              reg_909 = dib7000p_read_word(state, 909);
+
+       switch (no) {
+               case DIBX000_SLOW_ADC_ON:
+                       reg_909 |= (1 << 1) | (1 << 0);
+                       dib7000p_write_word(state, 909, reg_909);
+                       reg_909 &= ~(1 << 1);
+                       break;
+
+               case DIBX000_SLOW_ADC_OFF:
+                       reg_909 |=  (1 << 1) | (1 << 0);
+                       break;
+
+               case DIBX000_ADC_ON:
+                       reg_908 &= 0x0fff;
+                       reg_909 &= 0x0003;
+                       break;
+
+               case DIBX000_ADC_OFF: // leave the VBG voltage on
+                       reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
+                       reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+                       break;
+
+               case DIBX000_VBG_ENABLE:
+                       reg_908 &= ~(1 << 15);
+                       break;
+
+               case DIBX000_VBG_DISABLE:
+                       reg_908 |= (1 << 15);
+                       break;
+
+               default:
+                       break;
+       }
+
+//     dprintk("908: %x, 909: %x\n", reg_908, reg_909);
+
+       dib7000p_write_word(state, 908, reg_908);
+       dib7000p_write_word(state, 909, reg_909);
+}
+
+static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx)
+{
+       struct dib7000p_state *state = demod->demodulator_priv;
+       u32 timf;
+
+       // store the current bandwidth for later use
+       state->current_bandwidth = BW_Idx;
+
+       if (state->timf == 0) {
+               dprintk("-D-  Using default timf\n");
+               timf = state->cfg.bw->timf;
+       } else {
+               dprintk("-D-  Using updated timf\n");
+               timf = state->timf;
+       }
+
+       timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80;
+
+       dprintk("timf: %d\n",timf);
+
+       dib7000p_write_word(state, 23, (timf >> 16) & 0xffff);
+       dib7000p_write_word(state, 24, (timf      ) & 0xffff);
+
+       return 0;
+}
+
+static int dib7000p_sad_calib(struct dib7000p_state *state)
+{
+/* internal */
+//     dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+       dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
+       dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
+
+       /* do the calibration */
+       dib7000p_write_word(state, 73, (1 << 0));
+       dib7000p_write_word(state, 73, (0 << 0));
+
+       msleep(1);
+
+       return 0;
+}
+
+static void dib7000p_reset_pll(struct dib7000p_state *state)
+{
+       struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
+
+       dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
+       dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) |
+               (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0));
+
+       dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
+       dib7000p_write_word(state, 19,  (bw->internal*1000       ) & 0xffff);
+       dib7000p_write_word(state, 21,  (bw->ifreq          >> 16) & 0xffff);
+       dib7000p_write_word(state, 22,  (bw->ifreq               ) & 0xffff);
+
+       dib7000p_write_word(state, 72, bw->sad_cfg);
+}
+
+static int dib7000p_reset_gpio(struct dib7000p_state *st)
+{
+       /* reset the GPIOs */
+       dprintk("-D-  gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
+
+       dib7000p_write_word(st, 1029, st->gpio_dir);
+       dib7000p_write_word(st, 1030, st->gpio_val);
+
+       /* TODO 1031 is P_gpio_od */
+
+       dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
+
+       dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
+       return 0;
+}
+
+static int dib7000p_demod_reset(struct dib7000p_state *state)
+{
+       dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+
+       dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+       /* restart all parts */
+       dib7000p_write_word(state,  770, 0xffff);
+       dib7000p_write_word(state,  771, 0xffff);
+       dib7000p_write_word(state,  772, 0x001f);
+       dib7000p_write_word(state,  898, 0x0003);
+       /* except i2c, sdio, gpio - control interfaces */
+       dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
+
+       dib7000p_write_word(state,  770, 0);
+       dib7000p_write_word(state,  771, 0);
+       dib7000p_write_word(state,  772, 0);
+       dib7000p_write_word(state,  898, 0);
+       dib7000p_write_word(state, 1280, 0);
+
+       /* default */
+       dib7000p_reset_pll(state);
+
+       if (dib7000p_reset_gpio(state) != 0)
+               dprintk("-E-  GPIO reset was not successful.\n");
+
+       if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+               dprintk("-E-  OUTPUT_MODE could not be resetted.\n");
+
+       /* unforce divstr regardless whether i2c enumeration was done or not */
+       dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
+
+       dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+
+       return 0;
+}
+
+static void dib7000p_restart_agc(struct dib7000p_state *state)
+{
+       // P_restart_iqc & P_restart_agc
+       dib7000p_write_word(state, 770, 0x0c00);
+       dib7000p_write_word(state, 770, 0x0000);
+}
+
+static void dib7000p_update_lna(struct dib7000p_state *state)
+{
+       int i;
+       u16 dyn_gain;
+
+       // when there is no LNA to program return immediatly
+       if (state->cfg.update_lna == NULL)
+               return;
+
+       for (i = 0; i < 5; i++) {
+               // read dyn_gain here (because it is demod-dependent and not tuner)
+               dyn_gain = dib7000p_read_word(state, 394);
+
+               if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+                       dib7000p_restart_agc(state);
+                       msleep(5);
+               } else
+                       break;
+       }
+}
+
+static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
+{
+       u16 tmp = 0;
+       tmp = dib7000p_read_word(state, 903);
+       dib7000p_write_word(state, 903, (tmp | 0x1));   //pwr-up pll
+       tmp = dib7000p_read_word(state, 900);
+       dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));     //use High freq clock
+}
+
+static void dib7000p_update_timf_freq(struct dib7000p_state *state)
+{
+       u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
+       state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+       dib7000p_write_word(state, 23, (u16) (timf >> 16));
+       dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
+       dprintk("-D-  Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+}
+
+static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+{
+       u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208;
+
+       /* nfft, guard, qam, alpha */
+       dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+       dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
+
+       /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
+       tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
+       if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
+               tmp |= (ch->vit_code_rate_hp << 1);
+       else
+               tmp |= (ch->vit_code_rate_lp << 1);
+       dib7000p_write_word(state, 208, tmp);
+
+       /* P_dvsy_sync_wait */
+       switch (ch->nfft) {
+               case 1: tmp = 256; break;
+               case 2: tmp = 128; break;
+               case 0:
+               default: tmp = 64; break;
+       }
+       tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
+       tmp <<= 4;
+
+       /* deactive the possibility of diversity reception if extended interleave */
+       /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+       if (ch->intlv_native || ch->nfft == 1)
+               tmp |= (1 << 2) | (2 << 0);
+       dib7000p_write_word(state, 207, tmp);
+
+       dib7000p_write_word(state, 26, 0x6680);   // timf(6xxx)
+       dib7000p_write_word(state, 29, 0x1273);   // isi inh1273 on1073
+       dib7000p_write_word(state, 32, 0x0003);   // pha_off_max(xxx3)
+       dib7000p_write_word(state, 33, 0x0005);   // sfreq(xxx5)
+
+       /* channel estimation fine configuration */
+       switch (ch->nqam) {
+               case 2:
+                       est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
+                       est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
+                       est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+                       est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
+                       break;
+               case 1:
+                       est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
+                       est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
+                       est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+                       est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
+                       break;
+               default:
+                       est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
+                       est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
+                       est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
+                       est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
+                       break;
+       }
+       for (tmp = 0; tmp < 4; tmp++)
+               dib7000p_write_word(state, 187 + tmp, est[tmp]);
+
+       // set power-up level: interf+analog+AGC
+       dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+       dib7000p_set_adc_state(state, DIBX000_ADC_ON);
+       dib7000p_pll_clk_cfg(state);
+       msleep(7);
+
+       // AGC initialization
+       if (state->cfg.agc_control)
+               state->cfg.agc_control(&state->demod, 1);
+
+       dib7000p_restart_agc(state);
+
+       // wait AGC rough lock time
+       msleep(5);
+
+       dib7000p_update_lna(state);
+
+       // wait AGC accurate lock time
+       msleep(7);
+       if (state->cfg.agc_control)
+               state->cfg.agc_control(&state->demod, 0);
+}
+
+static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+       struct dib7000p_state *state = demod->demodulator_priv;
+       struct dibx000_ofdm_channel auto_ch;
+       u32 value;
+
+       INIT_OFDM_CHANNEL(&auto_ch);
+       auto_ch.RF_kHz           = ch->RF_kHz;
+       auto_ch.Bw               = ch->Bw;
+       auto_ch.nqam             = 2;
+       auto_ch.guard            = 0;
+       auto_ch.nfft             = 1;
+       auto_ch.vit_alpha        = 1;
+       auto_ch.vit_select_hp    = 1;
+       auto_ch.vit_code_rate_hp = 2;
+       auto_ch.vit_code_rate_lp = 3;
+       auto_ch.vit_hrch         = 0;
+       auto_ch.intlv_native     = 1;
+
+       dib7000p_set_channel(state, &auto_ch, 7);
+
+       // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
+       value = 30 * state->cfg.bw->internal;
+       dib7000p_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
+       dib7000p_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
+       value = 100 * state->cfg.bw->internal;
+       dib7000p_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
+       dib7000p_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
+       value = 500 * state->cfg.bw->internal;
+       dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
+       dib7000p_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
+
+       value = dib7000p_read_word(state, 0);
+       dib7000p_write_word(state, 0, (1 << 9) | value);
+       dib7000p_read_word(state, 1284);
+       dib7000p_write_word(state, 0, (u16) value);
+
+       return 0;
+}
+
+static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
+{
+       struct dib7000p_state *state = demod->demodulator_priv;
+       u16 irq_pending = dib7000p_read_word(state, 1284);
+
+       if (irq_pending & 0x1) // failed
+               return 1;
+
+       if (irq_pending & 0x2) // succeeded
+               return 2;
+
+       return 0; // still pending
+}
+
+static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+       struct dib7000p_state *state = demod->demodulator_priv;
+       u16 tmp = 0;
+
+       if (ch != NULL)
+               dib7000p_set_channel(state, ch, 0);
+       else
+               return -EINVAL;
+
+       // restart demod
+       dib7000p_write_word(state, 770, 0x4000);
+       dib7000p_write_word(state, 770, 0x0000);
+       msleep(45);
+
+       /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+       dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+       // never achieved a lock with that bandwidth so far - wait for osc-freq to update
+       if (state->timf == 0)
+               msleep(200);
+
+       /* offset loop parameters */
+
+       /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+       tmp = (6 << 8) | 0x80;
+       switch (ch->nfft) {
+               case 0: tmp |= (7 << 12); break;
+               case 1: tmp |= (9 << 12); break;
+               case 2: tmp |= (8 << 12); break;
+       }
+       dib7000p_write_word(state, 26, tmp);  /* timf_a(6xxx) */
+
+       /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+       tmp = (0 << 4);
+       switch (ch->nfft) {
+               case 0: tmp |= 0x6; break;
+               case 1: tmp |= 0x8; break;
+               case 2: tmp |= 0x7; break;
+       }
+       dib7000p_write_word(state, 32,  tmp);
+
+       /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+       tmp = (0 << 4);
+       switch (ch->nfft) {
+               case 0: tmp |= 0x6; break;
+               case 1: tmp |= 0x8; break;
+               case 2: tmp |= 0x7; break;
+       }
+       dib7000p_write_word(state, 33,  tmp);
+
+       tmp = dib7000p_read_word(state,509);
+       if (!((tmp >> 6) & 0x1)) {
+               /* restart the fec */
+               tmp = dib7000p_read_word(state,771);
+               dib7000p_write_word(state, 771, tmp | (1 << 1));
+               dib7000p_write_word(state, 771, tmp);
+               msleep(10);
+               tmp = dib7000p_read_word(state,509);
+       }
+
+       // we achieved a lock - it's time to update the osc freq
+       if ((tmp >> 6) & 0x1)
+               dib7000p_update_timf_freq(state);
+
+       return 0;
+}
+
+static int dib7000p_init(struct dvb_frontend *demod)
+{
+       struct dibx000_agc_config *agc;
+       struct dib7000p_state *state = demod->demodulator_priv;
+       int ret = 0;
+
+       // Demodulator default configuration
+       agc = state->cfg.agc;
+
+       dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+       dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+
+       /* AGC */
+       ret |= dib7000p_write_word(state, 75 ,  agc->setup );
+       ret |= dib7000p_write_word(state, 76 ,  agc->inv_gain );
+       ret |= dib7000p_write_word(state, 77 ,  agc->time_stabiliz );
+       ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
+
+       // Demod AGC loop configuration
+       ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
+       ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6)  | agc->beta_exp);
+
+       /* AGC continued */
+       dprintk("-D-  WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
+               state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+       if (state->wbd_ref != 0)
+               ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
+       else
+               ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
+
+       ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
+
+       ret |= dib7000p_write_word(state, 107,  agc->agc1_max);
+       ret |= dib7000p_write_word(state, 108,  agc->agc1_min);
+       ret |= dib7000p_write_word(state, 109,  agc->agc2_max);
+       ret |= dib7000p_write_word(state, 110,  agc->agc2_min);
+       ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
+       ret |= dib7000p_write_word(state, 112,  agc->agc1_pt3);
+       ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+       ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+       ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+       /* disable power smoothing */
+       ret |= dib7000p_write_word(state, 145, 0);
+       ret |= dib7000p_write_word(state, 146, 0);
+       ret |= dib7000p_write_word(state, 147, 0);
+       ret |= dib7000p_write_word(state, 148, 0);
+       ret |= dib7000p_write_word(state, 149, 0);
+       ret |= dib7000p_write_word(state, 150, 0);
+       ret |= dib7000p_write_word(state, 151, 0);
+       ret |= dib7000p_write_word(state, 152, 0);
+
+       // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
+       ret |= dib7000p_write_word(state, 26 ,0x6680);
+
+       // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
+       ret |= dib7000p_write_word(state, 142,0x0410);
+       // P_fft_freq_dir=1, P_fft_nb_to_cut=0
+       ret |= dib7000p_write_word(state, 154,1 << 13);
+       // P_pha3_thres, default 0x3000
+       ret |= dib7000p_write_word(state, 168,0x0ccd);
+       // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
+       //ret |= dib7000p_write_word(state, 169,0x0010);
+       // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
+       ret |= dib7000p_write_word(state, 183,0x200f);
+       // P_adp_regul_cnt=573, default: 410
+       ret |= dib7000p_write_word(state, 187,0x023d);
+       // P_adp_noise_cnt=
+       ret |= dib7000p_write_word(state, 188,0x00a4);
+       // P_adp_regul_ext
+       ret |= dib7000p_write_word(state, 189,0x00a4);
+       // P_adp_noise_ext
+       ret |= dib7000p_write_word(state, 190,0x7ff0);
+       // P_adp_fil
+       ret |= dib7000p_write_word(state, 191,0x3ccc);
+
+       ret |= dib7000p_write_word(state, 222,0x0010);
+       // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+       ret |= dib7000p_write_word(state, 235,0x0062);
+
+       // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
+       if(state->cfg.tuner_is_baseband)
+               ret |= dib7000p_write_word(state, 36,0x0755);
+       else
+               ret |= dib7000p_write_word(state, 36,0x1f55);
+
+       // auto search configuration
+       ret |= dib7000p_write_word(state, 2  ,0x0004);
+       ret |= dib7000p_write_word(state, 3  ,0x1000);
+
+       /* Equal Lock */
+       ret |= dib7000p_write_word(state, 4   ,0x0814);
+
+       ret |= dib7000p_write_word(state, 6  ,0x001b);
+       ret |= dib7000p_write_word(state, 7  ,0x7740);
+       ret |= dib7000p_write_word(state, 8  ,0x005b);
+       ret |= dib7000p_write_word(state, 9  ,0x8d80);
+       ret |= dib7000p_write_word(state, 10 ,0x01c9);
+       ret |= dib7000p_write_word(state, 11 ,0xc380);
+       ret |= dib7000p_write_word(state, 12 ,0x0000);
+       ret |= dib7000p_write_word(state, 13 ,0x0080);
+       ret |= dib7000p_write_word(state, 14 ,0x0000);
+       ret |= dib7000p_write_word(state, 15 ,0x0090);
+       ret |= dib7000p_write_word(state, 16 ,0x0001);
+       ret |= dib7000p_write_word(state, 17 ,0xd4c0);
+
+       // P_clk_cfg1
+       ret |= dib7000p_write_word(state, 901, 0x0006);
+
+       // P_divclksel=3 P_divbitsel=1
+       ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
+
+       // Tuner IO bank: max drive (14mA) + divout pads max drive
+       ret |= dib7000p_write_word(state, 905, 0x2c8e);
+
+       ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+       dib7000p_sad_calib(state);
+
+       return ret;
+}
+
+static int dib7000p_sleep(struct dvb_frontend *demod)
+{
+       struct dib7000p_state *state = demod->demodulator_priv;
+       return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+}
+
+static int dib7000p_identify(struct dib7000p_state *st)
+{
+       u16 value;
+       dprintk("-I-  DiB7000PC: checking demod on I2C address: %d (%x)\n",
+               st->i2c_addr, st->i2c_addr);
+
+       if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
+               dprintk("-E-  DiB7000PC: wrong Vendor ID (read=0x%x)\n",value);
+               return -EREMOTEIO;
+       }
+
+       if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
+               dprintk("-E-  DiB7000PC: wrong Device ID (%x)\n",value);
+               return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+
+static int dib7000p_get_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       u16 tps = dib7000p_read_word(state,463);
+
+       fep->inversion = INVERSION_AUTO;
+
+       fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+       switch ((tps >> 8) & 0x3) {
+               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+               /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+       }
+
+       switch (tps & 0x3) {
+               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+       }
+
+       switch ((tps >> 14) & 0x3) {
+               case 0: fep->u.ofdm.constellation = QPSK; break;
+               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 2:
+               default: fep->u.ofdm.constellation = QAM_64; break;
+       }
+
+       /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+       /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       switch ((tps >> 5) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+       }
+
+       switch ((tps >> 2) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+       }
+
+       /* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */
+
+       return 0;
+}
+
+static int dib7000p_set_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       struct dibx000_ofdm_channel ch;
+
+       INIT_OFDM_CHANNEL(&ch);
+       FEP2DIB(fep,&ch);
+
+       state->current_bandwidth = fep->u.ofdm.bandwidth;
+       dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, fep);
+
+       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
+               fep->u.ofdm.constellation     == QAM_AUTO ||
+               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+               int i = 800, found;
+
+               dib7000p_autosearch_start(fe, &ch);
+               do {
+                       msleep(1);
+                       found = dib7000p_autosearch_is_irq(fe);
+               } while (found == 0 && i--);
+
+               dprintk("autosearch returns: %d\n",found);
+               if (found == 0 || found == 1)
+                       return 0; // no channel found
+
+               dib7000p_get_frontend(fe, fep);
+               FEP2DIB(fep, &ch);
+       }
+
+       /* make this a config parameter */
+       dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+       return dib7000p_tune(fe, &ch);
+}
+
+static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       u16 lock = dib7000p_read_word(state, 509);
+
+       *stat = 0;
+
+       if (lock & 0x8000)
+               *stat |= FE_HAS_SIGNAL;
+       if (lock & 0x3000)
+               *stat |= FE_HAS_CARRIER;
+       if (lock & 0x0100)
+               *stat |= FE_HAS_VITERBI;
+       if (lock & 0x0010)
+               *stat |= FE_HAS_SYNC;
+       if (lock & 0x0008)
+               *stat |= FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
+       return 0;
+}
+
+static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       *unc = dib7000p_read_word(state, 506);
+       return 0;
+}
+
+static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+       u16 val = dib7000p_read_word(state, 394);
+       *strength = 65535 - val;
+       return 0;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+       *snr = 0x0000;
+       return 0;
+}
+
+static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void dib7000p_release(struct dvb_frontend *demod)
+{
+       struct dib7000p_state *st = demod->demodulator_priv;
+       dibx000_exit_i2c_master(&st->i2c_master);
+       kfree(st);
+}
+
+int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+{
+       u8 tx[2], rx[2];
+       struct i2c_msg msg[2] = {
+               { .addr = 18 >> 1, .flags = 0,        .buf = tx, .len = 2 },
+               { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
+       };
+
+       tx[0] = 0x03;
+       tx[1] = 0x00;
+
+       if (i2c_transfer(i2c_adap, msg, 2) == 2)
+               if (rx[0] == 0x01 && rx[1] == 0xb3) {
+                       dprintk("-D-  DiB7000PC detected\n");
+                       return 1;
+               }
+
+       msg[0].addr = msg[1].addr = 0x40;
+
+       if (i2c_transfer(i2c_adap, msg, 2) == 2)
+               if (rx[0] == 0x01 && rx[1] == 0xb3) {
+                       dprintk("-D-  DiB7000PC detected\n");
+                       return 1;
+               }
+
+       dprintk("-D-  DiB7000PC not detected\n");
+       return 0;
+}
+EXPORT_SYMBOL(dib7000pc_detection);
+
+struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+       struct dib7000p_state *st = demod->demodulator_priv;
+       return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000p_get_i2c_master);
+
+int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+{
+       struct dib7000p_state st = { .i2c_adap = i2c };
+       int k = 0;
+       u8 new_addr = 0;
+
+       for (k = no_of_demods-1; k >= 0; k--) {
+               st.cfg = cfg[k];
+
+               /* designated i2c address */
+               new_addr          = (0x40 + k) << 1;
+               st.i2c_addr = new_addr;
+               if (dib7000p_identify(&st) != 0) {
+                       st.i2c_addr = default_addr;
+                       if (dib7000p_identify(&st) != 0) {
+                               dprintk("DiB7000P #%d: not identified\n", k);
+                               return -EIO;
+                       }
+               }
+
+               /* start diversity to pull_down div_str - just for i2c-enumeration */
+               dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY);
+
+               /* set new i2c address and force divstart */
+               dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);
+
+               dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+       }
+
+       for (k = 0; k < no_of_demods; k++) {
+               st.cfg = cfg[k];
+               st.i2c_addr = (0x40 + k) << 1;
+
+               // unforce divstr
+               dib7000p_write_word(&st, 1285, st.i2c_addr << 2);
+
+               /* deactivate div - it was just for i2c-enumeration */
+               dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(dib7000p_i2c_enumeration);
+
+static struct dvb_frontend_ops dib7000p_ops;
+struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+{
+       struct dvb_frontend *demod;
+       struct dib7000p_state *st;
+       st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
+       if (st == NULL)
+               return NULL;
+
+       memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
+       st->i2c_adap = i2c_adap;
+       st->i2c_addr = i2c_addr;
+       st->gpio_val = cfg->gpio_val;
+       st->gpio_dir = cfg->gpio_dir;
+
+       demod                   = &st->demod;
+       demod->demodulator_priv = st;
+       memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+
+       if (dib7000p_identify(st) != 0)
+               goto error;
+
+       dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
+
+       dib7000p_demod_reset(st);
+
+       return demod;
+
+error:
+       kfree(st);
+       return NULL;
+}
+EXPORT_SYMBOL(dib7000p_attach);
+
+static struct dvb_frontend_ops dib7000p_ops = {
+       .info = {
+               .name = "DiBcom 7000PC",
+               .type = FE_OFDM,
+               .frequency_min      = 44250000,
+               .frequency_max      = 867250000,
+               .frequency_stepsize = 62500,
+               .caps = FE_CAN_INVERSION_AUTO |
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_HIERARCHY_AUTO,
+       },
+
+       .release              = dib7000p_release,
+
+       .init                 = dib7000p_init,
+       .sleep                = dib7000p_sleep,
+
+       .set_frontend         = dib7000p_set_frontend,
+       .get_tune_settings    = dib7000p_fe_get_tune_settings,
+       .get_frontend         = dib7000p_get_frontend,
+
+       .read_status          = dib7000p_read_status,
+       .read_ber             = dib7000p_read_ber,
+       .read_signal_strength = dib7000p_read_signal_strength,
+       .read_snr             = dib7000p_read_snr,
+       .read_ucblocks        = dib7000p_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
new file mode 100644 (file)
index 0000000..79465cf
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef DIB7000P_H
+#define DIB7000P_H
+
+#include "dibx000_common.h"
+
+struct dib7000p_config {
+       u8 output_mpeg2_in_188_bytes;
+       u8 hostbus_diversity;
+       u8 tuner_is_baseband;
+       int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+       struct dibx000_agc_config *agc;
+       struct dibx000_bandwidth_config *bw;
+
+#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
+       u16 gpio_dir;
+#define DIB7000P_GPIO_DEFAULT_VALUES     0x0000
+       u16 gpio_val;
+#define DIB7000P_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
+#define DIB7000P_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
+#define DIB7000P_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
+#define DIB7000P_GPIO_PWM_POS3(v)         (v & 0xf)
+#define DIB7000P_GPIO_DEFAULT_PWM_POS    0xffff
+       u16 gpio_pwm_pos;
+
+       u16 pwm_freq_div;
+
+       u8 quartz_direct;
+
+       int (*agc_control) (struct dvb_frontend *, u8 before);
+};
+
+#define DEFAULT_DIB7000P_I2C_ADDRESS 18
+
+extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
+
+/* TODO
+extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
+extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
+extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
+extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
+*/
+
+#endif
index bb0c65f..a1df604 100644 (file)
@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
 #define BAND_LBAND 0x01
 #define BAND_UHF   0x02
 #define BAND_VHF   0x04
+#define BAND_SBAND 0x08
+#define BAND_FM           0x10
+
+#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
+                                                                       (freq_kHz) <= 250000 ? BAND_VHF : \
+                                                                       (freq_kHz) <= 863000 ? BAND_UHF : \
+                                                                       (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
 
 struct dibx000_agc_config {
        /* defines the capabilities of this AGC-setting - using the BAND_-defines*/
@@ -129,6 +136,7 @@ enum dibx000_adc_states {
 
 /* I hope I can get rid of the following kludge in the near future */
 struct dibx000_ofdm_channel {
+       u32 RF_kHz;
        u8  Bw;
        s16 nfft;
        s16 guard;
@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel {
        s16 vit_alpha;
        s16 vit_code_rate_hp;
        s16 vit_code_rate_lp;
+       u8  intlv_native;
 };
 
 #define FEP2DIB(fep,ch) \
+       (ch)->RF_kHz           = (fep)->frequency / 1000; \
        (ch)->Bw               = (fep)->u.ofdm.bandwidth; \
        (ch)->nfft             = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
        (ch)->guard            = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel {
        (ch)->vit_select_hp    = 1; \
        (ch)->vit_alpha        = 1; \
        (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
-       (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
+       (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
+       (ch)->intlv_native     = 1;
 
 #define INIT_OFDM_CHANNEL(ch) do {\
        (ch)->Bw               = 0;  \
index b7e7108..62de760 100644 (file)
@@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
                printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
                       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
 
-       return 0;
+       // calculate the frequency we set it to
+       return (div * desc->entries[i].stepsize) - desc->entries[i].offset;
 }
 EXPORT_SYMBOL(dvb_pll_configure);
 
 static int dvb_pll_release(struct dvb_frontend *fe)
 {
-       if (fe->tuner_priv)
-               kfree(fe->tuner_priv);
+       kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
 }
@@ -489,7 +489,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
        struct dvb_pll_priv *priv = fe->tuner_priv;
        u8 buf[4];
        struct i2c_msg msg =
-               { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+               { .addr = priv->pll_i2c_address, .flags = 0,
+                 .buf = buf, .len = sizeof(buf) };
        int i;
        int result;
 
@@ -517,16 +518,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvb_pll_set_params(struct dvb_frontend *fe,
+                             struct dvb_frontend_parameters *params)
 {
        struct dvb_pll_priv *priv = fe->tuner_priv;
        u8 buf[4];
        struct i2c_msg msg =
-               { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+               { .addr = priv->pll_i2c_address, .flags = 0,
+                 .buf = buf, .len = sizeof(buf) };
        int result;
-       u32 div;
-       int i;
-       u32 bandwidth = 0;
+       u32 bandwidth = 0, frequency = 0;
 
        if (priv->i2c == NULL)
                return -EINVAL;
@@ -536,8 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
                bandwidth = params->u.ofdm.bandwidth;
        }
 
-       if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+       if ((result = dvb_pll_configure(priv->pll_desc, buf,
+                                       params->frequency, bandwidth)) < 0)
                return result;
+       else
+               frequency = result;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -545,26 +549,19 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
                return result;
        }
 
-       // calculate the frequency we set it to
-       for (i = 0; i < priv->pll_desc->count; i++) {
-               if (params->frequency > priv->pll_desc->entries[i].limit)
-                       continue;
-               break;
-       }
-       div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
-       priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+       priv->frequency = frequency;
        priv->bandwidth = bandwidth;
 
        return 0;
 }
 
-static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+static int dvb_pll_calc_regs(struct dvb_frontend *fe,
+                            struct dvb_frontend_parameters *params,
+                            u8 *buf, int buf_len)
 {
        struct dvb_pll_priv *priv = fe->tuner_priv;
        int result;
-       u32 div;
-       int i;
-       u32 bandwidth = 0;
+       u32 bandwidth = 0, frequency = 0;
 
        if (buf_len < 5)
                return -EINVAL;
@@ -574,18 +571,15 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame
                bandwidth = params->u.ofdm.bandwidth;
        }
 
-       if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+       if ((result = dvb_pll_configure(priv->pll_desc, buf+1,
+                                       params->frequency, bandwidth)) < 0)
                return result;
+       else
+               frequency = result;
+
        buf[0] = priv->pll_i2c_address;
 
-       // calculate the frequency we set it to
-       for (i = 0; i < priv->pll_desc->count; i++) {
-               if (params->frequency > priv->pll_desc->entries[i].limit)
-                       continue;
-               break;
-       }
-       div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
-       priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+       priv->frequency = frequency;
        priv->bandwidth = bandwidth;
 
        return 5;
@@ -614,10 +608,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
        .get_bandwidth = dvb_pll_get_bandwidth,
 };
 
-struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
+                                   struct i2c_adapter *i2c,
+                                   struct dvb_pll_desc *desc)
 {
        u8 b1 [] = { 0 };
-       struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
+       struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
+                              .buf = b1, .len = 1 };
        struct dvb_pll_priv *priv = NULL;
        int ret;
 
@@ -640,7 +637,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc
        priv->i2c = i2c;
        priv->pll_desc = desc;
 
-       memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+       memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
        strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
        fe->ops.tuner_ops.info.frequency_min = desc->min;
        fe->ops.tuner_ops.info.frequency_min = desc->max;
index ed5ac5a..681186a 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
 
 extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
-                     u32 freq, int bandwidth);
+                            u32 freq, int bandwidth);
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
@@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
  * @param desc dvb_pll_desc to use.
  * @return Frontend pointer on success, NULL on failure
  */
-extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+                                          int pll_addr,
+                                          struct i2c_adapter *i2c,
+                                          struct dvb_pll_desc *desc);
 
 #endif
index f3bc82e..1aeacb1 100644 (file)
@@ -36,7 +36,7 @@ struct l64781_state {
        struct dvb_frontend frontend;
 
        /* private demodulator data */
-       int first:1;
+       unsigned int first:1;
 };
 
 #define dprintk(args...) \
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
deleted file mode 100644 (file)
index 754d51d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
- *
- *  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.
- */
-
-#ifndef _LG_H06XF_H_
-#define _LG_H06XF_H_
-#include "dvb-pll.h"
-
-static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
-                    struct dvb_frontend_parameters* params)
-{
-       u8 buf[4];
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0,
-                              .buf = buf, .len = sizeof(buf) };
-       int err;
-
-       dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "lg_h06xf: %s error "
-                       "(addr %02x <- %02x, err = %i)\n",
-                       __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       /* Set the Auxiliary Byte. */
-       buf[0] = buf[2];
-       buf[0] &= ~0x20;
-       buf[0] |= 0x18;
-       buf[1] = 0x50;
-       msg.len = 2;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "lg_h06xf: %s error "
-                       "(addr %02x <- %02x, err = %i)\n",
-                       __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       return 0;
-}
-#endif
index 9a35470..68aad0f 100644 (file)
@@ -31,9 +31,6 @@
  *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
  *   pcHDTV HD5500
  *
- * TODO:
- * signal strength always returns 0.
- *
  */
 
 #include <linux/kernel.h>
 #include <asm/byteorder.h>
 
 #include "dvb_frontend.h"
+#include "dvb_math.h"
 #include "lgdt330x_priv.h"
 #include "lgdt330x.h"
 
+/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
+/* #define USE_EQMSE */
+
 static int debug = 0;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
@@ -68,6 +69,7 @@ struct lgdt330x_state
 
        /* Demodulator private data */
        fe_modulation_t current_modulation;
+       u32 snr; /* Result of last SNR calculation */
 
        /* Tuner private data */
        u32 current_frequency;
@@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        static u8 lgdt3303_8vsb_44_data[] = {
                0x04, 0x00,
                0x0d, 0x40,
-       0x0e, 0x87,
-       0x0f, 0x8e,
-       0x10, 0x01,
-       0x47, 0x8b };
+               0x0e, 0x87,
+               0x0f, 0x8e,
+               0x10, 0x01,
+               0x47, 0x8b };
 
        /*
         * Array of byte pairs <address, value>
@@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
                /* Test signal does not exist flag */
                /* as well as the AGC lock flag.   */
                *status |= FE_HAS_SIGNAL;
-       } else {
-               /* Without a signal all other status bits are meaningless */
-               return 0;
        }
 
        /*
@@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
                /* Test input signal does not exist flag */
                /* as well as the AGC lock flag.   */
                *status |= FE_HAS_SIGNAL;
-       } else {
-               /* Without a signal all other status bits are meaningless */
-               return 0;
        }
 
        /* Carrier Recovery Lock Status Register */
@@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
        return 0;
 }
 
-static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+/* Calculate SNR estimation (scaled by 2^24)
+
+   8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
+   equations from LGDT3303 datasheet.  VSB is the same between the '02
+   and '03, so maybe QAM is too?  Perhaps someone with a newer datasheet
+   that has QAM information could verify?
+
+   For 8-VSB: (two ways, take your pick)
+   LGDT3302:
+     SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
+   LGDT3303:
+     SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
+   LGDT3302 & LGDT3303:
+     SNR_PT = 10 * log10(25 * 32^2 / PT_MSE)  (we use this one)
+   For 64-QAM:
+     SNR    = 10 * log10( 688128   / MSEQAM)
+   For 256-QAM:
+     SNR    = 10 * log10( 696320   / MSEQAM)
+
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - intlog10(MSE))
+   Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
+
+static u32 calculate_snr(u32 mse, u32 c)
 {
-       /* not directly available. */
-       *strength = 0;
-       return 0;
+       if (mse == 0) /* No signal */
+               return 0;
+
+       mse = intlog10(mse);
+       if (mse > c) {
+               /* Negative SNR, which is possible, but realisticly the
+               demod will lose lock before the signal gets this bad.  The
+               API only allows for unsigned values, so just return 0 */
+               return 0;
+       }
+       return 10*(c - mse);
 }
 
 static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-#ifdef SNR_IN_DB
-       /*
-        * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
-        * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
-        * respectively. The following tables are built on these formulas.
-        * The usual definition is SNR = 20 log10(signal/noise)
-        * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
-        *
-        * This table is a an ordered list of noise values computed by the
-        * formula from the spec sheet such that the index into the table
-        * starting at 43 or 45 is the SNR value in db. There are duplicate noise
-        * value entries at the beginning because the SNR varies more than
-        * 1 db for a change of 1 digit in noise at very small values of noise.
-        *
-        * Examples from SNR_EQ table:
-        * noise SNR
-        *   0    43
-        *   1    42
-        *   2    39
-        *   3    37
-        *   4    36
-        *   5    35
-        *   6    34
-        *   7    33
-        *   8    33
-        *   9    32
-        *   10   32
-        *   11   31
-        *   12   31
-        *   13   30
-        */
-
-       static const u32 SNR_EQ[] =
-               { 1,     2,      2,      2, 3,      3,      4,     4,     5,     7,
-                 9,     11,     13,     17, 21,     26,     33,    41,    52,    65,
-                 81,    102,    129,    162, 204,    257,    323,   406,   511,   644,
-                 810,   1020,   1284,   1616, 2035,   2561,   3224,  4059,  5110,  6433,
-                 8098,  10195,  12835,  16158, 20341,  25608,  32238, 40585, 51094, 64323,
-                 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
-               };
-
-       static const u32 SNR_PH[] =
-               { 1,     2,      2,      2,      3,      3,     4,     5,     6,     8,
-                 10,    12,     15,     19,     23,     29, 37,    46,    58,    73,
-                 91,    115,    144,    182,    229,    288, 362,   456,   574,   722,
-                 909,   1144,   1440,   1813,   2282,   2873, 3617,  4553,  5732,  7216,
-                 9084,  11436,  14396,  18124,  22817,  28724,  36161, 45524, 57312, 72151,
-                 90833, 114351, 143960, 181235, 228161, 0x080000
-               };
-
-       static u8 buf[5];/* read data buffer */
-       static u32 noise;   /* noise value */
-       static u32 snr_db;  /* index into SNR_EQ[] */
        struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+       u8 buf[5];      /* read data buffer */
+       u32 noise;      /* noise value */
+       u32 c;          /* per-modulation SNR calculation constant */
 
-       /* read both equalizer and phase tracker noise data */
-       i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
-
-       if (state->current_modulation == VSB_8) {
-               /* Equalizer Mean-Square Error Register for VSB */
+       switch(state->current_modulation) {
+       case VSB_8:
+               i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+               /* Use Equalizer Mean-Square Error Register */
+               /* SNR for ranges from -15.61 to +41.58 */
                noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
-
-               /*
-                * Look up noise value in table.
-                * A better search algorithm could be used...
-                * watch out there are duplicate entries.
-                */
-               for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
-                       if (noise < SNR_EQ[snr_db]) {
-                               *snr = 43 - snr_db;
-                               break;
-                       }
-               }
-       } else {
-               /* Phase Tracker Mean-Square Error Register for QAM */
-               noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
-
-               /* Look up noise value in table. */
-               for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
-                       if (noise < SNR_PH[snr_db]) {
-                               *snr = 45 - snr_db;
-                               break;
-                       }
-               }
-       }
+               c = 69765745; /* log10(25*24^2)*2^24 */
 #else
-       /* Return the raw noise value */
-       static u8 buf[5];/* read data buffer */
-       static u32 noise;   /* noise value */
-       struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-
-       /* read both equalizer and pase tracker noise data */
-       i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
-
-       if (state->current_modulation == VSB_8) {
-               /* Phase Tracker Mean-Square Error Register for VSB */
+               /* Use Phase Tracker Mean-Square Error Register */
+               /* SNR for ranges from -13.11 to +44.08 */
                noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
-       } else {
-
-               /* Carrier Recovery Mean-Square Error for QAM */
-               i2c_read_demod_bytes(state, 0x1a, buf, 2);
+               c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+               break;
+       case QAM_64:
+       case QAM_256:
+               i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
                noise = ((buf[0] & 3) << 8) | buf[1];
+               c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+               /* log10(688128)*2^24 and log10(696320)*2^24 */
+               break;
+       default:
+               printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+                      __FUNCTION__);
+               return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
-       /* Small values for noise mean signal is better so invert noise */
-       *snr = ~noise;
-#endif
+       state->snr = calculate_snr(noise, c);
+       *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
-       dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+               state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
 }
 
 static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       /* Return the raw noise value */
-       static u8 buf[5];/* read data buffer */
-       static u32 noise;   /* noise value */
        struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+       u8 buf[5];      /* read data buffer */
+       u32 noise;      /* noise value */
+       u32 c;          /* per-modulation SNR calculation constant */
 
-       if (state->current_modulation == VSB_8) {
-
-               i2c_read_demod_bytes(state, 0x6e, buf, 5);
-               /* Phase Tracker Mean-Square Error Register for VSB */
+       switch(state->current_modulation) {
+       case VSB_8:
+               i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+               /* Use Equalizer Mean-Square Error Register */
+               /* SNR for ranges from -16.12 to +44.08 */
+               noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
+               c = 73957994; /* log10(25*32^2)*2^24 */
+#else
+               /* Use Phase Tracker Mean-Square Error Register */
+               /* SNR for ranges from -13.11 to +44.08 */
                noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
-       } else {
-
-               /* Carrier Recovery Mean-Square Error for QAM */
-               i2c_read_demod_bytes(state, 0x1a, buf, 2);
+               c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+               break;
+       case QAM_64:
+       case QAM_256:
+               i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
                noise = (buf[0] << 8) | buf[1];
+               c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+               /* log10(688128)*2^24 and log10(696320)*2^24 */
+               break;
+       default:
+               printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+                      __FUNCTION__);
+               return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
-       /* Small values for noise mean signal is better so invert noise */
-       *snr = ~noise;
+       state->snr = calculate_snr(noise, c);
+       *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+               state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+
+       return 0;
+}
+
+static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+       /* Calculate Strength from SNR up to 35dB */
+       /* Even though the SNR can go higher than 35dB, there is some comfort */
+       /* factor in having a range of strong signals that can show at 100%   */
+       struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+       u16 snr;
+       int ret;
 
-       dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+       ret = fe->ops.read_snr(fe, &snr);
+       if (ret != 0)
+               return ret;
+       /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+       /* scale the range 0 - 35*2^24 into 0 - 65535 */
+       if (state->snr >= 8960 * 0x10000)
+               *strength = 0xffff;
+       else
+               *strength = state->snr / 8960;
 
        return 0;
 }
index 59b7c5b..38c7669 100644 (file)
@@ -51,14 +51,19 @@ enum I2C_REG {
        AGC_RFIF_ACC2= 0x3b,
        AGC_STATUS= 0x3f,
        SYNC_STATUS_VSB= 0x43,
-       EQPH_ERR0= 0x47,
-       EQ_ERR1= 0x48,
-       EQ_ERR2= 0x49,
-       PH_ERR1= 0x4a,
-       PH_ERR2= 0x4b,
        DEMUX_CONTROL= 0x66,
+       LGDT3302_EQPH_ERR0= 0x47,
+       LGDT3302_EQ_ERR1= 0x48,
+       LGDT3302_EQ_ERR2= 0x49,
+       LGDT3302_PH_ERR1= 0x4a,
+       LGDT3302_PH_ERR2= 0x4b,
        LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
        LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+       LGDT3303_EQPH_ERR0= 0x6e,
+       LGDT3303_EQ_ERR1= 0x6f,
+       LGDT3303_EQ_ERR2= 0x70,
+       LGDT3303_PH_ERR1= 0x71,
+       LGDT3303_PH_ERR2= 0x72,
        LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
        LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
 };
diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c
new file mode 100644 (file)
index 0000000..2202d0c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  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 "dvb-pll.h"
+#include "lgh06xf.h"
+
+#define LG_H06XF_PLL_I2C_ADDR 0x61
+
+struct lgh06xf_priv {
+       struct i2c_adapter *i2c;
+       u32 frequency;
+};
+
+static int lgh06xf_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int lgh06xf_set_params(struct dvb_frontend* fe,
+                             struct dvb_frontend_parameters* params)
+{
+       struct lgh06xf_priv *priv = fe->tuner_priv;
+       u8 buf[4];
+       struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+       u32 frequency;
+       int result;
+
+       if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf,
+                                       params->frequency, 0)) < 0)
+               return result;
+       else
+               frequency = result;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lgh06xf: %s error "
+                      "(addr %02x <- %02x, result = %i)\n",
+                      __FUNCTION__, buf[0], buf[1], result);
+               if (result < 0)
+                       return result;
+               else
+                       return -EREMOTEIO;
+       }
+
+       /* Set the Auxiliary Byte. */
+       buf[0] = buf[2];
+       buf[0] &= ~0x20;
+       buf[0] |= 0x18;
+       buf[1] = 0x50;
+       msg.len = 2;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lgh06xf: %s error "
+                      "(addr %02x <- %02x, result = %i)\n",
+                      __FUNCTION__, buf[0], buf[1], result);
+               if (result < 0)
+                       return result;
+               else
+                       return -EREMOTEIO;
+       }
+
+       priv->frequency = frequency;
+
+       return 0;
+}
+
+static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct lgh06xf_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static struct dvb_tuner_ops lgh06xf_tuner_ops = {
+       .release       = lgh06xf_release,
+       .set_params    = lgh06xf_set_params,
+       .get_frequency = lgh06xf_get_frequency,
+};
+
+struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe,
+                                   struct i2c_adapter *i2c)
+{
+       struct lgh06xf_priv *priv = NULL;
+
+       priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->i2c = i2c;
+
+       memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name,
+               sizeof(fe->ops.tuner_ops.info.name));
+
+       fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min;
+       fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max;
+
+       fe->tuner_priv = priv;
+       return fe;
+}
+
+EXPORT_SYMBOL(lgh06xf_attach);
+
+MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support");
+MODULE_AUTHOR("Michael Krufky");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h
new file mode 100644 (file)
index 0000000..510b4be
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  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.
+ */
+
+#ifndef _LGH06XF_H_
+#define _LGH06XF_H_
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE))
+extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
+                                           struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
+                                                 struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_TUNER_LGH06XF */
+
+#endif /* _LGH06XF_H_ */
index d20ab30..5a3a6e5 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <asm/byteorder.h>
 
+#include "dvb_math.h"
 #include "dvb_frontend.h"
 #include "dvb-pll.h"
 #include "or51132.h"
@@ -62,6 +63,7 @@ struct or51132_state
 
        /* Demodulator private data */
        fe_modulation_t current_modulation;
+       u32 snr; /* Result of last SNR calculation */
 
        /* Tuner private data */
        u32 current_frequency;
@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
        return 0;
 }
 
-/* log10-1 table at .5 increments from 1 to 100.5 */
-static unsigned int i100x20log10[] = {
-     0,  352,  602,  795,  954, 1088, 1204, 1306, 1397, 1480,
-  1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
-  2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
-  2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
-  2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
-  2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
-  2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
-  3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
-  3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
-  3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
-  3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
-  3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
-  3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
-  3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
-  3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
-  3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
-  3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
-  3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
-  3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
-  3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
-};
+/* Calculate SNR estimation (scaled by 2^24)
 
-static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
+   8-VSB SNR and QAM equations from Oren datasheets
 
-static unsigned int i20Log10(unsigned short val)
-{
-       unsigned int rntval = 100;
-       unsigned int tmp = val;
-       unsigned int exp = 1;
+   For 8-VSB:
+     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
+
+     Where K = 0 if NTSC rejection filter is OFF; and
+          K = 3 if NTSC rejection filter is ON
+
+   For QAM64:
+     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
 
-       while(tmp > 100) {tmp /= 100; exp++;}
+   For QAM256:
+     SNR[dB] = 10 * log10(907832426.314266  / MSE^2 )
 
-       val = (2 * val)/denom[exp];
-       if (exp > 1) rntval = 2000*exp;
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+   Where for QAM256, c = log10(907832426.314266) * 2^24
+   and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
 
-       rntval += i100x20log10[val];
-       return rntval;
+static u32 calculate_snr(u32 mse, u32 c)
+{
+       if (mse == 0) /* No signal */
+               return 0;
+
+       mse = 2*intlog10(mse);
+       if (mse > c) {
+               /* Negative SNR, which is possible, but realisticly the
+               demod will lose lock before the signal gets this bad.  The
+               API only allows for unsigned values, so just return 0 */
+               return 0;
+       }
+       return 10*(c - mse);
 }
 
-static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct or51132_state* state = fe->demodulator_priv;
-       unsigned char rec_buf[2];
-       unsigned char snd_buf[2];
-       u8 rcvr_stat;
-       u16 snr_equ;
-       u32 signal_strength;
-       int usK;
+       u8 rec_buf[2];
+       u8 snd_buf[2];
+       u32 noise;
+       u32 c;
+       u32 usK;
 
+       /* Register is same for VSB or QAM firmware */
        snd_buf[0]=0x04;
        snd_buf[1]=0x02; /* SNR after Equalizer */
        msleep(30); /* 30ms */
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
-               printk(KERN_WARNING "or51132: read_status write error\n");
-               return -1;
+               printk(KERN_WARNING "or51132: snr write error\n");
+               return -EREMOTEIO;
        }
        msleep(30); /* 30ms */
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51132: read_status read error\n");
-               return -1;
+               printk(KERN_WARNING "or51132: snr read error\n");
+               return -EREMOTEIO;
        }
-       snr_equ = rec_buf[0] | (rec_buf[1] << 8);
-       dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
+       noise = rec_buf[0] | (rec_buf[1] << 8);
+       dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise);
 
-       /* Receiver Status */
+       /* Read status, contains modulation type for QAM_AUTO and
+          NTSC filter for VSB */
        snd_buf[0]=0x04;
-       snd_buf[1]=0x00;
+       snd_buf[1]=0x00; /* Status register */
        msleep(30); /* 30ms */
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
-               printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n");
-               return -1;
+               printk(KERN_WARNING "or51132: status write error\n");
+               return -EREMOTEIO;
        }
        msleep(30); /* 30ms */
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n");
-               return -1;
+               printk(KERN_WARNING "or51132: status read error\n");
+               return -EREMOTEIO;
        }
-       dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
-       rcvr_stat = rec_buf[1];
-       usK = (rcvr_stat & 0x10) ? 3 : 0;
 
-       /* The value reported back from the frontend will be FFFF=100% 0000=0% */
-       signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
-       if (signal_strength > 0xffff)
-               *strength = 0xffff;
-       else
-               *strength = signal_strength;
-       dprintk("read_signal_strength %i\n",*strength);
+       usK = 0;
+       switch (rec_buf[0]) {
+       case 0x06:
+               usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0;
+               /* Fall through to QAM64 case */
+       case 0x43:
+               c = 150204167;
+               break;
+       case 0x45:
+               c = 150290396;
+               break;
+       default:
+               printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]);
+               return -EREMOTEIO;
+       }
+       dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
+               rec_buf[0], rec_buf[1]&0x10?"n":"ff");
+
+       /* Calculate SNR using noise, c, and NTSC rejection correction */
+       state->snr = calculate_snr(noise, c) - usK;
+       *snr = (state->snr) >> 16;
+
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+               state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
 }
 
-static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
+static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct or51132_state* state = fe->demodulator_priv;
-       unsigned char rec_buf[2];
-       unsigned char snd_buf[2];
-       u16 snr_equ;
-
-       snd_buf[0]=0x04;
-       snd_buf[1]=0x02; /* SNR after Equalizer */
-       msleep(30); /* 30ms */
-       if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
-               printk(KERN_WARNING "or51132: read_snr write error\n");
-               return -1;
-       }
-       msleep(30); /* 30ms */
-       if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51132: read_snr dvr read error\n");
-               return -1;
-       }
-       snr_equ = rec_buf[0] | (rec_buf[1] << 8);
-       dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
+       /* Calculate Strength from SNR up to 35dB */
+       /* Even though the SNR can go higher than 35dB, there is some comfort */
+       /* factor in having a range of strong signals that can show at 100%   */
+       struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+       u16 snr;
+       int ret;
 
-       *snr = 0xFFFF - snr_equ;
-       dprintk("read_snr %i\n",*snr);
+       ret = fe->ops.read_snr(fe, &snr);
+       if (ret != 0)
+               return ret;
+       /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+       /* scale the range 0 - 35*2^24 into 0 - 65535 */
+       if (state->snr >= 8960 * 0x10000)
+               *strength = 0xffff;
+       else
+               *strength = state->snr / 8960;
 
        return 0;
 }
index 2bf124b..048d7cf 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/slab.h>
 #include <asm/byteorder.h>
 
+#include "dvb_math.h"
 #include "dvb_frontend.h"
 #include "or51211.h"
 
@@ -63,6 +64,7 @@ struct or51211_state {
 
        /* Demodulator private data */
        u8 initialized:1;
+       u32 snr; /* Result of last SNR claculation */
 
        /* Tuner private data */
        u32 current_frequency;
@@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
        return 0;
 }
 
-/* log10-1 table at .5 increments from 1 to 100.5 */
-static unsigned int i100x20log10[] = {
-               0,  352,  602,  795,  954, 1088, 1204, 1306, 1397, 1480,
-        1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
-        2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
-        2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
-        2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
-        2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
-        2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
-        3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
-        3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
-        3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
-        3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
-        3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
-        3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
-        3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
-        3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
-        3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
-        3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
-        3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
-        3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
-        3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
-};
-
-static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
+/* Calculate SNR estimation (scaled by 2^24)
 
-static unsigned int i20Log10(unsigned short val)
-{
-       unsigned int rntval = 100;
-       unsigned int tmp = val;
-       unsigned int exp = 1;
+   8-VSB SNR equation from Oren datasheets
 
-       while(tmp > 100) {tmp /= 100; exp++;}
+   For 8-VSB:
+     SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
 
-       val = (2 * val)/denom[exp];
-       if (exp > 1) rntval = 2000*exp;
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+   Where for 8-VSB, c = log10(219037.9454) * 2^24 */
 
-       rntval += i100x20log10[val];
-       return rntval;
+static u32 calculate_snr(u32 mse, u32 c)
+{
+       if (mse == 0) /* No signal */
+               return 0;
+
+       mse = 2*intlog10(mse);
+       if (mse > c) {
+               /* Negative SNR, which is possible, but realisticly the
+               demod will lose lock before the signal gets this bad.  The
+               API only allows for unsigned values, so just return 0 */
+               return 0;
+       }
+       return 10*(c - mse);
 }
 
-static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct or51211_state* state = fe->demodulator_priv;
        u8 rec_buf[2];
-       u8 snd_buf[4];
-       u8 snr_equ;
-       u32 signal_strength;
+       u8 snd_buf[3];
 
        /* SNR after Equalizer */
        snd_buf[0] = 0x04;
        snd_buf[1] = 0x00;
        snd_buf[2] = 0x04;
-       snd_buf[3] = 0x00;
 
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-               printk(KERN_WARNING "or51211: read_status write error\n");
+               printk(KERN_WARNING "%s: error writing snr reg\n",
+                      __FUNCTION__);
                return -1;
        }
-       msleep(3);
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51211: read_status read error\n");
+               printk(KERN_WARNING "%s: read_status read error\n",
+                      __FUNCTION__);
                return -1;
        }
-       snr_equ = rec_buf[0] & 0xff;
 
-       /* The value reported back from the frontend will be FFFF=100% 0000=0% */
-       signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
-       if (signal_strength > 0xffff)
-               *strength = 0xffff;
-       else
-               *strength = signal_strength;
-       dprintk("read_signal_strength %i\n",*strength);
+       state->snr = calculate_snr(rec_buf[0], 89599047);
+       *snr = (state->snr) >> 16;
+
+       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
+               state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
 }
 
-static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct or51211_state* state = fe->demodulator_priv;
-       u8 rec_buf[2];
-       u8 snd_buf[4];
-
-       /* SNR after Equalizer */
-       snd_buf[0] = 0x04;
-       snd_buf[1] = 0x00;
-       snd_buf[2] = 0x04;
-       snd_buf[3] = 0x00;
-
-       if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-               printk(KERN_WARNING "or51211: read_status write error\n");
-               return -1;
-       }
-       msleep(3);
-       if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-               printk(KERN_WARNING "or51211: read_status read error\n");
-               return -1;
-       }
-       *snr = rec_buf[0] & 0xff;
-
-       dprintk("read_snr %i\n",*snr);
+       /* Calculate Strength from SNR up to 35dB */
+       /* Even though the SNR can go higher than 35dB, there is some comfort */
+       /* factor in having a range of strong signals that can show at 100%   */
+       struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
+       u16 snr;
+       int ret;
+
+       ret = fe->ops.read_snr(fe, &snr);
+       if (ret != 0)
+               return ret;
+       /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+       /* scale the range 0 - 35*2^24 into 0 - 65535 */
+       if (state->snr >= 8960 * 0x10000)
+               *strength = 0xffff;
+       else
+               *strength = state->snr / 8960;
 
        return 0;
 }
index 11e0dca..00e4bcd 100644 (file)
@@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe)
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
                tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
                break;
-       case TDA10046_AGC_TDA827X:
+       case TDA10046_AGC_TDA827X_GP11:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
                tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
                tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
                tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
                break;
-       case TDA10046_AGC_TDA827X_GPL:
+       case TDA10046_AGC_TDA827X_GP00:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
                tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
                tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
                tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
                break;
+       case TDA10046_AGC_TDA827X_GP01:
+               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
+               tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
+               tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities
+               break;
        }
        tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
        tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
index 605ad2d..ec502d7 100644 (file)
@@ -35,8 +35,9 @@ enum tda10046_agc {
        TDA10046_AGC_DEFAULT,           /* original configuration */
        TDA10046_AGC_IFO_AUTO_NEG,      /* IF AGC only, automatic, negtive */
        TDA10046_AGC_IFO_AUTO_POS,      /* IF AGC only, automatic, positive */
-       TDA10046_AGC_TDA827X,           /* IF AGC only, special setup for tda827x */
-       TDA10046_AGC_TDA827X_GPL,       /* same as above, but GPIOs 0 */
+       TDA10046_AGC_TDA827X_GP11,      /* IF AGC only, special setup for tda827x */
+       TDA10046_AGC_TDA827X_GP00,      /* same as above, but GPIOs 0 */
+       TDA10046_AGC_TDA827X_GP01,      /* same as above, but GPIO3=0 GPIO1=1*/
 };
 
 enum tda10046_if {
index 3aa45eb..67415c9 100644 (file)
@@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
        if (sync & 0x10)
                *status |= FE_HAS_SYNC;
 
+       if (sync & 0x20) /* frontend can not lock */
+               *status |= FE_TIMEDOUT;
+
        if ((sync & 0x1f) == 0x1f)
                *status |= FE_HAS_LOCK;
 
        return 0;
 }
 
+static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       struct tda8083_state* state = fe->demodulator_priv;
+       int ret;
+       u8 buf[3];
+
+       if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
+               return ret;
+
+       *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
+
+       return 0;
+}
+
 static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
        struct tda8083_state* state = fe->demodulator_priv;
@@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
        return 0;
 }
 
+static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+       struct tda8083_state* state = fe->demodulator_priv;
+
+       *ucblocks = tda8083_readreg(state, 0x0f);
+       if (*ucblocks == 0xff)
+               *ucblocks = 0xffffffff;
+
+       return 0;
+}
+
 static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
        struct tda8083_state* state = fe->demodulator_priv;
@@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = {
        .read_status = tda8083_read_status,
        .read_signal_strength = tda8083_read_signal_strength,
        .read_snr = tda8083_read_snr,
+       .read_ber = tda8083_read_ber,
+       .read_ucblocks = tda8083_read_ucblocks,
 
        .diseqc_send_master_cmd = tda8083_send_diseqc_msg,
        .diseqc_send_burst = tda8083_diseqc_send_burst,
index 34815b0..79f971d 100644 (file)
@@ -42,8 +42,7 @@ struct tda826x_priv {
 
 static int tda826x_release(struct dvb_frontend *fe)
 {
-       if (fe->tuner_priv)
-               kfree(fe->tuner_priv);
+       kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
 }
@@ -133,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
 {
        struct tda826x_priv *priv = NULL;
        u8 b1 [] = { 0, 0 };
-       struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 };
+       struct i2c_msg msg[2] = {
+               { .addr = addr, .flags = 0,        .buf = NULL, .len = 0 },
+               { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }
+       };
        int ret;
 
        dprintk("%s:\n", __FUNCTION__);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       ret = i2c_transfer (i2c, &msg, 1);
+       ret = i2c_transfer (i2c, msg, 2);
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
 
-       if (ret != 1)
+       if (ret != 2)
                return NULL;
        if (!(b1[1] & 0x80))
                return NULL;
index 8855439..6ba0029 100644 (file)
@@ -43,8 +43,7 @@ struct tua6100_priv {
 
 static int tua6100_release(struct dvb_frontend *fe)
 {
-       if (fe->tuner_priv)
-               kfree(fe->tuner_priv);
+       kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
 }
index 95531a6..eec7ccf 100644 (file)
@@ -92,6 +92,7 @@ config DVB_BUDGET_CI
        select DVB_STV0299 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select VIDEO_IR
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
index bba23bc..366c137 100644 (file)
@@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension av7110_extension = {
        .name           = "dvb",
-       .flags          = SAA7146_I2C_SHORT_DELAY,
+       .flags          = SAA7146_USE_I2C_IRQ,
 
        .module         = THIS_MODULE,
        .pci_tbl        = &pci_tbl[0],
index d54bbcd..e4544ea 100644 (file)
@@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data)
        if (!data || !test_bit(data, input_dev->key))
                return;
 
-       input_event(input_dev, EV_KEY, data, !!0);
+       input_report_key(input_dev, data, 0);
+       input_sync(input_dev);
 }
 
 
@@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm)
                del_timer(&keyup_timer);
                if (keyup_timer.data != keycode || new_toggle != old_toggle) {
                        delay_timer_finished = 0;
-                       input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
-                       input_event(input_dev, EV_KEY, keycode, !0);
-               } else
-                       if (delay_timer_finished)
-                               input_event(input_dev, EV_KEY, keycode, 2);
+                       input_event(input_dev, EV_KEY, keyup_timer.data, 0);
+                       input_event(input_dev, EV_KEY, keycode, 1);
+                       input_sync(input_dev);
+               } else if (delay_timer_finished) {
+                       input_event(input_dev, EV_KEY, keycode, 2);
+                       input_sync(input_dev);
+               }
        } else {
                delay_timer_finished = 0;
-               input_event(input_dev, EV_KEY, keycode, !0);
+               input_event(input_dev, EV_KEY, keycode, 1);
+               input_sync(input_dev);
        }
 
        keyup_timer.expires = jiffies + UP_TIMEOUT;
@@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
 int __devinit av7110_ir_init(struct av7110 *av7110)
 {
        static struct proc_dir_entry *e;
+       int err;
 
        if (av_cnt >= sizeof av_list/sizeof av_list[0])
                return -ENOSPC;
@@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
                set_bit(EV_KEY, input_dev->evbit);
                set_bit(EV_REP, input_dev->evbit);
                input_register_keys();
-               input_register_device(input_dev);
+               err = input_register_device(input_dev);
+               if (err) {
+                       input_free_device(input_dev);
+                       return err;
+               }
                input_dev->timer.function = input_repeat_key;
 
                e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
index 2235ff8..89ab4b5 100644 (file)
@@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av)
        saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
 
        /* Enable DEBI pins */
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
+       saa7146_write(saa, MC1, MASK_27 | MASK_11);
 
        /* register CI interface */
        budget_av->ca.owner = THIS_MODULE;
@@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av)
        return 0;
 
 error:
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
        return result;
 }
 
@@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av)
        dvb_ca_en50221_release(&budget_av->ca);
 
        /* disable DEBI pins */
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
 }
 
 
@@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = {
        .demod_address = 0x0c,
 };
 
+static struct tda10021_config philips_cu1216_config_altaddress = {
+       .demod_address = 0x0d,
+};
+
 
 
 
@@ -831,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
                return -EINVAL;
 
        rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
-                       params->frequency, 0);
+                            params->frequency, 0);
        if(rc < 0) return rc;
 
        if (fe->ops.i2c_gate_ctrl)
@@ -914,6 +918,7 @@ static u8 read_pwm(struct budget_av *budget_av)
 #define SUBID_DVBS_TV_STAR_CI  0x0016
 #define SUBID_DVBS_EASYWATCH_1  0x001a
 #define SUBID_DVBS_EASYWATCH   0x001e
+#define SUBID_DVBC_EASYWATCH   0x002a
 #define SUBID_DVBC_KNC1                0x0020
 #define SUBID_DVBC_KNC1_PLUS   0x0021
 #define SUBID_DVBC_CINERGY1200 0x1156
@@ -947,11 +952,15 @@ static void frontend_init(struct budget_av *budget_av)
        /* Enable / PowerON Frontend */
        saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
 
+       /* Wait for PowerON */
+       msleep(100);
+
        /* additional setup necessary for the PLUS cards */
        switch (saa->pci->subsystem_device) {
                case SUBID_DVBS_KNC1_PLUS:
                case SUBID_DVBC_KNC1_PLUS:
                case SUBID_DVBT_KNC1_PLUS:
+               case SUBID_DVBC_EASYWATCH:
                        saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
                        break;
        }
@@ -1006,10 +1015,15 @@ static void frontend_init(struct budget_av *budget_av)
        case SUBID_DVBC_KNC1:
        case SUBID_DVBC_KNC1_PLUS:
        case SUBID_DVBC_CINERGY1200:
+       case SUBID_DVBC_EASYWATCH:
                budget_av->reinitialise_demod = 1;
                fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
                                     &budget_av->budget.i2c_adap,
                                     read_pwm(budget_av));
+               if (fe == NULL)
+                       fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
+                                            &budget_av->budget.i2c_adap,
+                                            read_pwm(budget_av));
                if (fe) {
                        budget_av->tda10021_poclkp = 1;
                        budget_av->tda10021_set_frontend = fe->ops.set_frontend;
@@ -1242,6 +1256,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
 MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
 MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
@@ -1260,6 +1275,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
        MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
        MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
+       MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
        MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
        MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
        MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
@@ -1277,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
        .name = "budget_av",
-       .flags = SAA7146_I2C_SHORT_DELAY,
+       .flags = SAA7146_USE_I2C_IRQ,
 
        .pci_tbl = pci_tbl,
 
index cd5ec48..f2066b4 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/spinlock.h>
+#include <media/ir-common.h>
 
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
 #define SLOTSTATUS_READY       8
 #define SLOTSTATUS_OCCUPIED    (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+/* Milliseconds during which key presses are regarded as key repeat and during
+ * which the debounce logic is active
+ */
+#define IR_REPEAT_TIMEOUT      350
+
+/* RC5 device wildcard */
+#define IR_DEVICE_ANY          255
+
+/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
+ * this setting allows the superflous sequences to be ignored
+ */
+static int debounce = 0;
+module_param(debounce, int, 0644);
+MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
+
+static int rc5_device = -1;
+module_param(rc5_device, int, 0644);
+MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+struct budget_ci_ir {
+       struct input_dev *dev;
+       struct tasklet_struct msp430_irq_tasklet;
+       char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
+       char phys[32];
+       struct ir_input_state state;
+       int rc5_device;
+};
+
 struct budget_ci {
        struct budget budget;
-       struct input_dev *input_dev;
-       struct tasklet_struct msp430_irq_tasklet;
        struct tasklet_struct ciintf_irq_tasklet;
        int slot_status;
        int ci_irq;
        struct dvb_ca_en50221 ca;
-       char ir_dev_name[50];
+       struct budget_ci_ir ir;
        u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 };
 
-/* from reading the following remotes:
-   Zenith Universal 7 / TV Mode 807 / VCR Mode 837
-   Hauppauge (from NOVA-CI-s box product)
-   i've taken a "middle of the road" approach and note the differences
-*/
-static u16 key_map[64] = {
-       /* 0x0X */
-       KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
-       KEY_9,
-       KEY_ENTER,
-       KEY_RED,
-       KEY_POWER,              /* RADIO on Hauppauge */
-       KEY_MUTE,
-       0,
-       KEY_A,                  /* TV on Hauppauge */
-       /* 0x1X */
-       KEY_VOLUMEUP, KEY_VOLUMEDOWN,
-       0, 0,
-       KEY_B,
-       0, 0, 0, 0, 0, 0, 0,
-       KEY_UP, KEY_DOWN,
-       KEY_OPTION,             /* RESERVED on Hauppauge */
-       KEY_BREAK,
-       /* 0x2X */
-       KEY_CHANNELUP, KEY_CHANNELDOWN,
-       KEY_PREVIOUS,           /* Prev. Ch on Zenith, SOURCE on Hauppauge */
-       0, KEY_RESTART, KEY_OK,
-       KEY_CYCLEWINDOWS,       /* MINIMIZE on Hauppauge */
-       0,
-       KEY_ENTER,              /* VCR mode on Zenith */
-       KEY_PAUSE,
-       0,
-       KEY_RIGHT, KEY_LEFT,
-       0,
-       KEY_MENU,               /* FULL SCREEN on Hauppauge */
-       0,
-       /* 0x3X */
-       KEY_SLOW,
-       KEY_PREVIOUS,           /* VCR mode on Zenith */
-       KEY_REWIND,
-       0,
-       KEY_FASTFORWARD,
-       KEY_PLAY, KEY_STOP,
-       KEY_RECORD,
-       KEY_TUNER,              /* TV/VCR on Zenith */
-       0,
-       KEY_C,
-       0,
-       KEY_EXIT,
-       KEY_POWER2,
-       KEY_TUNER,              /* VCR mode on Zenith */
-       0,
-};
-
-static void msp430_ir_debounce(unsigned long data)
+static void msp430_ir_keyup(unsigned long data)
 {
-       struct input_dev *dev = (struct input_dev *) data;
-
-       if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-               return;
-       }
-
-       dev->rep[0] = 0;
-       dev->timer.expires = jiffies + HZ * 350 / 1000;
-       add_timer(&dev->timer);
-       input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);  /* REPEAT */
+       struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
+       ir_input_nokey(ir->dev, &ir->state);
 }
 
 static void msp430_ir_interrupt(unsigned long data)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) data;
-       struct input_dev *dev = budget_ci->input_dev;
-       unsigned int code =
-               ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+       struct input_dev *dev = budget_ci->ir.dev;
+       static int bounces = 0;
+       int device;
+       int toggle;
+       static int prev_toggle = -1;
+       static u32 ir_key;
+       u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+
+       /*
+        * The msp430 chip can generate two different bytes, command and device
+        *
+        * type1: X1CCCCCC, C = command bits (0 - 63)
+        * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
+        *
+        * More than one command byte may be generated before the device byte
+        * Only when we have both, a correct keypress is generated
+        */
+
+       /* Is this a RC5 command byte? */
+       if (command & 0x40) {
+               if (ir_debug)
+                       printk("budget_ci: received command byte 0x%02x\n", command);
+               ir_key = command & 0x3f;
+               return;
+       }
 
-       if (code & 0x40) {
-               code &= 0x3f;
+       /* It's a RC5 device byte */
+       if (ir_debug)
+               printk("budget_ci: received device byte 0x%02x\n", command);
+       device = command & 0x1f;
+       toggle = command & 0x20;
 
-               if (timer_pending(&dev->timer)) {
-                       if (code == dev->repeat_key) {
-                               ++dev->rep[0];
-                               return;
-                       }
-                       del_timer(&dev->timer);
-                       input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-               }
+       if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
+               return;
 
-               if (!key_map[code]) {
-                       printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
-                       return;
-               }
+       /* Ignore repeated key sequences if requested */
+       if (toggle == prev_toggle && ir_key == dev->repeat_key &&
+           bounces > 0 && timer_pending(&dev->timer)) {
+               if (ir_debug)
+                       printk("budget_ci: debounce logic ignored IR command\n");
+               bounces--;
+               return;
+       }
+       prev_toggle = toggle;
 
-               /* initialize debounce and repeat */
-               dev->repeat_key = code;
-               /* Zenith remote _always_ sends 2 sequences */
-               dev->rep[0] = ~0;
-               /* 350 milliseconds */
-               dev->timer.expires = jiffies + HZ * 350 / 1000;
-               /* MAKE */
-               input_event(dev, EV_KEY, key_map[code], !0);
-               add_timer(&dev->timer);
+       /* Are we still waiting for a keyup event? */
+       if (del_timer(&dev->timer))
+               ir_input_nokey(dev, &budget_ci->ir.state);
+
+       /* Generate keypress */
+       if (ir_debug)
+               printk("budget_ci: generating keypress 0x%02x\n", ir_key);
+       ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
+
+       /* Do we want to delay the keyup event? */
+       if (debounce) {
+               bounces = debounce;
+               mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+       } else {
+               ir_input_nokey(dev, &budget_ci->ir.state);
        }
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
 {
        struct saa7146_dev *saa = budget_ci->budget.dev;
-       struct input_dev *input_dev;
-       int i;
+       struct input_dev *input_dev = budget_ci->ir.dev;
+       int error;
+
+       budget_ci->ir.dev = input_dev = input_allocate_device();
+       if (!input_dev) {
+               printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+               error = -ENOMEM;
+               goto out1;
+       }
+
+       snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
+                "Budget-CI dvb ir receiver %s", saa->name);
+       snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
+                "pci-%s/ir0", pci_name(saa->pci));
 
-       budget_ci->input_dev = input_dev = input_allocate_device();
-       if (!input_dev)
-               return -ENOMEM;
+       input_dev->name = budget_ci->ir.name;
 
-       sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
+       input_dev->phys = budget_ci->ir.phys;
+       input_dev->id.bustype = BUS_PCI;
+       input_dev->id.version = 1;
+       if (saa->pci->subsystem_vendor) {
+               input_dev->id.vendor = saa->pci->subsystem_vendor;
+               input_dev->id.product = saa->pci->subsystem_device;
+       } else {
+               input_dev->id.vendor = saa->pci->vendor;
+               input_dev->id.product = saa->pci->device;
+       }
+       input_dev->cdev.dev = &saa->pci->dev;
 
-       input_dev->name = budget_ci->ir_dev_name;
+       /* Select keymap and address */
+       switch (budget_ci->budget.dev->pci->subsystem_device) {
+       case 0x100c:
+       case 0x100f:
+       case 0x1010:
+       case 0x1011:
+       case 0x1012:
+       case 0x1017:
+               /* The hauppauge keymap is a superset of these remotes */
+               ir_input_init(input_dev, &budget_ci->ir.state,
+                             IR_TYPE_RC5, ir_codes_hauppauge_new);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = 0x1f;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
+               break;
+       default:
+               /* unknown remote */
+               ir_input_init(input_dev, &budget_ci->ir.state,
+                             IR_TYPE_RC5, ir_codes_budget_ci_old);
+
+               if (rc5_device < 0)
+                       budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+               else
+                       budget_ci->ir.rc5_device = rc5_device;
+               break;
+       }
 
-       set_bit(EV_KEY, input_dev->evbit);
-       for (i = 0; i < ARRAY_SIZE(key_map); i++)
-               if (key_map[i])
-                       set_bit(key_map[i], input_dev->keybit);
+       /* initialise the key-up debounce timeout handler */
+       input_dev->timer.function = msp430_ir_keyup;
+       input_dev->timer.data = (unsigned long) &budget_ci->ir;
 
-       input_register_device(budget_ci->input_dev);
+       error = input_register_device(input_dev);
+       if (error) {
+               printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
+               goto out2;
+       }
 
-       input_dev->timer.function = msp430_ir_debounce;
+       tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
+                    (unsigned long) budget_ci);
 
-       saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
+       SAA7146_IER_ENABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
        return 0;
+
+out2:
+       input_free_device(input_dev);
+out1:
+       return error;
 }
 
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
 {
        struct saa7146_dev *saa = budget_ci->budget.dev;
-       struct input_dev *dev = budget_ci->input_dev;
+       struct input_dev *dev = budget_ci->ir.dev;
 
-       saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
+       SAA7146_IER_DISABLE(saa, MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+       tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
-       if (del_timer(&dev->timer))
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+       if (del_timer(&dev->timer)) {
+               ir_input_nokey(dev, &budget_ci->ir.state);
+               input_sync(dev);
+       }
 
        input_unregister_device(dev);
 }
@@ -428,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
        memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
 
        // enable DEBI pins
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
+       saa7146_write(saa, MC1, MASK_27 | MASK_11);
 
        // test if it is there
        ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
@@ -480,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
                } else {
                        saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
                }
-               saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
+               SAA7146_IER_ENABLE(saa, MASK_03);
        }
 
        // enable interface
@@ -502,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
        return 0;
 
 error:
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
        return result;
 }
 
@@ -512,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
 
        // disable CI interrupts
        if (budget_ci->ci_irq) {
-               saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
+               SAA7146_IER_DISABLE(saa, MASK_03);
                saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
                tasklet_kill(&budget_ci->ciintf_irq_tasklet);
        }
@@ -530,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
        dvb_ca_en50221_release(&budget_ci->ca);
 
        // disable DEBI pins
-       saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+       saa7146_write(saa, MC1, MASK_27);
 }
 
 static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
@@ -540,7 +597,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
        dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
 
        if (*isr & MASK_06)
-               tasklet_schedule(&budget_ci->msp430_irq_tasklet);
+               tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
 
        if (*isr & MASK_10)
                ttpci_budget_irq10_handler(dev, isr);
@@ -835,7 +892,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
                band = 1;
        } else if (tuner_frequency < 200000000) {
                cp = 6;
-               band = 1;
+               band = 2;
        } else if (tuner_frequency < 290000000) {
                cp = 3;
                band = 2;
@@ -1083,24 +1140,23 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
        struct budget_ci *budget_ci;
        int err;
 
-       if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL)))
-               return -ENOMEM;
+       budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
+       if (!budget_ci) {
+               err = -ENOMEM;
+               goto out1;
+       }
 
        dprintk(2, "budget_ci: %p\n", budget_ci);
 
-       budget_ci->budget.ci_present = 0;
-
        dev->ext_priv = budget_ci;
 
-       if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
-               kfree(budget_ci);
-               return err;
-       }
-
-       tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
-                    (unsigned long) budget_ci);
+       err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
+       if (err)
+               goto out2;
 
-       msp430_ir_init(budget_ci);
+       err = msp430_ir_init(budget_ci);
+       if (err)
+               goto out3;
 
        ciintf_init(budget_ci);
 
@@ -1110,6 +1166,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
        ttpci_budget_init_hooks(&budget_ci->budget);
 
        return 0;
+
+out3:
+       ttpci_budget_deinit(&budget_ci->budget);
+out2:
+       kfree(budget_ci);
+out1:
+       return err;
 }
 
 static int budget_ci_detach(struct saa7146_dev *dev)
@@ -1120,16 +1183,13 @@ static int budget_ci_detach(struct saa7146_dev *dev)
 
        if (budget_ci->budget.ci_present)
                ciintf_deinit(budget_ci);
+       msp430_ir_deinit(budget_ci);
        if (budget_ci->budget.dvb_frontend) {
                dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
        }
        err = ttpci_budget_deinit(&budget_ci->budget);
 
-       tasklet_kill(&budget_ci->msp430_irq_tasklet);
-
-       msp430_ir_deinit(budget_ci);
-
        // disable frontend and CI interface
        saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
 
@@ -1162,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
        .name = "budget_ci dvb",
-       .flags = SAA7146_I2C_SHORT_DELAY,
+       .flags = SAA7146_USE_I2C_IRQ,
 
        .module = THIS_MODULE,
        .pci_tbl = &pci_tbl[0],
index 56f1c80..9268a82 100644 (file)
@@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
        .name           = "budget dvb",
-       .flags          = SAA7146_I2C_SHORT_DELAY,
+       .flags          = SAA7146_USE_I2C_IRQ,
 
        .module         = THIS_MODULE,
        .pci_tbl        = pci_tbl,
index 8135f3e..bd6e7ba 100644 (file)
@@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                 * for now lets report each signal as a key down and up*/
                dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+               input_sync(dec->rc_input_dev);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
                input_sync(dec->rc_input_dev);
        }
@@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
        struct input_dev *input_dev;
        u8 b[] = { 0x00, 0x01 };
        int i;
+       int err;
 
        usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
        strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
 
-       dec->rc_input_dev = input_dev = input_allocate_device();
+       input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
@@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
        for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
                  set_bit(rc_keys[i], input_dev->keybit);
 
-       input_register_device(input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
 
+       dec->rc_input_dev = input_dev;
        if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
                printk("%s: usb_submit_urb failed\n",__FUNCTION__);
        /* enable irq pipe */
@@ -1244,7 +1251,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
                        return -ENOMEM;
                }
                dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
-                                       SLAB_ATOMIC, &dec->irq_dma_handle);
+                                       GFP_ATOMIC, &dec->irq_dma_handle);
                if(!dec->irq_buffer) {
                        return -ENOMEM;
                }
index 6d96b17..920b63f 100644 (file)
@@ -173,38 +173,6 @@ config RADIO_MAESTRO
          To compile this driver as a module, choose M here: the
          module will be called radio-maestro.
 
-config RADIO_MIROPCM20
-       tristate "miroSOUND PCM20 radio"
-       depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER
-       ---help---
-         Choose Y here if you have this FM radio card. You also need to say Y
-         to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
-         for this to work.
-
-         In order to control your radio card, you will need to use programs
-         that are compatible with the Video For Linux API.  Information on
-         this API and pointers to "v4l" programs may be found at
-         <file:Documentation/video4linux/API.html>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called miropcm20.
-
-config RADIO_MIROPCM20_RDS
-       tristate "miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)"
-       depends on RADIO_MIROPCM20 && EXPERIMENTAL
-       ---help---
-         Choose Y here if you want to see RDS/RBDS information like
-         RadioText, Programme Service name, Clock Time and date, Programme
-         Type and Traffic Announcement/Programme identification.
-
-         It's not possible to read the raw RDS packets from the device, so
-         the driver cant provide an V4L interface for this.  But the
-         availability of RDS is reported over V4L by the basic driver
-         already.  Here RDS can be read from files in /dev/v4l/rds.
-
-         To compile this driver as a module, choose M here: the
-         module will be called miropcm20-rds.
-
 config RADIO_SF16FMI
        tristate "SF16FMI Radio"
        depends on ISA && VIDEO_V4L2
index b8fde5c..29a11c1 100644 (file)
@@ -184,6 +184,14 @@ config VIDEO_KS0127
          To compile this driver as a module, choose M here: the
          module will be called ks0127.
 
+config VIDEO_OV7670
+       tristate "OmniVision OV7670 sensor support"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV7670 VGA camera.  It currently only works with the M88ALP01
+         controller.
+
 config VIDEO_SAA7110
        tristate "Philips SAA7110 video decoder"
        depends on VIDEO_V4L1 && I2C
@@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES
        help
          Support for the AverMedia 6 Eyes video surveillance card.
 
-config VIDEO_ZR36120
-       tristate "Zoran ZR36120/36125 Video For Linux"
-       depends on PCI && I2C && VIDEO_V4L1 && BROKEN
-       help
-         Support for ZR36120/ZR36125 based frame grabber/overlay boards.
-         This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
-         and Buster boards. Please read the material in
-         <file:Documentation/video4linux/zr36120.txt> for more information.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr36120.
-
 config VIDEO_MEYE
        tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
        depends on PCI && SONYPI && VIDEO_V4L1
@@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278
          To compile this driver as a module, choose M here: the
          module will be called arv.
 
+config VIDEO_CAFE_CCIC
+       tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
+       depends on I2C && VIDEO_V4L2
+       select VIDEO_OV7670
+       ---help---
+         This is a video4linux2 driver for the Marvell 88ALP01 integrated
+         CMOS camera controller.  This is the controller found on first-
+         generation OLPC systems.
+
 #
 # USB Multimedia device configuration
 #
@@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig"
 
 source "drivers/media/video/em28xx/Kconfig"
 
+source "drivers/media/video/usbvision/Kconfig"
+
 source "drivers/media/video/usbvideo/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
index af57abc..9b1f3f0 100644 (file)
@@ -2,7 +2,6 @@
 # Makefile for the video capture/playback device drivers.
 #
 
-zoran-objs      :=     zr36120.o zr36120_i2c.o zr36120_mem.o
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
 tuner-objs     :=      tuner-core.o tuner-types.o tuner-simple.o \
@@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
 obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
-obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
 obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
@@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
 obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
@@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
+obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+obj-$(CONFIG_VIDEO_OV7670)     += ov7670.o
+
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
 obj-$(CONFIG_USB_OV511)         += ov511.o
 obj-$(CONFIG_USB_SE401)         += se401.o
index 6e1ddad..3c8e474 100644 (file)
@@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                memset(i,0,sizeof(*i));
                i->index    = n;
                i->type     = V4L2_INPUT_TYPE_CAMERA;
-               i->audioset = 0;
+               i->audioset = 1;
                if (i->index == bttv_tvcards[btv->c.type].tuner) {
                        sprintf(i->name, "Television");
                        i->type  = V4L2_INPUT_TYPE_TUNER;
index 933d6db..cbc012f 100644 (file)
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data)
 
 /* ---------------------------------------------------------------------- */
 
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+{
+       if (ir->polling) {
+               init_timer(&ir->timer);
+               ir->timer.function = bttv_input_timer;
+               ir->timer.data     = (unsigned long)btv;
+               ir->timer.expires  = jiffies + HZ;
+               add_timer(&ir->timer);
+       } else if (ir->rc5_gpio) {
+               /* set timer_end for code completion */
+               init_timer(&ir->timer_end);
+               ir->timer_end.function = bttv_rc5_timer_end;
+               ir->timer_end.data = (unsigned long)ir;
+
+               init_timer(&ir->timer_keyup);
+               ir->timer_keyup.function = bttv_rc5_timer_keyup;
+               ir->timer_keyup.data = (unsigned long)ir;
+       }
+}
+
+static void bttv_ir_stop(struct bttv *btv)
+{
+       if (btv->remote->polling) {
+               del_timer_sync(&btv->remote->timer);
+               flush_scheduled_work();
+       }
+
+       if (btv->remote->rc5_gpio) {
+               u32 gpio;
+
+               del_timer_sync(&btv->remote->timer_end);
+               flush_scheduled_work();
+
+               gpio = bttv_gpio_read(&btv->c);
+               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+       }
+}
+
 int bttv_input_init(struct bttv *btv)
 {
        struct bttv_ir *ir;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        struct input_dev *input_dev;
        int ir_type = IR_TYPE_OTHER;
+       int err = -ENOMEM;
 
        if (!btv->has_remote)
                return -ENODEV;
 
        ir = kzalloc(sizeof(*ir),GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
-       memset(ir,0,sizeof(*ir));
+       if (!ir || !input_dev)
+               goto err_out_free;
 
        /* detect & configure */
        switch (btv->c.type) {
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv)
                break;
        }
        if (NULL == ir_codes) {
-               dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENODEV;
+               dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        if (ir->rc5_gpio) {
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv)
        input_dev->cdev.dev = &btv->c.pci->dev;
 
        btv->remote = ir;
-       if (ir->polling) {
-               init_timer(&ir->timer);
-               ir->timer.function = bttv_input_timer;
-               ir->timer.data     = (unsigned long)btv;
-               ir->timer.expires  = jiffies + HZ;
-               add_timer(&ir->timer);
-       } else if (ir->rc5_gpio) {
-               /* set timer_end for code completion */
-               init_timer(&ir->timer_end);
-               ir->timer_end.function = bttv_rc5_timer_end;
-               ir->timer_end.data = (unsigned long)ir;
-
-               init_timer(&ir->timer_keyup);
-               ir->timer_keyup.function = bttv_rc5_timer_keyup;
-               ir->timer_keyup.data = (unsigned long)ir;
-       }
+       bttv_ir_start(btv, ir);
 
        /* all done */
-       input_register_device(btv->remote->dev);
-       printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
+       err = input_register_device(btv->remote->dev);
+       if (err)
+               goto err_out_stop;
 
        /* the remote isn't as bouncy as a keyboard */
        ir->dev->rep[REP_DELAY] = repeat_delay;
        ir->dev->rep[REP_PERIOD] = repeat_period;
 
        return 0;
+
+ err_out_stop:
+       bttv_ir_stop(btv);
+       btv->remote = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 void bttv_input_fini(struct bttv *btv)
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv)
        if (btv->remote == NULL)
                return;
 
-       if (btv->remote->polling) {
-               del_timer_sync(&btv->remote->timer);
-               flush_scheduled_work();
-       }
-
-
-       if (btv->remote->rc5_gpio) {
-               u32 gpio;
-
-               del_timer_sync(&btv->remote->timer_end);
-               flush_scheduled_work();
-
-               gpio = bttv_gpio_read(&btv->c);
-               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
-       }
-
+       bttv_ir_stop(btv);
        input_unregister_device(btv->remote->dev);
        kfree(btv->remote);
        btv->remote = NULL;
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h
new file mode 100644 (file)
index 0000000..b2c22a0
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Register definitions for the m88alp01 camera interface.  Offsets in bytes
+ * as given in the spec.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.
+ *
+ * Written by Jonathan Corbet, corbet@lwn.net.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#define REG_Y0BAR      0x00
+#define REG_Y1BAR      0x04
+#define REG_Y2BAR      0x08
+/* ... */
+
+#define REG_IMGPITCH   0x24    /* Image pitch register */
+#define   IMGP_YP_SHFT   2             /* Y pitch params */
+#define   IMGP_YP_MASK   0x00003ffc    /* Y pitch field */
+#define          IMGP_UVP_SHFT   18            /* UV pitch (planar) */
+#define   IMGP_UVP_MASK   0x3ffc0000
+#define REG_IRQSTATRAW 0x28    /* RAW IRQ Status */
+#define   IRQ_EOF0       0x00000001    /* End of frame 0 */
+#define   IRQ_EOF1       0x00000002    /* End of frame 1 */
+#define   IRQ_EOF2       0x00000004    /* End of frame 2 */
+#define   IRQ_SOF0       0x00000008    /* Start of frame 0 */
+#define   IRQ_SOF1       0x00000010    /* Start of frame 1 */
+#define   IRQ_SOF2       0x00000020    /* Start of frame 2 */
+#define   IRQ_OVERFLOW   0x00000040    /* FIFO overflow */
+#define   IRQ_TWSIW      0x00010000    /* TWSI (smbus) write */
+#define   IRQ_TWSIR      0x00020000    /* TWSI read */
+#define   IRQ_TWSIE      0x00040000    /* TWSI error */
+#define   TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
+#define   FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
+#define   ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
+#define REG_IRQMASK    0x2c    /* IRQ mask - same bits as IRQSTAT */
+#define REG_IRQSTAT    0x30    /* IRQ status / clear */
+
+#define REG_IMGSIZE    0x34    /* Image size */
+#define  IMGSZ_V_MASK    0x1fff0000
+#define  IMGSZ_V_SHIFT   16
+#define         IMGSZ_H_MASK     0x00003fff
+#define REG_IMGOFFSET  0x38    /* IMage offset */
+
+#define REG_CTRL0      0x3c    /* Control 0 */
+#define   C0_ENABLE      0x00000001    /* Makes the whole thing go */
+
+/* Mask for all the format bits */
+#define   C0_DF_MASK     0x00fffffc    /* Bits 2-23 */
+
+/* RGB ordering */
+#define   C0_RGB4_RGBX   0x00000000
+#define          C0_RGB4_XRGB    0x00000004
+#define          C0_RGB4_BGRX    0x00000008
+#define   C0_RGB4_XBGR   0x0000000c
+#define   C0_RGB5_RGGB   0x00000000
+#define          C0_RGB5_GRBG    0x00000004
+#define          C0_RGB5_GBRG    0x00000008
+#define   C0_RGB5_BGGR   0x0000000c
+
+/* Spec has two fields for DIN and DOUT, but they must match, so
+   combine them here. */
+#define   C0_DF_YUV      0x00000000    /* Data is YUV      */
+#define   C0_DF_RGB      0x000000a0    /* ... RGB                  */
+#define   C0_DF_BAYER     0x00000140   /* ... Bayer                */
+/* 8-8-8 must be missing from the below - ask */
+#define   C0_RGBF_565    0x00000000
+#define   C0_RGBF_444    0x00000800
+#define   C0_RGB_BGR     0x00001000    /* Blue comes first */
+#define   C0_YUV_PLANAR          0x00000000    /* YUV 422 planar format */
+#define   C0_YUV_PACKED          0x00008000    /* YUV 422 packed       */
+#define   C0_YUV_420PL   0x0000a000    /* YUV 420 planar       */
+/* Think that 420 packed must be 111 - ask */
+#define          C0_YUVE_YUYV    0x00000000    /* Y1CbY0Cr             */
+#define          C0_YUVE_YVYU    0x00010000    /* Y1CrY0Cb             */
+#define          C0_YUVE_VYUY    0x00020000    /* CrY1CbY0             */
+#define          C0_YUVE_UYVY    0x00030000    /* CbY1CrY0             */
+#define   C0_YUVE_XYUV   0x00000000    /* 420: .YUV            */
+#define          C0_YUVE_XYVU    0x00010000    /* 420: .YVU            */
+#define          C0_YUVE_XUVY    0x00020000    /* 420: .UVY            */
+#define          C0_YUVE_XVUY    0x00030000    /* 420: .VUY            */
+/* Bayer bits 18,19 if needed */
+#define   C0_HPOL_LOW    0x01000000    /* HSYNC polarity active low */
+#define   C0_VPOL_LOW    0x02000000    /* VSYNC polarity active low */
+#define   C0_VCLK_LOW    0x04000000    /* VCLK on falling edge */
+#define   C0_DOWNSCALE   0x08000000    /* Enable downscaler */
+#define          C0_SIFM_MASK    0xc0000000    /* SIF mode bits */
+#define   C0_SIF_HVSYNC          0x00000000    /* Use H/VSYNC */
+#define   CO_SOF_NOSYNC          0x40000000    /* Use inband active signaling */
+
+
+#define REG_CTRL1      0x40    /* Control 1 */
+#define   C1_444ALPHA    0x00f00000    /* Alpha field in RGB444 */
+#define   C1_ALPHA_SHFT          20
+#define   C1_DMAB32      0x00000000    /* 32-byte DMA burst */
+#define   C1_DMAB16      0x02000000    /* 16-byte DMA burst */
+#define          C1_DMAB64       0x04000000    /* 64-byte DMA burst */
+#define          C1_DMAB_MASK    0x06000000
+#define   C1_TWOBUFS     0x08000000    /* Use only two DMA buffers */
+#define   C1_PWRDWN      0x10000000    /* Power down */
+
+#define REG_CLKCTRL    0x88    /* Clock control */
+#define   CLK_DIV_MASK   0x0000ffff    /* Upper bits RW "reserved" */
+
+#define REG_GPR                0xb4    /* General purpose register.  This
+                                  controls inputs to the power and reset
+                                  pins on the OV7670 used with OLPC;
+                                  other deployments could differ.  */
+#define   GPR_C1EN       0x00000020    /* Pad 1 (power down) enable */
+#define   GPR_C0EN       0x00000010    /* Pad 0 (reset) enable */
+#define          GPR_C1          0x00000002    /* Control 1 value */
+/*
+ * Control 0 is wired to reset on OLPC machines.  For ov7x sensors,
+ * it is active low, for 0v6x, instead, it's active high.  What
+ * fun.
+ */
+#define   GPR_C0         0x00000001    /* Control 0 value */
+
+#define REG_TWSIC0     0xb8    /* TWSI (smbus) control 0 */
+#define   TWSIC0_EN       0x00000001   /* TWSI enable */
+#define   TWSIC0_MODE    0x00000002    /* 1 = 16-bit, 0 = 8-bit */
+#define   TWSIC0_SID     0x000003fc    /* Slave ID */
+#define   TWSIC0_SID_SHIFT 2
+#define   TWSIC0_CLKDIV   0x0007fc00   /* Clock divider */
+#define   TWSIC0_MASKACK  0x00400000   /* Mask ack from sensor */
+#define   TWSIC0_OVMAGIC  0x00800000   /* Make it work on OV sensors */
+
+#define REG_TWSIC1     0xbc    /* TWSI control 1 */
+#define   TWSIC1_DATA    0x0000ffff    /* Data to/from camchip */
+#define   TWSIC1_ADDR    0x00ff0000    /* Address (register) */
+#define   TWSIC1_ADDR_SHIFT 16
+#define   TWSIC1_READ    0x01000000    /* Set for read op */
+#define   TWSIC1_WSTAT   0x02000000    /* Write status */
+#define   TWSIC1_RVALID          0x04000000    /* Read data valid */
+#define   TWSIC1_ERROR   0x08000000    /* Something screwed up */
+
+
+#define REG_UBAR       0xc4    /* Upper base address register */
+
+/*
+ * Here's the weird global control registers which are said to live
+ * way up here.
+ */
+#define REG_GL_CSR     0x3004  /* Control/status register */
+#define   GCSR_SRS      0x00000001     /* SW Reset set */
+#define   GCSR_SRC      0x00000002     /* SW Reset clear */
+#define          GCSR_MRS       0x00000004     /* Master reset set */
+#define          GCSR_MRC       0x00000008     /* HW Reset clear */
+#define   GCSR_CCIC_EN   0x00004000    /* CCIC Clock enable */
+#define REG_GL_IMASK   0x300c  /* Interrupt mask register */
+#define   GIMSK_CCIC_EN          0x00000004    /* CCIC Interrupt enable */
+
+#define REG_LEN                REG_GL_IMASK + 4
+
+
+/*
+ * Useful stuff that probably belongs somewhere global.
+ */
+#define VGA_WIDTH      640
+#define VGA_HEIGHT     480
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
new file mode 100644 (file)
index 0000000..e347c7e
--- /dev/null
@@ -0,0 +1,2228 @@
+/*
+ * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
+ * multifunction chip.  Currently works with the Omnivision OV7670
+ * sensor.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.
+ *
+ * Written by Jonathan Corbet, corbet@lwn.net.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/jiffies.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "cafe_ccic-regs.h"
+
+#define CAFE_VERSION 0x000001
+
+
+/*
+ * Parameters.
+ */
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Video");
+
+/*
+ * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
+ * we must have physically contiguous buffers to bring frames into.
+ * These parameters control how many buffers we use, whether we
+ * allocate them at load time (better chance of success, but nails down
+ * memory) or when somebody tries to use the camera (riskier), and,
+ * for load-time allocation, how big they should be.
+ *
+ * The controller can cycle through three buffers.  We could use
+ * more by flipping pointers around, but it probably makes little
+ * sense.
+ */
+
+#define MAX_DMA_BUFS 3
+static int alloc_bufs_at_load = 0;
+module_param(alloc_bufs_at_load, bool, 0444);
+MODULE_PARM_DESC(alloc_bufs_at_load,
+               "Non-zero value causes DMA buffers to be allocated at module "
+               "load time.  This increases the chances of successfully getting "
+               "those buffers, but at the cost of nailing down the memory from "
+               "the outset.");
+
+static int n_dma_bufs = 3;
+module_param(n_dma_bufs, uint, 0644);
+MODULE_PARM_DESC(n_dma_bufs,
+               "The number of DMA buffers to allocate.  Can be either two "
+               "(saves memory, makes timing tighter) or three.");
+
+static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
+module_param(dma_buf_size, uint, 0444);
+MODULE_PARM_DESC(dma_buf_size,
+               "The size of the allocated DMA buffers.  If actual operating "
+               "parameters require larger buffers, an attempt to reallocate "
+               "will be made.");
+
+static int min_buffers = 1;
+module_param(min_buffers, uint, 0644);
+MODULE_PARM_DESC(min_buffers,
+               "The minimum number of streaming I/O buffers we are willing "
+               "to work with.");
+
+static int max_buffers = 10;
+module_param(max_buffers, uint, 0644);
+MODULE_PARM_DESC(max_buffers,
+               "The maximum number of streaming I/O buffers an application "
+               "will be allowed to allocate.  These buffers are big and live "
+               "in vmalloc space.");
+
+static int flip = 0;
+module_param(flip, bool, 0444);
+MODULE_PARM_DESC(flip,
+               "If set, the sensor will be instructed to flip the image "
+               "vertically.");
+
+
+enum cafe_state {
+       S_NOTREADY,     /* Not yet initialized */
+       S_IDLE,         /* Just hanging around */
+       S_FLAKED,       /* Some sort of problem */
+       S_SINGLEREAD,   /* In read() */
+       S_SPECREAD,     /* Speculative read (for future read()) */
+       S_STREAMING     /* Streaming data */
+};
+
+/*
+ * Tracking of streaming I/O buffers.
+ */
+struct cafe_sio_buffer {
+       struct list_head list;
+       struct v4l2_buffer v4lbuf;
+       char *buffer;   /* Where it lives in kernel space */
+       int mapcount;
+       struct cafe_camera *cam;
+};
+
+/*
+ * A description of one of our devices.
+ * Locking: controlled by s_mutex.  Certain fields, however, require
+ *         the dev_lock spinlock; they are marked as such by comments.
+ *         dev_lock is also required for access to device registers.
+ */
+struct cafe_camera
+{
+       enum cafe_state state;
+       unsigned long flags;            /* Buffer status, mainly (dev_lock) */
+       int users;                      /* How many open FDs */
+       struct file *owner;             /* Who has data access (v4l2) */
+
+       /*
+        * Subsystem structures.
+        */
+       struct pci_dev *pdev;
+       struct video_device v4ldev;
+       struct i2c_adapter i2c_adapter;
+       struct i2c_client *sensor;
+
+       unsigned char __iomem *regs;
+       struct list_head dev_list;      /* link to other devices */
+
+       /* DMA buffers */
+       unsigned int nbufs;             /* How many are alloc'd */
+       int next_buf;                   /* Next to consume (dev_lock) */
+       unsigned int dma_buf_size;      /* allocated size */
+       void *dma_bufs[MAX_DMA_BUFS];   /* Internal buffer addresses */
+       dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
+       unsigned int specframes;        /* Unconsumed spec frames (dev_lock) */
+       unsigned int sequence;          /* Frame sequence number */
+       unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */
+
+       /* Streaming buffers */
+       unsigned int n_sbufs;           /* How many we have */
+       struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */
+       struct list_head sb_avail;      /* Available for data (we own) (dev_lock) */
+       struct list_head sb_full;       /* With data (user space owns) (dev_lock) */
+       struct tasklet_struct s_tasklet;
+
+       /* Current operating parameters */
+       enum v4l2_chip_ident sensor_type;               /* Currently ov7670 only */
+       struct v4l2_pix_format pix_format;
+
+       /* Locks */
+       struct mutex s_mutex; /* Access to this structure */
+       spinlock_t dev_lock;  /* Access to device */
+
+       /* Misc */
+       wait_queue_head_t smbus_wait;   /* Waiting on i2c events */
+       wait_queue_head_t iowait;       /* Waiting on frame data */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       struct dentry *dfs_regs;
+       struct dentry *dfs_cam_regs;
+#endif
+};
+
+/*
+ * Status flags.  Always manipulated with bit operations.
+ */
+#define CF_BUF0_VALID   0      /* Buffers valid - first three */
+#define CF_BUF1_VALID   1
+#define CF_BUF2_VALID   2
+#define CF_DMA_ACTIVE   3      /* A frame is incoming */
+#define CF_CONFIG_NEEDED 4     /* Must configure hardware */
+
+
+
+/*
+ * Start over with DMA buffers - dev_lock needed.
+ */
+static void cafe_reset_buffers(struct cafe_camera *cam)
+{
+       int i;
+
+       cam->next_buf = -1;
+       for (i = 0; i < cam->nbufs; i++)
+               clear_bit(i, &cam->flags);
+       cam->specframes = 0;
+}
+
+static inline int cafe_needs_config(struct cafe_camera *cam)
+{
+       return test_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+static void cafe_set_config_needed(struct cafe_camera *cam, int needed)
+{
+       if (needed)
+               set_bit(CF_CONFIG_NEEDED, &cam->flags);
+       else
+               clear_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+
+
+
+/*
+ * Debugging and related.
+ */
+#define cam_err(cam, fmt, arg...) \
+       dev_err(&(cam)->pdev->dev, fmt, ##arg);
+#define cam_warn(cam, fmt, arg...) \
+       dev_warn(&(cam)->pdev->dev, fmt, ##arg);
+#define cam_dbg(cam, fmt, arg...) \
+       dev_dbg(&(cam)->pdev->dev, fmt, ##arg);
+
+
+/* ---------------------------------------------------------------------*/
+/*
+ * We keep a simple list of known devices to search at open time.
+ */
+static LIST_HEAD(cafe_dev_list);
+static DEFINE_MUTEX(cafe_dev_list_lock);
+
+static void cafe_add_dev(struct cafe_camera *cam)
+{
+       mutex_lock(&cafe_dev_list_lock);
+       list_add_tail(&cam->dev_list, &cafe_dev_list);
+       mutex_unlock(&cafe_dev_list_lock);
+}
+
+static void cafe_remove_dev(struct cafe_camera *cam)
+{
+       mutex_lock(&cafe_dev_list_lock);
+       list_del(&cam->dev_list);
+       mutex_unlock(&cafe_dev_list_lock);
+}
+
+static struct cafe_camera *cafe_find_dev(int minor)
+{
+       struct cafe_camera *cam;
+
+       mutex_lock(&cafe_dev_list_lock);
+       list_for_each_entry(cam, &cafe_dev_list, dev_list) {
+               if (cam->v4ldev.minor == minor)
+                       goto done;
+       }
+       cam = NULL;
+  done:
+       mutex_unlock(&cafe_dev_list_lock);
+       return cam;
+}
+
+
+static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev)
+{
+       struct cafe_camera *cam;
+
+       mutex_lock(&cafe_dev_list_lock);
+       list_for_each_entry(cam, &cafe_dev_list, dev_list) {
+               if (cam->pdev == pdev)
+                       goto done;
+       }
+       cam = NULL;
+  done:
+       mutex_unlock(&cafe_dev_list_lock);
+       return cam;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/*
+ * Device register I/O
+ */
+static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg,
+               unsigned int val)
+{
+       iowrite32(val, cam->regs + reg);
+}
+
+static inline unsigned int cafe_reg_read(struct cafe_camera *cam,
+               unsigned int reg)
+{
+       return ioread32(cam->regs + reg);
+}
+
+
+static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg,
+               unsigned int val, unsigned int mask)
+{
+       unsigned int v = cafe_reg_read(cam, reg);
+
+       v = (v & ~mask) | (val & mask);
+       cafe_reg_write(cam, reg, v);
+}
+
+static inline void cafe_reg_clear_bit(struct cafe_camera *cam,
+               unsigned int reg, unsigned int val)
+{
+       cafe_reg_write_mask(cam, reg, 0, val);
+}
+
+static inline void cafe_reg_set_bit(struct cafe_camera *cam,
+               unsigned int reg, unsigned int val)
+{
+       cafe_reg_write_mask(cam, reg, val, val);
+}
+
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * The I2C/SMBUS interface to the camera itself starts here.  The
+ * controller handles SMBUS itself, presenting a relatively simple register
+ * interface; all we have to do is to tell it where to route the data.
+ */
+#define CAFE_SMBUS_TIMEOUT (HZ)  /* generous */
+
+static int cafe_smbus_write_done(struct cafe_camera *cam)
+{
+       unsigned long flags;
+       int c1;
+
+       /*
+        * We must delay after the interrupt, or the controller gets confused
+        * and never does give us good status.  Fortunately, we don't do this
+        * often.
+        */
+       udelay(20);
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       c1 = cafe_reg_read(cam, REG_TWSIC1);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT;
+}
+
+static int cafe_smbus_write_data(struct cafe_camera *cam,
+               u16 addr, u8 command, u8 value)
+{
+       unsigned int rval;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+       rval |= TWSIC0_OVMAGIC;  /* Make OV sensors work */
+       /*
+        * Marvell sez set clkdiv to all 1's for now.
+        */
+       rval |= TWSIC0_CLKDIV;
+       cafe_reg_write(cam, REG_TWSIC0, rval);
+       (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
+       rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+       cafe_reg_write(cam, REG_TWSIC1, rval);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       msleep(2); /* Required or things flake */
+
+       wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
+                       CAFE_SMBUS_TIMEOUT);
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       rval = cafe_reg_read(cam, REG_TWSIC1);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+       if (rval & TWSIC1_WSTAT) {
+               cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr,
+                               command, value);
+               return -EIO;
+       }
+       if (rval & TWSIC1_ERROR) {
+               cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr,
+                               command, value);
+               return -EIO;
+       }
+       return 0;
+}
+
+
+
+static int cafe_smbus_read_done(struct cafe_camera *cam)
+{
+       unsigned long flags;
+       int c1;
+
+       /*
+        * We must delay after the interrupt, or the controller gets confused
+        * and never does give us good status.  Fortunately, we don't do this
+        * often.
+        */
+       udelay(20);
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       c1 = cafe_reg_read(cam, REG_TWSIC1);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return c1 & (TWSIC1_RVALID|TWSIC1_ERROR);
+}
+
+
+
+static int cafe_smbus_read_data(struct cafe_camera *cam,
+               u16 addr, u8 command, u8 *value)
+{
+       unsigned int rval;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+       rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */
+       /*
+        * Marvel sez set clkdiv to all 1's for now.
+        */
+       rval |= TWSIC0_CLKDIV;
+       cafe_reg_write(cam, REG_TWSIC0, rval);
+       (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
+       rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+       cafe_reg_write(cam, REG_TWSIC1, rval);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+       wait_event_timeout(cam->smbus_wait,
+                       cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT);
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       rval = cafe_reg_read(cam, REG_TWSIC1);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+       if (rval & TWSIC1_ERROR) {
+               cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command);
+               return -EIO;
+       }
+       if (! (rval & TWSIC1_RVALID)) {
+               cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr,
+                               command);
+               return -EIO;
+       }
+       *value = rval & 0xff;
+       return 0;
+}
+
+/*
+ * Perform a transfer over SMBUS.  This thing is called under
+ * the i2c bus lock, so we shouldn't race with ourselves...
+ */
+static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+               unsigned short flags, char rw, u8 command,
+               int size, union i2c_smbus_data *data)
+{
+       struct cafe_camera *cam = i2c_get_adapdata(adapter);
+       int ret = -EINVAL;
+
+       /*
+        * Refuse to talk to anything but OV cam chips.  We should
+        * never even see an attempt to do so, but one never knows.
+        */
+       if (cam->sensor && addr != cam->sensor->addr) {
+               cam_err(cam, "funky smbus addr %d\n", addr);
+               return -EINVAL;
+       }
+       /*
+        * This interface would appear to only do byte data ops.  OK
+        * it can do word too, but the cam chip has no use for that.
+        */
+       if (size != I2C_SMBUS_BYTE_DATA) {
+               cam_err(cam, "funky xfer size %d\n", size);
+               return -EINVAL;
+       }
+
+       if (rw == I2C_SMBUS_WRITE)
+               ret = cafe_smbus_write_data(cam, addr, command, data->byte);
+       else if (rw == I2C_SMBUS_READ)
+               ret = cafe_smbus_read_data(cam, addr, command, &data->byte);
+       return ret;
+}
+
+
+static void cafe_smbus_enable_irq(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+static u32 cafe_smbus_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_READ_BYTE_DATA  |
+              I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+static struct i2c_algorithm cafe_smbus_algo = {
+       .smbus_xfer = cafe_smbus_xfer,
+       .functionality = cafe_smbus_func
+};
+
+/* Somebody is on the bus */
+static int cafe_cam_init(struct cafe_camera *cam);
+static void cafe_ctlr_stop_dma(struct cafe_camera *cam);
+static void cafe_ctlr_power_down(struct cafe_camera *cam);
+
+static int cafe_smbus_attach(struct i2c_client *client)
+{
+       struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
+
+       /*
+        * Don't talk to chips we don't recognize.
+        */
+       if (client->driver->id == I2C_DRIVERID_OV7670) {
+               cam->sensor = client;
+               return cafe_cam_init(cam);
+       }
+       return -EINVAL;
+}
+
+static int cafe_smbus_detach(struct i2c_client *client)
+{
+       struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
+
+       if (cam->sensor == client) {
+               cafe_ctlr_stop_dma(cam);
+               cafe_ctlr_power_down(cam);
+               cam_err(cam, "lost the sensor!\n");
+               cam->sensor = NULL;  /* Bummer, no camera */
+               cam->state = S_NOTREADY;
+       }
+       return 0;
+}
+
+static int cafe_smbus_setup(struct cafe_camera *cam)
+{
+       struct i2c_adapter *adap = &cam->i2c_adapter;
+       int ret;
+
+       cafe_smbus_enable_irq(cam);
+       adap->id = I2C_HW_SMBUS_CAFE;
+       adap->class = I2C_CLASS_CAM_DIGITAL;
+       adap->owner = THIS_MODULE;
+       adap->client_register = cafe_smbus_attach;
+       adap->client_unregister = cafe_smbus_detach;
+       adap->algo = &cafe_smbus_algo;
+       strcpy(adap->name, "cafe_ccic");
+       i2c_set_adapdata(adap, cam);
+       ret = i2c_add_adapter(adap);
+       if (ret)
+               printk(KERN_ERR "Unable to register cafe i2c adapter\n");
+       return ret;
+}
+
+static void cafe_smbus_shutdown(struct cafe_camera *cam)
+{
+       i2c_del_adapter(&cam->i2c_adapter);
+}
+
+
+/* ------------------------------------------------------------------- */
+/*
+ * Deal with the controller.
+ */
+
+/*
+ * Do everything we think we need to have the interface operating
+ * according to the desired format.
+ */
+static void cafe_ctlr_dma(struct cafe_camera *cam)
+{
+       /*
+        * Store the first two Y buffers (we aren't supporting
+        * planar formats for now, so no UV bufs).  Then either
+        * set the third if it exists, or tell the controller
+        * to just use two.
+        */
+       cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);
+       cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);
+       if (cam->nbufs > 2) {
+               cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);
+               cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       }
+       else
+               cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */
+}
+
+static void cafe_ctlr_image(struct cafe_camera *cam)
+{
+       int imgsz;
+       struct v4l2_pix_format *fmt = &cam->pix_format;
+
+       imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
+               (fmt->bytesperline & IMGSZ_H_MASK);
+       cafe_reg_write(cam, REG_IMGSIZE, imgsz);
+       cafe_reg_write(cam, REG_IMGOFFSET, 0);
+       /* YPITCH just drops the last two bits */
+       cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
+                       IMGP_YP_MASK);
+       /*
+        * Tell the controller about the image format we are using.
+        */
+       switch (cam->pix_format.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+           cafe_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
+                           C0_DF_MASK);
+           break;
+
+       case V4L2_PIX_FMT_RGB444:
+           cafe_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
+                           C0_DF_MASK);
+               /* Alpha value? */
+           break;
+
+       case V4L2_PIX_FMT_RGB565:
+           cafe_reg_write_mask(cam, REG_CTRL0,
+                           C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
+                           C0_DF_MASK);
+           break;
+
+       default:
+           cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
+           break;
+       }
+       /*
+        * Make sure it knows we want to use hsync/vsync.
+        */
+       cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
+                       C0_SIFM_MASK);
+}
+
+
+/*
+ * Configure the controller for operation; caller holds the
+ * device mutex.
+ */
+static int cafe_ctlr_configure(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_ctlr_dma(cam);
+       cafe_ctlr_image(cam);
+       cafe_set_config_needed(cam, 0);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return 0;
+}
+
+static void cafe_ctlr_irq_enable(struct cafe_camera *cam)
+{
+       /*
+        * Clear any pending interrupts, since we do not
+        * expect to have I/O active prior to enabling.
+        */
+       cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
+       cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+static void cafe_ctlr_irq_disable(struct cafe_camera *cam)
+{
+       cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+/*
+ * Make the controller start grabbing images.  Everything must
+ * be set up before doing this.
+ */
+static void cafe_ctlr_start(struct cafe_camera *cam)
+{
+       /* set_bit performs a read, so no other barrier should be
+          needed here */
+       cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+static void cafe_ctlr_stop(struct cafe_camera *cam)
+{
+       cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+static void cafe_ctlr_init(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       /*
+        * Added magic to bring up the hardware on the B-Test board
+        */
+       cafe_reg_write(cam, 0x3038, 0x8);
+       cafe_reg_write(cam, 0x315c, 0x80008);
+       /*
+        * Go through the dance needed to wake the device up.
+        * Note that these registers are global and shared
+        * with the NAND and SD devices.  Interaction between the
+        * three still needs to be examined.
+        */
+       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */
+       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);
+       cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);
+       mdelay(5);      /* FIXME revisit this */
+       cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
+       cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN);
+       /*
+        * Make sure it's not powered down.
+        */
+       cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+       /*
+        * Turn off the enable bit.  It sure should be off anyway,
+        * but it's good to be sure.
+        */
+       cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+       /*
+        * Mask all interrupts.
+        */
+       cafe_reg_write(cam, REG_IRQMASK, 0);
+       /*
+        * Clock the sensor appropriately.  Controller clock should
+        * be 48MHz, sensor "typical" value is half that.
+        */
+       cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+/*
+ * Stop the controller, and don't return until we're really sure that no
+ * further DMA is going on.
+ */
+static void cafe_ctlr_stop_dma(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       /*
+        * Theory: stop the camera controller (whether it is operating
+        * or not).  Delay briefly just in case we race with the SOF
+        * interrupt, then wait until no DMA is active.
+        */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_ctlr_stop(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       mdelay(1);
+       wait_event_timeout(cam->iowait,
+                       !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ);
+       if (test_bit(CF_DMA_ACTIVE, &cam->flags))
+               cam_err(cam, "Timeout waiting for DMA to end\n");
+               /* This would be bad news - what now? */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cam->state = S_IDLE;
+       cafe_ctlr_irq_disable(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/*
+ * Power up and down.
+ */
+static void cafe_ctlr_power_up(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+       /*
+        * Put the sensor into operational mode (assumes OLPC-style
+        * wiring).  Control 0 is reset - set to 1 to operate.
+        * Control 1 is power down, set to 0 to operate.
+        */
+       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
+       mdelay(1); /* Marvell says 1ms will do it */
+       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
+       mdelay(1); /* Enough? */
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+static void cafe_ctlr_power_down(struct cafe_camera *cam)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+       cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/* -------------------------------------------------------------------- */
+/*
+ * Communications with the sensor.
+ */
+
+static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg)
+{
+       struct i2c_client *sc = cam->sensor;
+       int ret;
+
+       if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL)
+               return -EINVAL;
+       ret = sc->driver->command(sc, cmd, arg);
+       if (ret == -EPERM) /* Unsupported command */
+               return 0;
+       return ret;
+}
+
+static int __cafe_cam_reset(struct cafe_camera *cam)
+{
+       int zero = 0;
+       return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero);
+}
+
+/*
+ * We have found the sensor on the i2c.  Let's try to have a
+ * conversation.
+ */
+static int cafe_cam_init(struct cafe_camera *cam)
+{
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       if (cam->state != S_NOTREADY)
+               cam_warn(cam, "Cam init with device in funky state %d",
+                               cam->state);
+       ret = __cafe_cam_reset(cam);
+       if (ret)
+               goto out;
+       ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type);
+       if (ret)
+               goto out;
+//     if (cam->sensor->addr != OV7xx0_SID) {
+       if (cam->sensor_type != V4L2_IDENT_OV7670) {
+               cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);
+               ret = -EINVAL;
+               goto out;
+       }
+/* Get/set parameters? */
+       ret = 0;
+       cam->state = S_IDLE;
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+/*
+ * Configure the sensor to match the parameters we have.  Caller should
+ * hold s_mutex
+ */
+static int cafe_cam_set_flip(struct cafe_camera *cam)
+{
+       struct v4l2_control ctrl;
+
+       memset(&ctrl, 0, sizeof(ctrl));
+       ctrl.id = V4L2_CID_VFLIP;
+       ctrl.value = flip;
+       return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl);
+}
+
+
+static int cafe_cam_configure(struct cafe_camera *cam)
+{
+       struct v4l2_format fmt;
+       int ret, zero = 0;
+
+       if (cam->state != S_IDLE)
+               return -EINVAL;
+       fmt.fmt.pix = cam->pix_format;
+       ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero);
+       if (ret == 0)
+               ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt);
+       /*
+        * OV7670 does weird things if flip is set *before* format...
+        */
+       ret += cafe_cam_set_flip(cam);
+       return ret;
+}
+
+/* -------------------------------------------------------------------- */
+/*
+ * DMA buffer management.  These functions need s_mutex held.
+ */
+
+/* FIXME: this is inefficient as hell, since dma_alloc_coherent just
+ * does a get_free_pages() call, and we waste a good chunk of an orderN
+ * allocation.  Should try to allocate the whole set in one chunk.
+ */
+static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime)
+{
+       int i;
+
+       cafe_set_config_needed(cam, 1);
+       if (loadtime)
+               cam->dma_buf_size = dma_buf_size;
+       else
+               cam->dma_buf_size = cam->pix_format.sizeimage;
+       if (n_dma_bufs > 3)
+               n_dma_bufs = 3;
+
+       cam->nbufs = 0;
+       for (i = 0; i < n_dma_bufs; i++) {
+               cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev,
+                               cam->dma_buf_size, cam->dma_handles + i,
+                               GFP_KERNEL);
+               if (cam->dma_bufs[i] == NULL) {
+                       cam_warn(cam, "Failed to allocate DMA buffer\n");
+                       break;
+               }
+               /* For debug, remove eventually */
+               memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size);
+               (cam->nbufs)++;
+       }
+
+       switch (cam->nbufs) {
+       case 1:
+           dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
+                           cam->dma_bufs[0], cam->dma_handles[0]);
+           cam->nbufs = 0;
+       case 0:
+           cam_err(cam, "Insufficient DMA buffers, cannot operate\n");
+           return -ENOMEM;
+
+       case 2:
+           if (n_dma_bufs > 2)
+                   cam_warn(cam, "Will limp along with only 2 buffers\n");
+           break;
+       }
+       return 0;
+}
+
+static void cafe_free_dma_bufs(struct cafe_camera *cam)
+{
+       int i;
+
+       for (i = 0; i < cam->nbufs; i++) {
+               dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
+                               cam->dma_bufs[i], cam->dma_handles[i]);
+               cam->dma_bufs[i] = NULL;
+       }
+       cam->nbufs = 0;
+}
+
+
+
+
+
+/* ----------------------------------------------------------------------- */
+/*
+ * Here starts the V4L2 interface code.
+ */
+
+/*
+ * Read an image from the device.
+ */
+static ssize_t cafe_deliver_buffer(struct cafe_camera *cam,
+               char __user *buffer, size_t len, loff_t *pos)
+{
+       int bufno;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       if (cam->next_buf < 0) {
+               cam_err(cam, "deliver_buffer: No next buffer\n");
+               spin_unlock_irqrestore(&cam->dev_lock, flags);
+               return -EIO;
+       }
+       bufno = cam->next_buf;
+       clear_bit(bufno, &cam->flags);
+       if (++(cam->next_buf) >= cam->nbufs)
+               cam->next_buf = 0;
+       if (! test_bit(cam->next_buf, &cam->flags))
+               cam->next_buf = -1;
+       cam->specframes = 0;
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+       if (len > cam->pix_format.sizeimage)
+               len = cam->pix_format.sizeimage;
+       if (copy_to_user(buffer, cam->dma_bufs[bufno], len))
+               return -EFAULT;
+       (*pos) += len;
+       return len;
+}
+
+/*
+ * Get everything ready, and start grabbing frames.
+ */
+static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state)
+{
+       int ret;
+       unsigned long flags;
+
+       /*
+        * Configuration.  If we still don't have DMA buffers,
+        * make one last, desperate attempt.
+        */
+       if (cam->nbufs == 0)
+               if (cafe_alloc_dma_bufs(cam, 0))
+                       return -ENOMEM;
+
+       if (cafe_needs_config(cam)) {
+               cafe_cam_configure(cam);
+               ret = cafe_ctlr_configure(cam);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Turn it loose.
+        */
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       cafe_reset_buffers(cam);
+       cafe_ctlr_irq_enable(cam);
+       cam->state = state;
+       cafe_ctlr_start(cam);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       return 0;
+}
+
+
+static ssize_t cafe_v4l_read(struct file *filp,
+               char __user *buffer, size_t len, loff_t *pos)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret;
+
+       /*
+        * Perhaps we're in speculative read mode and already
+        * have data?
+        */
+       mutex_lock(&cam->s_mutex);
+       if (cam->state == S_SPECREAD) {
+               if (cam->next_buf >= 0) {
+                       ret = cafe_deliver_buffer(cam, buffer, len, pos);
+                       if (ret != 0)
+                               goto out_unlock;
+               }
+       } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) {
+               ret = -EIO;
+               goto out_unlock;
+       } else if (cam->state != S_IDLE) {
+               ret = -EBUSY;
+               goto out_unlock;
+       }
+
+       /*
+        * v4l2: multiple processes can open the device, but only
+        * one gets to grab data from it.
+        */
+       if (cam->owner && cam->owner != filp) {
+               ret = -EBUSY;
+               goto out_unlock;
+       }
+       cam->owner = filp;
+
+       /*
+        * Do setup if need be.
+        */
+       if (cam->state != S_SPECREAD) {
+               ret = cafe_read_setup(cam, S_SINGLEREAD);
+               if (ret)
+                       goto out_unlock;
+       }
+       /*
+        * Wait for something to happen.  This should probably
+        * be interruptible (FIXME).
+        */
+       wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ);
+       if (cam->next_buf < 0) {
+               cam_err(cam, "read() operation timed out\n");
+               cafe_ctlr_stop_dma(cam);
+               ret = -EIO;
+               goto out_unlock;
+       }
+       /*
+        * Give them their data and we should be done.
+        */
+       ret = cafe_deliver_buffer(cam, buffer, len, pos);
+
+  out_unlock:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+
+
+
+
+
+/*
+ * Streaming I/O support.
+ */
+
+
+
+static int cafe_vidioc_streamon(struct file *filp, void *priv,
+               enum v4l2_buf_type type)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret = -EINVAL;
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               goto out;
+       mutex_lock(&cam->s_mutex);
+       if (cam->state != S_IDLE || cam->n_sbufs == 0)
+               goto out_unlock;
+
+       cam->sequence = 0;
+       ret = cafe_read_setup(cam, S_STREAMING);
+
+  out_unlock:
+       mutex_unlock(&cam->s_mutex);
+  out:
+       return ret;
+}
+
+
+static int cafe_vidioc_streamoff(struct file *filp, void *priv,
+               enum v4l2_buf_type type)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret = -EINVAL;
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               goto out;
+       mutex_lock(&cam->s_mutex);
+       if (cam->state != S_STREAMING)
+               goto out_unlock;
+
+       cafe_ctlr_stop_dma(cam);
+       ret = 0;
+
+  out_unlock:
+       mutex_unlock(&cam->s_mutex);
+  out:
+       return ret;
+}
+
+
+
+static int cafe_setup_siobuf(struct cafe_camera *cam, int index)
+{
+       struct cafe_sio_buffer *buf = cam->sb_bufs + index;
+
+       INIT_LIST_HEAD(&buf->list);
+       buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage);
+       buf->buffer = vmalloc_user(buf->v4lbuf.length);
+       if (buf->buffer == NULL)
+               return -ENOMEM;
+       buf->mapcount = 0;
+       buf->cam = cam;
+
+       buf->v4lbuf.index = index;
+       buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->v4lbuf.field = V4L2_FIELD_NONE;
+       buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
+       /*
+        * Offset: must be 32-bit even on a 64-bit system.  video-buf
+        * just uses the length times the index, but the spec warns
+        * against doing just that - vma merging problems.  So we
+        * leave a gap between each pair of buffers.
+        */
+       buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
+       return 0;
+}
+
+static int cafe_free_sio_buffers(struct cafe_camera *cam)
+{
+       int i;
+
+       /*
+        * If any buffers are mapped, we cannot free them at all.
+        */
+       for (i = 0; i < cam->n_sbufs; i++)
+               if (cam->sb_bufs[i].mapcount > 0)
+                       return -EBUSY;
+       /*
+        * OK, let's do it.
+        */
+       for (i = 0; i < cam->n_sbufs; i++)
+               vfree(cam->sb_bufs[i].buffer);
+       cam->n_sbufs = 0;
+       kfree(cam->sb_bufs);
+       cam->sb_bufs = NULL;
+       INIT_LIST_HEAD(&cam->sb_avail);
+       INIT_LIST_HEAD(&cam->sb_full);
+       return 0;
+}
+
+
+
+static int cafe_vidioc_reqbufs(struct file *filp, void *priv,
+               struct v4l2_requestbuffers *req)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret;
+
+       /*
+        * Make sure it's something we can do.  User pointers could be
+        * implemented without great pain, but that's not been done yet.
+        */
+       if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (req->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+       /*
+        * If they ask for zero buffers, they really want us to stop streaming
+        * (if it's happening) and free everything.  Should we check owner?
+        */
+       mutex_lock(&cam->s_mutex);
+       if (req->count == 0) {
+               if (cam->state == S_STREAMING)
+                       cafe_ctlr_stop_dma(cam);
+               ret = cafe_free_sio_buffers (cam);
+               goto out;
+       }
+       /*
+        * Device needs to be idle and working.  We *could* try to do the
+        * right thing in S_SPECREAD by shutting things down, but it
+        * probably doesn't matter.
+        */
+       if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       cam->owner = filp;
+
+       if (req->count < min_buffers)
+               req->count = min_buffers;
+       else if (req->count > max_buffers)
+               req->count = max_buffers;
+       if (cam->n_sbufs > 0) {
+               ret = cafe_free_sio_buffers(cam);
+               if (ret)
+                       goto out;
+       }
+
+       cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer),
+                       GFP_KERNEL);
+       if (cam->sb_bufs == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) {
+               ret = cafe_setup_siobuf(cam, cam->n_sbufs);
+               if (ret)
+                       break;
+       }
+
+       if (cam->n_sbufs == 0)  /* no luck at all - ret already set */
+               kfree(cam->sb_bufs);
+       else
+               ret = 0;
+       req->count = cam->n_sbufs;  /* In case of partial success */
+
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int cafe_vidioc_querybuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret = -EINVAL;
+
+       mutex_lock(&cam->s_mutex);
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               goto out;
+       if (buf->index < 0 || buf->index >= cam->n_sbufs)
+               goto out;
+       *buf = cam->sb_bufs[buf->index].v4lbuf;
+       ret = 0;
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int cafe_vidioc_qbuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct cafe_camera *cam = filp->private_data;
+       struct cafe_sio_buffer *sbuf;
+       int ret = -EINVAL;
+       unsigned long flags;
+
+       mutex_lock(&cam->s_mutex);
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               goto out;
+       if (buf->index < 0 || buf->index >= cam->n_sbufs)
+               goto out;
+       sbuf = cam->sb_bufs + buf->index;
+       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) {
+               ret = 0; /* Already queued?? */
+               goto out;
+       }
+       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) {
+               /* Spec doesn't say anything, seems appropriate tho */
+               ret = -EBUSY;
+               goto out;
+       }
+       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       list_add(&sbuf->list, &cam->sb_avail);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+       ret = 0;
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int cafe_vidioc_dqbuf(struct file *filp, void *priv,
+               struct v4l2_buffer *buf)
+{
+       struct cafe_camera *cam = filp->private_data;
+       struct cafe_sio_buffer *sbuf;
+       int ret = -EINVAL;
+       unsigned long flags;
+
+       mutex_lock(&cam->s_mutex);
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               goto out_unlock;
+       if (cam->state != S_STREAMING)
+               goto out_unlock;
+       if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) {
+               ret = -EAGAIN;
+               goto out_unlock;
+       }
+
+       while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) {
+               mutex_unlock(&cam->s_mutex);
+               if (wait_event_interruptible(cam->iowait,
+                                               !list_empty(&cam->sb_full))) {
+                       ret = -ERESTARTSYS;
+                       goto out;
+               }
+               mutex_lock(&cam->s_mutex);
+       }
+
+       if (cam->state != S_STREAMING)
+               ret = -EINTR;
+       else {
+               spin_lock_irqsave(&cam->dev_lock, flags);
+               /* Should probably recheck !list_empty() here */
+               sbuf = list_entry(cam->sb_full.next,
+                               struct cafe_sio_buffer, list);
+               list_del_init(&sbuf->list);
+               spin_unlock_irqrestore(&cam->dev_lock, flags);
+               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;
+               *buf = sbuf->v4lbuf;
+               ret = 0;
+       }
+
+  out_unlock:
+       mutex_unlock(&cam->s_mutex);
+  out:
+       return ret;
+}
+
+
+
+static void cafe_v4l_vm_open(struct vm_area_struct *vma)
+{
+       struct cafe_sio_buffer *sbuf = vma->vm_private_data;
+       /*
+        * Locking: done under mmap_sem, so we don't need to
+        * go back to the camera lock here.
+        */
+       sbuf->mapcount++;
+}
+
+
+static void cafe_v4l_vm_close(struct vm_area_struct *vma)
+{
+       struct cafe_sio_buffer *sbuf = vma->vm_private_data;
+
+       mutex_lock(&sbuf->cam->s_mutex);
+       sbuf->mapcount--;
+       /* Docs say we should stop I/O too... */
+       if (sbuf->mapcount == 0)
+               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;
+       mutex_unlock(&sbuf->cam->s_mutex);
+}
+
+static struct vm_operations_struct cafe_v4l_vm_ops = {
+       .open = cafe_v4l_vm_open,
+       .close = cafe_v4l_vm_close
+};
+
+
+static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct cafe_camera *cam = filp->private_data;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret = -EINVAL;
+       int i;
+       struct cafe_sio_buffer *sbuf = NULL;
+
+       if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+       /*
+        * Find the buffer they are looking for.
+        */
+       mutex_lock(&cam->s_mutex);
+       for (i = 0; i < cam->n_sbufs; i++)
+               if (cam->sb_bufs[i].v4lbuf.m.offset == offset) {
+                       sbuf = cam->sb_bufs + i;
+                       break;
+               }
+       if (sbuf == NULL)
+               goto out;
+
+       ret = remap_vmalloc_range(vma, sbuf->buffer, 0);
+       if (ret)
+               goto out;
+       vma->vm_flags |= VM_DONTEXPAND;
+       vma->vm_private_data = sbuf;
+       vma->vm_ops = &cafe_v4l_vm_ops;
+       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;
+       cafe_v4l_vm_open(vma);
+       ret = 0;
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+static int cafe_v4l_open(struct inode *inode, struct file *filp)
+{
+       struct cafe_camera *cam;
+
+       cam = cafe_find_dev(iminor(inode));
+       if (cam == NULL)
+               return -ENODEV;
+       filp->private_data = cam;
+
+       mutex_lock(&cam->s_mutex);
+       if (cam->users == 0) {
+               cafe_ctlr_power_up(cam);
+               __cafe_cam_reset(cam);
+               cafe_set_config_needed(cam, 1);
+       /* FIXME make sure this is complete */
+       }
+       (cam->users)++;
+       mutex_unlock(&cam->s_mutex);
+       return 0;
+}
+
+
+static int cafe_v4l_release(struct inode *inode, struct file *filp)
+{
+       struct cafe_camera *cam = filp->private_data;
+
+       mutex_lock(&cam->s_mutex);
+       (cam->users)--;
+       if (filp == cam->owner) {
+               cafe_ctlr_stop_dma(cam);
+               cafe_free_sio_buffers(cam);
+               cam->owner = NULL;
+       }
+       if (cam->users == 0) {
+               cafe_ctlr_power_down(cam);
+               if (! alloc_bufs_at_load)
+                       cafe_free_dma_bufs(cam);
+       }
+       mutex_unlock(&cam->s_mutex);
+       return 0;
+}
+
+
+
+static unsigned int cafe_v4l_poll(struct file *filp,
+               struct poll_table_struct *pt)
+{
+       struct cafe_camera *cam = filp->private_data;
+
+       poll_wait(filp, &cam->iowait, pt);
+       if (cam->next_buf >= 0)
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+
+
+static int cafe_vidioc_queryctrl(struct file *filp, void *priv,
+               struct v4l2_queryctrl *qc)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int cafe_vidioc_g_ctrl(struct file *filp, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int cafe_vidioc_s_ctrl(struct file *filp, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct cafe_camera *cam = filp->private_data;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+
+
+
+static int cafe_vidioc_querycap(struct file *file, void *priv,
+               struct v4l2_capability *cap)
+{
+       strcpy(cap->driver, "cafe_ccic");
+       strcpy(cap->card, "cafe_ccic");
+       cap->version = CAFE_VERSION;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+
+/*
+ * The default format we use until somebody says otherwise.
+ */
+static struct v4l2_pix_format cafe_def_pix_format = {
+       .width          = VGA_WIDTH,
+       .height         = VGA_HEIGHT,
+       .pixelformat    = V4L2_PIX_FMT_YUYV,
+       .field          = V4L2_FIELD_NONE,
+       .bytesperline   = VGA_WIDTH*2,
+       .sizeimage      = VGA_WIDTH*VGA_HEIGHT*2,
+};
+
+static int cafe_vidioc_enum_fmt_cap(struct file *filp,
+               void *priv, struct v4l2_fmtdesc *fmt)
+{
+       struct cafe_camera *cam = priv;
+       int ret;
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+
+static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv,
+               struct v4l2_format *fmt)
+{
+       struct cafe_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
+               struct v4l2_format *fmt)
+{
+       struct cafe_camera *cam = priv;
+       int ret;
+
+       /*
+        * Can't do anything if the device is not idle
+        * Also can't if there are streaming buffers in place.
+        */
+       if (cam->state != S_IDLE || cam->n_sbufs > 0)
+               return -EBUSY;
+       /*
+        * See if the formatting works in principle.
+        */
+       ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt);
+       if (ret)
+               return ret;
+       /*
+        * Now we start to change things for real, so let's do it
+        * under lock.
+        */
+       mutex_lock(&cam->s_mutex);
+       cam->pix_format = fmt->fmt.pix;
+       /*
+        * Make sure we have appropriate DMA buffers.
+        */
+       ret = -ENOMEM;
+       if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
+               cafe_free_dma_bufs(cam);
+       if (cam->nbufs == 0) {
+               if (cafe_alloc_dma_bufs(cam, 0))
+                       goto out;
+       }
+       /*
+        * It looks like this might work, so let's program the sensor.
+        */
+       ret = cafe_cam_configure(cam);
+       if (! ret)
+               ret = cafe_ctlr_configure(cam);
+  out:
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+}
+
+/*
+ * Return our stored notion of how the camera is/should be configured.
+ * The V4l2 spec wants us to be smarter, and actually get this from
+ * the camera (and not mess with it at open time).  Someday.
+ */
+static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv,
+               struct v4l2_format *f)
+{
+       struct cafe_camera *cam = priv;
+
+       f->fmt.pix = cam->pix_format;
+       return 0;
+}
+
+/*
+ * We only have one input - the sensor - so minimize the nonsense here.
+ */
+static int cafe_vidioc_enum_input(struct file *filp, void *priv,
+               struct v4l2_input *input)
+{
+       if (input->index != 0)
+               return -EINVAL;
+
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       input->std = V4L2_STD_ALL; /* Not sure what should go here */
+       strcpy(input->name, "Camera");
+       return 0;
+}
+
+static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* from vivi.c */
+static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+{
+       return 0;
+}
+
+/*
+ * G/S_PARM.  Most of this is done by the sensor, but we are
+ * the level which controls the number of read buffers.
+ */
+static int cafe_vidioc_g_parm(struct file *filp, void *priv,
+               struct v4l2_streamparm *parms)
+{
+       struct cafe_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
+       mutex_unlock(&cam->s_mutex);
+       parms->parm.capture.readbuffers = n_dma_bufs;
+       return ret;
+}
+
+static int cafe_vidioc_s_parm(struct file *filp, void *priv,
+               struct v4l2_streamparm *parms)
+{
+       struct cafe_camera *cam = priv;
+       int ret;
+
+       mutex_lock(&cam->s_mutex);
+       ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
+       mutex_unlock(&cam->s_mutex);
+       parms->parm.capture.readbuffers = n_dma_bufs;
+       return ret;
+}
+
+
+static void cafe_v4l_dev_release(struct video_device *vd)
+{
+       struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
+
+       kfree(cam);
+}
+
+
+/*
+ * This template device holds all of those v4l2 methods; we
+ * clone it for specific real devices.
+ */
+
+static struct file_operations cafe_v4l_fops = {
+       .owner = THIS_MODULE,
+       .open = cafe_v4l_open,
+       .release = cafe_v4l_release,
+       .read = cafe_v4l_read,
+       .poll = cafe_v4l_poll,
+       .mmap = cafe_v4l_mmap,
+       .ioctl = video_ioctl2,
+       .llseek = no_llseek,
+};
+
+static struct video_device cafe_v4l_template = {
+       .name = "cafe",
+       .type = VFL_TYPE_GRABBER,
+       .type2 = VID_TYPE_CAPTURE,
+       .minor = -1, /* Get one dynamically */
+       .tvnorms = V4L2_STD_NTSC_M,
+       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
+
+       .fops = &cafe_v4l_fops,
+       .release = cafe_v4l_dev_release,
+
+       .vidioc_querycap        = cafe_vidioc_querycap,
+       .vidioc_enum_fmt_cap    = cafe_vidioc_enum_fmt_cap,
+       .vidioc_try_fmt_cap     = cafe_vidioc_try_fmt_cap,
+       .vidioc_s_fmt_cap       = cafe_vidioc_s_fmt_cap,
+       .vidioc_g_fmt_cap       = cafe_vidioc_g_fmt_cap,
+       .vidioc_enum_input      = cafe_vidioc_enum_input,
+       .vidioc_g_input         = cafe_vidioc_g_input,
+       .vidioc_s_input         = cafe_vidioc_s_input,
+       .vidioc_s_std           = cafe_vidioc_s_std,
+       .vidioc_reqbufs         = cafe_vidioc_reqbufs,
+       .vidioc_querybuf        = cafe_vidioc_querybuf,
+       .vidioc_qbuf            = cafe_vidioc_qbuf,
+       .vidioc_dqbuf           = cafe_vidioc_dqbuf,
+       .vidioc_streamon        = cafe_vidioc_streamon,
+       .vidioc_streamoff       = cafe_vidioc_streamoff,
+       .vidioc_queryctrl       = cafe_vidioc_queryctrl,
+       .vidioc_g_ctrl          = cafe_vidioc_g_ctrl,
+       .vidioc_s_ctrl          = cafe_vidioc_s_ctrl,
+       .vidioc_g_parm          = cafe_vidioc_g_parm,
+       .vidioc_s_parm          = cafe_vidioc_s_parm,
+};
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Interrupt handler stuff
+ */
+
+
+
+static void cafe_frame_tasklet(unsigned long data)
+{
+       struct cafe_camera *cam = (struct cafe_camera *) data;
+       int i;
+       unsigned long flags;
+       struct cafe_sio_buffer *sbuf;
+
+       spin_lock_irqsave(&cam->dev_lock, flags);
+       for (i = 0; i < cam->nbufs; i++) {
+               int bufno = cam->next_buf;
+               if (bufno < 0) {  /* "will never happen" */
+                       cam_err(cam, "No valid bufs in tasklet!\n");
+                       break;
+               }
+               if (++(cam->next_buf) >= cam->nbufs)
+                       cam->next_buf = 0;
+               if (! test_bit(bufno, &cam->flags))
+                       continue;
+               if (list_empty(&cam->sb_avail))
+                       break;  /* Leave it valid, hope for better later */
+               clear_bit(bufno, &cam->flags);
+               /*
+                * We could perhaps drop the spinlock during this
+                * big copy.  Something to consider.
+                */
+               sbuf = list_entry(cam->sb_avail.next,
+                               struct cafe_sio_buffer, list);
+               memcpy(sbuf->buffer, cam->dma_bufs[bufno],
+                               cam->pix_format.sizeimage);
+               sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage;
+               sbuf->v4lbuf.sequence = cam->buf_seq[bufno];
+               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
+               sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
+               list_move_tail(&sbuf->list, &cam->sb_full);
+       }
+       if (! list_empty(&cam->sb_full))
+               wake_up(&cam->iowait);
+       spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+
+static void cafe_frame_complete(struct cafe_camera *cam, int frame)
+{
+       /*
+        * Basic frame housekeeping.
+        */
+       if (test_bit(frame, &cam->flags) && printk_ratelimit())
+               cam_err(cam, "Frame overrun on %d, frames lost\n", frame);
+       set_bit(frame, &cam->flags);
+       clear_bit(CF_DMA_ACTIVE, &cam->flags);
+       if (cam->next_buf < 0)
+               cam->next_buf = frame;
+       cam->buf_seq[frame] = ++(cam->sequence);
+
+       switch (cam->state) {
+       /*
+        * If in single read mode, try going speculative.
+        */
+           case S_SINGLEREAD:
+               cam->state = S_SPECREAD;
+               cam->specframes = 0;
+               wake_up(&cam->iowait);
+               break;
+
+       /*
+        * If we are already doing speculative reads, and nobody is
+        * reading them, just stop.
+        */
+           case S_SPECREAD:
+               if (++(cam->specframes) >= cam->nbufs) {
+                       cafe_ctlr_stop(cam);
+                       cafe_ctlr_irq_disable(cam);
+                       cam->state = S_IDLE;
+               }
+               wake_up(&cam->iowait);
+               break;
+       /*
+        * For the streaming case, we defer the real work to the
+        * camera tasklet.
+        *
+        * FIXME: if the application is not consuming the buffers,
+        * we should eventually put things on hold and restart in
+        * vidioc_dqbuf().
+        */
+           case S_STREAMING:
+               tasklet_schedule(&cam->s_tasklet);
+               break;
+
+           default:
+               cam_err(cam, "Frame interrupt in non-operational state\n");
+               break;
+       }
+}
+
+
+
+
+static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs)
+{
+       unsigned int frame;
+
+       cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */
+       /*
+        * Handle any frame completions.  There really should
+        * not be more than one of these, or we have fallen
+        * far behind.
+        */
+       for (frame = 0; frame < cam->nbufs; frame++)
+               if (irqs & (IRQ_EOF0 << frame))
+                       cafe_frame_complete(cam, frame);
+       /*
+        * If a frame starts, note that we have DMA active.  This
+        * code assumes that we won't get multiple frame interrupts
+        * at once; may want to rethink that.
+        */
+       if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2))
+               set_bit(CF_DMA_ACTIVE, &cam->flags);
+}
+
+
+
+static irqreturn_t cafe_irq(int irq, void *data)
+{
+       struct cafe_camera *cam = data;
+       unsigned int irqs;
+
+       spin_lock(&cam->dev_lock);
+       irqs = cafe_reg_read(cam, REG_IRQSTAT);
+       if ((irqs & ALLIRQS) == 0) {
+               spin_unlock(&cam->dev_lock);
+               return IRQ_NONE;
+       }
+       if (irqs & FRAMEIRQS)
+               cafe_frame_irq(cam, irqs);
+       if (irqs & TWSIIRQS) {
+               cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS);
+               wake_up(&cam->smbus_wait);
+       }
+       spin_unlock(&cam->dev_lock);
+       return IRQ_HANDLED;
+}
+
+
+/* -------------------------------------------------------------------------- */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * Debugfs stuff.
+ */
+
+static char cafe_debug_buf[1024];
+static struct dentry *cafe_dfs_root;
+
+static void cafe_dfs_setup(void)
+{
+       cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL);
+       if (IS_ERR(cafe_dfs_root)) {
+               cafe_dfs_root = NULL;  /* Never mind */
+               printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n");
+       }
+}
+
+static void cafe_dfs_shutdown(void)
+{
+       if (cafe_dfs_root)
+               debugfs_remove(cafe_dfs_root);
+}
+
+static int cafe_dfs_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t cafe_dfs_read_regs(struct file *file,
+               char __user *buf, size_t count, loff_t *ppos)
+{
+       struct cafe_camera *cam = file->private_data;
+       char *s = cafe_debug_buf;
+       int offset;
+
+       for (offset = 0; offset < 0x44; offset += 4)
+               s += sprintf(s, "%02x: %08x\n", offset,
+                               cafe_reg_read(cam, offset));
+       for (offset = 0x88; offset <= 0x90; offset += 4)
+               s += sprintf(s, "%02x: %08x\n", offset,
+                               cafe_reg_read(cam, offset));
+       for (offset = 0xb4; offset <= 0xbc; offset += 4)
+               s += sprintf(s, "%02x: %08x\n", offset,
+                               cafe_reg_read(cam, offset));
+       for (offset = 0x3000; offset <= 0x300c; offset += 4)
+               s += sprintf(s, "%04x: %08x\n", offset,
+                               cafe_reg_read(cam, offset));
+       return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
+                       s - cafe_debug_buf);
+}
+
+static struct file_operations cafe_dfs_reg_ops = {
+       .owner = THIS_MODULE,
+       .read = cafe_dfs_read_regs,
+       .open = cafe_dfs_open
+};
+
+static ssize_t cafe_dfs_read_cam(struct file *file,
+               char __user *buf, size_t count, loff_t *ppos)
+{
+       struct cafe_camera *cam = file->private_data;
+       char *s = cafe_debug_buf;
+       int offset;
+
+       if (! cam->sensor)
+               return -EINVAL;
+       for (offset = 0x0; offset < 0x8a; offset++)
+       {
+               u8 v;
+
+               cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v);
+               s += sprintf(s, "%02x: %02x\n", offset, v);
+       }
+       return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
+                       s - cafe_debug_buf);
+}
+
+static struct file_operations cafe_dfs_cam_ops = {
+       .owner = THIS_MODULE,
+       .read = cafe_dfs_read_cam,
+       .open = cafe_dfs_open
+};
+
+
+
+static void cafe_dfs_cam_setup(struct cafe_camera *cam)
+{
+       char fname[40];
+
+       if (!cafe_dfs_root)
+               return;
+       sprintf(fname, "regs-%d", cam->v4ldev.minor);
+       cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
+                       cam, &cafe_dfs_reg_ops);
+       sprintf(fname, "cam-%d", cam->v4ldev.minor);
+       cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
+                       cam, &cafe_dfs_cam_ops);
+}
+
+
+static void cafe_dfs_cam_shutdown(struct cafe_camera *cam)
+{
+       if (! IS_ERR(cam->dfs_regs))
+               debugfs_remove(cam->dfs_regs);
+       if (! IS_ERR(cam->dfs_cam_regs))
+               debugfs_remove(cam->dfs_cam_regs);
+}
+
+#else
+
+#define cafe_dfs_setup()
+#define cafe_dfs_shutdown()
+#define cafe_dfs_cam_setup(cam)
+#define cafe_dfs_cam_shutdown(cam)
+#endif    /* CONFIG_VIDEO_ADV_DEBUG */
+
+
+
+
+/* ------------------------------------------------------------------------*/
+/*
+ * PCI interface stuff.
+ */
+
+static int cafe_pci_probe(struct pci_dev *pdev,
+               const struct pci_device_id *id)
+{
+       int ret;
+       u16 classword;
+       struct cafe_camera *cam;
+       /*
+        * Make sure we have a camera here - we'll get calls for
+        * the other cafe devices as well.
+        */
+       pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword);
+       if (classword != PCI_CLASS_MULTIMEDIA_VIDEO)
+               return -ENODEV;
+       /*
+        * Start putting together one of our big camera structures.
+        */
+       ret = -ENOMEM;
+       cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
+       if (cam == NULL)
+               goto out;
+       mutex_init(&cam->s_mutex);
+       mutex_lock(&cam->s_mutex);
+       spin_lock_init(&cam->dev_lock);
+       cam->state = S_NOTREADY;
+       cafe_set_config_needed(cam, 1);
+       init_waitqueue_head(&cam->smbus_wait);
+       init_waitqueue_head(&cam->iowait);
+       cam->pdev = pdev;
+       cam->pix_format = cafe_def_pix_format;
+       INIT_LIST_HEAD(&cam->dev_list);
+       INIT_LIST_HEAD(&cam->sb_avail);
+       INIT_LIST_HEAD(&cam->sb_full);
+       tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam);
+       /*
+        * Get set up on the PCI bus.
+        */
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto out_free;
+       pci_set_master(pdev);
+
+       ret = -EIO;
+       cam->regs = pci_iomap(pdev, 0, 0);
+       if (! cam->regs) {
+               printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n");
+               goto out_free;
+       }
+       ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
+       if (ret)
+               goto out_iounmap;
+       cafe_ctlr_init(cam);
+       cafe_ctlr_power_up(cam);
+       /*
+        * Set up I2C/SMBUS communications
+        */
+       mutex_unlock(&cam->s_mutex);  /* attach can deadlock */
+       ret = cafe_smbus_setup(cam);
+       if (ret)
+               goto out_freeirq;
+       /*
+        * Get the v4l2 setup done.
+        */
+       mutex_lock(&cam->s_mutex);
+       cam->v4ldev = cafe_v4l_template;
+       cam->v4ldev.debug = 0;
+//     cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
+       ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
+       if (ret)
+               goto out_smbus;
+       /*
+        * If so requested, try to get our DMA buffers now.
+        */
+       if (alloc_bufs_at_load) {
+               if (cafe_alloc_dma_bufs(cam, 1))
+                       cam_warn(cam, "Unable to alloc DMA buffers at load"
+                                       " will try again later.");
+       }
+
+       cafe_dfs_cam_setup(cam);
+       mutex_unlock(&cam->s_mutex);
+       cafe_add_dev(cam);
+       return 0;
+
+  out_smbus:
+       cafe_smbus_shutdown(cam);
+  out_freeirq:
+       cafe_ctlr_power_down(cam);
+       free_irq(pdev->irq, cam);
+  out_iounmap:
+       pci_iounmap(pdev, cam->regs);
+  out_free:
+       kfree(cam);
+  out:
+       return ret;
+}
+
+
+/*
+ * Shut down an initialized device
+ */
+static void cafe_shutdown(struct cafe_camera *cam)
+{
+/* FIXME: Make sure we take care of everything here */
+       cafe_dfs_cam_shutdown(cam);
+       if (cam->n_sbufs > 0)
+               /* What if they are still mapped?  Shouldn't be, but... */
+               cafe_free_sio_buffers(cam);
+       cafe_remove_dev(cam);
+       cafe_ctlr_stop_dma(cam);
+       cafe_ctlr_power_down(cam);
+       cafe_smbus_shutdown(cam);
+       cafe_free_dma_bufs(cam);
+       free_irq(cam->pdev->irq, cam);
+       pci_iounmap(cam->pdev, cam->regs);
+       video_unregister_device(&cam->v4ldev);
+       /* kfree(cam); done in v4l_release () */
+}
+
+
+static void cafe_pci_remove(struct pci_dev *pdev)
+{
+       struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+
+       if (cam == NULL) {
+               cam_warn(cam, "pci_remove on unknown pdev %p\n", pdev);
+               return;
+       }
+       mutex_lock(&cam->s_mutex);
+       if (cam->users > 0)
+               cam_warn(cam, "Removing a device with users!\n");
+       cafe_shutdown(cam);
+/* No unlock - it no longer exists */
+}
+
+
+
+
+static struct pci_device_id cafe_ids[] = {
+       { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */
+       { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
+       { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cafe_ids);
+
+static struct pci_driver cafe_pci_driver = {
+       .name = "cafe1000-ccic",
+       .id_table = cafe_ids,
+       .probe = cafe_pci_probe,
+       .remove = cafe_pci_remove,
+};
+
+
+
+
+static int __init cafe_init(void)
+{
+       int ret;
+
+       printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n",
+                       CAFE_VERSION);
+       cafe_dfs_setup();
+       ret = pci_register_driver(&cafe_pci_driver);
+       if (ret) {
+               printk(KERN_ERR "Unable to register cafe_ccic driver\n");
+               goto out;
+       }
+       request_module("ov7670");  /* FIXME want something more general */
+       ret = 0;
+
+  out:
+       return ret;
+}
+
+
+static void __exit cafe_exit(void)
+{
+       pci_unregister_driver(&cafe_pci_driver);
+       cafe_dfs_shutdown();
+}
+
+module_init(cafe_init);
+module_exit(cafe_exit);
index d82a488..f065ad1 100644 (file)
@@ -118,7 +118,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
        else if (file->f_op->ioctl) {
                lock_kernel();
-               ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+               ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
                unlock_kernel();
        }
 
index 41f4b8d..b12cec9 100644 (file)
@@ -82,6 +82,8 @@ struct pp_cam_entry {
        struct pardevice *pdev;
        struct parport *port;
        struct work_struct cb_task;
+       void (*cb_func)(void *cbdata);
+       void *cb_data;
        int open_count;
        wait_queue_head_t wq_stream;
        /* image state flags */
@@ -130,6 +132,20 @@ static void cpia_parport_disable_irq( struct parport *port ) {
 #define PARPORT_CHUNK_SIZE     PAGE_SIZE
 
 
+static void cpia_pp_run_callback(struct work_struct *work)
+{
+       void (*cb_func)(void *cbdata);
+       void *cb_data;
+       struct pp_cam_entry *cam;
+
+       cam = container_of(work, struct pp_cam_entry, cb_task);
+       cb_func = cam->cb_func;
+       cb_data = cam->cb_data;
+       work_release(work);
+
+       cb_func(cb_data);
+}
+
 /****************************************************************************
  *
  *  CPiA-specific  low-level parport functions for nibble uploads
@@ -664,7 +680,9 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo
        int retval = 0;
 
        if(cam->port->irq != PARPORT_IRQ_NONE) {
-               INIT_WORK(&cam->cb_task, cb, cbdata);
+               cam->cb_func = cb;
+               cam->cb_data = cbdata;
+               INIT_WORK_NAR(&cam->cb_task, cpia_pp_run_callback);
        } else {
                retval = -1;
        }
index 0f9d969..b2a66ba 100644 (file)
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB
        select DVB_OR51132 if !DVB_FE_CUSTOMISE
        select DVB_CX22702 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
        select DVB_NXT200X if !DVB_FE_CUSTOMISE
        select DVB_CX24123 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
index 4673832..0cf0360 100644 (file)
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 #define dprintk(level,fmt, arg...)     if (debug >= level) \
        printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
 
-static LIST_HEAD(cx8802_devlist);
 
 /* ------------------------------------------------------------------ */
 
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
                                  BLACKBIRD_MPEG_CAPTURE,
                                  BLACKBIRD_RAW_BITS_NONE);
 
-               cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+               cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
 
                blackbird_initialize_codec(dev);
                cx88_set_scale(dev->core, dev->width, dev->height,
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
        }
 
        default:
-               return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+               return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
        }
        return 0;
 }
 
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
 static unsigned int mpeg_translate_ioctl(unsigned int cmd)
 {
        return cmd;
@@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd)
 static int mpeg_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
-       cmd = mpeg_translate_ioctl( cmd );
-       return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+       cmd = cx88_ioctl_translator( cmd );
+       return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
 }
 
 static int mpeg_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
-       struct cx8802_dev *h,*dev = NULL;
+       struct cx8802_dev *dev = NULL;
        struct cx8802_fh *fh;
-       struct list_head *list;
+       struct cx8802_driver *drv = NULL;
+       int err;
 
-       list_for_each(list,&cx8802_devlist) {
-               h = list_entry(list, struct cx8802_dev, devlist);
-               if (h->mpeg_dev->minor == minor)
-                       dev = h;
-       }
-       if (NULL == dev)
+       dev = cx8802_get_device(inode);
+
+       dprintk( 1, "%s\n", __FUNCTION__);
+
+       if (dev == NULL)
                return -ENODEV;
 
-       if (blackbird_initialize_codec(dev) < 0)
+       /* Make sure we can acquire the hardware */
+       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+       if (drv) {
+               err = drv->request_acquire(drv);
+               if(err != 0) {
+                       dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+                       return err;
+               }
+       }
+
+       if (blackbird_initialize_codec(dev) < 0) {
+               if (drv)
+                       drv->request_release(drv);
                return -EINVAL;
+       }
        dprintk(1,"open minor=%d\n",minor);
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               if (drv)
+                       drv->request_release(drv);
                return -ENOMEM;
+       }
        file->private_data = fh;
        fh->dev      = dev;
 
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
 static int mpeg_release(struct inode *inode, struct file *file)
 {
        struct cx8802_fh  *fh  = file->private_data;
+       struct cx8802_dev *dev = NULL;
+       struct cx8802_driver *drv = NULL;
 
        /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
        blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
        videobuf_mmap_free(&fh->mpegq);
        file->private_data = NULL;
        kfree(fh);
+
+       /* Make sure we release the hardware */
+       dev = cx8802_get_device(inode);
+       if (dev == NULL)
+               return -ENODEV;
+
+       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+       if (drv)
+               drv->request_release(drv);
+
        return 0;
 }
 
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template =
 
 /* ------------------------------------------------------------------ */
 
+/* The CX8802 MPEG API will call this when we can use the hardware */
+static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+
+       switch (core->board) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* By default, core setup will leave the cx22702 out of reset, on the bus.
+                * We left the hardware on power up with the cx22702 active.
+                * We're being given access to re-arrange the GPIOs.
+                * Take the bus off the cx22702 and put the cx23416 on it.
+                */
+               cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
+               cx_set(MO_GP0_IO,   0x00000004); /* Disable the cx22702 */
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+/* The CX8802 MPEG API will call this when we need to release the hardware */
+static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+
+       switch (core->board) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* Exit leaving the cx23416 on the bus */
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
 static void blackbird_unregister_video(struct cx8802_dev *dev)
 {
        if (dev->mpeg_dev) {
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
 
 /* ----------------------------------------------------------- */
 
-static int __devinit blackbird_probe(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
+static int cx8802_blackbird_probe(struct cx8802_driver *drv)
 {
-       struct cx8802_dev *dev;
-       struct cx88_core  *core;
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = core->dvbdev;
        int err;
 
-       /* general setup */
-       core = cx88_core_get(pci_dev);
-       if (NULL == core)
-               return -EINVAL;
+       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+               core->board,
+               core->name,
+               core->pci_bus,
+               core->pci_slot);
 
        err = -ENODEV;
        if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
                goto fail_core;
 
-       err = -ENOMEM;
-       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-       if (NULL == dev)
-               goto fail_core;
-       dev->pci = pci_dev;
-       dev->core = core;
        dev->width = 720;
        dev->height = 576;
        cx2341x_fill_defaults(&dev->params);
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
                dev->height = 576;
        }
 
-       err = cx8802_init_common(dev);
-       if (0 != err)
-               goto fail_free;
-
        /* blackbird stuff */
        printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
               core->name);
        host_setup(dev->core);
 
-       list_add_tail(&dev->devlist,&cx8802_devlist);
        blackbird_register_video(dev);
 
        /* initial device configuration: needed ? */
 
        return 0;
 
- fail_free:
-       kfree(dev);
  fail_core:
-       cx88_core_put(core,pci_dev);
        return err;
 }
 
-static void __devexit blackbird_remove(struct pci_dev *pci_dev)
+static int cx8802_blackbird_remove(struct cx8802_driver *drv)
 {
-       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-
        /* blackbird */
-       blackbird_unregister_video(dev);
-       list_del(&dev->devlist);
+       blackbird_unregister_video(drv->core->dvbdev);
 
-       /* common */
-       cx8802_fini_common(dev);
-       cx88_core_put(dev->core,dev->pci);
-       kfree(dev);
+       return 0;
 }
 
-static struct pci_device_id cx8802_pci_tbl[] = {
-       {
-               .vendor       = 0x14f1,
-               .device       = 0x8802,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       },{
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver blackbird_pci_driver = {
-       .name     = "cx88-blackbird",
-       .id_table = cx8802_pci_tbl,
-       .probe    = blackbird_probe,
-       .remove   = __devexit_p(blackbird_remove),
-#ifdef CONFIG_PM
-       .suspend  = cx8802_suspend_common,
-       .resume   = cx8802_resume_common,
-#endif
+static struct cx8802_driver cx8802_blackbird_driver = {
+       .type_id        = CX88_MPEG_BLACKBIRD,
+       .hw_access      = CX8802_DRVCTL_SHARED,
+       .probe          = cx8802_blackbird_probe,
+       .remove         = cx8802_blackbird_remove,
+       .advise_acquire = cx8802_blackbird_advise_acquire,
+       .advise_release = cx8802_blackbird_advise_release,
 };
 
 static int blackbird_init(void)
@@ -1176,17 +1212,22 @@ static int blackbird_init(void)
        printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
               SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
-       return pci_register_driver(&blackbird_pci_driver);
+       cx88_ioctl_hook = mpeg_do_ioctl;
+       cx88_ioctl_translator = mpeg_translate_ioctl;
+       return cx8802_register_driver(&cx8802_blackbird_driver);
 }
 
 static void blackbird_fini(void)
 {
-       pci_unregister_driver(&blackbird_pci_driver);
+       cx8802_unregister_driver(&cx8802_blackbird_driver);
 }
 
 module_init(blackbird_init);
 module_exit(blackbird_fini);
 
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
index f764a57..c791708 100644 (file)
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
                        .gpio0  = 0x0000bde2,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0x0000bde6,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x0000bde6,
+                       .extadc = 1,
                }},
                .radio = {
                        .type   = CX88_RADIO,
                        .gpio0  = 0x0000bd62,
+                       .extadc = 1,
                },
                .mpeg           = CX88_MPEG_BLACKBIRD,
        },
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+                       .extadc = 1,
                }},
                .radio = {
                        .type   = CX88_RADIO,
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
+                       .extadc = 1,
                }},
                .mpeg           = CX88_MPEG_BLACKBIRD,
        },
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
                        .gpio0  = 0x00009d80,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0x00009d76,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x00009d76,
+                       .extadc = 1,
                }},
                .radio = {
                        .type   = CX88_RADIO,
                        .gpio0  = 0x00009d00,
+                       .extadc = 1,
                },
                .mpeg           = CX88_MPEG_BLACKBIRD,
        },
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .mpeg           = CX88_MPEG_BLACKBIRD,
                .input          = {{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 0,
                        .gpio0  = 0x0000cd73,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 1,
                        .gpio0  = 0x0000cd73,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 3,
                        .gpio0  = 0x0000cdb3,
+                       .extadc = 1,
                }},
                .radio = {
                        .type   = CX88_RADIO,
                        .vmux   = 2,
                        .gpio0  = 0x0000cdf3,
+                       .extadc = 1,
                },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
        },
        [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
                 /* Alexander Wold <awold@bigfoot.com> */
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = {
                .mpeg           = CX88_MPEG_DVB,
        },
        [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
-               /* FIXME: Audio not working for s-video / composite inputs. */
                .name           = "KWorld HardwareMpegTV XPert",
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .radio_type     = UNSET,
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0x3de6,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x3de6,
+                       .extadc = 1,
                }},
                .radio = {
                        .type   = CX88_RADIO,
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = {
                        .gpio0  = 0x070b,
                }},
        },
-       [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
-              .name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
-              .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-              .radio_type     = UNSET,
-              .tuner_addr     = ADDR_UNSET,
-              .radio_addr     = ADDR_UNSET,
-              .input          = {{
-                      .type   = CX88_VMUX_TELEVISION,
-                      .vmux   = 0,
-                      .gpio0  = 0x003fffff,
-                      .gpio1  = 0x00e00000,
-                      .gpio2  = 0x003fffff,
-                      .gpio3  = 0x02000000,
-              },{
-                      .type   = CX88_VMUX_COMPOSITE1,
-                      .vmux   = 1,
-                      .gpio0  = 0x003fffff,
-                      .gpio1  = 0x00e00000,
-                      .gpio2  = 0x003fffff,
-                      .gpio3  = 0x02000000,
-               },{
-                      .type   = CX88_VMUX_SVIDEO,
-                      .vmux   = 2,
-                      .gpio0  = 0x003fffff,
-                      .gpio1  = 0x00e00000,
-                      .gpio2  = 0x003fffff,
-                      .gpio3  = 0x02000000,
-              }},
-       },
+       [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
+               .name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               }},
+       },
        [CX88_BOARD_HAUPPAUGE_HVR1300] = {
                .name           = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
                .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
                        .gpio0  = 0xe780,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0xe780,
+                       .extadc = 1,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0xe780,
+                       .extadc = 1,
                }},
                /* fixme: Add radio support */
-               .mpeg           = CX88_MPEG_DVB,
+               .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
        },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = {
        },{
                .subvendor = 0x17de,
                .subdevice = 0x0840,
+              .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+       },{
+              .subvendor = 0x1421,
+              .subdevice = 0x0305,
                .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
        },{
                .subvendor = 0x18ac,
index 0ef13e7..8b20335 100644 (file)
@@ -42,7 +42,7 @@
 #include "cx22702.h"
 #include "or51132.h"
 #include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
 #include "nxt200x.h"
 #include "cx24123.h"
 #include "isl6421.h"
@@ -57,7 +57,7 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
 
 #define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg)
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
 
 /* ------------------------------------------------------------------ */
 
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q,
        return 0;
 }
 
-static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-                          enum v4l2_field field)
+static int dvb_buf_prepare(struct videobuf_queue *q,
+                          struct videobuf_buffer *vb, enum v4l2_field field)
 {
        struct cx8802_dev *dev = q->priv_data;
        return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
        cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
 }
 
-static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void dvb_buf_release(struct videobuf_queue *q,
+                           struct videobuf_buffer *vb)
 {
        cx88_free_buffer(q, (struct cx88_buffer*)vb);
 }
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = {
 };
 
 /* ------------------------------------------------------------------ */
+
+static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx8802_driver *drv = NULL;
+       int ret = 0;
+
+       drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+       if (drv) {
+               if (acquire)
+                       ret = drv->request_acquire(drv);
+               else
+                       ret = drv->request_release(drv);
+       }
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------ */
+
 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
 };
 #endif
 
-static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
-                                        struct dvb_frontend_parameters *params)
-{
-       u8 pllbuf[4];
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct i2c_msg msg =
-               { .addr = dev->core->pll_addr, .flags = 0,
-                 .buf = pllbuf, .len = 4 };
-       int err;
-
-       dvb_pll_configure(dev->core->pll_desc, pllbuf,
-                         params->frequency,
-                         params->u.ofdm.bandwidth);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "cx88-dvb: %s error "
-                      "(addr %02x <- %02x, err = %i)\n",
-                      __FUNCTION__, pllbuf[0], pllbuf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       return 0;
-}
-
 static struct zl10353_config dvico_fusionhdtv_hybrid = {
        .demod_address = 0x0f,
        .no_tuner      = 1,
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = {
        .output_mode   = CX22702_SERIAL_OUTPUT,
 };
 
-static struct cx22702_config hauppauge_novat_config = {
-       .demod_address = 0x43,
-       .output_mode   = CX22702_SERIAL_OUTPUT,
-};
-
-static struct cx22702_config hauppauge_hvr1100_config = {
+static struct cx22702_config hauppauge_hvr_config = {
        .demod_address = 0x63,
        .output_mode   = CX22702_SERIAL_OUTPUT,
 };
 
-static struct cx22702_config hauppauge_hvr1300_config = {
-       .demod_address = 0x63,
-       .output_mode   = CX22702_SERIAL_OUTPUT,
-};
-
-static struct cx22702_config hauppauge_hvr3000_config = {
-       .demod_address = 0x63,
-       .output_mode = CX22702_SERIAL_OUTPUT,
-};
-
-static int or51132_set_ts_param(struct dvb_frontend* fe,
-                               int is_punctured)
+static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = {
        .set_ts_params = or51132_set_ts_param,
 };
 
-static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
-                                    struct dvb_frontend_parameters* params)
-{
-       /* FIXME make this routine use the tuner-simple code.
-        * It could probably be shared with a number of ATSC
-        * frontends. Many share the same tuner with analog TV. */
-
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-       u8 buf[4];
-       struct i2c_msg msg =
-               { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
-       int err;
-
-       dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
-       dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-               __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "cx88-dvb: %s error "
-                      "(addr %02x <- %02x, err = %i)\n",
-                      __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-       return 0;
-}
-
-static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
-                                    struct dvb_frontend_parameters* params)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       /* Put the analog decoder in standby to keep it quiet */
-       cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
-
-       return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
-}
-
 static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = {
        .set_ts_params = lgdt330x_set_ts_param,
 };
 
-static int nxt200x_set_ts_param(struct dvb_frontend* fe,
-                               int is_punctured)
+static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
-       if (voltage == SEC_VOLTAGE_OFF) {
+       if (voltage == SEC_VOLTAGE_OFF)
                cx_write(MO_GP0_IO, 0x000006fb);
-       } else {
+       else
                cx_write(MO_GP0_IO, 0x000006f9);
-       }
 
        if (core->prev_set_voltage)
                return core->prev_set_voltage(fe, voltage);
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev)
        switch (dev->core->board) {
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
                dev->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_novat_config,
+                                              &connexant_refboard_config,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
                dev->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_hvr1100_config,
-                                              &dev->core->i2c_adap);
-               if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  &dvb_pll_fmd1216me);
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               dev->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_hvr1300_config,
-                                              &dev->core->i2c_adap);
-               if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  &dvb_pll_fmd1216me);
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-               dev->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_hvr3000_config,
+                                              &hauppauge_hvr_config,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  &dvb_pll_fmd1216me);
+                                  &dev->core->i2c_adap, &dvb_pll_fmd1216me);
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev)
 #endif
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_thomson_fe6600;
                dev->dvb.frontend = dvb_attach(zl10353_attach,
                                               &dvico_fusionhdtv_hybrid,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_thomson_fe6600);
                }
                break;
        case CX88_BOARD_PCHDTV_HD3000:
-               dev->dvb.frontend = dvb_attach(or51132_attach,
-                                              &pchdtv_hd3000,
+               dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev)
 
                /* Select RF connector callback */
                fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_microtune_4042;
                dev->dvb.frontend = dvb_attach(lgdt330x_attach,
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_microtune_4042);
                }
                }
                break;
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev)
                mdelay(100);
                cx_set(MO_GP0_IO, 9);
                mdelay(200);
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
                dev->dvb.frontend = dvb_attach(lgdt330x_attach,
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_thomson_dtt761x);
                }
                }
                break;
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_5_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+                       dvb_attach(lgh06xf_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap);
                }
                }
                break;
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &pchdtv_hd5500,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+                       dvb_attach(lgh06xf_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap);
                }
                }
                break;
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev)
                        dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
                }
                break;
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap, &dvb_pll_fmd1216me);
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap, &dvb_pll_fmd1216me);
+               }
+               break;
        default:
                printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
                dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
        }
+       /* Ensure all frontends negotiate bus access */
+       dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
 
        /* Put the analog decoder in standby to keep it quiet */
        cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev)
 
 /* ----------------------------------------------------------- */
 
-static int __devinit dvb_probe(struct pci_dev *pci_dev,
-                              const struct pci_device_id *pci_id)
+/* CX8802 MPEG -> mini driver - We have been given the hardware */
+static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
 {
-       struct cx8802_dev *dev;
-       struct cx88_core  *core;
+       struct cx88_core *core = drv->core;
+       int err = 0;
+       dprintk( 1, "%s\n", __FUNCTION__);
+
+       switch (core->board) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* We arrive here with either the cx23416 or the cx22702
+                * on the bus. Take the bus from the cx23416 and enable the
+                * cx22702 demod
+                */
+               cx_set(MO_GP0_IO,   0x00000080); /* cx22702 out of reset and enable */
+               cx_clear(MO_GP0_IO, 0x00000004);
+               udelay(1000);
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+/* CX8802 MPEG -> mini driver - We no longer have the hardware */
+static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+       dprintk( 1, "%s\n", __FUNCTION__);
+
+       switch (core->board) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* Do Nothing, leave the cx22702 on the bus. */
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+static int cx8802_dvb_probe(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = drv->core->dvbdev;
        int err;
 
-       /* general setup */
-       core = cx88_core_get(pci_dev);
-       if (NULL == core)
-               return -EINVAL;
+       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+               core->board,
+               core->name,
+               core->pci_bus,
+               core->pci_slot);
 
        err = -ENODEV;
        if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
                goto fail_core;
 
-       err = -ENOMEM;
-       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-       if (NULL == dev)
-               goto fail_core;
-       dev->pci = pci_dev;
-       dev->core = core;
-
-       err = cx8802_init_common(dev);
-       if (0 != err)
-               goto fail_free;
-
 #ifdef HAVE_VP3054_I2C
        err = vp3054_i2c_probe(dev);
        if (0 != err)
-               goto fail_free;
+               goto fail_core;
 #endif
 
        /* dvb stuff */
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
                            sizeof(struct cx88_buffer),
                            dev);
        err = dvb_register(dev);
-       if (0 != err)
-               goto fail_fini;
+       if (err != 0)
+               printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);
 
-       /* Maintain a reference to cx88-video can query the 8802 device. */
-       core->dvbdev = dev;
-       return 0;
-
- fail_fini:
-       cx8802_fini_common(dev);
- fail_free:
-       kfree(dev);
  fail_core:
-       cx88_core_put(core,pci_dev);
        return err;
 }
 
-static void __devexit dvb_remove(struct pci_dev *pci_dev)
+static int cx8802_dvb_remove(struct cx8802_driver *drv)
 {
-       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-
-       /* Destroy any 8802 reference. */
-       dev->core->dvbdev = NULL;
+       struct cx8802_dev *dev = drv->core->dvbdev;
 
        /* dvb */
        videobuf_dvb_unregister(&dev->dvb);
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
        vp3054_i2c_remove(dev);
 #endif
 
-       /* common */
-       cx8802_fini_common(dev);
-       cx88_core_put(dev->core,dev->pci);
-       kfree(dev);
+       return 0;
 }
 
-static struct pci_device_id cx8802_pci_tbl[] = {
-       {
-               .vendor       = 0x14f1,
-               .device       = 0x8802,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       },{
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver dvb_pci_driver = {
-       .name     = "cx88-dvb",
-       .id_table = cx8802_pci_tbl,
-       .probe    = dvb_probe,
-       .remove   = __devexit_p(dvb_remove),
-#ifdef CONFIG_PM
-       .suspend  = cx8802_suspend_common,
-       .resume   = cx8802_resume_common,
-#endif
+static struct cx8802_driver cx8802_dvb_driver = {
+       .type_id        = CX88_MPEG_DVB,
+       .hw_access      = CX8802_DRVCTL_SHARED,
+       .probe          = cx8802_dvb_probe,
+       .remove         = cx8802_dvb_remove,
+       .advise_acquire = cx8802_dvb_advise_acquire,
+       .advise_release = cx8802_dvb_advise_release,
 };
 
 static int dvb_init(void)
@@ -917,12 +848,12 @@ static int dvb_init(void)
        printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
               SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
-       return pci_register_driver(&dvb_pci_driver);
+       return cx8802_register_driver(&cx8802_dvb_driver);
 }
 
 static void dvb_fini(void)
 {
-       pci_unregister_driver(&dvb_pci_driver);
+       cx8802_unregister_driver(&cx8802_dvb_driver);
 }
 
 module_init(dvb_init);
index 57e1c02..8136673 100644 (file)
@@ -145,9 +145,9 @@ static void ir_timer(unsigned long data)
        schedule_work(&ir->work);
 }
 
-static void cx88_ir_work(void *data)
+static void cx88_ir_work(struct work_struct *work)
 {
-       struct cx88_IR *ir = data;
+       struct cx88_IR *ir = container_of(work, struct cx88_IR, work);
        unsigned long timeout;
 
        cx88_ir_handle_key(ir);
@@ -155,6 +155,35 @@ static void cx88_ir_work(void *data)
        mod_timer(&ir->timer, timeout);
 }
 
+static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
+{
+       if (ir->polling) {
+               INIT_WORK(&ir->work, cx88_ir_work);
+               init_timer(&ir->timer);
+               ir->timer.function = ir_timer;
+               ir->timer.data = (unsigned long)ir;
+               schedule_work(&ir->work);
+       }
+       if (ir->sampling) {
+               core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
+               cx_write(MO_DDS_IO, 0xa80a80);  /* 4 kHz sample rate */
+               cx_write(MO_DDSCFG_IO, 0x5);    /* enable */
+       }
+}
+
+static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
+{
+       if (ir->sampling) {
+               cx_write(MO_DDSCFG_IO, 0x0);
+               core->pci_irqmask &= ~(1 << 18);
+       }
+
+       if (ir->polling) {
+               del_timer_sync(&ir->timer);
+               flush_scheduled_work();
+       }
+}
+
 /* ---------------------------------------------------------------------- */
 
 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        struct input_dev *input_dev;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        int ir_type = IR_TYPE_OTHER;
+       int err = -ENOMEM;
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
+       if (!ir || !input_dev)
+               goto err_out_free;
 
        ir->input = input_dev;
 
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        }
 
        if (NULL == ir_codes) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        /* init input device */
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        ir->core = core;
        core->ir = ir;
 
-       if (ir->polling) {
-               INIT_WORK(&ir->work, cx88_ir_work, ir);
-               init_timer(&ir->timer);
-               ir->timer.function = ir_timer;
-               ir->timer.data = (unsigned long)ir;
-               schedule_work(&ir->work);
-       }
-       if (ir->sampling) {
-               core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
-               cx_write(MO_DDS_IO, 0xa80a80);  /* 4 kHz sample rate */
-               cx_write(MO_DDSCFG_IO, 0x5);    /* enable */
-       }
+       cx88_ir_start(core, ir);
 
        /* all done */
-       input_register_device(ir->input);
+       err = input_register_device(ir->input);
+       if (err)
+               goto err_out_stop;
 
        return 0;
+
+ err_out_stop:
+       cx88_ir_stop(core, ir);
+       core->ir = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 int cx88_ir_fini(struct cx88_core *core)
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
        if (NULL == ir)
                return 0;
 
-       if (ir->sampling) {
-               cx_write(MO_DDSCFG_IO, 0x0);
-               core->pci_irqmask &= ~(1 << 18);
-       }
-       if (ir->polling) {
-               del_timer(&ir->timer);
-               flush_scheduled_work();
-       }
-
+       cx88_ir_stop(core, ir);
        input_unregister_device(ir->input);
        kfree(ir);
 
index 6b23a4e..1fe1a83 100644 (file)
@@ -44,8 +44,12 @@ module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
 
 #define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg)
+       printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
 
+#define mpeg_dbg(level,fmt, arg...)    if (debug >= level) \
+       printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+
+static LIST_HEAD(cx8802_devlist);
 /* ------------------------------------------------------------------ */
 
 static int cx8802_start_dma(struct cx8802_dev    *dev,
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
 
        /* FIXME: this needs a review.
         * also: move to cx88-blackbird + cx88-dvb source files? */
-       if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) {
-               /* Report a warning until the mini driver patch is applied,
-                * else the following conditions will set the dma registers incorrectly.
-                * This will be removed in the next major patch and changes to the conditions
-                * will be made.
-                */
-               printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__);
-               return -EINVAL;
-       }
 
-       if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) {
+       dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
+
+       if ( (core->active_type_id == CX88_MPEG_DVB) &&
+               (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
+
+               dprintk( 1, "cx8802_start_dma doing .dvb\n");
                /* negedge driven & software reset */
                cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
                udelay(100);
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                        cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
                        udelay(100);
                        break;
+               case CX88_BOARD_HAUPPAUGE_HVR1300:
+                       break;
                default:
                        cx_write(TS_SOP_STAT, 0x00);
                        break;
                }
                cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
                udelay(100);
-       }
-
-       if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+       } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
+               (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
+               dprintk( 1, "cx8802_start_dma doing .blackbird\n");
                cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 
                cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
 
                cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
                udelay(100);
+       } else {
+               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
+                       cx88_boards[core->board].mpeg );
+               return -EINVAL;
        }
 
        /* reset counter */
@@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
        return 0;
 }
 
+struct cx8802_dev * cx8802_get_device(struct inode *inode)
+{
+       int minor = iminor(inode);
+       struct cx8802_dev *h = NULL;
+       struct list_head *list;
+
+       list_for_each(list,&cx8802_devlist) {
+               h = list_entry(list, struct cx8802_dev, devlist);
+               if (h->mpeg_dev->minor == minor)
+                       return h;
+       }
+
+       return NULL;
+}
+
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
+{
+       struct cx8802_dev *h = NULL;
+       struct cx8802_driver *d = NULL;
+       struct list_head *list;
+       struct list_head *list2;
+
+       list_for_each(list,&cx8802_devlist) {
+               h = list_entry(list, struct cx8802_dev, devlist);
+               if (h != dev)
+                       continue;
+
+               list_for_each(list2, &h->drvlist.devlist) {
+                       d = list_entry(list2, struct cx8802_driver, devlist);
+
+                       /* only unregister the correct driver type */
+                       if (d->type_id == btype) {
+                               return d;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+/* Driver asked for hardware access. */
+int cx8802_request_acquire(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+
+       /* Fail a request for hardware if the device is busy. */
+       if (core->active_type_id != CX88_BOARD_NONE)
+               return -EBUSY;
+
+       if (drv->advise_acquire)
+       {
+               core->active_type_id = drv->type_id;
+               drv->advise_acquire(drv);
+
+               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+       }
+
+       return 0;
+}
+
+/* Driver asked to release hardware. */
+int cx8802_request_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+
+       if (drv->advise_release)
+       {
+               drv->advise_release(drv);
+               core->active_type_id = CX88_BOARD_NONE;
+               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+       }
+
+       return 0;
+}
+
+static int cx8802_check_driver(struct cx8802_driver *drv)
+{
+       if (drv == NULL)
+               return -ENODEV;
+
+       if ((drv->type_id != CX88_MPEG_DVB) &&
+               (drv->type_id != CX88_MPEG_BLACKBIRD))
+               return -EINVAL;
+
+       if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
+               (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
+               return -EINVAL;
+
+       if ((drv->probe == NULL) ||
+               (drv->remove == NULL) ||
+               (drv->advise_acquire == NULL) ||
+               (drv->advise_release == NULL))
+               return -EINVAL;
+
+       return 0;
+}
+
+int cx8802_register_driver(struct cx8802_driver *drv)
+{
+       struct cx8802_dev *h;
+       struct cx8802_driver *driver;
+       struct list_head *list;
+       int err = 0, i = 0;
+
+       printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
+               drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+               drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+       if ((err = cx8802_check_driver(drv)) != 0) {
+               printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
+               return err;
+       }
+
+       list_for_each(list,&cx8802_devlist) {
+               h = list_entry(list, struct cx8802_dev, devlist);
+
+               printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
+                       h->core->name,h->pci->subsystem_vendor,
+                       h->pci->subsystem_device,cx88_boards[h->core->board].name,
+                       h->core->board);
+
+               /* Bring up a new struct for each driver instance */
+               driver = kzalloc(sizeof(*drv),GFP_KERNEL);
+               if (driver == NULL)
+                       return -ENOMEM;
+
+               /* Snapshot of the driver registration data */
+               drv->core = h->core;
+               drv->suspend = cx8802_suspend_common;
+               drv->resume = cx8802_resume_common;
+               drv->request_acquire = cx8802_request_acquire;
+               drv->request_release = cx8802_request_release;
+               memcpy(driver, drv, sizeof(*driver));
+
+               err = drv->probe(driver);
+               if (err == 0) {
+                       i++;
+                       mutex_lock(&drv->core->lock);
+                       list_add_tail(&driver->devlist,&h->drvlist.devlist);
+                       mutex_unlock(&drv->core->lock);
+               } else {
+                       printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
+               }
+
+       }
+       if (i == 0)
+               err = -ENODEV;
+       else
+               err = 0;
+
+       return err;
+}
+
+int cx8802_unregister_driver(struct cx8802_driver *drv)
+{
+       struct cx8802_dev *h;
+       struct cx8802_driver *d;
+       struct list_head *list;
+       struct list_head *list2, *q;
+       int err = 0, i = 0;
+
+       printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
+               drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
+
+       list_for_each(list,&cx8802_devlist) {
+               i++;
+               h = list_entry(list, struct cx8802_dev, devlist);
+
+               printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
+                       h->core->name,h->pci->subsystem_vendor,
+                       h->pci->subsystem_device,cx88_boards[h->core->board].name,
+                       h->core->board);
+
+               list_for_each_safe(list2, q, &h->drvlist.devlist) {
+                       d = list_entry(list2, struct cx8802_driver, devlist);
+
+                       /* only unregister the correct driver type */
+                       if (d->type_id != drv->type_id)
+                               continue;
+
+                       err = d->remove(d);
+                       if (err == 0) {
+                               mutex_lock(&drv->core->lock);
+                               list_del(list2);
+                               mutex_unlock(&drv->core->lock);
+                       } else
+                               printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
+
+               }
+
+       }
+
+       return err;
+}
+
 /* ----------------------------------------------------------- */
+static int __devinit cx8802_probe(struct pci_dev *pci_dev,
+                              const struct pci_device_id *pci_id)
+{
+       struct cx8802_dev *dev;
+       struct cx88_core  *core;
+       int err;
+
+       /* general setup */
+       core = cx88_core_get(pci_dev);
+       if (NULL == core)
+               return -EINVAL;
 
+       printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
+
+       err = -ENODEV;
+       if (!cx88_boards[core->board].mpeg)
+               goto fail_core;
+
+       err = -ENOMEM;
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+       if (NULL == dev)
+               goto fail_core;
+       dev->pci = pci_dev;
+       dev->core = core;
+
+       err = cx8802_init_common(dev);
+       if (err != 0)
+               goto fail_free;
+
+       INIT_LIST_HEAD(&dev->drvlist.devlist);
+       list_add_tail(&dev->devlist,&cx8802_devlist);
+
+       /* Maintain a reference so cx88-video can query the 8802 device. */
+       core->dvbdev = dev;
+       return 0;
+
+ fail_free:
+       kfree(dev);
+ fail_core:
+       cx88_core_put(core,pci_dev);
+       return err;
+}
+
+static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+{
+       struct cx8802_dev *dev;
+       struct cx8802_driver *h;
+       struct list_head *list;
+
+       dev = pci_get_drvdata(pci_dev);
+
+       dprintk( 1, "%s\n", __FUNCTION__);
+
+       list_for_each(list,&dev->drvlist.devlist) {
+               h = list_entry(list, struct cx8802_driver, devlist);
+               dprintk( 1, " ->driver\n");
+               if (h->remove == NULL) {
+                       printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
+                       continue;
+               }
+               printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
+               cx8802_unregister_driver(h);
+               list_del(&dev->drvlist.devlist);
+       }
+
+       /* Destroy any 8802 reference. */
+       dev->core->dvbdev = NULL;
+
+       /* common */
+       cx8802_fini_common(dev);
+       cx88_core_put(dev->core,dev->pci);
+       kfree(dev);
+}
+
+static struct pci_device_id cx8802_pci_tbl[] = {
+       {
+               .vendor       = 0x14f1,
+               .device       = 0x8802,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       },{
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
+
+static struct pci_driver cx8802_pci_driver = {
+       .name     = "cx88-mpeg driver manager",
+       .id_table = cx8802_pci_tbl,
+       .probe    = cx8802_probe,
+       .remove   = __devexit_p(cx8802_remove),
+};
+
+static int cx8802_init(void)
+{
+       printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
+              (CX88_VERSION_CODE >> 16) & 0xff,
+              (CX88_VERSION_CODE >>  8) & 0xff,
+              CX88_VERSION_CODE & 0xff);
+#ifdef SNAPSHOT
+       printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
+              SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
+#endif
+       return pci_register_driver(&cx8802_pci_driver);
+}
+
+static void cx8802_fini(void)
+{
+       pci_unregister_driver(&cx8802_pci_driver);
+}
+
+module_init(cx8802_init);
+module_exit(cx8802_fini);
 EXPORT_SYMBOL(cx8802_buf_prepare);
 EXPORT_SYMBOL(cx8802_buf_queue);
 EXPORT_SYMBOL(cx8802_cancel_buffers);
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers);
 EXPORT_SYMBOL(cx8802_init_common);
 EXPORT_SYMBOL(cx8802_fini_common);
 
-EXPORT_SYMBOL(cx8802_suspend_common);
-EXPORT_SYMBOL(cx8802_resume_common);
-
+EXPORT_SYMBOL(cx8802_register_driver);
+EXPORT_SYMBOL(cx8802_unregister_driver);
+EXPORT_SYMBOL(cx8802_get_device);
+EXPORT_SYMBOL(cx8802_get_driver);
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
index 58ba9f7..3482e01 100644 (file)
@@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
        cx88_start_audio_dma(core);
 
        if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
-               /* sets sound input from external adc */
-               switch (core->board) {
-               case CX88_BOARD_HAUPPAUGE_ROSLYN:
-               case CX88_BOARD_KWORLD_MCE200_DELUXE:
-               case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
-               case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
-               case CX88_BOARD_ASUS_PVR_416:
-                       cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
-                       break;
-               default:
-                       cx_set(AUD_CTL, EN_I2SIN_ENABLE);
-               }
-
                cx_write(AUD_I2SINPUTCNTL, 4);
                cx_write(AUD_BAUDRATE, 1);
                /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
index 90e298d..8613378 100644 (file)
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input)
                cx_clear(MO_FILTER_ODD,   0x00002020);
                break;
        }
+
+       if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+               /* sets sound input from external adc */
+               if (INPUT(input)->extadc)
+                       cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+               else
+                       cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+       }
        return 0;
 }
 
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
                mutex_unlock(&core->lock);
                return 0;
        }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       /* ioctls to allow direct acces to the cx2388x registers */
+       case VIDIOC_INT_G_REGISTER:
+       {
+               struct v4l2_register *reg = arg;
+
+               if (reg->i2c_id != 0)
+                       return -EINVAL;
+               /* cx2388x has a 24-bit register space */
+               reg->val = cx_read(reg->reg&0xffffff);
+               return 0;
+       }
+       case VIDIOC_INT_S_REGISTER:
+       {
+               struct v4l2_register *reg = arg;
+
+               if (reg->i2c_id != 0)
+                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               cx_write(reg->reg&0xffffff, reg->val);
+               return 0;
+       }
+#endif
 
        default:
                return v4l_compat_translate_ioctl(inode,file,cmd,arg,
index 3bc91aa..7054e94 100644 (file)
@@ -74,6 +74,11 @@ enum cx88_board_type {
        CX88_MPEG_BLACKBIRD
 };
 
+enum cx8802_board_access {
+       CX8802_DRVCTL_SHARED    = 1,
+       CX8802_DRVCTL_EXCLUSIVE = 2,
+};
+
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
@@ -220,6 +225,7 @@ struct cx88_input {
        enum cx88_itype type;
        unsigned int    vmux;
        u32             gpio0, gpio1, gpio2, gpio3;
+       unsigned int    extadc:1;
 };
 
 struct cx88_board {
@@ -330,6 +336,7 @@ struct cx88_core {
 
        /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
        struct cx8802_dev          *dvbdev;
+       enum cx88_board_type       active_type_id;
 };
 
 struct cx8800_dev;
@@ -405,6 +412,31 @@ struct cx8802_suspend_state {
        int                        disabled;
 };
 
+struct cx8802_driver {
+       struct cx88_core *core;
+       struct list_head devlist;
+
+       /* Type of driver and access required */
+       enum cx88_board_type type_id;
+       enum cx8802_board_access hw_access;
+
+       /* MPEG 8802 internal only */
+       int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+       int (*resume)(struct pci_dev *pci_dev);
+
+       /* MPEG 8802 -> mini driver - Driver probe and configuration */
+       int (*probe)(struct cx8802_driver *drv);
+       int (*remove)(struct cx8802_driver *drv);
+
+       /* MPEG 8802 -> mini driver - Access for hardware control */
+       int (*advise_acquire)(struct cx8802_driver *drv);
+       int (*advise_release)(struct cx8802_driver *drv);
+
+       /* MPEG 8802 <- mini driver - Access for hardware control */
+       int (*request_acquire)(struct cx8802_driver *drv);
+       int (*request_release)(struct cx8802_driver *drv);
+};
+
 struct cx8802_dev {
        struct cx88_core           *core;
        spinlock_t                 slock;
@@ -439,6 +471,9 @@ struct cx8802_dev {
 
        /* mpeg params */
        struct cx2341x_mpeg_params params;
+
+       /* List of attached drivers */
+       struct cx8802_driver       drvlist;
 };
 
 /* ----------------------------------------------------------- */
@@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
 int cx88_audio_thread(void *data);
 
+int cx8802_register_driver(struct cx8802_driver *drv);
+int cx8802_unregister_driver(struct cx8802_driver *drv);
+struct cx8802_dev * cx8802_get_device(struct inode *inode);
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
 /* ----------------------------------------------------------- */
 /* cx88-input.c                                                */
 
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
 extern const u32 cx88_user_ctrls[];
 extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
 
+/* ----------------------------------------------------------- */
+/* cx88-blackbird.c                                            */
+/* used by cx88-ivtv ioctl emulation layer                     */
+extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+                             unsigned int cmd, void *arg);
+extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
 /*
  * Local variables:
  * c-basic-offset: 8
index 1457b16..59edf58 100644 (file)
@@ -268,9 +268,9 @@ static void ir_timer(unsigned long data)
        schedule_work(&ir->work);
 }
 
-static void ir_work(void *data)
+static void ir_work(struct work_struct *work)
 {
-       struct IR_i2c *ir = data;
+       struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
        ir_key_poll(ir);
        mod_timer(&ir->timer, jiffies+HZ/10);
 }
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
        int ir_type;
        struct IR_i2c *ir;
        struct input_dev *input_dev;
+       int err;
 
        ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!ir || !input_dev) {
-               input_free_device(input_dev);
-               kfree(ir);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
-       memset(ir,0,sizeof(*ir));
 
        ir->c = client_template;
        ir->input = input_dev;
@@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                break;
        case 0x7a:
        case 0x47:
+       case 0x71:
                /* Handled by saa7134-input */
                name        = "SAA713x remote";
                ir_type     = IR_TYPE_OTHER;
                break;
        default:
                /* shouldn't happen */
-               printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
-               kfree(ir);
-               return -1;
+               printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        /* Sets name */
        snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
-       ir->ir_codes=ir_codes;
+       ir->ir_codes = ir_codes;
 
        /* register i2c device
         * At device register, IR codes may be changed to be
         * board dependent.
         */
-       i2c_attach_client(&ir->c);
+       err = i2c_attach_client(&ir->c);
+       if (err)
+               goto err_out_free;
 
        /* If IR not supported or disabled, unregisters driver */
        if (ir->get_key == NULL) {
-               i2c_detach_client(&ir->c);
-               kfree(ir);
-               return -1;
+               err = -ENODEV;
+               goto err_out_detach;
        }
 
        /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
@@ -389,24 +390,33 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                 ir->c.dev.bus_id);
 
        /* init + register input device */
-       ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
+       ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
        input_dev->id.bustype = BUS_I2C;
        input_dev->name       = ir->c.name;
        input_dev->phys       = ir->phys;
 
-       /* register event device */
-       input_register_device(ir->input);
+       err = input_register_device(ir->input);
+       if (err)
+               goto err_out_detach;
+
        printk(DEVNAME ": %s detected at %s [%s]\n",
-              ir->input->name,ir->input->phys,adap->name);
+              ir->input->name, ir->input->phys, adap->name);
 
        /* start polling via eventd */
-       INIT_WORK(&ir->work, ir_work, ir);
+       INIT_WORK(&ir->work, ir_work);
        init_timer(&ir->timer);
        ir->timer.function = ir_timer;
        ir->timer.data     = (unsigned long)ir;
        schedule_work(&ir->work);
 
        return 0;
+
+ err_out_detach:
+       i2c_detach_client(&ir->c);
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 static int ir_detach(struct i2c_client *client)
@@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client)
        struct IR_i2c *ir = i2c_get_clientdata(client);
 
        /* kill outstanding polls */
-       del_timer(&ir->timer);
+       del_timer_sync(&ir->timer);
        flush_scheduled_work();
 
        /* unregister devices */
@@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap)
        */
 
        static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
-       static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
+       static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 };
        static const int probe_em28XX[] = { 0x30, 0x47, -1 };
        const int *probe = NULL;
        struct i2c_client c;
index cf43df3..e1b56dc 100644 (file)
@@ -56,7 +56,7 @@
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
 #include <linux/kthread.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include "msp3400-driver.h"
 
 /* ---------------------------------------------------------------------- */
index b0aea40..152cc6b 100644 (file)
@@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev)
                printk("mxb: saa7111 i2c module not available.\n");
                return -ENODEV;
        }
-       if ((result = request_module("tuner")) < 0) {
-               printk("mxb: tuner i2c module not available.\n");
-               return -ENODEV;
-       }
        if ((result = request_module("tea6420")) < 0) {
                printk("mxb: tea6420 i2c module not available.\n");
                return -ENODEV;
@@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev)
                printk("mxb: tda9840 i2c module not available.\n");
                return -ENODEV;
        }
+       if ((result = request_module("tuner")) < 0) {
+               printk("mxb: tuner i2c module not available.\n");
+               return -ENODEV;
+       }
 
        mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
        if( NULL == mxb ) {
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
new file mode 100644 (file)
index 0000000..89dd18c
--- /dev/null
@@ -0,0 +1,1333 @@
+/*
+ * A V4L2 driver for OmniVision OV7670 cameras.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.  Written
+ * by Jonathan Corbet with substantial inspiration from Mark
+ * McClelland's ovcamchip code.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <linux/i2c.h>
+
+
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net.");
+MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
+MODULE_LICENSE("GPL");
+
+/*
+ * Basic window sizes.  These probably belong somewhere more globally
+ * useful.
+ */
+#define VGA_WIDTH      640
+#define VGA_HEIGHT     480
+#define QVGA_WIDTH     320
+#define QVGA_HEIGHT    240
+#define CIF_WIDTH      352
+#define CIF_HEIGHT     288
+#define QCIF_WIDTH     176
+#define        QCIF_HEIGHT     144
+
+/*
+ * Our nominal (default) frame rate.
+ */
+#define OV7670_FRAME_RATE 30
+
+/*
+ * The 7670 sits on i2c with ID 0x42
+ */
+#define OV7670_I2C_ADDR 0x42
+
+/* Registers */
+#define REG_GAIN       0x00    /* Gain lower 8 bits (rest in vref) */
+#define REG_BLUE       0x01    /* blue gain */
+#define REG_RED                0x02    /* red gain */
+#define REG_VREF       0x03    /* Pieces of GAIN, VSTART, VSTOP */
+#define REG_COM1       0x04    /* Control 1 */
+#define  COM1_CCIR656    0x40  /* CCIR656 enable */
+#define REG_BAVE       0x05    /* U/B Average level */
+#define REG_GbAVE      0x06    /* Y/Gb Average level */
+#define REG_AECHH      0x07    /* AEC MS 5 bits */
+#define REG_RAVE       0x08    /* V/R Average level */
+#define REG_COM2       0x09    /* Control 2 */
+#define  COM2_SSLEEP     0x10  /* Soft sleep mode */
+#define REG_PID                0x0a    /* Product ID MSB */
+#define REG_VER                0x0b    /* Product ID LSB */
+#define REG_COM3       0x0c    /* Control 3 */
+#define  COM3_SWAP       0x40    /* Byte swap */
+#define  COM3_SCALEEN    0x08    /* Enable scaling */
+#define  COM3_DCWEN      0x04    /* Enable downsamp/crop/window */
+#define REG_COM4       0x0d    /* Control 4 */
+#define REG_COM5       0x0e    /* All "reserved" */
+#define REG_COM6       0x0f    /* Control 6 */
+#define REG_AECH       0x10    /* More bits of AEC value */
+#define REG_CLKRC      0x11    /* Clocl control */
+#define   CLK_EXT        0x40    /* Use external clock directly */
+#define   CLK_SCALE      0x3f    /* Mask for internal clock scale */
+#define REG_COM7       0x12    /* Control 7 */
+#define   COM7_RESET     0x80    /* Register reset */
+#define   COM7_FMT_MASK          0x38
+#define   COM7_FMT_VGA   0x00
+#define          COM7_FMT_CIF    0x20    /* CIF format */
+#define   COM7_FMT_QVGA          0x10    /* QVGA format */
+#define   COM7_FMT_QCIF          0x08    /* QCIF format */
+#define          COM7_RGB        0x04    /* bits 0 and 2 - RGB format */
+#define          COM7_YUV        0x00    /* YUV */
+#define          COM7_BAYER      0x01    /* Bayer format */
+#define          COM7_PBAYER     0x05    /* "Processed bayer" */
+#define REG_COM8       0x13    /* Control 8 */
+#define   COM8_FASTAEC   0x80    /* Enable fast AGC/AEC */
+#define   COM8_AECSTEP   0x40    /* Unlimited AEC step size */
+#define   COM8_BFILT     0x20    /* Band filter enable */
+#define   COM8_AGC       0x04    /* Auto gain enable */
+#define   COM8_AWB       0x02    /* White balance enable */
+#define   COM8_AEC       0x01    /* Auto exposure enable */
+#define REG_COM9       0x14    /* Control 9  - gain ceiling */
+#define REG_COM10      0x15    /* Control 10 */
+#define   COM10_HSYNC    0x40    /* HSYNC instead of HREF */
+#define   COM10_PCLK_HB          0x20    /* Suppress PCLK on horiz blank */
+#define   COM10_HREF_REV  0x08   /* Reverse HREF */
+#define   COM10_VS_LEAD          0x04    /* VSYNC on clock leading edge */
+#define   COM10_VS_NEG   0x02    /* VSYNC negative */
+#define   COM10_HS_NEG   0x01    /* HSYNC negative */
+#define REG_HSTART     0x17    /* Horiz start high bits */
+#define REG_HSTOP      0x18    /* Horiz stop high bits */
+#define REG_VSTART     0x19    /* Vert start high bits */
+#define REG_VSTOP      0x1a    /* Vert stop high bits */
+#define REG_PSHFT      0x1b    /* Pixel delay after HREF */
+#define REG_MIDH       0x1c    /* Manuf. ID high */
+#define REG_MIDL       0x1d    /* Manuf. ID low */
+#define REG_MVFP       0x1e    /* Mirror / vflip */
+#define   MVFP_MIRROR    0x20    /* Mirror image */
+#define   MVFP_FLIP      0x10    /* Vertical flip */
+
+#define REG_AEW                0x24    /* AGC upper limit */
+#define REG_AEB                0x25    /* AGC lower limit */
+#define REG_VPT                0x26    /* AGC/AEC fast mode op region */
+#define REG_HSYST      0x30    /* HSYNC rising edge delay */
+#define REG_HSYEN      0x31    /* HSYNC falling edge delay */
+#define REG_HREF       0x32    /* HREF pieces */
+#define REG_TSLB       0x3a    /* lots of stuff */
+#define   TSLB_YLAST     0x04    /* UYVY or VYUY - see com13 */
+#define REG_COM11      0x3b    /* Control 11 */
+#define   COM11_NIGHT    0x80    /* NIght mode enable */
+#define   COM11_NMFR     0x60    /* Two bit NM frame rate */
+#define   COM11_HZAUTO   0x10    /* Auto detect 50/60 Hz */
+#define          COM11_50HZ      0x08    /* Manual 50Hz select */
+#define   COM11_EXP      0x02
+#define REG_COM12      0x3c    /* Control 12 */
+#define   COM12_HREF     0x80    /* HREF always */
+#define REG_COM13      0x3d    /* Control 13 */
+#define   COM13_GAMMA    0x80    /* Gamma enable */
+#define          COM13_UVSAT     0x40    /* UV saturation auto adjustment */
+#define   COM13_UVSWAP   0x01    /* V before U - w/TSLB */
+#define REG_COM14      0x3e    /* Control 14 */
+#define   COM14_DCWEN    0x10    /* DCW/PCLK-scale enable */
+#define REG_EDGE       0x3f    /* Edge enhancement factor */
+#define REG_COM15      0x40    /* Control 15 */
+#define   COM15_R10F0    0x00    /* Data range 10 to F0 */
+#define          COM15_R01FE     0x80    /*            01 to FE */
+#define   COM15_R00FF    0xc0    /*            00 to FF */
+#define   COM15_RGB565   0x10    /* RGB565 output */
+#define   COM15_RGB555   0x30    /* RGB555 output */
+#define REG_COM16      0x41    /* Control 16 */
+#define   COM16_AWBGAIN   0x08   /* AWB gain enable */
+#define REG_COM17      0x42    /* Control 17 */
+#define   COM17_AECWIN   0xc0    /* AEC window - must match COM4 */
+#define   COM17_CBAR     0x08    /* DSP Color bar */
+
+/*
+ * This matrix defines how the colors are generated, must be
+ * tweaked to adjust hue and saturation.
+ *
+ * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
+ *
+ * They are nine-bit signed quantities, with the sign bit
+ * stored in 0x58.  Sign for v-red is bit 0, and up from there.
+ */
+#define        REG_CMATRIX_BASE 0x4f
+#define   CMATRIX_LEN 6
+#define REG_CMATRIX_SIGN 0x58
+
+
+#define REG_BRIGHT     0x55    /* Brightness */
+#define REG_CONTRAS    0x56    /* Contrast control */
+
+#define REG_GFIX       0x69    /* Fix gain control */
+
+#define REG_RGB444     0x8c    /* RGB 444 control */
+#define   R444_ENABLE    0x02    /* Turn on RGB444, overrides 5x5 */
+#define   R444_RGBX      0x01    /* Empty nibble at end */
+
+#define REG_HAECC1     0x9f    /* Hist AEC/AGC control 1 */
+#define REG_HAECC2     0xa0    /* Hist AEC/AGC control 2 */
+
+#define REG_BD50MAX    0xa5    /* 50hz banding step limit */
+#define REG_HAECC3     0xa6    /* Hist AEC/AGC control 3 */
+#define REG_HAECC4     0xa7    /* Hist AEC/AGC control 4 */
+#define REG_HAECC5     0xa8    /* Hist AEC/AGC control 5 */
+#define REG_HAECC6     0xa9    /* Hist AEC/AGC control 6 */
+#define REG_HAECC7     0xaa    /* Hist AEC/AGC control 7 */
+#define REG_BD60MAX    0xab    /* 60hz banding step limit */
+
+
+/*
+ * Information we maintain about a known sensor.
+ */
+struct ov7670_format_struct;  /* coming later */
+struct ov7670_info {
+       struct ov7670_format_struct *fmt;  /* Current format */
+       unsigned char sat;              /* Saturation value */
+       int hue;                        /* Hue value */
+};
+
+
+
+
+/*
+ * The default register settings, as obtained from OmniVision.  There
+ * is really no making sense of most of these - lots of "reserved" values
+ * and such.
+ *
+ * These settings give VGA YUYV.
+ */
+
+struct regval_list {
+       unsigned char reg_num;
+       unsigned char value;
+};
+
+static struct regval_list ov7670_default_regs[] = {
+       { REG_COM7, COM7_RESET },
+/*
+ * Clock scale: 3 = 15fps
+ *              2 = 20fps
+ *              1 = 30fps
+ */
+       { REG_CLKRC, 0x1 },     /* OV: clock scale (30 fps) */
+       { REG_TSLB,  0x04 },    /* OV */
+       { REG_COM7, 0 },        /* VGA */
+       /*
+        * Set the hardware window.  These values from OV don't entirely
+        * make sense - hstop is less than hstart.  But they work...
+        */
+       { REG_HSTART, 0x13 },   { REG_HSTOP, 0x01 },
+       { REG_HREF, 0xb6 },     { REG_VSTART, 0x02 },
+       { REG_VSTOP, 0x7a },    { REG_VREF, 0x0a },
+
+       { REG_COM3, 0 },        { REG_COM14, 0 },
+       /* Mystery scaling numbers */
+       { 0x70, 0x3a },         { 0x71, 0x35 },
+       { 0x72, 0x11 },         { 0x73, 0xf0 },
+       { 0xa2, 0x02 },         { REG_COM10, 0x0 },
+
+       /* Gamma curve values */
+       { 0x7a, 0x20 },         { 0x7b, 0x10 },
+       { 0x7c, 0x1e },         { 0x7d, 0x35 },
+       { 0x7e, 0x5a },         { 0x7f, 0x69 },
+       { 0x80, 0x76 },         { 0x81, 0x80 },
+       { 0x82, 0x88 },         { 0x83, 0x8f },
+       { 0x84, 0x96 },         { 0x85, 0xa3 },
+       { 0x86, 0xaf },         { 0x87, 0xc4 },
+       { 0x88, 0xd7 },         { 0x89, 0xe8 },
+
+       /* AGC and AEC parameters.  Note we start by disabling those features,
+          then turn them only after tweaking the values. */
+       { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT },
+       { REG_GAIN, 0 },        { REG_AECH, 0 },
+       { REG_COM4, 0x40 }, /* magic reserved bit */
+       { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+       { REG_BD50MAX, 0x05 },  { REG_BD60MAX, 0x07 },
+       { REG_AEW, 0x95 },      { REG_AEB, 0x33 },
+       { REG_VPT, 0xe3 },      { REG_HAECC1, 0x78 },
+       { REG_HAECC2, 0x68 },   { 0xa1, 0x03 }, /* magic */
+       { REG_HAECC3, 0xd8 },   { REG_HAECC4, 0xd8 },
+       { REG_HAECC5, 0xf0 },   { REG_HAECC6, 0x90 },
+       { REG_HAECC7, 0x94 },
+       { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC },
+
+       /* Almost all of these are magic "reserved" values.  */
+       { REG_COM5, 0x61 },     { REG_COM6, 0x4b },
+       { 0x16, 0x02 },         { REG_MVFP, 0x07|MVFP_MIRROR },
+       { 0x21, 0x02 },         { 0x22, 0x91 },
+       { 0x29, 0x07 },         { 0x33, 0x0b },
+       { 0x35, 0x0b },         { 0x37, 0x1d },
+       { 0x38, 0x71 },         { 0x39, 0x2a },
+       { REG_COM12, 0x78 },    { 0x4d, 0x40 },
+       { 0x4e, 0x20 },         { REG_GFIX, 0 },
+       { 0x6b, 0x4a },         { 0x74, 0x10 },
+       { 0x8d, 0x4f },         { 0x8e, 0 },
+       { 0x8f, 0 },            { 0x90, 0 },
+       { 0x91, 0 },            { 0x96, 0 },
+       { 0x9a, 0 },            { 0xb0, 0x84 },
+       { 0xb1, 0x0c },         { 0xb2, 0x0e },
+       { 0xb3, 0x82 },         { 0xb8, 0x0a },
+
+       /* More reserved magic, some of which tweaks white balance */
+       { 0x43, 0x0a },         { 0x44, 0xf0 },
+       { 0x45, 0x34 },         { 0x46, 0x58 },
+       { 0x47, 0x28 },         { 0x48, 0x3a },
+       { 0x59, 0x88 },         { 0x5a, 0x88 },
+       { 0x5b, 0x44 },         { 0x5c, 0x67 },
+       { 0x5d, 0x49 },         { 0x5e, 0x0e },
+       { 0x6c, 0x0a },         { 0x6d, 0x55 },
+       { 0x6e, 0x11 },         { 0x6f, 0x9f }, /* "9e for advance AWB" */
+       { 0x6a, 0x40 },         { REG_BLUE, 0x40 },
+       { REG_RED, 0x60 },
+       { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB },
+
+       /* Matrix coefficients */
+       { 0x4f, 0x80 },         { 0x50, 0x80 },
+       { 0x51, 0 },            { 0x52, 0x22 },
+       { 0x53, 0x5e },         { 0x54, 0x80 },
+       { 0x58, 0x9e },
+
+       { REG_COM16, COM16_AWBGAIN },   { REG_EDGE, 0 },
+       { 0x75, 0x05 },         { 0x76, 0xe1 },
+       { 0x4c, 0 },            { 0x77, 0x01 },
+       { REG_COM13, 0xc3 },    { 0x4b, 0x09 },
+       { 0xc9, 0x60 },         { REG_COM16, 0x38 },
+       { 0x56, 0x40 },
+
+       { 0x34, 0x11 },         { REG_COM11, COM11_EXP|COM11_HZAUTO },
+       { 0xa4, 0x88 },         { 0x96, 0 },
+       { 0x97, 0x30 },         { 0x98, 0x20 },
+       { 0x99, 0x30 },         { 0x9a, 0x84 },
+       { 0x9b, 0x29 },         { 0x9c, 0x03 },
+       { 0x9d, 0x4c },         { 0x9e, 0x3f },
+       { 0x78, 0x04 },
+
+       /* Extra-weird stuff.  Some sort of multiplexor register */
+       { 0x79, 0x01 },         { 0xc8, 0xf0 },
+       { 0x79, 0x0f },         { 0xc8, 0x00 },
+       { 0x79, 0x10 },         { 0xc8, 0x7e },
+       { 0x79, 0x0a },         { 0xc8, 0x80 },
+       { 0x79, 0x0b },         { 0xc8, 0x01 },
+       { 0x79, 0x0c },         { 0xc8, 0x0f },
+       { 0x79, 0x0d },         { 0xc8, 0x20 },
+       { 0x79, 0x09 },         { 0xc8, 0x80 },
+       { 0x79, 0x02 },         { 0xc8, 0xc0 },
+       { 0x79, 0x03 },         { 0xc8, 0x40 },
+       { 0x79, 0x05 },         { 0xc8, 0x30 },
+       { 0x79, 0x26 },
+
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+
+/*
+ * Here we'll try to encapsulate the changes for just the output
+ * video format.
+ *
+ * RGB656 and YUV422 come from OV; RGB444 is homebrewed.
+ *
+ * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why.
+ */
+
+
+static struct regval_list ov7670_fmt_yuv422[] = {
+       { REG_COM7, 0x0 },  /* Selects YUV mode */
+       { REG_RGB444, 0 },      /* No RGB444 please */
+       { REG_COM1, 0 },
+       { REG_COM15, COM15_R00FF },
+       { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
+       { 0x4f, 0x80 },         /* "matrix coefficient 1" */
+       { 0x50, 0x80 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x22 },         /* "matrix coefficient 4" */
+       { 0x53, 0x5e },         /* "matrix coefficient 5" */
+       { 0x54, 0x80 },         /* "matrix coefficient 6" */
+       { REG_COM13, COM13_GAMMA|COM13_UVSAT },
+       { 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb565[] = {
+       { REG_COM7, COM7_RGB }, /* Selects RGB mode */
+       { REG_RGB444, 0 },      /* No RGB444 please */
+       { REG_COM1, 0x0 },
+       { REG_COM15, COM15_RGB565 },
+       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
+       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
+       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x3d },         /* "matrix coefficient 4" */
+       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
+       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
+       { REG_COM13, COM13_GAMMA|COM13_UVSAT },
+       { 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb444[] = {
+       { REG_COM7, COM7_RGB }, /* Selects RGB mode */
+       { REG_RGB444, R444_ENABLE },    /* Enable xxxxrrrr ggggbbbb */
+       { REG_COM1, 0x40 },     /* Magic reserved bit */
+       { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */
+       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
+       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
+       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x3d },         /* "matrix coefficient 4" */
+       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
+       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
+       { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 },  /* Magic rsvd bit */
+       { 0xff, 0xff },
+};
+
+
+
+
+/*
+ * Low-level register I/O.
+ */
+
+static int ov7670_read(struct i2c_client *c, unsigned char reg,
+               unsigned char *value)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(c, reg);
+       if (ret >= 0)
+               *value = (unsigned char) ret;
+       return ret;
+}
+
+
+static int ov7670_write(struct i2c_client *c, unsigned char reg,
+               unsigned char value)
+{
+       return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+
+/*
+ * Write a list of register settings; ff/ff stops the process.
+ */
+static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals)
+{
+       while (vals->reg_num != 0xff || vals->value != 0xff) {
+               int ret = ov7670_write(c, vals->reg_num, vals->value);
+               if (ret < 0)
+                       return ret;
+               vals++;
+       }
+       return 0;
+}
+
+
+/*
+ * Stuff that knows about the sensor.
+ */
+static void ov7670_reset(struct i2c_client *client)
+{
+       ov7670_write(client, REG_COM7, COM7_RESET);
+       msleep(1);
+}
+
+
+static int ov7670_init(struct i2c_client *client)
+{
+       return ov7670_write_array(client, ov7670_default_regs);
+}
+
+
+
+static int ov7670_detect(struct i2c_client *client)
+{
+       unsigned char v;
+       int ret;
+
+       ret = ov7670_init(client);
+       if (ret < 0)
+               return ret;
+       ret = ov7670_read(client, REG_MIDH, &v);
+       if (ret < 0)
+               return ret;
+       if (v != 0x7f) /* OV manuf. id. */
+               return -ENODEV;
+       ret = ov7670_read(client, REG_MIDL, &v);
+       if (ret < 0)
+               return ret;
+       if (v != 0xa2)
+               return -ENODEV;
+       /*
+        * OK, we know we have an OmniVision chip...but which one?
+        */
+       ret = ov7670_read(client, REG_PID, &v);
+       if (ret < 0)
+               return ret;
+       if (v != 0x76)  /* PID + VER = 0x76 / 0x73 */
+               return -ENODEV;
+       ret = ov7670_read(client, REG_VER, &v);
+       if (ret < 0)
+               return ret;
+       if (v != 0x73)  /* PID + VER = 0x76 / 0x73 */
+               return -ENODEV;
+       return 0;
+}
+
+
+/*
+ * Store information about the video data format.  The color matrix
+ * is deeply tied into the format, so keep the relevant values here.
+ * The magic matrix nubmers come from OmniVision.
+ */
+static struct ov7670_format_struct {
+       __u8 *desc;
+       __u32 pixelformat;
+       struct regval_list *regs;
+       int cmatrix[CMATRIX_LEN];
+} ov7670_formats[] = {
+       {
+               .desc           = "YUYV 4:2:2",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .regs           = ov7670_fmt_yuv422,
+               .cmatrix        = { 128, -128, 0, -34, -94, 128 },
+       },
+       {
+               .desc           = "RGB 444",
+               .pixelformat    = V4L2_PIX_FMT_RGB444,
+               .regs           = ov7670_fmt_rgb444,
+               .cmatrix        = { 179, -179, 0, -61, -176, 228 },
+       },
+       {
+               .desc           = "RGB 565",
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+               .regs           = ov7670_fmt_rgb565,
+               .cmatrix        = { 179, -179, 0, -61, -176, 228 },
+       },
+};
+#define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0]))
+
+/*
+ * All formats we support are 2 bytes/pixel.
+ */
+#define BYTES_PER_PIXEL 2
+
+/*
+ * Then there is the issue of window sizes.  Try to capture the info here.
+ */
+
+/*
+ * QCIF mode is done (by OV) in a very strange way - it actually looks like
+ * VGA with weird scaling options - they do *not* use the canned QCIF mode
+ * which is allegedly provided by the sensor.  So here's the weird register
+ * settings.
+ */
+static struct regval_list ov7670_qcif_regs[] = {
+       { REG_COM3, COM3_SCALEEN|COM3_DCWEN },
+       { REG_COM3, COM3_DCWEN },
+       { REG_COM14, COM14_DCWEN | 0x01},
+       { 0x73, 0xf1 },
+       { 0xa2, 0x52 },
+       { 0x7b, 0x1c },
+       { 0x7c, 0x28 },
+       { 0x7d, 0x3c },
+       { 0x7f, 0x69 },
+       { REG_COM9, 0x38 },
+       { 0xa1, 0x0b },
+       { 0x74, 0x19 },
+       { 0x9a, 0x80 },
+       { 0x43, 0x14 },
+       { REG_COM13, 0xc0 },
+       { 0xff, 0xff },
+};
+
+static struct ov7670_win_size {
+       int     width;
+       int     height;
+       unsigned char com7_bit;
+       int     hstart;         /* Start/stop values for the camera.  Note */
+       int     hstop;          /* that they do not always make complete */
+       int     vstart;         /* sense to humans, but evidently the sensor */
+       int     vstop;          /* will do the right thing... */
+       struct regval_list *regs; /* Regs to tweak */
+/* h/vref stuff */
+} ov7670_win_sizes[] = {
+       /* VGA */
+       {
+               .width          = VGA_WIDTH,
+               .height         = VGA_HEIGHT,
+               .com7_bit       = COM7_FMT_VGA,
+               .hstart         = 158,          /* These values from */
+               .hstop          =  14,          /* Omnivision */
+               .vstart         =  10,
+               .vstop          = 490,
+               .regs           = NULL,
+       },
+       /* CIF */
+       {
+               .width          = CIF_WIDTH,
+               .height         = CIF_HEIGHT,
+               .com7_bit       = COM7_FMT_CIF,
+               .hstart         = 170,          /* Empirically determined */
+               .hstop          =  90,
+               .vstart         =  14,
+               .vstop          = 494,
+               .regs           = NULL,
+       },
+       /* QVGA */
+       {
+               .width          = QVGA_WIDTH,
+               .height         = QVGA_HEIGHT,
+               .com7_bit       = COM7_FMT_QVGA,
+               .hstart         = 164,          /* Empirically determined */
+               .hstop          =  20,
+               .vstart         =  14,
+               .vstop          = 494,
+               .regs           = NULL,
+       },
+       /* QCIF */
+       {
+               .width          = QCIF_WIDTH,
+               .height         = QCIF_HEIGHT,
+               .com7_bit       = COM7_FMT_VGA, /* see comment above */
+               .hstart         = 456,          /* Empirically determined */
+               .hstop          =  24,
+               .vstart         =  14,
+               .vstop          = 494,
+               .regs           = ov7670_qcif_regs,
+       },
+};
+
+#define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0]))
+
+
+/*
+ * Store a set of start/stop values into the camera.
+ */
+static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop,
+               int vstart, int vstop)
+{
+       int ret;
+       unsigned char v;
+/*
+ * Horizontal: 11 bits, top 8 live in hstart and hstop.  Bottom 3 of
+ * hstart are in href[2:0], bottom 3 of hstop in href[5:3].  There is
+ * a mystery "edge offset" value in the top two bits of href.
+ */
+       ret =  ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff);
+       ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff);
+       ret += ov7670_read(client, REG_HREF, &v);
+       v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
+       msleep(10);
+       ret += ov7670_write(client, REG_HREF, v);
+/*
+ * Vertical: similar arrangement, but only 10 bits.
+ */
+       ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff);
+       ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff);
+       ret += ov7670_read(client, REG_VREF, &v);
+       v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
+       msleep(10);
+       ret += ov7670_write(client, REG_VREF, v);
+       return ret;
+}
+
+
+static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt)
+{
+       struct ov7670_format_struct *ofmt;
+
+       if (fmt->index >= N_OV7670_FMTS)
+               return -EINVAL;
+
+       ofmt = ov7670_formats + fmt->index;
+       fmt->flags = 0;
+       strcpy(fmt->description, ofmt->desc);
+       fmt->pixelformat = ofmt->pixelformat;
+       return 0;
+}
+
+
+static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
+               struct ov7670_format_struct **ret_fmt,
+               struct ov7670_win_size **ret_wsize)
+{
+       int index;
+       struct ov7670_win_size *wsize;
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       for (index = 0; index < N_OV7670_FMTS; index++)
+               if (ov7670_formats[index].pixelformat == pix->pixelformat)
+                       break;
+       if (index >= N_OV7670_FMTS)
+               return -EINVAL;
+       if (ret_fmt != NULL)
+               *ret_fmt = ov7670_formats + index;
+       /*
+        * Fields: the OV devices claim to be progressive.
+        */
+       if (pix->field == V4L2_FIELD_ANY)
+               pix->field = V4L2_FIELD_NONE;
+       else if (pix->field != V4L2_FIELD_NONE)
+               return -EINVAL;
+       /*
+        * Round requested image size down to the nearest
+        * we support, but not below the smallest.
+        */
+       for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
+            wsize++)
+               if (pix->width >= wsize->width && pix->height >= wsize->height)
+                       break;
+       if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
+               wsize--;   /* Take the smallest one */
+       if (ret_wsize != NULL)
+               *ret_wsize = wsize;
+       /*
+        * Note the size we'll actually handle.
+        */
+       pix->width = wsize->width;
+       pix->height = wsize->height;
+       pix->bytesperline = pix->width*BYTES_PER_PIXEL;
+       pix->sizeimage = pix->height*pix->bytesperline;
+       return 0;
+}
+
+/*
+ * Set a format.
+ */
+static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
+{
+       int ret;
+       struct ov7670_format_struct *ovfmt;
+       struct ov7670_win_size *wsize;
+       struct ov7670_info *info = i2c_get_clientdata(c);
+       unsigned char com7;
+
+       ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
+       if (ret)
+               return ret;
+       /*
+        * COM7 is a pain in the ass, it doesn't like to be read then
+        * quickly written afterward.  But we have everything we need
+        * to set it absolutely here, as long as the format-specific
+        * register sets list it first.
+        */
+       com7 = ovfmt->regs[0].value;
+       com7 |= wsize->com7_bit;
+       ov7670_write(c, REG_COM7, com7);
+       /*
+        * Now write the rest of the array.  Also store start/stops
+        */
+       ov7670_write_array(c, ovfmt->regs + 1);
+       ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart,
+                       wsize->vstop);
+       ret = 0;
+       if (wsize->regs)
+               ret = ov7670_write_array(c, wsize->regs);
+       info->fmt = ovfmt;
+       return 0;
+}
+
+/*
+ * Implement G/S_PARM.  There is a "high quality" mode we could try
+ * to do someday; for now, we just do the frame rate tweak.
+ */
+static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+{
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+       unsigned char clkrc;
+       int ret;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       ret = ov7670_read(c, REG_CLKRC, &clkrc);
+       if (ret < 0)
+               return ret;
+       memset(cp, 0, sizeof(struct v4l2_captureparm));
+       cp->capability = V4L2_CAP_TIMEPERFRAME;
+       cp->timeperframe.numerator = 1;
+       cp->timeperframe.denominator = OV7670_FRAME_RATE;
+       if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1)
+               cp->timeperframe.denominator /= (clkrc & CLK_SCALE);
+       return 0;
+}
+
+static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+{
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       unsigned char clkrc;
+       int ret, div;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (cp->extendedmode != 0)
+               return -EINVAL;
+       /*
+        * CLKRC has a reserved bit, so let's preserve it.
+        */
+       ret = ov7670_read(c, REG_CLKRC, &clkrc);
+       if (ret < 0)
+               return ret;
+       if (tpf->numerator == 0 || tpf->denominator == 0)
+               div = 1;  /* Reset to full rate */
+       else
+               div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator;
+       if (div == 0)
+               div = 1;
+       else if (div > CLK_SCALE)
+               div = CLK_SCALE;
+       clkrc = (clkrc & 0x80) | div;
+       tpf->numerator = 1;
+       tpf->denominator = OV7670_FRAME_RATE/div;
+       return ov7670_write(c, REG_CLKRC, clkrc);
+}
+
+
+
+/*
+ * Code for dealing with controls.
+ */
+
+
+
+
+
+static int ov7670_store_cmatrix(struct i2c_client *client,
+               int matrix[CMATRIX_LEN])
+{
+       int i, ret;
+       unsigned char signbits;
+
+       /*
+        * Weird crap seems to exist in the upper part of
+        * the sign bits register, so let's preserve it.
+        */
+       ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits);
+       signbits &= 0xc0;
+
+       for (i = 0; i < CMATRIX_LEN; i++) {
+               unsigned char raw;
+
+               if (matrix[i] < 0) {
+                       signbits |= (1 << i);
+                       if (matrix[i] < -255)
+                               raw = 0xff;
+                       else
+                               raw = (-1 * matrix[i]) & 0xff;
+               }
+               else {
+                       if (matrix[i] > 255)
+                               raw = 0xff;
+                       else
+                               raw = matrix[i] & 0xff;
+               }
+               ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw);
+       }
+       ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits);
+       return ret;
+}
+
+
+/*
+ * Hue also requires messing with the color matrix.  It also requires
+ * trig functions, which tend not to be well supported in the kernel.
+ * So here is a simple table of sine values, 0-90 degrees, in steps
+ * of five degrees.  Values are multiplied by 1000.
+ *
+ * The following naive approximate trig functions require an argument
+ * carefully limited to -180 <= theta <= 180.
+ */
+#define SIN_STEP 5
+static const int ov7670_sin_table[] = {
+          0,    87,   173,   258,   342,   422,
+        499,   573,   642,   707,   766,   819,
+        866,   906,   939,   965,   984,   996,
+       1000
+};
+
+static int ov7670_sine(int theta)
+{
+       int chs = 1;
+       int sine;
+
+       if (theta < 0) {
+               theta = -theta;
+               chs = -1;
+       }
+       if (theta <= 90)
+               sine = ov7670_sin_table[theta/SIN_STEP];
+       else {
+               theta -= 90;
+               sine = 1000 - ov7670_sin_table[theta/SIN_STEP];
+       }
+       return sine*chs;
+}
+
+static int ov7670_cosine(int theta)
+{
+       theta = 90 - theta;
+       if (theta > 180)
+               theta -= 360;
+       else if (theta < -180)
+               theta += 360;
+       return ov7670_sine(theta);
+}
+
+
+
+
+static void ov7670_calc_cmatrix(struct ov7670_info *info,
+               int matrix[CMATRIX_LEN])
+{
+       int i;
+       /*
+        * Apply the current saturation setting first.
+        */
+       for (i = 0; i < CMATRIX_LEN; i++)
+               matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7;
+       /*
+        * Then, if need be, rotate the hue value.
+        */
+       if (info->hue != 0) {
+               int sinth, costh, tmpmatrix[CMATRIX_LEN];
+
+               memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int));
+               sinth = ov7670_sine(info->hue);
+               costh = ov7670_cosine(info->hue);
+
+               matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000;
+               matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000;
+               matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000;
+               matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000;
+               matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000;
+               matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000;
+       }
+}
+
+
+
+static int ov7670_t_sat(struct i2c_client *client, int value)
+{
+       struct ov7670_info *info = i2c_get_clientdata(client);
+       int matrix[CMATRIX_LEN];
+       int ret;
+
+       info->sat = value;
+       ov7670_calc_cmatrix(info, matrix);
+       ret = ov7670_store_cmatrix(client, matrix);
+       return ret;
+}
+
+static int ov7670_q_sat(struct i2c_client *client, __s32 *value)
+{
+       struct ov7670_info *info = i2c_get_clientdata(client);
+
+       *value = info->sat;
+       return 0;
+}
+
+static int ov7670_t_hue(struct i2c_client *client, int value)
+{
+       struct ov7670_info *info = i2c_get_clientdata(client);
+       int matrix[CMATRIX_LEN];
+       int ret;
+
+       if (value < -180 || value > 180)
+               return -EINVAL;
+       info->hue = value;
+       ov7670_calc_cmatrix(info, matrix);
+       ret = ov7670_store_cmatrix(client, matrix);
+       return ret;
+}
+
+
+static int ov7670_q_hue(struct i2c_client *client, __s32 *value)
+{
+       struct ov7670_info *info = i2c_get_clientdata(client);
+
+       *value = info->hue;
+       return 0;
+}
+
+
+/*
+ * Some weird registers seem to store values in a sign/magnitude format!
+ */
+static unsigned char ov7670_sm_to_abs(unsigned char v)
+{
+       if ((v & 0x80) == 0)
+               return v + 128;
+       else
+               return 128 - (v & 0x7f);
+}
+
+
+static unsigned char ov7670_abs_to_sm(unsigned char v)
+{
+       if (v > 127)
+               return v & 0x7f;
+       else
+               return (128 - v) | 0x80;
+}
+
+static int ov7670_t_brightness(struct i2c_client *client, int value)
+{
+       unsigned char com8, v;
+       int ret;
+
+       ov7670_read(client, REG_COM8, &com8);
+       com8 &= ~COM8_AEC;
+       ov7670_write(client, REG_COM8, com8);
+       v = ov7670_abs_to_sm(value);
+       ret = ov7670_write(client, REG_BRIGHT, v);
+       return ret;
+}
+
+static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
+{
+       unsigned char v;
+       int ret = ov7670_read(client, REG_BRIGHT, &v);
+
+       *value = ov7670_sm_to_abs(v);
+       return ret;
+}
+
+static int ov7670_t_contrast(struct i2c_client *client, int value)
+{
+       return ov7670_write(client, REG_CONTRAS, (unsigned char) value);
+}
+
+static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
+{
+       unsigned char v;
+       int ret = ov7670_read(client, REG_CONTRAS, &v);
+
+       *value = v;
+       return ret;
+}
+
+static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
+{
+       int ret;
+       unsigned char v;
+
+       ret = ov7670_read(client, REG_MVFP, &v);
+       *value = (v & MVFP_MIRROR) == MVFP_MIRROR;
+       return ret;
+}
+
+
+static int ov7670_t_hflip(struct i2c_client *client, int value)
+{
+       unsigned char v;
+       int ret;
+
+       ret = ov7670_read(client, REG_MVFP, &v);
+       if (value)
+               v |= MVFP_MIRROR;
+       else
+               v &= ~MVFP_MIRROR;
+       msleep(10);  /* FIXME */
+       ret += ov7670_write(client, REG_MVFP, v);
+       return ret;
+}
+
+
+
+static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
+{
+       int ret;
+       unsigned char v;
+
+       ret = ov7670_read(client, REG_MVFP, &v);
+       *value = (v & MVFP_FLIP) == MVFP_FLIP;
+       return ret;
+}
+
+
+static int ov7670_t_vflip(struct i2c_client *client, int value)
+{
+       unsigned char v;
+       int ret;
+
+       ret = ov7670_read(client, REG_MVFP, &v);
+       if (value)
+               v |= MVFP_FLIP;
+       else
+               v &= ~MVFP_FLIP;
+       msleep(10);  /* FIXME */
+       ret += ov7670_write(client, REG_MVFP, v);
+       return ret;
+}
+
+
+static struct ov7670_control {
+       struct v4l2_queryctrl qc;
+       int (*query)(struct i2c_client *c, __s32 *value);
+       int (*tweak)(struct i2c_client *c, int value);
+} ov7670_controls[] =
+{
+       {
+               .qc = {
+                       .id = V4L2_CID_BRIGHTNESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "Brightness",
+                       .minimum = 0,
+                       .maximum = 255,
+                       .step = 1,
+                       .default_value = 0x80,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+               .tweak = ov7670_t_brightness,
+               .query = ov7670_q_brightness,
+       },
+       {
+               .qc = {
+                       .id = V4L2_CID_CONTRAST,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "Contrast",
+                       .minimum = 0,
+                       .maximum = 127,
+                       .step = 1,
+                       .default_value = 0x40,   /* XXX ov7670 spec */
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+               .tweak = ov7670_t_contrast,
+               .query = ov7670_q_contrast,
+       },
+       {
+               .qc = {
+                       .id = V4L2_CID_SATURATION,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "Saturation",
+                       .minimum = 0,
+                       .maximum = 256,
+                       .step = 1,
+                       .default_value = 0x80,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+               .tweak = ov7670_t_sat,
+               .query = ov7670_q_sat,
+       },
+       {
+               .qc = {
+                       .id = V4L2_CID_HUE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "HUE",
+                       .minimum = -180,
+                       .maximum = 180,
+                       .step = 5,
+                       .default_value = 0,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+               .tweak = ov7670_t_hue,
+               .query = ov7670_q_hue,
+       },
+       {
+               .qc = {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "Vertical flip",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+               },
+               .tweak = ov7670_t_vflip,
+               .query = ov7670_q_vflip,
+       },
+       {
+               .qc = {
+                       .id = V4L2_CID_HFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "Horizontal mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+               },
+               .tweak = ov7670_t_hflip,
+               .query = ov7670_q_hflip,
+       },
+};
+#define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0]))
+
+static struct ov7670_control *ov7670_find_control(__u32 id)
+{
+       int i;
+
+       for (i = 0; i < N_CONTROLS; i++)
+               if (ov7670_controls[i].qc.id == id)
+                       return ov7670_controls + i;
+       return NULL;
+}
+
+
+static int ov7670_queryctrl(struct i2c_client *client,
+               struct v4l2_queryctrl *qc)
+{
+       struct ov7670_control *ctrl = ov7670_find_control(qc->id);
+
+       if (ctrl == NULL)
+               return -EINVAL;
+       *qc = ctrl->qc;
+       return 0;
+}
+
+static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
+       int ret;
+
+       if (octrl == NULL)
+               return -EINVAL;
+       ret = octrl->query(client, &ctrl->value);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
+
+static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
+       int ret;
+
+       if (octrl == NULL)
+               return -EINVAL;
+       ret =  octrl->tweak(client, ctrl->value);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
+
+
+
+
+
+
+/*
+ * Basic i2c stuff.
+ */
+static struct i2c_driver ov7670_driver;
+
+static int ov7670_attach(struct i2c_adapter *adapter)
+{
+       int ret;
+       struct i2c_client *client;
+       struct ov7670_info *info;
+
+       /*
+        * For now: only deal with adapters we recognize.
+        */
+       if (adapter->id != I2C_HW_SMBUS_CAFE)
+               return -ENODEV;
+
+       client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL);
+       if (! client)
+               return -ENOMEM;
+       client->adapter = adapter;
+       client->addr = OV7670_I2C_ADDR;
+       client->driver = &ov7670_driver,
+       strcpy(client->name, "OV7670");
+       /*
+        * Set up our info structure.
+        */
+       info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL);
+       if (! info) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       info->fmt = &ov7670_formats[0];
+       info->sat = 128;        /* Review this */
+       i2c_set_clientdata(client, info);
+
+       /*
+        * Make sure it's an ov7670
+        */
+       ret = ov7670_detect(client);
+       if (ret)
+               goto out_free_info;
+       i2c_attach_client(client);
+       return 0;
+
+  out_free_info:
+       kfree(info);
+  out_free:
+       kfree(client);
+       return ret;
+}
+
+
+static int ov7670_detach(struct i2c_client *client)
+{
+       i2c_detach_client(client);
+       kfree(i2c_get_clientdata(client));
+       kfree(client);
+       return 0;
+}
+
+
+static int ov7670_command(struct i2c_client *client, unsigned int cmd,
+               void *arg)
+{
+       switch (cmd) {
+       case VIDIOC_INT_G_CHIP_IDENT:
+               * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670;
+               return 0;
+
+       case VIDIOC_INT_RESET:
+               ov7670_reset(client);
+               return 0;
+
+       case VIDIOC_INT_INIT:
+               return ov7670_init(client);
+
+       case VIDIOC_ENUM_FMT:
+               return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg);
+       case VIDIOC_TRY_FMT:
+               return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL);
+       case VIDIOC_S_FMT:
+               return ov7670_s_fmt(client, (struct v4l2_format *) arg);
+       case VIDIOC_QUERYCTRL:
+               return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg);
+       case VIDIOC_S_CTRL:
+               return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
+       case VIDIOC_G_CTRL:
+               return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
+       case VIDIOC_S_PARM:
+               return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
+       case VIDIOC_G_PARM:
+               return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
+       }
+       return -EINVAL;
+}
+
+
+
+static struct i2c_driver ov7670_driver = {
+       .driver = {
+               .name = "ov7670",
+       },
+       .id             = I2C_DRIVERID_OV7670,
+       .class          = I2C_CLASS_CAM_DIGITAL,
+       .attach_adapter = ov7670_attach,
+       .detach_client  = ov7670_detach,
+       .command        = ov7670_command,
+};
+
+
+/*
+ * Module initialization
+ */
+static int __init ov7670_mod_init(void)
+{
+       printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n");
+       return i2c_add_driver(&ov7670_driver);
+}
+
+static void __exit ov7670_mod_exit(void)
+{
+       i2c_del_driver(&ov7670_driver);
+}
+
+module_init(ov7670_mod_init);
+module_exit(ov7670_mod_exit);
index f129f31..cf12974 100644 (file)
@@ -45,16 +45,21 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp)
 }
 
 
-static void pvr2_context_poll(struct pvr2_context *mp)
+static void pvr2_context_poll(struct work_struct *work)
 {
+       struct pvr2_context *mp =
+               container_of(work, struct pvr2_context, workpoll);
        pvr2_context_enter(mp); do {
                pvr2_hdw_poll(mp->hdw);
        } while (0); pvr2_context_exit(mp);
 }
 
 
-static void pvr2_context_setup(struct pvr2_context *mp)
+static void pvr2_context_setup(struct work_struct *work)
 {
+       struct pvr2_context *mp =
+               container_of(work, struct pvr2_context, workinit);
+
        pvr2_context_enter(mp); do {
                if (!pvr2_hdw_dev_ok(mp->hdw)) break;
                pvr2_hdw_setup(mp->hdw);
@@ -92,8 +97,8 @@ struct pvr2_context *pvr2_context_create(
        }
 
        mp->workqueue = create_singlethread_workqueue("pvrusb2");
-       INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
-       INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
+       INIT_WORK(&mp->workinit, pvr2_context_setup);
+       INIT_WORK(&mp->workpoll, pvr2_context_poll);
        queue_work(mp->workqueue,&mp->workinit);
  done:
        return mp;
index c80c26b..848fb23 100644 (file)
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
                                  sizeof(decoder_ops[0]))) - 1;
        hdw->decoder_ctrl = &ctxt->ctrl;
        cp->handler = &ctxt->handler;
+       {
+               /*
+                 Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
+                 of nuttiness for cx25840 causes that module to
+                 correctly set up its video scaling.  This is really
+                 a problem in the cx25840 module itself, but we work
+                 around it here.  The problem has not been seen in
+                 ivtv because there VBI is supported and set up.  We
+                 don't do VBI here (at least not yet) and thus we
+                 never attempted to even set it up.
+                */
+               struct v4l2_format fmt;
+               memset(&fmt,0,sizeof(fmt));
+               fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+               pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
+       }
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
                   cp->client->addr);
        return !0;
index 1f78733..d200496 100644 (file)
@@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
        return 0;
 }
 
-static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       /* If we're dealing with a 24xxx device, force the horizontal
-          maximum to be 720 no matter what, since we can't get the device
-          to work properly with any other value.  Otherwise just return
-          the normal value. */
-       *vp = cptr->info->def.type_int.max_value;
-       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
-       return 0;
-}
-
-static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       /* If we're dealing with a 24xxx device, force the horizontal
-          minimum to be 720 no matter what, since we can't get the device
-          to work properly with any other value.  Otherwise just return
-          the normal value. */
-       *vp = cptr->info->def.type_int.min_value;
-       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
-       return 0;
-}
-
 static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
 {
        /* Actual maximum depends on the video standard in effect. */
@@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = {
                .default_value = 720,
                DEFREF(res_hor),
                DEFINT(19,720),
-               /* Hook in check for clamp on horizontal resolution in
-                  order to avoid unsolved problem involving cx25840. */
-               .get_max_value = ctrl_hres_max_get,
-               .get_min_value = ctrl_hres_min_get,
        },{
                .desc = "Vertical capture resolution",
                .name = "resolution_ver",
index 3b9012f..f9bb41d 100644 (file)
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
        }
 }
 
+
+/* This is a special entry point for cases of I2C transaction attempts to
+   the IR receiver.  The implementation here simulates the IR receiver by
+   issuing a command to the FX2 firmware and using that response to return
+   what the real I2C receiver would have returned.  We use this for 24xxx
+   devices, where the IR receiver chip has been removed and replaced with
+   FX2 related logic. */
+static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
+                       u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       u8 dat[4];
+       unsigned int stat;
+
+       if (!(rlen || wlen)) {
+               /* This is a probe attempt.  Just let it succeed. */
+               return 0;
+       }
+
+       /* We don't understand this kind of transaction */
+       if ((wlen != 0) || (rlen == 0)) return -EIO;
+
+       if (rlen < 3) {
+               /* Mike Isely <isely@pobox.com> Appears to be a probe
+                  attempt from lirc.  Just fill in zeroes and return.  If
+                  we try instead to do the full transaction here, then bad
+                  things seem to happen within the lirc driver module
+                  (version 0.8.0-7 sources from Debian, when run under
+                  vanilla 2.6.17.6 kernel) - and I don't have the patience
+                  to chase it down. */
+               if (rlen > 0) rdata[0] = 0;
+               if (rlen > 1) rdata[1] = 0;
+               return 0;
+       }
+
+       /* Issue a command to the FX2 to read the IR receiver. */
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = 0xec;
+               stat = pvr2_send_request(hdw,
+                                        hdw->cmd_buffer,1,
+                                        hdw->cmd_buffer,4);
+               dat[0] = hdw->cmd_buffer[0];
+               dat[1] = hdw->cmd_buffer[1];
+               dat[2] = hdw->cmd_buffer[2];
+               dat[3] = hdw->cmd_buffer[3];
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
+
+       /* Give up if that operation failed. */
+       if (stat != 0) return stat;
+
+       /* Mangle the results into something that looks like the real IR
+          receiver. */
+       rdata[2] = 0xc1;
+       if (dat[0] != 1) {
+               /* No code received. */
+               rdata[0] = 0;
+               rdata[1] = 0;
+       } else {
+               u16 val;
+               /* Mash the FX2 firmware-provided IR code into something
+                  that the normal i2c chip-level driver expects. */
+               val = dat[1];
+               val <<= 8;
+               val |= dat[2];
+               val >>= 1;
+               val &= ~0x0003;
+               val |= 0x8000;
+               rdata[0] = (val >> 8) & 0xffu;
+               rdata[1] = val & 0xffu;
+       }
+
+       return 0;
+}
+
 /* This is a special entry point that is entered if an I2C operation is
    attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
    part doesn't work, but we know it is really there.  So let's look for
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
 {
        unsigned int idx;
 
-       // The default action for all possible I2C addresses is just to do
-       // the transfer normally.
+       /* The default action for all possible I2C addresses is just to do
+          the transfer normally. */
        for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
                hdw->i2c_func[idx] = pvr2_i2c_basic_op;
        }
 
-       // If however we're dealing with new hardware, insert some hacks in
-       // the I2C transfer stack to let things work better.
+       /* However, deal with various special cases for 24xxx hardware. */
        if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
                hdw->i2c_func[0x1b] = i2c_hack_wm8775;
                hdw->i2c_func[0x44] = i2c_hack_cx25840;
+               hdw->i2c_func[0x18] = i2c_24xxx_ir;
        }
 
        // Configure the adapter and set up everything else related to it.
index 7b9859c..92eabf8 100644 (file)
@@ -324,9 +324,9 @@ static void saa6588_timer(unsigned long data)
        schedule_work(&s->work);
 }
 
-static void saa6588_work(void *data)
+static void saa6588_work(struct work_struct *work)
 {
-       struct saa6588 *s = (struct saa6588 *)data;
+       struct saa6588 *s = container_of(work, struct saa6588, work);
 
        saa6588_i2c_poll(s);
        mod_timer(&s->timer, jiffies + msecs_to_jiffies(20));
@@ -419,7 +419,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
        saa6588_configure(s);
 
        /* start polling via eventd */
-       INIT_WORK(&s->work, saa6588_work, s);
+       INIT_WORK(&s->work, saa6588_work);
        init_timer(&s->timer);
        s->timer.function = saa6588_timer;
        s->timer.data = (unsigned long)s;
index f28398d..c2374ed 100644 (file)
@@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
 
        /* On 60Hz, it is using a higher Vertical Output Size */
        if (!is_50hz)
-               res+=(VRES_60HZ-480)>>1;
+               res += (VRES_60HZ - 480) >> 1;
 
                /* height */
        saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
@@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
 
        /* Activates task "B" */
        saa711x_write(client, R_80_GLOBAL_CNTL_1,
-                               saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
+                               saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20);
 
        return 0;
 }
@@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
        if (std & V4L2_STD_525_60) {
                v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
                saa711x_writeregs(client, saa7115_cfg_60hz_video);
-               saa711x_set_size(client,720,480);
+               saa711x_set_size(client, 720, 480);
        } else {
                v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
                saa711x_writeregs(client, saa7115_cfg_50hz_video);
-               saa711x_set_size(client,720,576);
+               saa711x_set_size(client, 720, 576);
        }
 
        /* Register 0E - Bits D6-D4 on NO-AUTO mode
@@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
        client->driver = &i2c_driver_saa711x;
        snprintf(client->name, sizeof(client->name) - 1, "saa7115");
 
-       for (i=0;i<0x0f;i++) {
+       for (i = 0; i < 0x0f; i++) {
                saa711x_write(client, 0, i);
-               name[i] = (saa711x_read(client, 0) &0x0f) +'0';
-               if (name[i]>'9')
-                       name[i]+='a'-'9'-1;
+               name[i] = (saa711x_read(client, 0) & 0x0f) + '0';
+               if (name[i] > '9')
+                       name[i] += 'a' - '9' - 1;
        }
-       name[i]='\0';
+       name[i] = '\0';
 
        saa711x_write(client, 0, 5);
        chip_id = saa711x_read(client, 0) & 0x0f;
index 4abf5c0..ffb0f64 100644 (file)
@@ -1,10 +1,6 @@
 /*
  *   SAA713x ALSA support for V4L
  *
- *
- *   Caveats:
- *        - Volume doesn't work (it's always at max)
- *
  *   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
@@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
        snd_card_saa7134_pcm_t *pcm;
        snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
        struct saa7134_dev *dev = saa7134->dev;
-       int err;
+       int amux, err;
 
        mutex_lock(&dev->dmasound.lock);
 
        dev->dmasound.read_count  = 0;
        dev->dmasound.read_offset = 0;
 
+       amux = dev->input->amux;
+       if ((amux < 1) || (amux > 3))
+               amux = 1;
+       dev->dmasound.input  =  amux - 1;
+
        mutex_unlock(&dev->dmasound.lock);
 
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
@@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
                                  struct snd_ctl_elem_value * ucontrol)
 {
        snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+       struct saa7134_dev *dev = chip->dev;
+
        int change, addr = kcontrol->private_value;
        int left, right;
 
@@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
        if (right > 20)
                right = 20;
        spin_lock_irq(&chip->mixer_lock);
-       change = chip->mixer_volume[addr][0] != left ||
-                chip->mixer_volume[addr][1] != right;
-       chip->mixer_volume[addr][0] = left;
-       chip->mixer_volume[addr][1] = right;
+       change = 0;
+       if (chip->mixer_volume[addr][0] != left) {
+               change = 1;
+               right = left;
+       }
+       if (chip->mixer_volume[addr][1] != right) {
+               change = 1;
+               left = right;
+       }
+       if (change) {
+               switch (dev->pci->device) {
+                       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+                               switch (addr) {
+                                       case MIXER_ADDR_TVTUNER:
+                                               left = 20;
+                                               break;
+                                       case MIXER_ADDR_LINE1:
+                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
+                                                          (left > 10) ? 0x00 : 0x10);
+                                               break;
+                                       case MIXER_ADDR_LINE2:
+                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
+                                                          (left > 10) ? 0x00 : 0x20);
+                                               break;
+                               }
+                               break;
+                       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+                       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+                               switch (addr) {
+                                       case MIXER_ADDR_TVTUNER:
+                                               left = 20;
+                                               break;
+                                       case MIXER_ADDR_LINE1:
+                                               saa_andorb(0x0594,  0x10,
+                                                          (left > 10) ? 0x00 : 0x10);
+                                               break;
+                                       case MIXER_ADDR_LINE2:
+                                               saa_andorb(0x0594,  0x20,
+                                                          (left > 10) ? 0x00 : 0x20);
+                                               break;
+                               }
+                               break;
+               }
+               chip->mixer_volume[addr][0] = left;
+               chip->mixer_volume[addr][1] = right;
+       }
        spin_unlock_irq(&chip->mixer_lock);
        return change;
 }
index 51f0cfd..4dead84 100644 (file)
@@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = {
                        .vmux = 1,
                        .amux = TV,
                        .tv   = 1,
+                       .gpio = 0x0000000,
                },{
                        .name = name_comp1,
                        .vmux = 3,
                        .amux = LINE2,
+                       .gpio = 0x0200000,
                },{
                        .name = name_svideo,
                        .vmux = 8,
                        .amux = LINE2,
+                       .gpio = 0x0200000,
                }},
                .radio = {
                        .name = name_radio,
@@ -3022,6 +3025,158 @@ struct saa7134_board saa7134_boards[] = {
                        .amux   = LINE1,
                },
        },
+       [SAA7134_BOARD_PINNACLE_PCTV_310i] = {
+               .name           = "Pinnacle PCTV 310i",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x000200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
+               /* Mikhail Fedotov <mo_fedotov@mail.ru> */
+               .name           = "Avermedia AVerTV Studio 507",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x03,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x01,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
+               /* Francis Barber <fedora@barber-family.id.au> */
+               .name           = "Compro Videomate DVB-T200A",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
+               /* Thomas Genty <tomlohave@gmail.com> */
+               .name           = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE2, /* FIXME: audio doesn't work on svideo/composite */
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2, /* FIXME: audio doesn't work on svideo/composite */
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux   = TV,
+               },
+       },
+       [SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
+               .name           = "Terratec Cinergy HT PCMCIA",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 6,
+                       .amux   = LINE1,
+               }},
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3630,6 +3785,36 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x1043,
                .subdevice    = 0x4860,
                .driver_data  = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x11bd,
+               .subdevice    = 0x002f,
+               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_310i,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x9715,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4876,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6701,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1172,
+               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
        },{
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -3717,6 +3902,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_305:
        case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
        case SAA7134_BOARD_AVERMEDIA_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
        case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
        case SAA7134_BOARD_AVERMEDIA_777:
 /*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
@@ -3725,6 +3911,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
        case SAA7134_BOARD_MANLI_MTV001:
        case SAA7134_BOARD_MANLI_MTV002:
        case SAA7134_BOARD_BEHOLD_409FM:
@@ -3793,7 +3980,9 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                break;
        /* i2c remotes */
        case SAA7134_BOARD_PINNACLE_PCTV_110i:
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
        case SAA7134_BOARD_UPMOST_PURPLE_TV:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
                dev->has_remote = SAA7134_REMOTE_I2C;
                break;
        case SAA7134_BOARD_AVERMEDIA_A169_B:
@@ -3924,9 +4113,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
        case SAA7134_BOARD_TEVION_DVBT_220RF:
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
                /* this is a hybrid board, initialize to analog mode
                 * and configure firmware eeprom address
                 */
@@ -3952,6 +4143,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                i2c_transfer(&dev->i2c_adap, &msg, 1);
                }
                break;
+       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+               /* make the tda10046 find its eeprom */
+               {
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               }
+               break;
        case SAA7134_BOARD_KWORLD_ATSC110:
                {
                        /* enable tuner */
@@ -3964,6 +4163,29 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                                               dev->name, i);
                }
                break;
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+               /* The T200 and the T200A share the same pci id.  Consequently,
+                * we are going to query eeprom to try to find out which one we
+                * are actually looking at. */
+
+               /* Don't do this if the board was specifically selected with an
+                * insmod option or if we have the default configuration T200*/
+               if(!dev->autodetected || (dev->eedata[0x41] == 0xd0))
+                       break;
+               if(dev->eedata[0x41] == 0x02) {
+                       /* Reconfigure board  as T200A */
+                       dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
+                       dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+                       dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
+                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
+                               dev->name, saa7134_boards[dev->board].name);
+               } else {
+                       printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
+                               dev->name, dev->eedata[0x41]);
+                       break;
+               }
+               break;
        }
        return 0;
 }
index 5c9e63d..ed038ff 100644 (file)
@@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                must_configure_manually();
                dev->board = SAA7134_BOARD_UNKNOWN;
        }
+       dev->autodetected = card[dev->nr] != dev->board;
        dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
        dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
        if (UNSET != tuner[dev->nr])
                dev->tuner_type = tuner[dev->nr];
-       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-              dev->name,pci_dev->subsystem_vendor,
-              pci_dev->subsystem_device,saa7134_boards[dev->board].name,
-              dev->board, card[dev->nr] == dev->board ?
-              "insmod option" : "autodetected");
+               printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               dev->name,pci_dev->subsystem_vendor,
+               pci_dev->subsystem_device,saa7134_boards[dev->board].name,
+               dev->board, dev->autodetected ?
+               "autodetected" : "insmod option");
 
        /* get mmio */
        if (!request_mem_region(pci_resource_start(pci_dev,0),
index 6b61d9b..fa83398 100644 (file)
@@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0;
 module_param(antenna_pwr, int, 0444);
 MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
 
+static int use_frontent = 0;
+module_param(use_frontent, int, 0644);
+MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+
 /* ------------------------------------------------------------------ */
 static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
 {
@@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv
        return philips_tda6651_pll_set(0x60, fe, params);
 }
 
-static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
+static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
                                           const struct firmware **fw, char *name)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .request_firmware = philips_tu1216_request_firmware,
+       .request_firmware = philips_tda1004x_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
@@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .request_firmware = philips_tu1216_request_firmware,
+       .request_firmware = philips_tda1004x_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_europa_tuner_init(struct dvb_frontend *fe)
+static int philips_td1316_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
@@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
                return -EIO;
-       msleep(1);
-
-       /* switch the board to dvb mode */
-       init_msg.addr = 0x43;
-       init_msg.len  = 0x02;
-       msg[0] = 0x00;
-       msg[1] = 0x40;
        if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
-               return -EIO;
-
+               fe->ops.i2c_gate_ctrl(fe, 0);
        return 0;
 }
 
@@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
        return philips_tda6651_pll_set(0x61, fe, params);
 }
 
+static int philips_europa_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 msg[] = { 0x00, 0x40};
+       struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+
+       if (philips_td1316_tuner_init(fe))
+               return -EIO;
+       msleep(1);
+       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+               return -EIO;
+
+       return 0;
+}
+
 static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
@@ -812,32 +822,40 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
        return 0;
 }
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
-       int ret;
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 tda8290_close[] = { 0x21, 0xc0};
        static u8 tda8290_open[]  = { 0x21, 0x80};
        struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
-
-       /* close tda8290 i2c bridge */
-       tda8290_msg.buf = tda8290_close;
-       ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
-       if (ret != 1)
+       if (enable) {
+               tda8290_msg.buf = tda8290_close;
+       } else {
+               tda8290_msg.buf = tda8290_open;
+       }
+       if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1)
                return -EIO;
        msleep(20);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       int ret;
+
        ret = philips_tda827xa_pll_set(0x61, fe, params);
        if (ret != 0)
                return ret;
-       /* open tda8290 i2c bridge */
-       tda8290_msg.buf = tda8290_open;
-       i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
-       return ret;
+       return 0;
 }
 
 static int philips_tiger_tuner_init(struct dvb_frontend *fe)
@@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
+       .if_freq       = TDA10046_FREQ_045,
+       .request_firmware = NULL,
+};
+/* ------------------------------------------------------------------ */
+
+static int cinergy_ht_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 data[] = { 0x3c, 0x33, 0x62};
+       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+               return -EIO;
+       return 0;
+}
+
+static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 data[] = { 0x3c, 0x33, 0x60};
+       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+       i2c_transfer(&dev->i2c_adap, &msg, 1);
+       philips_tda827xa_tuner_sleep( 0x61, fe);
+       return 0;
+}
+
+static struct tda1004x_config cinergy_ht_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X_GP01,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
+static struct tda1004x_config pinnacle_pctv_310i_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
+       .if_freq       = TDA10046_FREQ_045,
+       .request_firmware = philips_tda1004x_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct tda1004x_config hauppauge_hvr_1110_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
+       .if_freq       = TDA10046_FREQ_045,
+       .request_firmware = philips_tda1004x_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct tda1004x_config asus_p7131_dual_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
+       .if_freq       = TDA10046_FREQ_045,
+       .request_firmware = philips_tda1004x_request_firmware,
+};
+
 static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X_GPL,
+       .agc_config    = TDA10046_AGC_TDA827X_GP00,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
@@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X_GPL,
+       .agc_config    = TDA10046_AGC_TDA827X_GP00,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
@@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
@@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = {
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
+       .agc_config    = TDA10046_AGC_TDA827X_GP11,
        .if_freq       = TDA10046_FREQ_045,
        .request_firmware = NULL,
 };
@@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev)
                                               &philips_tiger_config,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &pinnacle_pctv_310i_config,
+                                              &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &hauppauge_hvr_1110_config,
+                                              &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
                        dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
@@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev)
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
                dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_tiger_config,
+                                              &asus_p7131_dual_config,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
                        dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep;
                        dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
@@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &lifeview_trio_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
+               if(! use_frontent) {    //terrestrial
+                       dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                                      &lifeview_trio_config,
+                                                      &dev->i2c_adap);
+                       if (dev->dvb.frontend) {
+                               dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
+                               dev->dvb.frontend->ops.tuner_ops.set_params =
+                                                               lifeview_trio_tuner_set_params;
+                       }
+               } else {              //satellite
+                       dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+                       if (dev->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+                                                                       &dev->i2c_adap, 0) == NULL) {
+                                       printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
+                               }
+                               if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+                                                                               0x08, 0, 0) == NULL) {
+                                       printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
+                               }
+                       }
                }
                break;
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
@@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev)
                        dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
                }
                break;
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                               &philips_europa_config,
+                               &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &cinergy_ht_config,
+                                              &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+                       dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
 
+               }
+               break;
        default:
                printk("%s: Huh? unknown DVB card?\n",dev->name);
                break;
index 65d0440..daaae87 100644 (file)
@@ -343,9 +343,10 @@ static struct video_device saa7134_empress_template =
        .minor         = -1,
 };
 
-static void empress_signal_update(void* data)
+static void empress_signal_update(struct work_struct *work)
 {
-       struct saa7134_dev* dev = (struct saa7134_dev*) data;
+       struct saa7134_dev* dev =
+               container_of(work, struct saa7134_dev, empress_workqueue);
 
        if (dev->nosignal) {
                dprintk("no video signal\n");
@@ -378,7 +379,7 @@ static int empress_init(struct saa7134_dev *dev)
                 "%s empress (%s)", dev->name,
                 saa7134_boards[dev->board].name);
 
-       INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev);
+       INIT_WORK(&dev->empress_workqueue, empress_signal_update);
 
        err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
                                    empress_nr[dev->nr]);
@@ -399,7 +400,7 @@ static int empress_init(struct saa7134_dev *dev)
                            sizeof(struct saa7134_buf),
                            dev);
 
-       empress_signal_update(dev);
+       empress_signal_update(&dev->empress_workqueue);
        return 0;
 }
 
index 6162550..6f9fe86 100644 (file)
@@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client)
        switch (client->addr) {
                case 0x7a:
                case 0x47:
+               case 0x71:
                {
                        struct IR_i2c *ir = i2c_get_clientdata(client);
                        d1printk("%s i2c IR detected (%s).\n",
index dee8355..60b38de 100644 (file)
@@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        return 1;
 }
 
+static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char buf[5], cod4, code3, code4;
+
+       /* poll IR chip */
+       if (5 != i2c_master_recv(&ir->c,buf,5))
+               return -EIO;
+
+       cod4    = buf[4];
+       code4   = (cod4 >> 2);
+       code3   = buf[3];
+       if (code3 == 0)
+               /* no key pressed */
+               return 0;
+
+       /* return key */
+       *ir_key = code4;
+       *ir_raw = code4;
+       return 1;
+}
+
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
        struct saa7134_ir *ir = dev->remote;
@@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data)
        mod_timer(&ir->timer, timeout);
 }
 
+static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
+{
+       if (ir->polling) {
+               init_timer(&ir->timer);
+               ir->timer.function = saa7134_input_timer;
+               ir->timer.data     = (unsigned long)dev;
+               ir->timer.expires  = jiffies + HZ;
+               add_timer(&ir->timer);
+       }
+}
+
+static void saa7134_ir_stop(struct saa7134_dev *dev)
+{
+       if (dev->remote->polling)
+               del_timer_sync(&dev->remote->timer);
+}
+
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
        struct saa7134_ir *ir;
@@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        u32 mask_keyup   = 0;
        int polling      = 0;
        int ir_type      = IR_TYPE_OTHER;
+       int err;
 
        if (dev->has_remote != SAA7134_REMOTE_GPIO)
                return -ENODEV;
@@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_307:
        case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
        case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
        case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
                ir_codes     = ir_codes_avermedia;
                mask_keycode = 0x0007C8;
@@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
 
        ir->dev = input_dev;
@@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        }
        input_dev->cdev.dev = &dev->pci->dev;
 
-       /* all done */
        dev->remote = ir;
-       if (ir->polling) {
-               init_timer(&ir->timer);
-               ir->timer.function = saa7134_input_timer;
-               ir->timer.data     = (unsigned long)dev;
-               ir->timer.expires  = jiffies + HZ;
-               add_timer(&ir->timer);
-       }
+       saa7134_ir_start(dev, ir);
+
+       err = input_register_device(ir->dev);
+       if (err)
+               goto err_out_stop;
 
-       input_register_device(ir->dev);
        return 0;
+
+ err_out_stop:
+       saa7134_ir_stop(dev);
+       dev->remote = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 void saa7134_input_fini(struct saa7134_dev *dev)
@@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
        if (NULL == dev->remote)
                return;
 
-       if (dev->remote->polling)
-               del_timer_sync(&dev->remote->timer);
+       saa7134_ir_stop(dev);
        input_unregister_device(dev->remote->dev);
        kfree(dev->remote);
        dev->remote = NULL;
@@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
 
        switch (dev->board) {
        case SAA7134_BOARD_PINNACLE_PCTV_110i:
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
                snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
                if (pinnacle_remote == 0) {
                        ir->get_key   = get_key_pinnacle_color;
@@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
                ir->get_key   = get_key_purpletv;
                ir->ir_codes  = ir_codes_purpletv;
                break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+               snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
+               ir->get_key   = get_key_hvr1110;
+               ir->ir_codes  = ir_codes_hauppauge_new;
+               break;
        default:
                dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
                break;
index 7cf96b4..e88ad7b 100644 (file)
@@ -227,6 +227,11 @@ struct saa7134_format {
 #define SAA7134_BOARD_PROTEUS_2309 98
 #define SAA7134_BOARD_AVERMEDIA_A16AR   99
 #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
+#define SAA7134_BOARD_PINNACLE_PCTV_310i  101
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
+#define SAA7134_BOARD_VIDEOMATE_DVBT_200A  103
+#define SAA7134_BOARD_HAUPPAUGE_HVR1110    104
+#define SAA7134_BOARD_CINERGY_HT_PCMCIA    105
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -446,6 +451,9 @@ struct saa7134_dev {
        struct v4l2_prio_state     prio;
 #endif
 
+       /* insmod option/autodetected */
+       int                        autodetected;
+
        /* various device info */
        unsigned int               resources;
        struct video_device        *video_dev;
index 6d1ef1e..a1ec3ac 100644 (file)
@@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
                stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
                if (stv680->sbuf[i].data == NULL) {
                        PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
-                       return -1;
+                       goto nomem_err;
                }
        }
 
@@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
                stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
                if (stv680->scratch[i].data == NULL) {
                        PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
-                       return -1;
+                       goto nomem_err;
                }
                stv680->scratch[i].state = BUFFER_UNUSED;
        }
@@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
        for (i = 0; i < STV680_NUMSBUF; i++) {
                urb = usb_alloc_urb (0, GFP_KERNEL);
                if (!urb)
-                       return -ENOMEM;
+                       goto nomem_err;
 
                /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
                usb_fill_bulk_urb (urb, stv680->udev,
@@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680)
 
        stv680->framecount = 0;
        return 0;
+
+ nomem_err:
+       for (i = 0; i < STV680_NUMSCRATCH; i++) {
+               kfree(stv680->scratch[i].data);
+               stv680->scratch[i].data = NULL;
+       }
+       for (i = 0; i < STV680_NUMSBUF; i++) {
+               usb_kill_urb(stv680->urb[i]);
+               usb_free_urb(stv680->urb[i]);
+               stv680->urb[i] = NULL;
+               kfree(stv680->sbuf[i].data);
+               stv680->sbuf[i].data = NULL;
+       }
+       return -ENOMEM;
+
 }
 
 static int stv680_stop_stream (struct usb_stv *stv680)
index 87ffb0e..fde576f 100644 (file)
@@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf)
                buf[1] &= ~cQSS;
        if (t->tda9887_config & TDA9887_GATING_18)
                buf[3] &= ~cGating_36;
+
+       if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
+               radio_stereo.e &= ~cTunerGainLow;
+               radio_mono.e &= ~cTunerGainLow;
+       }
+
        return 0;
 }
 
index 40590ba..705daaa 100644 (file)
@@ -443,6 +443,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
                        printk("%02x ",buffer[i]);
                printk("\n");
        }
+       /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */
+       if (adap->id == I2C_HW_SAA7146 && addr < 0x4a)
+               return -ENODEV;
+
        /* autodetection code based on the i2c addr */
        if (!no_autodetect) {
                switch (addr) {
index 63db4e9..1b9b074 100644 (file)
@@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c)
                case TUNER_PHILIPS_FM1216ME_MK3:
                case TUNER_PHILIPS_FM1236_MK3:
                case TUNER_PHILIPS_FM1256_IH3:
+               case TUNER_LG_NTSC_TAPE:
                        stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
                        break;
                default:
@@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
        case TUNER_PHILIPS_FM1216ME_MK3:
        case TUNER_PHILIPS_FM1236_MK3:
        case TUNER_PHILIPS_FMD1216ME_MK3:
+       case TUNER_LG_NTSC_TAPE:
                buffer[3] = 0x19;
                break;
        case TUNER_TNF_5335MF:
@@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
                        config |= TDA9887_INTERCARRIER;
 /*             if (params->port1_set_for_fm_mono)
                        config &= ~TDA9887_PORT1_ACTIVE;*/
+               if (params->fm_gain_normal)
+                       config |= TDA9887_GAIN_NORMAL;
                i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
        }
        if (4 != (rc = i2c_master_send(c,buffer,4)))
index 7816823..74c3e6f 100644 (file)
@@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
                .has_tda9887 = 1,
                .port1_invert_for_secam_lc = 1,
                .default_pll_gating_18 = 1,
+               .fm_gain_normal=1,
        },
 };
 
@@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = {
        },
 };
 
-/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
-
-static struct tuner_params tuner_lg_ntsc_tape_params[] = {
-       {
-               .type   = TUNER_PARAM_TYPE_NTSC,
-               .ranges = tuner_fm1236_mk3_ntsc_ranges,
-               .count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-       },
-};
-
 /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
 
 static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
@@ -1331,8 +1322,8 @@ struct tunertype tuners[] = {
        },
        [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
                .name   = "LG NTSC (TAPE series)",
-               .params = tuner_lg_ntsc_tape_params,
-               .count  = ARRAY_SIZE(tuner_lg_ntsc_tape_params),
+               .params = tuner_fm1236_mk3_params,
+               .count  = ARRAY_SIZE(tuner_fm1236_mk3_params),
        },
        [TUNER_TNF_8831BGFF] = { /* Philips PAL */
                .name   = "Tenna TNF 8831 BGFF)",
index fcaef4b..d506dfa 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <media/tvaudio.h>
 #include <media/v4l2-common.h>
index 6b9ef73..2624e3f 100644 (file)
@@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        tvee->has_radio = eeprom_data[i+len-1];
                        /* old style tag, don't know how to detect
                        IR presence, mark as unknown. */
-                       tvee->has_ir = 2;
+                       tvee->has_ir = -1;
                        tvee->model =
                                eeprom_data[i+8] +
                                (eeprom_data[i+9] << 8);
@@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        STRM(decoderIC, tvee->decoder_processor),
                        tvee->decoder_processor);
        }
-       if (tvee->has_ir == 2)
+       if (tvee->has_ir == -1)
                tveeprom_info("has %sradio\n",
                                tvee->has_radio ? "" : "no ");
        else
-               tveeprom_info("has %sradio, has %sIR remote\n",
+               tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
                                tvee->has_radio ? "" : "no ",
-                               tvee->has_ir ? "" : "no ");
+                               (tvee->has_ir & 1) ? "" : "no ",
+                               (tvee->has_ir & 2) ? "" : "no ");
 }
 EXPORT_SYMBOL(tveeprom_hauppauge_analog);
 
index bbf2bee..ec0ff22 100644 (file)
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table);
 static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
 {
        struct input_dev *input_dev;
+       int error;
 
        usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
        strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
 
        input_dev->private = cam;
 
-       input_register_device(cam->input);
+       error = input_register_device(cam->input);
+       if (error) {
+               warn("Failed to register camera's input device, err: %d\n",
+                    error);
+               input_free_device(cam->input);
+               cam->input = NULL;
+       }
 }
 
 static void qcm_unregister_input(struct qcm *cam)
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig
new file mode 100644 (file)
index 0000000..fc24ef0
--- /dev/null
@@ -0,0 +1,12 @@
+config VIDEO_USBVISION
+       tristate "USB video devices based on Nogatech NT1003/1004/1005"
+       depends on I2C && VIDEO_V4L2
+       select VIDEO_TUNER
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       ---help---
+         There are more than 50 different USB video devices based on
+         NT1003/1004/1005 USB Bridges. This driver enables using those
+         devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called usbvision.
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
new file mode 100644 (file)
index 0000000..9ac92a8
--- /dev/null
@@ -0,0 +1,5 @@
+usbvision-objs  := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o
+
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
new file mode 100644 (file)
index 0000000..134eb98
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * USBVISION.H
+ *  usbvision header file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * 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/list.h>
+#include <linux/i2c.h>
+#include <media/v4l2-dev.h>
+#include <media/tuner.h>
+#include "usbvision.h"
+
+/* Supported Devices: A table for usbvision.c*/
+struct usbvision_device_data_st  usbvision_device_data[] = {
+       {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"},
+       {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC,  1, 0, 1, 0, 0,                          -1, -1, -1, -1, -1, "Xanboo"},
+       {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL,   1, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Belkin USBView II"},
+       {0x0571, 0x0002,  0, CODEC_SAA7111, 2, V4L2_STD_PAL,   0, 0, 1, 0, 0,                          -1, -1, -1, -1,  7, "echoFX InterView Lite"},
+       {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC,  1, 0, 1, 0, 0,                          -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"},
+       {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC,  0, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "D-Link V100"},
+       {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC,  1, 0, 1, 0, 0,                          -1, -1, -1, -1, -1, "X10 USB Camera"},
+       {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL,   1, 0, 1, 0, 0,                          -1, -1, -1,  3,  7, "Osprey 50"},
+       {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC,    0, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Hauppauge USB-Live Model 600"},
+       {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL,     2, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"},
+       {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"},
+       {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"},
+       {0x0573, 0x4450,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "PixelView PlayTv-USB PRO (PAL) FM"},
+       {0x0573, 0x4550,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "ZTV ZT-721 2.4GHz USB A/V Receiver"},
+       {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 0, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"},
+       {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 0, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
+       {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 0, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"},
+       {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM,        -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "},
+       {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"},
+       {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
+       {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
+       {0x0573, 0x4d2a,  0, CODEC_SAA7113, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_MICROTUNE_4049FM5,    -1, -1,  0,  3,  7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"},
+       {0x0573, 0x4d2b,  0, CODEC_SAA7113, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_MICROTUNE_4049FM5,    -1, -1,  0,  3,  7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"},
+       {0x0573, 0x4d2c,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1,  0,  3,  7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"},
+       {0x0573, 0x4d20,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"},
+       {0x0573, 0x4d21,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB II (PAL)"},
+       {0x0573, 0x4d22,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB II (PAL) MODEL 566"},
+       {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM,        -1, -1,  0,  3,  7, "Hauppauge WinTv-USB (SECAM) 4D23"},
+       {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM,        -1, -1,  0,  3,  7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"},
+       {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM,        -1, -1,  0,  3,  7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"},
+       {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL,       -1, -1,  0,  3,  7, "Hauppauge WinTv-USB Model 40204 Rev B281"},
+       {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL,       -1, -1,  0,  3,  7, "Hauppauge WinTv-USB Model 40204 Rev B283"},
+       {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB Model 40205 Rev B298"},
+       {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1,  0,  3,  7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"},
+       {0x0573, 0x4d31,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB III (PAL) FM Model 568"},
+       {0x0573, 0x4d32,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,  0,  3,  7, "Hauppauge WinTv-USB III (PAL) FM Model 573"},
+       {0x0573, 0x4d35,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_MICROTUNE_4049FM5,    -1, -1,  0,  3,  7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"},
+       {0x0573, 0x4d37,  0, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1,  0,  3,  7, "Hauppauge WinTV USB device Model 40219 Rev E189"},
+       {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1,  5,  5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"},
+       {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL,   0, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Digital Video Creator I"},
+       {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC,  0, 0, 1, 0, 0,                            -1, -1, 82, 20,  7, "Global Village GV-007 (NTSC)"},
+       {0x07d0, 0x0003,  0, CODEC_SAA7113, 2, V4L2_STD_NTSC,  0, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"},
+       {0x07d0, 0x0004,  0, CODEC_SAA7113, 2, V4L2_STD_PAL,   0, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"},
+       {0x07d0, 0x0005,  0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0,                            -1, -1,  0,  3,  7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"},
+       {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL,   1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I,  -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"},
+       {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM,        -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"},
+       {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_PHILIPS_PAL,          -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"},
+       {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL,   1, 0, 1, 1, TUNER_PHILIPS_PAL,          -1, -1, -1, -1, -1, "Miro PCTV USB"},
+       {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"},
+       {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL,    -1, -1,  0,  3,  7, "Pinnacle Studio PCTV USB (PAL) FM"},
+       {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC,  1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC,   -1, -1,  0,  3,  7, "Pinnacle Studio PCTV USB (NTSC) FM"},
+       {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL,    -1, -1,  0,  3,  7, "Pinnacle Studio PCTV USB (PAL) FM"},
+       {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC,  1, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Pinnacle Studio Linx Video input cable (NTSC)"},
+       {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL,   1, 0, 1, 0, 0,                          -1, -1,  0,  3,  7, "Pinnacle Studio Linx Video input cable (PAL)"},
+       {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL,   1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL,    -1, -1,  0,  3,  7, "Pinnacle PCTV Bungee USB (PAL) FM"},
+       {0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC,  1, 0, 1, 1, TUNER_PHILIPS_NTSC_M,       -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
+       {}  /* Terminating entry */
+};
+
+/* Supported Devices */
+
+struct usb_device_id usbvision_table [] = {
+       { USB_DEVICE(0xFFF0, 0xFFF0) },  /* Custom Dummy USBVision Device */
+       { USB_DEVICE(0x0A6F, 0x0400) },  /* Xanboo */
+       { USB_DEVICE(0x050d, 0x0208) },  /* Belkin USBView II */
+       { USB_DEVICE(0x0571, 0x0002) },  /* echoFX InterView Lite */
+       { USB_DEVICE(0x0573, 0x0003) },  /* USBGear USBG-V1 */
+       { USB_DEVICE(0x0573, 0x0400) },  /* D-Link V100 */
+       { USB_DEVICE(0x0573, 0x2000) },  /* X10 USB Camera */
+       { USB_DEVICE(0x0573, 0x2d00) },  /* Osprey 50 */
+       { USB_DEVICE(0x0573, 0x2d01) },  /* Hauppauge USB-Live Model 600 */
+       { USB_DEVICE(0x0573, 0x2101) },  /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */
+       { USB_DEVICE(0x0573, 0x4100) },  /* Nogatech USB-TV FM (NTSC) */
+       { USB_DEVICE(0x0573, 0x4110) },  /* PNY USB-TV (NTSC) FM */
+       { USB_DEVICE(0x0573, 0x4450) },  /* PixelView PlayTv-USB PRO (PAL) FM */
+       { USB_DEVICE(0x0573, 0x4550) },  /* ZTV ZT-721 2.4GHz USB A/V Receiver */
+       { USB_DEVICE(0x0573, 0x4d00) },  /* Hauppauge WinTv-USB USA */
+       { USB_DEVICE(0x0573, 0x4d01) },  /* Hauppauge WinTv-USB */
+       { USB_DEVICE(0x0573, 0x4d02) },  /* Hauppauge WinTv-USB UK */
+       { USB_DEVICE(0x0573, 0x4d03) },  /* Hauppauge WinTv-USB France */
+       { USB_DEVICE(0x0573, 0x4d10) },  /* Hauppauge WinTv-USB with FM USA radio */
+       { USB_DEVICE(0x0573, 0x4d11) },  /* Hauppauge WinTv-USB (PAL) with FM radio */
+       { USB_DEVICE(0x0573, 0x4d12) },  /* Hauppauge WinTv-USB UK with FM Radio */
+       { USB_DEVICE(0x0573, 0x4d2a) },  /* Hauppague WinTv USB Model 602 40201 Rev B285 */
+       { USB_DEVICE(0x0573, 0x4d2b) },  /* Hauppague WinTv USB Model 602 40201 Rev B282 */
+       { USB_DEVICE(0x0573, 0x4d2c) },  /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/
+       { USB_DEVICE(0x0573, 0x4d20) },  /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */
+       { USB_DEVICE(0x0573, 0x4d21) },  /* Hauppauge WinTv-USB II (PAL) with FM radio*/
+       { USB_DEVICE(0x0573, 0x4d22) },  /* Hauppauge WinTv-USB II (PAL) Model 566 */
+       { USB_DEVICE(0x0573, 0x4d23) },  /* Hauppauge WinTv-USB France 4D23*/
+       { USB_DEVICE(0x0573, 0x4d25) },  /* Hauppauge WinTv-USB Model 40209 rev B234 */
+       { USB_DEVICE(0x0573, 0x4d26) },  /* Hauppauge WinTv-USB Model 40209 Rev B243 */
+       { USB_DEVICE(0x0573, 0x4d27) },  /* Hauppauge WinTv-USB Model 40204 Rev B281 */
+       { USB_DEVICE(0x0573, 0x4d28) },  /* Hauppauge WinTv-USB Model 40204 Rev B283 */
+       { USB_DEVICE(0x0573, 0x4d29) },  /* Hauppauge WinTv-USB Model 40205 Rev B298 */
+       { USB_DEVICE(0x0573, 0x4d30) },  /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */
+       { USB_DEVICE(0x0573, 0x4d31) },  /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */
+       { USB_DEVICE(0x0573, 0x4d32) },  /* Hauppauge WinTv-USB III (PAL) FM Model 573 */
+       { USB_DEVICE(0x0573, 0x4d35) },  /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */
+       { USB_DEVICE(0x0573, 0x4d37) },  /* Hauppauge WinTv-USB Model 40219 Rev E189 */
+       { USB_DEVICE(0x0768, 0x0006) },  /* Camtel Technology USB TV Genie Pro FM Model TVB330 */
+       { USB_DEVICE(0x07d0, 0x0001) },  /* Digital Video Creator I */
+       { USB_DEVICE(0x07d0, 0x0002) },  /* Global Village GV-007 (NTSC) */
+       { USB_DEVICE(0x07d0, 0x0003) },  /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */
+       { USB_DEVICE(0x07d0, 0x0004) },  /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */
+       { USB_DEVICE(0x07d0, 0x0005) },  /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */
+       { USB_DEVICE(0x2304, 0x010d) },  /* Pinnacle Studio PCTV USB (PAL) */
+       { USB_DEVICE(0x2304, 0x0109) },  /* Pinnacle Studio PCTV USB (SECAM) */
+       { USB_DEVICE(0x2304, 0x0110) },  /* Pinnacle Studio PCTV USB (PAL) */
+       { USB_DEVICE(0x2304, 0x0111) },  /* Miro PCTV USB */
+       { USB_DEVICE(0x2304, 0x0112) },  /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
+       { USB_DEVICE(0x2304, 0x0210) },  /* Pinnacle Studio PCTV USB (PAL) with FM radio */
+       { USB_DEVICE(0x2304, 0x0212) },  /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
+       { USB_DEVICE(0x2304, 0x0214) },  /* Pinnacle Studio PCTV USB (PAL) with FM radio */
+       { USB_DEVICE(0x2304, 0x0300) },  /* Pinnacle Studio Linx Video input cable (NTSC) */
+       { USB_DEVICE(0x2304, 0x0301) },  /* Pinnacle Studio Linx Video input cable (PAL) */
+       { USB_DEVICE(0x2304, 0x0419) },  /* Pinnacle PCTV Bungee USB (PAL) FM */
+
+       { USB_DEVICE(0x2400, 0x4200) },  /* Hauppauge WinTv-USB2 Model 42012 */
+
+       { }  /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usbvision_table);
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
new file mode 100644 (file)
index 0000000..797b97b
--- /dev/null
@@ -0,0 +1,2554 @@
+/*
+ * usbvision-core.c - driver for NT100x USB video capture devices
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+#include <linux/videodev.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include "usbvision.h"
+
+static unsigned int core_debug = 0;
+module_param(core_debug,int,0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int force_testpattern = 0;
+module_param(force_testpattern,int,0644);
+MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
+
+static int adjustCompression = 1;                      // Set the compression to be adaptive
+module_param(adjustCompression, int, 0444);
+MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device.  Default: 1 (On)");
+
+static int SwitchSVideoInput = 0;                      // To help people with Black and White output with using s-video input.  Some cables and input device are wired differently.
+module_param(SwitchSVideoInput, int, 0444);
+MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
+
+#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+       #define PDEBUG(level, fmt, args...) \
+               if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+       #define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+#define DBG_HEADER     1<<0
+#define DBG_IRQ                1<<1
+#define DBG_ISOC       1<<2
+#define DBG_PARSE      1<<3
+#define DBG_SCRATCH    1<<4
+#define DBG_FUNC       1<<5
+
+static const int max_imgwidth = MAX_FRAME_WIDTH;
+static const int max_imgheight = MAX_FRAME_HEIGHT;
+static const int min_imgwidth = MIN_FRAME_WIDTH;
+static const int min_imgheight = MIN_FRAME_HEIGHT;
+
+/* The value of 'scratch_buf_size' affects quality of the picture
+ * in many ways. Shorter buffers may cause loss of data when client
+ * is too slow. Larger buffers are memory-consuming and take longer
+ * to work with. This setting can be adjusted, but the default value
+ * should be OK for most desktop users.
+ */
+#define DEFAULT_SCRATCH_BUF_SIZE       (0x20000)               // 128kB memory scratch buffer
+static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
+
+// Function prototypes
+static int usbvision_request_intra (struct usb_usbvision *usbvision);
+static int usbvision_unrequest_intra (struct usb_usbvision *usbvision);
+static int usbvision_adjust_compression (struct usb_usbvision *usbvision);
+static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision);
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+/*
+ * Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+
+void *usbvision_rvmalloc(unsigned long size)
+{
+       void *mem;
+       unsigned long adr;
+
+       size = PAGE_ALIGN(size);
+       mem = vmalloc_32(size);
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+       adr = (unsigned long) mem;
+       while (size > 0) {
+               SetPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       return mem;
+}
+
+void usbvision_rvfree(void *mem, unsigned long size)
+{
+       unsigned long adr;
+
+       if (!mem)
+               return;
+
+       size = PAGE_ALIGN(size);
+
+       adr = (unsigned long) mem;
+       while ((long) size > 0) {
+               ClearPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vfree(mem);
+}
+
+
+
+#if ENABLE_HEXDUMP
+static void usbvision_hexdump(const unsigned char *data, int len)
+{
+       char tmp[80];
+       int i, k;
+
+       for (i = k = 0; len > 0; i++, len--) {
+               if (i > 0 && (i % 16 == 0)) {
+                       printk("%s\n", tmp);
+                       k = 0;
+               }
+               k += sprintf(&tmp[k], "%02x ", data[i]);
+       }
+       if (k > 0)
+               printk("%s\n", tmp);
+}
+#endif
+
+/********************************
+ * scratch ring buffer handling
+ ********************************/
+int scratch_len(struct usb_usbvision *usbvision)    /*This returns the amount of data actually in the buffer */
+{
+       int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr;
+       if (len < 0) {
+               len += scratch_buf_size;
+       }
+       PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len);
+
+       return len;
+}
+
+
+/* This returns the free space left in the buffer */
+int scratch_free(struct usb_usbvision *usbvision)
+{
+       int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr;
+       if (free <= 0) {
+               free += scratch_buf_size;
+       }
+       if (free) {
+               free -= 1;                                                      /* at least one byte in the buffer must */
+                                                                               /* left blank, otherwise there is no chance to differ between full and empty */
+       }
+       PDEBUG(DBG_SCRATCH, "return %d\n", free);
+
+       return free;
+}
+
+
+/* This puts data into the buffer */
+int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, int len)
+{
+       int len_part;
+
+       if (usbvision->scratch_write_ptr + len < scratch_buf_size) {
+               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len);
+               usbvision->scratch_write_ptr += len;
+       }
+       else {
+               len_part = scratch_buf_size - usbvision->scratch_write_ptr;
+               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part);
+               if (len == len_part) {
+                       usbvision->scratch_write_ptr = 0;                       /* just set write_ptr to zero */
+               }
+               else {
+                       memcpy(usbvision->scratch, data + len_part, len - len_part);
+                       usbvision->scratch_write_ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr);
+
+       return len;
+}
+
+/* This marks the write_ptr as position of new frame header */
+void scratch_mark_header(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr);
+
+       usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] =
+                               usbvision->scratch_write_ptr;
+       usbvision->scratch_headermarker_write_ptr += 1;
+       usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER;
+}
+
+/* This gets data from the buffer at the given "ptr" position */
+int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len)
+{
+       int len_part;
+       if (*ptr + len < scratch_buf_size) {
+               memcpy(data, usbvision->scratch + *ptr, len);
+               *ptr += len;
+       }
+       else {
+               len_part = scratch_buf_size - *ptr;
+               memcpy(data, usbvision->scratch + *ptr, len_part);
+               if (len == len_part) {
+                       *ptr = 0;                                                       /* just set the y_ptr to zero */
+               }
+               else {
+                       memcpy(data + len_part, usbvision->scratch, len - len_part);
+                       *ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr);
+
+       return len;
+}
+
+
+/* This sets the scratch extra read pointer */
+void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len)
+{
+       *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size;
+
+       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/*This increments the scratch extra read pointer */
+void scratch_inc_extra_ptr(int *ptr, int len)
+{
+       *ptr = (*ptr + len) % scratch_buf_size;
+
+       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/* This gets data from the buffer */
+int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len)
+{
+       int len_part;
+       if (usbvision->scratch_read_ptr + len < scratch_buf_size) {
+               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len);
+               usbvision->scratch_read_ptr += len;
+       }
+       else {
+               len_part = scratch_buf_size - usbvision->scratch_read_ptr;
+               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part);
+               if (len == len_part) {
+                       usbvision->scratch_read_ptr = 0;                                /* just set the read_ptr to zero */
+               }
+               else {
+                       memcpy(data + len_part, usbvision->scratch, len - len_part);
+                       usbvision->scratch_read_ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr);
+
+       return len;
+}
+
+
+/* This sets read pointer to next header and returns it */
+int scratch_get_header(struct usb_usbvision *usbvision,struct usbvision_frame_header *header)
+{
+       int errCode = 0;
+
+       PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr);
+
+       while (usbvision->scratch_headermarker_write_ptr -
+               usbvision->scratch_headermarker_read_ptr != 0) {
+               usbvision->scratch_read_ptr =
+                       usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr];
+               usbvision->scratch_headermarker_read_ptr += 1;
+               usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER;
+               scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH);
+               if ((header->magic_1 == USBVISION_MAGIC_1)
+                        && (header->magic_2 == USBVISION_MAGIC_2)
+                        && (header->headerLength == USBVISION_HEADER_LENGTH)) {
+                       errCode = USBVISION_HEADER_LENGTH;
+                       header->frameWidth  = header->frameWidthLo  + (header->frameWidthHi << 8);
+                       header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8);
+                       break;
+               }
+       }
+
+       return errCode;
+}
+
+
+/*This removes len bytes of old data from the buffer */
+void scratch_rm_old(struct usb_usbvision *usbvision, int len)
+{
+
+       usbvision->scratch_read_ptr += len;
+       usbvision->scratch_read_ptr %= scratch_buf_size;
+       PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr);
+}
+
+
+/*This resets the buffer - kills all data in it too */
+void scratch_reset(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_SCRATCH, "\n");
+
+       usbvision->scratch_read_ptr = 0;
+       usbvision->scratch_write_ptr = 0;
+       usbvision->scratch_headermarker_read_ptr = 0;
+       usbvision->scratch_headermarker_write_ptr = 0;
+       usbvision->isocstate = IsocState_NoFrame;
+}
+
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
+{
+       usbvision->scratch = vmalloc(scratch_buf_size);
+       scratch_reset(usbvision);
+       if(usbvision->scratch == NULL) {
+               err("%s: unable to allocate %d bytes for scratch",
+                   __FUNCTION__, scratch_buf_size);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void usbvision_scratch_free(struct usb_usbvision *usbvision)
+{
+       if (usbvision->scratch != NULL) {
+               vfree(usbvision->scratch);
+               usbvision->scratch = NULL;
+       }
+}
+
+/*
+ * usbvision_testpattern()
+ *
+ * Procedure forms a test pattern (yellow grid on blue background).
+ *
+ * Parameters:
+ * fullframe:   if TRUE then entire frame is filled, otherwise the procedure
+ *             continues from the current scanline.
+ * pmode       0: fill the frame with solid blue color (like on VCR or TV)
+ *             1: Draw a colored grid
+ *
+ */
+void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe,
+                       int pmode)
+{
+       static const char proc[] = "usbvision_testpattern";
+       struct usbvision_frame *frame;
+       unsigned char *f;
+       int num_cell = 0;
+       int scan_length = 0;
+       static int num_pass = 0;
+
+       if (usbvision == NULL) {
+               printk(KERN_ERR "%s: usbvision == NULL\n", proc);
+               return;
+       }
+       if (usbvision->curFrame == NULL) {
+               printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc);
+               return;
+       }
+
+       /* Grab the current frame */
+       frame = usbvision->curFrame;
+
+       /* Optionally start at the beginning */
+       if (fullframe) {
+               frame->curline = 0;
+               frame->scanlength = 0;
+       }
+
+       /* Form every scan line */
+       for (; frame->curline < frame->frmheight; frame->curline++) {
+               int i;
+
+               f = frame->data + (usbvision->curwidth * 3 * frame->curline);
+               for (i = 0; i < usbvision->curwidth; i++) {
+                       unsigned char cb = 0x80;
+                       unsigned char cg = 0;
+                       unsigned char cr = 0;
+
+                       if (pmode == 1) {
+                               if (frame->curline % 32 == 0)
+                                       cb = 0, cg = cr = 0xFF;
+                               else if (i % 32 == 0) {
+                                       if (frame->curline % 32 == 1)
+                                               num_cell++;
+                                       cb = 0, cg = cr = 0xFF;
+                               } else {
+                                       cb =
+                                           ((num_cell * 7) +
+                                            num_pass) & 0xFF;
+                                       cg =
+                                           ((num_cell * 5) +
+                                            num_pass * 2) & 0xFF;
+                                       cr =
+                                           ((num_cell * 3) +
+                                            num_pass * 3) & 0xFF;
+                               }
+                       } else {
+                               /* Just the blue screen */
+                       }
+
+                       *f++ = cb;
+                       *f++ = cg;
+                       *f++ = cr;
+                       scan_length += 3;
+               }
+       }
+
+       frame->grabstate = FrameState_Done;
+       frame->scanlength += scan_length;
+       ++num_pass;
+
+}
+
+/*
+ * usbvision_decompress_alloc()
+ *
+ * allocates intermediate buffer for decompression
+ */
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
+{
+       int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
+       usbvision->IntraFrameBuffer = vmalloc(IFB_size);
+       if (usbvision->IntraFrameBuffer == NULL) {
+               err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/*
+ * usbvision_decompress_free()
+ *
+ * frees intermediate buffer for decompression
+ */
+void usbvision_decompress_free(struct usb_usbvision *usbvision)
+{
+       if (usbvision->IntraFrameBuffer != NULL) {
+               vfree(usbvision->IntraFrameBuffer);
+               usbvision->IntraFrameBuffer = NULL;
+       }
+}
+
+/************************************************************
+ * Here comes the data parsing stuff that is run as interrupt
+ ************************************************************/
+/*
+ * usbvision_find_header()
+ *
+ * Locate one of supported header markers in the scratch buffer.
+ */
+static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision)
+{
+       struct usbvision_frame *frame;
+       int foundHeader = 0;
+
+       frame = usbvision->curFrame;
+
+       while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) {
+               // found header in scratch
+               PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u",
+                               frame->isocHeader.magic_2,
+                               frame->isocHeader.magic_1,
+                               frame->isocHeader.headerLength,
+                               frame->isocHeader.frameNum,
+                               frame->isocHeader.framePhase,
+                               frame->isocHeader.frameLatency,
+                               frame->isocHeader.dataFormat,
+                               frame->isocHeader.formatParam,
+                               frame->isocHeader.frameWidth,
+                               frame->isocHeader.frameHeight);
+
+               if (usbvision->requestIntra) {
+                       if (frame->isocHeader.formatParam & 0x80) {
+                               foundHeader = 1;
+                               usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time
+                               usbvision_unrequest_intra(usbvision);
+                               break;
+                       }
+               }
+               else {
+                       foundHeader = 1;
+                       break;
+               }
+       }
+
+       if (foundHeader) {
+               frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width;
+               frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height;
+               frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3;
+       }
+       else { // no header found
+               PDEBUG(DBG_HEADER, "skipping scratch data, no header");
+               scratch_reset(usbvision);
+               return ParseState_EndParse;
+       }
+
+       // found header
+       if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) {
+               //check isocHeader.frameNum for lost frames
+               if (usbvision->lastIsocFrameNum >= 0) {
+                       if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) {
+                               // unexpected frame drop: need to request new intra frame
+                               PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum);
+                               usbvision_request_intra(usbvision);
+                               return ParseState_NextFrame;
+                       }
+               }
+               usbvision->lastIsocFrameNum = frame->isocHeader.frameNum;
+       }
+       usbvision->header_count++;
+       frame->scanstate = ScanState_Lines;
+       frame->curline = 0;
+
+       if (force_testpattern) {
+               usbvision_testpattern(usbvision, 1, 1);
+               return ParseState_NextFrame;
+       }
+       return ParseState_Continue;
+}
+
+static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+       volatile struct usbvision_frame *frame;
+       unsigned char *f;
+       int len;
+       int i;
+       unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components
+       unsigned char rv, gv, bv;       // RGB components
+       int clipmask_index, bytes_per_pixel;
+       int stretch_bytes, clipmask_add;
+
+       frame  = usbvision->curFrame;
+       f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+       /* Make sure there's enough data for the entire line */
+       len = (frame->isocHeader.frameWidth * 2)+5;
+       if (scratch_len(usbvision) < len) {
+               PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len);
+               return ParseState_Out;
+       }
+
+       if ((frame->curline + 1) >= frame->frmheight) {
+               return ParseState_NextFrame;
+       }
+
+       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+       clipmask_add = usbvision->stretch_width;
+
+       for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) {
+
+               scratch_get(usbvision, &yuyv[0], 4);
+
+               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = yuyv[0]; // Y
+                       *f++ = yuyv[3]; // U
+               }
+               else {
+
+                       YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+                                       *f++ = (0x07 & (gv >> 5)) | (0xF8 &  rv);
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       f++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+                                       *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+                                       break;
+                       }
+               }
+               clipmask_index += clipmask_add;
+               f += stretch_bytes;
+
+               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = yuyv[2]; // Y
+                       *f++ = yuyv[1]; // V
+               }
+               else {
+
+                       YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+                                       *f++ = (0x07 & (gv >> 5)) | (0xF8 &  rv);
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       f++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+                                       *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+                                       break;
+                       }
+               }
+               clipmask_index += clipmask_add;
+               f += stretch_bytes;
+       }
+
+       frame->curline += usbvision->stretch_height;
+       *pcopylen += frame->v4l2_linesize * usbvision->stretch_height;
+
+       if (frame->curline >= frame->frmheight) {
+               return ParseState_NextFrame;
+       }
+       else {
+               return ParseState_Continue;
+       }
+}
+
+/* The decompression routine  */
+static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed,
+                                                               unsigned char *Decompressed, int *StartPos,
+                                                               int *BlockTypeStartPos, int Len)
+{
+       int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen;
+       unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator;
+
+       Integrator = 0;
+       Pos = *StartPos;
+       BlockTypePos = *BlockTypeStartPos;
+       MaxPos = 396; //Pos + Len;
+       ExtraPos = Pos;
+       BlockLen = 0;
+       BlockByte = 0;
+       BlockCode = 0;
+       BlockType = 0;
+       BlockTypeByte = 0;
+       BlockTypeLen = 0;
+       RestPixel = Len;
+
+       for (Idx = 0; Idx < Len; Idx++) {
+
+               if (BlockLen == 0) {
+                       if (BlockTypeLen==0) {
+                               BlockTypeByte = Compressed[BlockTypePos];
+                               BlockTypePos++;
+                               BlockTypeLen = 4;
+                       }
+                       BlockType = (BlockTypeByte & 0xC0) >> 6;
+
+                       //statistic:
+                       usbvision->ComprBlockTypes[BlockType]++;
+
+                       Pos = ExtraPos;
+                       if (BlockType == 0) {
+                               if(RestPixel >= 24) {
+                                       Idx += 23;
+                                       RestPixel -= 24;
+                                       Integrator = Decompressed[Idx];
+                               } else {
+                                       Idx += RestPixel - 1;
+                                       RestPixel = 0;
+                               }
+                       } else {
+                               BlockCode = Compressed[Pos];
+                               Pos++;
+                               if (RestPixel >= 24) {
+                                       BlockLen  = 24;
+                               } else {
+                                       BlockLen = RestPixel;
+                               }
+                               RestPixel -= BlockLen;
+                               ExtraPos = Pos + (BlockLen / 4);
+                       }
+                       BlockTypeByte <<= 2;
+                       BlockTypeLen -= 1;
+               }
+               if (BlockLen > 0) {
+                       if ((BlockLen%4) == 0) {
+                               BlockByte = Compressed[Pos];
+                               Pos++;
+                       }
+                       if (BlockType == 1) { //inter Block
+                               Integrator = Decompressed[Idx];
+                       }
+                       switch (BlockByte & 0xC0) {
+                               case 0x03<<6:
+                                       Integrator += Compressed[ExtraPos];
+                                       ExtraPos++;
+                                       break;
+                               case 0x02<<6:
+                                       Integrator += BlockCode;
+                                       break;
+                               case 0x00:
+                                       Integrator -= BlockCode;
+                                       break;
+                       }
+                       Decompressed[Idx] = Integrator;
+                       BlockByte <<= 2;
+                       BlockLen -= 1;
+               }
+       }
+       *StartPos = ExtraPos;
+       *BlockTypeStartPos = BlockTypePos;
+       return Idx;
+}
+
+
+/*
+ * usbvision_parse_compress()
+ *
+ * Parse compressed frame from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+#define USBVISION_STRIP_MAGIC          0x5A
+#define USBVISION_STRIP_LEN_MAX                400
+#define USBVISION_STRIP_HEADER_LEN     3
+
+       struct usbvision_frame *frame;
+       unsigned char *f,*u = NULL ,*v = NULL;
+       unsigned char StripData[USBVISION_STRIP_LEN_MAX];
+       unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN];
+       int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos;
+       int clipmask_index, bytes_per_pixel, rc;
+       int imageSize;
+       unsigned char rv, gv, bv;
+       static unsigned char *Y, *U, *V;
+
+       frame  = usbvision->curFrame;
+       imageSize = frame->frmwidth * frame->frmheight;
+       if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
+            (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) {       // this is a planar format
+               //... v4l2_linesize not used here.
+               f = frame->data + (frame->width * frame->curline);
+       } else
+               f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers
+               // get base of u and b planes add halfoffset
+
+               u = frame->data
+                       + imageSize
+                       + (frame->frmwidth >>1) * frame->curline ;
+               v = u + (imageSize >>1 );
+
+       } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){
+
+               v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ;
+               u = v + (imageSize >>2) ;
+       }
+
+       if (frame->curline == 0) {
+               usbvision_adjust_compression(usbvision);
+       }
+
+       if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) {
+               return ParseState_Out;
+       }
+
+       //get strip header without changing the scratch_read_ptr
+       scratch_set_extra_ptr(usbvision, &StripPtr, 0);
+       scratch_get_extra(usbvision, &StripHeader[0], &StripPtr,
+                               USBVISION_STRIP_HEADER_LEN);
+
+       if (StripHeader[0] != USBVISION_STRIP_MAGIC) {
+               // wrong strip magic
+               usbvision->stripMagicErrors++;
+               return ParseState_NextFrame;
+       }
+
+       if (frame->curline != (int)StripHeader[2]) {
+               //line number missmatch error
+               usbvision->stripLineNumberErrors++;
+       }
+
+       StripLen = 2 * (unsigned int)StripHeader[1];
+       if (StripLen > USBVISION_STRIP_LEN_MAX) {
+               // strip overrun
+               // I think this never happens
+               usbvision_request_intra(usbvision);
+       }
+
+       if (scratch_len(usbvision) < StripLen) {
+               //there is not enough data for the strip
+               return ParseState_Out;
+       }
+
+       if (usbvision->IntraFrameBuffer) {
+               Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline;
+               U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2);
+               V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
+       }
+       else {
+               return ParseState_NextFrame;
+       }
+
+       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+
+       scratch_get(usbvision, StripData, StripLen);
+
+       IdxEnd = frame->frmwidth;
+       BlockTypePos = USBVISION_STRIP_HEADER_LEN;
+       StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2;
+       BlockPos = StartBlockPos;
+
+       usbvision->BlockPos = BlockPos;
+
+       if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) {
+               //return ParseState_Continue;
+       }
+       if (StripLen > usbvision->maxStripLen) {
+               usbvision->maxStripLen = StripLen;
+       }
+
+       if (frame->curline%2) {
+               if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
+               //return ParseState_Continue;
+               }
+       }
+       else {
+               if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
+                       //return ParseState_Continue;
+               }
+       }
+
+       if (BlockPos > usbvision->comprBlockPos) {
+               usbvision->comprBlockPos = BlockPos;
+       }
+       if (BlockPos > StripLen) {
+               usbvision->stripLenErrors++;
+       }
+
+       for (Idx = 0; Idx < IdxEnd; Idx++) {
+               if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = Y[Idx];
+                       *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2];
+               }
+               else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
+                       *f++ = Y[Idx];
+                       if ( Idx & 0x01)
+                               *u++ = U[Idx>>1] ;
+                       else
+                               *v++ = V[Idx>>1];
+               }
+               else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+                       *f++ = Y [Idx];
+                       if ( !((  Idx & 0x01  ) | (  frame->curline & 0x01  )) ){
+
+/*                              only need do this for 1 in 4 pixels */
+/*                              intraframe buffer is YUV420 format */
+
+                               *u++ = U[Idx >>1];
+                               *v++ = V[Idx >>1];
+                       }
+
+               }
+               else {
+                       YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_GREY:
+                                       *f++ = Y[Idx];
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+                                       *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+                                       break;
+                               case V4L2_PIX_FMT_RGB565:
+                                       *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+                                       *f++ = (0x07 & (gv >> 5)) | (0xF8 &  rv);
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f++ = bv;
+                                       *f++ = gv;
+                                       *f++ = rv;
+                                       f++;
+                                       break;
+                       }
+               }
+               clipmask_index++;
+       }
+       /* Deal with non-integer no. of bytes for YUV420P */
+       if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 )
+               *pcopylen += frame->v4l2_linesize;
+       else
+               *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
+
+       frame->curline += 1;
+
+       if (frame->curline >= frame->frmheight) {
+               return ParseState_NextFrame;
+       }
+       else {
+               return ParseState_Continue;
+       }
+
+}
+
+
+/*
+ * usbvision_parse_lines_420()
+ *
+ * Parse two lines from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+       struct usbvision_frame *frame;
+       unsigned char *f_even = NULL, *f_odd = NULL;
+       unsigned int pixel_per_line, block;
+       int pixel, block_split;
+       int y_ptr, u_ptr, v_ptr, y_odd_offset;
+       const int   y_block_size = 128;
+       const int  uv_block_size = 64;
+       const int sub_block_size = 32;
+       const int y_step[] = { 0, 0, 0, 2 },  y_step_size = 4;
+       const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4;
+       unsigned char y[2], u, v;       /* YUV components */
+       int y_, u_, v_, vb, uvg, ur;
+       int r_, g_, b_;                 /* RGB components */
+       unsigned char g;
+       int clipmask_even_index, clipmask_odd_index, bytes_per_pixel;
+       int clipmask_add, stretch_bytes;
+
+       frame  = usbvision->curFrame;
+       f_even = frame->data + (frame->v4l2_linesize * frame->curline);
+       f_odd  = f_even + frame->v4l2_linesize * usbvision->stretch_height;
+
+       /* Make sure there's enough data for the entire line */
+       /* In this mode usbvision transfer 3 bytes for every 2 pixels */
+       /* I need two lines to decode the color */
+       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+       clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
+       clipmask_odd_index  = clipmask_even_index + MAX_FRAME_WIDTH;
+       clipmask_add = usbvision->stretch_width;
+       pixel_per_line = frame->isocHeader.frameWidth;
+
+       if (scratch_len(usbvision) < (int)pixel_per_line * 3) {
+               //printk(KERN_DEBUG "out of data, need %d\n", len);
+               return ParseState_Out;
+       }
+
+       if ((frame->curline + 1) >= frame->frmheight) {
+               return ParseState_NextFrame;
+       }
+
+       block_split = (pixel_per_line%y_block_size) ? 1 : 0;    //are some blocks splitted into different lines?
+
+       y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size)
+                       + block_split * uv_block_size;
+
+       scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset);
+       scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size);
+       scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset
+                       + (4 - block_split) * sub_block_size);
+
+       for (block = 0; block < (pixel_per_line / sub_block_size);
+            block++) {
+
+
+               for (pixel = 0; pixel < sub_block_size; pixel +=2) {
+                       scratch_get(usbvision, &y[0], 2);
+                       scratch_get_extra(usbvision, &u, &u_ptr, 1);
+                       scratch_get_extra(usbvision, &v, &v_ptr, 1);
+
+                       //I don't use the YUV_TO_RGB macro for better performance
+                       v_ = v - 128;
+                       u_ = u - 128;
+                       vb =              132252 * v_;
+                       uvg= -53281 * u_ - 25625 * v_;
+                       ur = 104595 * u_;
+
+                       if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_even++ = y[0];
+                               *f_even++ = v;
+                       }
+                       else {
+                               y_ = 76284 * (y[0] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg)>> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                                       case V4L2_PIX_FMT_RGB565:
+                                               g = LIMIT_RGB(g_);
+                                               *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+                                               *f_even++ = (0x07 & (          g   >> 5)) | (0xF8 & LIMIT_RGB(r_));
+                                               break;
+                                       case V4L2_PIX_FMT_RGB24:
+                                               *f_even++ = LIMIT_RGB(b_);
+                                               *f_even++ = LIMIT_RGB(g_);
+                                               *f_even++ = LIMIT_RGB(r_);
+                                               break;
+                                       case V4L2_PIX_FMT_RGB32:
+                                               *f_even++ = LIMIT_RGB(b_);
+                                               *f_even++ = LIMIT_RGB(g_);
+                                               *f_even++ = LIMIT_RGB(r_);
+                                               f_even++;
+                                               break;
+                                       case V4L2_PIX_FMT_RGB555:
+                                               g = LIMIT_RGB(g_);
+                                               *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+                                               *f_even++ = (0x03 & (          g   >> 6)) |
+                                                           (0x7C & (LIMIT_RGB(r_) >> 1));
+                                               break;
+                               }
+                       }
+                       clipmask_even_index += clipmask_add;
+                       f_even += stretch_bytes;
+
+                       if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_even++ = y[1];
+                               *f_even++ = u;
+                       }
+                       else {
+                               y_ = 76284 * (y[1] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg)>> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                                       case V4L2_PIX_FMT_RGB565:
+                                               g = LIMIT_RGB(g_);
+                                               *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+                                               *f_even++ = (0x07 & (          g   >> 5)) | (0xF8 & LIMIT_RGB(r_));
+                                               break;
+                                       case V4L2_PIX_FMT_RGB24:
+                                               *f_even++ = LIMIT_RGB(b_);
+                                               *f_even++ = LIMIT_RGB(g_);
+                                               *f_even++ = LIMIT_RGB(r_);
+                                               break;
+                                       case V4L2_PIX_FMT_RGB32:
+                                               *f_even++ = LIMIT_RGB(b_);
+                                               *f_even++ = LIMIT_RGB(g_);
+                                               *f_even++ = LIMIT_RGB(r_);
+                                               f_even++;
+                                               break;
+                                       case V4L2_PIX_FMT_RGB555:
+                                               g = LIMIT_RGB(g_);
+                                               *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+                                               *f_even++ = (0x03 & (          g   >> 6)) |
+                                                           (0x7C & (LIMIT_RGB(r_) >> 1));
+                                               break;
+                               }
+                       }
+                       clipmask_even_index += clipmask_add;
+                       f_even += stretch_bytes;
+
+                       scratch_get_extra(usbvision, &y[0], &y_ptr, 2);
+
+                       if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_odd++ = y[0];
+                               *f_odd++ = v;
+                       }
+                       else {
+                               y_ = 76284 * (y[0] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg)>> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                                       case V4L2_PIX_FMT_RGB565:
+                                               g = LIMIT_RGB(g_);
+                                               *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+                                               *f_odd++ = (0x07 & (          g   >> 5)) | (0xF8 & LIMIT_RGB(r_));
+                                               break;
+                                       case V4L2_PIX_FMT_RGB24:
+                                               *f_odd++ = LIMIT_RGB(b_);
+                                               *f_odd++ = LIMIT_RGB(g_);
+                                               *f_odd++ = LIMIT_RGB(r_);
+                                               break;
+                                       case V4L2_PIX_FMT_RGB32:
+                                               *f_odd++ = LIMIT_RGB(b_);
+                                               *f_odd++ = LIMIT_RGB(g_);
+                                               *f_odd++ = LIMIT_RGB(r_);
+                                               f_odd++;
+                                               break;
+                                       case V4L2_PIX_FMT_RGB555:
+                                               g = LIMIT_RGB(g_);
+                                               *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+                                               *f_odd++ = (0x03 & (          g   >> 6)) |
+                                                          (0x7C & (LIMIT_RGB(r_) >> 1));
+                                               break;
+                               }
+                       }
+                       clipmask_odd_index += clipmask_add;
+                       f_odd += stretch_bytes;
+
+                       if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_odd++ = y[1];
+                               *f_odd++ = u;
+                       }
+                       else {
+                               y_ = 76284 * (y[1] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg)>> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                                       case V4L2_PIX_FMT_RGB565:
+                                               g = LIMIT_RGB(g_);
+                                               *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+                                               *f_odd++ = (0x07 & (          g   >> 5)) | (0xF8 & LIMIT_RGB(r_));
+                                               break;
+                                       case V4L2_PIX_FMT_RGB24:
+                                               *f_odd++ = LIMIT_RGB(b_);
+                                               *f_odd++ = LIMIT_RGB(g_);
+                                               *f_odd++ = LIMIT_RGB(r_);
+                                               break;
+                                       case V4L2_PIX_FMT_RGB32:
+                                               *f_odd++ = LIMIT_RGB(b_);
+                                               *f_odd++ = LIMIT_RGB(g_);
+                                               *f_odd++ = LIMIT_RGB(r_);
+                                               f_odd++;
+                                               break;
+                                       case V4L2_PIX_FMT_RGB555:
+                                               g = LIMIT_RGB(g_);
+                                               *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+                                               *f_odd++ = (0x03 & (          g   >> 6)) |
+                                                          (0x7C & (LIMIT_RGB(r_) >> 1));
+                                               break;
+                               }
+                       }
+                       clipmask_odd_index += clipmask_add;
+                       f_odd += stretch_bytes;
+               }
+
+               scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size);
+               scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size]
+                               * sub_block_size);
+               scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size]
+                               * sub_block_size);
+               scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size]
+                               * sub_block_size);
+       }
+
+       scratch_rm_old(usbvision, pixel_per_line * 3 / 2
+                       + block_split * sub_block_size);
+
+       frame->curline += 2 * usbvision->stretch_height;
+       *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height;
+
+       if (frame->curline >= frame->frmheight)
+               return ParseState_NextFrame;
+       else
+               return ParseState_Continue;
+}
+
+/*
+ * usbvision_parse_data()
+ *
+ * Generic routine to parse the scratch buffer. It employs either
+ * usbvision_find_header() or usbvision_parse_lines() to do most
+ * of work.
+ *
+ */
+static void usbvision_parse_data(struct usb_usbvision *usbvision)
+{
+       struct usbvision_frame *frame;
+       enum ParseState newstate;
+       long copylen = 0;
+       unsigned long lock_flags;
+
+       frame = usbvision->curFrame;
+
+       PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
+
+       while (1) {
+
+               newstate = ParseState_Out;
+               if (scratch_len(usbvision)) {
+                       if (frame->scanstate == ScanState_Scanning) {
+                               newstate = usbvision_find_header(usbvision);
+                       }
+                       else if (frame->scanstate == ScanState_Lines) {
+                               if (usbvision->isocMode == ISOC_MODE_YUV420) {
+                                       newstate = usbvision_parse_lines_420(usbvision, &copylen);
+                               }
+                               else if (usbvision->isocMode == ISOC_MODE_YUV422) {
+                                       newstate = usbvision_parse_lines_422(usbvision, &copylen);
+                               }
+                               else if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+                                       newstate = usbvision_parse_compress(usbvision, &copylen);
+                               }
+
+                       }
+               }
+               if (newstate == ParseState_Continue) {
+                       continue;
+               }
+               else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) {
+                       break;
+               }
+               else {
+                       return; /* ParseState_EndParse */
+               }
+       }
+
+       if (newstate == ParseState_NextFrame) {
+               frame->grabstate = FrameState_Done;
+               do_gettimeofday(&(frame->timestamp));
+               frame->sequence = usbvision->frame_num;
+
+               spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+               list_move_tail(&(frame->frame), &usbvision->outqueue);
+               usbvision->curFrame = NULL;
+               spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+               usbvision->frame_num++;
+
+               /* This will cause the process to request another frame. */
+               if (waitqueue_active(&usbvision->wait_frame)) {
+                       PDEBUG(DBG_PARSE, "Wake up !");
+                       wake_up_interruptible(&usbvision->wait_frame);
+               }
+       }
+       else
+               frame->grabstate = FrameState_Grabbing;
+
+
+       /* Update the frame's uncompressed length. */
+       frame->scanlength += copylen;
+}
+
+
+/*
+ * Make all of the blocks of data contiguous
+ */
+static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
+                                         struct urb *urb)
+{
+       unsigned char *packet_data;
+       int i, totlen = 0;
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int packet_len = urb->iso_frame_desc[i].actual_length;
+               int packet_stat = urb->iso_frame_desc[i].status;
+
+               packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* Detect and ignore errored packets */
+               if (packet_stat) {      // packet_stat != 0 ?????????????
+                       PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat);
+                       usbvision->isocErrCount++;
+                       continue;
+               }
+
+               /* Detect and ignore empty packets */
+               if (packet_len < 0) {
+                       PDEBUG(DBG_ISOC, "error packet [%d]", i);
+                       usbvision->isocSkipCount++;
+                       continue;
+               }
+               else if (packet_len == 0) {     /* Frame end ????? */
+                       PDEBUG(DBG_ISOC, "null packet [%d]", i);
+                       usbvision->isocstate=IsocState_NoFrame;
+                       usbvision->isocSkipCount++;
+                       continue;
+               }
+               else if (packet_len > usbvision->isocPacketSize) {
+                       PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i);
+                       usbvision->isocSkipCount++;
+                       continue;
+               }
+
+               PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len);
+
+               if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins
+                       usbvision->isocstate=IsocState_InFrame;
+                       scratch_mark_header(usbvision);
+                       usbvision_measure_bandwidth(usbvision);
+                       PDEBUG(DBG_ISOC, "packet with header");
+               }
+
+               /*
+                * If usbvision continues to feed us with data but there is no
+                * consumption (if, for example, V4L client fell asleep) we
+                * may overflow the buffer. We have to move old data over to
+                * free room for new data. This is bad for old data. If we
+                * just drop new data then it's bad for new data... choose
+                * your favorite evil here.
+                */
+               if (scratch_free(usbvision) < packet_len) {
+
+                       usbvision->scratch_ovf_count++;
+                       PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d",
+                              scratch_len(usbvision), packet_len);
+                       scratch_rm_old(usbvision, packet_len - scratch_free(usbvision));
+               }
+
+               /* Now we know that there is enough room in scratch buffer */
+               scratch_put(usbvision, packet_data, packet_len);
+               totlen += packet_len;
+               usbvision->isocDataCount += packet_len;
+               usbvision->isocPacketCount++;
+       }
+#if ENABLE_HEXDUMP
+       if (totlen > 0) {
+               static int foo = 0;
+               if (foo < 1) {
+                       printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
+                       usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
+                       ++foo;
+               }
+       }
+#endif
+ return totlen;
+}
+
+static void usbvision_isocIrq(struct urb *urb)
+{
+       int errCode = 0;
+       int len;
+       struct usb_usbvision *usbvision = urb->context;
+       int i;
+       unsigned long startTime = jiffies;
+       struct usbvision_frame **f;
+
+       /* We don't want to do anything if we are about to be removed! */
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return;
+
+       f = &usbvision->curFrame;
+
+       /* Manage streaming interruption */
+       if (usbvision->streaming == Stream_Interrupt) {
+               usbvision->streaming = Stream_Idle;
+               if ((*f)) {
+                       (*f)->grabstate = FrameState_Ready;
+                       (*f)->scanstate = ScanState_Scanning;
+               }
+               PDEBUG(DBG_IRQ, "stream interrupted");
+               wake_up_interruptible(&usbvision->wait_stream);
+       }
+
+       /* Copy the data received into our scratch buffer */
+       len = usbvision_compress_isochronous(usbvision, urb);
+
+       usbvision->isocUrbCount++;
+       usbvision->urb_length = len;
+
+       if (usbvision->streaming == Stream_On) {
+
+               /* If we collected enough data let's parse! */
+               if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */
+                       /*If we don't have a frame we're current working on, complain */
+                       if(!list_empty(&(usbvision->inqueue))) {
+                               if (!(*f)) {
+                                       (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
+                               }
+                               usbvision_parse_data(usbvision);
+                       }
+                       else {
+                               PDEBUG(DBG_IRQ, "received data, but no one needs it");
+                               scratch_reset(usbvision);
+                       }
+               }
+       }
+       else {
+               PDEBUG(DBG_IRQ, "received data, but no one needs it");
+               scratch_reset(usbvision);
+       }
+
+       usbvision->timeInIrq += jiffies - startTime;
+
+       for (i = 0; i < USBVISION_URB_FRAMES; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       urb->status = 0;
+       urb->dev = usbvision->dev;
+       errCode = usb_submit_urb (urb, GFP_ATOMIC);
+
+       /* Disable this warning.  By design of the driver. */
+       //      if(errCode) {
+       //              err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
+       //      }
+
+       return;
+}
+
+/*************************************/
+/* Low level usbvision access functions */
+/*************************************/
+
+/*
+ * usbvision_read_reg()
+ *
+ * return  < 0 -> Error
+ *        >= 0 -> Data
+ */
+
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
+{
+       int errCode = 0;
+       unsigned char buffer[1];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -1;
+
+       errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
+                               USBVISION_OP_CODE,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                               0, (__u16) reg, buffer, 1, HZ);
+
+       if (errCode < 0) {
+               err("%s: failed: error %d", __FUNCTION__, errCode);
+               return errCode;
+       }
+       return buffer[0];
+}
+
+/*
+ * usbvision_write_reg()
+ *
+ * return 1 -> Reg written
+ *        0 -> usbvision is not yet ready
+ *       -1 -> Something went wrong
+ */
+
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+                           unsigned char value)
+{
+       int errCode = 0;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                               USBVISION_OP_CODE,
+                               USB_DIR_OUT | USB_TYPE_VENDOR |
+                               USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
+
+       if (errCode < 0) {
+               err("%s: failed: error %d", __FUNCTION__, errCode);
+       }
+       return errCode;
+}
+
+
+static void usbvision_ctrlUrb_complete(struct urb *urb)
+{
+       struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->ctrlUrbBusy = 0;
+       if (waitqueue_active(&usbvision->ctrlUrb_wq)) {
+               wake_up_interruptible(&usbvision->ctrlUrb_wq);
+       }
+}
+
+
+static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address,
+                                                                       unsigned char *data, int len)
+{
+       int errCode = 0;
+
+       PDEBUG(DBG_IRQ, "");
+       if (len > 8) {
+               return -EFAULT;
+       }
+//     down(&usbvision->ctrlUrbLock);
+       if (usbvision->ctrlUrbBusy) {
+//             up(&usbvision->ctrlUrbLock);
+               return -EBUSY;
+       }
+       usbvision->ctrlUrbBusy = 1;
+//     up(&usbvision->ctrlUrbLock);
+
+       usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+       usbvision->ctrlUrbSetup.bRequest     = USBVISION_OP_CODE;
+       usbvision->ctrlUrbSetup.wValue       = 0;
+       usbvision->ctrlUrbSetup.wIndex       = cpu_to_le16(address);
+       usbvision->ctrlUrbSetup.wLength      = cpu_to_le16(len);
+       usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev,
+                                                       usb_sndctrlpipe(usbvision->dev, 1),
+                                                       (unsigned char *)&usbvision->ctrlUrbSetup,
+                                                       (void *)usbvision->ctrlUrbBuffer, len,
+                                                       usbvision_ctrlUrb_complete,
+                                                       (void *)usbvision);
+
+       memcpy(usbvision->ctrlUrbBuffer, data, len);
+
+       errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC);
+       if (errCode < 0) {
+               // error in usb_submit_urb()
+               usbvision->ctrlUrbBusy = 0;
+       }
+       PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode);
+       return errCode;
+}
+
+
+static int usbvision_init_compression(struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+
+       usbvision->lastIsocFrameNum = -1;
+       usbvision->isocDataCount = 0;
+       usbvision->isocPacketCount = 0;
+       usbvision->isocSkipCount = 0;
+       usbvision->comprLevel = 50;
+       usbvision->lastComprLevel = -1;
+       usbvision->isocUrbCount = 0;
+       usbvision->requestIntra = 1;
+       usbvision->isocMeasureBandwidthCount = 0;
+
+       return errCode;
+}
+
+/* this function measures the used bandwidth since last call
+ * return:    0 : no error
+ * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize
+ */
+static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+
+       if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames
+               usbvision->isocMeasureBandwidthCount++;
+               return errCode;
+       }
+       if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) {
+               usbvision->usedBandwidth = usbvision->isocDataCount /
+                                       (usbvision->isocPacketCount + usbvision->isocSkipCount) *
+                                       100 / usbvision->isocPacketSize;
+       }
+       usbvision->isocMeasureBandwidthCount = 0;
+       usbvision->isocDataCount = 0;
+       usbvision->isocPacketCount = 0;
+       usbvision->isocSkipCount = 0;
+       return errCode;
+}
+
+static int usbvision_adjust_compression (struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+       unsigned char buffer[6];
+
+       PDEBUG(DBG_IRQ, "");
+       if ((adjustCompression) && (usbvision->usedBandwidth > 0)) {
+               usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2;
+               RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100);
+               if (usbvision->comprLevel != usbvision->lastComprLevel) {
+                       int distorsion;
+                       if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) {
+                               buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);      // PCM Threshold 1
+                               buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);       // PCM Threshold 2
+                               distorsion = 7 + 248 * usbvision->comprLevel / 100;
+                               buffer[2] = (unsigned char)(distorsion & 0xFF);                         // Average distorsion Threshold (inter)
+                               buffer[3] = (unsigned char)(distorsion & 0xFF);                         // Average distorsion Threshold (intra)
+                               distorsion = 1 + 42 * usbvision->comprLevel / 100;
+                               buffer[4] = (unsigned char)(distorsion & 0xFF);                         // Maximum distorsion Threshold (inter)
+                               buffer[5] = (unsigned char)(distorsion & 0xFF);                         // Maximum distorsion Threshold (intra)
+                       }
+                       else { //BRIDGE_NT1003
+                               buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);      // PCM threshold 1
+                               buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);       // PCM threshold 2
+                               distorsion = 2 + 253 * usbvision->comprLevel / 100;
+                               buffer[2] = (unsigned char)(distorsion & 0xFF);                         // distorsion threshold bit0-7
+                               buffer[3] = 0;  //(unsigned char)((distorsion >> 8) & 0x0F);            // distorsion threshold bit 8-11
+                               distorsion = 0 + 43 * usbvision->comprLevel / 100;
+                               buffer[4] = (unsigned char)(distorsion & 0xFF);                         // maximum distorsion bit0-7
+                               buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01);             // maximum distorsion bit 8
+                       }
+                       errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
+                       if (errCode == 0){
+                               PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],
+                                                               buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
+                               usbvision->lastComprLevel = usbvision->comprLevel;
+                       }
+               }
+       }
+       return errCode;
+}
+
+static int usbvision_request_intra (struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+       unsigned char buffer[1];
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->requestIntra = 1;
+       buffer[0] = 1;
+       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+       return errCode;
+}
+
+static int usbvision_unrequest_intra (struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+       unsigned char buffer[1];
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->requestIntra = 0;
+       buffer[0] = 0;
+       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+       return errCode;
+}
+
+/*******************************
+ * usbvision utility functions
+ *******************************/
+
+int usbvision_power_off(struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+
+       PDEBUG(DBG_FUNC, "");
+
+       errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+       if (errCode == 1) {
+               usbvision->power = 0;
+       }
+       PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode);
+       return errCode;
+}
+
+/*
+ * usbvision_set_video_format()
+ *
+ */
+static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format)
+{
+       static const char proc[] = "usbvision_set_video_format";
+       int rc;
+       unsigned char value[2];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       PDEBUG(DBG_FUNC, "isocMode %#02x", format);
+
+       if ((format != ISOC_MODE_YUV422)
+           && (format != ISOC_MODE_YUV420)
+           && (format != ISOC_MODE_COMPRESS)) {
+               printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420",
+                      format);
+               format = ISOC_MODE_YUV420;
+       }
+       value[0] = 0x0A;  //TODO: See the effect of the filter
+       value[1] = format;
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_FILT_CONT, value, 2, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+       }
+       usbvision->isocMode = format;
+       return rc;
+}
+
+/*
+ * usbvision_set_output()
+ *
+ */
+
+int usbvision_set_output(struct usb_usbvision *usbvision, int width,
+                        int height)
+{
+       int errCode = 0;
+       int UsbWidth, UsbHeight;
+       unsigned int frameRate=0, frameDrop=0;
+       unsigned char value[4];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision)) {
+               return 0;
+       }
+
+       if (width > MAX_USB_WIDTH) {
+               UsbWidth = width / 2;
+               usbvision->stretch_width = 2;
+       }
+       else {
+               UsbWidth = width;
+               usbvision->stretch_width = 1;
+       }
+
+       if (height > MAX_USB_HEIGHT) {
+               UsbHeight = height / 2;
+               usbvision->stretch_height = 2;
+       }
+       else {
+               UsbHeight = height;
+               usbvision->stretch_height = 1;
+       }
+
+       RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
+       UsbWidth &= ~(MIN_FRAME_WIDTH-1);
+       RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
+       UsbHeight &= ~(1);
+
+       PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",
+                                               UsbWidth, UsbHeight, width, height,
+                                               usbvision->stretch_width, usbvision->stretch_height);
+
+       /* I'll not rewrite the same values */
+       if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) {
+               value[0] = UsbWidth & 0xff;             //LSB
+               value[1] = (UsbWidth >> 8) & 0x03;      //MSB
+               value[2] = UsbHeight & 0xff;            //LSB
+               value[3] = (UsbHeight >> 8) & 0x03;     //MSB
+
+               errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                                0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
+
+               if (errCode < 0) {
+                       err("%s failed: error %d", __FUNCTION__, errCode);
+                       return errCode;
+               }
+               usbvision->curwidth = usbvision->stretch_width * UsbWidth;
+               usbvision->curheight = usbvision->stretch_height * UsbHeight;
+       }
+
+       if (usbvision->isocMode == ISOC_MODE_YUV422) {
+               frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2);
+       }
+       else if (usbvision->isocMode == ISOC_MODE_YUV420) {
+               frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8);
+       }
+       else {
+               frameRate = FRAMERATE_MAX;
+       }
+
+       if (usbvision->tvnorm->id & V4L2_STD_625_50) {
+               frameDrop = frameRate * 32 / 25 - 1;
+       }
+       else if (usbvision->tvnorm->id & V4L2_STD_525_60) {
+               frameDrop = frameRate * 32 / 30 - 1;
+       }
+
+       RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX);
+
+       PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop);
+
+       frameDrop = FRAMERATE_MAX;      // We can allow the maximum here, because dropping is controlled
+
+       /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
+               => frameSkip = 4;
+               => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
+
+          frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
+           => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
+               => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
+       */
+       errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop);
+       return errCode;
+}
+
+
+/*
+ * usbvision_frames_alloc
+ * allocate the maximum frames this driver can manage
+ */
+int usbvision_frames_alloc(struct usb_usbvision *usbvision)
+{
+       int i;
+
+       /* Allocate memory for the frame buffers */
+       usbvision->max_frame_size = MAX_FRAME_SIZE;
+       usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size;
+       usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
+
+       if(usbvision->fbuf == NULL) {
+               err("%s: unable to allocate %d bytes for fbuf ",
+                   __FUNCTION__, usbvision->fbuf_size);
+               return -ENOMEM;
+       }
+       spin_lock_init(&usbvision->queue_lock);
+       init_waitqueue_head(&usbvision->wait_frame);
+       init_waitqueue_head(&usbvision->wait_stream);
+
+       /* Allocate all buffers */
+       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+               usbvision->frame[i].index = i;
+               usbvision->frame[i].grabstate = FrameState_Unused;
+               usbvision->frame[i].data = usbvision->fbuf +
+                       i * usbvision->max_frame_size;
+               /*
+                * Set default sizes for read operation.
+                */
+               usbvision->stretch_width = 1;
+               usbvision->stretch_height = 1;
+               usbvision->frame[i].width = usbvision->curwidth;
+               usbvision->frame[i].height = usbvision->curheight;
+               usbvision->frame[i].bytes_read = 0;
+       }
+       return 0;
+}
+
+/*
+ * usbvision_frames_free
+ * frees memory allocated for the frames
+ */
+void usbvision_frames_free(struct usb_usbvision *usbvision)
+{
+       /* Have to free all that memory */
+       if (usbvision->fbuf != NULL) {
+               usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
+               usbvision->fbuf = NULL;
+       }
+}
+/*
+ * usbvision_empty_framequeues()
+ * prepare queues for incoming and outgoing frames
+ */
+void usbvision_empty_framequeues(struct usb_usbvision *usbvision)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&(usbvision->inqueue));
+       INIT_LIST_HEAD(&(usbvision->outqueue));
+
+       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+               usbvision->frame[i].grabstate = FrameState_Unused;
+               usbvision->frame[i].bytes_read = 0;
+       }
+}
+
+/*
+ * usbvision_stream_interrupt()
+ * stops streaming
+ */
+int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
+{
+       int ret = 0;
+
+       /* stop reading from the device */
+
+       usbvision->streaming = Stream_Interrupt;
+       ret = wait_event_timeout(usbvision->wait_stream,
+                                (usbvision->streaming == Stream_Idle),
+                                msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
+       return ret;
+}
+
+/*
+ * usbvision_set_compress_params()
+ *
+ */
+
+static int usbvision_set_compress_params(struct usb_usbvision *usbvision)
+{
+       static const char proc[] = "usbvision_set_compresion_params: ";
+       int rc;
+       unsigned char value[6];
+
+       value[0] = 0x0F;    // Intra-Compression cycle
+       value[1] = 0x01;    // Reg.45 one line per strip
+       value[2] = 0x00;    // Reg.46 Force intra mode on all new frames
+       value[3] = 0x00;    // Reg.47 FORCE_UP <- 0 normal operation (not force)
+       value[4] = 0xA2;    // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode.
+       value[5] = 0x00;    // Reg.49 DVI_YUV This has nothing to do with compression
+
+       //catched values for NT1004
+       // value[0] = 0xFF; // Never apply intra mode automatically
+       // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip
+       // value[2] = 0x01; // Force intra mode on all new frames
+       // value[3] = 0x00; // Strip size 400 Bytes; do not force up
+       // value[4] = 0xA2; //
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_INTRA_CYC, value, 5, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+       if (usbvision->bridgeType == BRIDGE_NT1004) {
+               value[0] =  20; // PCM Threshold 1
+               value[1] =  12; // PCM Threshold 2
+               value[2] = 255; // Distorsion Threshold inter
+               value[3] = 255; // Distorsion Threshold intra
+               value[4] =  43; // Max Distorsion inter
+               value[5] =  43; // Max Distorsion intra
+       }
+       else {
+               value[0] =  20; // PCM Threshold 1
+               value[1] =  12; // PCM Threshold 2
+               value[2] = 255; // Distorsion Threshold d7-d0
+               value[3] =   0; // Distorsion Threshold d11-d8
+               value[4] =  43; // Max Distorsion d7-d0
+               value[5] =   0; // Max Distorsion d8
+       }
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_PCM_THR1, value, 6, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+
+       return rc;
+}
+
+
+/*
+ * usbvision_set_input()
+ *
+ * Set the input (saa711x, ...) size x y and other misc input params
+ * I've no idea if this parameters are right
+ *
+ */
+int usbvision_set_input(struct usb_usbvision *usbvision)
+{
+       static const char proc[] = "usbvision_set_input: ";
+       int rc;
+       unsigned char value[8];
+       unsigned char dvi_yuv_value;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       /* Set input format expected from decoder*/
+       if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) {
+               value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff;
+       } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
+               /* SAA7113 uses 8 bit output */
+               value[0] = USBVISION_8_422_SYNC;
+       } else {
+               /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses
+                * as that is how saa7111 is configured */
+               value[0] = USBVISION_16_422_SYNC;
+               /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/
+       }
+
+       rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]);
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+
+       if (usbvision->tvnorm->id & V4L2_STD_PAL) {
+               value[0] = 0xC0;
+               value[1] = 0x02;        //0x02C0 -> 704 Input video line length
+               value[2] = 0x20;
+               value[3] = 0x01;        //0x0120 -> 288 Input video n. of lines
+               value[4] = 0x60;
+               value[5] = 0x00;        //0x0060 -> 96 Input video h offset
+               value[6] = 0x16;
+               value[7] = 0x00;        //0x0016 -> 22 Input video v offset
+       } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) {
+               value[0] = 0xC0;
+               value[1] = 0x02;        //0x02C0 -> 704 Input video line length
+               value[2] = 0x20;
+               value[3] = 0x01;        //0x0120 -> 288 Input video n. of lines
+               value[4] = 0x01;
+               value[5] = 0x00;        //0x0001 -> 01 Input video h offset
+               value[6] = 0x01;
+               value[7] = 0x00;        //0x0001 -> 01 Input video v offset
+       } else {        /* V4L2_STD_NTSC */
+               value[0] = 0xD0;
+               value[1] = 0x02;        //0x02D0 -> 720 Input video line length
+               value[2] = 0xF0;
+               value[3] = 0x00;        //0x00F0 -> 240 Input video number of lines
+               value[4] = 0x50;
+               value[5] = 0x00;        //0x0050 -> 80 Input video h offset
+               value[6] = 0x10;
+               value[7] = 0x00;        //0x0010 -> 16 Input video v offset
+       }
+
+       if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) {
+               value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff;
+               value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8;
+       }
+
+       if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) {
+               value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff;
+               value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8;
+       }
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE, /* USBVISION specific code */
+                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_LXSIZE_I, value, 8, HZ);
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+
+       dvi_yuv_value = 0x00;   /* U comes after V, Ya comes after U/V, Yb comes after Yb */
+
+       if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){
+               dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff;
+       }
+       else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
+       /* This changes as the fine sync control changes. Further investigation necessary */
+               dvi_yuv_value = 0x06;
+       }
+
+       return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value));
+}
+
+
+/*
+ * usbvision_set_dram_settings()
+ *
+ * Set the buffer address needed by the usbvision dram to operate
+ * This values has been taken with usbsnoop.
+ *
+ */
+
+static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
+{
+       int rc;
+       unsigned char value[8];
+
+       if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+               value[0] = 0x42;
+               value[1] = 0x71;
+               value[2] = 0xff;
+               value[3] = 0x00;
+               value[4] = 0x98;
+               value[5] = 0xe0;
+               value[6] = 0x71;
+               value[7] = 0xff;
+               // UR:  0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte)
+               // FDL: 0x00000-0x0E099 =  57498 Words
+               // VDW: 0x0E3FF-0x3FFFF
+       }
+       else {
+               value[0] = 0x42;
+               value[1] = 0x00;
+               value[2] = 0xff;
+               value[3] = 0x00;
+               value[4] = 0x00;
+               value[5] = 0x00;
+               value[6] = 0x00;
+               value[7] = 0xff;
+       }
+       /* These are the values of the address of the video buffer,
+        * they have to be loaded into the USBVISION_DRM_PRM1-8
+        *
+        * Start address of video output buffer for read:       drm_prm1-2 -> 0x00000
+        * End address of video output buffer for read:         drm_prm1-3 -> 0x1ffff
+        * Start address of video frame delay buffer:           drm_prm1-4 -> 0x20000
+        *    Only used in compressed mode
+        * End address of video frame delay buffer:             drm_prm1-5-6 -> 0x3ffff
+        *    Only used in compressed mode
+        * Start address of video output buffer for write:      drm_prm1-7 -> 0x00000
+        * End address of video output buffer for write:        drm_prm1-8 -> 0x1ffff
+        */
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE, /* USBVISION specific code */
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
+
+       if (rc < 0) {
+               err("%sERROR=%d", __FUNCTION__, rc);
+               return rc;
+       }
+
+       /* Restart the video buffer logic */
+       if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
+                                  USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0)
+               return rc;
+       rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00);
+
+       return rc;
+}
+
+/*
+ * ()
+ *
+ * Power on the device, enables suspend-resume logic
+ * &  reset the isoc End-Point
+ *
+ */
+
+int usbvision_power_on(struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+
+       PDEBUG(DBG_FUNC, "");
+
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                        USBVISION_SSPND_EN | USBVISION_RES2);
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                        USBVISION_SSPND_EN | USBVISION_PWR_VID);
+       errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                                               USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
+       if (errCode == 1) {
+               usbvision->power = 1;
+       }
+       PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode);
+       return errCode;
+}
+
+
+/*
+ * usbvision timer stuff
+ */
+
+// to call usbvision_power_off from task queue
+static void call_usbvision_power_off(struct work_struct *work)
+{
+       struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork);
+
+       PDEBUG(DBG_FUNC, "");
+       down_interruptible(&usbvision->lock);
+       if(usbvision->user == 0) {
+               usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+
+               usbvision_power_off(usbvision);
+               usbvision->initialized = 0;
+       }
+       up(&usbvision->lock);
+}
+
+static void usbvision_powerOffTimer(unsigned long data)
+{
+       struct usb_usbvision *usbvision = (void *) data;
+
+       PDEBUG(DBG_FUNC, "");
+       del_timer(&usbvision->powerOffTimer);
+       INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off);
+       (void) schedule_work(&usbvision->powerOffWork);
+
+}
+
+void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision)
+{
+       init_timer(&usbvision->powerOffTimer);
+       usbvision->powerOffTimer.data = (long) usbvision;
+       usbvision->powerOffTimer.function = usbvision_powerOffTimer;
+}
+
+void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision)
+{
+       mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME);
+}
+
+void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision)
+{
+       if (timer_pending(&usbvision->powerOffTimer)) {
+               del_timer(&usbvision->powerOffTimer);
+       }
+}
+
+/*
+ * usbvision_begin_streaming()
+ * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no
+ * idea about the rest
+ */
+int usbvision_begin_streaming(struct usb_usbvision *usbvision)
+{
+       int errCode = 0;
+
+       if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+               usbvision_init_compression(usbvision);
+       }
+       errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID |
+                                                                               usbvision->Vin_Reg2_Preset);
+       return errCode;
+}
+
+/*
+ * usbvision_restart_isoc()
+ * Not sure yet if touching here PWR_REG make loose the config
+ */
+
+int usbvision_restart_isoc(struct usb_usbvision *usbvision)
+{
+       int ret;
+
+       if (
+           (ret =
+            usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                             USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0)
+               return ret;
+       if (
+           (ret =
+            usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                             USBVISION_SSPND_EN | USBVISION_PWR_VID |
+                             USBVISION_RES2)) < 0)
+               return ret;
+       if (
+           (ret =
+            usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+                             USBVISION_KEEP_BLANK | USBVISION_NOHVALID |
+                                 usbvision->Vin_Reg2_Preset)) < 0) return ret;
+
+       /* TODO: schedule timeout */
+       while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) && 0x01) != 1);
+
+       return 0;
+}
+
+int usbvision_audio_off(struct usb_usbvision *usbvision)
+{
+       if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) {
+               printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n");
+               return -1;
+       }
+       usbvision->AudioMute = 0;
+       usbvision->AudioChannel = USBVISION_AUDIO_MUTE;
+       return 0;
+}
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel)
+{
+       if (!usbvision->AudioMute) {
+               if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) {
+                       printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n");
+                       return -1;
+               }
+       }
+       usbvision->AudioChannel = AudioChannel;
+       return 0;
+}
+
+int usbvision_setup(struct usb_usbvision *usbvision,int format)
+{
+       usbvision_set_video_format(usbvision, format);
+       usbvision_set_dram_settings(usbvision);
+       usbvision_set_compress_params(usbvision);
+       usbvision_set_input(usbvision);
+       usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT);
+       usbvision_restart_isoc(usbvision);
+
+       /* cosas del PCM */
+       return USBVISION_IS_OPERATIONAL(usbvision);
+}
+
+
+int usbvision_sbuf_alloc(struct usb_usbvision *usbvision)
+{
+       int i, errCode = 0;
+       const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+
+       /* Clean pointers so we know if we allocated something */
+       for (i = 0; i < USBVISION_NUMSBUF; i++)
+               usbvision->sbuf[i].data = NULL;
+
+       for (i = 0; i < USBVISION_NUMSBUF; i++) {
+               usbvision->sbuf[i].data = kzalloc(sb_size, GFP_KERNEL);
+               if (usbvision->sbuf[i].data == NULL) {
+                       err("%s: unable to allocate %d bytes for sbuf", __FUNCTION__, sb_size);
+                       errCode = -ENOMEM;
+                       break;
+               }
+       }
+       return errCode;
+}
+
+
+void usbvision_sbuf_free(struct usb_usbvision *usbvision)
+{
+       int i;
+
+       for (i = 0; i < USBVISION_NUMSBUF; i++) {
+               if (usbvision->sbuf[i].data != NULL) {
+                       kfree(usbvision->sbuf[i].data);
+                       usbvision->sbuf[i].data = NULL;
+               }
+       }
+}
+
+/*
+ * usbvision_init_isoc()
+ *
+ */
+int usbvision_init_isoc(struct usb_usbvision *usbvision)
+{
+       struct usb_device *dev = usbvision->dev;
+       int bufIdx, errCode, regValue;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -EFAULT;
+
+       usbvision->curFrame = NULL;
+       scratch_reset(usbvision);
+
+       /* Alternate interface 1 is is the biggest frame size */
+       errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive);
+       if (errCode < 0) {
+               usbvision->last_error = errCode;
+               return -EBUSY;
+       }
+
+       regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+       usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
+       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+
+       usbvision->usb_bandwidth = regValue >> 1;
+       PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+
+
+
+       /* We double buffer the Iso lists */
+
+       for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+               int j, k;
+               struct urb *urb;
+
+               urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+               if (urb == NULL) {
+                       err("%s: usb_alloc_urb() failed", __FUNCTION__);
+                       return -ENOMEM;
+               }
+               usbvision->sbuf[bufIdx].urb = urb;
+               urb->dev = dev;
+               urb->context = usbvision;
+               urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->interval = 1;
+               urb->transfer_buffer = usbvision->sbuf[bufIdx].data;
+               urb->complete = usbvision_isocIrq;
+               urb->number_of_packets = USBVISION_URB_FRAMES;
+               urb->transfer_buffer_length =
+                   usbvision->isocPacketSize * USBVISION_URB_FRAMES;
+               for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
+                    k += usbvision->isocPacketSize) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length = usbvision->isocPacketSize;
+               }
+       }
+
+
+       /* Submit all URBs */
+       for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+                       errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL);
+               if (errCode) {
+                       err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode);
+               }
+       }
+
+       usbvision->streaming = Stream_Idle;
+       PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
+       return 0;
+}
+
+/*
+ * usbvision_stop_isoc()
+ *
+ * This procedure stops streaming and deallocates URBs. Then it
+ * activates zero-bandwidth alt. setting of the video interface.
+ *
+ */
+void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+{
+       int bufIdx, errCode, regValue;
+
+       if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
+               return;
+
+       /* Unschedule all of the iso td's */
+       for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+               usb_kill_urb(usbvision->sbuf[bufIdx].urb);
+               usb_free_urb(usbvision->sbuf[bufIdx].urb);
+               usbvision->sbuf[bufIdx].urb = NULL;
+       }
+
+
+       PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
+       usbvision->streaming = Stream_Off;
+
+       if (!usbvision->remove_pending) {
+
+               /* Set packet size to 0 */
+               errCode = usb_set_interface(usbvision->dev, usbvision->iface,
+                                     usbvision->ifaceAltInactive);
+               if (errCode < 0) {
+                       err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
+                       usbvision->last_error = errCode;
+               }
+               regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+               usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
+               PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+
+               usbvision->usb_bandwidth = regValue >> 1;
+               PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+       }
+}
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
+{
+       int mode[4];
+       int audio[]= {1, 0, 0, 0};
+       struct v4l2_routing route;
+       //channel 0 is TV with audiochannel 1 (tuner mono)
+       //channel 1 is Composite with audio channel 0 (line in)
+       //channel 2 is S-Video with audio channel 0 (line in)
+       //channel 3 is additional video inputs to the device with audio channel 0 (line in)
+
+       RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
+       usbvision->ctl_input = channel;
+         route.input = SAA7115_COMPOSITE1;
+         call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
+         call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
+
+       // set the new channel
+       // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video
+       // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red
+
+       switch (usbvision_device_data[usbvision->DevModel].Codec) {
+               case CODEC_SAA7113:
+                       if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices.  Use SwitchSVideoInput parameter when loading the module.
+                               mode[2] = 1;
+                       }
+                       else {
+                               mode[2] = 7;
+                       }
+                       if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+                               mode[0] = 0; mode[1] = 2; mode[3] = 3;  // Special for four input devices
+                       }
+                       else {
+                               mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices
+                       }
+                       break;
+               case CODEC_SAA7111:
+                       mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111
+                       break;
+               default:
+                       mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes
+       }
+       route.input = mode[channel];
+       call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
+       usbvision->channel = channel;
+       usbvision_set_audio(usbvision, audio[channel]);
+       return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
new file mode 100644 (file)
index 0000000..92bf9a1
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * I2C_ALGO_USB.C
+ *  i2c algorithm for USB-I2C Bridges
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "usbvision.h"
+
+#define DBG_I2C                1<<0
+#define DBG_ALGO       1<<1
+
+static int i2c_debug = 0;
+
+module_param (i2c_debug, int, 0644);                   // debug_i2c_usb mode of the device driver
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define PDEBUG(level, fmt, args...) \
+               if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+
+static inline int try_write_address(struct i2c_adapter *i2c_adap,
+                                   unsigned char addr, int retries)
+{
+       struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
+       void *data;
+       int i, ret = -1;
+       char buf[4];
+
+       data = i2c_get_adapdata(i2c_adap);
+       buf[0] = 0x00;
+       for (i = 0; i <= retries; i++) {
+               ret = (adap->outb(data, addr, buf, 1));
+               if (ret == 1)
+                       break;  /* success! */
+               udelay(5 /*adap->udelay */ );
+               if (i == retries)       /* no success */
+                       break;
+               udelay(adap->udelay);
+       }
+       if (i) {
+               PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
+               PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
+       }
+       return ret;
+}
+
+static inline int try_read_address(struct i2c_adapter *i2c_adap,
+                                  unsigned char addr, int retries)
+{
+       struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
+       void *data;
+       int i, ret = -1;
+       char buf[4];
+
+       data = i2c_get_adapdata(i2c_adap);
+       for (i = 0; i <= retries; i++) {
+               ret = (adap->inb(data, addr, buf, 1));
+               if (ret == 1)
+                       break;  /* success! */
+               udelay(5 /*adap->udelay */ );
+               if (i == retries)       /* no success */
+                       break;
+               udelay(adap->udelay);
+       }
+       if (i) {
+               PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
+               PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
+       }
+       return ret;
+}
+
+static inline int usb_find_address(struct i2c_adapter *i2c_adap,
+                                  struct i2c_msg *msg, int retries,
+                                  unsigned char *add)
+{
+       unsigned short flags = msg->flags;
+
+       unsigned char addr;
+       int ret;
+       if ((flags & I2C_M_TEN)) {
+               /* a ten bit address */
+               addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+               /* try extended address code... */
+               ret = try_write_address(i2c_adap, addr, retries);
+               if (ret != 1) {
+                       err("died at extended address code, while writing");
+                       return -EREMOTEIO;
+               }
+               add[0] = addr;
+               if (flags & I2C_M_RD) {
+                       /* okay, now switch into reading mode */
+                       addr |= 0x01;
+                       ret = try_read_address(i2c_adap, addr, retries);
+                       if (ret != 1) {
+                               err("died at extended address code, while reading");
+                               return -EREMOTEIO;
+                       }
+               }
+
+       } else {                /* normal 7bit address  */
+               addr = (msg->addr << 1);
+               if (flags & I2C_M_RD)
+                       addr |= 1;
+               if (flags & I2C_M_REV_DIR_ADDR)
+                       addr ^= 1;
+
+               add[0] = addr;
+               if (flags & I2C_M_RD)
+                       ret = try_read_address(i2c_adap, addr, retries);
+               else
+                       ret = try_write_address(i2c_adap, addr, retries);
+
+               if (ret != 1) {
+                       return -EREMOTEIO;
+               }
+       }
+       return 0;
+}
+
+static int
+usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+       struct i2c_msg *pmsg;
+       struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
+       void *data;
+       int i, ret;
+       unsigned char addr;
+
+       data = i2c_get_adapdata(i2c_adap);
+
+       for (i = 0; i < num; i++) {
+               pmsg = &msgs[i];
+               ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
+               if (ret != 0) {
+                       PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i);
+                       return (ret < 0) ? ret : -EREMOTEIO;
+               }
+
+               if (pmsg->flags & I2C_M_RD) {
+                       /* read bytes into buffer */
+                       ret = (adap->inb(data, addr, pmsg->buf, pmsg->len));
+                       if (ret < pmsg->len) {
+                               return (ret < 0) ? ret : -EREMOTEIO;
+                       }
+               } else {
+                       /* write bytes from buffer */
+                       ret = (adap->outb(data, addr, pmsg->buf, pmsg->len));
+                       if (ret < pmsg->len) {
+                               return (ret < 0) ? ret : -EREMOTEIO;
+                       }
+               }
+       }
+       return num;
+}
+
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg)
+{
+       return 0;
+}
+
+static u32 usb_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm i2c_usb_algo = {
+       .master_xfer   = usb_xfer,
+       .smbus_xfer    = NULL,
+       .algo_control  = algo_control,
+       .functionality = usb_func,
+};
+
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap)
+{
+       PDEBUG(DBG_I2C, "I2C   debugging is enabled [i2c]");
+       PDEBUG(DBG_ALGO, "ALGO   debugging is enabled [i2c]");
+
+       /* register new adapter to i2c module... */
+
+       adap->algo = &i2c_usb_algo;
+
+       adap->timeout = 100;    /* default values, should       */
+       adap->retries = 3;      /* be replaced by defines       */
+
+       i2c_add_adapter(adap);
+
+       PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name);
+
+       return 0;
+}
+
+
+int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap)
+{
+
+       i2c_del_adapter(adap);
+
+       PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name);
+
+       return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions                                        */
+/* ----------------------------------------------------------------------- */
+static struct i2c_adapter i2c_adap_template;
+static struct i2c_algo_usb_data i2c_algo_template;
+static struct i2c_client i2c_client_template;
+
+int usbvision_init_i2c(struct usb_usbvision *usbvision)
+{
+       memcpy(&usbvision->i2c_adap, &i2c_adap_template,
+              sizeof(struct i2c_adapter));
+       memcpy(&usbvision->i2c_algo, &i2c_algo_template,
+              sizeof(struct i2c_algo_usb_data));
+       memcpy(&usbvision->i2c_client, &i2c_client_template,
+              sizeof(struct i2c_client));
+
+       sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
+               " #%d", usbvision->vdev->minor & 0x1f);
+       PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
+
+       i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
+       i2c_set_clientdata(&usbvision->i2c_client, usbvision);
+       i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision);
+
+       usbvision->i2c_adap.algo_data = &usbvision->i2c_algo;
+       usbvision->i2c_client.adapter = &usbvision->i2c_adap;
+
+       if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
+               printk(KERN_ERR "usbvision_init_i2c: can't write reg\n");
+               return -EBUSY;
+       }
+
+#ifdef CONFIG_MODULES
+       /* Request the load of the i2c modules we need */
+       switch (usbvision_device_data[usbvision->DevModel].Codec) {
+       case CODEC_SAA7113:
+               request_module("saa7115");
+               break;
+       case CODEC_SAA7111:
+               request_module("saa7115");
+               break;
+       }
+       if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
+               request_module("tuner");
+       }
+#endif
+
+       return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap);
+}
+
+void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,
+                     void *arg)
+{
+       BUG_ON(NULL == usbvision->i2c_adap.algo_data);
+       i2c_clients_command(&usbvision->i2c_adap, cmd, arg);
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+       struct usb_usbvision *usbvision;
+
+       usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
+
+       switch (client->addr << 1) {
+               case 0x43:
+               case 0x4b:
+               {
+                       struct tuner_setup tun_setup;
+
+                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+                       tun_setup.type = TUNER_TDA9887;
+                       tun_setup.addr = client->addr;
+
+                       call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
+
+                       break;
+               }
+               case 0x42:
+                       PDEBUG(DBG_I2C,"attach_inform: saa7114 detected.");
+                       break;
+               case 0x4a:
+                       PDEBUG(DBG_I2C,"attach_inform: saa7113 detected.");
+                       break;
+               case 0xa0:
+                       PDEBUG(DBG_I2C,"attach_inform: eeprom detected.");
+                       break;
+
+               default:
+                       {
+                               struct tuner_setup tun_setup;
+
+                               PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1);
+                               usbvision->tuner_addr = client->addr;
+
+                               if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) {
+                                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+                                       tun_setup.type = usbvision->tuner_type;
+                                       tun_setup.addr = usbvision->tuner_addr;
+                                       call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
+                               }
+                       }
+                       break;
+       }
+       return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+       struct usb_usbvision *usbvision;
+
+       usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
+
+       PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name);
+       return 0;
+}
+
+static int
+usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
+                    char *buf, short len)
+{
+       int rc, retries;
+
+       for (retries = 5;;) {
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr);
+               if (rc < 0)
+                       return rc;
+
+               /* Initiate byte read cycle                    */
+               /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
+               /*                    d3 0=Wr 1=Rd             */
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+                                     (len & 0x07) | 0x18);
+               if (rc < 0)
+                       return rc;
+
+               /* Test for Busy and ACK */
+               do {
+                       /* USBVISION_SER_CONT -> d4 == 0 busy */
+                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+               if (rc < 0)
+                       return rc;
+
+               /* USBVISION_SER_CONT -> d5 == 1 Not ack */
+               if ((rc & 0x20) == 0)   /* Ack? */
+                       break;
+
+               /* I2C abort */
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+               if (rc < 0)
+                       return rc;
+
+               if (--retries < 0)
+                       return -1;
+       }
+
+       switch (len) {
+       case 4:
+               buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4);
+       case 3:
+               buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3);
+       case 2:
+               buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2);
+       case 1:
+               buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1);
+               break;
+       default:
+               printk(KERN_ERR
+                      "usbvision_i2c_read_max4: buffer length > 4\n");
+       }
+
+       if (i2c_debug & DBG_I2C) {
+               int idx;
+               for (idx = 0; idx < len; idx++) {
+                       PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr);
+               }
+       }
+       return len;
+}
+
+
+static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision,
+                                unsigned char addr, const char *buf,
+                                short len)
+{
+       int rc, retries;
+       int i;
+       unsigned char value[6];
+       unsigned char ser_cont;
+
+       ser_cont = (len & 0x07) | 0x10;
+
+       value[0] = addr;
+       value[1] = ser_cont;
+       for (i = 0; i < len; i++)
+               value[i + 2] = buf[i];
+
+       for (retries = 5;;) {
+               rc = usb_control_msg(usbvision->dev,
+                                    usb_sndctrlpipe(usbvision->dev, 1),
+                                    USBVISION_OP_CODE,
+                                    USB_DIR_OUT | USB_TYPE_VENDOR |
+                                    USB_RECIP_ENDPOINT, 0,
+                                    (__u16) USBVISION_SER_ADRS, value,
+                                    len + 2, HZ);
+
+               if (rc < 0)
+                       return rc;
+
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+                                     (len & 0x07) | 0x10);
+               if (rc < 0)
+                       return rc;
+
+               /* Test for Busy and ACK */
+               do {
+                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+               if (rc < 0)
+                       return rc;
+
+               if ((rc & 0x20) == 0)   /* Ack? */
+                       break;
+
+               /* I2C abort */
+               usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+
+               if (--retries < 0)
+                       return -1;
+
+       }
+
+       if (i2c_debug & DBG_I2C) {
+               int idx;
+               for (idx = 0; idx < len; idx++) {
+                       PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr);
+               }
+       }
+       return len;
+}
+
+static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
+                           short len)
+{
+       char *bufPtr = buf;
+       int retval;
+       int wrcount = 0;
+       int count;
+       int maxLen = 4;
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
+
+       while (len > 0) {
+               count = (len > maxLen) ? maxLen : len;
+               retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count);
+               if (retval > 0) {
+                       len -= count;
+                       bufPtr += count;
+                       wrcount += count;
+               } else
+                       return (retval < 0) ? retval : -EFAULT;
+       }
+       return wrcount;
+}
+
+static int usbvision_i2c_read(void *data, unsigned char addr, char *buf,
+                          short len)
+{
+       char temp[4];
+       int retval, i;
+       int rdcount = 0;
+       int count;
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
+
+       while (len > 0) {
+               count = (len > 3) ? 4 : len;
+               retval = usbvision_i2c_read_max4(usbvision, addr, temp, count);
+               if (retval > 0) {
+                       for (i = 0; i < len; i++)
+                               buf[rdcount + i] = temp[i];
+                       len -= count;
+                       rdcount += count;
+               } else
+                       return (retval < 0) ? retval : -EFAULT;
+       }
+       return rdcount;
+}
+
+static struct i2c_algo_usb_data i2c_algo_template = {
+       .data           = NULL,
+       .inb            = usbvision_i2c_read,
+       .outb           = usbvision_i2c_write,
+       .udelay         = 10,
+       .mdelay         = 10,
+       .timeout        = 100,
+};
+
+static struct i2c_adapter i2c_adap_template = {
+       .owner = THIS_MODULE,
+       .name              = "usbvision",
+       .id                = I2C_HW_B_BT848, /* FIXME */
+       .algo              = NULL,
+       .algo_data         = NULL,
+       .client_register   = attach_inform,
+       .client_unregister = detach_inform,
+#ifdef I2C_ADAP_CLASS_TV_ANALOG
+       .class             = I2C_ADAP_CLASS_TV_ANALOG,
+#else
+       .class             = I2C_CLASS_TV_ANALOG,
+#endif
+};
+
+static struct i2c_client i2c_client_template = {
+       .name           = "usbvision internal",
+};
+
+EXPORT_SYMBOL(usbvision_i2c_usb_add_bus);
+EXPORT_SYMBOL(usbvision_i2c_usb_del_bus);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
new file mode 100644 (file)
index 0000000..864446c
--- /dev/null
@@ -0,0 +1,2051 @@
+/*
+ * USB USBVISION Video device driver 0.9.9
+ *
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ *
+ * 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.
+ *
+ * Let's call the version 0.... until compression decoding is completely
+ * implemented.
+ *
+ * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach.
+ * It was based on USB CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt
+ * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler &
+ * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ *
+ * TODO:
+ *     - use submit_urb for all setup packets
+ *     - Fix memory settings for nt1004. It is 4 times as big as the
+ *       nt1003 memory.
+ *     - Add audio on endpoint 3 for nt1004 chip.  Seems impossible, needs a codec interface.  Which one?
+ *     - Clean up the driver.
+ *     - optimization for performance.
+ *     - Add Videotext capability (VBI).  Working on it.....
+ *     - Check audio for other devices
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+#include <linux/videodev.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include "usbvision.h"
+
+#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>"
+#define DRIVER_NAME "usbvision"
+#define DRIVER_ALIAS "USBVision"
+#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
+#define DRIVER_LICENSE "GPL"
+#define USBVISION_DRIVER_VERSION_MAJOR 0
+#define USBVISION_DRIVER_VERSION_MINOR 9
+#define USBVISION_DRIVER_VERSION_PATCHLEVEL 9
+#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+
+#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+       #define PDEBUG(level, fmt, args...) \
+               if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+       #define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+#define DBG_IOCTL      1<<0
+#define DBG_IO         1<<1
+#define DBG_PROBE      1<<2
+#define DBG_MMAP       1<<3
+
+//String operations
+#define rmspace(str)   while(*str==' ') str++;
+#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++;
+
+
+static int usbvision_nr = 0;                   // sequential number of usbvision device
+
+static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+       { 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
+       { 1, 2, 16, V4L2_PIX_FMT_RGB565  , "RGB565" },
+       { 1, 3, 24, V4L2_PIX_FMT_RGB24   , "RGB24" },
+       { 1, 4, 32, V4L2_PIX_FMT_RGB32   , "RGB32" },
+       { 1, 2, 16, V4L2_PIX_FMT_RGB555  , "RGB555" },
+       { 1, 2, 16, V4L2_PIX_FMT_YUYV    , "YUV422" },
+       { 1, 2, 12, V4L2_PIX_FMT_YVU420  , "YUV420P" }, // 1.5 !
+       { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
+};
+
+/* supported tv norms */
+static struct usbvision_tvnorm tvnorms[] = {
+       {
+               .name = "PAL",
+               .id = V4L2_STD_PAL,
+       }, {
+               .name = "NTSC",
+               .id = V4L2_STD_NTSC,
+       }, {
+                .name = "SECAM",
+                .id = V4L2_STD_SECAM,
+       }, {
+               .name = "PAL-M",
+               .id = V4L2_STD_PAL_M,
+       }
+};
+
+#define TVNORMS ARRAY_SIZE(tvnorms)
+
+// Function prototypes
+static void usbvision_release(struct usb_usbvision *usbvision);
+
+// Default initalization of device driver parameters
+static int isocMode = ISOC_MODE_COMPRESS;              // Set the default format for ISOC endpoint
+static int video_debug = 0;                            // Set the default Debug Mode of the device driver
+static int PowerOnAtOpen = 1;                          // Set the default device to power on at startup
+static int video_nr = -1;                              // Sequential Number of Video Device
+static int radio_nr = -1;                              // Sequential Number of Radio Device
+static int vbi_nr = -1;                                        // Sequential Number of VBI Device
+static char *CustomDevice=NULL;                                // Set as nothing....
+
+// Grab parameters for the device driver
+
+#if defined(module_param)                               // Showing parameters under SYSFS
+module_param(isocMode, int, 0444);
+module_param(video_debug, int, 0444);
+module_param(PowerOnAtOpen, int, 0444);
+module_param(video_nr, int, 0444);
+module_param(radio_nr, int, 0444);
+module_param(vbi_nr, int, 0444);
+module_param(CustomDevice, charp, 0444);
+#else                                                  // Old Style
+MODULE_PARAM(isocMode, "i");
+MODULE_PARM(video_debug, "i");                         // Grab the Debug Mode of the device driver
+MODULE_PARM(adjustCompression, "i");                   // Grab the compression to be adaptive
+MODULE_PARM(PowerOnAtOpen, "i");                       // Grab the device to power on at startup
+MODULE_PARM(SwitchSVideoInput, "i");                   // To help people with Black and White output with using s-video input.  Some cables and input device are wired differently.
+MODULE_PARM(video_nr, "i");                            // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...)
+MODULE_PARM(radio_nr, "i");                            // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...)
+MODULE_PARM(vbi_nr, "i");                              // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...)
+MODULE_PARM(CustomDevice, "s");                                // .... CustomDevice
+#endif
+
+MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
+MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver.  Default: 0 (Off)");
+MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened.  Default: 1 (On)");
+MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX).  Default: -1 (autodetect)");
+MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
+MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX).  Default: -1 (autodetect)");
+MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device.  Default: null");
+
+
+// Misc stuff
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_VERSION(USBVISION_VERSION_STRING);
+MODULE_ALIAS(DRIVER_ALIAS);
+
+
+/****************************************************************************************/
+/* SYSFS Code - Copied from the stv680.c usb module.                                   */
+/* Device information is located at /sys/class/video4linux/video0                      */
+/* Device parameters information is located at /sys/module/usbvision                    */
+/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber    */
+/****************************************************************************************/
+
+
+#define YES_NO(x) ((x) ? "Yes" : "No")
+
+static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd)
+{
+       struct video_device *vdev = to_video_device(cd);
+       return video_get_drvdata(vdev);
+}
+
+static ssize_t show_version(struct class_device *cd, char *buf)
+{
+       return sprintf(buf, "%s\n", USBVISION_VERSION_STRING);
+}
+static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+
+static ssize_t show_model(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString);
+}
+static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+
+static ssize_t show_hue(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_HUE;
+       ctrl.value = 0;
+       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
+
+static ssize_t show_contrast(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_CONTRAST;
+       ctrl.value = 0;
+       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
+
+static ssize_t show_brightness(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_BRIGHTNESS;
+       ctrl.value = 0;
+       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
+
+static ssize_t show_saturation(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_SATURATION;
+       ctrl.value = 0;
+       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
+
+static ssize_t show_streaming(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0));
+}
+static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
+
+static ssize_t show_compression(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
+}
+static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
+
+static ssize_t show_device_bridge(struct class_device *class_dev, char *buf)
+{
+       struct video_device *vdev = to_video_device(class_dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%d\n", usbvision->bridgeType);
+}
+static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
+
+static void usbvision_create_sysfs(struct video_device *vdev)
+{
+       int res;
+       if (vdev) {
+               res=video_device_create_file(vdev, &class_device_attr_version);
+               res=video_device_create_file(vdev, &class_device_attr_model);
+               res=video_device_create_file(vdev, &class_device_attr_hue);
+               res=video_device_create_file(vdev, &class_device_attr_contrast);
+               res=video_device_create_file(vdev, &class_device_attr_brightness);
+               res=video_device_create_file(vdev, &class_device_attr_saturation);
+               res=video_device_create_file(vdev, &class_device_attr_streaming);
+               res=video_device_create_file(vdev, &class_device_attr_compression);
+               res=video_device_create_file(vdev, &class_device_attr_bridge);
+       }
+}
+
+static void usbvision_remove_sysfs(struct video_device *vdev)
+{
+       if (vdev) {
+               video_device_remove_file(vdev, &class_device_attr_version);
+               video_device_remove_file(vdev, &class_device_attr_model);
+               video_device_remove_file(vdev, &class_device_attr_hue);
+               video_device_remove_file(vdev, &class_device_attr_contrast);
+               video_device_remove_file(vdev, &class_device_attr_brightness);
+               video_device_remove_file(vdev, &class_device_attr_saturation);
+               video_device_remove_file(vdev, &class_device_attr_streaming);
+               video_device_remove_file(vdev, &class_device_attr_compression);
+               video_device_remove_file(vdev, &class_device_attr_bridge);
+       }
+}
+
+
+/*
+ * usbvision_open()
+ *
+ * This is part of Video 4 Linux API. The driver can be opened by one
+ * client only (checks internal counter 'usbvision->user'). The procedure
+ * then allocates buffers needed for video processing.
+ *
+ */
+static int usbvision_v4l2_open(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+       int errCode = 0;
+
+       PDEBUG(DBG_IO, "open");
+
+
+       usbvision_reset_powerOffTimer(usbvision);
+
+       if (usbvision->user)
+               errCode = -EBUSY;
+       else {
+               /* Allocate memory for the frame buffers */
+               errCode = usbvision_frames_alloc(usbvision);
+               if(!errCode) {
+                       /* Allocate memory for the scratch ring buffer */
+                       errCode = usbvision_scratch_alloc(usbvision);
+                       if(!errCode) {
+                               /* Allocate memory for the USB S buffers */
+                               errCode = usbvision_sbuf_alloc(usbvision);
+                               if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) {
+                                       /* Allocate intermediate decompression buffers only if needed */
+                                       errCode = usbvision_decompress_alloc(usbvision);
+                               }
+                       }
+               }
+               if (errCode) {
+                       /* Deallocate all buffers if trouble */
+                       usbvision_frames_free(usbvision);
+                       usbvision_scratch_free(usbvision);
+                       usbvision_sbuf_free(usbvision);
+                       usbvision_decompress_free(usbvision);
+               }
+       }
+
+       /* If so far no errors then we shall start the camera */
+       if (!errCode) {
+               down(&usbvision->lock);
+               if (usbvision->power == 0) {
+                       usbvision_power_on(usbvision);
+                       usbvision_init_i2c(usbvision);
+               }
+
+               /* Send init sequence only once, it's large! */
+               if (!usbvision->initialized) {
+                       int setup_ok = 0;
+                       setup_ok = usbvision_setup(usbvision,isocMode);
+                       if (setup_ok)
+                               usbvision->initialized = 1;
+                       else
+                               errCode = -EBUSY;
+               }
+
+               if (!errCode) {
+                       usbvision_begin_streaming(usbvision);
+                       errCode = usbvision_init_isoc(usbvision);
+                       /* device needs to be initialized before isoc transfer */
+                       usbvision_muxsel(usbvision,0);
+                       usbvision->user++;
+               }
+               else {
+                       if (PowerOnAtOpen) {
+                               usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+                               usbvision_power_off(usbvision);
+                               usbvision->initialized = 0;
+                       }
+               }
+               up(&usbvision->lock);
+       }
+
+       if (errCode) {
+       }
+
+       /* prepare queues */
+       usbvision_empty_framequeues(usbvision);
+
+       PDEBUG(DBG_IO, "success");
+       return errCode;
+}
+
+/*
+ * usbvision_v4l2_close()
+ *
+ * This is part of Video 4 Linux API. The procedure
+ * stops streaming and deallocates all buffers that were earlier
+ * allocated in usbvision_v4l2_open().
+ *
+ */
+static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+       PDEBUG(DBG_IO, "close");
+       down(&usbvision->lock);
+
+       usbvision_audio_off(usbvision);
+       usbvision_restart_isoc(usbvision);
+       usbvision_stop_isoc(usbvision);
+
+       usbvision_decompress_free(usbvision);
+       usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
+       usbvision_scratch_free(usbvision);
+       usbvision_sbuf_free(usbvision);
+
+       usbvision->user--;
+
+       if (PowerOnAtOpen) {
+               /* power off in a little while to avoid off/on every close/open short sequences */
+               usbvision_set_powerOffTimer(usbvision);
+               usbvision->initialized = 0;
+       }
+
+       up(&usbvision->lock);
+
+       if (usbvision->remove_pending) {
+               info("%s: Final disconnect", __FUNCTION__);
+               usbvision_release(usbvision);
+       }
+
+       PDEBUG(DBG_IO, "success");
+
+
+       return 0;
+}
+
+
+/*
+ * usbvision_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ */
+static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
+                                unsigned int cmd, void *arg)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -EFAULT;
+
+       switch (cmd) {
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+               /* ioctls to allow direct acces to the NT100x registers */
+               case VIDIOC_INT_G_REGISTER:
+               {
+                       struct v4l2_register *reg = arg;
+                       int errCode;
+
+                       if (reg->i2c_id != 0)
+                               return -EINVAL;
+                       /* NT100x has a 8-bit register space */
+                       errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+                       if (errCode < 0) {
+                               err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
+                       }
+                       else {
+                               reg->val=(unsigned char)errCode;
+                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
+                                                       (unsigned int)reg->reg, reg->val);
+                               errCode = 0; // No error
+                       }
+                       return errCode;
+               }
+               case VIDIOC_INT_S_REGISTER:
+               {
+                       struct v4l2_register *reg = arg;
+                       int errCode;
+
+                       if (reg->i2c_id != 0)
+                               return -EINVAL;
+                       if (!capable(CAP_SYS_ADMIN))
+                               return -EPERM;
+                       errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+                       if (errCode < 0) {
+                               err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
+                       }
+                       else {
+                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
+                                                       (unsigned int)reg->reg, reg->val);
+                               errCode = 0;
+                       }
+                       return 0;
+               }
+#endif
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *vc=arg;
+
+                       memset(vc, 0, sizeof(*vc));
+                       strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+                       strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
+                               sizeof(vc->card));
+                       strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+                               sizeof(vc->bus_info));
+                       vc->version = USBVISION_DRIVER_VERSION;
+                       vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_AUDIO |
+                               V4L2_CAP_READWRITE |
+                               V4L2_CAP_STREAMING |
+                               (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+                       PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP");
+                       return 0;
+               }
+               case VIDIOC_ENUMINPUT:
+               {
+                       struct v4l2_input *vi = arg;
+                       int chan;
+
+                       if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
+                               return -EINVAL;
+                       if (usbvision->have_tuner) {
+                               chan = vi->index;
+                       }
+                       else {
+                               chan = vi->index + 1; //skip Television string
+                       }
+                       switch(chan) {
+                               case 0:
+                                       if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+                                               strcpy(vi->name, "White Video Input");
+                                       }
+                                       else {
+                                               strcpy(vi->name, "Television");
+                                               vi->type = V4L2_INPUT_TYPE_TUNER;
+                                               vi->audioset = 1;
+                                               vi->tuner = chan;
+                                               vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM;
+                                       }
+                                       break;
+                               case 1:
+                                       vi->type = V4L2_INPUT_TYPE_CAMERA;
+                                       if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+                                               strcpy(vi->name, "Green Video Input");
+                                       }
+                                       else {
+                                               strcpy(vi->name, "Composite Video Input");
+                                       }
+                                       vi->std = V4L2_STD_PAL;
+                                       break;
+                               case 2:
+                                       vi->type = V4L2_INPUT_TYPE_CAMERA;
+                                       if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+                                               strcpy(vi->name, "Yellow Video Input");
+                                       }
+                                       else {
+                                       strcpy(vi->name, "S-Video Input");
+                                       }
+                                       vi->std = V4L2_STD_PAL;
+                                       break;
+                               case 3:
+                                       vi->type = V4L2_INPUT_TYPE_CAMERA;
+                                       strcpy(vi->name, "Red Video Input");
+                                       vi->std = V4L2_STD_PAL;
+                                       break;
+                       }
+                       PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x",
+                              vi->name, vi->index, vi->tuner,vi->type,(int)vi->std);
+                       return 0;
+               }
+               case VIDIOC_ENUMSTD:
+               {
+                       struct v4l2_standard *e = arg;
+                       unsigned int i;
+                       int ret;
+
+                       i = e->index;
+                       if (i >= TVNORMS)
+                               return -EINVAL;
+                       ret = v4l2_video_std_construct(e, tvnorms[e->index].id,
+                                                      tvnorms[e->index].name);
+                       e->index = i;
+                       if (ret < 0)
+                               return ret;
+                       return 0;
+               }
+               case VIDIOC_G_INPUT:
+               {
+                       int *input = arg;
+                       *input = usbvision->ctl_input;
+                       return 0;
+               }
+               case VIDIOC_S_INPUT:
+               {
+                       int *input = arg;
+                       if ((*input >= usbvision->video_inputs) || (*input < 0) )
+                               return -EINVAL;
+                       usbvision->ctl_input = *input;
+
+                       down(&usbvision->lock);
+                       usbvision_muxsel(usbvision, usbvision->ctl_input);
+                       usbvision_set_input(usbvision);
+                       usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
+                       up(&usbvision->lock);
+                       return 0;
+               }
+               case VIDIOC_G_STD:
+               {
+                       v4l2_std_id *id = arg;
+
+                       *id = usbvision->tvnorm->id;
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name);
+                       return 0;
+               }
+               case VIDIOC_S_STD:
+               {
+                       v4l2_std_id *id = arg;
+                       unsigned int i;
+
+                       for (i = 0; i < TVNORMS; i++)
+                               if (*id == tvnorms[i].id)
+                                       break;
+                       if (i == TVNORMS)
+                               for (i = 0; i < TVNORMS; i++)
+                                       if (*id & tvnorms[i].id)
+                                               break;
+                       if (i == TVNORMS)
+                               return -EINVAL;
+
+                       down(&usbvision->lock);
+                       usbvision->tvnorm = &tvnorms[i];
+
+                       call_i2c_clients(usbvision, VIDIOC_S_STD,
+                                        &usbvision->tvnorm->id);
+
+                       up(&usbvision->lock);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name);
+                       return 0;
+               }
+               case VIDIOC_G_TUNER:
+               {
+                       struct v4l2_tuner *vt = arg;
+
+                       if (!usbvision->have_tuner || vt->index)        // Only tuner 0
+                               return -EINVAL;
+                       strcpy(vt->name, "Television");
+                       /* Let clients fill in the remainder of this struct */
+                       call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc);
+                       return 0;
+               }
+               case VIDIOC_S_TUNER:
+               {
+                       struct v4l2_tuner *vt = arg;
+
+                       // Only no or one tuner for now
+                       if (!usbvision->have_tuner || vt->index)
+                               return -EINVAL;
+                       /* let clients handle this */
+                       call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER");
+                       return 0;
+               }
+               case VIDIOC_G_FREQUENCY:
+               {
+                       struct v4l2_frequency *freq = arg;
+
+                       freq->tuner = 0; // Only one tuner
+                       freq->type = V4L2_TUNER_ANALOG_TV;
+                       freq->frequency = usbvision->freq;
+                       PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
+                       return 0;
+               }
+               case VIDIOC_S_FREQUENCY:
+               {
+                       struct v4l2_frequency *freq = arg;
+
+                       // Only no or one tuner for now
+                       if (!usbvision->have_tuner || freq->tuner)
+                               return -EINVAL;
+
+                       usbvision->freq = freq->frequency;
+                       call_i2c_clients(usbvision, cmd, freq);
+                       PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
+                       return 0;
+               }
+               case VIDIOC_G_AUDIO:
+               {
+                       struct v4l2_audio *v = arg;
+                       memset(v,0, sizeof(v));
+                       strcpy(v->name, "TV");
+                       PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO");
+                       return 0;
+               }
+               case VIDIOC_S_AUDIO:
+               {
+                       struct v4l2_audio *v = arg;
+                       if(v->index) {
+                               return -EINVAL;
+                       }
+                       PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO");
+                       return 0;
+               }
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *ctrl = arg;
+                       int id=ctrl->id;
+
+                       memset(ctrl,0,sizeof(*ctrl));
+                       ctrl->id=id;
+
+                       call_i2c_clients(usbvision, cmd, arg);
+
+                       if (ctrl->type)
+                               return 0;
+                       else
+                               return -EINVAL;
+
+                       PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl = arg;
+                       PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+                       call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+                       return 0;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl = arg;
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+                       call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+                       return 0;
+               }
+               case VIDIOC_REQBUFS:
+               {
+                       struct v4l2_requestbuffers *vr = arg;
+                       int ret;
+
+                       RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+
+                       // Check input validity : the user must do a VIDEO CAPTURE and MMAP method.
+                       if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+                          (vr->memory != V4L2_MEMORY_MMAP))
+                               return -EINVAL;
+
+                       if(usbvision->streaming == Stream_On) {
+                               if ((ret = usbvision_stream_interrupt(usbvision)))
+                                   return ret;
+                       }
+
+                       usbvision_empty_framequeues(usbvision);
+
+                       usbvision->curFrame = NULL;
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count);
+                       return 0;
+               }
+               case VIDIOC_QUERYBUF:
+               {
+                       struct v4l2_buffer *vb = arg;
+                       struct usbvision_frame *frame;
+
+                       // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called)
+
+                       if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+                               return -EINVAL;
+                       }
+                       if(vb->index>=USBVISION_NUMFRAMES)  {
+                               return -EINVAL;
+                       }
+                       // Updating the corresponding frame state
+                       vb->flags = 0;
+                       frame = &usbvision->frame[vb->index];
+                       if(frame->grabstate >= FrameState_Ready)
+                               vb->flags |= V4L2_BUF_FLAG_QUEUED;
+                       if(frame->grabstate >= FrameState_Done)
+                               vb->flags |= V4L2_BUF_FLAG_DONE;
+                       if(frame->grabstate == FrameState_Unused)
+                               vb->flags |= V4L2_BUF_FLAG_MAPPED;
+                       vb->memory = V4L2_MEMORY_MMAP;
+
+                       vb->m.offset = vb->index*usbvision->max_frame_size;
+
+                       vb->memory = V4L2_MEMORY_MMAP;
+                       vb->field = V4L2_FIELD_NONE;
+                       vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel;
+                       vb->timestamp = usbvision->frame[vb->index].timestamp;
+                       vb->sequence = usbvision->frame[vb->index].sequence;
+                       return 0;
+               }
+               case VIDIOC_QBUF:
+               {
+                       struct v4l2_buffer *vb = arg;
+                       struct usbvision_frame *frame;
+                       unsigned long lock_flags;
+
+                       // FIXME : works only on VIDEO_CAPTURE MODE, MMAP.
+                       if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+                               return -EINVAL;
+                       }
+                       if(vb->index>=USBVISION_NUMFRAMES)  {
+                               return -EINVAL;
+                       }
+
+                       frame = &usbvision->frame[vb->index];
+
+                       if (frame->grabstate != FrameState_Unused) {
+                               return -EAGAIN;
+                       }
+
+                       /* Mark it as ready and enqueue frame */
+                       frame->grabstate = FrameState_Ready;
+                       frame->scanstate = ScanState_Scanning;
+                       frame->scanlength = 0;  /* Accumulated in usbvision_parse_data() */
+
+                       vb->flags &= ~V4L2_BUF_FLAG_DONE;
+
+                       /* set v4l2_format index */
+                       frame->v4l2_format = usbvision->palette;
+
+                       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+                       list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
+                       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index);
+                       return 0;
+               }
+               case VIDIOC_DQBUF:
+               {
+                       struct v4l2_buffer *vb = arg;
+                       int ret;
+                       struct usbvision_frame *f;
+                       unsigned long lock_flags;
+
+                       if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       if (list_empty(&(usbvision->outqueue))) {
+                               if (usbvision->streaming == Stream_Idle)
+                                       return -EINVAL;
+                               ret = wait_event_interruptible
+                                       (usbvision->wait_frame,
+                                        !list_empty(&(usbvision->outqueue)));
+                               if (ret)
+                                       return ret;
+                       }
+
+                       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+                       f = list_entry(usbvision->outqueue.next,
+                                      struct usbvision_frame, frame);
+                       list_del(usbvision->outqueue.next);
+                       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+                       f->grabstate = FrameState_Unused;
+
+                       vb->memory = V4L2_MEMORY_MMAP;
+                       vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE;
+                       vb->index = f->index;
+                       vb->sequence = f->sequence;
+                       vb->timestamp = f->timestamp;
+                       vb->field = V4L2_FIELD_NONE;
+                       vb->bytesused = f->scanlength;
+
+                       return 0;
+               }
+               case VIDIOC_STREAMON:
+               {
+                       int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+                       usbvision->streaming = Stream_On;
+
+                       call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON");
+
+                       return 0;
+               }
+               case VIDIOC_STREAMOFF:
+               {
+                       int *type = arg;
+                       int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+                       if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       if(usbvision->streaming == Stream_On) {
+                               usbvision_stream_interrupt(usbvision);
+                               // Stop all video streamings
+                               call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
+                       }
+                       usbvision_empty_framequeues(usbvision);
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF");
+                       return 0;
+               }
+               case VIDIOC_ENUM_FMT:
+               {
+                       struct v4l2_fmtdesc *vfd = arg;
+
+                       if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
+                               return -EINVAL;
+                       }
+                       vfd->flags = 0;
+                       vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
+                       vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
+                       memset(vfd->reserved, 0, sizeof(vfd->reserved));
+                       return 0;
+               }
+               case VIDIOC_G_FMT:
+               {
+                       struct v4l2_format *vf = arg;
+
+                       switch (vf->type) {
+                               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                               {
+                                       vf->fmt.pix.width = usbvision->curwidth;
+                                       vf->fmt.pix.height = usbvision->curheight;
+                                       vf->fmt.pix.pixelformat = usbvision->palette.format;
+                                       vf->fmt.pix.bytesperline =  usbvision->curwidth*usbvision->palette.bytes_per_pixel;
+                                       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight;
+                                       vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+                                       vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
+                                       PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s",
+                                              vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+                                       return 0;
+                               }
+                               default:
+                                       PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type);
+                                       return -EINVAL;
+                       }
+                       return 0;
+               }
+               case VIDIOC_TRY_FMT:
+               case VIDIOC_S_FMT:
+               {
+                       struct v4l2_format *vf = arg;
+                       int formatIdx,ret;
+
+                       switch(vf->type) {
+                               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                               {
+                                       /* Find requested format in available ones */
+                                       for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) {
+                                               if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) {
+                                                       usbvision->palette = usbvision_v4l2_format[formatIdx];
+                                                       break;
+                                               }
+                                       }
+                                       /* robustness */
+                                       if(formatIdx == USBVISION_SUPPORTED_PALETTES) {
+                                               return -EINVAL;
+                                       }
+                                       RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
+                                       RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
+
+                                       vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel;
+                                       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
+
+                                       if(cmd == VIDIOC_TRY_FMT) {
+                                               PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s",
+                                              vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+                                               return 0;
+                                       }
+
+                                       /* stop io in case it is already in progress */
+                                       if(usbvision->streaming == Stream_On) {
+                                               if ((ret = usbvision_stream_interrupt(usbvision)))
+                                                       return ret;
+                                       }
+                                       usbvision_empty_framequeues(usbvision);
+
+                                       usbvision->curFrame = NULL;
+
+                                       // by now we are committed to the new data...
+                                       down(&usbvision->lock);
+                                       usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
+                                       up(&usbvision->lock);
+
+                                       PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s",
+                                              vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+                                       return 0;
+                               }
+                               default:
+                                       return -EINVAL;
+                       }
+               }
+               default:
+                       return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl);
+}
+
+
+static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
+                     size_t count, loff_t *ppos)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+       int noblock = file->f_flags & O_NONBLOCK;
+       unsigned long lock_flags;
+
+       int frmx = -1;
+       int ret,i;
+       struct usbvision_frame *frame;
+
+       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock);
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
+               return -EFAULT;
+
+       /* no stream is running, make it running ! */
+       usbvision->streaming = Stream_On;
+       call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
+
+       /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
+       for(i=0;i<USBVISION_NUMFRAMES;i++) {
+               frame = &usbvision->frame[i];
+               if(frame->grabstate == FrameState_Unused) {
+                       /* Mark it as ready and enqueue frame */
+                       frame->grabstate = FrameState_Ready;
+                       frame->scanstate = ScanState_Scanning;
+                       frame->scanlength = 0;  /* Accumulated in usbvision_parse_data() */
+
+                       /* set v4l2_format index */
+                       frame->v4l2_format = usbvision->palette;
+
+                       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+                       list_add_tail(&frame->frame, &usbvision->inqueue);
+                       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+               }
+       }
+
+       /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */
+       if (list_empty(&(usbvision->outqueue))) {
+               if(noblock)
+                       return -EAGAIN;
+
+               ret = wait_event_interruptible
+                       (usbvision->wait_frame,
+                        !list_empty(&(usbvision->outqueue)));
+               if (ret)
+                       return ret;
+       }
+
+       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+       frame = list_entry(usbvision->outqueue.next,
+                          struct usbvision_frame, frame);
+       list_del(usbvision->outqueue.next);
+       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+       /* An error returns an empty frame */
+       if (frame->grabstate == FrameState_Error) {
+               frame->bytes_read = 0;
+               return 0;
+       }
+
+       PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__,
+                      frame->index, frame->bytes_read, frame->scanlength);
+
+       /* copy bytes to user space; we allow for partials reads */
+       if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
+               count = frame->scanlength - frame->bytes_read;
+
+       if (copy_to_user(buf, frame->data + frame->bytes_read, count)) {
+               return -EFAULT;
+       }
+
+       frame->bytes_read += count;
+       PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__,
+                      (unsigned long)count, frame->bytes_read);
+
+       // For now, forget the frame if it has not been read in one shot.
+/*     if (frame->bytes_read >= frame->scanlength) {// All data has been read */
+               frame->bytes_read = 0;
+
+               /* Mark it as available to be used again. */
+               usbvision->frame[frmx].grabstate = FrameState_Unused;
+/*     } */
+
+       return count;
+}
+
+static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       unsigned long size = vma->vm_end - vma->vm_start,
+               start = vma->vm_start;
+       void *pos;
+       u32 i;
+
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+       down(&usbvision->lock);
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision)) {
+               up(&usbvision->lock);
+               return -EFAULT;
+       }
+
+       if (!(vma->vm_flags & VM_WRITE) ||
+           size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) {
+               up(&usbvision->lock);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+               if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+       if (i == USBVISION_NUMFRAMES) {
+               PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range");
+               up(&usbvision->lock);
+               return -EINVAL;
+       }
+
+       /* VM_IO is eventually going to replace PageReserved altogether */
+       vma->vm_flags |= VM_IO;
+       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+
+       pos = usbvision->frame[i].data;
+       while (size > 0) {
+
+               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+                       PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed");
+                       up(&usbvision->lock);
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       up(&usbvision->lock);
+       return 0;
+}
+
+
+/*
+ * Here comes the stuff for radio on usbvision based devices
+ *
+ */
+static int usbvision_radio_open(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+       struct v4l2_frequency freq;
+       int errCode = 0;
+
+       PDEBUG(DBG_IO, "%s:", __FUNCTION__);
+
+       down(&usbvision->lock);
+
+       if (usbvision->user) {
+               err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
+               errCode = -EBUSY;
+       }
+       else {
+               if(PowerOnAtOpen) {
+                       usbvision_reset_powerOffTimer(usbvision);
+                       if (usbvision->power == 0) {
+                               usbvision_power_on(usbvision);
+                               usbvision_init_i2c(usbvision);
+                       }
+               }
+
+               // If so far no errors then we shall start the radio
+               usbvision->radio = 1;
+               call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
+               freq.frequency = 1517; //SWR3 @ 94.8MHz
+               call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq);
+               usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
+               usbvision->user++;
+       }
+
+       if (errCode) {
+               if (PowerOnAtOpen) {
+                       usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+                       usbvision_power_off(usbvision);
+                       usbvision->initialized = 0;
+               }
+       }
+       up(&usbvision->lock);
+       return errCode;
+}
+
+
+static int usbvision_radio_close(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+       int errCode = 0;
+
+       PDEBUG(DBG_IO, "");
+
+       down(&usbvision->lock);
+
+       usbvision_audio_off(usbvision);
+       usbvision->radio=0;
+       usbvision->user--;
+
+       if (PowerOnAtOpen) {
+               usbvision_set_powerOffTimer(usbvision);
+               usbvision->initialized = 0;
+       }
+
+       up(&usbvision->lock);
+
+       if (usbvision->remove_pending) {
+               info("%s: Final disconnect", __FUNCTION__);
+               usbvision_release(usbvision);
+       }
+
+
+       PDEBUG(DBG_IO, "success");
+
+       return errCode;
+}
+
+static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
+                                unsigned int cmd, void *arg)
+{
+       struct video_device *dev = video_devdata(file);
+       struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -EIO;
+
+       switch (cmd) {
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *vc=arg;
+
+                       memset(vc, 0, sizeof(*vc));
+                       strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+                       strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
+                               sizeof(vc->card));
+                       strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+                               sizeof(vc->bus_info));
+                       vc->version = USBVISION_DRIVER_VERSION;
+                       vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+                       PDEBUG(DBG_IO, "VIDIOC_QUERYCAP");
+                       return 0;
+               }
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *ctrl = arg;
+                       int id=ctrl->id;
+
+                       memset(ctrl,0,sizeof(*ctrl));
+                       ctrl->id=id;
+
+                       call_i2c_clients(usbvision, cmd, arg);
+                       PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
+
+                       if (ctrl->type)
+                               return 0;
+                       else
+                               return -EINVAL;
+
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl = arg;
+
+                       call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+                       PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+                       return 0;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl = arg;
+
+                       call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+                       PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+                       return 0;
+               }
+               case VIDIOC_G_TUNER:
+               {
+                       struct v4l2_tuner *t = arg;
+
+                       if (t->index > 0)
+                               return -EINVAL;
+
+                       memset(t,0,sizeof(*t));
+                       strcpy(t->name, "Radio");
+                       t->type = V4L2_TUNER_RADIO;
+
+                       /* Let clients fill in the remainder of this struct */
+                       call_i2c_clients(usbvision,VIDIOC_G_TUNER,t);
+                       PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc);
+                       return 0;
+               }
+               case VIDIOC_S_TUNER:
+               {
+                       struct v4l2_tuner *vt = arg;
+
+                       // Only no or one tuner for now
+                       if (!usbvision->have_tuner || vt->index)
+                               return -EINVAL;
+                       /* let clients handle this */
+                       call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+
+                       PDEBUG(DBG_IO, "VIDIOC_S_TUNER");
+                       return 0;
+               }
+               case VIDIOC_G_AUDIO:
+               {
+                       struct v4l2_audio *a = arg;
+
+                       memset(a,0,sizeof(*a));
+                       strcpy(a->name,"Radio");
+                       PDEBUG(DBG_IO, "VIDIOC_G_AUDIO");
+                       return 0;
+               }
+               case VIDIOC_S_AUDIO:
+               case VIDIOC_S_INPUT:
+               case VIDIOC_S_STD:
+               return 0;
+
+               case VIDIOC_G_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
+
+                       memset(f,0,sizeof(*f));
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = usbvision->freq;
+                       call_i2c_clients(usbvision, cmd, f);
+                       PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency);
+
+                       return 0;
+               }
+               case VIDIOC_S_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
+
+                       if (f->tuner != 0)
+                               return -EINVAL;
+                       usbvision->freq = f->frequency;
+                       call_i2c_clients(usbvision, cmd, f);
+                       PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency);
+
+                       return 0;
+               }
+               default:
+               {
+                       PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd);
+                       return -ENOIOCTLCMD;
+               }
+       }
+       return 0;
+}
+
+
+static int usbvision_radio_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl);
+}
+
+
+/*
+ * Here comes the stuff for vbi on usbvision based devices
+ *
+ */
+static int usbvision_vbi_open(struct inode *inode, struct file *file)
+{
+       /* TODO */
+       return -EINVAL;
+
+}
+
+static int usbvision_vbi_close(struct inode *inode, struct file *file)
+{
+       /* TODO */
+       return -EINVAL;
+}
+
+static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file,
+                                unsigned int cmd, void *arg)
+{
+       /* TODO */
+       return -EINVAL;
+}
+
+static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl);
+}
+
+
+//
+// Video registration stuff
+//
+
+// Video template
+static struct file_operations usbvision_fops = {
+       .owner             = THIS_MODULE,
+       .open           = usbvision_v4l2_open,
+       .release        = usbvision_v4l2_close,
+       .read           = usbvision_v4l2_read,
+       .mmap           = usbvision_v4l2_mmap,
+       .ioctl          = usbvision_v4l2_ioctl,
+       .llseek         = no_llseek,
+};
+static struct video_device usbvision_video_template = {
+       .owner             = THIS_MODULE,
+       .type           = VID_TYPE_TUNER | VID_TYPE_CAPTURE,
+       .hardware       = VID_HARDWARE_USBVISION,
+       .fops           = &usbvision_fops,
+       .name           = "usbvision-video",
+       .release        = video_device_release,
+       .minor          = -1,
+};
+
+
+// Radio template
+static struct file_operations usbvision_radio_fops = {
+       .owner             = THIS_MODULE,
+       .open           = usbvision_radio_open,
+       .release        = usbvision_radio_close,
+       .ioctl          = usbvision_radio_ioctl,
+       .llseek         = no_llseek,
+};
+
+static struct video_device usbvision_radio_template=
+{
+       .owner             = THIS_MODULE,
+       .type           = VID_TYPE_TUNER,
+       .hardware       = VID_HARDWARE_USBVISION,
+       .fops           = &usbvision_radio_fops,
+       .release        = video_device_release,
+       .name           = "usbvision-radio",
+       .minor          = -1,
+};
+
+
+// vbi template
+static struct file_operations usbvision_vbi_fops = {
+       .owner             = THIS_MODULE,
+       .open           = usbvision_vbi_open,
+       .release        = usbvision_vbi_close,
+       .ioctl          = usbvision_vbi_ioctl,
+       .llseek         = no_llseek,
+};
+
+static struct video_device usbvision_vbi_template=
+{
+       .owner             = THIS_MODULE,
+       .type           = VID_TYPE_TUNER,
+       .hardware       = VID_HARDWARE_USBVISION,
+       .fops           = &usbvision_vbi_fops,
+       .release        = video_device_release,
+       .name           = "usbvision-vbi",
+       .minor          = -1,
+};
+
+
+static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
+                                       struct video_device *vdev_template,
+                                       char *name)
+{
+       struct usb_device *usb_dev = usbvision->dev;
+       struct video_device *vdev;
+
+       if (usb_dev == NULL) {
+               err("%s: usbvision->dev is not set", __FUNCTION__);
+               return NULL;
+       }
+
+       vdev = video_device_alloc();
+       if (NULL == vdev) {
+               return NULL;
+       }
+       *vdev = *vdev_template;
+//     vdev->minor   = -1;
+       vdev->dev     = &usb_dev->dev;
+       snprintf(vdev->name, sizeof(vdev->name), "%s", name);
+       video_set_drvdata(vdev, usbvision);
+       return vdev;
+}
+
+// unregister video4linux devices
+static void usbvision_unregister_video(struct usb_usbvision *usbvision)
+{
+       // vbi Device:
+       if (usbvision->vbi) {
+               PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f);
+               if (usbvision->vbi->minor != -1) {
+                       video_unregister_device(usbvision->vbi);
+               }
+               else {
+                       video_device_release(usbvision->vbi);
+               }
+               usbvision->vbi = NULL;
+       }
+
+       // Radio Device:
+       if (usbvision->rdev) {
+               PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f);
+               if (usbvision->rdev->minor != -1) {
+                       video_unregister_device(usbvision->rdev);
+               }
+               else {
+                       video_device_release(usbvision->rdev);
+               }
+               usbvision->rdev = NULL;
+       }
+
+       // Video Device:
+       if (usbvision->vdev) {
+               PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f);
+               if (usbvision->vdev->minor != -1) {
+                       video_unregister_device(usbvision->vdev);
+               }
+               else {
+                       video_device_release(usbvision->vdev);
+               }
+               usbvision->vdev = NULL;
+       }
+}
+
+// register video4linux devices
+static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
+{
+       // Video Device:
+       usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video");
+       if (usbvision->vdev == NULL) {
+               goto err_exit;
+       }
+       if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) {
+               goto err_exit;
+       }
+       info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f);
+
+       // Radio Device:
+       if (usbvision_device_data[usbvision->DevModel].Radio) {
+               // usbvision has radio
+               usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio");
+               if (usbvision->rdev == NULL) {
+                       goto err_exit;
+               }
+               if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) {
+                       goto err_exit;
+               }
+               info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f);
+       }
+       // vbi Device:
+       if (usbvision_device_data[usbvision->DevModel].vbi) {
+               usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI");
+               if (usbvision->vdev == NULL) {
+                       goto err_exit;
+               }
+               if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) {
+                       goto err_exit;
+               }
+               info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f);
+       }
+       // all done
+       return 0;
+
+ err_exit:
+       err("USBVision[%d]: video_register_device() failed", usbvision->nr);
+       usbvision_unregister_video(usbvision);
+       return -1;
+}
+
+/*
+ * usbvision_alloc()
+ *
+ * This code allocates the struct usb_usbvision. It is filled with default values.
+ *
+ * Returns NULL on error, a pointer to usb_usbvision else.
+ *
+ */
+static struct usb_usbvision *usbvision_alloc(struct usb_device *dev)
+{
+       struct usb_usbvision *usbvision;
+
+       if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) {
+               goto err_exit;
+       }
+
+       usbvision->dev = dev;
+
+       init_MUTEX(&usbvision->lock);   /* to 1 == available */
+
+       // prepare control urb for control messages during interrupts
+       usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+       if (usbvision->ctrlUrb == NULL) {
+               goto err_exit;
+       }
+       init_waitqueue_head(&usbvision->ctrlUrb_wq);
+       init_MUTEX(&usbvision->ctrlUrbLock);    /* to 1 == available */
+
+       usbvision_init_powerOffTimer(usbvision);
+
+       return usbvision;
+
+err_exit:
+       if (usbvision && usbvision->ctrlUrb) {
+               usb_free_urb(usbvision->ctrlUrb);
+       }
+       if (usbvision) {
+               kfree(usbvision);
+       }
+       return NULL;
+}
+
+/*
+ * usbvision_release()
+ *
+ * This code does final release of struct usb_usbvision. This happens
+ * after the device is disconnected -and- all clients closed their files.
+ *
+ */
+static void usbvision_release(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_PROBE, "");
+
+       down(&usbvision->lock);
+
+       usbvision_reset_powerOffTimer(usbvision);
+
+       usbvision->initialized = 0;
+
+       up(&usbvision->lock);
+
+       usbvision_remove_sysfs(usbvision->vdev);
+       usbvision_unregister_video(usbvision);
+
+       if (usbvision->ctrlUrb) {
+               usb_free_urb(usbvision->ctrlUrb);
+       }
+
+       kfree(usbvision);
+
+       PDEBUG(DBG_PROBE, "success");
+}
+
+
+/******************************** usb interface *****************************************/
+
+static void usbvision_configure_video(struct usb_usbvision *usbvision)
+{
+       int model,i;
+
+       if (usbvision == NULL)
+               return;
+
+       model = usbvision->DevModel;
+       usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
+
+       if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) {
+               usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff;
+       } else {
+               usbvision->Vin_Reg2_Preset = 0;
+       }
+
+       for (i = 0; i < TVNORMS; i++)
+               if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode)
+                       break;
+       if (i == TVNORMS)
+               i = 0;
+       usbvision->tvnorm = &tvnorms[i];        /* set default norm */
+
+       usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
+       usbvision->ctl_input = 0;
+
+       /* This should be here to make i2c clients to be able to register */
+       usbvision_audio_off(usbvision); //first switch off audio
+       if (!PowerOnAtOpen) {
+               usbvision_power_on(usbvision);  //and then power up the noisy tuner
+               usbvision_init_i2c(usbvision);
+       }
+}
+
+/*
+ * usbvision_probe()
+ *
+ * This procedure queries device descriptor and accepts the interface
+ * if it looks like USBVISION video device
+ *
+ */
+static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
+       const struct usb_host_interface *interface;
+       struct usb_usbvision *usbvision = NULL;
+       const struct usb_endpoint_descriptor *endpoint;
+       int model;
+
+       PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
+                                       dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+       /* Is it an USBVISION video dev? */
+       model = 0;
+       for(model = 0; usbvision_device_data[model].idVendor; model++) {
+               if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) {
+                       continue;
+               }
+               if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) {
+                       continue;
+               }
+
+               info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString);
+               break;
+       }
+
+       if (usbvision_device_data[model].idVendor == 0) {
+               return -ENODEV; //no matching device
+       }
+       if (usbvision_device_data[model].Interface >= 0) {
+               interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0];
+       }
+       else {
+               interface = &dev->actconfig->interface[ifnum]->altsetting[0];
+       }
+       endpoint = &interface->endpoint[1].desc;
+       if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) {
+               err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum);
+               err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes);
+               return -ENODEV;
+       }
+       if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+               err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum);
+               return -ENODEV;
+       }
+
+       usb_get_dev(dev);
+
+       if ((usbvision = usbvision_alloc(dev)) == NULL) {
+               err("%s: couldn't allocate USBVision struct", __FUNCTION__);
+               return -ENOMEM;
+       }
+       if (dev->descriptor.bNumConfigurations > 1) {
+               usbvision->bridgeType = BRIDGE_NT1004;
+       }
+       else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") {
+               usbvision->bridgeType = BRIDGE_NT1005;
+       }
+       else {
+               usbvision->bridgeType = BRIDGE_NT1003;
+       }
+       PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType);
+
+       down(&usbvision->lock);
+
+       usbvision->nr = usbvision_nr++;
+
+       usbvision->have_tuner = usbvision_device_data[model].Tuner;
+       if (usbvision->have_tuner) {
+               usbvision->tuner_type = usbvision_device_data[model].TunerType;
+       }
+
+       usbvision->tuner_addr = ADDR_UNSET;
+
+       usbvision->DevModel = model;
+       usbvision->remove_pending = 0;
+       usbvision->iface = ifnum;
+       usbvision->ifaceAltInactive = 0;
+       usbvision->ifaceAltActive = 1;
+       usbvision->video_endp = endpoint->bEndpointAddress;
+       usbvision->isocPacketSize = 0;
+       usbvision->usb_bandwidth = 0;
+       usbvision->user = 0;
+       usbvision->streaming = Stream_Off;
+       usbvision_register_video(usbvision);
+       usbvision_configure_video(usbvision);
+       up(&usbvision->lock);
+
+
+       usb_set_intfdata (intf, usbvision);
+       usbvision_create_sysfs(usbvision->vdev);
+
+       PDEBUG(DBG_PROBE, "success");
+       return 0;
+}
+
+
+/*
+ * usbvision_disconnect()
+ *
+ * This procedure stops all driver activity, deallocates interface-private
+ * structure (pointed by 'ptr') and after that driver should be removable
+ * with no ill consequences.
+ *
+ */
+static void __devexit usbvision_disconnect(struct usb_interface *intf)
+{
+       struct usb_usbvision *usbvision = usb_get_intfdata(intf);
+
+       PDEBUG(DBG_PROBE, "");
+
+       if (usbvision == NULL) {
+               err("%s: usb_get_intfdata() failed", __FUNCTION__);
+               return;
+       }
+       usb_set_intfdata (intf, NULL);
+
+       down(&usbvision->lock);
+
+       // At this time we ask to cancel outstanding URBs
+       usbvision_stop_isoc(usbvision);
+
+       if (usbvision->power) {
+               usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+               usbvision_power_off(usbvision);
+       }
+       usbvision->remove_pending = 1;  // Now all ISO data will be ignored
+
+       usb_put_dev(usbvision->dev);
+       usbvision->dev = NULL;  // USB device is no more
+
+       up(&usbvision->lock);
+
+       if (usbvision->user) {
+               info("%s: In use, disconnect pending", __FUNCTION__);
+               wake_up_interruptible(&usbvision->wait_frame);
+               wake_up_interruptible(&usbvision->wait_stream);
+       }
+       else {
+               usbvision_release(usbvision);
+       }
+
+       PDEBUG(DBG_PROBE, "success");
+
+}
+
+static struct usb_driver usbvision_driver = {
+       .name           = "usbvision",
+       .id_table       = usbvision_table,
+       .probe          = usbvision_probe,
+       .disconnect     = usbvision_disconnect
+};
+
+/*
+ * customdevice_process()
+ *
+ * This procedure preprocesses CustomDevice parameter if any
+ *
+ */
+void customdevice_process(void)
+{
+       usbvision_device_data[0]=usbvision_device_data[1];
+       usbvision_table[0]=usbvision_table[1];
+
+       if(CustomDevice)
+       {
+               char *parse=CustomDevice;
+
+               PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice);
+
+               /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1"
+               usbvision_device_data[0].idVendor;
+               usbvision_device_data[0].idProduct;
+               usbvision_device_data[0].Interface;
+               usbvision_device_data[0].Codec;
+               usbvision_device_data[0].VideoChannels;
+               usbvision_device_data[0].VideoNorm;
+               usbvision_device_data[0].AudioChannels;
+               usbvision_device_data[0].Radio;
+               usbvision_device_data[0].Tuner;
+               usbvision_device_data[0].TunerType;
+               usbvision_device_data[0].Vin_Reg1;
+               usbvision_device_data[0].Vin_Reg2;
+               usbvision_device_data[0].X_Offset;
+               usbvision_device_data[0].Y_Offset;
+               usbvision_device_data[0].Dvi_yuv;
+               usbvision_device_data[0].ModelString;
+               */
+
+               rmspace(parse);
+               usbvision_device_data[0].ModelString="USBVISION Custom Device";
+
+               parse+=2;
+               sscanf(parse,"%x",&usbvision_device_data[0].idVendor);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor);
+               parse+=2;
+               sscanf(parse,"%x",&usbvision_device_data[0].idProduct);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct);
+               sscanf(parse,"%d",&usbvision_device_data[0].Interface);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface);
+               sscanf(parse,"%d",&usbvision_device_data[0].Codec);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec);
+               sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels);
+
+               switch(*parse)
+               {
+                       case 'P':
+                               PDEBUG(DBG_PROBE, "VideoNorm=PAL");
+                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL;
+                               break;
+
+                       case 'S':
+                               PDEBUG(DBG_PROBE, "VideoNorm=SECAM");
+                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM;
+                               break;
+
+                       case 'N':
+                               PDEBUG(DBG_PROBE, "VideoNorm=NTSC");
+                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC;
+                               break;
+
+                       default:
+                               PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)");
+                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL;
+                               break;
+               }
+               goto2next(parse);
+
+               sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels);
+               sscanf(parse,"%d",&usbvision_device_data[0].Radio);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio);
+               sscanf(parse,"%d",&usbvision_device_data[0].Tuner);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner);
+               sscanf(parse,"%d",&usbvision_device_data[0].TunerType);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType);
+               sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1);
+               sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2);
+               sscanf(parse,"%d",&usbvision_device_data[0].X_Offset);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset);
+               sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset);
+               goto2next(parse);
+               PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset);
+               sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv);
+               PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv);
+
+               //add to usbvision_table also
+               usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE;
+               usbvision_table[0].idVendor=usbvision_device_data[0].idVendor;
+               usbvision_table[0].idProduct=usbvision_device_data[0].idProduct;
+
+       }
+}
+
+
+
+/*
+ * usbvision_init()
+ *
+ * This code is run to initialize the driver.
+ *
+ */
+static int __init usbvision_init(void)
+{
+       int errCode;
+
+       PDEBUG(DBG_PROBE, "");
+
+       PDEBUG(DBG_IOCTL, "IOCTL   debugging is enabled [video]");
+       PDEBUG(DBG_IO,  "IO      debugging is enabled [video]");
+       PDEBUG(DBG_PROBE, "PROBE   debugging is enabled [video]");
+       PDEBUG(DBG_MMAP, "MMAP    debugging is enabled [video]");
+
+       /* disable planar mode support unless compression enabled */
+       if (isocMode != ISOC_MODE_COMPRESS ) {
+               // FIXME : not the right way to set supported flag
+               usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420
+               usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P
+       }
+
+       customdevice_process();
+
+       errCode = usb_register(&usbvision_driver);
+
+       if (errCode == 0) {
+               info(DRIVER_DESC " : " USBVISION_VERSION_STRING);
+               PDEBUG(DBG_PROBE, "success");
+       }
+       return errCode;
+}
+
+static void __exit usbvision_exit(void)
+{
+ PDEBUG(DBG_PROBE, "");
+
+ usb_deregister(&usbvision_driver);
+ PDEBUG(DBG_PROBE, "success");
+}
+
+module_init(usbvision_init);
+module_exit(usbvision_exit);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
new file mode 100644 (file)
index 0000000..0e7e3d6
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * USBVISION.H
+ *  usbvision header file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ *
+ * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ * v4l2 conversion by Thierry Merle <thierry.merle@free.fr>
+ *
+ * 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.
+ */
+
+
+#ifndef __LINUX_USBVISION_H
+#define __LINUX_USBVISION_H
+
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <linux/videodev2.h>
+
+#define USBVISION_DEBUG                /* Turn on debug messages */
+
+#ifndef VID_HARDWARE_USBVISION
+       #define VID_HARDWARE_USBVISION 34   /* USBVision Video Grabber */
+#endif
+
+#define USBVISION_PWR_REG              0x00
+       #define USBVISION_SSPND_EN              (1 << 1)
+       #define USBVISION_RES2                  (1 << 2)
+       #define USBVISION_PWR_VID               (1 << 5)
+       #define USBVISION_E2_EN                 (1 << 7)
+#define USBVISION_CONFIG_REG           0x01
+#define USBVISION_ADRS_REG             0x02
+#define USBVISION_ALTER_REG            0x03
+#define USBVISION_FORCE_ALTER_REG      0x04
+#define USBVISION_STATUS_REG           0x05
+#define USBVISION_IOPIN_REG            0x06
+       #define USBVISION_IO_1                  (1 << 0)
+       #define USBVISION_IO_2                  (1 << 1)
+       #define USBVISION_AUDIO_IN              0
+       #define USBVISION_AUDIO_TV              1
+       #define USBVISION_AUDIO_RADIO           2
+       #define USBVISION_AUDIO_MUTE            3
+#define USBVISION_SER_MODE             0x07
+#define USBVISION_SER_ADRS             0x08
+#define USBVISION_SER_CONT             0x09
+#define USBVISION_SER_DAT1             0x0A
+#define USBVISION_SER_DAT2             0x0B
+#define USBVISION_SER_DAT3             0x0C
+#define USBVISION_SER_DAT4             0x0D
+#define USBVISION_EE_DATA              0x0E
+#define USBVISION_EE_LSBAD             0x0F
+#define USBVISION_EE_CONT              0x10
+#define USBVISION_DRM_CONT                     0x12
+       #define USBVISION_REF                   (1 << 0)
+       #define USBVISION_RES_UR                (1 << 2)
+       #define USBVISION_RES_FDL               (1 << 3)
+       #define USBVISION_RES_VDW               (1 << 4)
+#define USBVISION_DRM_PRM1             0x13
+#define USBVISION_DRM_PRM2             0x14
+#define USBVISION_DRM_PRM3             0x15
+#define USBVISION_DRM_PRM4             0x16
+#define USBVISION_DRM_PRM5             0x17
+#define USBVISION_DRM_PRM6             0x18
+#define USBVISION_DRM_PRM7             0x19
+#define USBVISION_DRM_PRM8             0x1A
+#define USBVISION_VIN_REG1             0x1B
+       #define USBVISION_8_422_SYNC            0x01
+       #define USBVISION_16_422_SYNC           0x02
+       #define USBVISION_VSNC_POL              (1 << 3)
+       #define USBVISION_HSNC_POL              (1 << 4)
+       #define USBVISION_FID_POL               (1 << 5)
+       #define USBVISION_HVALID_PO             (1 << 6)
+       #define USBVISION_VCLK_POL              (1 << 7)
+#define USBVISION_VIN_REG2             0x1C
+       #define USBVISION_AUTO_FID              (1 << 0)
+       #define USBVISION_NONE_INTER            (1 << 1)
+       #define USBVISION_NOHVALID              (1 << 2)
+       #define USBVISION_UV_ID                 (1 << 3)
+       #define USBVISION_FIX_2C                (1 << 4)
+       #define USBVISION_SEND_FID              (1 << 5)
+       #define USBVISION_KEEP_BLANK            (1 << 7)
+#define USBVISION_LXSIZE_I             0x1D
+#define USBVISION_MXSIZE_I             0x1E
+#define USBVISION_LYSIZE_I             0x1F
+#define USBVISION_MYSIZE_I             0x20
+#define USBVISION_LX_OFFST             0x21
+#define USBVISION_MX_OFFST             0x22
+#define USBVISION_LY_OFFST             0x23
+#define USBVISION_MY_OFFST             0x24
+#define USBVISION_FRM_RATE             0x25
+#define USBVISION_LXSIZE_O             0x26
+#define USBVISION_MXSIZE_O             0x27
+#define USBVISION_LYSIZE_O             0x28
+#define USBVISION_MYSIZE_O             0x29
+#define USBVISION_FILT_CONT            0x2A
+#define USBVISION_VO_MODE              0x2B
+#define USBVISION_INTRA_CYC            0x2C
+#define USBVISION_STRIP_SZ             0x2D
+#define USBVISION_FORCE_INTRA          0x2E
+#define USBVISION_FORCE_UP             0x2F
+#define USBVISION_BUF_THR              0x30
+#define USBVISION_DVI_YUV              0x31
+#define USBVISION_AUDIO_CONT           0x32
+#define USBVISION_AUD_PK_LEN           0x33
+#define USBVISION_BLK_PK_LEN           0x34
+#define USBVISION_PCM_THR1             0x38
+#define USBVISION_PCM_THR2             0x39
+#define USBVISION_DIST_THR_L           0x3A
+#define USBVISION_DIST_THR_H           0x3B
+#define USBVISION_MAX_DIST_L           0x3C
+#define USBVISION_MAX_DIST_H           0x3D
+#define USBVISION_OP_CODE              0x33
+
+#define MAX_BYTES_PER_PIXEL            4
+
+#define MIN_FRAME_WIDTH                        64
+#define MAX_USB_WIDTH                  320  //384
+#define MAX_FRAME_WIDTH                        320  //384                      /*streching sometimes causes crashes*/
+
+#define MIN_FRAME_HEIGHT               48
+#define MAX_USB_HEIGHT                 240  //288
+#define MAX_FRAME_HEIGHT               240  //288                      /*Streching sometimes causes crashes*/
+
+#define MAX_FRAME_SIZE                 (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
+#define USBVISION_CLIPMASK_SIZE                (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
+
+#define USBVISION_URB_FRAMES           32
+#define USBVISION_MAX_ISOC_PACKET_SIZE         959                     // NT1003 Specs Document says 1023
+
+#define USBVISION_NUM_HEADERMARKER     20
+#define USBVISION_NUMFRAMES            3  /* Maximum number of frames an application can get */
+#define USBVISION_NUMSBUF              2 /* Dimensioning the USB S buffering */
+
+#define USBVISION_POWEROFF_TIME                3 * (HZ)                // 3 seconds
+
+
+#define FRAMERATE_MIN  0
+#define FRAMERATE_MAX  31
+
+enum {
+       ISOC_MODE_YUV422 = 0x03,
+       ISOC_MODE_YUV420 = 0x14,
+       ISOC_MODE_COMPRESS = 0x60,
+};
+
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+
+/*
+ * We use macros to do YUV -> RGB conversion because this is
+ * very important for speed and totally unimportant for size.
+ *
+ * YUV -> RGB Conversion
+ * ---------------------
+ *
+ * B = 1.164*(Y-16)                + 2.018*(V-128)
+ * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
+ * R = 1.164*(Y-16) + 1.596*(U-128)
+ *
+ * If you fancy integer arithmetics (as you should), hear this:
+ *
+ * 65536*B = 76284*(Y-16)                + 132252*(V-128)
+ * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
+ * 65536*R = 76284*(Y-16) + 104595*(U-128)
+ *
+ * Make sure the output values are within [0..255] range.
+ */
+#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
+#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
+    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
+    mm_y = (my) - 16;  \
+    mm_u = (mu) - 128; \
+    mm_v = (mv) - 128; \
+    mm_yc= mm_y * 76284; \
+    mm_b = (mm_yc              + 132252*mm_v   ) >> 16; \
+    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v  ) >> 16; \
+    mm_r = (mm_yc + 104595*mm_u                        ) >> 16; \
+    mb = LIMIT_RGB(mm_b); \
+    mg = LIMIT_RGB(mm_g); \
+    mr = LIMIT_RGB(mm_r); \
+}
+
+/* Debugging aid */
+#define USBVISION_SAY_AND_WAIT(what) { \
+       wait_queue_head_t wq; \
+       init_waitqueue_head(&wq); \
+       printk(KERN_INFO "Say: %s\n", what); \
+       interruptible_sleep_on_timeout (&wq, HZ*3); \
+}
+
+/*
+ * This macro checks if usbvision is still operational. The 'usbvision'
+ * pointer must be valid, usbvision->dev must be valid, we are not
+ * removing the device and the device has not erred on us.
+ */
+#define USBVISION_IS_OPERATIONAL(udevice) (\
+       (udevice != NULL) && \
+       ((udevice)->dev != NULL) && \
+       ((udevice)->last_error == 0) && \
+       (!(udevice)->remove_pending))
+
+/* I2C structures */
+struct i2c_algo_usb_data {
+       void *data;             /* private data for lowlevel routines */
+       int (*inb) (void *data, unsigned char addr, char *buf, short len);
+       int (*outb) (void *data, unsigned char addr, char *buf, short len);
+
+       /* local settings */
+       int udelay;
+       int mdelay;
+       int timeout;
+};
+
+#define I2C_USB_ADAP_MAX       16
+
+/* ----------------------------------------------------------------- */
+/* usbvision video structures                                        */
+/* ----------------------------------------------------------------- */
+enum ScanState {
+       ScanState_Scanning,     /* Scanning for header */
+       ScanState_Lines         /* Parsing lines */
+};
+
+/* Completion states of the data parser */
+enum ParseState {
+       ParseState_Continue,    /* Just parse next item */
+       ParseState_NextFrame,   /* Frame done, send it to V4L */
+       ParseState_Out,         /* Not enough data for frame */
+       ParseState_EndParse     /* End parsing */
+};
+
+enum FrameState {
+       FrameState_Unused,      /* Unused (no MCAPTURE) */
+       FrameState_Ready,       /* Ready to start grabbing */
+       FrameState_Grabbing,    /* In the process of being grabbed into */
+       FrameState_Done,        /* Finished grabbing, but not been synced yet */
+       FrameState_DoneHold,    /* Are syncing or reading */
+       FrameState_Error,       /* Something bad happened while processing */
+};
+
+/* stream states */
+enum StreamState {
+       Stream_Off,             /* Driver streaming is completely OFF */
+       Stream_Idle,            /* Driver streaming is ready to be put ON by the application */
+       Stream_Interrupt,       /* Driver streaming must be interrupted */
+       Stream_On,              /* Driver streaming is put ON by the application */
+};
+
+enum IsocState {
+       IsocState_InFrame,      /* Isoc packet is member of frame */
+       IsocState_NoFrame,      /* Isoc packet is not member of any frame */
+};
+
+struct usb_device;
+
+struct usbvision_sbuf {
+       char *data;
+       struct urb *urb;
+};
+
+#define USBVISION_MAGIC_1                              0x55
+#define USBVISION_MAGIC_2                              0xAA
+#define USBVISION_HEADER_LENGTH                        0x0c
+#define USBVISION_SAA7111_ADDR                 0x48
+#define USBVISION_SAA7113_ADDR                 0x4a
+#define USBVISION_IIC_LRACK                    0x20
+#define USBVISION_IIC_LRNACK                   0x30
+#define USBVISION_FRAME_FORMAT_PARAM_INTRA     (1<<7)
+
+struct usbvision_v4l2_format_st {
+       int             supported;
+       int             bytes_per_pixel;
+       int             depth;
+       int             format;
+       char            *desc;
+};
+#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format)
+
+struct usbvision_frame_header {
+       unsigned char magic_1;                          /* 0 magic */
+       unsigned char magic_2;                          /* 1  magic */
+       unsigned char headerLength;                     /* 2 */
+       unsigned char frameNum;                         /* 3 */
+       unsigned char framePhase;                       /* 4 */
+       unsigned char frameLatency;                     /* 5 */
+       unsigned char dataFormat;                       /* 6 */
+       unsigned char formatParam;                      /* 7 */
+       unsigned char frameWidthLo;                     /* 8 */
+       unsigned char frameWidthHi;                     /* 9 */
+       unsigned char frameHeightLo;                    /* 10 */
+       unsigned char frameHeightHi;                    /* 11 */
+       __u16 frameWidth;                               /* 8 - 9 after endian correction*/
+       __u16 frameHeight;                              /* 10 - 11 after endian correction*/
+};
+
+/* tvnorms */
+struct usbvision_tvnorm {
+       char *name;
+       v4l2_std_id id;
+       /* mode for saa7113h */
+       int mode;
+};
+
+struct usbvision_frame {
+       char *data;                                     /* Frame buffer */
+       struct usbvision_frame_header isocHeader;       /* Header from stream */
+
+       int width;                                      /* Width application is expecting */
+       int height;                                     /* Height */
+       int index;                                      /* Frame index */
+       int frmwidth;                                   /* Width the frame actually is */
+       int frmheight;                                  /* Height */
+
+       volatile int grabstate;                         /* State of grabbing */
+       int scanstate;                                  /* State of scanning */
+
+       struct list_head frame;
+
+       int curline;                                    /* Line of frame we're working on */
+
+       long scanlength;                                /* uncompressed, raw data length of frame */
+       long bytes_read;                                /* amount of scanlength that has been read from data */
+       struct usbvision_v4l2_format_st v4l2_format;    /* format the user needs*/
+       int v4l2_linesize;                              /* bytes for one videoline*/
+       struct timeval timestamp;
+       int sequence;                                   // How many video frames we send to user
+};
+
+#define CODEC_SAA7113  7113
+#define CODEC_SAA7111  7111
+#define BRIDGE_NT1003  1003
+#define BRIDGE_NT1004  1004
+#define BRIDGE_NT1005   1005
+
+struct usbvision_device_data_st {
+       int idVendor;
+       int idProduct;
+       int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
+       int Codec;
+       int VideoChannels;
+       __u64 VideoNorm;
+       int AudioChannels;
+       int Radio;
+       int vbi;
+       int Tuner;
+       int TunerType;
+       int Vin_Reg1;
+       int Vin_Reg2;
+       int X_Offset;
+       int Y_Offset;
+       int Dvi_yuv;
+       char *ModelString;
+};
+
+/* Declared on usbvision-cards.c */
+extern struct usbvision_device_data_st usbvision_device_data[];
+extern struct usb_device_id usbvision_table[];
+
+struct usb_usbvision {
+       struct video_device *vdev;                                      /* Video Device */
+       struct video_device *rdev;                                      /* Radio Device */
+       struct video_device *vbi;                                       /* VBI Device   */
+
+       /* i2c Declaration Section*/
+       struct i2c_adapter i2c_adap;
+       struct i2c_algo_usb_data i2c_algo;
+       struct i2c_client i2c_client;
+
+       struct urb *ctrlUrb;
+       unsigned char ctrlUrbBuffer[8];
+       int ctrlUrbBusy;
+       struct usb_ctrlrequest ctrlUrbSetup;
+       wait_queue_head_t ctrlUrb_wq;                                   // Processes waiting
+       struct semaphore ctrlUrbLock;
+
+       /* configuration part */
+       int have_tuner;
+       int tuner_type;
+       int tuner_addr;
+       int bridgeType;                                                 // NT1003, NT1004, NT1005
+       int channel;
+       int radio;
+       int video_inputs;                                               // # of inputs
+       unsigned long freq;
+       int AudioMute;
+       int AudioChannel;
+       int isocMode;                                                   // format of video data for the usb isoc-transfer
+       unsigned int nr;                                                // Number of the device
+
+       /* Device structure */
+       struct usb_device *dev;
+       unsigned char iface;                                            /* Video interface number */
+       unsigned char ifaceAltActive, ifaceAltInactive;                 /* Alt settings */
+       unsigned char Vin_Reg2_Preset;
+       struct semaphore lock;
+       struct timer_list powerOffTimer;
+       struct work_struct powerOffWork;
+       int power;                                                      /* is the device powered on? */
+       int user;                                                       /* user count for exclusive use */
+       int initialized;                                                /* Had we already sent init sequence? */
+       int DevModel;                                                   /* What type of USBVISION device we got? */
+       enum StreamState streaming;                                     /* Are we streaming Isochronous? */
+       int last_error;                                                 /* What calamity struck us? */
+       int curwidth;                                                   /* width of the frame the device is currently set to*/
+       int curheight;                                                  /* height of the frame the device is currently set to*/
+       int stretch_width;                                              /* stretch-factor for frame width (from usb to screen)*/
+       int stretch_height;                                             /* stretch-factor for frame height (from usb to screen)*/
+       char *fbuf;                                                     /* Videodev buffer area for mmap*/
+       int max_frame_size;                                             /* Bytes in one video frame */
+       int fbuf_size;                                                  /* Videodev buffer size */
+       spinlock_t queue_lock;                                          /* spinlock for protecting mods on inqueue and outqueue */
+       struct list_head inqueue, outqueue;                             /* queued frame list and ready to dequeue frame list */
+       wait_queue_head_t wait_frame;                                   /* Processes waiting */
+       wait_queue_head_t wait_stream;                                  /* Processes waiting */
+       struct usbvision_frame *curFrame;                               // pointer to current frame, set by usbvision_find_header
+       struct usbvision_frame frame[USBVISION_NUMFRAMES];              // frame buffer
+       struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];                  // S buffering
+       volatile int remove_pending;                                    /* If set then about to exit */
+
+       /* Scratch space from the Isochronous Pipe.*/
+       unsigned char *scratch;
+       int scratch_read_ptr;
+       int scratch_write_ptr;
+       int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
+       int scratch_headermarker_read_ptr;
+       int scratch_headermarker_write_ptr;
+       enum IsocState isocstate;
+       struct usbvision_v4l2_format_st palette;
+
+       struct v4l2_capability vcap;                                    /* Video capabilities */
+       unsigned int ctl_input;                                         /* selected input */
+       struct usbvision_tvnorm *tvnorm;                                /* selected tv norm */
+       unsigned char video_endp;                                       /* 0x82 for USBVISION devices based */
+
+       // Decompression stuff:
+       unsigned char *IntraFrameBuffer;                                /* Buffer for reference frame */
+       int BlockPos;                                                   //for test only
+       int requestIntra;                                               // 0 = normal; 1 = intra frame is requested;
+       int lastIsocFrameNum;                                           // check for lost isoc frames
+       int isocPacketSize;                                             // need to calculate usedBandwidth
+       int usedBandwidth;                                              // used bandwidth 0-100%, need to set comprLevel
+       int comprLevel;                                                 // How strong (100) or weak (0) is compression
+       int lastComprLevel;                                             // How strong (100) or weak (0) was compression
+       int usb_bandwidth;                                              /* Mbit/s */
+
+       /* Statistics that can be overlayed on the screen */
+       unsigned long isocUrbCount;                     // How many URBs we received so far
+       unsigned long urb_length;                       /* Length of last URB */
+       unsigned long isocDataCount;                    /* How many bytes we received */
+       unsigned long header_count;                     /* How many frame headers we found */
+       unsigned long scratch_ovf_count;                /* How many times we overflowed scratch */
+       unsigned long isocSkipCount;                    /* How many empty ISO packets received */
+       unsigned long isocErrCount;                     /* How many bad ISO packets received */
+       unsigned long isocPacketCount;                  // How many packets we totally got
+       unsigned long timeInIrq;                        // How long do we need for interrupt
+       int isocMeasureBandwidthCount;
+       int frame_num;                                  // How many video frames we send to user
+       int maxStripLen;                                // How big is the biggest strip
+       int comprBlockPos;
+       int stripLenErrors;                             // How many times was BlockPos greater than StripLen
+       int stripMagicErrors;
+       int stripLineNumberErrors;
+       int ComprBlockTypes[4];
+};
+
+
+/* --------------------------------------------------------------- */
+/* defined in usbvision-i2c.c                                      */
+/* i2c-algo-usb declaration                                        */
+/* --------------------------------------------------------------- */
+
+int usbvision_i2c_usb_add_bus(struct i2c_adapter *);
+int usbvision_i2c_usb_del_bus(struct i2c_adapter *);
+
+static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev)
+{
+       return dev->data;
+}
+
+static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data)
+{
+       dev->data = data;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions                                        */
+/* ----------------------------------------------------------------------- */
+int usbvision_init_i2c(struct usb_usbvision *usbvision);
+void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg);
+
+/* defined in usbvision-core.c                                      */
+void *usbvision_rvmalloc(unsigned long size);
+void usbvision_rvfree(void *mem, unsigned long size);
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+                       unsigned char value);
+
+int usbvision_frames_alloc(struct usb_usbvision *usbvision);
+void usbvision_frames_free(struct usb_usbvision *usbvision);
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
+void usbvision_scratch_free(struct usb_usbvision *usbvision);
+int usbvision_sbuf_alloc(struct usb_usbvision *usbvision);
+void usbvision_sbuf_free(struct usb_usbvision *usbvision);
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
+void usbvision_decompress_free(struct usb_usbvision *usbvision);
+
+int usbvision_setup(struct usb_usbvision *usbvision,int format);
+int usbvision_init_isoc(struct usb_usbvision *usbvision);
+int usbvision_restart_isoc(struct usb_usbvision *usbvision);
+void usbvision_stop_isoc(struct usb_usbvision *usbvision);
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
+int usbvision_audio_off(struct usb_usbvision *usbvision);
+
+int usbvision_begin_streaming(struct usb_usbvision *usbvision);
+void usbvision_empty_framequeues(struct usb_usbvision *dev);
+int usbvision_stream_interrupt(struct usb_usbvision *dev);
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
+int usbvision_set_input(struct usb_usbvision *usbvision);
+int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
+
+void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision);
+void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision);
+void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision);
+int usbvision_power_off(struct usb_usbvision *usbvision);
+int usbvision_power_on(struct usb_usbvision *usbvision);
+
+#endif                                                                 /* __LINUX_USBVISION_H */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index 1d899e2..8a13e59 100644 (file)
@@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                struct video_buffer     *buffer = arg;
 
                memset(buffer, 0, sizeof(*buffer));
+               memset(&fbuf2, 0, sizeof(fbuf2));
 
                err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
                if (err < 0) {
@@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        case VIDIOCSPICT: /*  set tone controls & partial capture format  */
        {
                struct video_picture    *pict = arg;
+               memset(&fbuf2, 0, sizeof(fbuf2));
 
                set_v4l_control(inode, file,
                                V4L2_CID_BRIGHTNESS, pict->brightness, drv);
@@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        }
        case VIDIOCSTUNER: /*  select a tuner input  */
        {
-               err = 0;
+               struct video_tuner      *tun = arg;
+               struct v4l2_tuner       t;
+               memset(&t,0,sizeof(t));
+
+               t.index=tun->tuner;
+
+               err = drv(inode, file, VIDIOC_S_INPUT, &t);
+               if (err < 0)
+                       dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+
                break;
        }
        case VIDIOCGFREQ: /*  get frequency  */
        {
                unsigned long *freq = arg;
+               memset(&freq2,0,sizeof(freq2));
 
                freq2.tuner = 0;
                err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
@@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        case VIDIOCSFREQ: /*  set frequency  */
        {
                unsigned long *freq = arg;
+               memset(&freq2,0,sizeof(freq2));
 
-               freq2.tuner = 0;
                drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
                freq2.frequency = *freq;
                err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
@@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        case VIDIOCGAUDIO: /*  get audio properties/controls  */
        {
                struct video_audio      *aud = arg;
+               memset(&aud2,0,sizeof(aud2));
 
                err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
                if (err < 0) {
@@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        {
                int                     *i = arg;
 
+               memset(&buf2,0,sizeof(buf2));
                buf2.index = *i;
                buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
index 78d28b0..752c82c 100644 (file)
@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL");
  */
 
 
+char *v4l2_norm_to_name(v4l2_std_id id)
+{
+       char *name;
+
+       switch (id) {
+       case V4L2_STD_PAL:
+               name="PAL";             break;
+       case V4L2_STD_PAL_BG:
+               name="PAL-BG";          break;
+       case V4L2_STD_PAL_DK:
+               name="PAL-DK";          break;
+       case V4L2_STD_PAL_B:
+               name="PAL-B";           break;
+       case V4L2_STD_PAL_B1:
+               name="PAL-B1";          break;
+       case V4L2_STD_PAL_G:
+               name="PAL-G";           break;
+       case V4L2_STD_PAL_H:
+               name="PAL-H";           break;
+       case V4L2_STD_PAL_I:
+               name="PAL-I";           break;
+       case V4L2_STD_PAL_D:
+               name="PAL-D";           break;
+       case V4L2_STD_PAL_D1:
+               name="PAL-D1";          break;
+       case V4L2_STD_PAL_K:
+               name="PAL-K";           break;
+       case V4L2_STD_PAL_M:
+               name="PAL-M";           break;
+       case V4L2_STD_PAL_N:
+               name="PAL-N";           break;
+       case V4L2_STD_PAL_Nc:
+               name="PAL-Nc";          break;
+       case V4L2_STD_PAL_60:
+               name="PAL-60";          break;
+       case V4L2_STD_NTSC:
+               name="NTSC";            break;
+       case V4L2_STD_NTSC_M:
+               name="NTSC-M";          break;
+       case V4L2_STD_NTSC_M_JP:
+               name="NTSC-M-JP";       break;
+       case V4L2_STD_NTSC_443:
+               name="NTSC-443";        break;
+       case V4L2_STD_NTSC_M_KR:
+               name="NTSC-M-KR";       break;
+       case V4L2_STD_SECAM:
+               name="SECAM";           break;
+       case V4L2_STD_SECAM_DK:
+               name="SECAM-DK";        break;
+       case V4L2_STD_SECAM_B:
+               name="SECAM-B";         break;
+       case V4L2_STD_SECAM_D:
+               name="SECAM-D";         break;
+       case V4L2_STD_SECAM_G:
+               name="SECAM-G";         break;
+       case V4L2_STD_SECAM_H:
+               name="SECAM-H";         break;
+       case V4L2_STD_SECAM_K:
+               name="SECAM-K";         break;
+       case V4L2_STD_SECAM_K1:
+               name="SECAM-K1";        break;
+       case V4L2_STD_SECAM_L:
+               name="SECAM-L";         break;
+       case V4L2_STD_SECAM_LC:
+               name="SECAM-LC";        break;
+       default:
+               name="Unknown";         break;
+       }
+
+       return name;
+}
+
 /* Fill in the fields of a v4l2_standard structure according to the
    'id' and 'transmission' parameters.  Returns negative on error.  */
 int v4l2_video_std_construct(struct v4l2_standard *vs,
@@ -184,11 +256,13 @@ char *v4l2_field_names[] = {
 };
 
 char *v4l2_type_names[] = {
-       [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
-       [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
-       [V4L2_BUF_TYPE_VIDEO_OUTPUT]  = "video-out",
-       [V4L2_BUF_TYPE_VBI_CAPTURE]   = "vbi-cap",
-       [V4L2_BUF_TYPE_VBI_OUTPUT]    = "vbi-out",
+       [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "video-cap",
+       [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "video-over",
+       [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "video-out",
+       [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
+       [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
+       [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
+       [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "slicec-vbi-out",
 };
 
 static char *v4l2_memory_names[] = {
@@ -1451,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
 
 /* ----------------------------------------------------------------- */
 
+EXPORT_SYMBOL(v4l2_norm_to_name);
 EXPORT_SYMBOL(v4l2_video_std_construct);
 
 EXPORT_SYMBOL(v4l2_prio_init);
index f53edf1..fcc5467 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/fs.h>
 #include <linux/kthread.h>
 #include <linux/file.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 
 #include <media/video-buf.h>
 #include <media/video-buf-dvb.h>
index d424a41..6a0e8ca 100644 (file)
@@ -105,7 +105,7 @@ static DEFINE_MUTEX(videodev_lock);
 
 struct video_device* video_devdata(struct file *file)
 {
-       return video_device[iminor(file->f_dentry->d_inode)];
+       return video_device[iminor(file->f_path.dentry->d_inode)];
 }
 
 /*
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
 
        dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
                "bytesused=%d, flags=0x%08d, "
-               "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
+               "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
                        (p->timestamp.tv_sec/3600),
                        (int)(p->timestamp.tv_sec/60)%60,
                        (int)(p->timestamp.tv_sec%60),
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
                        p->bytesused,p->flags,
                        p->field,p->sequence,
                        prt_names(p->memory,v4l2_memory_names),
-                       p->m.userptr);
+                       p->m.userptr, p->length);
        dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
                "flags=0x%08d, frames=%d, userbits=0x%08x\n",
                        tc->hours,tc->minutes,tc->seconds,
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s,
 static inline void v4l_print_pix_fmt (struct video_device *vfd,
                                                struct v4l2_pix_format *fmt)
 {
-       dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
+       dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "
                "bytesperline=%d sizeimage=%d, colorspace=%d\n",
-               fmt->width,fmt->height,fmt->pixelformat,
+               fmt->width,fmt->height,
+               (fmt->pixelformat & 0xff),
+               (fmt->pixelformat >>  8) & 0xff,
+               (fmt->pixelformat >> 16) & 0xff,
+               (fmt->pixelformat >> 24) & 0xff,
                prt_names(fmt->field,v4l2_field_names_FIXME),
                fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
 };
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                v4l_print_ioctl(vfd->name, cmd);
        }
 
+       if (_IOC_TYPE(cmd)=='v')
+               return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                               __video_do_ioctl);
+
        switch(cmd) {
        /* --- capabilities ------------------------------------------ */
        case VIDIOC_QUERYCAP:
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                }
                if (!ret)
                        dbgarg (cmd, "index=%d, type=%d, flags=%d, "
-                                       "description=%s,"
-                                       " pixelformat=0x%8x\n",
+                                       "pixelformat=%c%c%c%c, description='%s'\n",
                                        f->index, f->type, f->flags,
-                                       f->description,
-                                       f->pixelformat);
-
+                                       (f->pixelformat & 0xff),
+                                       (f->pixelformat >>  8) & 0xff,
+                                       (f->pixelformat >> 16) & 0xff,
+                                       (f->pixelformat >> 24) & 0xff,
+                                       f->description);
                break;
        }
        case VIDIOC_G_FMT:
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_ENUMSTD:
        {
                struct v4l2_standard *p = arg;
-               unsigned int index = p->index;
+               v4l2_std_id id = vfd->tvnorms,curr_id=0;
+               unsigned int index = p->index,i;
 
-               if (!vfd->tvnormsize) {
-                       printk (KERN_WARNING "%s: no TV norms defined!\n",
-                                               vfd->name);
+               if (index<0) {
+                       ret=-EINVAL;
                        break;
                }
 
-               if (index<0 || index >= vfd->tvnormsize) {
-                       ret=-EINVAL;
-                       break;
+               /* Return norm array on a canonical way */
+               for (i=0;i<= index && id; i++) {
+                       if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
+                               curr_id = V4L2_STD_PAL;
+                       } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
+                               curr_id = V4L2_STD_PAL_BG;
+                       } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
+                               curr_id = V4L2_STD_PAL_DK;
+                       } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
+                               curr_id = V4L2_STD_PAL_B;
+                       } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
+                               curr_id = V4L2_STD_PAL_B1;
+                       } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
+                               curr_id = V4L2_STD_PAL_G;
+                       } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
+                               curr_id = V4L2_STD_PAL_H;
+                       } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
+                               curr_id = V4L2_STD_PAL_I;
+                       } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
+                               curr_id = V4L2_STD_PAL_D;
+                       } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
+                               curr_id = V4L2_STD_PAL_D1;
+                       } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
+                               curr_id = V4L2_STD_PAL_K;
+                       } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
+                               curr_id = V4L2_STD_PAL_M;
+                       } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
+                               curr_id = V4L2_STD_PAL_N;
+                       } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
+                               curr_id = V4L2_STD_PAL_Nc;
+                       } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
+                               curr_id = V4L2_STD_PAL_60;
+                       } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+                               curr_id = V4L2_STD_NTSC;
+                       } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
+                               curr_id = V4L2_STD_NTSC_M;
+                       } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
+                               curr_id = V4L2_STD_NTSC_M_JP;
+                       } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
+                               curr_id = V4L2_STD_NTSC_443;
+                       } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
+                               curr_id = V4L2_STD_NTSC_M_KR;
+                       } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
+                               curr_id = V4L2_STD_SECAM;
+                       } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
+                               curr_id = V4L2_STD_SECAM_DK;
+                       } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
+                               curr_id = V4L2_STD_SECAM_B;
+                       } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
+                               curr_id = V4L2_STD_SECAM_D;
+                       } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
+                               curr_id = V4L2_STD_SECAM_G;
+                       } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
+                               curr_id = V4L2_STD_SECAM_H;
+                       } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
+                               curr_id = V4L2_STD_SECAM_K;
+                       } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
+                               curr_id = V4L2_STD_SECAM_K1;
+                       } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
+                               curr_id = V4L2_STD_SECAM_L;
+                       } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
+                               curr_id = V4L2_STD_SECAM_LC;
+                       } else {
+                               break;
+                       }
+                       id &= ~curr_id;
                }
-               v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
-                                        vfd->tvnorms[p->index].name);
+               if (i<=index)
+                       return -EINVAL;
+
+               v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
                p->index = index;
 
                dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        }
        case VIDIOC_S_STD:
        {
-               v4l2_std_id *id = arg;
-               unsigned int i;
-
-               if (!vfd->tvnormsize) {
-                       printk (KERN_WARNING "%s: no TV norms defined!\n",
-                                               vfd->name);
-                       break;
-               }
+               v4l2_std_id *id = arg,norm;
 
                dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
 
-               /* First search for exact match */
-               for (i = 0; i < vfd->tvnormsize; i++)
-                       if (*id == vfd->tvnorms[i].id)
-                               break;
-               /* Then for a generic video std that contains desired std */
-               if (i == vfd->tvnormsize)
-                       for (i = 0; i < vfd->tvnormsize; i++)
-                               if (*id & vfd->tvnorms[i].id)
-                                       break;
-               if (i == vfd->tvnormsize) {
+               norm = (*id) & vfd->tvnorms;
+               if ( vfd->tvnorms && !norm)     /* Check if std is supported */
                        break;
-               }
 
                /* Calls the specific handler */
                if (vfd->vidioc_s_std)
-                       ret=vfd->vidioc_s_std(file, fh, i);
+                       ret=vfd->vidioc_s_std(file, fh, &norm);
                else
                        ret=-EINVAL;
 
                /* Updates standard information */
-               if (!ret)
-                       vfd->current_norm=*id;
+               if (ret>=0)
+                       vfd->current_norm=norm;
 
                break;
        }
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_G_AUDIO:
        {
                struct v4l2_audio *p=arg;
+               __u32 index=p->index;
 
                if (!vfd->vidioc_g_audio)
                        break;
+
+               memset(p,0,sizeof(*p));
+               p->index=index;
                dbgarg(cmd, "Get for index=%d\n", p->index);
                ret=vfd->vidioc_g_audio(file, fh, p);
                if (!ret)
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                        ret=vfd->vidioc_g_parm(file, fh, p);
                } else {
                        struct v4l2_standard s;
-                       int i;
-
-                       if (!vfd->tvnormsize) {
-                               printk (KERN_WARNING "%s: no TV norms defined!\n",
-                                                       vfd->name);
-                               break;
-                       }
 
                        if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                                return -EINVAL;
 
-                       for (i = 0; i < vfd->tvnormsize; i++)
-                               if (vfd->tvnorms[i].id == vfd->current_norm)
-                                       break;
-                       if (i >= vfd->tvnormsize)
-                               return -EINVAL;
-
                        v4l2_video_std_construct(&s, vfd->current_norm,
-                                                vfd->tvnorms[i].name);
+                                                v4l2_norm_to_name(vfd->current_norm));
 
                        memset(p,0,sizeof(*p));
 
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_G_TUNER:
        {
                struct v4l2_tuner *p=arg;
+               __u32 index=p->index;
+
                if (!vfd->vidioc_g_tuner)
                        break;
+
+               memset(p,0,sizeof(*p));
+               p->index=index;
+
                ret=vfd->vidioc_g_tuner(file, fh, p);
                if (!ret)
                        dbgarg (cmd, "index=%d, name=%s, type=%d, "
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_frequency *p=arg;
                if (!vfd->vidioc_g_frequency)
                        break;
+
+               memset(p,0,sizeof(*p));
+
                ret=vfd->vidioc_g_frequency(file, fh, p);
                if (!ret)
                        dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                ret=vfd->vidioc_log_status(file, fh);
                break;
        }
-
-       /* --- Others --------------------------------------------- */
-
-       default:
-               ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
-       }
+       } /* switch */
 
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
                if (ret<0) {
index 3c8dc72..474ddb7 100644 (file)
@@ -36,6 +36,7 @@
 #include <media/v4l2-common.h>
 #include <linux/kthread.h>
 #include <linux/highmem.h>
+#include <linux/freezer.h>
 
 /* Wake up at about 30 fps */
 #define WAKE_NUMERATOR 30
@@ -1043,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
        return (0);
 }
 
-static struct v4l2_tvnorm tvnorms[] = {
-       {
-               .name      = "NTSC-M",
-               .id        = V4L2_STD_NTSC_M,
-       }
-};
-
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i)
 {
-
        return 0;
 }
 
@@ -1332,8 +1325,8 @@ static struct video_device vivi = {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf          = vidiocgmbuf,
 #endif
-       .tvnorms              = tvnorms,
-       .tvnormsize           = ARRAY_SIZE(tvnorms),
+       .tvnorms              = V4L2_STD_NTSC_M,
+       .current_norm         = V4L2_STD_NTSC_M,
 };
 /* -----------------------------------------------------------------
        Initialization and module stuff
@@ -1360,8 +1353,6 @@ static int __init vivi_init(void)
        dev->vidq.timeout.data     = (unsigned long)dev;
        init_timer(&dev->vidq.timeout);
 
-       vivi.current_norm         = tvnorms[0].id;
-
        ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
        printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
        return ret;
index c7f6f64..c374c76 100644 (file)
@@ -144,7 +144,7 @@ static int zoran_open(struct inode *inode, struct file *file)
 static ssize_t zoran_write(struct file *file, const char __user *buffer,
                        size_t count, loff_t *ppos)
 {
-       struct zoran *zr = PDE(file->f_dentry->d_inode)->data;
+       struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
        char *string, *sp;
        char *line, *ldelim, *varname, *svar, *tdelim;
 
@@ -165,7 +165,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
        }
        string[count] = 0;
        dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
-               ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr);
+               ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
        ldelim = " \t\n";
        tdelim = "=";
        line = strpbrk(sp, ldelim);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
deleted file mode 100644 (file)
index 0cbf564..0000000
+++ /dev/null
@@ -1,2079 +0,0 @@
-/*
-    zr36120.c - Zoran 36120/36125 based framegrabbers
-
-    Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
-    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/init.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/signal.h>
-#include <linux/wait.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
-#include <linux/video_decoder.h>
-
-#include <asm/uaccess.h>
-
-#include "tuner.h"
-#include "zr36120.h"
-#include "zr36120_mem.h"
-
-/* mark an required function argument unused - lintism */
-#define        UNUSED(x)       (void)(x)
-
-/* sensible default */
-#ifndef CARDTYPE
-#define CARDTYPE 0
-#endif
-
-/* Anybody who uses more than four? */
-#define ZORAN_MAX 4
-
-static unsigned int triton1=0;                 /* triton1 chipset? */
-static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };
-static int video_nr = -1;
-static int vbi_nr = -1;
-
-static struct pci_device_id zr36120_pci_tbl[] = {
-       { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-       { 0 }
-};
-MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl);
-
-MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>");
-MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
-MODULE_LICENSE("GPL");
-
-module_param(triton1, uint, 0);
-module_param_array(cardtype, uint, NULL, 0);
-module_param(video_nr, int, 0);
-module_param(vbi_nr, int, 0);
-
-static int zoran_cards;
-static struct zoran zorans[ZORAN_MAX];
-
-/*
- * the meaning of each element can be found in zr36120.h
- * Determining the value of gpdir/gpval can be tricky. The
- * best way is to run the card under the original software
- * and read the values from the general purpose registers
- * 0x28 and 0x2C. How you do that is left as an exercise
- * to the impatient reader :)
- */
-#define T 1    /* to separate the bools from the ints */
-#define F 0
-static struct tvcard tvcards[] = {
-       /* reported working by <middelin@polyware.nl> */
-/*0*/  { "Trust Victor II",
-         2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
-       /* reported working by <Michael.Paxton@aihw.gov.au>  */
-/*1*/   { "Aitech WaveWatcher TV-PCI",
-         3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } },
-       /* reported working by ? */
-/*2*/  { "Genius Video Wonder PCI Video Capture Card",
-         2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
-       /* reported working by <Pascal.Gabriel@wanadoo.fr> */
-/*3*/  { "Guillemot Maxi-TV PCI",
-         2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
-       /* reported working by "Craig Whitmore <lennon@igrin.co.nz> */
-/*4*/  { "Quadrant Buster",
-         3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } },
-       /* a debug entry which has all inputs mapped */
-/*5*/  { "ZR36120 based framegrabber (all inputs enabled)",
-         6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } }
-};
-#undef T
-#undef F
-#define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0]))
-
-#ifdef __sparc__
-#define        ENDIANESS       0
-#else
-#define        ENDIANESS       ZORAN_VFEC_LE
-#endif
-
-static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = {
-/* n/a     */  { "n/a",     0, 0 },
-/* GREY    */  { "GRAY",    0, 0 },
-/* HI240   */  { "HI240",   0, 0 },
-/* RGB565  */  { "RGB565",  ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 },
-/* RGB24   */  { "RGB24",   ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 },
-/* RGB32   */  { "RGB32",   ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 },
-/* RGB555  */  { "RGB555",  ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 },
-/* YUV422  */  { "YUV422",  ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 },
-/* YUYV    */  { "YUYV",    0, 0 },
-/* UYVY    */  { "UYVY",    0, 0 },
-/* YUV420  */  { "YUV420",  0, 0 },
-/* YUV411  */  { "YUV411",  0, 0 },
-/* RAW     */  { "RAW",     0, 0 },
-/* YUV422P */  { "YUV422P", 0, 0 },
-/* YUV411P */  { "YUV411P", 0, 0 }};
-#define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0]))
-#undef ENDIANESS
-
-/* ----------------------------------------------------------------------- */
-/* ZORAN chipset detector                                                 */
-/* shamelessly stolen from bttv.c                                         */
-/* Reason for beeing here: we need to detect if we are running on a        */
-/* Triton based chipset, and if so, enable a certain bit                   */
-/* ----------------------------------------------------------------------- */
-static
-void __init handle_chipset(void)
-{
-       /* Just in case some nut set this to something dangerous */
-       if (triton1)
-               triton1 = ZORAN_VDC_TRICOM;
-
-       if (pci_pci_problems & PCIPCI_TRITON) {
-               printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n");
-               triton1 = ZORAN_VDC_TRICOM;
-       }
-}
-
-/* ----------------------------------------------------------------------- */
-/* ZORAN functions                                                        */
-/* ----------------------------------------------------------------------- */
-
-static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i);
-
-#if 0 /* unused */
-static
-void zoran_dump(struct zoran *ztv)
-{
-       char    str[256];
-       char    *p=str; /* shut up, gcc! */
-       int     i;
-
-       for (i=0; i<0x60; i+=4) {
-               if ((i % 16) == 0) {
-                       if (i) printk("%s\n",str);
-                       p = str;
-                       p+= sprintf(str, KERN_DEBUG "       %04x: ",i);
-               }
-               p += sprintf(p, "%08x ",zrread(i));
-       }
-}
-#endif /* unused */
-
-static
-void reap_states(struct zoran* ztv)
-{
-       /* count frames */
-       ztv->fieldnr++;
-
-       /*
-        * Are we busy at all?
-        * This depends on if there is a workqueue AND the
-        * videotransfer is enabled on the chip...
-        */
-       if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN))
-       {
-               struct vidinfo* newitem;
-
-               /* did we get a complete frame? */
-               if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB)
-                       return;
-
-DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue));
-
-               /* we are done with this buffer, tell everyone */
-               ztv->workqueue->status = FBUFFER_DONE;
-               ztv->workqueue->fieldnr = ztv->fieldnr;
-               /* not good, here for BTTV_FIELDNR reasons */
-               ztv->lastfieldnr = ztv->fieldnr;
-
-               switch (ztv->workqueue->kindof) {
-                case FBUFFER_GRAB:
-                       wake_up_interruptible(&ztv->grabq);
-                       break;
-                case FBUFFER_VBI:
-                       wake_up_interruptible(&ztv->vbiq);
-                       break;
-                default:
-                       printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof);
-               }
-
-               /* item completed, skip to next item in queue */
-               write_lock(&ztv->lock);
-               newitem = ztv->workqueue->next;
-               ztv->workqueue->next = 0;       /* mark completed */
-               ztv->workqueue = newitem;
-               write_unlock(&ztv->lock);
-       }
-
-       /*
-        * ok, so it seems we have nothing in progress right now.
-        * Lets see if we can find some work.
-        */
-       if (ztv->workqueue)
-       {
-               struct vidinfo* newitem;
-again:
-
-DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue));
-
-               /* loadup the frame settings */
-               read_lock(&ztv->lock);
-               zoran_set_geo(ztv,ztv->workqueue);
-               read_unlock(&ztv->lock);
-
-               switch (ztv->workqueue->kindof) {
-                case FBUFFER_GRAB:
-                case FBUFFER_VBI:
-                       zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR);
-                       zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR);
-                       zror(ZORAN_VDC_VIDEN,ZORAN_VDC);
-
-                       /* start single-shot grab */
-                       zror(ZORAN_VSTR_GRAB, ZORAN_VSTR);
-                       break;
-                default:
-                       printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof);
-                       write_lock(&ztv->lock);
-                       newitem = ztv->workqueue->next;
-                       ztv->workqueue->next = 0;
-                       ztv->workqueue = newitem;
-                       write_unlock(&ztv->lock);
-                       if (newitem)
-                               goto again;     /* yeah, sure.. */
-               }
-               /* bye for now */
-               return;
-       }
-DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD));
-
-       /*
-        * What? Even the workqueue is empty? Am i really here
-        * for nothing? Did i come all that way to... do nothing?
-        */
-
-       /* do we need to overlay? */
-       if (test_bit(STATE_OVERLAY, &ztv->state))
-       {
-               /* are we already overlaying? */
-               if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) ||
-                   !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN))
-               {
-DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD));
-
-                       read_lock(&ztv->lock);
-                       zoran_set_geo(ztv,&ztv->overinfo);
-                       read_unlock(&ztv->lock);
-
-                       zror(ZORAN_OCR_OVLEN, ZORAN_OCR);
-                       zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR);
-                       zror(ZORAN_VDC_VIDEN,ZORAN_VDC);
-               }
-
-               /*
-                * leave overlaying on, but turn interrupts off.
-                */
-               zrand(~ZORAN_ICR_EN,ZORAN_ICR);
-               return;
-       }
-
-       /* do we have any VBI idle time processing? */
-       if (test_bit(STATE_VBI, &ztv->state))
-       {
-               struct vidinfo* item;
-               struct vidinfo* lastitem;
-
-               /* protect the workqueue */
-               write_lock(&ztv->lock);
-               lastitem = ztv->workqueue;
-               if (lastitem)
-                       while (lastitem->next) lastitem = lastitem->next;
-               for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
-                       if (item->next == 0 && item->status == FBUFFER_FREE)
-                       {
-DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item));
-                               item->status = FBUFFER_BUSY;
-                               if (!lastitem)
-                                       ztv->workqueue = item;
-                               else
-                                       lastitem->next = item;
-                               lastitem = item;
-                       }
-               write_unlock(&ztv->lock);
-               if (ztv->workqueue)
-                       goto again;     /* hey, _i_ graduated :) */
-       }
-
-       /*
-        * Then we must be realy IDLE
-        */
-DEBUG(printk(CARD_DEBUG "turning off\n",CARD));
-       /* nothing further to do, disable DMA and further IRQs */
-       zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
-       zrand(~ZORAN_ICR_EN,ZORAN_ICR);
-}
-
-static
-void zoran_irq(int irq, void *dev_id)
-{
-       u32 stat,estat;
-       int count = 0;
-       struct zoran *ztv = dev_id;
-
-       UNUSED(irq);
-       for (;;) {
-               /* get/clear interrupt status bits */
-               stat=zrread(ZORAN_ISR);
-               estat=stat & zrread(ZORAN_ICR);
-               if (!estat)
-                       return;
-               zrwrite(estat,ZORAN_ISR);
-               IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat));
-               IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat));
-
-               if (estat & ZORAN_ISR_CODE)
-               {
-                       IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD));
-               }
-               if (estat & ZORAN_ISR_GIRQ0)
-               {
-                       IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD));
-                       if (!ztv->card->usegirq1)
-                               reap_states(ztv);
-               }
-               if (estat & ZORAN_ISR_GIRQ1)
-               {
-                       IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD));
-                       if (ztv->card->usegirq1)
-                               reap_states(ztv);
-               }
-
-               count++;
-               if (count > 10)
-                       printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat);
-               if (count > 20)
-               {
-                       zrwrite(0, ZORAN_ICR);
-                       printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD);
-               }
-       }
-}
-
-static
-int zoran_muxsel(struct zoran* ztv, int channel, int norm)
-{
-       int     rv;
-
-       /* set the new video norm */
-       rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm);
-       if (rv)
-               return rv;
-       ztv->norm = norm;
-
-       /* map the given channel to the cards decoder's channel */
-       channel = ztv->card->video_mux[channel] & CHANNEL_MASK;
-
-       /* set the new channel */
-       rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel);
-       return rv;
-}
-
-/* Tell the interrupt handler what to to.  */
-static
-void zoran_cap(struct zoran* ztv, int on)
-{
-DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state));
-
-       if (on) {
-               ztv->running = 1;
-
-               /*
-                * turn interrupts (back) on. The DMA will be enabled
-                * inside the irq handler when it detects a restart.
-                */
-               zror(ZORAN_ICR_EN,ZORAN_ICR);
-       }
-       else {
-               /*
-                * turn both interrupts and DMA off
-                */
-               zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
-               zrand(~ZORAN_ICR_EN,ZORAN_ICR);
-
-               ztv->running = 0;
-       }
-}
-
-static ulong dmask[] = {
-       0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8,
-       0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80,
-       0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800,
-       0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000,
-       0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000,
-       0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000,
-       0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000,
-       0xF0000000, 0xE0000000, 0xC0000000, 0x80000000
-};
-
-static
-void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp)
-{
-       ulong*  mtop;
-       int     ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */
-       int     i;
-
-DEBUG(printk(KERN_DEBUG "       overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count));
-
-       for (i=0; i<count; i++) {
-               struct video_clip *vp = vcp+i;
-               UNUSED(vp);
-DEBUG(printk(KERN_DEBUG "       %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->width,vp->height));
-       }
-
-       /*
-        * activate the visible portion of the screen
-        * Note we take some shortcuts here, because we
-        * know the width can never be < 32. (I.e. a DWORD)
-        * We also assume the overlay starts somewhere in
-        * the FIRST dword.
-        */
-       {
-               int start = ztv->vidXshift;
-               ulong firstd = dmask[start];
-               ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31];
-               mtop = ztv->overinfo.overlay;
-               for (i=0; i<ztv->overinfo.h; i++) {
-                       int w = ztv->vidWidth;
-                       ulong* line = mtop;
-                       if (start & 31) {
-                               *line++ = firstd;
-                               w -= 32-(start&31);
-                       }
-                       memset(line, ~0, w/8);
-                       if (w & 31)
-                               line[w/32] = lastd;
-                       mtop += ystep;
-               }
-       }
-
-       /* process clipping regions */
-       for (i=0; i<count; i++) {
-               int h;
-               if (vcp->x < 0 || (uint)vcp->x > ztv->overinfo.w ||
-                   vcp->y < 0 || vcp->y > ztv->overinfo.h ||
-                   vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w ||
-                   vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h)
-               {
-                       DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h));
-                       if (vcp->x < 0) vcp->x = 0;
-                       if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w;
-                       if (vcp->y < 0) vcp->y = 0;
-                       if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h;
-                       if (vcp->width < 0) vcp->width = 0;
-                       if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x;
-                       if (vcp->height < 0) vcp->height = 0;
-                       if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y;
-//                     continue;
-               }
-
-               mtop = &ztv->overinfo.overlay[vcp->y*ystep];
-               for (h=0; h<=vcp->height; h++) {
-                       int w;
-                       int x = ztv->vidXshift + vcp->x;
-                       for (w=0; w<=vcp->width; w++) {
-                               clear_bit(x&31, &mtop[x/32]);
-                               x++;
-                       }
-                       mtop += ystep;
-               }
-               ++vcp;
-       }
-
-       mtop = ztv->overinfo.overlay;
-       zrwrite(virt_to_bus(mtop), ZORAN_MTOP);
-       zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT);
-       zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR);
-}
-
-struct tvnorm
-{
-       u16 Wt, Wa, Ht, Ha, HStart, VStart;
-};
-
-static struct tvnorm tvnorms[] = {
-       /* PAL-BDGHI */
-/*     { 864, 720, 625, 576, 131, 21 },*/
-/*00*/ { 864, 768, 625, 576, 81, 17 },
-       /* NTSC */
-/*01*/ { 858, 720, 525, 480, 121, 10 },
-       /* SECAM */
-/*02*/ { 864, 720, 625, 576, 131, 21 },
-       /* BW50 */
-/*03*/ { 864, 720, 625, 576, 131, 21 },
-       /* BW60 */
-/*04*/ { 858, 720, 525, 480, 121, 10 }
-};
-#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
-
-/*
- * Program the chip for a setup as described in the vidinfo struct.
- *
- * Side-effects: calculates vidXshift, vidInterlace,
- * vidHeight, vidWidth which are used in a later stage
- * to calculate the overlay mask
- *
- * This is an internal function, as such it does not check the
- * validity of the struct members... Spectaculair crashes will
- * follow /very/ quick when you're wrong and the chip right :)
- */
-static
-void zoran_set_geo(struct zoran* ztv, struct vidinfo* i)
-{
-       ulong   top, bot;
-       int     stride;
-       int     winWidth, winHeight;
-       int     maxWidth, maxHeight, maxXOffset, maxYOffset;
-       long    vfec;
-
-DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay));
-
-       /*
-        * make sure the DMA transfers are inhibited during our
-        * reprogramming of the chip
-        */
-       zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
-
-       maxWidth = tvnorms[ztv->norm].Wa;
-       maxHeight = tvnorms[ztv->norm].Ha/2;
-       maxXOffset = tvnorms[ztv->norm].HStart;
-       maxYOffset = tvnorms[ztv->norm].VStart;
-
-       /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */
-       vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) |
-              (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24));
-
-       /*
-        * Set top, bottom ptrs. Since these must be DWORD aligned,
-        * possible adjust the x and the width of the window.
-        * so the endposition stay the same. The vidXshift will make
-        * sure we are not writing pixels before the requested x.
-        */
-       ztv->vidXshift = 0;
-       winWidth = i->w;
-       if (winWidth < 0)
-               winWidth = -winWidth;
-       top = i->busadr + i->x*i->bpp + i->y*i->bpl;
-       if (top & 3) {
-               ztv->vidXshift = (top & 3) / i->bpp;
-               winWidth += ztv->vidXshift;
-               DEBUG(printk(KERN_DEBUG "       window-x shifted %d pixels left\n",ztv->vidXshift));
-               top &= ~3;
-       }
-
-       /*
-        * bottom points to next frame but in interleaved mode we want
-        * to 'mix' the 2 frames to one capture, so 'bot' points to one
-        * (physical) line below the top line.
-        */
-       bot = top + i->bpl;
-       zrwrite(top,ZORAN_VTOP);
-       zrwrite(bot,ZORAN_VBOT);
-
-       /*
-        * Make sure the winWidth is DWORD aligned too,
-        * thereby automaticly making sure the stride to the
-        * next line is DWORD aligned too (as required by spec).
-        */
-       if ((winWidth*i->bpp) & 3) {
-DEBUG(printk(KERN_DEBUG "       window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3));
-               winWidth += (winWidth*i->bpp) & 3;
-       }
-
-       /* determine the DispMode and stride */
-       if (i->h >= 0 && i->h <= maxHeight) {
-               /* single frame grab suffices for this height. */
-               vfec |= ZORAN_VFEC_DISPMOD;
-               ztv->vidInterlace = 0;
-               stride = i->bpl - (winWidth*i->bpp);
-               winHeight = i->h;
-       }
-       else {
-               /* interleaving needed for this height */
-               ztv->vidInterlace = 1;
-               stride = i->bpl*2 - (winWidth*i->bpp);
-               winHeight = i->h/2;
-       }
-       if (winHeight < 0)      /* can happen for VBI! */
-               winHeight = -winHeight;
-
-       /* safety net, sometimes bpl is too short??? */
-       if (stride<0) {
-DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride));
-               stride = 0;
-       }
-
-       zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC);
-       zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR);
-
-       /* remember vidWidth, vidHeight for overlay calculations */
-       ztv->vidWidth = winWidth;
-       ztv->vidHeight = winHeight;
-DEBUG(printk(KERN_DEBUG "       top=%08lx, bottom=%08lx\n",top,bot));
-DEBUG(printk(KERN_DEBUG "       winWidth=%d, winHeight=%d\n",winWidth,winHeight));
-DEBUG(printk(KERN_DEBUG "       maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight));
-DEBUG(printk(KERN_DEBUG "       stride=%d\n",stride));
-
-       /*
-        * determine horizontal scales and crops
-        */
-       if (i->w < 0) {
-               int Hstart = 1;
-               int Hend = Hstart + winWidth;
-DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Hstart, Hend));
-               zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
-       }
-       else {
-               int Wa = maxWidth;
-               int X = (winWidth*64+Wa-1)/Wa;
-               int We = winWidth*64/X;
-               int HorDcm = 64-X;
-               int hcrop1 = 2*(Wa-We)/4;
-               /*
-                * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi>
-                * found the solution to the color phase shift.
-                * See ChangeLog for the full explanation)
-                */
-               int Hstart = (maxXOffset + hcrop1) | 1;
-               int Hend = Hstart + We - 1;
-
-DEBUG(printk(KERN_DEBUG "       X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend));
-
-               zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
-               vfec |= HorDcm<<14;
-
-               if (HorDcm<16)
-                       vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */
-               else if (HorDcm<32)
-                       vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */
-               else if (HorDcm<48)
-                       vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */
-               else    vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */
-       }
-
-       /*
-        * Determine vertical scales and crops
-        *
-        * when height is negative, we want to read starting at line 0
-        * One day someone might need access to these lines...
-        */
-       if (i->h < 0) {
-               int Vstart = 0;
-               int Vend = Vstart + winHeight;
-DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Vstart, Vend));
-               zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
-       }
-       else {
-               int Ha = maxHeight;
-               int Y = (winHeight*64+Ha-1)/Ha;
-               int He = winHeight*64/Y;
-               int VerDcm = 64-Y;
-               int vcrop1 = 2*(Ha-He)/4;
-               int Vstart = maxYOffset + vcrop1;
-               int Vend = Vstart + He - 1;
-
-DEBUG(printk(KERN_DEBUG "       Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend));
-               zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
-               vfec |= VerDcm<<8;
-       }
-
-DEBUG(printk(KERN_DEBUG "       F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name));
-
-       /* setup the requested format */
-       zrwrite(vfec, ZORAN_VFEC);
-}
-
-static
-void zoran_common_open(struct zoran* ztv, int flags)
-{
-       UNUSED(flags);
-
-       /* already opened? */
-       if (ztv->users++ != 0)
-               return;
-
-       /* unmute audio */
-       /* /what/ audio? */
-
-       ztv->state = 0;
-
-       /* setup the encoder to the initial values */
-       ztv->picture.colour=254<<7;
-       ztv->picture.brightness=128<<8;
-       ztv->picture.hue=128<<8;
-       ztv->picture.contrast=216<<7;
-       i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture);
-
-       /* default to the composite input since my camera is there */
-       zoran_muxsel(ztv, 0, VIDEO_MODE_PAL);
-}
-
-static
-void zoran_common_close(struct zoran* ztv)
-{
-       if (--ztv->users != 0)
-               return;
-
-       /* mute audio */
-       /* /what/ audio? */
-
-       /* stop the chip */
-       zoran_cap(ztv, 0);
-}
-
-/*
- * Open a zoran card. Right now the flags are just a hack
- */
-static int zoran_open(struct video_device *dev, int flags)
-{
-       struct zoran *ztv = (struct zoran*)dev;
-       struct vidinfo* item;
-       char* pos;
-
-       DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags));
-
-       /*********************************************
-        * We really should be doing lazy allocing...
-        *********************************************/
-       /* allocate a frame buffer */
-       if (!ztv->fbuffer)
-               ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE);
-       if (!ztv->fbuffer) {
-               /* could not get a buffer, bail out */
-               return -ENOBUFS;
-       }
-       /* at this time we _always_ have a framebuffer */
-       memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE);
-
-       if (!ztv->overinfo.overlay)
-               ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL);
-       if (!ztv->overinfo.overlay) {
-               /* could not get an overlay buffer, bail out */
-               bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
-               return -ENOBUFS;
-       }
-       /* at this time we _always_ have a overlay */
-
-       /* clear buffer status, and give them a DMAable address */
-       pos = ztv->fbuffer;
-       for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
-       {
-               item->status = FBUFFER_FREE;
-               item->memadr = pos;
-               item->busadr = virt_to_bus(pos);
-               pos += ZORAN_MAX_FBUFFER;
-       }
-
-       /* do the common part of all open's */
-       zoran_common_open(ztv, flags);
-
-       return 0;
-}
-
-static
-void zoran_close(struct video_device* dev)
-{
-       struct zoran *ztv = (struct zoran*)dev;
-
-       DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD));
-
-       /* driver specific closure */
-       clear_bit(STATE_OVERLAY, &ztv->state);
-
-       zoran_common_close(ztv);
-
-       /*
-        *      This is sucky but right now I can't find a good way to
-        *      be sure its safe to free the buffer. We wait 5-6 fields
-        *      which is more than sufficient to be sure.
-        */
-       msleep(100);                    /* Wait 1/10th of a second */
-
-       /* free the allocated framebuffer */
-       bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
-       ztv->fbuffer = 0;
-       kfree(ztv->overinfo.overlay);
-       ztv->overinfo.overlay = 0;
-
-}
-
-/*
- * This read function could be used reentrant in a SMP situation.
- *
- * This is made possible by the spinlock which is kept till we
- * found and marked a buffer for our own use. The lock must
- * be released as soon as possible to prevent lock contention.
- */
-static
-long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
-{
-       struct zoran *ztv = (struct zoran*)dev;
-       unsigned long max;
-       struct vidinfo* unused = 0;
-       struct vidinfo* done = 0;
-
-       DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock));
-
-       /* find ourself a free or completed buffer */
-       for (;;) {
-               struct vidinfo* item;
-
-               write_lock_irq(&ztv->lock);
-               for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
-               {
-                       if (!unused && item->status == FBUFFER_FREE)
-                               unused = item;
-                       if (!done && item->status == FBUFFER_DONE)
-                               done = item;
-               }
-               if (done || unused)
-                       break;
-
-               /* no more free buffers, wait for them. */
-               write_unlock_irq(&ztv->lock);
-               if (nonblock)
-                       return -EWOULDBLOCK;
-               interruptible_sleep_on(&ztv->grabq);
-               if (signal_pending(current))
-                       return -EINTR;
-       }
-
-       /* Do we have 'ready' data? */
-       if (!done) {
-               /* no? than this will take a while... */
-               if (nonblock) {
-                       write_unlock_irq(&ztv->lock);
-                       return -EWOULDBLOCK;
-               }
-
-               /* mark the unused buffer as wanted */
-               unused->status = FBUFFER_BUSY;
-               unused->w = 320;
-               unused->h = 240;
-               unused->format = VIDEO_PALETTE_RGB24;
-               unused->bpp = palette2fmt[unused->format].bpp;
-               unused->bpl = unused->w * unused->bpp;
-               unused->next = 0;
-               { /* add to tail of queue */
-                 struct vidinfo* oldframe = ztv->workqueue;
-                 if (!oldframe) ztv->workqueue = unused;
-                 else {
-                   while (oldframe->next) oldframe = oldframe->next;
-                   oldframe->next = unused;
-                 }
-               }
-               write_unlock_irq(&ztv->lock);
-
-               /* tell the state machine we want it filled /NOW/ */
-               zoran_cap(ztv, 1);
-
-               /* wait till this buffer gets grabbed */
-               wait_event_interruptible(ztv->grabq,
-                               (unused->status != FBUFFER_BUSY));
-               /* see if a signal did it */
-               if (signal_pending(current))
-                       return -EINTR;
-               done = unused;
-       }
-       else
-               write_unlock_irq(&ztv->lock);
-
-       /* Yes! we got data! */
-       max = done->bpl * done->h;
-       if (count > max)
-               count = max;
-       if (copy_to_user((void*)buf, done->memadr, count))
-               count = -EFAULT;
-
-       /* keep the engine running */
-       done->status = FBUFFER_FREE;
-//     zoran_cap(ztv,1);
-
-       /* tell listeners this buffer became free */
-       wake_up_interruptible(&ztv->grabq);
-
-       /* goodbye */
-       DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count));
-       return count;
-}
-
-static
-long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock)
-{
-       struct zoran *ztv = (struct zoran *)dev;
-       UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock);
-       DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD));
-       return -EINVAL;
-}
-
-static
-unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait)
-{
-       struct zoran *ztv = (struct zoran *)dev;
-       struct vidinfo* item;
-       unsigned int mask = 0;
-
-       poll_wait(file, &ztv->grabq, wait);
-
-       for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
-               if (item->status == FBUFFER_DONE)
-               {
-                       mask |= (POLLIN | POLLRDNORM);
-                       break;
-               }
-
-       DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask));
-
-       return mask;
-}
-
-/* append a new clipregion to the vector of video_clips */
-static
-void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h)
-{
-       vcp[vw->clipcount].x = x;
-       vcp[vw->clipcount].y = y;
-       vcp[vw->clipcount].width = w;
-       vcp[vw->clipcount].height = h;
-       vw->clipcount++;
-}
-
-static
-int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
-{
-       struct zoran* ztv = (struct zoran*)dev;
-
-       switch (cmd) {
-        case VIDIOCGCAP:
-        {
-               struct video_capability c;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD));
-
-               strcpy(c.name,ztv->video_dev.name);
-               c.type = VID_TYPE_CAPTURE|
-                        VID_TYPE_OVERLAY|
-                        VID_TYPE_CLIPPING|
-                        VID_TYPE_FRAMERAM|
-                        VID_TYPE_SCALES;
-               if (ztv->have_tuner)
-                       c.type |= VID_TYPE_TUNER;
-               if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
-                       c.type &= ~VID_TYPE_OVERLAY;
-               if (ztv->have_decoder) {
-                       c.channels = ztv->card->video_inputs;
-                       c.audios = ztv->card->audio_inputs;
-               } else
-                       /* no decoder -> no channels */
-                       c.channels = c.audios = 0;
-               c.maxwidth = 768;
-               c.maxheight = 576;
-               c.minwidth = 32;
-               c.minheight = 32;
-               if (copy_to_user(arg,&c,sizeof(c)))
-                       return -EFAULT;
-               break;
-        }
-
-        case VIDIOCGCHAN:
-        {
-               struct video_channel v;
-               int mux;
-               if (copy_from_user(&v, arg,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel));
-               v.flags=VIDEO_VC_AUDIO
-#ifdef VIDEO_VC_NORM
-                       |VIDEO_VC_NORM
-#endif
-                       ;
-               v.tuners=0;
-               v.type=VIDEO_TYPE_CAMERA;
-#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API
-               v.norm=VIDEO_MODE_PAL|
-                      VIDEO_MODE_NTSC|
-                      VIDEO_MODE_SECAM;
-#else
-               v.norm=VIDEO_MODE_PAL;
-#endif
-               /* too many inputs? no decoder -> no channels */
-               if (!ztv->have_decoder || v.channel < 0 ||  v.channel >= ztv->card->video_inputs)
-                       return -EINVAL;
-
-               /* now determine the name of the channel */
-               mux = ztv->card->video_mux[v.channel];
-               if (mux & IS_TUNER) {
-                       /* lets assume only one tuner, yes? */
-                       strcpy(v.name,"Television");
-                       v.type = VIDEO_TYPE_TV;
-                       if (ztv->have_tuner) {
-                               v.flags |= VIDEO_VC_TUNER;
-                               v.tuners = 1;
-                       }
-               }
-               else if (mux & IS_SVHS)
-                       sprintf(v.name,"S-Video-%d",v.channel);
-               else
-                       sprintf(v.name,"CVBS-%d",v.channel);
-
-               if (copy_to_user(arg,&v,sizeof(v)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSCHAN:
-        {      /* set video channel */
-               struct video_channel v;
-               if (copy_from_user(&v, arg,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm));
-
-               /* too many inputs? no decoder -> no channels */
-               if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0)
-                       return -EINVAL;
-
-               if (v.norm != VIDEO_MODE_PAL &&
-                   v.norm != VIDEO_MODE_NTSC &&
-                   v.norm != VIDEO_MODE_SECAM &&
-                   v.norm != VIDEO_MODE_AUTO)
-                       return -EOPNOTSUPP;
-
-               /* make it happen, nr1! */
-               return zoran_muxsel(ztv,v.channel,v.norm);
-        }
-
-        case VIDIOCGTUNER:
-        {
-               struct video_tuner v;
-               if (copy_from_user(&v, arg,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner));
-
-               /* Only no or one tuner for now */
-               if (!ztv->have_tuner || v.tuner)
-                       return -EINVAL;
-
-               strcpy(v.name,"Television");
-               v.rangelow  = 0;
-               v.rangehigh = ~0;
-               v.flags     = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
-               v.mode      = ztv->norm;
-               v.signal    = 0xFFFF; /* unknown */
-
-               if (copy_to_user(arg,&v,sizeof(v)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSTUNER:
-        {
-               struct video_tuner v;
-               if (copy_from_user(&v, arg, sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode));
-
-               /* Only no or one tuner for now */
-               if (!ztv->have_tuner || v.tuner)
-                       return -EINVAL;
-
-               /* and it only has certain valid modes */
-               if( v.mode != VIDEO_MODE_PAL &&
-                   v.mode != VIDEO_MODE_NTSC &&
-                   v.mode != VIDEO_MODE_SECAM)
-                       return -EOPNOTSUPP;
-
-               /* engage! */
-               return zoran_muxsel(ztv,v.tuner,v.mode);
-        }
-
-        case VIDIOCGPICT:
-        {
-               struct video_picture p = ztv->picture;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD));
-               p.depth = ztv->depth;
-               switch (p.depth) {
-                case  8: p.palette=VIDEO_PALETTE_YUV422;
-                         break;
-                case 15: p.palette=VIDEO_PALETTE_RGB555;
-                         break;
-                case 16: p.palette=VIDEO_PALETTE_RGB565;
-                         break;
-                case 24: p.palette=VIDEO_PALETTE_RGB24;
-                         break;
-                case 32: p.palette=VIDEO_PALETTE_RGB32;
-                         break;
-               }
-               if (copy_to_user(arg, &p, sizeof(p)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSPICT:
-        {
-               struct video_picture p;
-               if (copy_from_user(&p, arg,sizeof(p)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette));
-
-               /* depth must match with framebuffer */
-               if (p.depth != ztv->depth)
-                       return -EINVAL;
-
-               /* check if palette matches this bpp */
-               if (p.palette>NRPALETTES ||
-                   palette2fmt[p.palette].bpp != ztv->overinfo.bpp)
-                       return -EINVAL;
-
-               write_lock_irq(&ztv->lock);
-               ztv->overinfo.format = p.palette;
-               ztv->picture = p;
-               write_unlock_irq(&ztv->lock);
-
-               /* tell the decoder */
-               i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p);
-               break;
-        }
-
-        case VIDIOCGWIN:
-        {
-               struct video_window vw;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD));
-               read_lock(&ztv->lock);
-               vw.x      = ztv->overinfo.x;
-               vw.y      = ztv->overinfo.y;
-               vw.width  = ztv->overinfo.w;
-               vw.height = ztv->overinfo.h;
-               vw.chromakey= 0;
-               vw.flags  = 0;
-               if (ztv->vidInterlace)
-                       vw.flags|=VIDEO_WINDOW_INTERLACE;
-               read_unlock(&ztv->lock);
-               if (copy_to_user(arg,&vw,sizeof(vw)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSWIN:
-        {
-               struct video_window vw;
-               struct video_clip *vcp;
-               int on;
-               if (copy_from_user(&vw,arg,sizeof(vw)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount));
-
-               if (vw.flags)
-                       return -EINVAL;
-
-               if (vw.clipcount <0 || vw.clipcount>256)
-                       return -EDOM;   /* Too many! */
-
-               /*
-                *      Do any clips.
-                */
-               vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
-               if (vcp==NULL)
-                       return -ENOMEM;
-               if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {
-                       vfree(vcp);
-                       return -EFAULT;
-               }
-
-               on = ztv->running;
-               if (on)
-                       zoran_cap(ztv, 0);
-
-               /*
-                * strange, it seems xawtv sometimes calls us with 0
-                * width and/or height. Ignore these values
-                */
-               if (vw.x == 0)
-                       vw.x = ztv->overinfo.x;
-               if (vw.y == 0)
-                       vw.y = ztv->overinfo.y;
-
-               /* by now we are committed to the new data... */
-               write_lock_irq(&ztv->lock);
-               ztv->overinfo.x = vw.x;
-               ztv->overinfo.y = vw.y;
-               ztv->overinfo.w = vw.width;
-               ztv->overinfo.h = vw.height;
-               write_unlock_irq(&ztv->lock);
-
-               /*
-                *      Impose display clips
-                */
-               if (vw.x+vw.width > ztv->swidth)
-                       new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1);
-               if (vw.y+vw.height > ztv->sheight)
-                       new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1);
-
-               /* built the requested clipping zones */
-               zoran_set_geo(ztv, &ztv->overinfo);
-               zoran_built_overlay(ztv, vw.clipcount, vcp);
-               vfree(vcp);
-
-               /* if we were on, restart the video engine */
-               if (on)
-                       zoran_cap(ztv, 1);
-               break;
-        }
-
-        case VIDIOCCAPTURE:
-        {
-               int v;
-               if (get_user(v, (int *)arg))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v));
-
-               if (v==0) {
-                       clear_bit(STATE_OVERLAY, &ztv->state);
-                       zoran_cap(ztv, 1);
-               }
-               else {
-                       /* is VIDIOCSFBUF, VIDIOCSWIN done? */
-                       if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0)
-                               return -EINVAL;
-
-                       set_bit(STATE_OVERLAY, &ztv->state);
-                       zoran_cap(ztv, 1);
-               }
-               break;
-        }
-
-        case VIDIOCGFBUF:
-        {
-               struct video_buffer v;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD));
-               read_lock(&ztv->lock);
-               v.base   = (void *)ztv->overinfo.busadr;
-               v.height = ztv->sheight;
-               v.width  = ztv->swidth;
-               v.depth  = ztv->depth;
-               v.bytesperline = ztv->overinfo.bpl;
-               read_unlock(&ztv->lock);
-               if(copy_to_user(arg, &v,sizeof(v)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSFBUF:
-        {
-               struct video_buffer v;
-               if(!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-               if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
-                       return -ENXIO;
-               if (copy_from_user(&v, arg,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline));
-
-               if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)
-                       return -EINVAL;
-               if (v.bytesperline<1)
-                       return -EINVAL;
-               if (ztv->running)
-                       return -EBUSY;
-               write_lock_irq(&ztv->lock);
-               ztv->overinfo.busadr  = (ulong)v.base;
-               ztv->sheight      = v.height;
-               ztv->swidth       = v.width;
-               ztv->depth        = v.depth;            /* bits per pixel */
-               ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */
-               ztv->overinfo.bpl = v.bytesperline;     /* bytes per line */
-               write_unlock_irq(&ztv->lock);
-               break;
-        }
-
-        case VIDIOCKEY:
-        {
-               /* Will be handled higher up .. */
-               break;
-        }
-
-        case VIDIOCSYNC:
-        {
-               int i;
-               if (get_user(i, (int *) arg))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i));
-               if (i<0 || i>ZORAN_MAX_FBUFFERS)
-                       return -EINVAL;
-               switch (ztv->grabinfo[i].status) {
-                case FBUFFER_FREE:
-                       return -EINVAL;
-                case FBUFFER_BUSY:
-                       /* wait till this buffer gets grabbed */
-                       wait_event_interruptible(ztv->grabq,
-                                       (ztv->grabinfo[i].status != FBUFFER_BUSY));
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -EINTR;
-                       /* don't fall through; a DONE buffer is not UNUSED */
-                       break;
-                case FBUFFER_DONE:
-                       ztv->grabinfo[i].status = FBUFFER_FREE;
-                       /* tell ppl we have a spare buffer */
-                       wake_up_interruptible(&ztv->grabq);
-                       break;
-               }
-               DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i));
-               break;
-        }
-
-        case VIDIOCMCAPTURE:
-        {
-               struct video_mmap vm;
-               struct vidinfo* frame;
-               if (copy_from_user(&vm,arg,sizeof(vm)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format));
-               if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS ||
-                   vm.width<32 || vm.width>768 ||
-                   vm.height<32 || vm.height>576 ||
-                   vm.format>NRPALETTES ||
-                   palette2fmt[vm.format].mode == 0)
-                       return -EINVAL;
-
-               /* we are allowed to take over UNUSED and DONE buffers */
-               frame = &ztv->grabinfo[vm.frame];
-               if (frame->status == FBUFFER_BUSY)
-                       return -EBUSY;
-
-               /* setup the other parameters if they are given */
-               write_lock_irq(&ztv->lock);
-               frame->w = vm.width;
-               frame->h = vm.height;
-               frame->format = vm.format;
-               frame->bpp = palette2fmt[frame->format].bpp;
-               frame->bpl = frame->w*frame->bpp;
-               frame->status = FBUFFER_BUSY;
-               frame->next = 0;
-               { /* add to tail of queue */
-                 struct vidinfo* oldframe = ztv->workqueue;
-                 if (!oldframe) ztv->workqueue = frame;
-                 else {
-                   while (oldframe->next) oldframe = oldframe->next;
-                   oldframe->next = frame;
-                 }
-               }
-               write_unlock_irq(&ztv->lock);
-               zoran_cap(ztv, 1);
-               break;
-        }
-
-        case VIDIOCGMBUF:
-        {
-               struct video_mbuf mb;
-               int i;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD));
-               mb.size = ZORAN_MAX_FBUFSIZE;
-               mb.frames = ZORAN_MAX_FBUFFERS;
-               for (i=0; i<ZORAN_MAX_FBUFFERS; i++)
-                       mb.offsets[i] = i*ZORAN_MAX_FBUFFER;
-               if(copy_to_user(arg, &mb,sizeof(mb)))
-                       return -EFAULT;
-               break;
-        }
-
-        case VIDIOCGUNIT:
-        {
-               struct video_unit vu;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD));
-               vu.video = ztv->video_dev.minor;
-               vu.vbi = ztv->vbi_dev.minor;
-               vu.radio = VIDEO_NO_UNIT;
-               vu.audio = VIDEO_NO_UNIT;
-               vu.teletext = VIDEO_NO_UNIT;
-               if(copy_to_user(arg, &vu,sizeof(vu)))
-                       return -EFAULT;
-               break;
-        }
-
-        case VIDIOCGFREQ:
-        {
-               unsigned long v = ztv->tuner_freq;
-               if (copy_to_user(arg,&v,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD));
-               break;
-        }
-        case VIDIOCSFREQ:
-        {
-               unsigned long v;
-               if (copy_from_user(&v, arg, sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD));
-
-               if (ztv->have_tuner) {
-                       int fixme = v;
-                       if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0)
-                               return -EAGAIN;
-               }
-               ztv->tuner_freq = v;
-               break;
-        }
-
-        /* Why isn't this in the API?
-         * And why doesn't it take a buffer number?
-        case BTTV_FIELDNR:
-        {
-               unsigned long v = ztv->lastfieldnr;
-               if (copy_to_user(arg,&v,sizeof(v)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD));
-               break;
-        }
-        */
-
-        default:
-               return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static
-int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size)
-{
-       struct zoran* ztv = (struct zoran*)dev;
-       unsigned long start = (unsigned long)adr;
-       unsigned long pos;
-
-       DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size));
-
-       /* sanity checks */
-       if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer)
-               return -EINVAL;
-
-       /* start mapping the whole shabang to user memory */
-       pos = (unsigned long)ztv->fbuffer;
-       while (size>0) {
-               unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT;
-               if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       return 0;
-}
-
-static struct video_device zr36120_template=
-{
-       .owner          = THIS_MODULE,
-       .name           = "UNSET",
-       .type           = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
-       .hardware       = VID_HARDWARE_ZR36120,
-       .open           = zoran_open,
-       .close          = zoran_close,
-       .read           = zoran_read,
-       .write          = zoran_write,
-       .poll           = zoran_poll,
-       .ioctl          = zoran_ioctl,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .mmap           = zoran_mmap,
-       .minor          = -1,
-};
-
-static
-int vbi_open(struct video_device *dev, int flags)
-{
-       struct zoran *ztv = dev->priv;
-       struct vidinfo* item;
-
-       DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags));
-
-       /*
-        * During VBI device open, we continiously grab VBI-like
-        * data in the vbi buffer when we have nothing to do.
-        * Only when there is an explicit request for VBI data
-        * (read call) we /force/ a read.
-        */
-
-       /* allocate buffers */
-       for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
-       {
-               item->status = FBUFFER_FREE;
-
-               /* alloc */
-               if (!item->memadr) {
-                       item->memadr = bmalloc(ZORAN_VBI_BUFSIZE);
-                       if (!item->memadr) {
-                               /* could not get a buffer, bail out */
-                               while (item != ztv->readinfo) {
-                                       item--;
-                                       bfree(item->memadr, ZORAN_VBI_BUFSIZE);
-                                       item->memadr = 0;
-                                       item->busadr = 0;
-                               }
-                               return -ENOBUFS;
-                       }
-               }
-
-               /* determine the DMAable address */
-               item->busadr = virt_to_bus(item->memadr);
-       }
-
-       /* do the common part of all open's */
-       zoran_common_open(ztv, flags);
-
-       set_bit(STATE_VBI, &ztv->state);
-       /* start read-ahead */
-       zoran_cap(ztv, 1);
-
-       return 0;
-}
-
-static
-void vbi_close(struct video_device *dev)
-{
-       struct zoran *ztv = dev->priv;
-       struct vidinfo* item;
-
-       DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD));
-
-       /* driver specific closure */
-       clear_bit(STATE_VBI, &ztv->state);
-
-       zoran_common_close(ztv);
-
-       /*
-        *      This is sucky but right now I can't find a good way to
-        *      be sure its safe to free the buffer. We wait 5-6 fields
-        *      which is more than sufficient to be sure.
-        */
-       msleep(100);                    /* Wait 1/10th of a second */
-
-       for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
-       {
-               if (item->memadr)
-                       bfree(item->memadr, ZORAN_VBI_BUFSIZE);
-               item->memadr = 0;
-       }
-
-}
-
-/*
- * This read function could be used reentrant in a SMP situation.
- *
- * This is made possible by the spinlock which is kept till we
- * found and marked a buffer for our own use. The lock must
- * be released as soon as possible to prevent lock contention.
- */
-static
-long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
-{
-       struct zoran *ztv = dev->priv;
-       unsigned long max;
-       struct vidinfo* unused = 0;
-       struct vidinfo* done = 0;
-
-       DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock));
-
-       /* find ourself a free or completed buffer */
-       for (;;) {
-               struct vidinfo* item;
-
-               write_lock_irq(&ztv->lock);
-               for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) {
-                       if (!unused && item->status == FBUFFER_FREE)
-                               unused = item;
-                       if (!done && item->status == FBUFFER_DONE)
-                               done = item;
-               }
-               if (done || unused)
-                       break;
-
-               /* no more free buffers, wait for them. */
-               write_unlock_irq(&ztv->lock);
-               if (nonblock)
-                       return -EWOULDBLOCK;
-               interruptible_sleep_on(&ztv->vbiq);
-               if (signal_pending(current))
-                       return -EINTR;
-       }
-
-       /* Do we have 'ready' data? */
-       if (!done) {
-               /* no? than this will take a while... */
-               if (nonblock) {
-                       write_unlock_irq(&ztv->lock);
-                       return -EWOULDBLOCK;
-               }
-
-               /* mark the unused buffer as wanted */
-               unused->status = FBUFFER_BUSY;
-               unused->next = 0;
-               { /* add to tail of queue */
-                 struct vidinfo* oldframe = ztv->workqueue;
-                 if (!oldframe) ztv->workqueue = unused;
-                 else {
-                   while (oldframe->next) oldframe = oldframe->next;
-                   oldframe->next = unused;
-                 }
-               }
-               write_unlock_irq(&ztv->lock);
-
-               /* tell the state machine we want it filled /NOW/ */
-               zoran_cap(ztv, 1);
-
-               /* wait till this buffer gets grabbed */
-               wait_event_interruptible(ztv->vbiq,
-                               (unused->status != FBUFFER_BUSY));
-               /* see if a signal did it */
-               if (signal_pending(current))
-                       return -EINTR;
-               done = unused;
-       }
-       else
-               write_unlock_irq(&ztv->lock);
-
-       /* Yes! we got data! */
-       max = done->bpl * -done->h;
-       if (count > max)
-               count = max;
-
-       /* check if the user gave us enough room to write the data */
-       if (!access_ok(VERIFY_WRITE, buf, count)) {
-               count = -EFAULT;
-               goto out;
-       }
-
-       /*
-        * Now transform/strip the data from YUV to Y-only
-        * NB. Assume the Y is in the LSB of the YUV data.
-        */
-       {
-       unsigned char* optr = buf;
-       unsigned char* eptr = buf+count;
-
-       /* are we beeing accessed from an old driver? */
-       if (count == 2*19*2048) {
-               /*
-                * Extreme HACK, old VBI programs expect 2048 points
-                * of data, and we only got 864 orso. Double each
-                * datapoint and clear the rest of the line.
-                * This way we have appear to have a
-                * sample_frequency of 29.5 Mc.
-                */
-               int x,y;
-               unsigned char* iptr = done->memadr+1;
-               for (y=done->h; optr<eptr && y<0; y++)
-               {
-                       /* copy to doubled data to userland */
-                       for (x=0; optr+1<eptr && x<-done->w; x++)
-                       {
-                               unsigned char a = iptr[x*2];
-                               __put_user(a, optr++);
-                               __put_user(a, optr++);
-                       }
-                       /* and clear the rest of the line */
-                       for (x*=2; optr<eptr && x<done->bpl; x++)
-                               __put_user(0, optr++);
-                       /* next line */
-                       iptr += done->bpl;
-               }
-       }
-       else {
-               /*
-                * Other (probably newer) programs asked
-                * us what geometry we are using, and are
-                * reading the correct size.
-                */
-               int x,y;
-               unsigned char* iptr = done->memadr+1;
-               for (y=done->h; optr<eptr && y<0; y++)
-               {
-                       /* copy to doubled data to userland */
-                       for (x=0; optr<eptr && x<-done->w; x++)
-                               __put_user(iptr[x*2], optr++);
-                       /* and clear the rest of the line */
-                       for (;optr<eptr && x<done->bpl; x++)
-                               __put_user(0, optr++);
-                       /* next line */
-                       iptr += done->bpl;
-               }
-       }
-
-       /* API compliance:
-        * place the framenumber (half fieldnr) in the last long
-        */
-       __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]);
-       }
-
-       /* keep the engine running */
-       done->status = FBUFFER_FREE;
-       zoran_cap(ztv, 1);
-
-       /* tell listeners this buffer just became free */
-       wake_up_interruptible(&ztv->vbiq);
-
-       /* goodbye */
-out:
-       DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count));
-       return count;
-}
-
-static
-unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait)
-{
-       struct zoran *ztv = dev->priv;
-       struct vidinfo* item;
-       unsigned int mask = 0;
-
-       poll_wait(file, &ztv->vbiq, wait);
-
-       for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
-               if (item->status == FBUFFER_DONE)
-               {
-                       mask |= (POLLIN | POLLRDNORM);
-                       break;
-               }
-
-       DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask));
-
-       return mask;
-}
-
-static
-int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
-       struct zoran* ztv = dev->priv;
-
-       switch (cmd) {
-        case VIDIOCGVBIFMT:
-        {
-               struct vbi_format f;
-               DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD));
-               f.sampling_rate = 14750000UL;
-               f.samples_per_line = -ztv->readinfo[0].w;
-               f.sample_format = VIDEO_PALETTE_RAW;
-               f.start[0] = f.start[1] = ztv->readinfo[0].y;
-               f.start[1] += 312;
-               f.count[0] = f.count[1] = -ztv->readinfo[0].h;
-               f.flags = VBI_INTERLACED;
-               if (copy_to_user(arg,&f,sizeof(f)))
-                       return -EFAULT;
-               break;
-        }
-        case VIDIOCSVBIFMT:
-        {
-               struct vbi_format f;
-               int i;
-               if (copy_from_user(&f, arg,sizeof(f)))
-                       return -EFAULT;
-               DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags));
-
-               /* lots of parameters are fixed... (PAL) */
-               if (f.sampling_rate != 14750000UL ||
-                   f.samples_per_line > 864 ||
-                   f.sample_format != VIDEO_PALETTE_RAW ||
-                   f.start[0] < 0 ||
-                   f.start[0] != f.start[1]-312 ||
-                   f.count[0] != f.count[1] ||
-                   f.start[0]+f.count[0] >= 288 ||
-                   f.flags != VBI_INTERLACED)
-                       return -EINVAL;
-
-               write_lock_irq(&ztv->lock);
-               ztv->readinfo[0].y = f.start[0];
-               ztv->readinfo[0].w = -f.samples_per_line;
-               ztv->readinfo[0].h = -f.count[0];
-               ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp;
-               for (i=1; i<ZORAN_VBI_BUFFERS; i++)
-                       ztv->readinfo[i] = ztv->readinfo[i];
-               write_unlock_irq(&ztv->lock);
-               break;
-        }
-        default:
-               return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static struct video_device vbi_template=
-{
-       .owner          = THIS_MODULE,
-       .name           = "UNSET",
-       .type           = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
-       .hardware       = VID_HARDWARE_ZR36120,
-       .open           = vbi_open,
-       .close          = vbi_close,
-       .read           = vbi_read,
-       .write          = zoran_write,
-       .poll           = vbi_poll,
-       .ioctl          = vbi_ioctl,
-       .minor          = -1,
-};
-
-/*
- *      Scan for a Zoran chip, request the irq and map the io memory
- */
-static
-int __init find_zoran(void)
-{
-       int result;
-       struct zoran *ztv;
-       struct pci_dev *dev = NULL;
-       unsigned char revision;
-       int zoran_num = 0;
-
-       while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev)))
-       {
-               /* Ok, a ZR36120/ZR36125 found! */
-               ztv = &zorans[zoran_num];
-               ztv->dev = dev;
-
-               if (pci_enable_device(dev))
-                       continue;
-
-               pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision);
-               printk(KERN_INFO "zoran: Zoran %x (rev %d) ",
-                       dev->device, revision);
-               printk("bus: %d, devfn: %d, irq: %d, ",
-                       dev->bus->number, dev->devfn, dev->irq);
-               printk("memory: 0x%08lx.\n", ztv->zoran_adr);
-
-               ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000);
-               DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem));
-
-               result = request_irq(dev->irq, zoran_irq,
-                       IRQF_SHARED|IRQF_DISABLED,"zoran", ztv);
-               if (result==-EINVAL)
-               {
-                       iounmap(ztv->zoran_mem);
-                       printk(KERN_ERR "zoran: Bad irq number or handler\n");
-                       continue;
-               }
-               if (result==-EBUSY)
-                       printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq);
-               if (result < 0) {
-                       iounmap(ztv->zoran_mem);
-                       continue;
-               }
-               /* Enable bus-mastering */
-               pci_set_master(dev);
-               /* Keep a reference */
-               pci_dev_get(dev);
-               zoran_num++;
-       }
-       if(zoran_num)
-               printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num);
-       return zoran_num;
-}
-
-static
-int __init init_zoran(int card)
-{
-       struct zoran *ztv = &zorans[card];
-       int     i;
-
-       /* if the given cardtype valid? */
-       if (cardtype[card]>=NRTVCARDS) {
-               printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]);
-               return -1;
-       }
-
-       /* reset the zoran */
-       zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);
-       udelay(10);
-       zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);
-       udelay(10);
-
-       /* zoran chip specific details */
-       ztv->card = tvcards+cardtype[card];     /* point to the selected card */
-       ztv->norm = 0;                          /* PAL */
-       ztv->tuner_freq = 0;
-
-       /* videocard details */
-       ztv->swidth = 800;
-       ztv->sheight = 600;
-       ztv->depth = 16;
-
-       /* State details */
-       ztv->fbuffer = 0;
-       ztv->overinfo.kindof = FBUFFER_OVERLAY;
-       ztv->overinfo.status = FBUFFER_FREE;
-       ztv->overinfo.x = 0;
-       ztv->overinfo.y = 0;
-       ztv->overinfo.w = 768; /* 640 */
-       ztv->overinfo.h = 576; /* 480 */
-       ztv->overinfo.format = VIDEO_PALETTE_RGB565;
-       ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp;
-       ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth;
-       ztv->overinfo.busadr = 0;
-       ztv->overinfo.memadr = 0;
-       ztv->overinfo.overlay = 0;
-       for (i=0; i<ZORAN_MAX_FBUFFERS; i++) {
-               ztv->grabinfo[i] = ztv->overinfo;
-               ztv->grabinfo[i].kindof = FBUFFER_GRAB;
-       }
-       init_waitqueue_head(&ztv->grabq);
-
-       /* VBI details */
-       ztv->readinfo[0] = ztv->overinfo;
-       ztv->readinfo[0].kindof = FBUFFER_VBI;
-       ztv->readinfo[0].w = -864;
-       ztv->readinfo[0].h = -38;
-       ztv->readinfo[0].format = VIDEO_PALETTE_YUV422;
-       ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp;
-       ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp;
-       for (i=1; i<ZORAN_VBI_BUFFERS; i++)
-               ztv->readinfo[i] = ztv->readinfo[0];
-       init_waitqueue_head(&ztv->vbiq);
-
-       /* maintenance data */
-       ztv->have_decoder = 0;
-       ztv->have_tuner = 0;
-       ztv->tuner_type = 0;
-       ztv->running = 0;
-       ztv->users = 0;
-       rwlock_init(&ztv->lock);
-       ztv->workqueue = 0;
-       ztv->fieldnr = 0;
-       ztv->lastfieldnr = 0;
-
-       if (triton1)
-               zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC);
-
-       /* external FL determines TOP frame */
-       zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC);
-
-       /* set HSpol */
-       if (ztv->card->hsync_pos)
-               zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH);
-       /* set VSpol */
-       if (ztv->card->vsync_pos)
-               zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV);
-
-       /* Set the proper General Purpuse register bits */
-       /* implicit: no softreset, 0 waitstates */
-       zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI);
-       /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */
-       zrwrite(ztv->card->gpval<<24,ZORAN_GUEST);
-
-       /* clear interrupt status */
-       zrwrite(~0, ZORAN_ISR);
-
-       /*
-        * i2c template
-        */
-       ztv->i2c = zoran_i2c_bus_template;
-       sprintf(ztv->i2c.name,"zoran-%d",card);
-       ztv->i2c.data = ztv;
-
-       /*
-        * Now add the template and register the device unit
-        */
-       ztv->video_dev = zr36120_template;
-       strcpy(ztv->video_dev.name, ztv->i2c.name);
-       ztv->video_dev.priv = ztv;
-       if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0)
-               return -1;
-
-       ztv->vbi_dev = vbi_template;
-       strcpy(ztv->vbi_dev.name, ztv->i2c.name);
-       ztv->vbi_dev.priv = ztv;
-       if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {
-               video_unregister_device(&ztv->video_dev);
-               return -1;
-       }
-       i2c_register_bus(&ztv->i2c);
-
-       /* set interrupt mask - the PIN enable will be set later */
-       zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR);
-
-       printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name);
-       return 0;
-}
-
-static
-void release_zoran(int max)
-{
-       struct zoran *ztv;
-       int i;
-
-       for (i=0;i<max; i++)
-       {
-               ztv = &zorans[i];
-
-               /* turn off all capturing, DMA and IRQs */
-               /* reset the zoran */
-               zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);
-               udelay(10);
-               zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);
-               udelay(10);
-
-               /* first disable interrupts before unmapping the memory! */
-               zrwrite(0, ZORAN_ICR);
-               zrwrite(0xffffffffUL,ZORAN_ISR);
-
-               /* free it */
-               free_irq(ztv->dev->irq,ztv);
-
-               /* unregister i2c_bus */
-               i2c_unregister_bus((&ztv->i2c));
-
-               /* unmap and free memory */
-               if (ztv->zoran_mem)
-                       iounmap(ztv->zoran_mem);
-
-               /* Drop PCI device */
-               pci_dev_put(ztv->dev);
-
-               video_unregister_device(&ztv->video_dev);
-               video_unregister_device(&ztv->vbi_dev);
-       }
-}
-
-void __exit zr36120_exit(void)
-{
-       release_zoran(zoran_cards);
-}
-
-int __init zr36120_init(void)
-{
-       int     card;
-
-       handle_chipset();
-       zoran_cards = find_zoran();
-       if (zoran_cards <= 0)
-               return -EIO;
-
-       /* initialize Zorans */
-       for (card=0; card<zoran_cards; card++) {
-               if (init_zoran(card) < 0) {
-                       /* only release the zorans we have registered */
-                       release_zoran(card);
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-module_init(zr36120_init);
-module_exit(zr36120_exit);
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h
deleted file mode 100644 (file)
index a71e485..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
-    zr36120.h - Zoran 36120/36125 based framegrabbers
-
-    Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl)
-
-    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.
-*/
-
-#ifndef _ZR36120_H
-#define _ZR36120_H
-
-#ifdef __KERNEL__
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-#include <linux/i2c-old.h>
-#include <linux/videodev.h>
-
-#include <asm/io.h>
-
-/*
- * Debug macro's, place an x behind the ) for actual debug-compilation
- * E.g. #define DEBUG(x...)    x
- */
-#define DEBUG(x...)                    /* Debug driver */
-#define IDEBUG(x...)                   /* Debug interrupt handler */
-#define PDEBUG         0               /* Debug PCI writes */
-
-/* defined in zr36120_i2c */
-extern struct i2c_bus zoran_i2c_bus_template;
-
-#define        ZORAN_MAX_FBUFFERS      2
-#define        ZORAN_MAX_FBUFFER       (768*576*2)
-#define        ZORAN_MAX_FBUFSIZE      (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER)
-
-#define        ZORAN_VBI_BUFFERS       2
-#define        ZORAN_VBI_BUFSIZE       (22*1024*2)
-
-struct tvcard {
-       char*   name;           /* name of the cardtype */
-       int     video_inputs;   /* number of channels defined in video_mux */
-       int     audio_inputs;   /* number of channels defined in audio_mux */
-       __u32   swapi2c:1,      /* need to swap i2c wires SDA/SCL? */
-               usegirq1:1,     /* VSYNC at GIRQ1 instead of GIRQ0? */
-               vsync_pos:1,    /* positive VSYNC signal? */
-               hsync_pos:1,    /* positive HSYNC signal? */
-               gpdir:8,        /* General Purpose Direction register */
-               gpval:8;        /* General Purpose Value register */
-       int     video_mux[6];   /* mapping channel number to physical input */
-#define                IS_TUNER        0x80
-#define                IS_SVHS         0x40
-#define                CHANNEL_MASK    0x3F
-       int     audio_mux[6];   /* mapping channel number to physical input */
-};
-#define        TUNER(x)        ((x)|IS_TUNER)
-#define        SVHS(x)         ((x)|IS_SVHS)
-
-struct vidinfo {
-       struct  vidinfo* next;  /* next active buffer                   */
-       uint    kindof;
-#define        FBUFFER_OVERLAY         0
-#define        FBUFFER_GRAB            1
-#define        FBUFFER_VBI             2
-       uint    status;
-#define FBUFFER_FREE           0
-#define FBUFFER_BUSY           1
-#define FBUFFER_DONE           2
-       ulong   fieldnr;        /* # of field, not framer!              */
-       uint    x,y;
-       int     w,h;            /* w,h can be negative!                 */
-       uint    format;         /* index in palette2fmt[]               */
-       uint    bpp;            /* lookup from palette2fmt[]            */
-       uint    bpl;            /* calc: width * bpp                    */
-       ulong   busadr;         /* bus addr for DMA engine              */
-       char*   memadr;         /* kernel addr for making copies        */
-       ulong*  overlay;        /* kernel addr of overlay mask          */
-};
-
-struct zoran
-{
-       struct video_device video_dev;
-#define CARD_DEBUG     KERN_DEBUG "%s(%lu): "
-#define CARD_INFO      KERN_INFO "%s(%lu): "
-#define CARD_ERR       KERN_ERR "%s(%lu): "
-#define CARD           ztv->video_dev.name,ztv->fieldnr
-
-       /* zoran chip specific details */
-       struct i2c_bus  i2c;            /* i2c registration data        */
-       struct pci_dev* dev;            /* ptr to PCI device            */
-       ulong           zoran_adr;      /* bus address of IO memory     */
-       char*           zoran_mem;      /* kernel address of IO memory  */
-       struct tvcard*  card;           /* the cardtype                 */
-       uint            norm;           /* 0=PAL, 1=NTSC, 2=SECAM       */
-       uint            tuner_freq;     /* Current freq in kHz          */
-       struct video_picture picture;   /* Current picture params       */
-
-       /* videocard details */
-       uint            swidth;         /* screen width                 */
-       uint            sheight;        /* screen height                */
-       uint            depth;          /* depth in bits                */
-
-       /* State details */
-       char*           fbuffer;        /* framebuffers for mmap        */
-       struct vidinfo  overinfo;       /* overlay data                 */
-       struct vidinfo  grabinfo[ZORAN_MAX_FBUFFERS];   /* grabbing data*/
-       wait_queue_head_t grabq;        /* grabbers queue               */
-
-       /* VBI details */
-       struct video_device vbi_dev;
-       struct vidinfo  readinfo[2];    /* VBI data - flip buffers      */
-       wait_queue_head_t vbiq;         /* vbi queue                    */
-
-       /* maintenance data */
-       int             have_decoder;   /* did we detect a mux?         */
-       int             have_tuner;     /* did we detect a tuner?       */
-       int             users;          /* howmany video/vbi open?      */
-       int             tuner_type;     /* tuner type, when found       */
-       int             running;        /* are we rolling?              */
-       rwlock_t        lock;
-       long            state;          /* what is requested of us?     */
-#define STATE_OVERLAY  0
-#define STATE_VBI      1
-       struct vidinfo* workqueue;      /* buffers to grab, head is active */
-       ulong           fieldnr;        /* #field, ticked every VSYNC   */
-       ulong           lastfieldnr;    /* #field, ticked every GRAB    */
-
-       int             vidInterlace;   /* calculated */
-       int             vidXshift;      /* calculated */
-       uint            vidWidth;       /* calculated */
-       uint            vidHeight;      /* calculated */
-};
-
-#define zrwrite(dat,adr)    writel((dat),(char *) (ztv->zoran_mem+(adr)))
-#define zrread(adr)         readl(ztv->zoran_mem+(adr))
-
-#if PDEBUG == 0
-#define zrand(dat,adr)      zrwrite((dat) & zrread(adr), adr)
-#define zror(dat,adr)       zrwrite((dat) | zrread(adr), adr)
-#define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr)
-#else
-#define zrand(dat, adr) \
-do { \
-       ulong data = (dat) & zrread((adr)); \
-       zrwrite(data, (adr)); \
-       if (0 != (~(dat) & zrread((adr)))) \
-               printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \
-} while(0)
-
-#define zror(dat, adr) \
-do { \
-       ulong data = (dat) | zrread((adr)); \
-       zrwrite(data, (adr)); \
-       if ((dat) != ((dat) & zrread(adr))) \
-               printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \
-} while(0)
-
-#define zraor(dat, mask, adr) \
-do { \
-       ulong data; \
-       if ((dat) & (mask)) \
-               printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \
-       data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \
-       zrwrite(data,(adr)); \
-       if ( (dat) != (~(mask) & zrread((adr))) ) \
-               printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \
-} while(0)
-#endif
-
-#endif
-
-/* zoran PCI address space */
-#define ZORAN_VFEH             0x000   /* Video Front End Horizontal Conf. */
-#define        ZORAN_VFEH_HSPOL        (1<<30)
-#define        ZORAN_VFEH_HSTART       (0x3FF<<10)
-#define        ZORAN_VFEH_HEND         (0x3FF<<0)
-
-#define ZORAN_VFEV             0x004   /* Video Front End Vertical Conf. */
-#define        ZORAN_VFEV_VSPOL        (1<<30)
-#define        ZORAN_VFEV_VSTART       (0x3FF<<10)
-#define        ZORAN_VFEV_VEND         (0x3FF<<0)
-
-#define        ZORAN_VFEC              0x008   /* Video Front End Scaler and Pixel */
-#define ZORAN_VFEC_EXTFL       (1<<26)
-#define        ZORAN_VFEC_TOPFIELD     (1<<25)
-#define        ZORAN_VFEC_VCLKPOL      (1<<24)
-#define        ZORAN_VFEC_HFILTER      (7<<21)
-#define        ZORAN_VFEC_HFILTER_1    (0<<21) /* no lumi,    3-tap chromo */
-#define        ZORAN_VFEC_HFILTER_2    (1<<21) /* 3-tap lumi, 3-tap chromo */
-#define        ZORAN_VFEC_HFILTER_3    (2<<21) /* 4-tap lumi, 4-tap chromo */
-#define        ZORAN_VFEC_HFILTER_4    (3<<21) /* 5-tap lumi, 4-tap chromo */
-#define        ZORAN_VFEC_HFILTER_5    (4<<21) /* 4-tap lumi, 4-tap chromo */
-#define        ZORAN_VFEC_DUPFLD       (1<<20)
-#define        ZORAN_VFEC_HORDCM       (63<<14)
-#define        ZORAN_VFEC_VERDCM       (63<<8)
-#define        ZORAN_VFEC_DISPMOD      (1<<6)
-#define        ZORAN_VFEC_RGB          (3<<3)
-#define        ZORAN_VFEC_RGB_YUV422   (0<<3)
-#define        ZORAN_VFEC_RGB_RGB888   (1<<3)
-#define        ZORAN_VFEC_RGB_RGB565   (2<<3)
-#define        ZORAN_VFEC_RGB_RGB555   (3<<3)
-#define        ZORAN_VFEC_ERRDIF       (1<<2)
-#define        ZORAN_VFEC_PACK24       (1<<1)
-#define        ZORAN_VFEC_LE           (1<<0)
-
-#define        ZORAN_VTOP              0x00C   /* Video Display "Top" */
-
-#define        ZORAN_VBOT              0x010   /* Video Display "Bottom" */
-
-#define        ZORAN_VSTR              0x014   /* Video Display Stride */
-#define        ZORAN_VSTR_DISPSTRIDE   (0xFFFF<<16)
-#define        ZORAN_VSTR_VIDOVF       (1<<8)
-#define        ZORAN_VSTR_SNAPSHOT     (1<<1)
-#define        ZORAN_VSTR_GRAB         (1<<0)
-
-#define        ZORAN_VDC               0x018   /* Video Display Conf. */
-#define        ZORAN_VDC_VIDEN         (1<<31)
-#define        ZORAN_VDC_MINPIX        (0x1F<<25)
-#define        ZORAN_VDC_TRICOM        (1<<24)
-#define        ZORAN_VDC_VIDWINHT      (0x3FF<<12)
-#define        ZORAN_VDC_VIDWINWID     (0x3FF<<0)
-
-#define        ZORAN_MTOP              0x01C   /* Masking Map "Top" */
-
-#define        ZORAN_MBOT              0x020   /* Masking Map "Bottom" */
-
-#define        ZORAN_OCR               0x024   /* Overlay Control */
-#define        ZORAN_OCR_OVLEN         (1<<15)
-#define        ZORAN_OCR_MASKSTRIDE    (0xFF<<0)
-
-#define        ZORAN_PCI               0x028   /* System, PCI and GPP Control */
-#define        ZORAN_PCI_SOFTRESET     (1<<24)
-#define        ZORAN_PCI_WAITSTATE     (3<<16)
-#define        ZORAN_PCI_GENPURDIR     (0xFF<<0)
-
-#define        ZORAN_GUEST             0x02C   /* GuestBus Control */
-
-#define        ZORAN_CSOURCE           0x030   /* Code Source Address */
-
-#define        ZORAN_CTRANS            0x034   /* Code Transfer Control */
-
-#define        ZORAN_CMEM              0x038   /* Code Memory Pointer */
-
-#define        ZORAN_ISR               0x03C   /* Interrupt Status Register */
-#define        ZORAN_ISR_CODE          (1<<28)
-#define        ZORAN_ISR_GIRQ0         (1<<29)
-#define        ZORAN_ISR_GIRQ1         (1<<30)
-
-#define        ZORAN_ICR               0x040   /* Interrupt Control Register */
-#define        ZORAN_ICR_EN            (1<<24)
-#define        ZORAN_ICR_CODE          (1<<28)
-#define        ZORAN_ICR_GIRQ0         (1<<29)
-#define        ZORAN_ICR_GIRQ1         (1<<30)
-
-#define        ZORAN_I2C               0x044   /* I2C-Bus */
-#define ZORAN_I2C_SCL          (1<<1)
-#define ZORAN_I2C_SDA          (1<<0)
-
-#define        ZORAN_POST              0x48    /* PostOffice */
-#define        ZORAN_POST_PEN          (1<<25)
-#define        ZORAN_POST_TIME         (1<<24)
-#define        ZORAN_POST_DIR          (1<<23)
-#define        ZORAN_POST_GUESTID      (3<<20)
-#define        ZORAN_POST_GUEST        (7<<16)
-#define        ZORAN_POST_DATA         (0xFF<<0)
-
-#endif
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c
deleted file mode 100644 (file)
index 21fde43..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-    zr36120_i2c.c - Zoran 36120/36125 based framegrabbers
-
-    Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
-    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/types.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#include <linux/video_decoder.h>
-#include <asm/uaccess.h>
-
-#include "tuner.h"
-#include "zr36120.h"
-
-/* ----------------------------------------------------------------------- */
-/* I2C functions                                                          */
-/* ----------------------------------------------------------------------- */
-
-/* software I2C functions */
-
-#define I2C_DELAY   10
-
-static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
-{
-       struct zoran *ztv = (struct zoran*)bus->data;
-       unsigned int b = 0;
-       if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA;
-       if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL;
-       zrwrite(b, ZORAN_I2C);
-       udelay(I2C_DELAY);
-}
-
-static int i2c_getdataline(struct i2c_bus *bus)
-{
-       struct zoran *ztv = (struct zoran*)bus->data;
-       if (ztv->card->swapi2c)
-               return zrread(ZORAN_I2C) & ZORAN_I2C_SCL;
-       return zrread(ZORAN_I2C) & ZORAN_I2C_SDA;
-}
-
-static
-void attach_inform(struct i2c_bus *bus, int id)
-{
-       struct zoran *ztv = (struct zoran*)bus->data;
-       struct video_decoder_capability dc;
-       int rv;
-
-       switch (id) {
-        case I2C_DRIVERID_VIDEODECODER:
-               DEBUG(printk(CARD_INFO "decoder attached\n",CARD));
-
-               /* fetch the capabilities of the decoder */
-               rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc);
-               if (rv) {
-                       DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD));
-                       break;
-               }
-               DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs));
-
-               /* Test if the decoder can de VBI transfers */
-               if (dc.flags & 16 /*VIDEO_DECODER_VBI*/)
-                       ztv->have_decoder = 2;
-               else
-                       ztv->have_decoder = 1;
-               break;
-        case I2C_DRIVERID_TUNER:
-               ztv->have_tuner = 1;
-               DEBUG(printk(CARD_INFO "tuner attached\n",CARD));
-               if (ztv->tuner_type >= 0)
-               {
-                       if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0)
-                       DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type));
-               }
-               break;
-        default:
-               DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id));
-               break;
-       }
-}
-
-static
-void detach_inform(struct i2c_bus *bus, int id)
-{
-       struct zoran *ztv = (struct zoran*)bus->data;
-
-       switch (id) {
-        case I2C_DRIVERID_VIDEODECODER:
-               ztv->have_decoder = 0;
-               DEBUG(printk(CARD_INFO "decoder detached\n",CARD));
-               break;
-        case I2C_DRIVERID_TUNER:
-               ztv->have_tuner = 0;
-               DEBUG(printk(CARD_INFO "tuner detached\n",CARD));
-               break;
-        default:
-               DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id));
-               break;
-       }
-}
-
-struct i2c_bus zoran_i2c_bus_template =
-{
-       "ZR36120",
-       I2C_BUSID_ZORAN,
-       NULL,
-
-       SPIN_LOCK_UNLOCKED,
-
-       attach_inform,
-       detach_inform,
-
-       i2c_setlines,
-       i2c_getdataline,
-       NULL,
-       NULL
-};
diff --git a/drivers/media/video/zr36120_mem.c b/drivers/media/video/zr36120_mem.c
deleted file mode 100644 (file)
index 416eaa9..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-    zr36120_mem.c - Zoran 36120/36125 based framegrabbers
-
-    Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
-    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/mm.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#ifdef CONFIG_BIGPHYS_AREA
-#include <linux/bigphysarea.h>
-#endif
-
-#include "zr36120.h"
-#include "zr36120_mem.h"
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-void* bmalloc(unsigned long size)
-{
-       void* mem;
-#ifdef CONFIG_BIGPHYS_AREA
-       mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL);
-#else
-       /*
-        * The following function got a lot of memory at boottime,
-        * so we know its always there...
-        */
-       mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size));
-#endif
-       if (mem) {
-               unsigned long adr = (unsigned long)mem;
-               while (size > 0) {
-                       SetPageReserved(virt_to_page(phys_to_virt(adr)));
-                       adr += PAGE_SIZE;
-                       size -= PAGE_SIZE;
-               }
-       }
-       return mem;
-}
-
-void bfree(void* mem, unsigned long size)
-{
-       if (mem) {
-               unsigned long adr = (unsigned long)mem;
-               unsigned long siz = size;
-               while (siz > 0) {
-                       ClearPageReserved(virt_to_page(phys_to_virt(adr)));
-                       adr += PAGE_SIZE;
-                       siz -= PAGE_SIZE;
-               }
-#ifdef CONFIG_BIGPHYS_AREA
-               bigphysarea_free_pages(mem);
-#else
-               free_pages((unsigned long)mem,get_order(size));
-#endif
-       }
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zr36120_mem.h b/drivers/media/video/zr36120_mem.h
deleted file mode 100644 (file)
index aad117a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* either kmalloc() or bigphysarea() alloced memory - continuous */
-void*  bmalloc(unsigned long size);
-void   bfree(void* mem, unsigned long size);
index 051b7c5..6e068cf 100644 (file)
@@ -347,7 +347,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
  *     @irq: irq number (not used)
  *     @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
@@ -387,14 +387,16 @@ mpt_interrupt(int irq, void *bus_id)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mpt_base_reply - MPT base driver's callback routine; all base driver
- *     "internal" request/reply processing is routed here.
- *     Currently used for EventNotification and EventAck handling.
+/**
+ *     mpt_base_reply - MPT base driver's callback routine
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @mf: Pointer to original MPT request frame
  *     @reply: Pointer to MPT reply frame (NULL if TurboReply)
  *
+ *     MPT base driver's callback routine; all base driver
+ *     "internal" request/reply processing is routed here.
+ *     Currently used for EventNotification and EventAck handling.
+ *
  *     Returns 1 indicating original alloc'd request frame ptr
  *     should be freed, or 0 if it shouldn't.
  */
@@ -530,7 +532,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
  *     @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
  *
  *     This routine is called by a protocol-specific driver (SCSI host,
- *     LAN, SCSI target) to register it's reply callback routine.  Each
+ *     LAN, SCSI target) to register its reply callback routine.  Each
  *     protocol-specific driver must do this before it will be able to
  *     use any IOC resources, such as obtaining request frames.
  *
@@ -572,7 +574,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
  *     mpt_deregister - Deregister a protocol drivers resources.
  *     @cb_idx: previously registered callback handle
  *
- *     Each protocol-specific driver should call this routine when it's
+ *     Each protocol-specific driver should call this routine when its
  *     module is unloaded.
  */
 void
@@ -617,7 +619,7 @@ mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
  *
  *     Each protocol-specific driver should call this routine
  *     when it does not (or can no longer) handle events,
- *     or when it's module is unloaded.
+ *     or when its module is unloaded.
  */
 void
 mpt_event_deregister(int cb_idx)
@@ -656,7 +658,7 @@ mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
  *
  *     Each protocol-specific driver should call this routine
  *     when it does not (or can no longer) handle IOC reset handling,
- *     or when it's module is unloaded.
+ *     or when its module is unloaded.
  */
 void
 mpt_reset_deregister(int cb_idx)
@@ -670,6 +672,8 @@ mpt_reset_deregister(int cb_idx)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_device_driver_register - Register device driver hooks
+ *     @dd_cbfunc: driver callbacks struct
+ *     @cb_idx: MPT protocol driver index
  */
 int
 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
@@ -696,6 +700,7 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_device_driver_deregister - DeRegister device driver hooks
+ *     @cb_idx: MPT protocol driver index
  */
 void
 mpt_device_driver_deregister(int cb_idx)
@@ -887,8 +892,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_send_handshake_request - Send MPT request via doorbell
- *     handshake method.
+ *     mpt_send_handshake_request - Send MPT request via doorbell handshake method.
  *     @handle: Handle of registered MPT protocol driver
  *     @ioc: Pointer to MPT adapter structure
  *     @reqBytes: Size of the request in bytes
@@ -981,10 +985,13 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- * mpt_host_page_access_control - provides mechanism for the host
- * driver to control the IOC's Host Page Buffer access.
+ * mpt_host_page_access_control - control the IOC's Host Page Buffer access
  * @ioc: Pointer to MPT adapter structure
  * @access_control_value: define bits below
+ * @sleepFlag: Specifies whether the process can sleep
+ *
+ * Provides mechanism for the host driver to control the IOC's
+ * Host Page Buffer access.
  *
  * Access Control Value - bits[15:12]
  * 0h Reserved
@@ -1022,10 +1029,10 @@ mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int slee
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_host_page_alloc - allocate system memory for the fw
- *     If we already allocated memory in past, then resend the same pointer.
- *     ioc@: Pointer to pointer to IOC adapter
- *     ioc_init@: Pointer to ioc init config page
+ *     @ioc: Pointer to pointer to IOC adapter
+ *     @ioc_init: Pointer to ioc init config page
  *
+ *     If we already allocated memory in past, then resend the same pointer.
  *     Returns 0 for success, non-zero for failure.
  */
 static int
@@ -1091,12 +1098,15 @@ return 0;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_verify_adapter - Given a unique IOC identifier, set pointer to
- *     the associated MPT adapter structure.
+ *     mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
  *     @iocid: IOC unique identifier (integer)
  *     @iocpp: Pointer to pointer to IOC adapter
  *
- *     Returns iocid and sets iocpp.
+ *     Given a unique IOC identifier, set pointer to the associated MPT
+ *     adapter structure.
+ *
+ *     Returns iocid and sets iocpp if iocid is found.
+ *     Returns -1 if iocid is not found.
  */
 int
 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
@@ -1115,9 +1125,10 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_attach - Install a PCI intelligent MPT adapter.
  *     @pdev: Pointer to pci_dev structure
+ *     @id: PCI device ID information
  *
  *     This routine performs all the steps necessary to bring the IOC of
  *     a MPT adapter to a OPERATIONAL state.  This includes registering
@@ -1417,10 +1428,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_detach - Remove a PCI intelligent MPT adapter.
  *     @pdev: Pointer to pci_dev structure
- *
  */
 
 void
@@ -1466,10 +1476,10 @@ mpt_detach(struct pci_dev *pdev)
  */
 #ifdef CONFIG_PM
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_suspend - Fusion MPT base driver suspend routine.
- *
- *
+ *     @pdev: Pointer to pci_dev structure
+ *     @state: new state to enter
  */
 int
 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -1505,10 +1515,9 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_resume - Fusion MPT base driver resume routine.
- *
- *
+ *     @pdev: Pointer to pci_dev structure
  */
 int
 mpt_resume(struct pci_dev *pdev)
@@ -1566,7 +1575,7 @@ mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_do_ioc_recovery - Initialize or recover MPT adapter.
  *     @ioc: Pointer to MPT adapter structure
  *     @reason: Event word / reason
@@ -1892,13 +1901,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mpt_detect_bound_ports - Search for PCI bus/dev_function
- *     which matches PCI bus/dev_function (+/-1) for newly discovered 929,
- *     929X, 1030 or 1035.
+/**
+ *     mpt_detect_bound_ports - Search for matching PCI bus/dev_function
  *     @ioc: Pointer to MPT adapter structure
  *     @pdev: Pointer to (struct pci_dev) structure
  *
+ *     Search for PCI bus/dev_function which matches
+ *     PCI bus/dev_function (+/-1) for newly discovered 929,
+ *     929X, 1030 or 1035.
+ *
  *     If match on PCI dev_function +/-1 is found, bind the two MPT adapters
  *     using alt_ioc pointer fields in their %MPT_ADAPTER structures.
  */
@@ -1945,9 +1956,9 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_adapter_disable - Disable misbehaving MPT adapter.
- *     @this: Pointer to MPT adapter structure
+ *     @ioc: Pointer to MPT adapter structure
  */
 static void
 mpt_adapter_disable(MPT_ADAPTER *ioc)
@@ -2046,9 +2057,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mpt_adapter_dispose - Free all resources associated with a MPT
- *     adapter.
+/**
+ *     mpt_adapter_dispose - Free all resources associated with an MPT adapter
  *     @ioc: Pointer to MPT adapter structure
  *
  *     This routine unregisters h/w resources and frees all alloc'd memory
@@ -2099,8 +2109,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     MptDisplayIocCapabilities - Disply IOC's capacilities.
+/**
+ *     MptDisplayIocCapabilities - Disply IOC's capabilities.
  *     @ioc: Pointer to MPT adapter structure
  */
 static void
@@ -2142,7 +2152,7 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     MakeIocReady - Get IOC to a READY state, using KickStart if needed.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @force: Force hard KickStart of IOC
@@ -2279,7 +2289,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_GetIocState - Get the current state of a MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @cooked: Request raw or cooked IOC state
@@ -2304,7 +2314,7 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     GetIocFacts - Send IOCFacts request to MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @sleepFlag: Specifies whether the process can sleep
@@ -2478,7 +2488,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     GetPortFacts - Send PortFacts request to MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @portnum: Port number
@@ -2545,7 +2555,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     SendIocInit - Send IOCInit request to MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @sleepFlag: Specifies whether the process can sleep
@@ -2630,7 +2640,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
        }
 
        /* No need to byte swap the multibyte fields in the reply
-        * since we don't even look at it's contents.
+        * since we don't even look at its contents.
         */
 
        dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
@@ -2672,7 +2682,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     SendPortEnable - Send PortEnable request to MPT adapter port.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @portnum: Port number to enable
@@ -2723,9 +2733,13 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
        return rc;
 }
 
-/*
- *     ioc: Pointer to MPT_ADAPTER structure
- *      size - total FW bytes
+/**
+ *     mpt_alloc_fw_memory - allocate firmware memory
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *      @size: total FW bytes
+ *
+ *     If memory has already been allocated, the same (cached) value
+ *     is returned.
  */
 void
 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
@@ -2742,9 +2756,12 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
                        ioc->alloc_total += size;
        }
 }
-/*
- * If alt_img is NULL, delete from ioc structure.
- * Else, delete a secondary image in same format.
+/**
+ *     mpt_free_fw_memory - free firmware memory
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *
+ *     If alt_img is NULL, delete from ioc structure.
+ *     Else, delete a secondary image in same format.
  */
 void
 mpt_free_fw_memory(MPT_ADAPTER *ioc)
@@ -2763,7 +2780,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @sleepFlag: Specifies whether the process can sleep
@@ -2865,10 +2882,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_downloadboot - DownloadBoot code
  *     @ioc: Pointer to MPT_ADAPTER structure
- *     @flag: Specify which part of IOC memory is to be uploaded.
+ *     @pFwHeader: Pointer to firmware header info
  *     @sleepFlag: Specifies whether the process can sleep
  *
  *     FwDownloadBoot requires Programmed IO access.
@@ -3071,7 +3088,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     KickStart - Perform hard reset of MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @force: Force hard reset
@@ -3145,12 +3162,12 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_diag_reset - Perform hard reset of the adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @ignore: Set if to honor and clear to ignore
  *             the reset history bit
- *     @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
+ *     @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
  *             else set to NO_SLEEP (use mdelay instead)
  *
  *     This routine places the adapter in diagnostic mode via the
@@ -3436,11 +3453,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     SendIocReset - Send IOCReset request to MPT adapter.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @reset_type: reset type, expected values are
  *     %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
+ *     @sleepFlag: Specifies whether the process can sleep
  *
  *     Send IOCReset request to the MPT adapter.
  *
@@ -3494,11 +3512,12 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     initChainBuffers - Allocate memory for and initialize
- *     chain buffers, chain buffer control arrays and spinlock.
- *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @init: If set, initialize the spin lock.
+/**
+ *     initChainBuffers - Allocate memory for and initialize chain buffers
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *
+ *     Allocates memory for and initializes chain buffers,
+ *     chain buffer control arrays and spinlock.
  */
 static int
 initChainBuffers(MPT_ADAPTER *ioc)
@@ -3594,7 +3613,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     PrimeIocFifos - Initialize IOC request and reply FIFOs.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *
@@ -3891,15 +3910,15 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
- *     in it's IntStatus register.
+/**
+ *     WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @howlong: How long to wait (in seconds)
  *     @sleepFlag: Specifies whether the process can sleep
  *
  *     This routine waits (up to ~2 seconds max) for IOC doorbell
- *     handshake ACKnowledge.
+ *     handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
+ *     bit in its IntStatus register being clear.
  *
  *     Returns a negative value on failure, else wait loop count.
  */
@@ -3942,14 +3961,14 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
- *     in it's IntStatus register.
+/**
+ *     WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @howlong: How long to wait (in seconds)
  *     @sleepFlag: Specifies whether the process can sleep
  *
- *     This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
+ *     This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
+ *     (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
  *
  *     Returns a negative value on failure, else wait loop count.
  */
@@ -3991,8 +4010,8 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
+/**
+ *     WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @howlong: How long to wait (in seconds)
  *     @sleepFlag: Specifies whether the process can sleep
@@ -4077,7 +4096,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     GetLanConfigPages - Fetch LANConfig pages.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *
@@ -4188,12 +4207,9 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
+/**
+ *     mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
  *     @ioc: Pointer to MPT_ADAPTER structure
- *     @sas_address: 64bit SAS Address for operation.
- *     @target_id: specified target for operation
- *     @bus: specified bus for operation
  *     @persist_opcode: see below
  *
  *     MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
@@ -4202,7 +4218,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
  *
  *     NOTE: Don't use not this function during interrupt time.
  *
- *     Returns: 0 for success, non-zero error
+ *     Returns 0 for success, non-zero error
  */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4399,7 +4415,7 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     GetIoUnitPage2 - Retrieve BIOS version and boot order information.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *
@@ -4457,7 +4473,8 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
+/**
+ *     mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
  *     @ioc: Pointer to a Adapter Strucutre
  *     @portnum: IOC port number
  *
@@ -4644,7 +4661,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mpt_readScsiDevicePageHeaders - save version and length of SDP1
+/**
+ *     mpt_readScsiDevicePageHeaders - save version and length of SDP1
  *     @ioc: Pointer to a Adapter Strucutre
  *     @portnum: IOC port number
  *
@@ -4996,9 +5014,8 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     SendEventNotification - Send EventNotification (on or off) request
- *     to MPT adapter.
+/**
+ *     SendEventNotification - Send EventNotification (on or off) request to adapter
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @EvSwitch: Event switch flags
  */
@@ -5062,8 +5079,8 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_config - Generic function to issue config message
- *     @ioc - Pointer to an adapter structure
- *     @cfg - Pointer to a configuration structure. Struct contains
+ *     @ioc:   Pointer to an adapter structure
+ *     @pCfg:  Pointer to a configuration structure. Struct contains
  *             action, page address, direction, physical address
  *             and pointer to a configuration page header
  *             Page header is updated.
@@ -5188,8 +5205,8 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mpt_timer_expired - Call back for timer process.
+/**
+ *     mpt_timer_expired - Callback for timer process.
  *     Used only internal config functionality.
  *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
  */
@@ -5214,12 +5231,12 @@ mpt_timer_expired(unsigned long data)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_ioc_reset - Base cleanup for hard reset
  *     @ioc: Pointer to the adapter structure
  *     @reset_phase: Indicates pre- or post-reset functionality
  *
- *     Remark: Free's resources with internally generated commands.
+ *     Remark: Frees resources with internally generated commands.
  */
 static int
 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
@@ -5271,7 +5288,7 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
  *     procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
  *
  *     Returns 0 for success, non-zero for failure.
@@ -5297,7 +5314,7 @@ procmpt_create(void)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
  *
  *     Returns 0 for success, non-zero for failure.
@@ -5311,16 +5328,16 @@ procmpt_destroy(void)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     procmpt_summary_read - Handle read request from /proc/mpt/summary
- *     or from /proc/mpt/iocN/summary.
+/**
+ *     procmpt_summary_read - Handle read request of a summary file
  *     @buf: Pointer to area to write information
  *     @start: Pointer to start pointer
  *     @offset: Offset to start writing
- *     @request:
+ *     @request: Amount of read data requested
  *     @eof: Pointer to EOF integer
  *     @data: Pointer
  *
+ *     Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
  *     Returns number of characters written to process performing the read.
  */
 static int
@@ -5355,12 +5372,12 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     procmpt_version_read - Handle read request from /proc/mpt/version.
  *     @buf: Pointer to area to write information
  *     @start: Pointer to start pointer
  *     @offset: Offset to start writing
- *     @request:
+ *     @request: Amount of read data requested
  *     @eof: Pointer to EOF integer
  *     @data: Pointer
  *
@@ -5411,12 +5428,12 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
  *     @buf: Pointer to area to write information
  *     @start: Pointer to start pointer
  *     @offset: Offset to start writing
- *     @request:
+ *     @request: Amount of read data requested
  *     @eof: Pointer to EOF integer
  *     @data: Pointer
  *
@@ -5577,16 +5594,17 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mpt_HardResetHandler - Generic reset handler, issue SCSI Task
- *     Management call based on input arg values.  If TaskMgmt fails,
- *     return associated SCSI request.
+ *     mpt_HardResetHandler - Generic reset handler
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @sleepFlag: Indicates if sleep or schedule must be called.
  *
+ *     Issues SCSI Task Management call based on input arg values.
+ *     If TaskMgmt fails, returns associated SCSI request.
+ *
  *     Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  *     or a non-interrupt thread.  In the former, must not call schedule().
  *
- *     Remark: A return of -1 is a FATAL error case, as it means a
+ *     Note: A return of -1 is a FATAL error case, as it means a
  *     FW reload/initialization failed.
  *
  *     Returns 0 for SUCCESS or -1 if FAILED.
@@ -5935,13 +5953,14 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     ProcessEventNotification - Route a received EventNotificationReply to
- *     all currently regeistered event handlers.
+/**
+ *     ProcessEventNotification - Route EventNotificationReply to all event handlers
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @pEventReply: Pointer to EventNotification reply frame
  *     @evHandlers: Pointer to integer, number of event handlers
  *
+ *     Routes a received EventNotificationReply to all currently registered
+ *     event handlers.
  *     Returns sum of event handlers return values.
  */
 static int
@@ -6056,7 +6075,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_fc_log_info - Log information returned from Fibre Channel IOC.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @log_info: U32 LogInfo reply word from the IOC
@@ -6077,7 +6096,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @mr: Pointer to MPT reply frame
@@ -6200,7 +6219,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
        };
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_sas_log_info - Log information returned from SAS IOC.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @log_info: U32 LogInfo reply word from the IOC
@@ -6255,7 +6274,7 @@ union loginfo_type {
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @ioc_status: U32 IOCStatus word from IOC
@@ -6416,7 +6435,7 @@ EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     fusion_init - Fusion MPT base driver initialization routine.
  *
  *     Returns 0 for success, non-zero for failure.
@@ -6456,7 +6475,7 @@ fusion_init(void)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *     fusion_exit - Perform driver unload cleanup.
  *
  *     This routine frees all resources associated with each MPT adapter
index 1dd4917..ca2f910 100644 (file)
@@ -1018,9 +1018,10 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
 }
 
 static void
-mptfc_setup_reset(void *arg)
+mptfc_setup_reset(struct work_struct *work)
 {
-       MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
+       MPT_ADAPTER             *ioc =
+               container_of(work, MPT_ADAPTER, fc_setup_reset_work);
        u64                     pn;
        struct mptfc_rport_info *ri;
 
@@ -1043,9 +1044,10 @@ mptfc_setup_reset(void *arg)
 }
 
 static void
-mptfc_rescan_devices(void *arg)
+mptfc_rescan_devices(struct work_struct *work)
 {
-       MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
+       MPT_ADAPTER             *ioc =
+               container_of(work, MPT_ADAPTER, fc_rescan_work);
        int                     ii;
        u64                     pn;
        struct mptfc_rport_info *ri;
@@ -1154,8 +1156,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
         }
 
        spin_lock_init(&ioc->fc_rescan_work_lock);
-       INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
-       INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
+       INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
+       INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
 
        spin_lock_irqsave(&ioc->FreeQlock, flags);
 
@@ -1393,8 +1395,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptfc_init - Register MPT adapter(s) as SCSI host(s) with
- *     linux scsi mid-layer.
+ *     mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
  *
  *     Returns 0 for success, non-zero for failure.
  */
@@ -1438,7 +1439,7 @@ mptfc_init(void)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptfc_remove - Removed fc infrastructure for devices
+ *     mptfc_remove - Remove fc infrastructure for devices
  *     @pdev: Pointer to pci_dev structure
  *
  */
index 314c3a2..b7c4407 100644 (file)
@@ -111,7 +111,8 @@ struct mpt_lan_priv {
        u32 total_received;
        struct net_device_stats stats;  /* Per device statistics */
 
-       struct work_struct post_buckets_task;
+       struct delayed_work post_buckets_task;
+       struct net_device *dev;
        unsigned long post_buckets_active;
 };
 
@@ -132,7 +133,7 @@ static int  lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
 static int  mpt_lan_open(struct net_device *dev);
 static int  mpt_lan_reset(struct net_device *dev);
 static int  mpt_lan_close(struct net_device *dev);
-static void mpt_lan_post_receive_buckets(void *dev_id);
+static void mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv);
 static void mpt_lan_wake_post_buckets_task(struct net_device *dev,
                                           int priority);
 static int  mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg);
@@ -345,7 +346,7 @@ mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                        priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
                spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
        } else {
-               mpt_lan_post_receive_buckets(dev);
+               mpt_lan_post_receive_buckets(priv);
                netif_wake_queue(dev);
        }
 
@@ -441,7 +442,7 @@ mpt_lan_open(struct net_device *dev)
 
        dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n"));
 
-       mpt_lan_post_receive_buckets(dev);
+       mpt_lan_post_receive_buckets(priv);
        printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n",
                        IOC_AND_NETDEV_NAMES_s_s(dev));
 
@@ -854,7 +855,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
        
        if (test_and_set_bit(0, &priv->post_buckets_active) == 0) {
                if (priority) {
-                       schedule_work(&priv->post_buckets_task);
+                       schedule_delayed_work(&priv->post_buckets_task, 0);
                } else {
                        schedule_delayed_work(&priv->post_buckets_task, 1);
                        dioprintk((KERN_INFO MYNAM ": post_buckets queued on "
@@ -1188,10 +1189,9 @@ mpt_lan_receive_post_reply(struct net_device *dev,
 /* Simple SGE's only at the moment */
 
 static void
-mpt_lan_post_receive_buckets(void *dev_id)
+mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
 {
-       struct net_device *dev = dev_id;
-       struct mpt_lan_priv *priv = dev->priv;
+       struct net_device *dev = priv->dev;
        MPT_ADAPTER *mpt_dev = priv->mpt_dev;
        MPT_FRAME_HDR *mf;
        LANReceivePostRequest_t *pRecvReq;
@@ -1335,6 +1335,13 @@ out:
        clear_bit(0, &priv->post_buckets_active);
 }
 
+static void
+mpt_lan_post_receive_buckets_work(struct work_struct *work)
+{
+       mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv,
+                                                 post_buckets_task.work));
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static struct net_device *
 mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
@@ -1350,11 +1357,13 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
 
        priv = netdev_priv(dev);
 
+       priv->dev = dev;
        priv->mpt_dev = mpt_dev;
        priv->pnum = pnum;
 
-       memset(&priv->post_buckets_task, 0, sizeof(struct work_struct));
-       INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev);
+       memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task));
+       INIT_DELAYED_WORK(&priv->post_buckets_task,
+                         mpt_lan_post_receive_buckets_work);
        priv->post_buckets_active = 0;
 
        dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n",
index b752a47..4f0c530 100644 (file)
@@ -2006,9 +2006,10 @@ __mptsas_discovery_work(MPT_ADAPTER *ioc)
  *(Mutex LOCKED)
  */
 static void
-mptsas_discovery_work(void * arg)
+mptsas_discovery_work(struct work_struct *work)
 {
-       struct mptsas_discovery_event *ev = arg;
+       struct mptsas_discovery_event *ev =
+               container_of(work, struct mptsas_discovery_event, work);
        MPT_ADAPTER *ioc = ev->ioc;
 
        mutex_lock(&ioc->sas_discovery_mutex);
@@ -2068,9 +2069,9 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
  * Work queue thread to clear the persitency table
  */
 static void
-mptsas_persist_clear_table(void * arg)
+mptsas_persist_clear_table(struct work_struct *work)
 {
-       MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+       MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
 
        mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
 }
@@ -2093,9 +2094,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
  * Work queue thread to handle SAS hotplug events
  */
 static void
-mptsas_hotplug_work(void *arg)
+mptsas_hotplug_work(struct work_struct *work)
 {
-       struct mptsas_hotplug_event *ev = arg;
+       struct mptsas_hotplug_event *ev =
+               container_of(work, struct mptsas_hotplug_event, work);
        MPT_ADAPTER *ioc = ev->ioc;
        struct mptsas_phyinfo *phy_info;
        struct sas_rphy *rphy;
@@ -2341,7 +2343,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
                        break;
                }
 
-               INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+               INIT_WORK(&ev->work, mptsas_hotplug_work);
                ev->ioc = ioc;
                ev->handle = le16_to_cpu(sas_event_data->DevHandle);
                ev->parent_handle =
@@ -2366,7 +2368,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
         * Persistent table is full.
         */
                INIT_WORK(&ioc->sas_persist_task,
-                   mptsas_persist_clear_table, (void *)ioc);
+                   mptsas_persist_clear_table);
                schedule_work(&ioc->sas_persist_task);
                break;
        case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
@@ -2395,7 +2397,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
                return;
        }
 
-       INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+       INIT_WORK(&ev->work, mptsas_hotplug_work);
        ev->ioc = ioc;
        ev->id = raid_event_data->VolumeID;
        ev->event_type = MPTSAS_IGNORE_EVENT;
@@ -2474,7 +2476,7 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc,
        ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
        if (!ev)
                return;
-       INIT_WORK(&ev->work, mptsas_discovery_work, ev);
+       INIT_WORK(&ev->work, mptsas_discovery_work);
        ev->ioc = ioc;
        schedule_work(&ev->work);
 };
@@ -2511,8 +2513,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
                break;
        case MPI_EVENT_PERSISTENT_TABLE_FULL:
                INIT_WORK(&ioc->sas_persist_task,
-                   mptsas_persist_clear_table,
-                   (void *)ioc);
+                   mptsas_persist_clear_table);
                schedule_work(&ioc->sas_persist_task);
                break;
         case MPI_EVENT_SAS_DISCOVERY:
index 30524dc..2c72c36 100644 (file)
@@ -1230,15 +1230,15 @@ mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_proc_info - Return information about MPT adapter
+ *     @host:   scsi host struct
+ *     @buffer: if write, user data; if read, buffer for user
+ *     @start: returns the buffer address
+ *     @offset: if write, 0; if read, the current offset into the buffer from
+ *              the previous read.
+ *     @length: if write, return length;
+ *     @func:   write = 1; read = 0
  *
  *     (linux scsi_host_template.info routine)
- *
- *     buffer: if write, user data; if read, buffer for user
- *     length: if write, return length;
- *     offset: if write, 0; if read, the current offset into the buffer from
- *             the previous read.
- *     hostno: scsi host number
- *     func:   if write = 1; if read = 0
  */
 int
 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
@@ -1902,8 +1902,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_host_reset - Perform a SCSI host adapter RESET!
- *     new_eh variant
+ *     mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
  *     @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
  *
  *     (linux scsi_host_template.eh_host_reset_handler routine)
@@ -1949,8 +1948,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_tm_pending_wait - wait for pending task management request to
- *             complete.
+ *     mptscsih_tm_pending_wait - wait for pending task management request to complete
  *     @hd: Pointer to MPT host structure.
  *
  *     Returns {SUCCESS,FAILED}.
@@ -1982,6 +1980,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 /**
  *     mptscsih_tm_wait_for_completion - wait for completion of TM task
  *     @hd: Pointer to MPT host structure.
+ *     @timeout: timeout in seconds
  *
  *     Returns {SUCCESS,FAILED}.
  */
@@ -3429,8 +3428,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 /**
  *     mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
  *     @hd: Pointer to a SCSI HOST structure
- *     @vtarget: per device private data
- *     @lun: lun
+ *     @vdevice: virtual target device
  *
  *     Uses the ISR, but with special processing.
  *     MUST be single-threaded.
index e4cc3dd..36641da 100644 (file)
@@ -646,9 +646,10 @@ struct work_queue_wrapper {
        int                     disk;
 };
 
-static void mpt_work_wrapper(void *data)
+static void mpt_work_wrapper(struct work_struct *work)
 {
-       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct work_queue_wrapper *wqw =
+               container_of(work, struct work_queue_wrapper, work);
        struct _MPT_SCSI_HOST *hd = wqw->hd;
        struct Scsi_Host *shost = hd->ioc->sh;
        struct scsi_device *sdev;
@@ -695,7 +696,7 @@ static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
                           disk);
                return;
        }
-       INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
+       INIT_WORK(&wqw->work, mpt_work_wrapper);
        wqw->hd = hd;
        wqw->disk = disk;
 
@@ -784,9 +785,10 @@ MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
  * renegotiate for a given target
  */
 static void
-mptspi_dv_renegotiate_work(void *data)
+mptspi_dv_renegotiate_work(struct work_struct *work)
 {
-       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct work_queue_wrapper *wqw =
+               container_of(work, struct work_queue_wrapper, work);
        struct _MPT_SCSI_HOST *hd = wqw->hd;
        struct scsi_device *sdev;
 
@@ -804,7 +806,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
        if (!wqw)
                return;
 
-       INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
+       INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);
        wqw->hd = hd;
 
        schedule_work(&wqw->work);
@@ -1098,8 +1100,7 @@ static struct pci_driver mptspi_driver = {
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptspi_init - Register MPT adapter(s) as SCSI host(s) with
- *     linux scsi mid-layer.
+ *     mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
  *
  *     Returns 0 for success, non-zero for failure.
  */
@@ -1133,7 +1134,6 @@ mptspi_init(void)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptspi_exit - Unregisters MPT adapter(s)
- *
  */
 static void __exit
 mptspi_exit(void)
index d96c687..c463dc2 100644 (file)
@@ -56,6 +56,9 @@ static int i2o_bus_scan(struct i2o_device *dev)
 /**
  *     i2o_bus_store_scan - Scan the I2O Bus Adapter
  *     @d: device which should be scanned
+ *     @attr: device_attribute
+ *     @buf: output buffer
+ *     @count: buffer size
  *
  *     Returns count.
  */
index ee18305..b9df143 100644 (file)
@@ -54,8 +54,8 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
  *     @dev: I2O device to claim
  *     @drv: I2O driver which wants to claim the device
  *
- *     Do the leg work to assign a device to a given OSM. If the claim succeed
- *     the owner of the rimary. If the attempt fails a negative errno code
+ *     Do the leg work to assign a device to a given OSM. If the claim succeeds,
+ *     the owner is the primary. If the attempt fails a negative errno code
  *     is returned. On success zero is returned.
  */
 int i2o_device_claim(struct i2o_device *dev)
@@ -208,24 +208,23 @@ static struct i2o_device *i2o_device_alloc(void)
 
 /**
  *     i2o_device_add - allocate a new I2O device and add it to the IOP
- *     @iop: I2O controller where the device is on
+ *     @c: I2O controller that the device is on
  *     @entry: LCT entry of the I2O device
  *
  *     Allocate a new I2O device and initialize it with the LCT entry. The
  *     device is appended to the device list of the controller.
  *
- *     Returns a pointer to the I2O device on success or negative error code
- *     on failure.
+ *     Returns zero on success, or a -ve errno.
  */
-static struct i2o_device *i2o_device_add(struct i2o_controller *c,
-                                        i2o_lct_entry * entry)
+static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
 {
        struct i2o_device *i2o_dev, *tmp;
+       int rc;
 
        i2o_dev = i2o_device_alloc();
        if (IS_ERR(i2o_dev)) {
                printk(KERN_ERR "i2o: unable to allocate i2o device\n");
-               return i2o_dev;
+               return PTR_ERR(i2o_dev);
        }
 
        i2o_dev->lct_data = *entry;
@@ -236,7 +235,9 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
        i2o_dev->iop = c;
        i2o_dev->device.parent = &c->device;
 
-       device_register(&i2o_dev->device);
+       rc = device_register(&i2o_dev->device);
+       if (rc)
+               goto err;
 
        list_add_tail(&i2o_dev->list, &c->devices);
 
@@ -270,12 +271,16 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
 
        pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id);
 
-       return i2o_dev;
+       return 0;
+
+err:
+       kfree(i2o_dev);
+       return rc;
 }
 
 /**
  *     i2o_device_remove - remove an I2O device from the I2O core
- *     @dev: I2O device which should be released
+ *     @i2o_dev: I2O device which should be released
  *
  *     Is used on I2O controller removal or LCT modification, when the device
  *     is removed from the system. Note that the device could still hang
index 6413022..9104b65 100644 (file)
@@ -34,9 +34,7 @@ static spinlock_t i2o_drivers_lock;
 static struct i2o_driver **i2o_drivers;
 
 /**
- *     i2o_bus_match - Tell if a I2O device class id match the class ids of
- *                     the I2O driver (OSM)
- *
+ *     i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM)
  *     @dev: device which should be verified
  *     @drv: the driver to match against
  *
@@ -232,7 +230,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
                        break;
                }
 
-               INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
+               INIT_WORK(&evt->work, drv->event);
                queue_work(drv->event_queue, &evt->work);
                return 1;
        }
@@ -248,7 +246,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
 
 /**
  *     i2o_driver_notify_controller_add_all - Send notify of added controller
- *                                            to all I2O drivers
+ *     @c: newly added controller
  *
  *     Send notifications to all registered drivers that a new controller was
  *     added.
@@ -267,8 +265,8 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c)
 }
 
 /**
- *     i2o_driver_notify_controller_remove_all - Send notify of removed
- *                                               controller to all I2O drivers
+ *     i2o_driver_notify_controller_remove_all - Send notify of removed controller
+ *     @c: controller that is being removed
  *
  *     Send notifications to all registered drivers that a controller was
  *     removed.
@@ -287,8 +285,8 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c)
 }
 
 /**
- *     i2o_driver_notify_device_add_all - Send notify of added device to all
- *                                        I2O drivers
+ *     i2o_driver_notify_device_add_all - Send notify of added device
+ *     @i2o_dev: newly added I2O device
  *
  *     Send notifications to all registered drivers that a device was added.
  */
@@ -306,8 +304,8 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev)
 }
 
 /**
- *     i2o_driver_notify_device_remove_all - Send notify of removed device to
- *                                           all I2O drivers
+ *     i2o_driver_notify_device_remove_all - Send notify of removed device
+ *     @i2o_dev: device that is being removed
  *
  *     Send notifications to all registered drivers that a device was removed.
  */
@@ -362,7 +360,7 @@ int __init i2o_driver_init(void)
 /**
  *     i2o_driver_exit - clean up I2O drivers (OSMs)
  *
- *     Unregisters the I2O bus and free driver array.
+ *     Unregisters the I2O bus and frees driver array.
  */
 void __exit i2o_driver_exit(void)
 {
index a235064..902753b 100644 (file)
@@ -94,8 +94,8 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
 };
 
 /**
- *     i2o_exec_wait_free - Free a i2o_exec_wait struct
- *     @i2o_exec_wait: I2O wait data which should be cleaned up
+ *     i2o_exec_wait_free - Free an i2o_exec_wait struct
+ *     @wait: I2O wait data which should be cleaned up
  */
 static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
 {
@@ -105,7 +105,7 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
 /**
  *     i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
  *     @c: controller
- *     @m: message to post
+ *     @msg: message to post
  *     @timeout: time in seconds to wait
  *     @dma: i2o_dma struct of the DMA buffer to free on failure
  *
@@ -269,6 +269,7 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
 /**
  *     i2o_exec_show_vendor_id - Displays Vendor ID of controller
  *     @d: device of which the Vendor ID should be displayed
+ *     @attr: device_attribute to display
  *     @buf: buffer into which the Vendor ID should be printed
  *
  *     Returns number of bytes printed into buffer.
@@ -290,6 +291,7 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d,
 /**
  *     i2o_exec_show_product_id - Displays Product ID of controller
  *     @d: device of which the Product ID should be displayed
+ *     @attr: device_attribute to display
  *     @buf: buffer into which the Product ID should be printed
  *
  *     Returns number of bytes printed into buffer.
@@ -365,14 +367,16 @@ static int i2o_exec_remove(struct device *dev)
 
 /**
  *     i2o_exec_lct_modified - Called on LCT NOTIFY reply
- *     @c: I2O controller on which the LCT has modified
+ *     @work: work struct for a specific controller
  *
  *     This function handles asynchronus LCT NOTIFY replies. It parses the
  *     new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
  *     again, otherwise send LCT NOTIFY to get informed on next LCT change.
  */
-static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work)
+static void i2o_exec_lct_modified(struct work_struct *_work)
 {
+       struct i2o_exec_lct_notify_work *work =
+               container_of(_work, struct i2o_exec_lct_notify_work, work);
        u32 change_ind = 0;
        struct i2o_controller *c = work->c;
 
@@ -439,8 +443,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 
                work->c = c;
 
-               INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified,
-                         work);
+               INIT_WORK(&work->work, i2o_exec_lct_modified);
                queue_work(i2o_exec_driver.event_queue, &work->work);
                return 1;
        }
@@ -460,13 +463,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 
 /**
  *     i2o_exec_event - Event handling function
- *     @evt: Event which occurs
+ *     @work: Work item in occurring event
  *
  *     Handles events send by the Executive device. At the moment does not do
  *     anything useful.
  */
-static void i2o_exec_event(struct i2o_event *evt)
+static void i2o_exec_event(struct work_struct *work)
 {
+       struct i2o_event *evt = container_of(work, struct i2o_event, work);
+
        if (likely(evt->i2o_dev))
                osm_debug("Event received from device: %d\n",
                          evt->i2o_dev->lct_data.tid);
index eaba81b..da9859f 100644 (file)
@@ -259,7 +259,7 @@ static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
 /**
  *     i2o_block_device_power - Power management for device dev
  *     @dev: I2O device which should receive the power management request
- *     @operation: Operation which should be send
+ *     @op: Operation to send
  *
  *     Send a power management request to the device dev.
  *
@@ -315,7 +315,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void)
  *     i2o_block_request_free - Frees a I2O block request
  *     @ireq: I2O block request which should be freed
  *
- *     Fres the allocated memory (give it back to the request mempool).
+ *     Frees the allocated memory (give it back to the request mempool).
  */
 static inline void i2o_block_request_free(struct i2o_block_request *ireq)
 {
@@ -326,6 +326,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
  *     i2o_block_sglist_alloc - Allocate the SG list and map it
  *     @c: I2O controller to which the request belongs
  *     @ireq: I2O block request
+ *     @mptr: message body pointer
  *
  *     Builds the SG list and map it to be accessable by the controller.
  *
@@ -419,16 +420,18 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
 
 /**
  *     i2o_block_delayed_request_fn - delayed request queue function
- *     delayed_request: the delayed request with the queue to start
+ *     @work: the delayed request with the queue to start
  *
  *     If the request queue is stopped for a disk, and there is no open
  *     request, a new event is created, which calls this function to start
  *     the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never
  *     be started again.
  */
-static void i2o_block_delayed_request_fn(void *delayed_request)
+static void i2o_block_delayed_request_fn(struct work_struct *work)
 {
-       struct i2o_block_delayed_request *dreq = delayed_request;
+       struct i2o_block_delayed_request *dreq =
+               container_of(work, struct i2o_block_delayed_request,
+                            work.work);
        struct request_queue *q = dreq->queue;
        unsigned long flags;
 
@@ -488,7 +491,7 @@ static void i2o_block_end_request(struct request *req, int uptodate,
  *     i2o_block_reply - Block OSM reply handler.
  *     @c: I2O controller from which the message arrives
  *     @m: message id of reply
- *     qmsg: the actuall I2O message reply
+ *     @msg: the actual I2O message reply
  *
  *     This function gets all the message replies.
  *
@@ -538,8 +541,9 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
        return 1;
 };
 
-static void i2o_block_event(struct i2o_event *evt)
+static void i2o_block_event(struct work_struct *work)
 {
+       struct i2o_event *evt = container_of(work, struct i2o_event, work);
        osm_debug("event received\n");
        kfree(evt);
 };
@@ -599,6 +603,8 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls,
 
 /**
  *     i2o_block_open - Open the block device
+ *     @inode: inode for block device being opened
+ *     @file: file to open
  *
  *     Power up the device, mount and lock the media. This function is called,
  *     if the block device is opened for access.
@@ -626,6 +632,8 @@ static int i2o_block_open(struct inode *inode, struct file *file)
 
 /**
  *     i2o_block_release - Release the I2O block device
+ *     @inode: inode for block device being released
+ *     @file: file to close
  *
  *     Unlock and unmount the media, and power down the device. Gets called if
  *     the block device is closed.
@@ -672,6 +680,8 @@ static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 
 /**
  *     i2o_block_ioctl - Issue device specific ioctl calls.
+ *     @inode: inode for block device ioctl
+ *     @file: file for ioctl
  *     @cmd: ioctl command
  *     @arg: arg
  *
@@ -899,7 +909,7 @@ static int i2o_block_transfer(struct request *req)
 
 /**
  *     i2o_block_request_fn - request queue handling function
- *     q: request queue from which the request could be fetched
+ *     @q: request queue from which the request could be fetched
  *
  *     Takes the next request from the queue, transfers it and if no error
  *     occurs dequeue it from the queue. On arrival of the reply the message
@@ -938,8 +948,8 @@ static void i2o_block_request_fn(struct request_queue *q)
                                continue;
 
                        dreq->queue = q;
-                       INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
-                                 dreq);
+                       INIT_DELAYED_WORK(&dreq->work,
+                                         i2o_block_delayed_request_fn);
 
                        if (!queue_delayed_work(i2o_block_driver.event_queue,
                                                &dreq->work,
index 4fdaa5b..67f921b 100644 (file)
@@ -64,7 +64,7 @@
 
 /* I2O Block OSM mempool struct */
 struct i2o_block_mempool {
-       kmem_cache_t *slab;
+       struct kmem_cache *slab;
        mempool_t *pool;
 };
 
@@ -96,7 +96,7 @@ struct i2o_block_request {
 
 /* I2O Block device delayed request */
 struct i2o_block_delayed_request {
-       struct work_struct work;
+       struct delayed_work work;
        struct request_queue *queue;
 };
 
index 7d23e08..1de30d7 100644 (file)
@@ -265,7 +265,11 @@ static int i2o_cfg_swdl(unsigned long arg)
                return -ENOMEM;
        }
 
-       __copy_from_user(buffer.virt, kxfer.buf, fragsize);
+       if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) {
+               i2o_msg_nop(c, msg);
+               i2o_dma_free(&c->pdev->dev, &buffer);
+               return -EFAULT;
+       }
 
        msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
        msg->u.head[1] =
@@ -516,7 +520,6 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
        return 0;
 }
 
-#ifdef CONFIG_I2O_EXT_ADAPTEC
 #ifdef CONFIG_COMPAT
 static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
                              unsigned long arg)
@@ -759,6 +762,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
 
 #endif
 
+#ifdef CONFIG_I2O_EXT_ADAPTEC
 static int i2o_cfg_passthru(unsigned long arg)
 {
        struct i2o_cmd_passthru __user *cmd =
index 3d2e76e..a61cb17 100644 (file)
@@ -163,7 +163,7 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
  *     i2o_get_class_name -    do i2o class name lookup
  *     @class: class number
  *
- *     Return a descriptive string for an i2o class
+ *     Return a descriptive string for an i2o class.
  */
 static const char *i2o_get_class_name(int class)
 {
index 6ebf382..1045c8a 100644 (file)
@@ -220,7 +220,7 @@ static int i2o_scsi_probe(struct device *dev)
        u32 id = -1;
        u64 lun = -1;
        int channel = -1;
-       int i;
+       int i, rc;
 
        i2o_shost = i2o_scsi_get_host(c);
        if (!i2o_shost)
@@ -304,14 +304,20 @@ static int i2o_scsi_probe(struct device *dev)
                return PTR_ERR(scsi_dev);
        }
 
-       sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
-                         "scsi");
+       rc = sysfs_create_link(&i2o_dev->device.kobj,
+                              &scsi_dev->sdev_gendev.kobj, "scsi");
+       if (rc)
+               goto err;
 
        osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
                 i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
                 (long unsigned int)le64_to_cpu(lun));
 
        return 0;
+
+err:
+       scsi_remove_device(scsi_dev);
+       return rc;
 };
 
 static const char *i2o_scsi_info(struct Scsi_Host *SChost)
@@ -405,8 +411,7 @@ static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
 };
 
 /**
- *     i2o_scsi_notify_device_remove - Retrieve notifications of removed
- *                                     devices
+ *     i2o_scsi_notify_device_remove - Retrieve notifications of removed devices
  *     @i2o_dev: the I2O device which was removed
  *
  *     If a I2O device is removed, we catch the notification to remove the
@@ -426,8 +431,7 @@ static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
 };
 
 /**
- *     i2o_scsi_notify_controller_add - Retrieve notifications of added
- *                                      controllers
+ *     i2o_scsi_notify_controller_add - Retrieve notifications of added controllers
  *     @c: the controller which was added
  *
  *     If a I2O controller is added, we catch the notification to add a
@@ -457,8 +461,7 @@ static void i2o_scsi_notify_controller_add(struct i2o_controller *c)
 };
 
 /**
- *     i2o_scsi_notify_controller_remove - Retrieve notifications of removed
- *                                         controllers
+ *     i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers
  *     @c: the controller which was removed
  *
  *     If a I2O controller is removed, we catch the notification to remove the
@@ -745,7 +748,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
  *     @capacity: size in sectors
  *     @ip: geometry array
  *
- *     This is anyones guess quite frankly. We use the same rules everyone
+ *     This is anyone's guess quite frankly. We use the same rules everyone
  *     else appears to and hope. It seems to work.
  */
 
index 8287f95..3661e6e 100644 (file)
@@ -259,6 +259,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id)
 
 /**
  *     i2o_pci_irq_enable - Allocate interrupt for I2O controller
+ *     @c: i2o_controller that the request is for
  *
  *     Allocate an interrupt for the I2O controller, and activate interrupts
  *     on the I2O controller.
@@ -305,7 +306,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c)
 
 /**
  *     i2o_pci_probe - Probe the PCI device for an I2O controller
- *     @dev: PCI device to test
+ *     @pdev: PCI device to test
  *     @id: id which matched with the PCI device id table
  *
  *     Probe the PCI device for any device which is a memory of the
@@ -447,7 +448,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
 
 /**
  *     i2o_pci_remove - Removes a I2O controller from the system
- *     pdev: I2O controller which should be removed
+ *     @pdev: I2O controller which should be removed
  *
  *     Reset the I2O controller, disable interrupts and remove all allocated
  *     resources.
index 82938ad..ce1a481 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/string.h>
 #include <linux/input.h>
 #include <linux/device.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
 
index 1ba8754..2ab7add 100644 (file)
@@ -33,9 +33,10 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
        spin_unlock_irqrestore(&fm->lock, flags);
 }
 
-static void tifm_7xx1_remove_media(void *adapter)
+static void tifm_7xx1_remove_media(struct work_struct *work)
 {
-       struct tifm_adapter *fm = adapter;
+       struct tifm_adapter *fm =
+               container_of(work, struct tifm_adapter, media_remover);
        unsigned long flags;
        int cnt;
        struct tifm_dev *sock;
@@ -169,9 +170,10 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
        return base_addr + ((sock_num + 1) << 10);
 }
 
-static void tifm_7xx1_insert_media(void *adapter)
+static void tifm_7xx1_insert_media(struct work_struct *work)
 {
-       struct tifm_adapter *fm = adapter;
+       struct tifm_adapter *fm =
+               container_of(work, struct tifm_adapter, media_inserter);
        unsigned long flags;
        tifm_media_id media_id;
        char *card_name = "xx";
@@ -261,7 +263,7 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
        spin_unlock_irqrestore(&fm->lock, flags);
        flush_workqueue(fm->wq);
 
-       tifm_7xx1_remove_media(fm);
+       tifm_7xx1_remove_media(&fm->media_remover);
 
        pci_set_power_state(dev, PCI_D3hot);
         pci_disable_device(dev);
@@ -328,8 +330,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        if (!fm->sockets)
                goto err_out_free;
 
-       INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media, fm);
-       INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media, fm);
+       INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
+       INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
        fm->eject = tifm_7xx1_eject;
        pci_set_drvdata(dev, fm);
 
@@ -384,7 +386,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
 
        flush_workqueue(fm->wq);
 
-       tifm_7xx1_remove_media(fm);
+       tifm_7xx1_remove_media(&fm->media_remover);
 
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        free_irq(dev->irq, fm);
index ee32613..d61df5c 100644 (file)
@@ -219,8 +219,9 @@ static int tifm_device_remove(struct device *dev)
        struct tifm_driver *drv = fm_dev->drv;
 
        if (drv) {
-               if (drv->remove) drv->remove(fm_dev);
-               fm_dev->drv = 0;
+               if (drv->remove)
+                       drv->remove(fm_dev);
+               fm_dev->drv = NULL;
        }
 
        put_device(dev);
index f4f8cca..4224686 100644 (file)
@@ -91,11 +91,11 @@ config MMC_AU1X
 
          If unsure, say N.
 
-config MMC_AT91RM9200
-       tristate "AT91RM9200 SD/MMC Card Interface support"
-       depends on ARCH_AT91RM9200 && MMC
+config MMC_AT91
+       tristate "AT91 SD/MMC Card Interface support"
+       depends on ARCH_AT91 && MMC
        help
-         This selects the AT91RM9200 MCI controller.
+         This selects the AT91 MCI controller.
 
          If unsure, say N.
 
index acfd4de..83ffb93 100644 (file)
@@ -22,7 +22,7 @@ obj-$(CONFIG_MMC_SDHCI)               += sdhci.o
 obj-$(CONFIG_MMC_WBSD)         += wbsd.o
 obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)         += omap.o
-obj-$(CONFIG_MMC_AT91RM9200)   += at91_mci.o
+obj-$(CONFIG_MMC_AT91)         += at91_mci.o
 obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
 
 mmc_core-y := mmc.o mmc_sysfs.o
index 6495cd8..08a33c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *  linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
  *
  *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
  *
@@ -11,7 +11,7 @@
  */
 
 /*
-   This is the AT91RM9200 MCI driver that has been tested with both MMC cards
+   This is the AT91 MCI driver that has been tested with both MMC cards
    and SD-cards.  Boards that support write protect are now supported.
    The CCAT91SBC001 board does not support SD cards.
 
@@ -38,8 +38,8 @@
      controller to manage the transfers.
 
      A read is done from the controller directly to the scatterlist passed in from the request.
-     Due to a bug in the controller, when a read is completed, all the words are byte
-     swapped in the scatterlist buffers.
+     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
+     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
 
      The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
 
 #include <asm/irq.h>
 #include <asm/mach/mmc.h>
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
-#include <asm/arch/at91rm9200_mci.h>
-#include <asm/arch/at91rm9200_pdc.h>
+#include <asm/arch/at91_mci.h>
+#include <asm/arch/at91_pdc.h>
 
 #define DRIVER_NAME "at91_mci"
 
 #undef SUPPORT_4WIRE
 
-static struct clk *mci_clk;
+#define FL_SENT_COMMAND        (1 << 0)
+#define FL_SENT_STOP   (1 << 1)
 
-#define FL_SENT_COMMAND (1 << 0)
-#define FL_SENT_STOP (1 << 1)
+#define AT91_MCI_ERRORS        (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE       \
+               | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE               \
+               | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)                        
 
+#define at91_mci_read(host, reg)       __raw_readl((host)->baseaddr + (reg))
+#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
 
 
-/*
- * Read from a MCI register.
- */
-static inline unsigned long at91_mci_read(unsigned int reg)
-{
-       void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
-       return __raw_readl(mci_base + reg);
-}
-
-/*
- * Write to a MCI register.
- */
-static inline void at91_mci_write(unsigned int reg, unsigned long value)
-{
-        void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
-        __raw_writel(value, mci_base + reg);
-}
-
 /*
  * Low level type for this driver
  */
@@ -116,9 +101,14 @@ struct at91mci_host
        struct mmc_command *cmd;
        struct mmc_request *request;
 
+       void __iomem *baseaddr;
+       int irq;
+
        struct at91_mmc_data *board;
        int present;
 
+       struct clk *mci_clk;
+
        /*
         * Flag indicating when the command has been sent. This is used to
         * work out whether or not to send the stop
@@ -158,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
        for (i = 0; i < len; i++) {
                struct scatterlist *sg;
                int amount;
-               int index;
                unsigned int *sgbuffer;
 
                sg = &data->sg[i];
@@ -166,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
                sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
                amount = min(size, sg->length);
                size -= amount;
-               amount /= 4;
 
-               for (index = 0; index < amount; index++)
-                       *dmabuf++ = swab32(sgbuffer[index]);
+               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
+                       int index;
+
+                       for (index = 0; index < (amount / 4); index++)
+                               *dmabuf++ = swab32(sgbuffer[index]);
+               }
+               else
+                       memcpy(dmabuf, sgbuffer, amount);
 
                kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
 
@@ -217,13 +211,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
 
                /* Check to see if this needs filling */
                if (i == 0) {
-                       if (at91_mci_read(AT91_PDC_RCR) != 0) {
+                       if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
                                pr_debug("Transfer active in current\n");
                                continue;
                        }
                }
                else {
-                       if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+                       if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
                                pr_debug("Transfer active in next\n");
                                continue;
                        }
@@ -240,12 +234,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
                pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
 
                if (i == 0) {
-                       at91_mci_write(AT91_PDC_RPR, sg->dma_address);
-                       at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+                       at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
+                       at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
                }
                else {
-                       at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
-                       at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+                       at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
+                       at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
                }
        }
 
@@ -276,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
 
        while (host->in_use_index < host->transfer_index) {
                unsigned int *buffer;
-               int index;
-               int len;
 
                struct scatterlist *sg;
 
@@ -295,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
 
                data->bytes_xfered += sg->length;
 
-               len = sg->length / 4;
+               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
+                       int index;
 
-               for (index = 0; index < len; index++) {
-                       buffer[index] = swab32(buffer[index]);
+                       for (index = 0; index < (sg->length / 4); index++)
+                               buffer[index] = swab32(buffer[index]);
                }
+
                kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
                flush_dcache_page(sg->page);
        }
@@ -308,8 +302,8 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
        if (host->transfer_index < data->sg_len)
                at91mci_pre_dma_read(host);
        else {
-               at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
-               at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+               at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
        }
 
        pr_debug("post dma read done\n");
@@ -326,11 +320,11 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
        pr_debug("Handling the transmit\n");
 
        /* Disable the transfer */
-       at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 
        /* Now wait for cmd ready */
-       at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
-       at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
+       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
 
        cmd = host->cmd;
        if (!cmd) return;
@@ -344,21 +338,23 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
 /*
  * Enable the controller
  */
-static void at91_mci_enable(void)
+static void at91_mci_enable(struct at91mci_host *host)
 {
-       at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
-       at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
-       at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-       at91_mci_write(AT91_MCI_MR, 0x834A);
-       at91_mci_write(AT91_MCI_SDCR, 0x0);
+       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+       at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+       at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+
+       /* use Slot A or B (only one at same time) */
+       at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
 }
 
 /*
  * Disable the controller
  */
-static void at91_mci_disable(void)
+static void at91_mci_disable(struct at91mci_host *host)
 {
-       at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
 }
 
 /*
@@ -378,13 +374,13 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
 
        /* Not sure if this is needed */
 #if 0
-       if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+       if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
                pr_debug("Clearing timeout\n");
-               at91_mci_write(AT91_MCI_ARGR, 0);
-               at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
-               while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+               at91_mci_write(host, AT91_MCI_ARGR, 0);
+               at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+               while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
                        /* spin */
-                       pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+                       pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
                }
        }
 #endif
@@ -431,32 +427,32 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
        /*
         * Set the arguments and send the command
         */
-       pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
-               cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+       pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
+               cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
 
        if (!data) {
-               at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
-               at91_mci_write(AT91_PDC_RPR, 0);
-               at91_mci_write(AT91_PDC_RCR, 0);
-               at91_mci_write(AT91_PDC_RNPR, 0);
-               at91_mci_write(AT91_PDC_RNCR, 0);
-               at91_mci_write(AT91_PDC_TPR, 0);
-               at91_mci_write(AT91_PDC_TCR, 0);
-               at91_mci_write(AT91_PDC_TNPR, 0);
-               at91_mci_write(AT91_PDC_TNCR, 0);
-
-               at91_mci_write(AT91_MCI_ARGR, cmd->arg);
-               at91_mci_write(AT91_MCI_CMDR, cmdr);
+               at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+               at91_mci_write(host, AT91_PDC_RPR, 0);
+               at91_mci_write(host, AT91_PDC_RCR, 0);
+               at91_mci_write(host, AT91_PDC_RNPR, 0);
+               at91_mci_write(host, AT91_PDC_RNCR, 0);
+               at91_mci_write(host, AT91_PDC_TPR, 0);
+               at91_mci_write(host, AT91_PDC_TCR, 0);
+               at91_mci_write(host, AT91_PDC_TNPR, 0);
+               at91_mci_write(host, AT91_PDC_TNCR, 0);
+
+               at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+               at91_mci_write(host, AT91_MCI_CMDR, cmdr);
                return AT91_MCI_CMDRDY;
        }
 
-       mr = at91_mci_read(AT91_MCI_MR) & 0x7fff;       /* zero block length and PDC mode */
-       at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+       mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
+       at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
 
        /*
         * Disable the PDC controller
         */
-       at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 
        if (cmdr & AT91_MCI_TRCMD_START) {
                data->bytes_xfered = 0;
@@ -485,8 +481,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
 
                        pr_debug("Transmitting %d bytes\n", host->total_length);
 
-                       at91_mci_write(AT91_PDC_TPR, host->physical_address);
-                       at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+                       at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
+                       at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
                        ier = AT91_MCI_TXBUFE;
                }
        }
@@ -496,14 +492,14 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
         * the data sheet says
         */
 
-       at91_mci_write(AT91_MCI_ARGR, cmd->arg);
-       at91_mci_write(AT91_MCI_CMDR, cmdr);
+       at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+       at91_mci_write(host, AT91_MCI_CMDR, cmdr);
 
        if (cmdr & AT91_MCI_TRCMD_START) {
                if (cmdr & AT91_MCI_TRDIR)
-                       at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+                       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
                else
-                       at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+                       at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
        }
        return ier;
 }
@@ -520,7 +516,7 @@ static void at91mci_process_command(struct at91mci_host *host, struct mmc_comman
        pr_debug("setting ier to %08X\n", ier);
 
        /* Stop on errors or the required value */
-       at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
 }
 
 /*
@@ -548,19 +544,19 @@ static void at91mci_completed_command(struct at91mci_host *host)
        struct mmc_command *cmd = host->cmd;
        unsigned int status;
 
-       at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
 
-       cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
-       cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
-       cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
-       cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+       cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
+       cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
+       cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
+       cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
 
        if (host->buffer) {
                dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
                host->buffer = NULL;
        }
 
-       status = at91_mci_read(AT91_MCI_SR);
+       status = at91_mci_read(host, AT91_MCI_SR);
 
        pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
                 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
@@ -611,18 +607,18 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        int clkdiv;
        struct at91mci_host *host = mmc_priv(mmc);
-       unsigned long at91_master_clock = clk_get_rate(mci_clk);
+       unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
 
        host->bus_mode = ios->bus_mode;
 
        if (ios->clock == 0) {
                /* Disable the MCI controller */
-               at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
                clkdiv = 0;
        }
        else {
                /* Enable the MCI controller */
-               at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
 
                if ((at91_master_clock % (ios->clock * 2)) == 0)
                        clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
@@ -634,25 +630,25 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
        if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
                pr_debug("MMC: Setting controller bus width to 4\n");
-               at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
        }
        else {
                pr_debug("MMC: Setting controller bus width to 1\n");
-               at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
        }
 
        /* Set the clock divider */
-       at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+       at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
 
        /* maybe switch power to the card */
        if (host->board->vcc_pin) {
                switch (ios->power_mode) {
                        case MMC_POWER_OFF:
-                               at91_set_gpio_output(host->board->vcc_pin, 0);
+                               at91_set_gpio_value(host->board->vcc_pin, 0);
                                break;
                        case MMC_POWER_UP:
                        case MMC_POWER_ON:
-                               at91_set_gpio_output(host->board->vcc_pin, 1);
+                               at91_set_gpio_value(host->board->vcc_pin, 1);
                                break;
                }
        }
@@ -665,39 +661,40 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
 {
        struct at91mci_host *host = devid;
        int completed = 0;
+       unsigned int int_status, int_mask;
 
-       unsigned int int_status;
+       int_status = at91_mci_read(host, AT91_MCI_SR);
+       int_mask = at91_mci_read(host, AT91_MCI_IMR);
+       
+       pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
+               int_status & int_mask);
+       
+       int_status = int_status & int_mask;
 
-       int_status = at91_mci_read(AT91_MCI_SR);
-       pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
-               int_status & at91_mci_read(AT91_MCI_IMR));
-
-       if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+       if (int_status & AT91_MCI_ERRORS) {
                completed = 1;
+               
+               if (int_status & AT91_MCI_UNRE)
+                       pr_debug("MMC: Underrun error\n");
+               if (int_status & AT91_MCI_OVRE)
+                       pr_debug("MMC: Overrun error\n");
+               if (int_status & AT91_MCI_DTOE)
+                       pr_debug("MMC: Data timeout\n");
+               if (int_status & AT91_MCI_DCRCE)
+                       pr_debug("MMC: CRC error in data\n");
+               if (int_status & AT91_MCI_RTOE)
+                       pr_debug("MMC: Response timeout\n");
+               if (int_status & AT91_MCI_RENDE)
+                       pr_debug("MMC: Response end bit error\n");
+               if (int_status & AT91_MCI_RCRCE)
+                       pr_debug("MMC: Response CRC error\n");
+               if (int_status & AT91_MCI_RDIRE)
+                       pr_debug("MMC: Response direction error\n");
+               if (int_status & AT91_MCI_RINDE)
+                       pr_debug("MMC: Response index error\n");
+       } else {
+               /* Only continue processing if no errors */
 
-       int_status &= at91_mci_read(AT91_MCI_IMR);
-
-       if (int_status & AT91_MCI_UNRE)
-               pr_debug("MMC: Underrun error\n");
-       if (int_status & AT91_MCI_OVRE)
-               pr_debug("MMC: Overrun error\n");
-       if (int_status & AT91_MCI_DTOE)
-               pr_debug("MMC: Data timeout\n");
-       if (int_status & AT91_MCI_DCRCE)
-               pr_debug("MMC: CRC error in data\n");
-       if (int_status & AT91_MCI_RTOE)
-               pr_debug("MMC: Response timeout\n");
-       if (int_status & AT91_MCI_RENDE)
-               pr_debug("MMC: Response end bit error\n");
-       if (int_status & AT91_MCI_RCRCE)
-               pr_debug("MMC: Response CRC error\n");
-       if (int_status & AT91_MCI_RDIRE)
-               pr_debug("MMC: Response direction error\n");
-       if (int_status & AT91_MCI_RINDE)
-               pr_debug("MMC: Response index error\n");
-
-       /* Only continue processing if no errors */
-       if (!completed) {
                if (int_status & AT91_MCI_TXBUFE) {
                        pr_debug("TX buffer empty\n");
                        at91_mci_handle_transmitted(host);
@@ -705,12 +702,11 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
 
                if (int_status & AT91_MCI_RXBUFF) {
                        pr_debug("RX buffer full\n");
-                       at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
                }
 
-               if (int_status & AT91_MCI_ENDTX) {
+               if (int_status & AT91_MCI_ENDTX)
                        pr_debug("Transmit has ended\n");
-               }
 
                if (int_status & AT91_MCI_ENDRX) {
                        pr_debug("Receive has ended\n");
@@ -719,37 +715,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
 
                if (int_status & AT91_MCI_NOTBUSY) {
                        pr_debug("Card is ready\n");
-                       at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
                }
 
-               if (int_status & AT91_MCI_DTIP) {
+               if (int_status & AT91_MCI_DTIP)
                        pr_debug("Data transfer in progress\n");
-               }
 
-               if (int_status & AT91_MCI_BLKE) {
+               if (int_status & AT91_MCI_BLKE)
                        pr_debug("Block transfer has ended\n");
-               }
 
-               if (int_status & AT91_MCI_TXRDY) {
+               if (int_status & AT91_MCI_TXRDY)
                        pr_debug("Ready to transmit\n");
-               }
 
-               if (int_status & AT91_MCI_RXRDY) {
+               if (int_status & AT91_MCI_RXRDY)
                        pr_debug("Ready to receive\n");
-               }
 
                if (int_status & AT91_MCI_CMDRDY) {
                        pr_debug("Command ready\n");
                        completed = 1;
                }
        }
-       at91_mci_write(AT91_MCI_IDR, int_status);
 
        if (completed) {
                pr_debug("Completed command\n");
-               at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+               at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
                at91mci_completed_command(host);
-       }
+       } else
+               at91_mci_write(host, AT91_MCI_IDR, int_status);
 
        return IRQ_HANDLED;
 }
@@ -769,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
                        present ? "insert" : "remove");
                if (!present) {
                        pr_debug("****** Resetting SD-card bus width ******\n");
-                       at91_mci_write(AT91_MCI_SDCR, 0);
+                       at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
                }
                mmc_detect_change(host->mmc, msecs_to_jiffies(100));
        }
@@ -806,15 +798,22 @@ static int at91_mci_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
        struct at91mci_host *host;
+       struct resource *res;
        int ret;
 
        pr_debug("Probe MCI devices\n");
-       at91_mci_disable();
-       at91_mci_enable();
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENXIO;
+
+       if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
+               return -EBUSY;
 
        mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
        if (!mmc) {
                pr_debug("Failed to allocate mmc host\n");
+               release_mem_region(res->start, res->end - res->start + 1);
                return -ENOMEM;
        }
 
@@ -833,30 +832,51 @@ static int at91_mci_probe(struct platform_device *pdev)
 #ifdef SUPPORT_4WIRE
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 #else
-               printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+               printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
 #endif
        }
 
        /*
         * Get Clock
         */
-       mci_clk = clk_get(&pdev->dev, "mci_clk");
-       if (IS_ERR(mci_clk)) {
+       host->mci_clk = clk_get(&pdev->dev, "mci_clk");
+       if (IS_ERR(host->mci_clk)) {
                printk(KERN_ERR "AT91 MMC: no clock defined.\n");
                mmc_free_host(mmc);
+               release_mem_region(res->start, res->end - res->start + 1);
                return -ENODEV;
        }
-       clk_enable(mci_clk);                    /* Enable the peripheral clock */
+
+       /*
+        * Map I/O region
+        */
+       host->baseaddr = ioremap(res->start, res->end - res->start + 1);
+       if (!host->baseaddr) {
+               clk_put(host->mci_clk);
+               mmc_free_host(mmc);
+               release_mem_region(res->start, res->end - res->start + 1);
+               return -ENOMEM;
+       }
+
+       /*
+        * Reset hardware
+        */
+       clk_enable(host->mci_clk);              /* Enable the peripheral clock */
+       at91_mci_disable(host);
+       at91_mci_enable(host);
 
        /*
         * Allocate the MCI interrupt
         */
-       ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+       host->irq = platform_get_irq(pdev, 0);
+       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
        if (ret) {
-               printk(KERN_ERR "Failed to request MCI interrupt\n");
-               clk_disable(mci_clk);
-               clk_put(mci_clk);
+               printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
+               clk_disable(host->mci_clk);
+               clk_put(host->mci_clk);
                mmc_free_host(mmc);
+               iounmap(host->baseaddr);
+               release_mem_region(res->start, res->end - res->start + 1);
                return ret;
        }
 
@@ -879,10 +899,10 @@ static int at91_mci_probe(struct platform_device *pdev)
                ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
                                0, DRIVER_NAME, host);
                if (ret)
-                       printk(KERN_ERR "couldn't allocate MMC detect irq\n");
+                       printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
        }
 
-       pr_debug(KERN_INFO "Added MCI driver\n");
+       pr_debug("Added MCI driver\n");
 
        return 0;
 }
@@ -894,6 +914,7 @@ static int at91_mci_remove(struct platform_device *pdev)
 {
        struct mmc_host *mmc = platform_get_drvdata(pdev);
        struct at91mci_host *host;
+       struct resource *res;
 
        if (!mmc)
                return -1;
@@ -905,16 +926,19 @@ static int at91_mci_remove(struct platform_device *pdev)
                cancel_delayed_work(&host->mmc->detect);
        }
 
+       at91_mci_disable(host);
        mmc_remove_host(mmc);
-       at91_mci_disable();
-       free_irq(AT91RM9200_ID_MCI, host);
-       mmc_free_host(mmc);
+       free_irq(host->irq, host);
 
-       clk_disable(mci_clk);                           /* Disable the peripheral clock */
-       clk_put(mci_clk);
+       clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
+       clk_put(host->mci_clk);
 
-       platform_set_drvdata(pdev, NULL);
+       iounmap(host->baseaddr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, res->end - res->start + 1);
 
+       mmc_free_host(mmc);
+       platform_set_drvdata(pdev, NULL);
        pr_debug("MCI Removed\n");
 
        return 0;
index 447fba5..800527c 100644 (file)
@@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host)
        host->rx_chan = rxchan;
 }
 
-struct const mmc_host_ops au1xmmc_ops = {
+static const struct mmc_host_ops au1xmmc_ops = {
        .request        = au1xmmc_request,
        .set_ios        = au1xmmc_set_ios,
 };
index 9d19002..6f2a282 100644 (file)
@@ -1419,18 +1419,16 @@ static void mmc_setup(struct mmc_host *host)
  */
 void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
-       if (delay)
-               mmc_schedule_delayed_work(&host->detect, delay);
-       else
-               mmc_schedule_work(&host->detect);
+       mmc_schedule_delayed_work(&host->detect, delay);
 }
 
 EXPORT_SYMBOL(mmc_detect_change);
 
 
-static void mmc_rescan(void *data)
+static void mmc_rescan(struct work_struct *work)
 {
-       struct mmc_host *host = data;
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
        struct list_head *l, *n;
        unsigned char power_mode;
 
@@ -1513,7 +1511,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
                spin_lock_init(&host->lock);
                init_waitqueue_head(&host->wq);
                INIT_LIST_HEAD(&host->cards);
-               INIT_WORK(&host->detect, mmc_rescan, host);
+               INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 
                /*
                 * By default, hosts do not support SGIO or large requests.
@@ -1611,7 +1609,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
  */
 int mmc_resume_host(struct mmc_host *host)
 {
-       mmc_rescan(host);
+       mmc_rescan(&host->detect.work);
 
        return 0;
 }
index cd5e0ab..149affe 100644 (file)
@@ -20,6 +20,6 @@ void mmc_remove_host_sysfs(struct mmc_host *host);
 void mmc_free_host_sysfs(struct mmc_host *host);
 
 int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay);
+int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
 void mmc_flush_scheduled_work(void);
 #endif
index a17423a..3e35a43 100644 (file)
@@ -78,8 +78,10 @@ static int mmc_queue_thread(void *d)
                spin_unlock_irq(q->queue_lock);
 
                if (!req) {
-                       if (kthread_should_stop())
+                       if (kthread_should_stop()) {
+                               set_current_state(TASK_RUNNING);
                                break;
+                       }
                        up(&mq->thread_sem);
                        schedule();
                        down(&mq->thread_sem);
index ac53296..e334acd 100644 (file)
@@ -320,18 +320,10 @@ void mmc_free_host_sysfs(struct mmc_host *host)
 
 static struct workqueue_struct *workqueue;
 
-/*
- * Internal function. Schedule work in the MMC work queue.
- */
-int mmc_schedule_work(struct work_struct *work)
-{
-       return queue_work(workqueue, work);
-}
-
 /*
  * Internal function. Schedule delayed work in the MMC work queue.
  */
-int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay)
+int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
 {
        return queue_delayed_work(workqueue, work, delay);
 }
index 471e9f4..45a9283 100644 (file)
@@ -355,7 +355,7 @@ static int pxamci_get_ro(struct mmc_host *mmc)
        struct pxamci_host *host = mmc_priv(mmc);
 
        if (host->pdata && host->pdata->get_ro)
-               return host->pdata->get_ro(mmc->dev);
+               return host->pdata->get_ro(mmc_dev(mmc));
        /* Host doesn't support read only detection so assume writeable */
        return 0;
 }
@@ -383,7 +383,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                host->power_mode = ios->power_mode;
 
                if (host->pdata && host->pdata->setpower)
-                       host->pdata->setpower(mmc->dev, ios->vdd);
+                       host->pdata->setpower(mmc_dev(mmc), ios->vdd);
 
                if (ios->power_mode == MMC_POWER_ON)
                        host->cmdat |= CMDAT_INIT;
index cd98117..c2d13d7 100644 (file)
@@ -1170,8 +1170,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        }
 
        if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
-               printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
-               return -ENODEV;
+               printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. "
+                       "You may experience problems.\n");
        }
 
        if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
index 0fdc55b..f18ad99 100644 (file)
@@ -99,7 +99,7 @@ struct tifm_sd {
 
        struct mmc_request    *req;
        struct work_struct    cmd_handler;
-       struct work_struct    abort_handler;
+       struct delayed_work   abort_handler;
        wait_queue_head_t     can_eject;
 
        size_t                written_blocks;
@@ -387,7 +387,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
 
        writel(TIFM_FIFO_INT_SETALL,
                sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-       writel(long_log2(cmd->data->blksz) - 2,
+       writel(ilog2(cmd->data->blksz) - 2,
                        sock->addr + SOCK_FIFO_PAGE_SIZE);
        writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
        writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
@@ -496,9 +496,9 @@ err_out:
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd(void *data)
+static void tifm_sd_end_cmd(struct work_struct *work)
 {
-       struct tifm_sd *host = data;
+       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
        struct tifm_dev *sock = host->dev;
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        struct mmc_request *mrq;
@@ -608,9 +608,9 @@ err_out:
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd_nodma(void *data)
+static void tifm_sd_end_cmd_nodma(struct work_struct *work)
 {
-       struct tifm_sd *host = (struct tifm_sd*)data;
+       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
        struct tifm_dev *sock = host->dev;
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        struct mmc_request *mrq;
@@ -661,11 +661,14 @@ static void tifm_sd_end_cmd_nodma(void *data)
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_abort(void *data)
+static void tifm_sd_abort(struct work_struct *work)
 {
+       struct tifm_sd *host =
+               container_of(work, struct tifm_sd, abort_handler.work);
+
        printk(KERN_ERR DRIVER_NAME
                ": card failed to respond for a long period of time");
-       tifm_eject(((struct tifm_sd*)data)->dev);
+       tifm_eject(host->dev);
 }
 
 static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -762,9 +765,9 @@ static struct mmc_host_ops tifm_sd_ops = {
        .get_ro  = tifm_sd_ro
 };
 
-static void tifm_sd_register_host(void *data)
+static void tifm_sd_register_host(struct work_struct *work)
 {
-       struct tifm_sd *host = (struct tifm_sd*)data;
+       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
        struct tifm_dev *sock = host->dev;
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        unsigned long flags;
@@ -772,8 +775,7 @@ static void tifm_sd_register_host(void *data)
        spin_lock_irqsave(&sock->lock, flags);
        host->flags |= HOST_REG;
        PREPARE_WORK(&host->cmd_handler,
-                       no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
-                       data);
+                       no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd);
        spin_unlock_irqrestore(&sock->lock, flags);
        dev_dbg(&sock->dev, "adding host\n");
        mmc_add_host(mmc);
@@ -799,8 +801,8 @@ static int tifm_sd_probe(struct tifm_dev *sock)
        host->dev = sock;
        host->clk_div = 61;
        init_waitqueue_head(&host->can_eject);
-       INIT_WORK(&host->cmd_handler, tifm_sd_register_host, host);
-       INIT_WORK(&host->abort_handler, tifm_sd_abort, host);
+       INIT_WORK(&host->cmd_handler, tifm_sd_register_host);
+       INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort);
 
        tifm_set_drvdata(sock, mmc);
        sock->signal_irq = tifm_sd_signal_irq;
index ef4a731..334e078 100644 (file)
@@ -451,7 +451,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
                return -ENODEV;
        }
 
-       flash = kzalloc(sizeof *flash, SLAB_KERNEL);
+       flash = kzalloc(sizeof *flash, GFP_KERNEL);
        if (!flash)
                return -ENOMEM;
 
index 11d170a..06e3378 100644 (file)
@@ -922,7 +922,7 @@ int __init init_module(void)
  * and then free up the resources we took when the card was found.
  */
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        struct net_device *dev = dev_3c501;
        unregister_netdev(dev);
index a34b220..7e34c4f 100644 (file)
@@ -726,7 +726,7 @@ static void cleanup_card(struct net_device *dev)
                iounmap(ei_status.mem);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index 458cb9c..702bfb2 100644 (file)
@@ -1670,7 +1670,7 @@ int __init init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index aa43563..54e1d5a 100644 (file)
@@ -940,7 +940,7 @@ int __init init_module(void)
        return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        struct net_device *dev = dev_3c507;
index 9184946..17d61eb 100644 (file)
@@ -1302,7 +1302,7 @@ int __init init_module(void)
        } else return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
        for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
index f4aca53..6c7437e 100644 (file)
@@ -1659,7 +1659,7 @@ int __init init_module(void)
  *     transmit operations are allowed to start scribbling into memory.
  */
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(this_device);
        cleanup_card(this_device);
index 7733697..2d5ba07 100644 (file)
@@ -500,7 +500,7 @@ int lance_open (struct net_device *dev)
        int res;
 
         /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
-        if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev))
+        if (request_irq(lp->irq, lance_interrupt, SA_SHIRQ, lp->name, dev))
                 return -EAGAIN;
 
         res = lance_reset(dev);
index d02ed51..931028f 100644 (file)
@@ -594,7 +594,7 @@ struct rtl8139_private {
        u32 rx_config;
        struct rtl_extra_stats xstats;
 
-       struct work_struct thread;
+       struct delayed_work thread;
 
        struct mii_if_info mii;
        unsigned int regs_len;
@@ -636,8 +636,8 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
 static void rtl8139_set_rx_mode (struct net_device *dev);
 static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
-static void rtl8139_thread (void *_data);
-static void rtl8139_tx_timeout_task(void *_data);
+static void rtl8139_thread (struct work_struct *work);
+static void rtl8139_tx_timeout_task(struct work_struct *work);
 static const struct ethtool_ops rtl8139_ethtool_ops;
 
 /* write MMIO register, with flush */
@@ -1010,7 +1010,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
                (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));
        spin_lock_init (&tp->lock);
        spin_lock_init (&tp->rx_lock);
-       INIT_WORK(&tp->thread, rtl8139_thread, dev);
+       INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
        tp->mii.dev = dev;
        tp->mii.mdio_read = mdio_read;
        tp->mii.mdio_write = mdio_write;
@@ -1596,15 +1596,16 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
                 RTL_R8 (Config1));
 }
 
-static void rtl8139_thread (void *_data)
+static void rtl8139_thread (struct work_struct *work)
 {
-       struct net_device *dev = _data;
-       struct rtl8139_private *tp = netdev_priv(dev);
+       struct rtl8139_private *tp =
+               container_of(work, struct rtl8139_private, thread.work);
+       struct net_device *dev = tp->mii.dev;
        unsigned long thr_delay = next_tick;
 
        if (tp->watchdog_fired) {
                tp->watchdog_fired = 0;
-               rtl8139_tx_timeout_task(_data);
+               rtl8139_tx_timeout_task(work);
        } else if (rtnl_trylock()) {
                rtl8139_thread_iter (dev, tp, tp->mmio_addr);
                rtnl_unlock ();
@@ -1646,10 +1647,11 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
        /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
-static void rtl8139_tx_timeout_task (void *_data)
+static void rtl8139_tx_timeout_task (struct work_struct *work)
 {
-       struct net_device *dev = _data;
-       struct rtl8139_private *tp = netdev_priv(dev);
+       struct rtl8139_private *tp =
+               container_of(work, struct rtl8139_private, thread.work);
+       struct net_device *dev = tp->mii.dev;
        void __iomem *ioaddr = tp->mmio_addr;
        int i;
        u8 tmp8;
@@ -1695,7 +1697,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
        struct rtl8139_private *tp = netdev_priv(dev);
 
        if (!tp->have_thread) {
-               INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+               INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task);
                schedule_delayed_work(&tp->thread, next_tick);
        } else
                tp->watchdog_fired = 1;
index 9de0eed..8aa8dd0 100644 (file)
@@ -2384,6 +2384,14 @@ config CHELSIO_T1_1G
           Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
           are using only 10G cards say 'N' here.
 
+config CHELSIO_T1_NAPI
+       bool "Use Rx Polling (NAPI)"
+       depends on CHELSIO_T1
+       default y
+       help
+         NAPI is a driver API designed to reduce CPU and interrupt load
+         when the driver is receiving lots of packets from the card.
+
 config EHEA
        tristate "eHEA Ethernet support"
        depends on IBMEBUS
index 0dca8bb..c01f87f 100644 (file)
@@ -405,7 +405,7 @@ static void cleanup_card(struct net_device *dev)
        iounmap(ei_status.mem);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index 9164d8c..9541911 100644 (file)
@@ -311,9 +311,10 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
 #endif
 
     dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
 
     /* Install the Interrupt handler */
-    i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
+    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
     if (i) return i;
 
     for(i = 0; i < ETHER_ADDR_LEN; i++) {
@@ -568,7 +569,7 @@ static irqreturn_t apne_interrupt(int irq, void *dev_id)
 #ifdef MODULE
 static struct net_device *apne_dev;
 
-int init_module(void)
+int __init init_module(void)
 {
        apne_dev = apne_probe(-1);
        if (IS_ERR(apne_dev))
@@ -576,7 +577,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(apne_dev);
 
index cc1a27e..dba5e51 100644 (file)
@@ -1041,7 +1041,7 @@ int __init init_module(void)
         return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(cops_dev);
        cleanup_card(cops_dev);
index b54b857..fada15d 100644 (file)
@@ -41,9 +41,6 @@
 #define DRV_NAME       "at91_ether"
 #define DRV_VERSION    "1.0"
 
-static struct net_device *at91_dev;
-
-static struct timer_list check_timer;
 #define LINK_POLL_INTERVAL     (HZ)
 
 /* ..................................................................... */
@@ -146,7 +143,7 @@ static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int
  */
 static void update_linkspeed(struct net_device *dev, int silent)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned int bmsr, bmcr, lpa, mac_cfg;
        unsigned int speed, duplex;
 
@@ -199,7 +196,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
 static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned int phy;
 
        /*
@@ -242,7 +239,7 @@ done:
  */
 static void enable_phyirq(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned int dsintr, irq_number;
        int status;
 
@@ -252,8 +249,7 @@ static void enable_phyirq(struct net_device *dev)
                 * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
                 * or board does not have it connected.
                 */
-               check_timer.expires = jiffies + LINK_POLL_INTERVAL;
-               add_timer(&check_timer);
+               mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
                return;
        }
 
@@ -294,13 +290,13 @@ static void enable_phyirq(struct net_device *dev)
  */
 static void disable_phyirq(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned int dsintr;
        unsigned int irq_number;
 
        irq_number = lp->board_data.phy_irq_pin;
        if (!irq_number) {
-               del_timer_sync(&check_timer);
+               del_timer_sync(&lp->check_timer);
                return;
        }
 
@@ -340,7 +336,7 @@ static void disable_phyirq(struct net_device *dev)
 #if 0
 static void reset_phy(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned int bmcr;
 
        spin_lock_irq(&lp->lock);
@@ -362,13 +358,13 @@ static void reset_phy(struct net_device *dev)
 static void at91ether_check_link(unsigned long dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
+       struct at91_private *lp = netdev_priv(dev);
 
        enable_mdi();
        update_linkspeed(dev, 1);
        disable_mdi();
 
-       check_timer.expires = jiffies + LINK_POLL_INTERVAL;
-       add_timer(&check_timer);
+       mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
 }
 
 /* ......................... ADDRESS MANAGEMENT ........................ */
@@ -590,7 +586,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 
 static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        int ret;
 
        spin_lock_irq(&lp->lock);
@@ -611,7 +607,7 @@ static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cm
 
 static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        int ret;
 
        spin_lock_irq(&lp->lock);
@@ -627,7 +623,7 @@ static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cm
 
 static int at91ether_nwayreset(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        int ret;
 
        spin_lock_irq(&lp->lock);
@@ -658,7 +654,7 @@ static const struct ethtool_ops at91ether_ethtool_ops = {
 
 static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        int res;
 
        if (!netif_running(dev))
@@ -680,7 +676,7 @@ static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  */
 static void at91ether_start(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        struct recv_desc_bufs *dlist, *dlist_phys;
        int i;
        unsigned long ctl;
@@ -712,7 +708,7 @@ static void at91ether_start(struct net_device *dev)
  */
 static int at91ether_open(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned long ctl;
 
        if (!is_valid_ether_addr(dev->dev_addr))
@@ -752,7 +748,7 @@ static int at91ether_open(struct net_device *dev)
  */
 static int at91ether_close(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned long ctl;
 
        /* Disable Receiver and Transmitter */
@@ -779,7 +775,7 @@ static int at91ether_close(struct net_device *dev)
  */
 static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
 
        if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
                netif_stop_queue(dev);
@@ -811,7 +807,7 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
  */
 static struct net_device_stats *at91ether_stats(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        int ale, lenerr, seqe, lcol, ecol;
 
        if (netif_running(dev)) {
@@ -847,7 +843,7 @@ static struct net_device_stats *at91ether_stats(struct net_device *dev)
  */
 static void at91ether_rx(struct net_device *dev)
 {
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        struct recv_desc_bufs *dlist;
        unsigned char *p_recv;
        struct sk_buff *skb;
@@ -857,14 +853,13 @@ static void at91ether_rx(struct net_device *dev)
        while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
                p_recv = dlist->recv_buf[lp->rxBuffIndex];
                pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;      /* Length of frame including FCS */
-               skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
+               skb = dev_alloc_skb(pktlen + 2);
                if (skb != NULL) {
                        skb_reserve(skb, 2);
                        memcpy(skb_put(skb, pktlen), p_recv, pktlen);
 
                        skb->dev = dev;
                        skb->protocol = eth_type_trans(skb, dev);
-                       skb->len = pktlen;
                        dev->last_rx = jiffies;
                        lp->stats.rx_bytes += pktlen;
                        netif_rx(skb);
@@ -891,7 +886,7 @@ static void at91ether_rx(struct net_device *dev)
 static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = (struct at91_private *) dev->priv;
+       struct at91_private *lp = netdev_priv(dev);
        unsigned long intstatus, ctl;
 
        /* MAC Interrupt Status register indicates what interrupts are pending.
@@ -927,6 +922,17 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void at91ether_poll_controller(struct net_device *dev)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       at91ether_interrupt(dev->irq, dev);
+       local_irq_restore(flags);
+}
+#endif
+
 /*
  * Initialize the ethernet interface
  */
@@ -939,9 +945,6 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
        unsigned int val;
        int res;
 
-       if (at91_dev)                   /* already initialized */
-               return 0;
-
        dev = alloc_etherdev(sizeof(struct at91_private));
        if (!dev)
                return -ENOMEM;
@@ -957,7 +960,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
        }
 
        /* Allocate memory for DMA Receive descriptors */
-       lp = (struct at91_private *)dev->priv;
+       lp = netdev_priv(dev);
        lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
        if (lp->dlist == NULL) {
                free_irq(dev->irq, dev);
@@ -979,6 +982,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
        dev->set_mac_address = set_mac_address;
        dev->ethtool_ops = &at91ether_ethtool_ops;
        dev->do_ioctl = at91ether_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = at91ether_poll_controller;
+#endif
 
        SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -1024,7 +1030,6 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
                dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
                return res;
        }
-       at91_dev = dev;
 
        /* Determine current link speed */
        spin_lock_irq(&lp->lock);
@@ -1036,9 +1041,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
 
        /* If board has no PHY IRQ, use a timer to poll the PHY */
        if (!lp->board_data.phy_irq_pin) {
-               init_timer(&check_timer);
-               check_timer.data = (unsigned long)dev;
-               check_timer.function = at91ether_check_link;
+               init_timer(&lp->check_timer);
+               lp->check_timer.data = (unsigned long)dev;
+               lp->check_timer.function = at91ether_check_link;
        }
 
        /* Display ethernet banner */
@@ -1115,15 +1120,16 @@ static int __init at91ether_probe(struct platform_device *pdev)
 
 static int __devexit at91ether_remove(struct platform_device *pdev)
 {
-       struct at91_private *lp = (struct at91_private *) at91_dev->priv;
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct at91_private *lp = netdev_priv(dev);
 
-       unregister_netdev(at91_dev);
-       free_irq(at91_dev->irq, at91_dev);
+       unregister_netdev(dev);
+       free_irq(dev->irq, dev);
        dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
        clk_put(lp->ether_clk);
 
-       free_netdev(at91_dev);
-       at91_dev = NULL;
+       platform_set_drvdata(pdev, NULL);
+       free_netdev(dev);
        return 0;
 }
 
@@ -1131,8 +1137,8 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
 
 static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
-       struct at91_private *lp = (struct at91_private *) at91_dev->priv;
        struct net_device *net_dev = platform_get_drvdata(pdev);
+       struct at91_private *lp = netdev_priv(net_dev);
        int phy_irq = lp->board_data.phy_irq_pin;
 
        if (netif_running(net_dev)) {
@@ -1149,8 +1155,8 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 static int at91ether_resume(struct platform_device *pdev)
 {
-       struct at91_private *lp = (struct at91_private *) at91_dev->priv;
        struct net_device *net_dev = platform_get_drvdata(pdev);
+       struct at91_private *lp = netdev_priv(net_dev);
        int phy_irq = lp->board_data.phy_irq_pin;
 
        if (netif_running(net_dev)) {
index d1e72e0..b6b665d 100644 (file)
@@ -87,6 +87,7 @@ struct at91_private
        spinlock_t lock;                        /* lock for MDI interface */
        short phy_media;                        /* media interface type */
        unsigned short phy_address;             /* 5-bit MDI address of PHY (0..31) */
+       struct timer_list check_timer;          /* Poll link status */
 
        /* Transmit */
        struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
index f3478a3..d6da3ce 100644 (file)
@@ -254,7 +254,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
        } while (thislen);
 }
 
-static int __init
+static int __devinit
 ether1_ramtest(struct net_device *dev, unsigned char byte)
 {
        unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
@@ -308,7 +308,7 @@ ether1_reset (struct net_device *dev)
        return BUS_16;
 }
 
-static int __init
+static int __devinit
 ether1_init_2(struct net_device *dev)
 {
        int i;
@@ -986,7 +986,7 @@ ether1_setmulticastlist (struct net_device *dev)
 
 /* ------------------------------------------------------------------------- */
 
-static void __init ether1_banner(void)
+static void __devinit ether1_banner(void)
 {
        static unsigned int version_printed = 0;
 
index 84686c8..4fc2347 100644 (file)
@@ -198,7 +198,7 @@ static inline void ether3_ledon(struct net_device *dev)
  * Read the ethernet address string from the on board rom.
  * This is an ascii string!!!
  */
-static int __init
+static int __devinit
 ether3_addr(char *addr, struct expansion_card *ec)
 {
        struct in_chunk_dir cd;
@@ -223,7 +223,7 @@ ether3_addr(char *addr, struct expansion_card *ec)
 
 /* --------------------------------------------------------------------------- */
 
-static int __init
+static int __devinit
 ether3_ramtest(struct net_device *dev, unsigned char byte)
 {
        unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
@@ -272,7 +272,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte)
 
 /* ------------------------------------------------------------------------------- */
 
-static int __init ether3_init_2(struct net_device *dev)
+static int __devinit ether3_init_2(struct net_device *dev)
 {
        int i;
 
@@ -765,7 +765,7 @@ static void ether3_tx(struct net_device *dev)
        }
 }
 
-static void __init ether3_banner(void)
+static void __devinit ether3_banner(void)
 {
        static unsigned version_printed = 0;
 
index 8620a5b..56ae8ba 100644 (file)
@@ -908,7 +908,7 @@ int __init init_module(void)
        return 0;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        unregister_netdev(dev_at1700);
index d79489e..7e37ac8 100644 (file)
@@ -1179,7 +1179,7 @@ static int lance_set_mac_address( struct net_device *dev, void *addr )
 #ifdef MODULE
 static struct net_device *atarilance_dev;
 
-int init_module(void)
+int __init init_module(void)
 {
        atarilance_dev = atarilance_probe(-1);
        if (IS_ERR(atarilance_dev))
@@ -1187,7 +1187,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(atarilance_dev);
        free_irq(atarilance_dev->irq, atarilance_dev);
index fc2f1d1..7d824cf 100644 (file)
@@ -2510,7 +2510,7 @@ bnx2_init_cpus(struct bnx2 *bp)
        if (CHIP_NUM(bp) == CHIP_NUM_5709) {
                fw = &bnx2_cp_fw_09;
 
-               load_cpu_fw(bp, &cpu_reg, fw);
+               rc = load_cpu_fw(bp, &cpu_reg, fw);
                if (rc)
                        goto init_cpu_err;
        }
@@ -4411,9 +4411,9 @@ bnx2_open(struct net_device *dev)
 }
 
 static void
-bnx2_reset_task(void *data)
+bnx2_reset_task(struct work_struct *work)
 {
-       struct bnx2 *bp = data;
+       struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
 
        if (!netif_running(bp->dev))
                return;
@@ -5702,7 +5702,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->pdev = pdev;
 
        spin_lock_init(&bp->phy_lock);
-       INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
+       INIT_WORK(&bp->reset_task, bnx2_reset_task);
 
        dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
        mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1);
index 488d8ed..6482aed 100644 (file)
@@ -3684,7 +3684,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
                        mii->val_out = 0;
                        read_lock_bh(&bond->lock);
                        read_lock(&bond->curr_slave_lock);
-                       if (bond->curr_active_slave) {
+                       if (netif_carrier_ok(bond->dev)) {
                                mii->val_out = BMSR_LSTATUS;
                        }
                        read_unlock(&bond->curr_slave_lock);
index fd2cc13..c812648 100644 (file)
@@ -4066,9 +4066,9 @@ static int cas_alloc_rxds(struct cas *cp)
        return 0;
 }
 
-static void cas_reset_task(void *data)
+static void cas_reset_task(struct work_struct *work)
 {
-       struct cas *cp = (struct cas *) data;
+       struct cas *cp = container_of(work, struct cas, reset_task);
 #if 0
        int pending = atomic_read(&cp->reset_task_pending);
 #else
@@ -5006,7 +5006,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
        atomic_set(&cp->reset_task_pending_spare, 0);
        atomic_set(&cp->reset_task_pending_mtu, 0);
 #endif
-       INIT_WORK(&cp->reset_task, cas_reset_task, cp);
+       INIT_WORK(&cp->reset_task, cas_reset_task);
 
        /* Default link parameters */
        if (link_mode >= 0 && link_mode <= 6)
index b265941..74758d2 100644 (file)
@@ -279,7 +279,7 @@ struct adapter {
        struct petp   *tp;
 
        struct port_info port[MAX_NPORTS];
-       struct work_struct stats_update_task;
+       struct delayed_work stats_update_task;
        struct timer_list stats_update_timer;
 
        spinlock_t tpi_lock;
index 60901f2..cf91434 100644 (file)
@@ -91,7 +91,7 @@ struct cphy {
        int state;      /* Link status state machine */
        adapter_t *adapter;                  /* associated adapter */
 
-       struct work_struct phy_update;
+       struct delayed_work phy_update;
 
        u16 bmsr;
        int count;
index 53bec67..fd5d821 100644 (file)
@@ -220,9 +220,8 @@ static int cxgb_up(struct adapter *adapter)
 
        t1_interrupts_clear(adapter);
 
-       adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0;
-       err = request_irq(adapter->pdev->irq,
-                         t1_select_intr_handler(adapter),
+       adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
+       err = request_irq(adapter->pdev->irq, t1_interrupt,
                          adapter->params.has_msi ? 0 : IRQF_SHARED,
                          adapter->name, adapter);
        if (err) {
@@ -764,18 +763,7 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
 {
        struct adapter *adapter = dev->priv;
 
-       /*
-        * If RX coalescing is requested we use NAPI, otherwise interrupts.
-        * This choice can be made only when all ports and the TOE are off.
-        */
-       if (adapter->open_device_map == 0)
-               adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
-
-       if (adapter->params.sge.polling) {
-               adapter->params.sge.rx_coalesce_usecs = 0;
-       } else {
-               adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
-       }
+       adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
        adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
        adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
        t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
@@ -944,7 +932,7 @@ static void t1_netpoll(struct net_device *dev)
        struct adapter *adapter = dev->priv;
 
        local_irq_save(flags);
-       t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
+       t1_interrupt(adapter->pdev->irq, adapter);
        local_irq_restore(flags);
 }
 #endif
@@ -953,10 +941,11 @@ static void t1_netpoll(struct net_device *dev)
  * Periodic accumulation of MAC statistics.  This is used only if the MAC
  * does not have any other way to prevent stats counter overflow.
  */
-static void mac_stats_task(void *data)
+static void mac_stats_task(struct work_struct *work)
 {
        int i;
-       struct adapter *adapter = data;
+       struct adapter *adapter =
+               container_of(work, struct adapter, stats_update_task.work);
 
        for_each_port(adapter, i) {
                struct port_info *p = &adapter->port[i];
@@ -977,9 +966,10 @@ static void mac_stats_task(void *data)
 /*
  * Processes elmer0 external interrupts in process context.
  */
-static void ext_intr_task(void *data)
+static void ext_intr_task(struct work_struct *work)
 {
-       struct adapter *adapter = data;
+       struct adapter *adapter =
+               container_of(work, struct adapter, ext_intr_handler_task);
 
        t1_elmer0_ext_intr_handler(adapter);
 
@@ -1113,9 +1103,9 @@ static int __devinit init_one(struct pci_dev *pdev,
                        spin_lock_init(&adapter->mac_lock);
 
                        INIT_WORK(&adapter->ext_intr_handler_task,
-                                 ext_intr_task, adapter);
-                       INIT_WORK(&adapter->stats_update_task, mac_stats_task,
-                                 adapter);
+                                 ext_intr_task);
+                       INIT_DELAYED_WORK(&adapter->stats_update_task,
+                                         mac_stats_task);
 
                        pci_set_drvdata(pdev, netdev);
                }
@@ -1163,7 +1153,10 @@ static int __devinit init_one(struct pci_dev *pdev,
 #ifdef CONFIG_NET_POLL_CONTROLLER
                netdev->poll_controller = t1_netpoll;
 #endif
+#ifdef CONFIG_CHELSIO_T1_NAPI
                netdev->weight = 64;
+               netdev->poll = t1_poll;
+#endif
 
                SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
        }
index 0b90014..c7731b6 100644 (file)
@@ -93,9 +93,11 @@ static int my3126_interrupt_handler(struct cphy *cphy)
        return cphy_cause_link_change;
 }
 
-static void my3216_poll(void *arg)
+static void my3216_poll(struct work_struct *work)
 {
-       my3126_interrupt_handler(arg);
+       struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
+
+       my3126_interrupt_handler(cphy);
 }
 
 static int my3126_set_loopback(struct cphy *cphy, int on)
@@ -171,7 +173,7 @@ static struct cphy *my3126_phy_create(adapter_t *adapter,
        if (cphy)
                cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
 
-       INIT_WORK(&cphy->phy_update, my3216_poll, cphy);
+       INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
        cphy->bmsr = 0;
 
        return (cphy);
index 0ca8d87..659cb22 100644 (file)
@@ -1413,16 +1413,20 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
 
        if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
                st->vlan_xtract++;
-               if (adapter->params.sge.polling)
+#ifdef CONFIG_CHELSIO_T1_NAPI
                        vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
                                                 ntohs(p->vlan));
-               else
+#else
                        vlan_hwaccel_rx(skb, adapter->vlan_grp,
                                        ntohs(p->vlan));
-       } else if (adapter->params.sge.polling)
+#endif
+       } else {
+#ifdef CONFIG_CHELSIO_T1_NAPI
                netif_receive_skb(skb);
-       else
+#else
                netif_rx(skb);
+#endif
+       }
        return 0;
 }
 
@@ -1572,6 +1576,7 @@ static int process_responses(struct adapter *adapter, int budget)
        return budget;
 }
 
+#ifdef CONFIG_CHELSIO_T1_NAPI
 /*
  * A simpler version of process_responses() that handles only pure (i.e.,
  * non data-carrying) responses.  Such respones are too light-weight to justify
@@ -1619,92 +1624,76 @@ static int process_pure_responses(struct adapter *adapter, struct respQ_e *e)
  * or protection from interrupts as data interrupts are off at this point and
  * other adapter interrupts do not interfere.
  */
-static int t1_poll(struct net_device *dev, int *budget)
+int t1_poll(struct net_device *dev, int *budget)
 {
        struct adapter *adapter = dev->priv;
        int effective_budget = min(*budget, dev->quota);
-
        int work_done = process_responses(adapter, effective_budget);
+
        *budget -= work_done;
        dev->quota -= work_done;
 
        if (work_done >= effective_budget)
                return 1;
 
+       spin_lock_irq(&adapter->async_lock);
        __netif_rx_complete(dev);
-
-       /*
-        * Because we don't atomically flush the following write it is
-        * possible that in very rare cases it can reach the device in a way
-        * that races with a new response being written plus an error interrupt
-        * causing the NAPI interrupt handler below to return unhandled status
-        * to the OS.  To protect against this would require flushing the write
-        * and doing both the write and the flush with interrupts off.  Way too
-        * expensive and unjustifiable given the rarity of the race.
-        */
        writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
-       return 0;
-}
+       writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+              adapter->regs + A_PL_ENABLE);
+       spin_unlock_irq(&adapter->async_lock);
 
-/*
- * Returns true if the device is already scheduled for polling.
- */
-static inline int napi_is_scheduled(struct net_device *dev)
-{
-       return test_bit(__LINK_STATE_RX_SCHED, &dev->state);
+       return 0;
 }
 
 /*
  * NAPI version of the main interrupt handler.
  */
-static irqreturn_t t1_interrupt_napi(int irq, void *data)
+irqreturn_t t1_interrupt(int irq, void *data)
 {
-       int handled;
        struct adapter *adapter = data;
+       struct net_device *dev = adapter->sge->netdev;
        struct sge *sge = adapter->sge;
-       struct respQ *q = &adapter->sge->respQ;
+       u32 cause;
+       int handled = 0;
 
-       /*
-        * Clear the SGE_DATA interrupt first thing.  Normally the NAPI
-        * handler has control of the response queue and the interrupt handler
-        * can look at the queue reliably only once it knows NAPI is off.
-        * We can't wait that long to clear the SGE_DATA interrupt because we
-        * could race with t1_poll rearming the SGE interrupt, so we need to
-        * clear the interrupt speculatively and really early on.
-        */
-       writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+       cause = readl(adapter->regs + A_PL_CAUSE);
+       if (cause == 0 || cause == ~0)
+               return IRQ_NONE;
 
        spin_lock(&adapter->async_lock);
-       if (!napi_is_scheduled(sge->netdev)) {
+       if (cause & F_PL_INTR_SGE_DATA) {
+               struct respQ *q = &adapter->sge->respQ;
                struct respQ_e *e = &q->entries[q->cidx];
 
-               if (e->GenerationBit == q->genbit) {
-                       if (e->DataValid ||
-                           process_pure_responses(adapter, e)) {
-                               if (likely(__netif_rx_schedule_prep(sge->netdev)))
-                                       __netif_rx_schedule(sge->netdev);
-                               else if (net_ratelimit())
-                                       printk(KERN_INFO
-                                              "NAPI schedule failure!\n");
-                       } else
-                               writel(q->cidx, adapter->regs + A_SG_SLEEPING);
-
-                       handled = 1;
-                       goto unlock;
-               } else
-                       writel(q->cidx, adapter->regs + A_SG_SLEEPING);
-       }  else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) {
-               printk(KERN_ERR "data interrupt while NAPI running\n");
-       }
-       
-       handled = t1_slow_intr_handler(adapter);
+               handled = 1;
+               writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+               if (e->GenerationBit == q->genbit &&
+                   __netif_rx_schedule_prep(dev)) {
+                       if (e->DataValid || process_pure_responses(adapter, e)) {
+                               /* mask off data IRQ */
+                               writel(adapter->slow_intr_mask,
+                                      adapter->regs + A_PL_ENABLE);
+                               __netif_rx_schedule(sge->netdev);
+                               goto unlock;
+                       }
+                       /* no data, no NAPI needed */
+                       netif_poll_enable(dev);
+
+               }
+               writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+       } else
+               handled = t1_slow_intr_handler(adapter);
+
        if (!handled)
                sge->stats.unhandled_irqs++;
- unlock:
+unlock:
        spin_unlock(&adapter->async_lock);
        return IRQ_RETVAL(handled != 0);
 }
 
+#else
 /*
  * Main interrupt handler, optimized assuming that we took a 'DATA'
  * interrupt.
@@ -1720,7 +1709,7 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data)
  * 5. If we took an interrupt, but no valid respQ descriptors was found we
  *      let the slow_intr_handler run and do error handling.
  */
-static irqreturn_t t1_interrupt(int irq, void *cookie)
+irqreturn_t t1_interrupt(int irq, void *cookie)
 {
        int work_done;
        struct respQ_e *e;
@@ -1752,11 +1741,7 @@ static irqreturn_t t1_interrupt(int irq, void *cookie)
        spin_unlock(&adapter->async_lock);
        return IRQ_RETVAL(work_done != 0);
 }
-
-irq_handler_t t1_select_intr_handler(adapter_t *adapter)
-{
-       return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
-}
+#endif
 
 /*
  * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
@@ -2033,7 +2018,6 @@ static void sge_tx_reclaim_cb(unsigned long data)
  */
 int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
 {
-       sge->netdev->poll = t1_poll;
        sge->fixed_intrtimer = p->rx_coalesce_usecs *
                core_ticks_per_usec(sge->adapter);
        writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
@@ -2234,7 +2218,6 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter,
 
        p->coalesce_enable = 0;
        p->sample_interval_usecs = 0;
-       p->polling = 0;
 
        return sge;
 nomem_port:
index 7ceb011..d132a0e 100644 (file)
@@ -76,7 +76,9 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params *);
 int t1_sge_configure(struct sge *, struct sge_params *);
 int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
 void t1_sge_destroy(struct sge *);
-irq_handler_t t1_select_intr_handler(adapter_t *adapter);
+irqreturn_t t1_interrupt(int irq, void *cookie);
+int t1_poll(struct net_device *, int *);
+
 int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
 void t1_set_vlan_accel(struct adapter *adapter, int on_off);
 void t1_sge_start(struct sge *);
index dec70c2..4612f71 100644 (file)
@@ -1974,7 +1974,7 @@ out:
        return ret;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        unregister_netdev(dev_cs89x0);
index 690bb40..8396e41 100644 (file)
@@ -43,7 +43,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj
  * modify the following "#define": (see <asm/io.h> for more info)
 #define REALLY_SLOW_IO
  */
-#define SLOW_IO_BY_JUMPING /* Looks "better" than dummy write to port 0x80 :-) */
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifdef DE600_DEBUG
index 00e2a8a..4ae0fed 100644 (file)
  *
  *      v0.009: Module support fixes, multiple interfaces support, various
  *              bits. macro
+ *
+ *      v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
+ *              PMAX requirement to only use halfword accesses to the
+ *              buffer. macro
  */
 
 #include <linux/crc32.h>
@@ -54,6 +58,7 @@
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
+#include <linux/types.h>
 
 #include <asm/addrspace.h>
 #include <asm/system.h>
@@ -67,7 +72,7 @@
 #include <asm/dec/tc.h>
 
 static char version[] __devinitdata =
-"declance.c: v0.009 by Linux MIPS DECstation task force\n";
+"declance.c: v0.010 by Linux MIPS DECstation task force\n";
 
 MODULE_AUTHOR("Linux MIPS DECstation task force");
 MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
@@ -110,24 +115,25 @@ MODULE_LICENSE("GPL");
 #define        LE_C3_BCON      0x1     /* Byte control */
 
 /* Receive message descriptor 1 */
-#define LE_R1_OWN       0x80   /* Who owns the entry */
-#define LE_R1_ERR       0x40   /* Error: if FRA, OFL, CRC or BUF is set */
-#define LE_R1_FRA       0x20   /* FRA: Frame error */
-#define LE_R1_OFL       0x10   /* OFL: Frame overflow */
-#define LE_R1_CRC       0x08   /* CRC error */
-#define LE_R1_BUF       0x04   /* BUF: Buffer error */
-#define LE_R1_SOP       0x02   /* Start of packet */
-#define LE_R1_EOP       0x01   /* End of packet */
-#define LE_R1_POK       0x03   /* Packet is complete: SOP + EOP */
-
-#define LE_T1_OWN       0x80   /* Lance owns the packet */
-#define LE_T1_ERR       0x40   /* Error summary */
-#define LE_T1_EMORE     0x10   /* Error: more than one retry needed */
-#define LE_T1_EONE      0x08   /* Error: one retry needed */
-#define LE_T1_EDEF      0x04   /* Error: deferred */
-#define LE_T1_SOP       0x02   /* Start of packet */
-#define LE_T1_EOP       0x01   /* End of packet */
-#define LE_T1_POK      0x03    /* Packet is complete: SOP + EOP */
+#define LE_R1_OWN      0x8000  /* Who owns the entry */
+#define LE_R1_ERR      0x4000  /* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA      0x2000  /* FRA: Frame error */
+#define LE_R1_OFL      0x1000  /* OFL: Frame overflow */
+#define LE_R1_CRC      0x0800  /* CRC error */
+#define LE_R1_BUF      0x0400  /* BUF: Buffer error */
+#define LE_R1_SOP      0x0200  /* Start of packet */
+#define LE_R1_EOP      0x0100  /* End of packet */
+#define LE_R1_POK      0x0300  /* Packet is complete: SOP + EOP */
+
+/* Transmit message descriptor 1 */
+#define LE_T1_OWN      0x8000  /* Lance owns the packet */
+#define LE_T1_ERR      0x4000  /* Error summary */
+#define LE_T1_EMORE    0x1000  /* Error: more than one retry needed */
+#define LE_T1_EONE     0x0800  /* Error: one retry needed */
+#define LE_T1_EDEF     0x0400  /* Error: deferred */
+#define LE_T1_SOP      0x0200  /* Start of packet */
+#define LE_T1_EOP      0x0100  /* End of packet */
+#define LE_T1_POK      0x0300  /* Packet is complete: SOP + EOP */
 
 #define LE_T3_BUF       0x8000 /* Buffer error */
 #define LE_T3_UFL       0x4000 /* Error underflow */
@@ -156,69 +162,57 @@ MODULE_LICENSE("GPL");
 #undef TEST_HITS
 #define ZERO 0
 
-/* The DS2000/3000 have a linear 64 KB buffer.
-
- * The PMAD-AA has 128 kb buffer on-board.
+/*
+ * The DS2100/3100 have a linear 64 kB buffer which supports halfword
+ * accesses only.  Each halfword of the buffer is word-aligned in the
+ * CPU address space.
  *
- * The IOASIC LANCE devices use a shared memory region. This region as seen
- * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary.
- * The LANCE sees this as a 64 KB long continuous memory region.
+ * The PMAD-AA has a 128 kB buffer on-board.
  *
- * The LANCE's DMA address is used as an index in this buffer and DMA takes
- * place in bursts of eight 16-Bit words which are packed into four 32-Bit words
- * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed
- * by a 16 byte gap :-(.
+ * The IOASIC LANCE devices use a shared memory region.  This region
+ * as seen from the CPU is (max) 128 kB long and has to be on an 128 kB
+ * boundary.  The LANCE sees this as a 64 kB long continuous memory
+ * region.
+ *
+ * The LANCE's DMA address is used as an index in this buffer and DMA
+ * takes place in bursts of eight 16-bit words which are packed into
+ * four 32-bit words by the IOASIC.  This leads to a strange padding:
+ * 16 bytes of valid data followed by a 16 byte gap :-(.
  */
 
 struct lance_rx_desc {
        unsigned short rmd0;            /* low address of packet */
-       short gap0;
-       unsigned char rmd1_hadr;        /* high address of packet */
-       unsigned char rmd1_bits;        /* descriptor bits */
-       short gap1;
+       unsigned short rmd1;            /* high address of packet
+                                          and descriptor bits */
        short length;                   /* 2s complement (negative!)
                                           of buffer length */
-       short gap2;
        unsigned short mblength;        /* actual number of bytes received */
-       short gap3;
 };
 
 struct lance_tx_desc {
        unsigned short tmd0;            /* low address of packet */
-       short gap0;
-       unsigned char tmd1_hadr;        /* high address of packet */
-       unsigned char tmd1_bits;        /* descriptor bits */
-       short gap1;
+       unsigned short tmd1;            /* high address of packet
+                                          and descriptor bits */
        short length;                   /* 2s complement (negative!)
                                           of buffer length */
-       short gap2;
        unsigned short misc;
-       short gap3;
 };
 
 
 /* First part of the LANCE initialization block, described in databook. */
 struct lance_init_block {
        unsigned short mode;            /* pre-set mode (reg. 15) */
-       short gap0;
 
-       unsigned char phys_addr[12];    /* physical ethernet address
-                                          only 0, 1, 4, 5, 8, 9 are valid
-                                          2, 3, 6, 7, 10, 11 are gaps */
-       unsigned short filter[8];       /* multicast filter
-                                          only 0, 2, 4, 6 are valid
-                                          1, 3, 5, 7 are gaps */
+       unsigned short phys_addr[3];    /* physical ethernet address */
+       unsigned short filter[4];       /* multicast filter */
 
        /* Receive and transmit ring base, along with extra bits. */
        unsigned short rx_ptr;          /* receive descriptor addr */
-       short gap1;
        unsigned short rx_len;          /* receive len and high addr */
-       short gap2;
        unsigned short tx_ptr;          /* transmit descriptor addr */
-       short gap3;
        unsigned short tx_len;          /* transmit len and high addr */
-       short gap4;
-       short gap5[8];
+
+       short gap[4];
 
        /* The buffer descriptors */
        struct lance_rx_desc brx_ring[RX_RING_SIZE];
@@ -226,15 +220,28 @@ struct lance_init_block {
 };
 
 #define BUF_OFFSET_CPU sizeof(struct lance_init_block)
-#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1)
+#define BUF_OFFSET_LNC sizeof(struct lance_init_block)
 
-#define libdesc_offset(rt, elem) \
-((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem])))))
+#define shift_off(off, type)                                           \
+       (type == ASIC_LANCE || type == PMAX_LANCE ? off << 1 : off)
 
-/*
- * This works *only* for the ring descriptors
- */
-#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
+#define lib_off(rt, type)                                              \
+       shift_off(offsetof(struct lance_init_block, rt), type)
+
+#define lib_ptr(ib, rt, type)                                          \
+       ((volatile u16 *)((u8 *)(ib) + lib_off(rt, type)))
+
+#define rds_off(rt, type)                                              \
+       shift_off(offsetof(struct lance_rx_desc, rt), type)
+
+#define rds_ptr(rd, rt, type)                                          \
+       ((volatile u16 *)((u8 *)(rd) + rds_off(rt, type)))
+
+#define tds_off(rt, type)                                              \
+       shift_off(offsetof(struct lance_tx_desc, rt), type)
+
+#define tds_ptr(td, rt, type)                                          \
+       ((volatile u16 *)((u8 *)(td) + tds_off(rt, type)))
 
 struct lance_private {
        struct net_device *next;
@@ -242,7 +249,6 @@ struct lance_private {
        int slot;
        int dma_irq;
        volatile struct lance_regs *ll;
-       volatile struct lance_init_block *init_block;
 
        spinlock_t      lock;
 
@@ -260,8 +266,8 @@ struct lance_private {
        char *tx_buf_ptr_cpu[TX_RING_SIZE];
 
        /* Pointers to the ring buffers as seen from the LANCE */
-       char *rx_buf_ptr_lnc[RX_RING_SIZE];
-       char *tx_buf_ptr_lnc[TX_RING_SIZE];
+       uint rx_buf_ptr_lnc[RX_RING_SIZE];
+       uint tx_buf_ptr_lnc[TX_RING_SIZE];
 };
 
 #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
@@ -294,7 +300,7 @@ static inline void writereg(volatile unsigned short *regptr, short value)
 static void load_csrs(struct lance_private *lp)
 {
        volatile struct lance_regs *ll = lp->ll;
-       int leptr;
+       uint leptr;
 
        /* The address space as seen from the LANCE
         * begins at address 0. HK
@@ -316,12 +322,14 @@ static void load_csrs(struct lance_private *lp)
  * Our specialized copy routines
  *
  */
-void cp_to_buf(const int type, void *to, const void *from, int len)
+static void cp_to_buf(const int type, void *to, const void *from, int len)
 {
        unsigned short *tp, *fp, clen;
        unsigned char *rtp, *rfp;
 
-       if (type == PMAX_LANCE) {
+       if (type == PMAD_LANCE) {
+               memcpy(to, from, len);
+       } else if (type == PMAX_LANCE) {
                clen = len >> 1;
                tp = (unsigned short *) to;
                fp = (unsigned short *) from;
@@ -370,12 +378,14 @@ void cp_to_buf(const int type, void *to, const void *from, int len)
        iob();
 }
 
-void cp_from_buf(const int type, void *to, const void *from, int len)
+static void cp_from_buf(const int type, void *to, const void *from, int len)
 {
        unsigned short *tp, *fp, clen;
        unsigned char *rtp, *rfp;
 
-       if (type == PMAX_LANCE) {
+       if (type == PMAD_LANCE) {
+               memcpy(to, from, len);
+       } else if (type == PMAX_LANCE) {
                clen = len >> 1;
                tp = (unsigned short *) to;
                fp = (unsigned short *) from;
@@ -431,12 +441,10 @@ void cp_from_buf(const int type, void *to, const void *from, int len)
 static void lance_init_ring(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib;
-       int leptr;
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
+       uint leptr;
        int i;
 
-       ib = (struct lance_init_block *) (dev->mem_start);
-
        /* Lock out other processes while setting up hardware */
        netif_stop_queue(dev);
        lp->rx_new = lp->tx_new = 0;
@@ -445,55 +453,64 @@ static void lance_init_ring(struct net_device *dev)
        /* Copy the ethernet address to the lance init block.
         * XXX bit 0 of the physical address registers has to be zero
         */
-       ib->phys_addr[0] = dev->dev_addr[0];
-       ib->phys_addr[1] = dev->dev_addr[1];
-       ib->phys_addr[4] = dev->dev_addr[2];
-       ib->phys_addr[5] = dev->dev_addr[3];
-       ib->phys_addr[8] = dev->dev_addr[4];
-       ib->phys_addr[9] = dev->dev_addr[5];
+       *lib_ptr(ib, phys_addr[0], lp->type) = (dev->dev_addr[1] << 8) |
+                                    dev->dev_addr[0];
+       *lib_ptr(ib, phys_addr[1], lp->type) = (dev->dev_addr[3] << 8) |
+                                    dev->dev_addr[2];
+       *lib_ptr(ib, phys_addr[2], lp->type) = (dev->dev_addr[5] << 8) |
+                                    dev->dev_addr[4];
        /* Setup the initialization block */
 
        /* Setup rx descriptor pointer */
-       leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0));
-       ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
-       ib->rx_ptr = leptr;
+       leptr = offsetof(struct lance_init_block, brx_ring);
+       *lib_ptr(ib, rx_len, lp->type) = (LANCE_LOG_RX_BUFFERS << 13) |
+                                        (leptr >> 16);
+       *lib_ptr(ib, rx_ptr, lp->type) = leptr;
        if (ZERO)
-               printk("RX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0));
+               printk("RX ptr: %8.8x(%8.8x)\n",
+                      leptr, lib_off(brx_ring, lp->type));
 
        /* Setup tx descriptor pointer */
-       leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0));
-       ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
-       ib->tx_ptr = leptr;
+       leptr = offsetof(struct lance_init_block, btx_ring);
+       *lib_ptr(ib, tx_len, lp->type) = (LANCE_LOG_TX_BUFFERS << 13) |
+                                        (leptr >> 16);
+       *lib_ptr(ib, tx_ptr, lp->type) = leptr;
        if (ZERO)
-               printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0));
+               printk("TX ptr: %8.8x(%8.8x)\n",
+                      leptr, lib_off(btx_ring, lp->type));
 
        if (ZERO)
                printk("TX rings:\n");
 
        /* Setup the Tx ring entries */
        for (i = 0; i < TX_RING_SIZE; i++) {
-               leptr = (int) lp->tx_buf_ptr_lnc[i];
-               ib->btx_ring[i].tmd0 = leptr;
-               ib->btx_ring[i].tmd1_hadr = leptr >> 16;
-               ib->btx_ring[i].tmd1_bits = 0;
-               ib->btx_ring[i].length = 0xf000;        /* The ones required by tmd2 */
-               ib->btx_ring[i].misc = 0;
+               leptr = lp->tx_buf_ptr_lnc[i];
+               *lib_ptr(ib, btx_ring[i].tmd0, lp->type) = leptr;
+               *lib_ptr(ib, btx_ring[i].tmd1, lp->type) = (leptr >> 16) &
+                                                          0xff;
+               *lib_ptr(ib, btx_ring[i].length, lp->type) = 0xf000;
+                                               /* The ones required by tmd2 */
+               *lib_ptr(ib, btx_ring[i].misc, lp->type) = 0;
                if (i < 3 && ZERO)
-                       printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]);
+                       printk("%d: 0x%8.8x(0x%8.8x)\n",
+                              i, leptr, (uint)lp->tx_buf_ptr_cpu[i]);
        }
 
        /* Setup the Rx ring entries */
        if (ZERO)
                printk("RX rings:\n");
        for (i = 0; i < RX_RING_SIZE; i++) {
-               leptr = (int) lp->rx_buf_ptr_lnc[i];
-               ib->brx_ring[i].rmd0 = leptr;
-               ib->brx_ring[i].rmd1_hadr = leptr >> 16;
-               ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
-               ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000;
-               ib->brx_ring[i].mblength = 0;
+               leptr = lp->rx_buf_ptr_lnc[i];
+               *lib_ptr(ib, brx_ring[i].rmd0, lp->type) = leptr;
+               *lib_ptr(ib, brx_ring[i].rmd1, lp->type) = ((leptr >> 16) &
+                                                           0xff) |
+                                                          LE_R1_OWN;
+               *lib_ptr(ib, brx_ring[i].length, lp->type) = -RX_BUFF_SIZE |
+                                                            0xf000;
+               *lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0;
                if (i < 3 && ZERO)
-                       printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
+                       printk("%d: 0x%8.8x(0x%8.8x)\n",
+                              i, leptr, (uint)lp->rx_buf_ptr_cpu[i]);
        }
        iob();
 }
@@ -511,11 +528,13 @@ static int init_restart_lance(struct lance_private *lp)
                udelay(10);
        }
        if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
-               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
+                      i, ll->rdp);
                return -1;
        }
        if ((ll->rdp & LE_C0_ERR)) {
-               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
+                      i, ll->rdp);
                return -1;
        }
        writereg(&ll->rdp, LE_C0_IDON);
@@ -528,12 +547,11 @@ static int init_restart_lance(struct lance_private *lp)
 static int lance_rx(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib;
-       volatile struct lance_rx_desc *rd = 0;
-       unsigned char bits;
-       int len = 0;
-       struct sk_buff *skb = 0;
-       ib = (struct lance_init_block *) (dev->mem_start);
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
+       volatile u16 *rd;
+       unsigned short bits;
+       int entry, len;
+       struct sk_buff *skb;
 
 #ifdef TEST_HITS
        {
@@ -542,19 +560,22 @@ static int lance_rx(struct net_device *dev)
                printk("[");
                for (i = 0; i < RX_RING_SIZE; i++) {
                        if (i == lp->rx_new)
-                               printk("%s", ib->brx_ring[i].rmd1_bits &
+                               printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
+                                                     lp->type) &
                                             LE_R1_OWN ? "_" : "X");
                        else
-                               printk("%s", ib->brx_ring[i].rmd1_bits &
+                               printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
+                                                     lp->type) &
                                             LE_R1_OWN ? "." : "1");
                }
                printk("]");
        }
 #endif
 
-       for (rd = &ib->brx_ring[lp->rx_new];
-            !((bits = rd->rmd1_bits) & LE_R1_OWN);
-            rd = &ib->brx_ring[lp->rx_new]) {
+       for (rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type);
+            !((bits = *rds_ptr(rd, rmd1, lp->type)) & LE_R1_OWN);
+            rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type)) {
+               entry = lp->rx_new;
 
                /* We got an incomplete frame? */
                if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -575,16 +596,18 @@ static int lance_rx(struct net_device *dev)
                        if (bits & LE_R1_EOP)
                                lp->stats.rx_errors++;
                } else {
-                       len = (rd->mblength & 0xfff) - 4;
+                       len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4;
                        skb = dev_alloc_skb(len + 2);
 
                        if (skb == 0) {
                                printk("%s: Memory squeeze, deferring packet.\n",
                                       dev->name);
                                lp->stats.rx_dropped++;
-                               rd->mblength = 0;
-                               rd->rmd1_bits = LE_R1_OWN;
-                               lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+                               *rds_ptr(rd, mblength, lp->type) = 0;
+                               *rds_ptr(rd, rmd1, lp->type) =
+                                       ((lp->rx_buf_ptr_lnc[entry] >> 16) &
+                                        0xff) | LE_R1_OWN;
+                               lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
                                return 0;
                        }
                        lp->stats.rx_bytes += len;
@@ -594,8 +617,7 @@ static int lance_rx(struct net_device *dev)
                        skb_put(skb, len);      /* make room */
 
                        cp_from_buf(lp->type, skb->data,
-                                   (char *)lp->rx_buf_ptr_cpu[lp->rx_new],
-                                   len);
+                                   (char *)lp->rx_buf_ptr_cpu[entry], len);
 
                        skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
@@ -604,10 +626,11 @@ static int lance_rx(struct net_device *dev)
                }
 
                /* Return the packet to the pool */
-               rd->mblength = 0;
-               rd->length = -RX_BUFF_SIZE | 0xf000;
-               rd->rmd1_bits = LE_R1_OWN;
-               lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+               *rds_ptr(rd, mblength, lp->type) = 0;
+               *rds_ptr(rd, length, lp->type) = -RX_BUFF_SIZE | 0xf000;
+               *rds_ptr(rd, rmd1, lp->type) =
+                       ((lp->rx_buf_ptr_lnc[entry] >> 16) & 0xff) | LE_R1_OWN;
+               lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
        }
        return 0;
 }
@@ -615,24 +638,24 @@ static int lance_rx(struct net_device *dev)
 static void lance_tx(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib;
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
        volatile struct lance_regs *ll = lp->ll;
-       volatile struct lance_tx_desc *td;
+       volatile u16 *td;
        int i, j;
        int status;
-       ib = (struct lance_init_block *) (dev->mem_start);
+
        j = lp->tx_old;
 
        spin_lock(&lp->lock);
 
        for (i = j; i != lp->tx_new; i = j) {
-               td = &ib->btx_ring[i];
+               td = lib_ptr(ib, btx_ring[i], lp->type);
                /* If we hit a packet not owned by us, stop */
-               if (td->tmd1_bits & LE_T1_OWN)
+               if (*tds_ptr(td, tmd1, lp->type) & LE_T1_OWN)
                        break;
 
-               if (td->tmd1_bits & LE_T1_ERR) {
-                       status = td->misc;
+               if (*tds_ptr(td, tmd1, lp->type) & LE_T1_ERR) {
+                       status = *tds_ptr(td, misc, lp->type);
 
                        lp->stats.tx_errors++;
                        if (status & LE_T3_RTY)
@@ -667,18 +690,19 @@ static void lance_tx(struct net_device *dev)
                                init_restart_lance(lp);
                                goto out;
                        }
-               } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+               } else if ((*tds_ptr(td, tmd1, lp->type) & LE_T1_POK) ==
+                          LE_T1_POK) {
                        /*
                         * So we don't count the packet more than once.
                         */
-                       td->tmd1_bits &= ~(LE_T1_POK);
+                       *tds_ptr(td, tmd1, lp->type) &= ~(LE_T1_POK);
 
                        /* One collision before packet was sent. */
-                       if (td->tmd1_bits & LE_T1_EONE)
+                       if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EONE)
                                lp->stats.collisions++;
 
                        /* More than one collision, be optimistic. */
-                       if (td->tmd1_bits & LE_T1_EMORE)
+                       if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EMORE)
                                lp->stats.collisions += 2;
 
                        lp->stats.tx_packets++;
@@ -752,7 +776,7 @@ struct net_device *last_dev = 0;
 
 static int lance_open(struct net_device *dev)
 {
-       volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
        struct lance_private *lp = netdev_priv(dev);
        volatile struct lance_regs *ll = lp->ll;
        int status = 0;
@@ -769,11 +793,11 @@ static int lance_open(struct net_device *dev)
         *
         * BTW it is common bug in all lance drivers! --ANK
         */
-       ib->mode = 0;
-       ib->filter [0] = 0;
-       ib->filter [2] = 0;
-       ib->filter [4] = 0;
-       ib->filter [6] = 0;
+       *lib_ptr(ib, mode, lp->type) = 0;
+       *lib_ptr(ib, filter[0], lp->type) = 0;
+       *lib_ptr(ib, filter[1], lp->type) = 0;
+       *lib_ptr(ib, filter[2], lp->type) = 0;
+       *lib_ptr(ib, filter[3], lp->type) = 0;
 
        lance_init_ring(dev);
        load_csrs(lp);
@@ -874,12 +898,10 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
        volatile struct lance_regs *ll = lp->ll;
-       volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
-       int entry, skblen, len;
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
+       int entry, len;
 
-       skblen = skb->len;
-
-       len = skblen;
+       len = skb->len;
 
        if (len < ETH_ZLEN) {
                if (skb_padto(skb, ETH_ZLEN))
@@ -889,23 +911,17 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        lp->stats.tx_bytes += len;
 
-       entry = lp->tx_new & TX_RING_MOD_MASK;
-       ib->btx_ring[entry].length = (-len);
-       ib->btx_ring[entry].misc = 0;
-
-       cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data,
-                 skblen);
+       entry = lp->tx_new;
+       *lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len);
+       *lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0;
 
-       /* Clear the slack of the packet, do I need this? */
-       /* For a firewall it's a good idea - AC */
-/*
-   if (len != skblen)
-   memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1);
- */
+       cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, len);
 
        /* Now, give the packet to the lance */
-       ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
-       lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
+       *lib_ptr(ib, btx_ring[entry].tmd1, lp->type) =
+               ((lp->tx_buf_ptr_lnc[entry] >> 16) & 0xff) |
+               (LE_T1_POK | LE_T1_OWN);
+       lp->tx_new = (entry + 1) & TX_RING_MOD_MASK;
 
        if (TX_BUFFS_AVAIL <= 0)
                netif_stop_queue(dev);
@@ -930,8 +946,8 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev)
 
 static void lance_load_multicast(struct net_device *dev)
 {
-       volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
-       volatile u16 *mcast_table = (u16 *) & ib->filter;
+       struct lance_private *lp = netdev_priv(dev);
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
        struct dev_mc_list *dmi = dev->mc_list;
        char *addrs;
        int i;
@@ -939,17 +955,17 @@ static void lance_load_multicast(struct net_device *dev)
 
        /* set all multicast bits */
        if (dev->flags & IFF_ALLMULTI) {
-               ib->filter[0] = 0xffff;
-               ib->filter[2] = 0xffff;
-               ib->filter[4] = 0xffff;
-               ib->filter[6] = 0xffff;
+               *lib_ptr(ib, filter[0], lp->type) = 0xffff;
+               *lib_ptr(ib, filter[1], lp->type) = 0xffff;
+               *lib_ptr(ib, filter[2], lp->type) = 0xffff;
+               *lib_ptr(ib, filter[3], lp->type) = 0xffff;
                return;
        }
        /* clear the multicast filter */
-       ib->filter[0] = 0;
-       ib->filter[2] = 0;
-       ib->filter[4] = 0;
-       ib->filter[6] = 0;
+       *lib_ptr(ib, filter[0], lp->type) = 0;
+       *lib_ptr(ib, filter[1], lp->type) = 0;
+       *lib_ptr(ib, filter[2], lp->type) = 0;
+       *lib_ptr(ib, filter[3], lp->type) = 0;
 
        /* Add addresses */
        for (i = 0; i < dev->mc_count; i++) {
@@ -962,7 +978,7 @@ static void lance_load_multicast(struct net_device *dev)
 
                crc = ether_crc_le(ETH_ALEN, addrs);
                crc = crc >> 26;
-               mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf);
+               *lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf);
        }
        return;
 }
@@ -970,11 +986,9 @@ static void lance_load_multicast(struct net_device *dev)
 static void lance_set_multicast(struct net_device *dev)
 {
        struct lance_private *lp = netdev_priv(dev);
-       volatile struct lance_init_block *ib;
+       volatile u16 *ib = (volatile u16 *)dev->mem_start;
        volatile struct lance_regs *ll = lp->ll;
 
-       ib = (struct lance_init_block *) (dev->mem_start);
-
        if (!netif_running(dev))
                return;
 
@@ -992,9 +1006,9 @@ static void lance_set_multicast(struct net_device *dev)
        lance_init_ring(dev);
 
        if (dev->flags & IFF_PROMISC) {
-               ib->mode |= LE_MO_PROM;
+               *lib_ptr(ib, mode, lp->type) |= LE_MO_PROM;
        } else {
-               ib->mode &= ~LE_MO_PROM;
+               *lib_ptr(ib, mode, lp->type) &= ~LE_MO_PROM;
                lance_load_multicast(dev);
        }
        load_csrs(lp);
@@ -1051,7 +1065,6 @@ static int __init dec_lance_init(const int type, const int slot)
        lp->type = type;
        lp->slot = slot;
        switch (type) {
-#ifdef CONFIG_TC
        case ASIC_LANCE:
                dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
 
@@ -1073,20 +1086,20 @@ static int __init dec_lance_init(const int type, const int slot)
                 */
                for (i = 0; i < RX_RING_SIZE; i++) {
                        lp->rx_buf_ptr_cpu[i] =
-                               (char *)(dev->mem_start + BUF_OFFSET_CPU +
+                               (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
                                         2 * i * RX_BUFF_SIZE);
                        lp->rx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
                }
                for (i = 0; i < TX_RING_SIZE; i++) {
                        lp->tx_buf_ptr_cpu[i] =
-                               (char *)(dev->mem_start + BUF_OFFSET_CPU +
+                               (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
                                         2 * RX_RING_SIZE * RX_BUFF_SIZE +
                                         2 * i * TX_BUFF_SIZE);
                        lp->tx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC +
-                                        RX_RING_SIZE * RX_BUFF_SIZE +
-                                        i * TX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC +
+                                RX_RING_SIZE * RX_BUFF_SIZE +
+                                i * TX_BUFF_SIZE);
                }
 
                /* Setup I/O ASIC LANCE DMA.  */
@@ -1095,11 +1108,12 @@ static int __init dec_lance_init(const int type, const int slot)
                             CPHYSADDR(dev->mem_start) << 3);
 
                break;
-
+#ifdef CONFIG_TC
        case PMAD_LANCE:
                claim_tc_card(slot);
 
                dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
+               dev->mem_end = dev->mem_start + 0x100000;
                dev->base_addr = dev->mem_start + 0x100000;
                dev->irq = get_tc_irq_nr(slot);
                esar_base = dev->mem_start + 0x1c0002;
@@ -1110,7 +1124,7 @@ static int __init dec_lance_init(const int type, const int slot)
                                (char *)(dev->mem_start + BUF_OFFSET_CPU +
                                         i * RX_BUFF_SIZE);
                        lp->rx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
                }
                for (i = 0; i < TX_RING_SIZE; i++) {
                        lp->tx_buf_ptr_cpu[i] =
@@ -1118,18 +1132,18 @@ static int __init dec_lance_init(const int type, const int slot)
                                         RX_RING_SIZE * RX_BUFF_SIZE +
                                         i * TX_BUFF_SIZE);
                        lp->tx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC +
-                                        RX_RING_SIZE * RX_BUFF_SIZE +
-                                        i * TX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC +
+                                RX_RING_SIZE * RX_BUFF_SIZE +
+                                i * TX_BUFF_SIZE);
                }
 
                break;
 #endif
-
        case PMAX_LANCE:
                dev->irq = dec_interrupt[DEC_IRQ_LANCE];
                dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
                dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+               dev->mem_end = dev->mem_start + KN01_SLOT_SIZE;
                esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
                lp->dma_irq = -1;
 
@@ -1138,20 +1152,20 @@ static int __init dec_lance_init(const int type, const int slot)
                 */
                for (i = 0; i < RX_RING_SIZE; i++) {
                        lp->rx_buf_ptr_cpu[i] =
-                               (char *)(dev->mem_start + BUF_OFFSET_CPU +
+                               (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
                                         2 * i * RX_BUFF_SIZE);
                        lp->rx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
                }
                for (i = 0; i < TX_RING_SIZE; i++) {
                        lp->tx_buf_ptr_cpu[i] =
-                               (char *)(dev->mem_start + BUF_OFFSET_CPU +
+                               (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
                                         2 * RX_RING_SIZE * RX_BUFF_SIZE +
                                         2 * i * TX_BUFF_SIZE);
                        lp->tx_buf_ptr_lnc[i] =
-                               (char *)(BUF_OFFSET_LNC +
-                                        RX_RING_SIZE * RX_BUFF_SIZE +
-                                        i * TX_BUFF_SIZE);
+                               (BUF_OFFSET_LNC +
+                                RX_RING_SIZE * RX_BUFF_SIZE +
+                                i * TX_BUFF_SIZE);
                }
 
                break;
@@ -1279,10 +1293,8 @@ static int __init dec_lance_probe(void)
        /* Then handle onboard devices. */
        if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
                if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
-#ifdef CONFIG_TC
                        if (dec_lance_init(ASIC_LANCE, -1) >= 0)
                                count++;
-#endif
                } else if (!TURBOCHANNEL) {
                        if (dec_lance_init(PMAX_LANCE, -1) >= 0)
                                count++;
index 3a8df47..03bf164 100644 (file)
@@ -2102,9 +2102,10 @@ static void e100_tx_timeout(struct net_device *netdev)
        schedule_work(&nic->tx_timeout_task);
 }
 
-static void e100_tx_timeout_task(struct net_device *netdev)
+static void e100_tx_timeout_task(struct work_struct *work)
 {
-       struct nic *nic = netdev_priv(netdev);
+       struct nic *nic = container_of(work, struct nic, tx_timeout_task);
+       struct net_device *netdev = nic->netdev;
 
        DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
                readb(&nic->csr->scb.status));
@@ -2637,8 +2638,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        nic->blink_timer.function = e100_blink_led;
        nic->blink_timer.data = (unsigned long)nic;
 
-       INIT_WORK(&nic->tx_timeout_task,
-               (void (*)(void *))e100_tx_timeout_task, netdev);
+       INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);
 
        if((err = e100_alloc(nic))) {
                DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
index 32dde0a..73f3a85 100644 (file)
@@ -190,7 +190,7 @@ void e1000_set_ethtool_ops(struct net_device *netdev);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static void e1000_tx_timeout(struct net_device *dev);
-static void e1000_reset_task(struct net_device *dev);
+static void e1000_reset_task(struct work_struct *work);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
 static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
                                        struct sk_buff *skb);
@@ -914,8 +914,7 @@ e1000_probe(struct pci_dev *pdev,
        adapter->phy_info_timer.function = &e1000_update_phy_info;
        adapter->phy_info_timer.data = (unsigned long) adapter;
 
-       INIT_WORK(&adapter->reset_task,
-               (void (*)(void *))e1000_reset_task, netdev);
+       INIT_WORK(&adapter->reset_task, e1000_reset_task);
 
        e1000_check_options(adapter);
 
@@ -3306,9 +3305,10 @@ e1000_tx_timeout(struct net_device *netdev)
 }
 
 static void
-e1000_reset_task(struct net_device *netdev)
+e1000_reset_task(struct work_struct *work)
 {
-       struct e1000_adapter *adapter = netdev_priv(netdev);
+       struct e1000_adapter *adapter =
+               container_of(work, struct e1000_adapter, reset_task);
 
        e1000_reinit_locked(adapter);
 }
index d39e848..c62d9c6 100644 (file)
@@ -463,7 +463,7 @@ static void cleanup_card(struct net_device *dev)
        release_region(dev->base_addr, E21_IO_EXTENT);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index a4eb0dc..b446309 100644 (file)
@@ -1827,7 +1827,7 @@ int __init init_module(void)
        return n_eepro ? 0 : -ENODEV;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int i;
index e14be02..4a50fcb 100644 (file)
@@ -1719,7 +1719,7 @@ int __init init_module(void)
        return -ENXIO;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index 6ad6961..83fa32f 100644 (file)
@@ -2224,11 +2224,12 @@ static int ehea_stop(struct net_device *dev)
        return ret;
 }
 
-static void ehea_reset_port(void *data)
+static void ehea_reset_port(struct work_struct *work)
 {
        int ret;
-       struct net_device *dev = data;
-       struct ehea_port *port = netdev_priv(dev);
+       struct ehea_port *port =
+               container_of(work, struct ehea_port, reset_task);
+       struct net_device *dev = port->netdev;
 
        port->resets++;
        down(&port->port_lock);
@@ -2379,7 +2380,7 @@ static int ehea_setup_single_port(struct ehea_port *port,
        dev->tx_timeout = &ehea_tx_watchdog;
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
-       INIT_WORK(&port->reset_task, ehea_reset_port, dev);
+       INIT_WORK(&port->reset_task, ehea_reset_port);
 
        ehea_set_ethtool_ops(dev);
 
index fd7b32a..2d2ea94 100644 (file)
@@ -455,7 +455,7 @@ static void cleanup_card(struct net_device *dev)
        iounmap(ei_status.mem);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index b7b8bc2..93283e3 100644 (file)
@@ -1475,7 +1475,7 @@ int __init init_module(void)
        return -ENXIO;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index 92420f0..760d04a 100644 (file)
@@ -325,11 +325,6 @@ static int sp_rebuild_header(struct sk_buff *skb)
 
 static void sp_setup(struct net_device *dev)
 {
-       static char ax25_bcast[AX25_ADDR_LEN] =
-               {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
-       static char ax25_test[AX25_ADDR_LEN] =
-               {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
        /* Finish setting up the DEVICE info. */
        dev->mtu                = SIXP_MTU;
        dev->hard_start_xmit    = sp_xmit;
@@ -347,8 +342,8 @@ static void sp_setup(struct net_device *dev)
        dev->tx_timeout         = NULL;
 
        /* Only activated in AX.25 mode */
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 
        SET_MODULE_OWNER(dev);
 
index 1ed9ccc..153b6dc 100644 (file)
@@ -168,8 +168,9 @@ struct baycom_state {
        int magic;
 
         struct pardevice *pdev;
+       struct net_device *dev;
        unsigned int work_running;
-       struct work_struct run_work;
+       struct delayed_work run_work;
        unsigned int modem;
        unsigned int bitrate;
        unsigned char stat;
@@ -659,16 +660,18 @@ static int receive(struct net_device *dev, int cnt)
 #define GETTICK(x)
 #endif /* __i386__ */
 
-static void epp_bh(struct net_device *dev)
+static void epp_bh(struct work_struct *work)
 {
+       struct net_device *dev;
        struct baycom_state *bc;
        struct parport *pp;
        unsigned char stat;
        unsigned char tmp[2];
        unsigned int time1 = 0, time2 = 0, time3 = 0;
        int cnt, cnt2;
-       
-       bc = netdev_priv(dev);
+
+       bc = container_of(work, struct baycom_state, run_work.work);
+       dev = bc->dev;
        if (!bc->work_running)
                return;
        baycom_int_freq(bc);
@@ -889,7 +892,7 @@ static int epp_open(struct net_device *dev)
                 return -EBUSY;
         }
         dev->irq = /*pp->irq*/ 0;
-       INIT_WORK(&bc->run_work, (void *)(void *)epp_bh, dev);
+       INIT_DELAYED_WORK(&bc->run_work, epp_bh);
        bc->work_running = 1;
        bc->modem = EPP_CONVENTIONAL;
        if (eppconfig(bc))
@@ -1138,12 +1141,6 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  */
 static void baycom_probe(struct net_device *dev)
 {
-       static char ax25_bcast[AX25_ADDR_LEN] = {
-               'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1
-       };
-       static char ax25_nocall[AX25_ADDR_LEN] = {
-               'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1
-       };
        const struct hdlcdrv_channel_params dflt_ch_params = { 
                20, 2, 10, 40, 0 
        };
@@ -1179,8 +1176,8 @@ static void baycom_probe(struct net_device *dev)
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
        dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN);
        dev->tx_queue_len = 16;
 
        /* New style flags */
@@ -1213,6 +1210,7 @@ static void __init baycom_epp_dev_setup(struct net_device *dev)
        /*
         * initialize part of the baycom_state struct
         */
+       bc->dev = dev;
        bc->magic = BAYCOM_MAGIC;
        bc->cfg.fclk = 19666600;
        bc->cfg.bps = 9600;
index 889f338..5b788d8 100644 (file)
 
 static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n";
 
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
-       {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
-       {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
 static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
 
 static char bpq_eth_addr[6];
@@ -487,8 +482,8 @@ static void bpq_setup(struct net_device *dev)
        dev->do_ioctl        = bpq_ioctl;
        dev->destructor      = free_netdev;
 
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr,  ax25_defaddr, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr,  &ax25_defaddr, AX25_ADDR_LEN);
 
        dev->flags      = 0;
 
index 0f8b9af..0fbb414 100644 (file)
@@ -252,7 +252,7 @@ static inline void z8530_isr(struct scc_info *info);
 static irqreturn_t scc_isr(int irq, void *dev_id);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
-static void rx_bh(void *arg);
+static void rx_bh(struct work_struct *);
 static void tx_isr(struct scc_priv *priv);
 static void es_isr(struct scc_priv *priv);
 static void tm_isr(struct scc_priv *priv);
@@ -264,12 +264,6 @@ static int io[MAX_NUM_DEVS] __initdata = { 0, };
 
 /* Beware! hw[] is also used in cleanup_module(). */
 static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE;
-static char ax25_broadcast[7] __initdata =
-    { 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1,
-'0' << 1 };
-static char ax25_test[7] __initdata =
-    { 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1,
-'1' << 1 };
 
 
 /* Global variables */
@@ -443,8 +437,8 @@ static void __init dev_setup(struct net_device *dev)
        dev->mtu = 1500;
        dev->addr_len = AX25_ADDR_LEN;
        dev->tx_queue_len = 64;
-       memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 }
 
 static int __init setup_adapter(int card_base, int type, int n)
@@ -579,7 +573,7 @@ static int __init setup_adapter(int card_base, int type, int n)
                priv->param.clocks = TCTRxCP | RCRTxCP;
                priv->param.persist = 256;
                priv->param.dma = -1;
-               INIT_WORK(&priv->rx_work, rx_bh, priv);
+               INIT_WORK(&priv->rx_work, rx_bh);
                dev->priv = priv;
                sprintf(dev->name, "dmascc%i", 2 * n + i);
                dev->base_addr = card_base;
@@ -1272,9 +1266,9 @@ static void special_condition(struct scc_priv *priv, int rc)
 }
 
 
-static void rx_bh(void *arg)
+static void rx_bh(struct work_struct *ugli_api)
 {
-       struct scc_priv *priv = arg;
+       struct scc_priv *priv = container_of(ugli_api, struct scc_priv, rx_work);
        int i = priv->rx_tail;
        int cb;
        unsigned long flags;
index dacc768..452873e 100644 (file)
 
 /* --------------------------------------------------------------------- */
 
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-
-static char ax25_bcast[AX25_ADDR_LEN] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_nocall[AX25_ADDR_LEN] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-/* --------------------------------------------------------------------- */
-
 #define KISS_VERBOSE
 
 /* --------------------------------------------------------------------- */
@@ -709,8 +697,8 @@ static void hdlcdrv_setup(struct net_device *dev)
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
        dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
        dev->tx_queue_len = 16;
 }
 
index d8715b2..d08fbc3 100644 (file)
@@ -672,11 +672,6 @@ static struct net_device_stats *ax_get_stats(struct net_device *dev)
 
 static void ax_setup(struct net_device *dev)
 {
-       static char ax25_bcast[AX25_ADDR_LEN] =
-               {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
-       static char ax25_test[AX25_ADDR_LEN] =
-               {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
        /* Finish setting up the DEVICE info. */
        dev->mtu             = AX_MTU;
        dev->hard_start_xmit = ax_xmit;
@@ -691,8 +686,8 @@ static void ax_setup(struct net_device *dev)
        dev->hard_header     = ax_header;
        dev->rebuild_header  = ax_rebuild_header;
 
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr,  ax25_test,  AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr,  &ax25_defaddr,  AX25_ADDR_LEN);
 
        dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
 }
index ec9b6d9..2ce047e 100644 (file)
@@ -1540,11 +1540,6 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
 /* *                       Network driver methods                    * */
 /* ******************************************************************** */
 
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_nocall[AX25_ADDR_LEN] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
 /* ----> Initialize device <----- */
 
 static void scc_net_setup(struct net_device *dev)
@@ -1562,8 +1557,8 @@ static void scc_net_setup(struct net_device *dev)
        dev->do_ioctl        = scc_net_ioctl;
        dev->tx_timeout      = NULL;
 
-       memcpy(dev->broadcast, ax25_bcast,  AX25_ADDR_LEN);
-       memcpy(dev->dev_addr,  ax25_nocall, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast,  AX25_ADDR_LEN);
+       memcpy(dev->dev_addr,  &ax25_defaddr, AX25_ADDR_LEN);
  
        dev->flags      = 0;
 
index 3c4455b..6d74f08 100644 (file)
@@ -156,11 +156,6 @@ static struct net_device *yam_devs[NR_PORTS];
 
 static struct yam_mcs *yam_data;
 
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
 static DEFINE_TIMER(yam_timer, NULL, 0, 0);
 
 /* --------------------------------------------------------------------- */
@@ -1115,8 +1110,8 @@ static void yam_setup(struct net_device *dev)
        dev->hard_header_len = AX25_MAX_HEADER_LEN;
        dev->mtu = AX25_MTU;
        dev->addr_len = AX25_ADDR_LEN;
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+       memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 }
 
 static int __init yam_init_driver(void)
index 6abcfd2..99a36cc 100644 (file)
@@ -482,7 +482,7 @@ static void cleanup_card(struct net_device *dev)
        release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index 2947097..635b13c 100644 (file)
@@ -444,7 +444,7 @@ static void cleanup_card(struct net_device *dev)
        release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index 9c643f2..c991cb8 100644 (file)
@@ -77,6 +77,7 @@ static int __devinit hplance_init_one(struct dio_dev *d,
 {
        struct net_device *dev;
        int err = -ENOMEM;
+       int i;
 
        dev = alloc_etherdev(sizeof(struct hplance_private));
        if (!dev)
@@ -93,6 +94,15 @@ static int __devinit hplance_init_one(struct dio_dev *d,
                goto out_release_mem_region;
 
        dio_set_drvdata(d, dev);
+
+       printk(KERN_INFO "%s: %s; select code %d, addr %2.2x", dev->name, d->name, d->scode, dev->dev_addr[0]);
+
+       for (i=1; i<6; i++) {
+               printk(":%2.2x", dev->dev_addr[i]);
+       }
+
+       printk(", irq %d\n", d->ipl);
+
        return 0;
 
  out_release_mem_region:
@@ -119,8 +129,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
         struct hplance_private *lp;
         int i;
 
-        printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, d->name, d->scode);
-
         /* reset the board */
         out_8(va+DIO_IDOFF, 0xff);
         udelay(100);                              /* ariba! ariba! udelay! udelay! */
@@ -143,7 +151,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
                  */
                 dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
                         | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
-                printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
         }
 
         lp = netdev_priv(dev);
@@ -160,7 +167,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
         lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
         lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
         lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
-       printk(", irq %d\n", lp->lance.irq);
 }
 
 /* This is disgusting. We have to check the DIO status register for ack every
index 6a98b7a..ad18573 100644 (file)
@@ -117,7 +117,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
 {
        struct sirtty_cb *priv = dev->priv;
        struct tty_struct *tty;
-        struct termios old_termios;
+        struct ktermios old_termios;
        int cflag;
 
        IRDA_ASSERT(priv != NULL, return -1;);
@@ -318,7 +318,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
 
 static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
 {
-       struct termios old_termios;
+       struct ktermios old_termios;
        int cflag;
 
        lock_kernel();
index b32c52e..f0c61f3 100644 (file)
@@ -560,9 +560,9 @@ static inline int mcs_find_endpoints(struct mcs_cb *mcs,
        return ret;
 }
 
-static void mcs_speed_work(void *arg)
+static void mcs_speed_work(struct work_struct *work)
 {
-       struct mcs_cb *mcs = arg;
+       struct mcs_cb *mcs = container_of(work, struct mcs_cb, work);
        struct net_device *netdev = mcs->netdev;
 
        mcs_speed_change(mcs);
@@ -927,7 +927,7 @@ static int mcs_probe(struct usb_interface *intf,
        irda_qos_bits_to_value(&mcs->qos);
 
        /* Speed change work initialisation*/
-       INIT_WORK(&mcs->work, mcs_speed_work, mcs);
+       INIT_WORK(&mcs->work, mcs_speed_work);
 
        /* Override the network functions we need to use */
        ndev->hard_start_xmit = mcs_hard_xmit;
index f9a1c88..9137e23 100644 (file)
@@ -704,9 +704,9 @@ static int pxa_irda_stop(struct net_device *dev)
        return 0;
 }
 
-static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
+static int pxa_irda_suspend(struct platform_device *_dev, pm_message_t state)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
        struct pxa_irda *si;
 
        if (dev && netif_running(dev)) {
@@ -718,9 +718,9 @@ static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
        return 0;
 }
 
-static int pxa_irda_resume(struct device *_dev)
+static int pxa_irda_resume(struct platform_device *_dev)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
        struct pxa_irda *si;
 
        if (dev && netif_running(dev)) {
@@ -746,9 +746,8 @@ static int pxa_irda_init_iobuf(iobuff_t *io, int size)
        return io->head ? 0 : -ENOMEM;
 }
 
-static int pxa_irda_probe(struct device *_dev)
+static int pxa_irda_probe(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(_dev);
        struct net_device *dev;
        struct pxa_irda *si;
        unsigned int baudrate_mask;
@@ -822,9 +821,9 @@ err_mem_1:
        return err;
 }
 
-static int pxa_irda_remove(struct device *_dev)
+static int pxa_irda_remove(struct platform_device *_dev)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
 
        if (dev) {
                struct pxa_irda *si = netdev_priv(dev);
@@ -840,9 +839,10 @@ static int pxa_irda_remove(struct device *_dev)
        return 0;
 }
 
-static struct device_driver pxa_ir_driver = {
-       .name           = "pxa2xx-ir",
-       .bus            = &platform_bus_type,
+static struct platform_driver pxa_ir_driver = {
+       .driver         = {
+               .name   = "pxa2xx-ir",
+       },
        .probe          = pxa_irda_probe,
        .remove         = pxa_irda_remove,
        .suspend        = pxa_irda_suspend,
@@ -851,12 +851,12 @@ static struct device_driver pxa_ir_driver = {
 
 static int __init pxa_irda_init(void)
 {
-       return driver_register(&pxa_ir_driver);
+       return platform_driver_register(&pxa_ir_driver);
 }
 
 static void __exit pxa_irda_exit(void)
 {
-       driver_unregister(&pxa_ir_driver);
+       platform_driver_unregister(&pxa_ir_driver);
 }
 
 module_init(pxa_irda_init);
index 9fa294a..2a57bc6 100644 (file)
@@ -22,7 +22,7 @@
 
 struct sir_fsm {
        struct semaphore        sem;
-       struct work_struct      work;
+       struct delayed_work     work;
        unsigned                state, substate;
        int                     param;
        int                     result;
index 3b5854d..17b0c3a 100644 (file)
@@ -100,9 +100,9 @@ static int sirdev_tx_complete_fsm(struct sir_dev *dev)
  * Both must be unlocked/restarted on completion - but only on final exit.
  */
 
-static void sirdev_config_fsm(void *data)
+static void sirdev_config_fsm(struct work_struct *work)
 {
-       struct sir_dev *dev = data;
+       struct sir_dev *dev = container_of(work, struct sir_dev, fsm.work.work);
        struct sir_fsm *fsm = &dev->fsm;
        int next_state;
        int ret = -1;
@@ -309,8 +309,8 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
        fsm->param = param;
        fsm->result = 0;
 
-       INIT_WORK(&fsm->work, sirdev_config_fsm, dev);
-       queue_work(irda_sir_wq, &fsm->work);
+       INIT_DELAYED_WORK(&fsm->work, sirdev_config_fsm);
+       queue_delayed_work(irda_sir_wq, &fsm->work, 0);
        return 0;
 }
 
index 3b4c478..c14a746 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/usb.h>
 #include <linux/crc32.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 #include <net/irda/irda.h>
 #include <net/irda/irlap.h>
 #include <net/irda/irda_device.h>
index 2284e2c..d6f4f18 100644 (file)
@@ -166,7 +166,7 @@ struct veth_msg {
 
 struct veth_lpar_connection {
        HvLpIndex remote_lp;
-       struct work_struct statemachine_wq;
+       struct delayed_work statemachine_wq;
        struct veth_msg *msgs;
        int num_events;
        struct veth_cap_data local_caps;
@@ -456,7 +456,7 @@ static struct kobj_type veth_port_ktype = {
 
 static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx)
 {
-       schedule_work(&cnx->statemachine_wq);
+       schedule_delayed_work(&cnx->statemachine_wq, 0);
 }
 
 static void veth_take_cap(struct veth_lpar_connection *cnx,
@@ -638,9 +638,11 @@ static int veth_process_caps(struct veth_lpar_connection *cnx)
 }
 
 /* FIXME: The gotos here are a bit dubious */
-static void veth_statemachine(void *p)
+static void veth_statemachine(struct work_struct *work)
 {
-       struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)p;
+       struct veth_lpar_connection *cnx =
+               container_of(work, struct veth_lpar_connection,
+                            statemachine_wq.work);
        int rlp = cnx->remote_lp;
        int rc;
 
@@ -827,7 +829,7 @@ static int veth_init_connection(u8 rlp)
 
        cnx->remote_lp = rlp;
        spin_lock_init(&cnx->lock);
-       INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx);
+       INIT_DELAYED_WORK(&cnx->statemachine_wq, veth_statemachine);
 
        init_timer(&cnx->ack_timer);
        cnx->ack_timer.function = veth_timed_ack;
index 7b12721..e628126 100644 (file)
@@ -106,7 +106,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
 void ixgb_set_ethtool_ops(struct net_device *netdev);
 static void ixgb_tx_timeout(struct net_device *dev);
-static void ixgb_tx_timeout_task(struct net_device *dev);
+static void ixgb_tx_timeout_task(struct work_struct *work);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
                                  struct vlan_group *grp);
 static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
@@ -489,8 +489,7 @@ ixgb_probe(struct pci_dev *pdev,
        adapter->watchdog_timer.function = &ixgb_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
 
-       INIT_WORK(&adapter->tx_timeout_task,
-                 (void (*)(void *))ixgb_tx_timeout_task, netdev);
+       INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task);
 
        strcpy(netdev->name, "eth%d");
        if((err = register_netdev(netdev)))
@@ -1493,9 +1492,10 @@ ixgb_tx_timeout(struct net_device *netdev)
 }
 
 static void
-ixgb_tx_timeout_task(struct net_device *netdev)
+ixgb_tx_timeout_task(struct work_struct *work)
 {
-       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       struct ixgb_adapter *adapter =
+               container_of(work, struct ixgb_adapter, tx_timeout_task);
 
        adapter->tx_timeout_count++;
        ixgb_down(adapter, TRUE);
index 4256c13..a384332 100644 (file)
@@ -368,7 +368,7 @@ static void cleanup_card(struct net_device *dev)
        kfree(lp);
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index f4d815b..ea392f2 100644 (file)
 #define DEB(x,y)       if (i596_debug & (x)) { y; }
 
 
-#define  CHECK_WBACK(addr,len) \
-       do { dma_cache_sync((void *)addr, len, DMA_TO_DEVICE); } while (0)
+#define  CHECK_WBACK(priv, addr,len) \
+       do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
 
-#define  CHECK_INV(addr,len) \
-       do { dma_cache_sync((void *)addr, len, DMA_FROM_DEVICE); } while(0)
+#define  CHECK_INV(priv, addr,len) \
+       do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
 
-#define  CHECK_WBACK_INV(addr,len) \
-       do { dma_cache_sync((void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
+#define  CHECK_WBACK_INV(priv, addr,len) \
+       do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
 
 
 #define PA_I82596_RESET                0       /* Offsets relative to LASI-LAN-Addr.*/
@@ -449,10 +449,10 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
 
 static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
 {
-       CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp));
+       CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
        while (--delcnt && lp->iscp.stat) {
                udelay(10);
-               CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp));
+               CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
        }
        if (!delcnt) {
                printk("%s: %s, iscp.stat %04x, didn't clear\n",
@@ -466,10 +466,10 @@ static inline int wait_istat(struct net_device *dev, struct i596_private *lp, in
 
 static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
 {
-       CHECK_INV(&(lp->scb), sizeof(struct i596_scb));
+       CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
        while (--delcnt && lp->scb.command) {
                udelay(10);
-               CHECK_INV(&(lp->scb), sizeof(struct i596_scb));
+               CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
        }
        if (!delcnt) {
                printk("%s: %s, status %4.4x, cmd %4.4x.\n",
@@ -522,7 +522,7 @@ static void i596_display_data(struct net_device *dev)
                        rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
                rbd = rbd->v_next;
        } while (rbd != lp->rbd_head);
-       CHECK_INV(lp, sizeof(struct i596_private));
+       CHECK_INV(lp, lp, sizeof(struct i596_private));
 }
 
 
@@ -592,7 +592,7 @@ static inline void init_rx_bufs(struct net_device *dev)
        rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
        rfd->cmd = CMD_EOL|CMD_FLEX;
 
-       CHECK_WBACK_INV(lp, sizeof(struct i596_private));
+       CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
 }
 
 static inline void remove_rx_bufs(struct net_device *dev)
@@ -629,7 +629,7 @@ static void rebuild_rx_bufs(struct net_device *dev)
        lp->rbd_head = lp->rbds;
        lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
 
-       CHECK_WBACK_INV(lp, sizeof(struct i596_private));
+       CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
 }
 
 
@@ -663,8 +663,8 @@ static int init_i596_mem(struct net_device *dev)
 
        DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
 
-       CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp));
-       CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp));
+       CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
+       CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
 
        MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
 
@@ -678,25 +678,25 @@ static int init_i596_mem(struct net_device *dev)
        rebuild_rx_bufs(dev);
 
        lp->scb.command = 0;
-       CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
 
        enable_irq(dev->irq);   /* enable IRQs from LAN */
 
        DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
        memcpy(lp->cf_cmd.i596_config, init_setup, 14);
        lp->cf_cmd.cmd.command = CmdConfigure;
-       CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd));
+       CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
        i596_add_cmd(dev, &lp->cf_cmd.cmd);
 
        DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
        memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
        lp->sa_cmd.cmd.command = CmdSASetup;
-       CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd));
+       CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
        i596_add_cmd(dev, &lp->sa_cmd.cmd);
 
        DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
        lp->tdr_cmd.cmd.command = CmdTDR;
-       CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd));
+       CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
        i596_add_cmd(dev, &lp->tdr_cmd.cmd);
 
        spin_lock_irqsave (&lp->lock, flags);
@@ -708,7 +708,7 @@ static int init_i596_mem(struct net_device *dev)
        DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
        lp->scb.command = RX_START;
        lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-       CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
 
        CA(dev);
 
@@ -740,13 +740,13 @@ static inline int i596_rx(struct net_device *dev)
 
        rfd = lp->rfd_head;             /* Ref next frame to check */
 
-       CHECK_INV(rfd, sizeof(struct i596_rfd));
+       CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
        while ((rfd->stat) & STAT_C) {  /* Loop while complete frames */
                if (rfd->rbd == I596_NULL)
                        rbd = NULL;
                else if (rfd->rbd == lp->rbd_head->b_addr) {
                        rbd = lp->rbd_head;
-                       CHECK_INV(rbd, sizeof(struct i596_rbd));
+                       CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
                }
                else {
                        printk("%s: rbd chain broken!\n", dev->name);
@@ -790,7 +790,7 @@ static inline int i596_rx(struct net_device *dev)
                                dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
                                rbd->v_data = newskb->data;
                                rbd->b_data = WSWAPchar(dma_addr);
-                               CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));
+                               CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
                        }
                        else
                                skb = dev_alloc_skb(pkt_len + 2);
@@ -842,7 +842,7 @@ memory_squeeze:
                if (rbd != NULL && (rbd->count & 0x4000)) {
                        rbd->count = 0;
                        lp->rbd_head = rbd->v_next;
-                       CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));
+                       CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
                }
 
                /* Tidy the frame descriptor, marking it as end of list */
@@ -860,10 +860,10 @@ memory_squeeze:
 
                lp->scb.rfd = rfd->b_next;
                lp->rfd_head = rfd->v_next;
-               CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd));
-               CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd));
+               CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
+               CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
                rfd = lp->rfd_head;
-               CHECK_INV(rfd, sizeof(struct i596_rfd));
+               CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
        }
 
        DEB(DEB_RXFRAME, printk("frames %d\n", frames));
@@ -902,12 +902,12 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private
                        ptr->v_next = NULL;
                        ptr->b_next = I596_NULL;
                }
-               CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd));
+               CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
        }
 
        wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
        lp->scb.cmd = I596_NULL;
-       CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
 }
 
 
@@ -925,7 +925,7 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
 
        /* FIXME: this command might cause an lpmc */
        lp->scb.command = CUC_ABORT | RX_ABORT;
-       CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
        CA(dev);
 
        /* wait for shutdown */
@@ -951,20 +951,20 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
        cmd->command |= (CMD_EOL | CMD_INTR);
        cmd->v_next = NULL;
        cmd->b_next = I596_NULL;
-       CHECK_WBACK(cmd, sizeof(struct i596_cmd));
+       CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
 
        spin_lock_irqsave (&lp->lock, flags);
 
        if (lp->cmd_head != NULL) {
                lp->cmd_tail->v_next = cmd;
                lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
-               CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd));
+               CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
        } else {
                lp->cmd_head = cmd;
                wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
                lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
                lp->scb.command = CUC_START;
-               CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+               CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
                CA(dev);
        }
        lp->cmd_tail = cmd;
@@ -998,12 +998,12 @@ static int i596_test(struct net_device *dev)
        data = virt_to_dma(lp,tint);
 
        tint[1] = -1;
-       CHECK_WBACK(tint,PAGE_SIZE);
+       CHECK_WBACK(lp, tint, PAGE_SIZE);
 
        MPU_PORT(dev, 1, data);
 
        for(data = 1000000; data; data--) {
-               CHECK_INV(tint,PAGE_SIZE);
+               CHECK_INV(lp, tint, PAGE_SIZE);
                if(tint[1] != -1)
                        break;
 
@@ -1061,7 +1061,7 @@ static void i596_tx_timeout (struct net_device *dev)
                /* Issue a channel attention signal */
                DEB(DEB_ERRORS, printk("Kicking board.\n"));
                lp->scb.command = CUC_START | RX_START;
-               CHECK_WBACK_INV(&(lp->scb), sizeof(struct i596_scb));
+               CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
                CA (dev);
                lp->last_restart = lp->stats.tx_packets;
        }
@@ -1118,8 +1118,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
                tbd->data = WSWAPchar(tx_cmd->dma_addr);
 
                DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
-               CHECK_WBACK_INV(tx_cmd, sizeof(struct tx_cmd));
-               CHECK_WBACK_INV(tbd, sizeof(struct i596_tbd));
+               CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
+               CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
                i596_add_cmd(dev, &tx_cmd->cmd);
 
                lp->stats.tx_packets++;
@@ -1228,7 +1228,7 @@ static int __devinit i82596_probe(struct net_device *dev,
        lp->dma_addr = dma_addr;
        lp->dev = gen_dev;
 
-       CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private));
+       CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
 
        i = register_netdev(dev);
        if (i) {
@@ -1295,7 +1295,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
                        DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
 
                while (lp->cmd_head != NULL) {
-                       CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd));
+                       CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
                        if (!(lp->cmd_head->status & STAT_C))
                                break;
 
@@ -1358,7 +1358,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
                        }
                        ptr->v_next = NULL;
                        ptr->b_next = I596_NULL;
-                       CHECK_WBACK(ptr, sizeof(struct i596_cmd));
+                       CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
                        lp->last_cmd = jiffies;
                }
 
@@ -1372,13 +1372,13 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
 
                        ptr->command &= 0x1fff;
                        ptr = ptr->v_next;
-                       CHECK_WBACK_INV(prev, sizeof(struct i596_cmd));
+                       CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
                }
 
                if ((lp->cmd_head != NULL))
                        ack_cmd |= CUC_START;
                lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
-               CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb));
+               CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
        }
        if ((status & 0x1000) || (status & 0x4000)) {
                if ((status & 0x4000))
@@ -1397,7 +1397,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
        }
        wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
        lp->scb.command = ack_cmd;
-       CHECK_WBACK(&lp->scb, sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
 
        /* DANGER: I suspect that some kind of interrupt
         acknowledgement aside from acking the 82596 might be needed
@@ -1426,7 +1426,7 @@ static int i596_close(struct net_device *dev)
 
        wait_cmd(dev, lp, 100, "close1 timed out");
        lp->scb.command = CUC_ABORT | RX_ABORT;
-       CHECK_WBACK(&lp->scb, sizeof(struct i596_scb));
+       CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
 
        CA(dev);
 
@@ -1486,7 +1486,7 @@ static void set_multicast_list(struct net_device *dev)
                               dev->name);
                else {
                        lp->cf_cmd.cmd.command = CmdConfigure;
-                       CHECK_WBACK_INV(&lp->cf_cmd, sizeof(struct cf_cmd));
+                       CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
                        i596_add_cmd(dev, &lp->cf_cmd.cmd);
                }
        }
@@ -1514,7 +1514,7 @@ static void set_multicast_list(struct net_device *dev)
                                DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
                                                dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
                }
-               CHECK_WBACK_INV(&lp->mc_cmd, sizeof(struct mc_cmd));
+               CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
                i596_add_cmd(dev, &cmd->cmd);
        }
 }
index 5795ee1..0a08d0c 100644 (file)
@@ -440,7 +440,7 @@ static void cleanup_card(struct net_device *dev)
        iounmap(ei_status.mem);
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index bd0ce98..25b559b 100644 (file)
@@ -264,12 +264,12 @@ static void macb_update_stats(struct macb *bp)
        WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
 
        for(; p < end; p++, reg++)
-               *p += readl(reg);
+               *p += __raw_readl(reg);
 }
 
-static void macb_periodic_task(void *arg)
+static void macb_periodic_task(struct work_struct *work)
 {
-       struct macb *bp = arg;
+       struct macb *bp = container_of(work, struct macb, periodic_task.work);
 
        macb_update_stats(bp);
        macb_check_media(bp, 1, 0);
@@ -1088,7 +1088,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
 
        dev->base_addr = regs->start;
 
-       INIT_WORK(&bp->periodic_task, macb_periodic_task, bp);
+       INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
        mutex_init(&bp->mdio_mutex);
        init_completion(&bp->mdio_complete);
 
index 8c253db..27bf0ae 100644 (file)
 
 /* Register access macros */
 #define macb_readl(port,reg)                           \
-       readl((port)->regs + MACB_##reg)
+       __raw_readl((port)->regs + MACB_##reg)
 #define macb_writel(port,reg,value)                    \
-       writel((value), (port)->regs + MACB_##reg)
+       __raw_writel((value), (port)->regs + MACB_##reg)
 
 struct dma_desc {
        u32     addr;
@@ -377,7 +377,7 @@ struct macb {
 
        unsigned int            rx_pending, tx_pending;
 
-       struct work_struct      periodic_task;
+       struct delayed_work     periodic_task;
 
        struct mutex            mdio_mutex;
        struct completion       mdio_complete;
index 9997081..c41ae42 100644 (file)
@@ -277,9 +277,11 @@ static void mv643xx_eth_tx_timeout(struct net_device *dev)
  *
  * Actual routine to reset the adapter when a timeout on Tx has occurred
  */
-static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
+static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
 {
-       struct mv643xx_private *mp = netdev_priv(dev);
+       struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private,
+                                                 tx_timeout_task);
+       struct net_device *dev = mp->mii.dev; /* yuck */
 
        if (!netif_running(dev))
                return;
@@ -1098,7 +1100,7 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp,
                                         ETH_TX_ENABLE_INTERRUPT;
                        mp->tx_skb[tx_index] = skb;
                } else
-                       mp->tx_skb[tx_index] = 0;
+                       mp->tx_skb[tx_index] = NULL;
 
                desc = &mp->p_tx_desc_area[tx_index];
                desc->l4i_chk = 0;
@@ -1134,7 +1136,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
                eth_tx_fill_frag_descs(mp, skb);
 
                length = skb_headlen(skb);
-               mp->tx_skb[tx_index] = 0;
+               mp->tx_skb[tx_index] = NULL;
        } else {
                cmd_sts |= ETH_ZERO_PADDING |
                           ETH_TX_LAST_DESC |
@@ -1360,8 +1362,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 #endif
 
        /* Configure the timeout task */
-       INIT_WORK(&mp->tx_timeout_task,
-                       (void (*)(void *))mv643xx_eth_tx_timeout_task, dev);
+       INIT_WORK(&mp->tx_timeout_task, mv643xx_eth_tx_timeout_task);
 
        spin_lock_init(&mp->lock);
 
index 56a82d8..e246d00 100644 (file)
@@ -184,7 +184,7 @@ static int m147lance_close(struct net_device *dev)
 MODULE_LICENSE("GPL");
 
 static struct net_device *dev_mvme147_lance;
-int init_module(void)
+int __init init_module(void)
 {
        dev_mvme147_lance = mvme147lance_probe(-1);
        if (IS_ERR(dev_mvme147_lance))
@@ -192,7 +192,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        struct m147lance_private *lp = dev_mvme147_lance->priv;
        unregister_netdev(dev_mvme147_lance);
index 36350e6..94ac168 100644 (file)
@@ -71,7 +71,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.0.0"
+#define MYRI10GE_VERSION_STR "1.1.0"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -89,11 +89,16 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define MYRI10GE_EEPROM_STRINGS_SIZE 256
 #define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
 
-#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
+#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
 #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
 
+#define MYRI10GE_ALLOC_ORDER 0
+#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
+#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
+
 struct myri10ge_rx_buffer_state {
-       struct sk_buff *skb;
+       struct page *page;
+       int page_offset;
         DECLARE_PCI_UNMAP_ADDR(bus)
         DECLARE_PCI_UNMAP_LEN(len)
 };
@@ -116,9 +121,14 @@ struct myri10ge_rx_buf {
        u8 __iomem *wc_fifo;    /* w/c rx dma addr fifo address */
        struct mcp_kreq_ether_recv *shadow;     /* host shadow of recv ring */
        struct myri10ge_rx_buffer_state *info;
+       struct page *page;
+       dma_addr_t bus;
+       int page_offset;
        int cnt;
+       int fill_cnt;
        int alloc_fail;
        int mask;               /* number of rx slots -1 */
+       int watchdog_needed;
 };
 
 struct myri10ge_tx_buf {
@@ -150,14 +160,15 @@ struct myri10ge_priv {
        struct myri10ge_rx_buf rx_big;
        struct myri10ge_rx_done rx_done;
        int small_bytes;
+       int big_bytes;
        struct net_device *dev;
        struct net_device_stats stats;
        u8 __iomem *sram;
        int sram_size;
        unsigned long board_span;
        unsigned long iomem_base;
-       u32 __iomem *irq_claim;
-       u32 __iomem *irq_deassert;
+       __be32 __iomem *irq_claim;
+       __be32 __iomem *irq_deassert;
        char *mac_addr_string;
        struct mcp_cmd_response *cmd;
        dma_addr_t cmd_bus;
@@ -165,10 +176,10 @@ struct myri10ge_priv {
        dma_addr_t fw_stats_bus;
        struct pci_dev *pdev;
        int msi_enabled;
-       unsigned int link_state;
+       __be32 link_state;
        unsigned int rdma_tags_available;
        int intr_coal_delay;
-       u32 __iomem *intr_coal_delay_ptr;
+       __be32 __iomem *intr_coal_delay_ptr;
        int mtrr;
        int wake_queue;
        int stop_queue;
@@ -238,11 +249,6 @@ module_param(myri10ge_force_firmware, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_force_firmware,
                 "Force firmware to assume aligned completions\n");
 
-static int myri10ge_skb_cross_4k = 0;
-module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(myri10ge_skb_cross_4k,
-                "Can a small skb cross a 4KB boundary?\n");
-
 static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
 module_param(myri10ge_initial_mtu, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
@@ -266,6 +272,10 @@ static int myri10ge_debug = -1;    /* defaults above */
 module_param(myri10ge_debug, int, 0);
 MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
+static int myri10ge_fill_thresh = 256;
+module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
+
 #define MYRI10GE_FW_OFFSET 1024*1024
 #define MYRI10GE_HIGHPART_TO_U32(X) \
 (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -273,6 +283,11 @@ MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
 #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
 
+static inline void put_be32(__be32 val, __be32 __iomem * p)
+{
+       __raw_writel((__force __u32) val, (__force void __iomem *)p);
+}
+
 static int
 myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                  struct myri10ge_cmd *data, int atomic)
@@ -296,7 +311,7 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
 
        buf->response_addr.low = htonl(dma_low);
        buf->response_addr.high = htonl(dma_high);
-       response->result = MYRI10GE_NO_RESPONSE_RESULT;
+       response->result = htonl(MYRI10GE_NO_RESPONSE_RESULT);
        mb();
        myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
 
@@ -311,14 +326,14 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                 * (1ms will be enough for those commands) */
                for (sleep_total = 0;
                     sleep_total < 1000
-                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);
                     sleep_total += 10)
                        udelay(10);
        } else {
                /* use msleep for most command */
                for (sleep_total = 0;
                     sleep_total < 15
-                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);
                     sleep_total++)
                        msleep(1);
        }
@@ -393,7 +408,7 @@ abort:
 static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
 {
        char __iomem *submit;
-       u32 buf[16];
+       __be32 buf[16];
        u32 dma_low, dma_high;
        int i;
 
@@ -410,7 +425,7 @@ static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
 
        buf[0] = htonl(dma_high);       /* confirm addr MSW */
        buf[1] = htonl(dma_low);        /* confirm addr LSW */
-       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+       buf[2] = MYRI10GE_NO_CONFIRM_DATA;      /* confirm data */
        buf[3] = htonl(dma_high);       /* dummy addr MSW */
        buf[4] = htonl(dma_low);        /* dummy addr LSW */
        buf[5] = htonl(enable); /* enable? */
@@ -479,7 +494,7 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
        }
 
        /* check id */
-       hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
+       hdr_offset = ntohl(*(__be32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
        if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
                dev_err(dev, "Bad firmware file\n");
                status = -EINVAL;
@@ -550,7 +565,7 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
 static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
 {
        char __iomem *submit;
-       u32 buf[16];
+       __be32 buf[16];
        u32 dma_low, dma_high, size;
        int status, i;
 
@@ -600,7 +615,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
 
        buf[0] = htonl(dma_high);       /* confirm addr MSW */
        buf[1] = htonl(dma_low);        /* confirm addr LSW */
-       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+       buf[2] = MYRI10GE_NO_CONFIRM_DATA;      /* confirm data */
 
        /* FIX: All newest firmware should un-protect the bottom of
         * the sram before handoff. However, the very first interfaces
@@ -705,21 +720,21 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
 
        status |=
            myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
-       mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0);
+       mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0);
        if (!mgp->msi_enabled) {
                status |= myri10ge_send_cmd
                    (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
-               mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0);
+               mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
 
        }
        status |= myri10ge_send_cmd
            (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
-       mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0);
+       mgp->intr_coal_delay_ptr = (__iomem __be32 *) (mgp->sram + cmd.data0);
        if (status != 0) {
                dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n");
                return status;
        }
-       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+       put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
 
        /* Run a small DMA test.
         * The magic multipliers to the length tell the firmware
@@ -786,216 +801,202 @@ static inline void
 myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
                    struct mcp_kreq_ether_recv *src)
 {
-       u32 low;
+       __be32 low;
 
        low = src->addr_low;
-       src->addr_low = DMA_32BIT_MASK;
-       myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
+       src->addr_low = htonl(DMA_32BIT_MASK);
+       myri10ge_pio_copy(dst, src, 4 * sizeof(*src));
+       mb();
+       myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof(*src));
        mb();
        src->addr_low = low;
-       __raw_writel(low, &dst->addr_low);
+       put_be32(low, &dst->addr_low);
        mb();
 }
 
-/*
- * Set of routines to get a new receive buffer.  Any buffer which
- * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
- * wdma restrictions. We also try to align any smaller allocation to
- * at least a 16 byte boundary for efficiency.  We assume the linux
- * memory allocator works by powers of 2, and will not return memory
- * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
- * back to allocating 2x as much space as required.
- *
- * We intend to replace large (>4KB) skb allocations by using
- * pages directly and building a fraglist in the near future.
- */
-
-static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev,
-                                                int bytes)
-{
-       struct sk_buff *skb;
-       unsigned long data, roundup;
-
-       skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD);
-       if (skb == NULL)
-               return NULL;
-
-       /* Correct skb->truesize so that socket buffer
-        * accounting is not confused the rounding we must
-        * do to satisfy alignment constraints.
-        */
-       skb->truesize -= 4096;
-
-       data = (unsigned long)(skb->data);
-       roundup = (-data) & (4095);
-       skb_reserve(skb, roundup);
-       return skb;
-}
-
-/* Allocate 2x as much space as required and use whichever portion
- * does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev,
-                                                       unsigned int bytes)
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
 {
-       struct sk_buff *skb;
-       unsigned long data, boundary;
-
-       skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1);
-       if (unlikely(skb == NULL))
-               return NULL;
-
-       /* Correct skb->truesize so that socket buffer
-        * accounting is not confused the rounding we must
-        * do to satisfy alignment constraints.
-        */
-       skb->truesize -= bytes + MXGEFW_PAD;
-
-       data = (unsigned long)(skb->data);
-       boundary = (data + 4095UL) & ~4095UL;
-       if ((boundary - data) >= (bytes + MXGEFW_PAD))
-               return skb;
+       struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
 
-       skb_reserve(skb, boundary - data);
-       return skb;
+       if ((skb->protocol == htons(ETH_P_8021Q)) &&
+           (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
+            vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
+               skb->csum = hw_csum;
+               skb->ip_summed = CHECKSUM_COMPLETE;
+       }
 }
 
-/* Allocate just enough space, and verify that the allocated
- * space does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev,
-                                                  int bytes)
+static inline void
+myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
+                     struct skb_frag_struct *rx_frags, int len, int hlen)
 {
-       struct sk_buff *skb;
-       unsigned long roundup, data, end;
-
-       skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD);
-       if (unlikely(skb == NULL))
-               return NULL;
-
-       /* Round allocated buffer to 16 byte boundary */
-       data = (unsigned long)(skb->data);
-       roundup = (-data) & 15UL;
-       skb_reserve(skb, roundup);
-       /* Verify that the data buffer does not cross a page boundary */
-       data = (unsigned long)(skb->data);
-       end = data + bytes + MXGEFW_PAD - 1;
-       if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
-               printk(KERN_NOTICE
-                      "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
-               myri10ge_skb_cross_4k = 1;
-               dev_kfree_skb_any(skb);
-               skb = myri10ge_alloc_small_safe(dev, bytes);
-       }
-       return skb;
+       struct skb_frag_struct *skb_frags;
+
+       skb->len = skb->data_len = len;
+       skb->truesize = len + sizeof(struct sk_buff);
+       /* attach the page(s) */
+
+       skb_frags = skb_shinfo(skb)->frags;
+       while (len > 0) {
+               memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
+               len -= rx_frags->size;
+               skb_frags++;
+               rx_frags++;
+               skb_shinfo(skb)->nr_frags++;
+       }
+
+       /* pskb_may_pull is not available in irq context, but
+        * skb_pull() (for ether_pad and eth_type_trans()) requires
+        * the beginning of the packet in skb_headlen(), move it
+        * manually */
+       memcpy(skb->data, va, hlen);
+       skb_shinfo(skb)->frags[0].page_offset += hlen;
+       skb_shinfo(skb)->frags[0].size -= hlen;
+       skb->data_len -= hlen;
+       skb->tail += hlen;
+       skb_pull(skb, MXGEFW_PAD);
 }
 
-static inline int
-myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp,
-               int bytes, int idx)
+static void
+myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+                       int bytes, int watchdog)
 {
-       struct net_device *dev = mgp->dev;
-       struct pci_dev *pdev = mgp->pdev;
-       struct sk_buff *skb;
-       dma_addr_t bus;
-       int len, retval = 0;
+       struct page *page;
+       int idx;
 
-       bytes += VLAN_HLEN;     /* account for 802.1q vlan tag */
+       if (unlikely(rx->watchdog_needed && !watchdog))
+               return;
 
-       if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
-               skb = myri10ge_alloc_big(dev, bytes);
-       else if (myri10ge_skb_cross_4k)
-               skb = myri10ge_alloc_small_safe(dev, bytes);
-       else
-               skb = myri10ge_alloc_small(dev, bytes);
+       /* try to refill entire ring */
+       while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) {
+               idx = rx->fill_cnt & rx->mask;
 
-       if (unlikely(skb == NULL)) {
-               rx->alloc_fail++;
-               retval = -ENOBUFS;
-               goto done;
-       }
-
-       /* set len so that it only covers the area we
-        * need mapped for DMA */
-       len = bytes + MXGEFW_PAD;
-
-       bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
-       rx->info[idx].skb = skb;
-       pci_unmap_addr_set(&rx->info[idx], bus, bus);
-       pci_unmap_len_set(&rx->info[idx], len, len);
-       rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
-       rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
-
-done:
-       /* copy 8 descriptors (64-bytes) to the mcp at a time */
-       if ((idx & 7) == 7) {
-               if (rx->wc_fifo == NULL)
-                       myri10ge_submit_8rx(&rx->lanai[idx - 7],
-                                           &rx->shadow[idx - 7]);
-               else {
-                       mb();
-                       myri10ge_pio_copy(rx->wc_fifo,
-                                         &rx->shadow[idx - 7], 64);
+               if ((bytes < MYRI10GE_ALLOC_SIZE / 2) &&
+                   (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) {
+                       /* we can use part of previous page */
+                       get_page(rx->page);
+               } else {
+                       /* we need a new page */
+                       page =
+                           alloc_pages(GFP_ATOMIC | __GFP_COMP,
+                                       MYRI10GE_ALLOC_ORDER);
+                       if (unlikely(page == NULL)) {
+                               if (rx->fill_cnt - rx->cnt < 16)
+                                       rx->watchdog_needed = 1;
+                               return;
+                       }
+                       rx->page = page;
+                       rx->page_offset = 0;
+                       rx->bus = pci_map_page(mgp->pdev, page, 0,
+                                              MYRI10GE_ALLOC_SIZE,
+                                              PCI_DMA_FROMDEVICE);
+               }
+               rx->info[idx].page = rx->page;
+               rx->info[idx].page_offset = rx->page_offset;
+               /* note that this is the address of the start of the
+                * page */
+               pci_unmap_addr_set(&rx->info[idx], bus, rx->bus);
+               rx->shadow[idx].addr_low =
+                   htonl(MYRI10GE_LOWPART_TO_U32(rx->bus) + rx->page_offset);
+               rx->shadow[idx].addr_high =
+                   htonl(MYRI10GE_HIGHPART_TO_U32(rx->bus));
+
+               /* start next packet on a cacheline boundary */
+               rx->page_offset += SKB_DATA_ALIGN(bytes);
+               rx->fill_cnt++;
+
+               /* copy 8 descriptors to the firmware at a time */
+               if ((idx & 7) == 7) {
+                       if (rx->wc_fifo == NULL)
+                               myri10ge_submit_8rx(&rx->lanai[idx - 7],
+                                                   &rx->shadow[idx - 7]);
+                       else {
+                               mb();
+                               myri10ge_pio_copy(rx->wc_fifo,
+                                                 &rx->shadow[idx - 7], 64);
+                       }
                }
        }
-       return retval;
 }
 
-static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
+static inline void
+myri10ge_unmap_rx_page(struct pci_dev *pdev,
+                      struct myri10ge_rx_buffer_state *info, int bytes)
 {
-       struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
-
-       if ((skb->protocol == ntohs(ETH_P_8021Q)) &&
-           (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
-            vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
-               skb->csum = hw_csum;
-               skb->ip_summed = CHECKSUM_COMPLETE;
+       /* unmap the recvd page if we're the only or last user of it */
+       if (bytes >= MYRI10GE_ALLOC_SIZE / 2 ||
+           (info->page_offset + 2 * bytes) > MYRI10GE_ALLOC_SIZE) {
+               pci_unmap_page(pdev, (pci_unmap_addr(info, bus)
+                                     & ~(MYRI10GE_ALLOC_SIZE - 1)),
+                              MYRI10GE_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
        }
 }
 
-static inline unsigned long
+#define MYRI10GE_HLEN 64       /* The number of bytes to copy from a
+                                * page into an skb */
+
+static inline int
 myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
-                int bytes, int len, int csum)
+                int bytes, int len, __wsum csum)
 {
-       dma_addr_t bus;
        struct sk_buff *skb;
-       int idx, unmap_len;
+       struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
+       int i, idx, hlen, remainder;
+       struct pci_dev *pdev = mgp->pdev;
+       struct net_device *dev = mgp->dev;
+       u8 *va;
 
+       len += MXGEFW_PAD;
        idx = rx->cnt & rx->mask;
-       rx->cnt++;
+       va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
+       prefetch(va);
+       /* Fill skb_frag_struct(s) with data from our receive */
+       for (i = 0, remainder = len; remainder > 0; i++) {
+               myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
+               rx_frags[i].page = rx->info[idx].page;
+               rx_frags[i].page_offset = rx->info[idx].page_offset;
+               if (remainder < MYRI10GE_ALLOC_SIZE)
+                       rx_frags[i].size = remainder;
+               else
+                       rx_frags[i].size = MYRI10GE_ALLOC_SIZE;
+               rx->cnt++;
+               idx = rx->cnt & rx->mask;
+               remainder -= MYRI10GE_ALLOC_SIZE;
+       }
+
+       hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
 
-       /* save a pointer to the received skb */
-       skb = rx->info[idx].skb;
-       bus = pci_unmap_addr(&rx->info[idx], bus);
-       unmap_len = pci_unmap_len(&rx->info[idx], len);
+       /* allocate an skb to attach the page(s) to. */
 
-       /* try to replace the received skb */
-       if (myri10ge_getbuf(rx, mgp, bytes, idx)) {
-               /* drop the frame -- the old skbuf is re-cycled */
-               mgp->stats.rx_dropped += 1;
+       skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
+       if (unlikely(skb == NULL)) {
+               mgp->stats.rx_dropped++;
+               do {
+                       i--;
+                       put_page(rx_frags[i].page);
+               } while (i != 0);
                return 0;
        }
 
-       /* unmap the recvd skb */
-       pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
-
-       /* mcp implicitly skips 1st bytes so that packet is properly
-        * aligned */
-       skb_reserve(skb, MXGEFW_PAD);
-
-       /* set the length of the frame */
-       skb_put(skb, len);
+       /* Attach the pages to the skb, and trim off any padding */
+       myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
+       if (skb_shinfo(skb)->frags[0].size <= 0) {
+               put_page(skb_shinfo(skb)->frags[0].page);
+               skb_shinfo(skb)->nr_frags = 0;
+       }
+       skb->protocol = eth_type_trans(skb, dev);
+       skb->dev = dev;
 
-       skb->protocol = eth_type_trans(skb, mgp->dev);
        if (mgp->csum_flag) {
-               if ((skb->protocol == ntohs(ETH_P_IP)) ||
-                   (skb->protocol == ntohs(ETH_P_IPV6))) {
-                       skb->csum = ntohs((u16) csum);
+               if ((skb->protocol == htons(ETH_P_IP)) ||
+                   (skb->protocol == htons(ETH_P_IPV6))) {
+                       skb->csum = csum;
                        skb->ip_summed = CHECKSUM_COMPLETE;
                } else
-                       myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
+                       myri10ge_vlan_ip_csum(skb, csum);
        }
-
        netif_receive_skb(skb);
-       mgp->dev->last_rx = jiffies;
+       dev->last_rx = jiffies;
        return 1;
 }
 
@@ -1060,19 +1061,19 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
        int idx = rx_done->idx;
        int cnt = rx_done->cnt;
        u16 length;
-       u16 checksum;
+       __wsum checksum;
 
        while (rx_done->entry[idx].length != 0 && *limit != 0) {
                length = ntohs(rx_done->entry[idx].length);
                rx_done->entry[idx].length = 0;
-               checksum = ntohs(rx_done->entry[idx].checksum);
+               checksum = csum_unfold(rx_done->entry[idx].checksum);
                if (length <= mgp->small_bytes)
                        rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small,
                                                 mgp->small_bytes,
                                                 length, checksum);
                else
                        rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
-                                                mgp->dev->mtu + ETH_HLEN,
+                                                mgp->big_bytes,
                                                 length, checksum);
                rx_packets += rx_ok;
                rx_bytes += rx_ok * (unsigned long)length;
@@ -1087,6 +1088,14 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
        rx_done->cnt = cnt;
        mgp->stats.rx_packets += rx_packets;
        mgp->stats.rx_bytes += rx_bytes;
+
+       /* restock receive rings if needed */
+       if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh)
+               myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+                                       mgp->small_bytes + MXGEFW_PAD, 0);
+       if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh)
+               myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+
 }
 
 static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
@@ -1142,7 +1151,7 @@ static int myri10ge_poll(struct net_device *netdev, int *budget)
 
        if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
                netif_rx_complete(netdev);
-               __raw_writel(htonl(3), mgp->irq_claim);
+               put_be32(htonl(3), mgp->irq_claim);
                return 0;
        }
        return 1;
@@ -1166,7 +1175,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
                netif_rx_schedule(mgp->dev);
 
        if (!mgp->msi_enabled) {
-               __raw_writel(0, mgp->irq_deassert);
+               put_be32(0, mgp->irq_deassert);
                if (!myri10ge_deassert_wait)
                        stats->valid = 0;
                mb();
@@ -1195,7 +1204,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
 
        myri10ge_check_statblock(mgp);
 
-       __raw_writel(htonl(3), mgp->irq_claim + 1);
+       put_be32(htonl(3), mgp->irq_claim + 1);
        return (IRQ_HANDLED);
 }
 
@@ -1233,7 +1242,7 @@ myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
        struct myri10ge_priv *mgp = netdev_priv(netdev);
 
        mgp->intr_coal_delay = coal->rx_coalesce_usecs;
-       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+       put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
        return 0;
 }
 
@@ -1477,56 +1486,48 @@ static int myri10ge_allocate_rings(struct net_device *dev)
                goto abort_with_rx_small_info;
 
        /* Fill the receive rings */
+       mgp->rx_big.cnt = 0;
+       mgp->rx_small.cnt = 0;
+       mgp->rx_big.fill_cnt = 0;
+       mgp->rx_small.fill_cnt = 0;
+       mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE;
+       mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
+       mgp->rx_small.watchdog_needed = 0;
+       mgp->rx_big.watchdog_needed = 0;
+       myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+                               mgp->small_bytes + MXGEFW_PAD, 0);
 
-       for (i = 0; i <= mgp->rx_small.mask; i++) {
-               status = myri10ge_getbuf(&mgp->rx_small, mgp,
-                                        mgp->small_bytes, i);
-               if (status) {
-                       printk(KERN_ERR
-                              "myri10ge: %s: alloced only %d small bufs\n",
-                              dev->name, i);
-                       goto abort_with_rx_small_ring;
-               }
+       if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) {
+               printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n",
+                      dev->name, mgp->rx_small.fill_cnt);
+               goto abort_with_rx_small_ring;
        }
 
-       for (i = 0; i <= mgp->rx_big.mask; i++) {
-               status =
-                   myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i);
-               if (status) {
-                       printk(KERN_ERR
-                              "myri10ge: %s: alloced only %d big bufs\n",
-                              dev->name, i);
-                       goto abort_with_rx_big_ring;
-               }
+       myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+       if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) {
+               printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n",
+                      dev->name, mgp->rx_big.fill_cnt);
+               goto abort_with_rx_big_ring;
        }
 
        return 0;
 
 abort_with_rx_big_ring:
-       for (i = 0; i <= mgp->rx_big.mask; i++) {
-               if (mgp->rx_big.info[i].skb != NULL)
-                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
-               if (pci_unmap_len(&mgp->rx_big.info[i], len))
-                       pci_unmap_single(mgp->pdev,
-                                        pci_unmap_addr(&mgp->rx_big.info[i],
-                                                       bus),
-                                        pci_unmap_len(&mgp->rx_big.info[i],
-                                                      len),
-                                        PCI_DMA_FROMDEVICE);
+       for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+               int idx = i & mgp->rx_big.mask;
+               myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+                                      mgp->big_bytes);
+               put_page(mgp->rx_big.info[idx].page);
        }
 
 abort_with_rx_small_ring:
-       for (i = 0; i <= mgp->rx_small.mask; i++) {
-               if (mgp->rx_small.info[i].skb != NULL)
-                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
-               if (pci_unmap_len(&mgp->rx_small.info[i], len))
-                       pci_unmap_single(mgp->pdev,
-                                        pci_unmap_addr(&mgp->rx_small.info[i],
-                                                       bus),
-                                        pci_unmap_len(&mgp->rx_small.info[i],
-                                                      len),
-                                        PCI_DMA_FROMDEVICE);
+       for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+               int idx = i & mgp->rx_small.mask;
+               myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+                                      mgp->small_bytes + MXGEFW_PAD);
+               put_page(mgp->rx_small.info[idx].page);
        }
+
        kfree(mgp->rx_big.info);
 
 abort_with_rx_small_info:
@@ -1559,30 +1560,24 @@ static void myri10ge_free_rings(struct net_device *dev)
 
        mgp = netdev_priv(dev);
 
-       for (i = 0; i <= mgp->rx_big.mask; i++) {
-               if (mgp->rx_big.info[i].skb != NULL)
-                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
-               if (pci_unmap_len(&mgp->rx_big.info[i], len))
-                       pci_unmap_single(mgp->pdev,
-                                        pci_unmap_addr(&mgp->rx_big.info[i],
-                                                       bus),
-                                        pci_unmap_len(&mgp->rx_big.info[i],
-                                                      len),
-                                        PCI_DMA_FROMDEVICE);
-       }
-
-       for (i = 0; i <= mgp->rx_small.mask; i++) {
-               if (mgp->rx_small.info[i].skb != NULL)
-                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
-               if (pci_unmap_len(&mgp->rx_small.info[i], len))
-                       pci_unmap_single(mgp->pdev,
-                                        pci_unmap_addr(&mgp->rx_small.info[i],
-                                                       bus),
-                                        pci_unmap_len(&mgp->rx_small.info[i],
-                                                      len),
-                                        PCI_DMA_FROMDEVICE);
+       for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+               idx = i & mgp->rx_big.mask;
+               if (i == mgp->rx_big.fill_cnt - 1)
+                       mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE;
+               myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+                                      mgp->big_bytes);
+               put_page(mgp->rx_big.info[idx].page);
        }
 
+       for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+               idx = i & mgp->rx_small.mask;
+               if (i == mgp->rx_small.fill_cnt - 1)
+                       mgp->rx_small.info[idx].page_offset =
+                           MYRI10GE_ALLOC_SIZE;
+               myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+                                      mgp->small_bytes + MXGEFW_PAD);
+               put_page(mgp->rx_small.info[idx].page);
+       }
        tx = &mgp->tx;
        while (tx->done != tx->req) {
                idx = tx->done & tx->mask;
@@ -1650,19 +1645,18 @@ static int myri10ge_open(struct net_device *dev)
         */
 
        if (dev->mtu <= ETH_DATA_LEN)
-               mgp->small_bytes = 128; /* enough for a TCP header */
+               /* enough for a TCP header */
+               mgp->small_bytes = (128 > SMP_CACHE_BYTES)
+                   ? (128 - MXGEFW_PAD)
+                   : (SMP_CACHE_BYTES - MXGEFW_PAD);
        else
-               mgp->small_bytes = ETH_FRAME_LEN;       /* enough for an ETH_DATA_LEN frame */
+               /* enough for a vlan encapsulated ETH_DATA_LEN frame */
+               mgp->small_bytes = VLAN_ETH_FRAME_LEN;
 
        /* Override the small buffer size? */
        if (myri10ge_small_bytes > 0)
                mgp->small_bytes = myri10ge_small_bytes;
 
-       /* If the user sets an obscenely small MTU, adjust the small
-        * bytes down to nearly nothing */
-       if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
-               mgp->small_bytes = 64;
-
        /* get the lanai pointers to the send and receive rings */
 
        status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
@@ -1698,17 +1692,23 @@ static int myri10ge_open(struct net_device *dev)
                mgp->rx_big.wc_fifo = NULL;
        }
 
-       status = myri10ge_allocate_rings(dev);
-       if (status != 0)
-               goto abort_with_nothing;
-
        /* Firmware needs the big buff size as a power of 2.  Lie and
         * tell him the buffer is larger, because we only use 1
         * buffer/pkt, and the mtu will prevent overruns.
         */
-       big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
-       while ((big_pow2 & (big_pow2 - 1)) != 0)
-               big_pow2++;
+       big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+       if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
+               while ((big_pow2 & (big_pow2 - 1)) != 0)
+                       big_pow2++;
+               mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+       } else {
+               big_pow2 = MYRI10GE_ALLOC_SIZE;
+               mgp->big_bytes = big_pow2;
+       }
+
+       status = myri10ge_allocate_rings(dev);
+       if (status != 0)
+               goto abort_with_nothing;
 
        /* now give firmware buffers sizes, and MTU */
        cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
@@ -1748,7 +1748,7 @@ static int myri10ge_open(struct net_device *dev)
                goto abort_with_rings;
        }
 
-       mgp->link_state = -1;
+       mgp->link_state = htonl(~0U);
        mgp->rdma_tags_available = 15;
 
        netif_poll_enable(mgp->dev);    /* must happen prior to any irq */
@@ -1876,7 +1876,7 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
 
        /* re-write the last 32-bits with the valid flags */
        src->flags = last_flags;
-       __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
+       put_be32(*((__be32 *) src + 3), (__be32 __iomem *) dst + 3);
        tx->req += cnt;
        mb();
 }
@@ -1919,7 +1919,8 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
        struct myri10ge_tx_buf *tx = &mgp->tx;
        struct skb_frag_struct *frag;
        dma_addr_t bus;
-       u32 low, high_swapped;
+       u32 low;
+       __be32 high_swapped;
        unsigned int len;
        int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
        u16 pseudo_hdr_offset, cksum_offset;
@@ -1964,7 +1965,6 @@ again:
                        cksum_offset = 0;
                        pseudo_hdr_offset = 0;
                } else {
-                       pseudo_hdr_offset = htons(pseudo_hdr_offset);
                        odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
                        flags |= MXGEFW_FLAGS_CKSUM;
                }
@@ -1986,7 +1986,7 @@ again:
                /* for TSO, pseudo_hdr_offset holds mss.
                 * The firmware figures out where to put
                 * the checksum by parsing the header. */
-               pseudo_hdr_offset = htons(mss);
+               pseudo_hdr_offset = mss;
        } else
 #endif                         /*NETIF_F_TSO */
                /* Mark small packets, and pad out tiny packets */
@@ -2086,7 +2086,7 @@ again:
 #endif                         /* NETIF_F_TSO */
                        req->addr_high = high_swapped;
                        req->addr_low = htonl(low);
-                       req->pseudo_hdr_offset = pseudo_hdr_offset;
+                       req->pseudo_hdr_offset = htons(pseudo_hdr_offset);
                        req->pad = 0;   /* complete solid 16-byte block; does this matter? */
                        req->rdma_count = 1;
                        req->length = htons(seglen);
@@ -2199,6 +2199,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
        struct myri10ge_cmd cmd;
        struct myri10ge_priv *mgp;
        struct dev_mc_list *mc_list;
+       __be32 data[2] = { 0, 0 };
        int err;
 
        mgp = netdev_priv(dev);
@@ -2237,10 +2238,9 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
 
        /* Walk the multicast list, and add each address */
        for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) {
-               memcpy(&cmd.data0, &mc_list->dmi_addr, 4);
-               memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2);
-               cmd.data0 = htonl(cmd.data0);
-               cmd.data1 = htonl(cmd.data1);
+               memcpy(data, &mc_list->dmi_addr, 6);
+               cmd.data0 = ntohl(data[0]);
+               cmd.data1 = ntohl(data[1]);
                err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP,
                                        &cmd, 1);
 
@@ -2615,9 +2615,10 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
  * This watchdog is used to check whether the board has suffered
  * from a parity error and needs to be recovered.
  */
-static void myri10ge_watchdog(void *arg)
+static void myri10ge_watchdog(struct work_struct *work)
 {
-       struct myri10ge_priv *mgp = arg;
+       struct myri10ge_priv *mgp =
+           container_of(work, struct myri10ge_priv, watchdog_work);
        u32 reboot;
        int status;
        u16 cmd, vendor;
@@ -2690,6 +2691,21 @@ static void myri10ge_watchdog_timer(unsigned long arg)
        struct myri10ge_priv *mgp;
 
        mgp = (struct myri10ge_priv *)arg;
+
+       if (mgp->rx_small.watchdog_needed) {
+               myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+                                       mgp->small_bytes + MXGEFW_PAD, 1);
+               if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >=
+                   myri10ge_fill_thresh)
+                       mgp->rx_small.watchdog_needed = 0;
+       }
+       if (mgp->rx_big.watchdog_needed) {
+               myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1);
+               if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >=
+                   myri10ge_fill_thresh)
+                       mgp->rx_big.watchdog_needed = 0;
+       }
+
        if (mgp->tx.req != mgp->tx.done &&
            mgp->tx.done == mgp->watchdog_tx_done &&
            mgp->watchdog_tx_req != mgp->watchdog_tx_done)
@@ -2887,7 +2903,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                    (unsigned long)mgp);
 
        SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
-       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp);
+       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
        status = register_netdev(netdev);
        if (status != 0) {
                dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
index 9519ae7..29463b3 100644 (file)
@@ -6,23 +6,23 @@
 
 /* 8 Bytes */
 struct mcp_dma_addr {
-       u32 high;
-       u32 low;
+       __be32 high;
+       __be32 low;
 };
 
 /* 4 Bytes */
 struct mcp_slot {
-       u16 checksum;
-       u16 length;
+       __sum16 checksum;
+       __be16 length;
 };
 
 /* 64 Bytes */
 struct mcp_cmd {
-       u32 cmd;
-       u32 data0;              /* will be low portion if data > 32 bits */
+       __be32 cmd;
+       __be32 data0;           /* will be low portion if data > 32 bits */
        /* 8 */
-       u32 data1;              /* will be high portion if data > 32 bits */
-       u32 data2;              /* currently unused.. */
+       __be32 data1;           /* will be high portion if data > 32 bits */
+       __be32 data2;           /* currently unused.. */
        /* 16 */
        struct mcp_dma_addr response_addr;
        /* 24 */
@@ -31,8 +31,8 @@ struct mcp_cmd {
 
 /* 8 Bytes */
 struct mcp_cmd_response {
-       u32 data;
-       u32 result;
+       __be32 data;
+       __be32 result;
 };
 
 /*
@@ -73,10 +73,10 @@ union mcp_pso_or_cumlen {
 
 /* 16 Bytes */
 struct mcp_kreq_ether_send {
-       u32 addr_high;
-       u32 addr_low;
-       u16 pseudo_hdr_offset;
-       u16 length;
+       __be32 addr_high;
+       __be32 addr_low;
+       __be16 pseudo_hdr_offset;
+       __be16 length;
        u8 pad;
        u8 rdma_count;
        u8 cksum_offset;        /* where to start computing cksum */
@@ -85,8 +85,8 @@ struct mcp_kreq_ether_send {
 
 /* 8 Bytes */
 struct mcp_kreq_ether_recv {
-       u32 addr_high;
-       u32 addr_low;
+       __be32 addr_high;
+       __be32 addr_low;
 };
 
 /* Commands */
@@ -219,19 +219,19 @@ enum myri10ge_mcp_cmd_status {
 
 struct mcp_irq_data {
        /* add new counters at the beginning */
-       u32 future_use[5];
-       u32 dropped_multicast_filtered;
+       __be32 future_use[5];
+       __be32 dropped_multicast_filtered;
        /* 40 Bytes */
-       u32 send_done_count;
-
-       u32 link_up;
-       u32 dropped_link_overflow;
-       u32 dropped_link_error_or_filtered;
-       u32 dropped_runt;
-       u32 dropped_overrun;
-       u32 dropped_no_small_buffer;
-       u32 dropped_no_big_buffer;
-       u32 rdma_tags_available;
+       __be32 send_done_count;
+
+       __be32 link_up;
+       __be32 dropped_link_overflow;
+       __be32 dropped_link_error_or_filtered;
+       __be32 dropped_runt;
+       __be32 dropped_overrun;
+       __be32 dropped_no_small_buffer;
+       __be32 dropped_no_big_buffer;
+       __be32 rdma_tags_available;
 
        u8 tx_stopped;
        u8 link_down;
index 487f779..16a810d 100644 (file)
@@ -36,7 +36,7 @@
 struct mcp_gen_header {
        /* the first 4 fields are filled at compile time */
        unsigned header_length;
-       unsigned mcp_type;
+       __be32 mcp_type;
        char version[128];
        unsigned mcp_globals;   /* pointer to mcp-type specific structure */
 
index 787aa42..a5c4199 100644 (file)
@@ -867,7 +867,7 @@ static void cleanup_card(struct net_device *dev)
        release_region(dev->base_addr, NE_IO_EXTENT);
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index 5fccfea..089b5bb 100644 (file)
@@ -813,7 +813,7 @@ static void cleanup_card(struct net_device *dev)
        release_region(dev->base_addr, NE_IO_EXTENT);
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index d925053..b5410be 100644 (file)
@@ -1,25 +1,25 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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 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.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
 
 #include "netxen_nic_hw.h"
 
-#define NETXEN_NIC_BUILD_NO     "5"
-#define _NETXEN_NIC_LINUX_MAJOR 2
+#define NETXEN_NIC_BUILD_NO     "1"
+#define _NETXEN_NIC_LINUX_MAJOR 3
 #define _NETXEN_NIC_LINUX_MINOR 3
-#define _NETXEN_NIC_LINUX_SUBVERSION 59
-#define NETXEN_NIC_LINUX_VERSIONID  "2.3.59" "-" NETXEN_NIC_BUILD_NO
-#define NETXEN_NIC_FW_VERSIONID "2.3.59"
+#define _NETXEN_NIC_LINUX_SUBVERSION 2
+#define NETXEN_NIC_LINUX_VERSIONID  "3.3.2" "-" NETXEN_NIC_BUILD_NO
+#define NETXEN_NIC_FW_VERSIONID "3.3.2"
 
 #define RCV_DESC_RINGSIZE      \
        (sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
 #define STATUS_DESC_RINGSIZE   \
        (sizeof(struct status_desc)* adapter->max_rx_desc_count)
+#define LRO_DESC_RINGSIZE      \
+       (sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count)
 #define TX_RINGSIZE    \
        (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
 #define RCV_BUFFSIZE   \
        (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
 #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
 
-#define NETXEN_NETDEV_STATUS 0x1
+#define NETXEN_NETDEV_STATUS           0x1
+#define NETXEN_RCV_PRODUCER_OFFSET     0
+#define NETXEN_RCV_PEG_DB_ID           2
+#define NETXEN_HOST_DUMMY_DMA_SIZE 1024
 
 #define ADDR_IN_WINDOW1(off)   \
        ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
+/*
+ * In netxen_nic_down(), we must wait for any pending callback requests into
+ * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
+ * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK()
+ * does this synchronization.
+ *
+ * Normally, schedule_work()/flush_scheduled_work() could have worked, but
+ * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
+ * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
+ * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
+ * linkwatch_event() to be executed which also attempts to acquire the rtnl
+ * lock thus causing a deadlock.
+ */
+
+#define SCHEDULE_WORK(tp)      queue_work(netxen_workq, tp)
+#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
+extern struct workqueue_struct *netxen_workq;
 
 /* 
  * normalize a 64MB crb address to 32MB PCI window 
  * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1
  */
-#define NETXEN_CRB_NORMAL(reg)        \
-       (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST
+#define NETXEN_CRB_NORMAL(reg) \
+       ((reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST)
 
 #define NETXEN_CRB_NORMALIZE(adapter, reg) \
        pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg))
 
+#define DB_NORMALIZE(adapter, off) \
+       (adapter->ahw.db_base + (off))
+
+#define NX_P2_C0               0x24
+#define NX_P2_C1               0x25
+
 #define FIRST_PAGE_GROUP_START 0
-#define FIRST_PAGE_GROUP_END   0x400000
+#define FIRST_PAGE_GROUP_END   0x100000
 
 #define SECOND_PAGE_GROUP_START        0x4000000
 #define SECOND_PAGE_GROUP_END  0x66BC000
 #define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
 #define THIRD_PAGE_GROUP_SIZE  THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
 
-#define MAX_RX_BUFFER_LENGTH           2000
+#define MAX_RX_BUFFER_LENGTH           1760
 #define MAX_RX_JUMBO_BUFFER_LENGTH     9046
-#define RX_DMA_MAP_LEN                 (MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN)
+#define MAX_RX_LRO_BUFFER_LENGTH       ((48*1024)-512)
+#define RX_DMA_MAP_LEN                 (MAX_RX_BUFFER_LENGTH - 2)
 #define RX_JUMBO_DMA_MAP_LEN   \
-       (MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN)
+       (MAX_RX_JUMBO_BUFFER_LENGTH - 2)
+#define RX_LRO_DMA_MAP_LEN             (MAX_RX_LRO_BUFFER_LENGTH - 2)
 #define NETXEN_ROM_ROUNDUP             0x80000000ULL
 
 /*
@@ -151,30 +181,38 @@ enum {
 /* Host writes the following to notify that it has done the init-handshake */
 #define PHAN_INITIALIZE_ACK    0xf00f
 
-#define NUM_RCV_DESC_RINGS     2       /* No of Rcv Descriptor contexts */
+#define NUM_RCV_DESC_RINGS     3       /* No of Rcv Descriptor contexts */
 
 /* descriptor types */
 #define RCV_DESC_NORMAL                0x01
 #define RCV_DESC_JUMBO         0x02
+#define RCV_DESC_LRO           0x04
 #define RCV_DESC_NORMAL_CTXID  0
 #define RCV_DESC_JUMBO_CTXID   1
+#define RCV_DESC_LRO_CTXID     2
 
 #define RCV_DESC_TYPE(ID) \
-       ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL)
+       ((ID == RCV_DESC_JUMBO_CTXID)   \
+               ? RCV_DESC_JUMBO        \
+               : ((ID == RCV_DESC_LRO_CTXID)   \
+                       ? RCV_DESC_LRO :        \
+                       (RCV_DESC_NORMAL)))
 
 #define MAX_CMD_DESCRIPTORS            1024
 #define MAX_RCV_DESCRIPTORS            32768
-#define MAX_JUMBO_RCV_DESCRIPTORS      1024
+#define MAX_JUMBO_RCV_DESCRIPTORS      4096
+#define MAX_LRO_RCV_DESCRIPTORS                2048
 #define MAX_RCVSTATUS_DESCRIPTORS      MAX_RCV_DESCRIPTORS
 #define MAX_JUMBO_RCV_DESC     MAX_JUMBO_RCV_DESCRIPTORS
 #define MAX_RCV_DESC           MAX_RCV_DESCRIPTORS
 #define MAX_RCVSTATUS_DESC     MAX_RCV_DESCRIPTORS
-#define NUM_RCV_DESC           (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS)
 #define MAX_EPG_DESCRIPTORS    (MAX_CMD_DESCRIPTORS * 8)
-
+#define NUM_RCV_DESC           (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \
+                                MAX_LRO_RCV_DESCRIPTORS)
 #define MIN_TX_COUNT   4096
 #define MIN_RX_COUNT   4096
-
+#define NETXEN_CTX_SIGNATURE   0xdee0
+#define NETXEN_RCV_PRODUCER(ringid)    (ringid)
 #define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */
 
 #define PHAN_PEG_RCV_INITIALIZED       0xff01
@@ -186,6 +224,67 @@ enum {
 #define get_index_range(index,length,count)    \
        (((index) + (count)) & ((length) - 1))
 
+#define MPORT_SINGLE_FUNCTION_MODE 0x1111
+
+extern unsigned long long netxen_dma_mask;
+
+/*
+ * NetXen host-peg signal message structure
+ *
+ *     Bit 0-1         : peg_id => 0x2 for tx and 01 for rx
+ *     Bit 2           : priv_id => must be 1
+ *     Bit 3-17        : count => for doorbell
+ *     Bit 18-27       : ctx_id => Context id
+ *     Bit 28-31       : opcode
+ */
+
+typedef u32 netxen_ctx_msg;
+
+#define _netxen_set_bits(config_word, start, bits, val)        {\
+       unsigned long long mask = (((1ULL << (bits)) - 1) << (start));  \
+       unsigned long long value = (val);       \
+       (config_word) &= ~mask; \
+       (config_word) |= (((value) << (start)) & mask); \
+}
+
+#define netxen_set_msg_peg_id(config_word, val)        \
+       _netxen_set_bits(config_word, 0, 2, val)
+#define netxen_set_msg_privid(config_word)     \
+       set_bit(2, (unsigned long*)&config_word)
+#define netxen_set_msg_count(config_word, val) \
+       _netxen_set_bits(config_word, 3, 15, val)
+#define netxen_set_msg_ctxid(config_word, val) \
+       _netxen_set_bits(config_word, 18, 10, val)
+#define netxen_set_msg_opcode(config_word, val)        \
+       _netxen_set_bits(config_word, 28, 4, val)
+
+struct netxen_rcv_context {
+       u32 rcv_ring_addr_lo;
+       u32 rcv_ring_addr_hi;
+       u32 rcv_ring_size;
+       u32 rsrvd;
+};
+
+struct netxen_ring_ctx {
+
+       /* one command ring */
+       u64 cmd_consumer_offset;
+       u32 cmd_ring_addr_lo;
+       u32 cmd_ring_addr_hi;
+       u32 cmd_ring_size;
+       u32 rsrvd;
+
+       /* three receive rings */
+       struct netxen_rcv_context rcv_ctx[3];
+
+       /* one status ring */
+       u32 sts_ring_addr_lo;
+       u32 sts_ring_addr_hi;
+       u32 sts_ring_size;
+
+       u32 ctx_id;
+} __attribute__ ((aligned(64)));
+
 /*
  * Following data structures describe the descriptors that will be used.
  * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
@@ -203,22 +302,32 @@ enum {
 #define FLAGS_IPSEC_SA_DELETE  0x08
 #define FLAGS_VLAN_TAGGED      0x10
 
-#define CMD_DESC_TOTAL_LENGTH(cmd_desc)        \
-               ((cmd_desc)->length_tcp_hdr & 0x00FFFFFF)
-#define CMD_DESC_TCP_HDR_OFFSET(cmd_desc)      \
-               (((cmd_desc)->length_tcp_hdr >> 24) & 0x0FF)
-#define CMD_DESC_PORT(cmd_desc)                ((cmd_desc)->port_ctxid & 0x0F)
-#define CMD_DESC_CTX_ID(cmd_desc)      (((cmd_desc)->port_ctxid >> 4) & 0x0F)
+#define netxen_set_cmd_desc_port(cmd_desc, var)        \
+       ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
 
-#define CMD_DESC_TOTAL_LENGTH_WRT(cmd_desc, var)       \
-               ((cmd_desc)->length_tcp_hdr |= ((var) & 0x00FFFFFF))
-#define CMD_DESC_TCP_HDR_OFFSET_WRT(cmd_desc, var)     \
-               ((cmd_desc)->length_tcp_hdr |= (((var) << 24) & 0xFF000000))
-#define CMD_DESC_PORT_WRT(cmd_desc, var)       \
-               ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
+#define netxen_set_cmd_desc_flags(cmd_desc, val)       \
+       _netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val)
+#define netxen_set_cmd_desc_opcode(cmd_desc, val)      \
+       _netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val)
+
+#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
+       _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val);
+#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
+       _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val);
+
+#define netxen_get_cmd_desc_opcode(cmd_desc)   \
+       (((cmd_desc)->flags_opcode >> 7) & 0x003F)
+#define netxen_get_cmd_desc_totallength(cmd_desc)      \
+       (((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF)
 
 struct cmd_desc_type0 {
-       u64 netxen_next;        /* for fragments handled by Phantom */
+       u8 tcp_hdr_offset;      /* For LSO only */
+       u8 ip_hdr_offset;       /* For LSO only */
+       /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
+       u16 flags_opcode;
+       /* Bit pattern: 0-7 total number of segments,
+          8-31 Total size of the packet */
+       u32 num_of_buffers_total_length;
        union {
                struct {
                        u32 addr_low_part2;
@@ -227,13 +336,6 @@ struct cmd_desc_type0 {
                u64 addr_buffer2;
        };
 
-       /* Bit pattern: 0-23 total length, 24-32 tcp header offset */
-       u32 length_tcp_hdr;
-       u8 ip_hdr_offset;       /* For LSO only */
-       u8 num_of_buffers;      /* total number of segments */
-       u8 flags;               /* as defined above */
-       u8 opcode;
-
        u16 reference_handle;   /* changed to u16 to add mss */
        u16 mss;                /* passed by NDIS_PACKET for LSO */
        /* Bit pattern 0-3 port, 0-3 ctx id */
@@ -248,7 +350,6 @@ struct cmd_desc_type0 {
                };
                u64 addr_buffer3;
        };
-
        union {
                struct {
                        u32 addr_low_part1;
@@ -270,6 +371,8 @@ struct cmd_desc_type0 {
                u64 addr_buffer4;
        };
 
+       u64 unused;
+
 } __attribute__ ((aligned(64)));
 
 /* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
@@ -296,22 +399,49 @@ struct rcv_desc {
 #define NETXEN_PROT_UNKNOWN    (0)
 
 /* Note: sizeof(status_desc) should always be a mutliple of 2 */
-#define STATUS_DESC_PORT(status_desc)  \
-               ((status_desc)->port_status_type_op & 0x0F)
-#define STATUS_DESC_STATUS(status_desc)        \
-               (((status_desc)->port_status_type_op >> 4) & 0x0F)
-#define STATUS_DESC_TYPE(status_desc)  \
-               (((status_desc)->port_status_type_op >> 8) & 0x0F)
-#define STATUS_DESC_OPCODE(status_desc)        \
-               (((status_desc)->port_status_type_op >> 12) & 0x0F)
+
+#define netxen_get_sts_desc_lro_cnt(status_desc)       \
+       ((status_desc)->lro & 0x7F)
+#define netxen_get_sts_desc_lro_last_frag(status_desc) \
+       (((status_desc)->lro & 0x80) >> 7)
+
+#define netxen_get_sts_port(status_desc)       \
+       ((status_desc)->status_desc_data & 0x0F)
+#define netxen_get_sts_status(status_desc)     \
+       (((status_desc)->status_desc_data >> 4) & 0x0F)
+#define netxen_get_sts_type(status_desc)       \
+       (((status_desc)->status_desc_data >> 8) & 0x0F)
+#define netxen_get_sts_totallength(status_desc)        \
+       (((status_desc)->status_desc_data >> 12) & 0xFFFF)
+#define netxen_get_sts_refhandle(status_desc)  \
+       (((status_desc)->status_desc_data >> 28) & 0xFFFF)
+#define netxen_get_sts_prot(status_desc)       \
+       (((status_desc)->status_desc_data >> 44) & 0x0F)
+#define netxen_get_sts_owner(status_desc)      \
+       (((status_desc)->status_desc_data >> 56) & 0x03)
+#define netxen_get_sts_opcode(status_desc)     \
+       (((status_desc)->status_desc_data >> 58) & 0x03F)
+
+#define netxen_clear_sts_owner(status_desc)    \
+       ((status_desc)->status_desc_data &=     \
+       ~(((unsigned long long)3) << 56 ))
+#define netxen_set_sts_owner(status_desc, val) \
+       ((status_desc)->status_desc_data |=     \
+       (((unsigned long long)((val) & 0x3)) << 56 ))
 
 struct status_desc {
-       /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-15 opcode */
-       u16 port_status_type_op;
-       u16 total_length;       /* NIC mode */
-       u16 reference_handle;   /* handle for the associated packet */
-       /* Bit pattern: 0-1 owner, 2-5 protocol */
-       u16 owner;              /* Owner of the descriptor */
+       /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+          28-43 reference_handle, 44-47 protocol, 48-52 unused
+          53-55 desc_cnt, 56-57 owner, 58-63 opcode
+        */
+       u64 status_desc_data;
+       u32 hash_value;
+       u8 hash_type;
+       u8 msg_type;
+       u8 unused;
+       /* Bit pattern: 0-6 lro_count indicates frag sequence,
+          7 last_frag indicates last frag */
+       u8 lro;
 } __attribute__ ((aligned(8)));
 
 enum {
@@ -559,11 +689,12 @@ typedef enum {
 #define PRIMARY_START          (BOOTLD_START)
 #define FLASH_CRBINIT_SIZE     (0x4000)
 #define FLASH_BRDCFG_SIZE      (sizeof(struct netxen_board_info))
-#define FLASH_USER_SIZE                (sizeof(netxen_user_info)/sizeof(u32))
+#define FLASH_USER_SIZE                (sizeof(struct netxen_user_info)/sizeof(u32))
 #define FLASH_SECONDARY_SIZE   (USER_START-SECONDARY_START)
 #define NUM_PRIMARY_SECTORS    (0x20)
 #define NUM_CONFIG_SECTORS     (1)
-#define PFX "netxen: "
+#define PFX "NetXen: "
+extern char netxen_nic_driver_name[];
 
 /* Note: Make sure to not call this before adapter->port is valid */
 #if !defined(NETXEN_DEBUG)
@@ -572,7 +703,7 @@ typedef enum {
 #else
 #define DPRINTK(klevel, fmt, args...)  do { \
        printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
-               (adapter != NULL && adapter->port != NULL && \
+               (adapter != NULL && \
                adapter->port[0] != NULL && \
                adapter->port[0]->netdev != NULL) ? \
                adapter->port[0]->netdev->name : NULL, \
@@ -609,7 +740,6 @@ struct netxen_cmd_buffer {
        u8 frag_count;
        unsigned long time_stamp;
        u32 state;
-       u32 no_of_descriptors;
 };
 
 /* In rx_buffer, we do not need multiple fragments as is a single buffer */
@@ -618,6 +748,9 @@ struct netxen_rx_buffer {
        u64 dma;
        u16 ref_handle;
        u16 state;
+       u32 lro_expected_frags;
+       u32 lro_current_frags;
+       u32 lro_length;
 };
 
 /* Board types */
@@ -633,6 +766,8 @@ struct netxen_hardware_context {
        void __iomem *pci_base0;
        void __iomem *pci_base1;
        void __iomem *pci_base2;
+       void __iomem *db_base;
+       unsigned long db_len;
 
        u8 revision_id;
        u16 board_type;
@@ -642,14 +777,13 @@ struct netxen_hardware_context {
        u32 qg_linksup;
        /* Address of cmd ring in Phantom */
        struct cmd_desc_type0 *cmd_desc_head;
-       char *pauseaddr;
        struct pci_dev *cmd_desc_pdev;
        dma_addr_t cmd_desc_phys_addr;
-       dma_addr_t pause_physaddr;
-       struct pci_dev *pause_pdev;
        struct netxen_adapter *adapter;
 };
 
+#define RCV_RING_LRO   RCV_DESC_LRO
+
 #define MINIMUM_ETHERNET_FRAME_SIZE    64      /* With FCS */
 #define ETHERNET_FCS_SIZE              4
 
@@ -702,8 +836,13 @@ struct netxen_recv_context {
 };
 
 #define NETXEN_NIC_MSI_ENABLED 0x02
+#define NETXEN_DMA_MASK        0xfffffffe
+#define NETXEN_DB_MAPSIZE_BYTES    0x1000
 
-struct netxen_drvops;
+struct netxen_dummy_dma {
+       void *addr;
+       dma_addr_t phys_addr;
+};
 
 struct netxen_adapter {
        struct netxen_hardware_context ahw;
@@ -714,17 +853,19 @@ struct netxen_adapter {
        spinlock_t lock;
        struct work_struct watchdog_task;
        struct work_struct tx_timeout_task;
+       struct net_device *netdev;
        struct timer_list watchdog_timer;
 
        u32 curr_window;
 
        u32 cmd_producer;
-       u32 cmd_consumer;
+       u32 *cmd_consumer;
 
        u32 last_cmd_consumer;
        u32 max_tx_desc_count;
        u32 max_rx_desc_count;
        u32 max_jumbo_rx_desc_count;
+       u32 max_lro_rx_desc_count;
        /* Num of instances active on cmd buffer ring */
        u32 proc_cmd_buf_counter;
 
@@ -746,8 +887,27 @@ struct netxen_adapter {
        struct netxen_recv_context recv_ctx[MAX_RCV_CTX];
 
        int is_up;
-       int work_done;
-       struct netxen_drvops *ops;
+       int number;
+       struct netxen_dummy_dma dummy_dma;
+
+       /* Context interface shared between card and host */
+       struct netxen_ring_ctx *ctx_desc;
+       struct pci_dev *ctx_desc_pdev;
+       dma_addr_t ctx_desc_phys_addr;
+       int (*enable_phy_interrupts) (struct netxen_adapter *, int);
+       int (*disable_phy_interrupts) (struct netxen_adapter *, int);
+       void (*handle_phy_intr) (struct netxen_adapter *);
+       int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t);
+       int (*set_mtu) (struct netxen_port *, int);
+       int (*set_promisc) (struct netxen_adapter *, int,
+                           netxen_niu_prom_mode_t);
+       int (*unset_promisc) (struct netxen_adapter *, int,
+                             netxen_niu_prom_mode_t);
+       int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *);
+       int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val);
+       int (*init_port) (struct netxen_adapter *, int);
+       void (*init_niu) (struct netxen_adapter *);
+       int (*stop_port) (struct netxen_adapter *, int);
 };                             /* netxen_adapter structure */
 
 /* Max number of xmit producer threads that can run simultaneously */
@@ -829,25 +989,6 @@ static inline void __iomem *pci_base(struct netxen_adapter *adapter,
        return NULL;
 }
 
-struct netxen_drvops {
-       int (*enable_phy_interrupts) (struct netxen_adapter *, int);
-       int (*disable_phy_interrupts) (struct netxen_adapter *, int);
-       void (*handle_phy_intr) (struct netxen_adapter *);
-       int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t);
-       int (*set_mtu) (struct netxen_port *, int);
-       int (*set_promisc) (struct netxen_adapter *, int,
-                           netxen_niu_prom_mode_t);
-       int (*unset_promisc) (struct netxen_adapter *, int,
-                             netxen_niu_prom_mode_t);
-       int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *);
-       int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val);
-       int (*init_port) (struct netxen_adapter *, int);
-       void (*init_niu) (struct netxen_adapter *);
-       int (*stop_port) (struct netxen_adapter *, int);
-};
-
-extern char netxen_nic_driver_name[];
-
 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter,
                                          int port);
 int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
@@ -886,10 +1027,20 @@ int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
                          int len);
 int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
                           int len);
+int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
+                            void *data, int len);
+int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
+                             void *data, int len);
+int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter,
+                                  u64 off, void *data, int size);
+int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
+                                 u64 off, void *data, int size);
 void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
                                 unsigned long off, int data);
 
 /* Functions from netxen_nic_init.c */
+void netxen_free_adapter_offload(struct netxen_adapter *adapter);
+int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
 void netxen_load_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
@@ -921,10 +1072,12 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
                    struct netxen_port *port);
 int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
 int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
-void netxen_watchdog_task(unsigned long v);
+void netxen_watchdog_task(struct work_struct *work);
 void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
                            u32 ringid);
-void netxen_process_cmd_ring(unsigned long data);
+void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, u32 ctx,
+                                u32 ringid);
+int netxen_process_cmd_ring(unsigned long data);
 u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
 void netxen_nic_set_multi(struct net_device *netdev);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
@@ -1018,7 +1171,6 @@ static inline void get_brd_name_by_type(u32 type, char *name)
 
 int netxen_is_flash_supported(struct netxen_adapter *adapter);
 int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
-
 extern void netxen_change_ringparam(struct netxen_adapter *adapter);
 extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
                                int *valp);
index 9a914ae..2ab4885 100644 (file)
@@ -1,25 +1,25 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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 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.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -118,7 +118,7 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        u32 fw_minor = 0;
        u32 fw_build = 0;
 
-       strncpy(drvinfo->driver, "netxen_nic", 32);
+       strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
        strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
        fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
                                              NETXEN_FW_VERSION_MAJOR));
@@ -210,7 +210,6 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
                       (netxen_brdtype_t) boardinfo->board_type);
                return -EIO;
-
        }
 
        return 0;
@@ -226,18 +225,18 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
                /* autonegotiation */
-               if (adapter->ops->phy_write
-                   && adapter->ops->phy_write(adapter, port->portnum,
-                                              NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-                                              (__le32) ecmd->autoneg) != 0)
+               if (adapter->phy_write
+                   && adapter->phy_write(adapter, port->portnum,
+                                         NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+                                         (__le32) ecmd->autoneg) != 0)
                        return -EIO;
                else
                        port->link_autoneg = ecmd->autoneg;
 
-               if (adapter->ops->phy_read
-                   && adapter->ops->phy_read(adapter, port->portnum,
-                                             NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-                                             &status) != 0)
+               if (adapter->phy_read
+                   && adapter->phy_read(adapter, port->portnum,
+                                        NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+                                        &status) != 0)
                        return -EIO;
 
                /* speed */
@@ -257,10 +256,10 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        netxen_clear_phy_duplex(status);
                if (ecmd->duplex == DUPLEX_FULL)
                        netxen_set_phy_duplex(status);
-               if (adapter->ops->phy_write
-                   && adapter->ops->phy_write(adapter, port->portnum,
-                                              NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-                                              *((int *)&status)) != 0)
+               if (adapter->phy_write
+                   && adapter->phy_write(adapter, port->portnum,
+                                         NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+                                         *((int *)&status)) != 0)
                        return -EIO;
                else {
                        port->link_speed = ecmd->speed;
@@ -422,10 +421,10 @@ static u32 netxen_nic_get_link(struct net_device *dev)
 
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
-               if (adapter->ops->phy_read
-                   && adapter->ops->phy_read(adapter, port->portnum,
-                                             NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-                                             &status) != 0)
+               if (adapter->phy_read
+                   && adapter->phy_read(adapter, port->portnum,
+                                        NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+                                        &status) != 0)
                        return -EIO;
                else
                        return (netxen_get_phy_link(status));
@@ -460,20 +459,22 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       int i, j;
+       int i;
 
        ring->rx_pending = 0;
+       ring->rx_jumbo_pending = 0;
        for (i = 0; i < MAX_RCV_CTX; ++i) {
-               for (j = 0; j < NUM_RCV_DESC_RINGS; j++)
-                       ring->rx_pending +=
-                           adapter->recv_ctx[i].rcv_desc[j].rcv_pending;
+               ring->rx_pending += adapter->recv_ctx[i].
+                   rcv_desc[RCV_DESC_NORMAL_CTXID].rcv_pending;
+               ring->rx_jumbo_pending += adapter->recv_ctx[i].
+                   rcv_desc[RCV_DESC_JUMBO_CTXID].rcv_pending;
        }
 
        ring->rx_max_pending = adapter->max_rx_desc_count;
        ring->tx_max_pending = adapter->max_tx_desc_count;
+       ring->rx_jumbo_max_pending = adapter->max_jumbo_rx_desc_count;
        ring->rx_mini_max_pending = 0;
        ring->rx_mini_pending = 0;
-       ring->rx_jumbo_max_pending = 0;
        ring->rx_jumbo_pending = 0;
 }
 
@@ -526,10 +527,10 @@ netxen_nic_set_pauseparam(struct net_device *dev,
                                    *(u32 *) (&val));
                /* set autoneg */
                autoneg = pause->autoneg;
-               if (adapter->ops->phy_write
-                   && adapter->ops->phy_write(adapter, port->portnum,
-                                              NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-                                              (__le32) autoneg) != 0)
+               if (adapter->phy_write
+                   && adapter->phy_write(adapter, port->portnum,
+                                         NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
+                                         (__le32) autoneg) != 0)
                        return -EIO;
                else {
                        port->link_autoneg = pause->autoneg;
index 72c6ec4..fe8b675 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
index 105c24f..9147b60 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -42,7 +42,7 @@
 
 #define NETXEN_FLASH_BASE      (BOOTLD_START)
 #define NETXEN_PHANTOM_MEM_BASE        (NETXEN_FLASH_BASE)
-#define NETXEN_MAX_MTU         8000
+#define NETXEN_MAX_MTU         8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
 #define NETXEN_MIN_MTU         64
 #define NETXEN_ETH_FCS_SIZE     4
 #define NETXEN_ENET_HEADER_SIZE 14
@@ -81,8 +81,8 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
        DPRINTK(INFO, "valid ether addr\n");
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
-       if (adapter->ops->macaddr_set)
-               adapter->ops->macaddr_set(port, addr->sa_data);
+       if (adapter->macaddr_set)
+               adapter->macaddr_set(port, addr->sa_data);
 
        return 0;
 }
@@ -99,17 +99,17 @@ void netxen_nic_set_multi(struct net_device *netdev)
 
        mc_ptr = netdev->mc_list;
        if (netdev->flags & IFF_PROMISC) {
-               if (adapter->ops->set_promisc)
-                       adapter->ops->set_promisc(adapter,
-                                                 port->portnum,
-                                                 NETXEN_NIU_PROMISC_MODE);
+               if (adapter->set_promisc)
+                       adapter->set_promisc(adapter,
+                                            port->portnum,
+                                            NETXEN_NIU_PROMISC_MODE);
        } else {
-               if (adapter->ops->unset_promisc &&
+               if (adapter->unset_promisc &&
                    adapter->ahw.boardcfg.board_type
                    != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ)
-                       adapter->ops->unset_promisc(adapter,
-                                                   port->portnum,
-                                                   NETXEN_NIU_NON_PROMISC_MODE);
+                       adapter->unset_promisc(adapter,
+                                              port->portnum,
+                                              NETXEN_NIU_NON_PROMISC_MODE);
        }
        if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
                netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03);
@@ -160,8 +160,8 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
                return -EINVAL;
        }
 
-       if (adapter->ops->set_mtu)
-               adapter->ops->set_mtu(port, mtu);
+       if (adapter->set_mtu)
+               adapter->set_mtu(port, mtu);
        netdev->mtu = mtu;
 
        return 0;
@@ -176,22 +176,18 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
        struct netxen_hardware_context *hw = &adapter->ahw;
        u32 state = 0;
        void *addr;
-       void *pause_addr;
        int loops = 0, err = 0;
        int ctx, ring;
        u32 card_cmdring = 0;
-       struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
        struct netxen_recv_context *recv_ctx;
        struct netxen_rcv_desc_ctx *rcv_desc;
 
-       DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE,
+       DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
                PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
-       DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM,
+       DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
                pci_base_offset(adapter, NETXEN_CRB_CAM));
-       DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE,
+       DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
                pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
-       DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1,
-               pci_base_offset(adapter, NIC_CRB_BASE_PORT1));
 
        /* Window 1 call */
        card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
@@ -226,33 +222,42 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
        DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
 
        addr = netxen_alloc(adapter->ahw.pdev,
-                           sizeof(struct cmd_desc_type0) *
-                           adapter->max_tx_desc_count,
-                           &hw->cmd_desc_phys_addr, &hw->cmd_desc_pdev);
+                           sizeof(struct netxen_ring_ctx) +
+                           sizeof(uint32_t),
+                           (dma_addr_t *) & adapter->ctx_desc_phys_addr,
+                           &adapter->ctx_desc_pdev);
 
+       printk("ctx_desc_phys_addr: 0x%llx\n",
+              (u64) adapter->ctx_desc_phys_addr);
        if (addr == NULL) {
                DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
-               return -ENOMEM;
+               err = -ENOMEM;
+               return err;
        }
+       memset(addr, 0, sizeof(struct netxen_ring_ctx));
+       adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
+       adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr
+           + sizeof(struct netxen_ring_ctx);
+       adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
+                                             sizeof(struct netxen_ring_ctx));
+
+       addr = pci_alloc_consistent(adapter->ahw.pdev,
+                                   sizeof(struct cmd_desc_type0) *
+                                   adapter->max_tx_desc_count,
+                                   (dma_addr_t *) & hw->cmd_desc_phys_addr);
+       printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr);
 
-       pause_addr = netxen_alloc(adapter->ahw.pdev, 512,
-                                 (dma_addr_t *) & hw->pause_physaddr,
-                                 &hw->pause_pdev);
-       if (pause_addr == NULL) {
-               DPRINTK(1, ERR, "bad return from pci_alloc_consistent\n");
+       if (addr == NULL) {
+               DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
+               netxen_free_hw_resources(adapter);
                return -ENOMEM;
        }
 
-       hw->pauseaddr = (char *)pause_addr;
-       {
-               u64 *ptr = (u64 *) pause_addr;
-               *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
-               *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
-               *ptr++ = NETXEN_NIC_UNIT_PAUSE_ADDR;
-               *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
-               *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR1;
-               *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR2;
-       }
+       adapter->ctx_desc->cmd_ring_addr_lo =
+           hw->cmd_desc_phys_addr & 0xffffffffUL;
+       adapter->ctx_desc->cmd_ring_addr_hi =
+           ((u64) hw->cmd_desc_phys_addr >> 32);
+       adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count;
 
        hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
 
@@ -273,6 +278,12 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                                return err;
                        }
                        rcv_desc->desc_head = (struct rcv_desc *)addr;
+                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo =
+                           rcv_desc->phys_addr & 0xffffffffUL;
+                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi =
+                           ((u64) rcv_desc->phys_addr >> 32);
+                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+                           rcv_desc->max_rx_desc_count;
                }
 
                addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
@@ -286,47 +297,21 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                        return err;
                }
                recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
-               for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       rcv_desc = &recv_ctx->rcv_desc[ring];
-                       rcv_desc_crb =
-                           &recv_crb_registers[ctx].rcv_desc_crb[ring];
-                       DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n",
-                               ring, rcv_desc_crb->crb_globalrcv_ring);
-                       /* Window = 1 */
-                       writel(lower32(rcv_desc->phys_addr),
-                              NETXEN_CRB_NORMALIZE(adapter,
-                                                   rcv_desc_crb->
-                                                   crb_globalrcv_ring));
-                       DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x"
-                               " val 0x%llx,"
-                               " virt %p\n", ctx,
-                               rcv_desc_crb->crb_globalrcv_ring,
-                               (unsigned long long)rcv_desc->phys_addr,
-                               +rcv_desc->desc_head);
-               }
+               adapter->ctx_desc->sts_ring_addr_lo =
+                   recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL;
+               adapter->ctx_desc->sts_ring_addr_hi =
+                   ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32);
+               adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count;
 
-               /* Window = 1 */
-               writel(lower32(recv_ctx->rcv_status_desc_phys_addr),
-                      NETXEN_CRB_NORMALIZE(adapter,
-                                           recv_crb_registers[ctx].
-                                           crb_rcvstatus_ring));
-               DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x,"
-                       " val 0x%x,virt%p\n",
-                       ctx,
-                       recv_crb_registers[ctx].crb_rcvstatus_ring,
-                       (unsigned long long)recv_ctx->rcv_status_desc_phys_addr,
-                       recv_ctx->rcv_status_desc_head);
        }
        /* Window = 1 */
-       writel(lower32(hw->pause_physaddr),
-              NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_LO));
-       writel(upper32(hw->pause_physaddr),
-              NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_HI));
-
-       writel(lower32(hw->cmd_desc_phys_addr),
-              NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
-       writel(upper32(hw->cmd_desc_phys_addr),
-              NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_HI));
+
+       writel(lower32(adapter->ctx_desc_phys_addr),
+              NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO));
+       writel(upper32(adapter->ctx_desc_phys_addr),
+              NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI));
+       writel(NETXEN_CTX_SIGNATURE,
+              NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG));
        return err;
 }
 
@@ -336,6 +321,15 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
        struct netxen_rcv_desc_ctx *rcv_desc;
        int ctx, ring;
 
+       if (adapter->ctx_desc != NULL) {
+               pci_free_consistent(adapter->ctx_desc_pdev,
+                                   sizeof(struct netxen_ring_ctx) +
+                                   sizeof(uint32_t),
+                                   adapter->ctx_desc,
+                                   adapter->ctx_desc_phys_addr);
+               adapter->ctx_desc = NULL;
+       }
+
        if (adapter->ahw.cmd_desc_head != NULL) {
                pci_free_consistent(adapter->ahw.cmd_desc_pdev,
                                    sizeof(struct cmd_desc_type0) *
@@ -344,11 +338,9 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
                                    adapter->ahw.cmd_desc_phys_addr);
                adapter->ahw.cmd_desc_head = NULL;
        }
-       if (adapter->ahw.pauseaddr != NULL) {
-               pci_free_consistent(adapter->ahw.pause_pdev, 512,
-                                   adapter->ahw.pauseaddr,
-                                   adapter->ahw.pause_physaddr);
-               adapter->ahw.pauseaddr = NULL;
+       /* Special handling: there are 2 ports on this board */
+       if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
+               adapter->ahw.max_ports = 2;
        }
 
        for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
@@ -383,19 +375,22 @@ void netxen_tso_check(struct netxen_adapter *adapter,
                desc->total_hdr_length = sizeof(struct ethhdr) +
                    ((skb->nh.iph)->ihl * sizeof(u32)) +
                    ((skb->h.th)->doff * sizeof(u32));
-               desc->opcode = TX_TCP_LSO;
+               netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
        } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
                if (skb->nh.iph->protocol == IPPROTO_TCP) {
-                       desc->opcode = TX_TCP_PKT;
+                       netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
                } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
-                       desc->opcode = TX_UDP_PKT;
+                       netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
                } else {
                        return;
                }
        }
        adapter->stats.xmitcsummed++;
-       CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data);
-       desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr);
+       desc->tcp_hdr_offset = skb->h.raw - skb->data;
+       netxen_set_cmd_desc_totallength(desc,
+                                       cpu_to_le32
+                                       (netxen_get_cmd_desc_totallength
+                                        (desc)));
        desc->ip_hdr_offset = skb->nh.raw - skb->data;
 }
 
@@ -648,7 +643,7 @@ void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
 
        addr = NETXEN_CRB_NORMALIZE(adapter, off);
        DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
-               pci_base(adapter, off), off, addr);
+               pci_base(adapter, off), off, addr, val);
        writel(val, addr);
 
 }
@@ -660,7 +655,7 @@ int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
 
        addr = NETXEN_CRB_NORMALIZE(adapter, off);
        DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
-               adapter->ahw.pci_base, off, addr);
+               pci_base(adapter, off), off, addr);
        val = readl(addr);
        writel(val, addr);
 
@@ -848,8 +843,8 @@ void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
 
        for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
                port = adapter->port[port_nr];
-               if (adapter->ops->stop_port)
-                       adapter->ops->stop_port(adapter, port->portnum);
+               if (adapter->stop_port)
+                       adapter->stop_port(adapter, port->portnum);
        }
 }
 
@@ -873,13 +868,13 @@ void netxen_nic_set_link_parameters(struct netxen_port *port)
 {
        struct netxen_adapter *adapter = port->adapter;
        __le32 status;
-       u16 autoneg;
+       __le32 autoneg;
        __le32 mode;
 
        netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
        if (netxen_get_niu_enable_ge(mode)) {   /* Gb 10/100/1000 Mbps mode */
-               if (adapter->ops->phy_read
-                   && adapter->ops->
+               if (adapter->phy_read
+                   && adapter->
                    phy_read(adapter, port->portnum,
                             NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
                             &status) == 0) {
@@ -909,11 +904,11 @@ void netxen_nic_set_link_parameters(struct netxen_port *port)
                                        port->link_duplex = -1;
                                        break;
                                }
-                               if (adapter->ops->phy_read
-                                   && adapter->ops->
+                               if (adapter->phy_read
+                                   && adapter->
                                    phy_read(adapter, port->portnum,
                                             NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-                                            (__le32 *) & autoneg) != 0)
+                                            &autoneg) != 0)
                                        port->link_autoneg = autoneg;
                        } else
                                goto link_down;
@@ -1008,3 +1003,291 @@ int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
        netxen_nic_hw_read_wx(adapter, off, &data, 4);
        return data;
 }
+
+int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
+                             void *data, int len)
+{
+       void *addr;
+       u64 offset = off;
+       u8 *mem_ptr = NULL;
+       unsigned long mem_base;
+       unsigned long mem_page;
+
+       if (ADDR_IN_WINDOW1(off)) {
+               addr = NETXEN_CRB_NORMALIZE(adapter, off);
+               if (!addr) {
+                       mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+                       offset = NETXEN_CRB_NORMAL(off);
+                       mem_page = offset & PAGE_MASK;
+                       if (mem_page != ((offset + len - 1) & PAGE_MASK))
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+                       else
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE);
+                       if (mem_ptr == 0UL) {
+                               return 1;
+                       }
+                       addr = mem_ptr;
+                       addr += offset & (PAGE_SIZE - 1);
+               }
+       } else {
+               addr = pci_base_offset(adapter, off);
+               if (!addr) {
+                       mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+                       mem_page = off & PAGE_MASK;
+                       if (mem_page != ((off + len - 1) & PAGE_MASK))
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+                       else
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE);
+                       if (mem_ptr == 0UL) {
+                               return 1;
+                       }
+                       addr = mem_ptr;
+                       addr += off & (PAGE_SIZE - 1);
+               }
+               netxen_nic_pci_change_crbwindow(adapter, 0);
+       }
+       switch (len) {
+       case 1:
+               writeb(*(u8 *) data, addr);
+               break;
+       case 2:
+               writew(*(u16 *) data, addr);
+               break;
+       case 4:
+               writel(*(u32 *) data, addr);
+               break;
+       case 8:
+               writeq(*(u64 *) data, addr);
+               break;
+       default:
+               DPRINTK(INFO,
+                       "writing data %lx to offset %llx, num words=%d\n",
+                       *(unsigned long *)data, off, (len >> 3));
+
+               netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
+                                           (len >> 3));
+               break;
+       }
+
+       if (!ADDR_IN_WINDOW1(off))
+               netxen_nic_pci_change_crbwindow(adapter, 1);
+       if (mem_ptr)
+               iounmap(mem_ptr);
+       return 0;
+}
+
+int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
+                            void *data, int len)
+{
+       void *addr;
+       u64 offset;
+       u8 *mem_ptr = NULL;
+       unsigned long mem_base;
+       unsigned long mem_page;
+
+       if (ADDR_IN_WINDOW1(off)) {
+               addr = NETXEN_CRB_NORMALIZE(adapter, off);
+               if (!addr) {
+                       mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+                       offset = NETXEN_CRB_NORMAL(off);
+                       mem_page = offset & PAGE_MASK;
+                       if (mem_page != ((offset + len - 1) & PAGE_MASK))
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+                       else
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE);
+                       if (mem_ptr == 0UL) {
+                               *(u8 *) data = 0;
+                               return 1;
+                       }
+                       addr = mem_ptr;
+                       addr += offset & (PAGE_SIZE - 1);
+               }
+       } else {
+               addr = pci_base_offset(adapter, off);
+               if (!addr) {
+                       mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+                       mem_page = off & PAGE_MASK;
+                       if (mem_page != ((off + len - 1) & PAGE_MASK))
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+                       else
+                               mem_ptr =
+                                   ioremap(mem_base + mem_page, PAGE_SIZE);
+                       if (mem_ptr == 0UL)
+                               return 1;
+                       addr = mem_ptr;
+                       addr += off & (PAGE_SIZE - 1);
+               }
+               netxen_nic_pci_change_crbwindow(adapter, 0);
+       }
+       switch (len) {
+       case 1:
+               *(u8 *) data = readb(addr);
+               break;
+       case 2:
+               *(u16 *) data = readw(addr);
+               break;
+       case 4:
+               *(u32 *) data = readl(addr);
+               break;
+       case 8:
+               *(u64 *) data = readq(addr);
+               break;
+       default:
+               netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
+                                          (len >> 3));
+               break;
+       }
+       if (!ADDR_IN_WINDOW1(off))
+               netxen_nic_pci_change_crbwindow(adapter, 1);
+       if (mem_ptr)
+               iounmap(mem_ptr);
+       return 0;
+}
+
+int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter, u64 off,
+                                  void *data, int size)
+{
+       void *addr;
+       int ret = 0;
+       u8 *mem_ptr = NULL;
+       unsigned long mem_base;
+       unsigned long mem_page;
+
+       if (data == NULL || off > (128 * 1024 * 1024)) {
+               printk(KERN_ERR "%s: data: %p off:%llx\n",
+                      netxen_nic_driver_name, data, off);
+               return 1;
+       }
+       off = netxen_nic_pci_set_window(adapter, off);
+       /* Corner case : Malicious user tried to break the driver by reading
+          last few bytes in ranges and tries to read further addresses.
+        */
+       if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
+               printk(KERN_ERR "%s: Invalid access to memory address range"
+                      " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
+                      off + size);
+               return 1;
+       }
+       addr = pci_base_offset(adapter, off);
+       DPRINTK(INFO, "writing data %llx to offset %llx\n",
+               *(unsigned long long *)data, off);
+       if (!addr) {
+               mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+               mem_page = off & PAGE_MASK;
+               /* Map two pages whenever user tries to access addresses in two
+                  consecutive pages.
+                */
+               if (mem_page != ((off + size - 1) & PAGE_MASK))
+                       mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+               else
+                       mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+               if (mem_ptr == 0UL) {
+                       return 1;
+               }
+               addr = mem_ptr;
+               addr += off & (PAGE_SIZE - 1);
+       }
+       switch (size) {
+       case 1:
+               writeb(*(u8 *) data, addr);
+               break;
+       case 2:
+               writew(*(u16 *) data, addr);
+               break;
+       case 4:
+               writel(*(u32 *) data, addr);
+               break;
+       case 8:
+               writeq(*(u64 *) data, addr);
+               break;
+       default:
+               DPRINTK(INFO,
+                       "writing data %lx to offset %llx, num words=%d\n",
+                       *(unsigned long *)data, off, (size >> 3));
+
+               netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
+                                           (size >> 3));
+               break;
+       }
+
+       if (mem_ptr)
+               iounmap(mem_ptr);
+       DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data);
+
+       return ret;
+}
+
+int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
+                                 u64 off, void *data, int size)
+{
+       void *addr;
+       int ret = 0;
+       u8 *mem_ptr = NULL;
+       unsigned long mem_base;
+       unsigned long mem_page;
+
+       if (data == NULL || off > (128 * 1024 * 1024)) {
+               printk(KERN_ERR "%s: data: %p off:%llx\n",
+                      netxen_nic_driver_name, data, off);
+               return 1;
+       }
+       off = netxen_nic_pci_set_window(adapter, off);
+       /* Corner case : Malicious user tried to break the driver by reading
+          last few bytes in ranges and tries to read further addresses.
+        */
+       if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
+               printk(KERN_ERR "%s: Invalid access to memory address range"
+                      " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
+                      off + size);
+               return 1;
+       }
+       addr = pci_base_offset(adapter, off);
+       if (!addr) {
+               mem_base = pci_resource_start(adapter->ahw.pdev, 0);
+               mem_page = off & PAGE_MASK;
+               /* Map two pages whenever user tries to access addresses in two
+                  consecutive pages.
+                */
+               if (mem_page != ((off + size - 1) & PAGE_MASK))
+                       mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+               else
+                       mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+               if (mem_ptr == 0UL) {
+                       *(u8 *) data = 0;
+                       return 1;
+               }
+               addr = mem_ptr;
+               addr += off & (PAGE_SIZE - 1);
+       }
+       switch (size) {
+       case 1:
+               *(u8 *) data = readb(addr);
+               break;
+       case 2:
+               *(u16 *) data = readw(addr);
+               break;
+       case 4:
+               *(u32 *) data = readl(addr);
+               break;
+       case 8:
+               *(u64 *) data = readq(addr);
+               break;
+       default:
+               netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
+                                          (size >> 3));
+               break;
+       }
+
+       if (mem_ptr)
+               iounmap(mem_ptr);
+       DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data);
+
+       return ret;
+}
index 201a636..0685633 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -83,8 +83,8 @@ struct netxen_adapter;
 #define NETXEN_PCI_MAPSIZE_BYTES  (NETXEN_PCI_MAPSIZE << 20)
 
 #define NETXEN_NIC_LOCKED_READ_REG(X, Y)       \
-       addr = pci_base_offset(adapter, (X));   \
-       *(u32 *)Y = readl(addr);
+       addr = pci_base_offset(adapter, X);     \
+       *(u32 *)Y = readl((void __iomem*) addr);
 
 struct netxen_port;
 void netxen_nic_set_link_parameters(struct netxen_port *port);
index 0dca029..869725f 100644 (file)
@@ -1,25 +1,25 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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 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.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -137,6 +137,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
                return err;
        }
        /* Window 1 call */
+       writel(MPORT_SINGLE_FUNCTION_MODE,
+              NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
        writel(PHAN_INITIALIZE_ACK,
               NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
 
@@ -184,15 +186,12 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
                        for (i = 0; i < num_rx_bufs; i++) {
                                rx_buf->ref_handle = i;
                                rx_buf->state = NETXEN_BUFFER_FREE;
-
                                DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
                                        "%p\n", ctxid, i, rx_buf);
                                rx_buf++;
                        }
                }
        }
-       DPRINTK(INFO, "initialized buffers for %s and %s\n",
-               "adapter->free_cmd_buf_list", "adapter->free_rxbuf");
 }
 
 void netxen_initialize_adapter_hw(struct netxen_adapter *adapter)
@@ -212,37 +211,36 @@ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter)
 
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 {
-       struct netxen_drvops *ops = adapter->ops;
        switch (adapter->ahw.board_type) {
        case NETXEN_NIC_GBE:
-               ops->enable_phy_interrupts =
+               adapter->enable_phy_interrupts =
                    netxen_niu_gbe_enable_phy_interrupts;
-               ops->disable_phy_interrupts =
+               adapter->disable_phy_interrupts =
                    netxen_niu_gbe_disable_phy_interrupts;
-               ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
-               ops->macaddr_set = netxen_niu_macaddr_set;
-               ops->set_mtu = netxen_nic_set_mtu_gb;
-               ops->set_promisc = netxen_niu_set_promiscuous_mode;
-               ops->unset_promisc = netxen_niu_set_promiscuous_mode;
-               ops->phy_read = netxen_niu_gbe_phy_read;
-               ops->phy_write = netxen_niu_gbe_phy_write;
-               ops->init_port = netxen_niu_gbe_init_port;
-               ops->init_niu = netxen_nic_init_niu_gb;
-               ops->stop_port = netxen_niu_disable_gbe_port;
+               adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
+               adapter->macaddr_set = netxen_niu_macaddr_set;
+               adapter->set_mtu = netxen_nic_set_mtu_gb;
+               adapter->set_promisc = netxen_niu_set_promiscuous_mode;
+               adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
+               adapter->phy_read = netxen_niu_gbe_phy_read;
+               adapter->phy_write = netxen_niu_gbe_phy_write;
+               adapter->init_port = netxen_niu_gbe_init_port;
+               adapter->init_niu = netxen_nic_init_niu_gb;
+               adapter->stop_port = netxen_niu_disable_gbe_port;
                break;
 
        case NETXEN_NIC_XGBE:
-               ops->enable_phy_interrupts =
+               adapter->enable_phy_interrupts =
                    netxen_niu_xgbe_enable_phy_interrupts;
-               ops->disable_phy_interrupts =
+               adapter->disable_phy_interrupts =
                    netxen_niu_xgbe_disable_phy_interrupts;
-               ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
-               ops->macaddr_set = netxen_niu_xg_macaddr_set;
-               ops->set_mtu = netxen_nic_set_mtu_xgb;
-               ops->init_port = netxen_niu_xg_init_port;
-               ops->set_promisc = netxen_niu_xg_set_promiscuous_mode;
-               ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
-               ops->stop_port = netxen_niu_disable_xg_port;
+               adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
+               adapter->macaddr_set = netxen_niu_xg_macaddr_set;
+               adapter->set_mtu = netxen_nic_set_mtu_xgb;
+               adapter->init_port = netxen_niu_xg_init_port;
+               adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
+               adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
+               adapter->stop_port = netxen_niu_disable_xg_port;
                break;
 
        default:
@@ -383,8 +381,8 @@ int netxen_rom_wip_poll(struct netxen_adapter *adapter)
        return 0;
 }
 
-static inline int do_rom_fast_write(struct netxen_adapter *adapter,
-                                   int addr, int data)
+static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
+                                   int data)
 {
        if (netxen_rom_wren(adapter)) {
                return -1;
@@ -622,6 +620,43 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
        return 0;
 }
 
+int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
+{
+       uint64_t addr;
+       uint32_t hi;
+       uint32_t lo;
+
+       adapter->dummy_dma.addr =
+           pci_alloc_consistent(adapter->ahw.pdev,
+                                NETXEN_HOST_DUMMY_DMA_SIZE,
+                                &adapter->dummy_dma.phys_addr);
+       if (adapter->dummy_dma.addr == NULL) {
+               printk("%s: ERROR: Could not allocate dummy DMA memory\n",
+                      __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       addr = (uint64_t) adapter->dummy_dma.phys_addr;
+       hi = (addr >> 32) & 0xffffffff;
+       lo = addr & 0xffffffff;
+
+       writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
+       writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+
+       return 0;
+}
+
+void netxen_free_adapter_offload(struct netxen_adapter *adapter)
+{
+       if (adapter->dummy_dma.addr) {
+               pci_free_consistent(adapter->ahw.pdev,
+                                   NETXEN_HOST_DUMMY_DMA_SIZE,
+                                   adapter->dummy_dma.addr,
+                                   adapter->dummy_dma.phys_addr);
+               adapter->dummy_dma.addr = NULL;
+       }
+}
+
 void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
 {
        u32 val = 0;
@@ -656,7 +691,8 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
                desc_head = recv_ctx->rcv_status_desc_head;
                desc = &desc_head[consumer];
 
-               if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST))
+               if (((le16_to_cpu(netxen_get_sts_owner(desc)))
+                    & STATUS_OWNER_HOST))
                        return 1;
        }
 
@@ -710,12 +746,13 @@ static inline int netxen_nic_check_temp(struct netxen_adapter *adapter)
        return rv;
 }
 
-void netxen_watchdog_task(unsigned long v)
+void netxen_watchdog_task(struct work_struct *work)
 {
        int port_num;
        struct netxen_port *port;
        struct net_device *netdev;
-       struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+       struct netxen_adapter *adapter =
+               container_of(work, struct netxen_adapter, watchdog_task);
 
        if (netxen_nic_check_temp(adapter))
                return;
@@ -734,8 +771,8 @@ void netxen_watchdog_task(unsigned long v)
                        netif_wake_queue(netdev);
        }
 
-       if (adapter->ops->handle_phy_intr)
-               adapter->ops->handle_phy_intr(adapter);
+       if (adapter->handle_phy_intr)
+               adapter->handle_phy_intr(adapter);
        mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
 
@@ -748,19 +785,19 @@ void
 netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
                   struct status_desc *desc)
 {
-       struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)];
+       struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)];
        struct pci_dev *pdev = port->pdev;
        struct net_device *netdev = port->netdev;
-       int index = le16_to_cpu(desc->reference_handle);
+       int index = le16_to_cpu(netxen_get_sts_refhandle(desc));
        struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
        struct netxen_rx_buffer *buffer;
        struct sk_buff *skb;
-       u32 length = le16_to_cpu(desc->total_length);
+       u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
        u32 desc_ctx;
        struct netxen_rcv_desc_ctx *rcv_desc;
        int ret;
 
-       desc_ctx = STATUS_DESC_TYPE(desc);
+       desc_ctx = netxen_get_sts_type(desc);
        if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
                printk("%s: %s Bad Rcv descriptor ring\n",
                       netxen_nic_driver_name, netdev->name);
@@ -768,20 +805,49 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
        }
 
        rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
+       if (unlikely(index > rcv_desc->max_rx_desc_count)) {
+               DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
+                       index, rcv_desc->max_rx_desc_count);
+               return;
+       }
        buffer = &rcv_desc->rx_buf_arr[index];
+       if (desc_ctx == RCV_DESC_LRO_CTXID) {
+               buffer->lro_current_frags++;
+               if (netxen_get_sts_desc_lro_last_frag(desc)) {
+                       buffer->lro_expected_frags =
+                           netxen_get_sts_desc_lro_cnt(desc);
+                       buffer->lro_length = length;
+               }
+               if (buffer->lro_current_frags != buffer->lro_expected_frags) {
+                       if (buffer->lro_expected_frags != 0) {
+                               printk("LRO: (refhandle:%x) recv frag."
+                                      "wait for last. flags: %x expected:%d"
+                                      "have:%d\n", index,
+                                      netxen_get_sts_desc_lro_last_frag(desc),
+                                      buffer->lro_expected_frags,
+                                      buffer->lro_current_frags);
+                       }
+                       return;
+               }
+       }
 
        pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
                         PCI_DMA_FROMDEVICE);
 
        skb = (struct sk_buff *)buffer->skb;
 
-       if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) {
+       if (likely(netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) {
                port->stats.csummed++;
                skb->ip_summed = CHECKSUM_UNNECESSARY;
-       } else
-               skb->ip_summed = CHECKSUM_NONE;
+       }
        skb->dev = netdev;
-       skb_put(skb, length);
+       if (desc_ctx == RCV_DESC_LRO_CTXID) {
+               /* True length was only available on the last pkt */
+               skb_put(skb, buffer->lro_length);
+       } else {
+               skb_put(skb, length);
+       }
+
        skb->protocol = eth_type_trans(skb, netdev);
 
        ret = netif_receive_skb(skb);
@@ -827,6 +893,8 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
        adapter->stats.post_called++;
        buffer->skb = NULL;
        buffer->state = NETXEN_BUFFER_FREE;
+       buffer->lro_current_frags = 0;
+       buffer->lro_expected_frags = 0;
 
        port->stats.no_rcv++;
        port->stats.rxbytes += length;
@@ -839,6 +907,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
        struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
        struct status_desc *desc;       /* used to read status desc here */
        u32 consumer = recv_ctx->status_rx_consumer;
+       u32 producer = 0;
        int count = 0, ring;
 
        DPRINTK(INFO, "procesing receive\n");
@@ -850,18 +919,22 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
         */
        while (count < max) {
                desc = &desc_head[consumer];
-               if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) {
-                       DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner);
+               if (!
+                   (le16_to_cpu(netxen_get_sts_owner(desc)) &
+                    STATUS_OWNER_HOST)) {
+                       DPRINTK(ERR, "desc %p ownedby %x\n", desc,
+                               netxen_get_sts_owner(desc));
                        break;
                }
                netxen_process_rcv(adapter, ctxid, desc);
-               desc->owner = STATUS_OWNER_PHANTOM;
+               netxen_clear_sts_owner(desc);
+               netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
                consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
                count++;
        }
        if (count) {
                for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       netxen_post_rx_buffers(adapter, ctxid, ring);
+                       netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
                }
        }
 
@@ -869,6 +942,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
        if (count) {
                adapter->stats.process_rcv++;
                recv_ctx->status_rx_consumer = consumer;
+               recv_ctx->status_rx_producer = producer;
 
                /* Window = 1 */
                writel(consumer,
@@ -881,12 +955,13 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
 }
 
 /* Process Command status ring */
-void netxen_process_cmd_ring(unsigned long data)
+int netxen_process_cmd_ring(unsigned long data)
 {
        u32 last_consumer;
        u32 consumer;
        struct netxen_adapter *adapter = (struct netxen_adapter *)data;
-       int count = 0;
+       int count1 = 0;
+       int count2 = 0;
        struct netxen_cmd_buffer *buffer;
        struct netxen_port *port;       /* port #1 */
        struct netxen_port *nport;
@@ -895,6 +970,7 @@ void netxen_process_cmd_ring(unsigned long data)
        u32 i;
        struct sk_buff *skb = NULL;
        int p;
+       int done;
 
        spin_lock(&adapter->tx_lock);
        last_consumer = adapter->last_cmd_consumer;
@@ -904,14 +980,13 @@ void netxen_process_cmd_ring(unsigned long data)
         * number as part of the descriptor. This way we will be able to get
         * the netdev which is associated with that device.
         */
-       consumer =
-           readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
 
+       consumer = *(adapter->cmd_consumer);
        if (last_consumer == consumer) {        /* Ring is empty    */
                DPRINTK(INFO, "last_consumer %d == consumer %d\n",
                        last_consumer, consumer);
                spin_unlock(&adapter->tx_lock);
-               return;
+               return 1;
        }
 
        adapter->proc_cmd_buf_counter++;
@@ -922,7 +997,7 @@ void netxen_process_cmd_ring(unsigned long data)
         */
        spin_unlock(&adapter->tx_lock);
 
-       while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) {
+       while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) {
                buffer = &adapter->cmd_buf_arr[last_consumer];
                port = adapter->port[buffer->port];
                pdev = port->pdev;
@@ -948,24 +1023,24 @@ void netxen_process_cmd_ring(unsigned long data)
                             && netif_carrier_ok(port->netdev))
                    && ((jiffies - port->netdev->trans_start) >
                        port->netdev->watchdog_timeo)) {
-                       schedule_work(&port->adapter->tx_timeout_task);
+                       SCHEDULE_WORK(&port->adapter->tx_timeout_task);
                }
 
                last_consumer = get_next_index(last_consumer,
                                               adapter->max_tx_desc_count);
-               count++;
+               count1++;
        }
-       adapter->stats.noxmitdone += count;
+       adapter->stats.noxmitdone += count1;
 
-       count = 0;
+       count2 = 0;
        spin_lock(&adapter->tx_lock);
        if ((--adapter->proc_cmd_buf_counter) == 0) {
                adapter->last_cmd_consumer = last_consumer;
                while ((adapter->last_cmd_consumer != consumer)
-                      && (count < MAX_STATUS_HANDLE)) {
+                      && (count2 < MAX_STATUS_HANDLE)) {
                        buffer =
                            &adapter->cmd_buf_arr[adapter->last_cmd_consumer];
-                       count++;
+                       count2++;
                        if (buffer->skb)
                                break;
                        else
@@ -974,7 +1049,7 @@ void netxen_process_cmd_ring(unsigned long data)
                                                   adapter->max_tx_desc_count);
                }
        }
-       if (count) {
+       if (count1 || count2) {
                for (p = 0; p < adapter->ahw.max_ports; p++) {
                        nport = adapter->port[p];
                        if (netif_queue_stopped(nport->netdev)
@@ -984,10 +1059,30 @@ void netxen_process_cmd_ring(unsigned long data)
                        }
                }
        }
+       /*
+        * If everything is freed up to consumer then check if the ring is full
+        * If the ring is full then check if more needs to be freed and
+        * schedule the call back again.
+        *
+        * This happens when there are 2 CPUs. One could be freeing and the
+        * other filling it. If the ring is full when we get out of here and
+        * the card has already interrupted the host then the host can miss the
+        * interrupt.
+        *
+        * There is still a possible race condition and the host could miss an
+        * interrupt. The card has to take care of this.
+        */
+       if (adapter->last_cmd_consumer == consumer &&
+           (((adapter->cmd_producer + 1) %
+             adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
+               consumer = *(adapter->cmd_consumer);
+       }
+       done = (adapter->last_cmd_consumer == consumer);
 
        spin_unlock(&adapter->tx_lock);
        DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
                __FUNCTION__);
+       return (done);
 }
 
 /*
@@ -999,17 +1094,16 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
        struct sk_buff *skb;
        struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
        struct netxen_rcv_desc_ctx *rcv_desc = NULL;
-       struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx];
-       struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
-       u32 producer;
+       uint producer;
        struct rcv_desc *pdesc;
        struct netxen_rx_buffer *buffer;
        int count = 0;
        int index = 0;
+       netxen_ctx_msg msg = 0;
+       dma_addr_t dma;
 
        adapter->stats.post_called++;
        rcv_desc = &recv_ctx->rcv_desc[ringid];
-       rcv_desc_crb = &crbarea->rcv_desc_crb[ringid];
 
        producer = rcv_desc->producer;
        index = rcv_desc->begin_alloc;
@@ -1019,6 +1113,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
                skb = dev_alloc_skb(rcv_desc->skb_size);
                if (unlikely(!skb)) {
                        /*
+                        * TODO
                         * We need to schedule the posting of buffers to the pegs.
                         */
                        rcv_desc->begin_alloc = index;
@@ -1026,9 +1121,105 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
                                " allocated only %d buffers\n", count);
                        break;
                }
+
                count++;        /* now there should be no failure */
                pdesc = &rcv_desc->desc_head[producer];
-               skb_reserve(skb, NET_IP_ALIGN);
+
+#if defined(XGB_DEBUG)
+               *(unsigned long *)(skb->head) = 0xc0debabe;
+               if (skb_is_nonlinear(skb)) {
+                       printk("Allocated SKB @%p is nonlinear\n");
+               }
+#endif
+               skb_reserve(skb, 2);
+               /* This will be setup when we receive the
+                * buffer after it has been filled  FSL  TBD TBD
+                * skb->dev = netdev;
+                */
+               dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
+                                    PCI_DMA_FROMDEVICE);
+               pdesc->addr_buffer = dma;
+               buffer->skb = skb;
+               buffer->state = NETXEN_BUFFER_BUSY;
+               buffer->dma = dma;
+               /* make a rcv descriptor  */
+               pdesc->reference_handle = buffer->ref_handle;
+               pdesc->buffer_length = rcv_desc->dma_size;
+               DPRINTK(INFO, "done writing descripter\n");
+               producer =
+                   get_next_index(producer, rcv_desc->max_rx_desc_count);
+               index = get_next_index(index, rcv_desc->max_rx_desc_count);
+               buffer = &rcv_desc->rx_buf_arr[index];
+       }
+       /* if we did allocate buffers, then write the count to Phantom */
+       if (count) {
+               rcv_desc->begin_alloc = index;
+               rcv_desc->rcv_pending += count;
+               adapter->stats.lastposted = count;
+               adapter->stats.posted += count;
+               rcv_desc->producer = producer;
+               if (rcv_desc->rcv_free >= 32) {
+                       rcv_desc->rcv_free = 0;
+                       /* Window = 1 */
+                       writel((producer - 1) &
+                              (rcv_desc->max_rx_desc_count - 1),
+                              NETXEN_CRB_NORMALIZE(adapter,
+                                                   recv_crb_registers[0].
+                                                   rcv_desc_crb[ringid].
+                                                   crb_rcv_producer_offset));
+                       /*
+                        * Write a doorbell msg to tell phanmon of change in
+                        * receive ring producer
+                        */
+                       netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
+                       netxen_set_msg_privid(msg);
+                       netxen_set_msg_count(msg,
+                                            ((producer -
+                                              1) & (rcv_desc->
+                                                    max_rx_desc_count - 1)));
+                       netxen_set_msg_ctxid(msg, 0);
+                       netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
+                       writel(msg,
+                              DB_NORMALIZE(adapter,
+                                           NETXEN_RCV_PRODUCER_OFFSET));
+               }
+       }
+}
+
+void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx,
+                                uint32_t ringid)
+{
+       struct pci_dev *pdev = adapter->ahw.pdev;
+       struct sk_buff *skb;
+       struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
+       struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+       u32 producer;
+       struct rcv_desc *pdesc;
+       struct netxen_rx_buffer *buffer;
+       int count = 0;
+       int index = 0;
+
+       adapter->stats.post_called++;
+       rcv_desc = &recv_ctx->rcv_desc[ringid];
+
+       producer = rcv_desc->producer;
+       index = rcv_desc->begin_alloc;
+       buffer = &rcv_desc->rx_buf_arr[index];
+       /* We can start writing rx descriptors into the phantom memory. */
+       while (buffer->state == NETXEN_BUFFER_FREE) {
+               skb = dev_alloc_skb(rcv_desc->skb_size);
+               if (unlikely(!skb)) {
+                       /*
+                        * We need to schedule the posting of buffers to the pegs.
+                        */
+                       rcv_desc->begin_alloc = index;
+                       DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
+                               " allocated only %d buffers\n", count);
+                       break;
+               }
+               count++;        /* now there should be no failure */
+               pdesc = &rcv_desc->desc_head[producer];
+               skb_reserve(skb, 2);
                /* 
                 * This will be setup when we receive the
                 * buffer after it has been filled
@@ -1039,6 +1230,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
                buffer->dma = pci_map_single(pdev, skb->data,
                                             rcv_desc->dma_size,
                                             PCI_DMA_FROMDEVICE);
+
                /* make a rcv descriptor  */
                pdesc->reference_handle = le16_to_cpu(buffer->ref_handle);
                pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size);
@@ -1063,7 +1255,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
                        writel((producer - 1) &
                               (rcv_desc->max_rx_desc_count - 1),
                               NETXEN_CRB_NORMALIZE(adapter,
-                                                   rcv_desc_crb->
+                                                   recv_crb_registers[0].
+                                                   rcv_desc_crb[ringid].
                                                    crb_rcv_producer_offset));
                        wmb();
                }
@@ -1196,8 +1389,8 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
 
        switch (data.cmd) {
        case netxen_nic_cmd_pci_read:
-               if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
-                                                   &(data.u), data.size)))
+               if ((retval = netxen_nic_hw_read_ioctl(adapter, data.off,
+                                                      &(data.u), data.size)))
                        goto error_out;
                if (copy_to_user
                    ((void __user *)&(up_data->u), &(data.u), data.size)) {
@@ -1210,8 +1403,35 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
                break;
 
        case netxen_nic_cmd_pci_write:
-               data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
-                                                data.size);
+               if ((retval = netxen_nic_hw_write_ioctl(adapter, data.off,
+                                                       &(data.u), data.size)))
+                       goto error_out;
+               data.rv = 0;
+               break;
+
+       case netxen_nic_cmd_pci_mem_read:
+               if (netxen_nic_pci_mem_read_ioctl(adapter, data.off, &(data.u),
+                                                 data.size)) {
+                       DPRINTK(ERR, "Failed to read the data.\n");
+                       retval = -EFAULT;
+                       goto error_out;
+               }
+               if (copy_to_user
+                   ((void __user *)&(up_data->u), &(data.u), data.size)) {
+                       DPRINTK(ERR, "bad copy to userland: %d\n",
+                               (int)sizeof(data));
+                       retval = -EFAULT;
+                       goto error_out;
+               }
+               data.rv = 0;
+               break;
+
+       case netxen_nic_cmd_pci_mem_write:
+               if ((retval = netxen_nic_pci_mem_write_ioctl(adapter, data.off,
+                                                            &(data.u),
+                                                            data.size)))
+                       goto error_out;
+               data.rv = 0;
                break;
 
        case netxen_nic_cmd_pci_config_read:
@@ -1296,7 +1516,7 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
                retval = -EOPNOTSUPP;
                goto error_out;
        }
-       put_user(data.rv, (u16 __user *) (&(up_data->rv)));
+       put_user(data.rv, (&(up_data->rv)));
        DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
 
       error_out:
index 23e53ad..1221fa5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -36,7 +36,7 @@
 #define NETXEN_NIC_CMD         (NETXEN_CMD_START + 1)
 #define NETXEN_NIC_NAME                (NETXEN_CMD_START + 2)
 #define NETXEN_NIC_NAME_LEN    16
-#define NETXEN_NIC_NAME_RSP    "NETXEN"
+#define NETXEN_NIC_NAME_RSP    "NETXEN-UNM"
 
 typedef enum {
        netxen_nic_cmd_none = 0,
index ae180fe..1b45f50 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -68,8 +68,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno,
                                 u32 link)
 {
-       struct netxen_port *pport = adapter->port[portno];
-       struct net_device *netdev = pport->netdev;
+       struct net_device *netdev = (adapter->port[portno])->netdev;
 
        if (link)
                netif_carrier_on(netdev);
@@ -84,46 +83,41 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
        struct netxen_port *port;
 
        /*  This should clear the interrupt source */
-       if (adapter->ops->phy_read)
-               adapter->ops->phy_read(adapter, portno,
-                                      NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
-                                      &int_src);
+       if (adapter->phy_read)
+               adapter->phy_read(adapter, portno,
+                                 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+                                 &int_src);
        if (int_src == 0) {
                DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
                return;
        }
-       if (adapter->ops->disable_phy_interrupts)
-               adapter->ops->disable_phy_interrupts(adapter, portno);
+       if (adapter->disable_phy_interrupts)
+               adapter->disable_phy_interrupts(adapter, portno);
 
        port = adapter->port[portno];
 
        if (netxen_get_phy_int_jabber(int_src))
-               DPRINTK(INFO, "NetXen: %s Jabber interrupt \n",
-                       port->netdev->name);
+               DPRINTK(INFO, "Jabber interrupt \n");
 
        if (netxen_get_phy_int_polarity_changed(int_src))
-               DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n",
-                       port->netdev->name);
+               DPRINTK(INFO, "POLARITY CHANGED int \n");
 
        if (netxen_get_phy_int_energy_detect(int_src))
-               DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n",
-                       port->netdev->name);
+               DPRINTK(INFO, "ENERGY DETECT INT \n");
 
        if (netxen_get_phy_int_downshift(int_src))
-               DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n",
-                       port->netdev->name);
+               DPRINTK(INFO, "DOWNSHIFT INT \n");
        /* write it down later.. */
        if ((netxen_get_phy_int_speed_changed(int_src))
            || (netxen_get_phy_int_link_status_changed(int_src))) {
                __le32 status;
 
-               DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR"
-                       " LINK STATUS CHANGED \n", port->netdev->name);
+               DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
 
-               if (adapter->ops->phy_read
-                   && adapter->ops->phy_read(adapter, portno,
-                                             NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-                                             &status) == 0) {
+               if (adapter->phy_read
+                   && adapter->phy_read(adapter, portno,
+                                        NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+                                        &status) == 0) {
                        if (netxen_get_phy_int_link_status_changed(int_src)) {
                                if (netxen_get_phy_link(status)) {
                                        netxen_niu_gbe_init_port(adapter,
@@ -143,8 +137,8 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
                        }
                }
        }
-       if (adapter->ops->enable_phy_interrupts)
-               adapter->ops->enable_phy_interrupts(adapter, portno);
+       if (adapter->enable_phy_interrupts)
+               adapter->enable_phy_interrupts(adapter, portno);
 }
 
 void netxen_nic_isr_other(struct netxen_adapter *adapter)
@@ -159,8 +153,7 @@ void netxen_nic_isr_other(struct netxen_adapter *adapter)
 
        qg_linksup = adapter->ahw.qg_linksup;
        adapter->ahw.qg_linksup = val;
-       DPRINTK(1, INFO, "%s: link update 0x%08x\n", netxen_nic_driver_name,
-               val);
+       DPRINTK(INFO, "link update 0x%08x\n", val);
        for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) {
                linkup = val & 1;
                if (linkup != (qg_linksup & 1)) {
index 1cb662d..575b71b 100644 (file)
@@ -1,25 +1,25 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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 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.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
@@ -32,6 +32,7 @@
  */
 
 #include <linux/vmalloc.h>
+#include <linux/highmem.h>
 #include "netxen_nic_hw.h"
 
 #include "netxen_nic.h"
@@ -48,14 +49,21 @@ MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
 
-char netxen_nic_driver_name[] = "netxen";
+char netxen_nic_driver_name[] = "netxen-nic";
 static char netxen_nic_driver_string[] = "NetXen Network Driver version "
     NETXEN_NIC_LINUX_VERSIONID;
 
+struct netxen_adapter *g_adapter = NULL;
+
 #define NETXEN_NETDEV_WEIGHT 120
 #define NETXEN_ADAPTER_UP_MAGIC 777
 #define NETXEN_NIC_PEG_TUNE 0
 
+u8 nx_p2_id = NX_P2_C0;
+
+#define DMA_32BIT_MASK 0x00000000ffffffffULL
+#define DMA_35BIT_MASK 0x00000007ffffffffULL
+
 /* Local functions to NetXen NIC driver */
 static int __devinit netxen_nic_probe(struct pci_dev *pdev,
                                      const struct pci_device_id *ent);
@@ -64,7 +72,7 @@ static int netxen_nic_open(struct net_device *netdev);
 static int netxen_nic_close(struct net_device *netdev);
 static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
 static void netxen_tx_timeout(struct net_device *netdev);
-static void netxen_tx_timeout_task(struct net_device *netdev);
+static void netxen_tx_timeout_task(struct work_struct *work);
 static void netxen_watchdog(unsigned long);
 static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
 static int netxen_nic_ioctl(struct net_device *netdev,
@@ -87,6 +95,9 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
 
+struct workqueue_struct *netxen_workq;
+static void netxen_watchdog(unsigned long);
+
 /*
  * netxen_nic_probe()
  *
@@ -105,20 +116,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct net_device *netdev = NULL;
        struct netxen_adapter *adapter = NULL;
        struct netxen_port *port = NULL;
-       u8 *mem_ptr0 = NULL;
-       u8 *mem_ptr1 = NULL;
-       u8 *mem_ptr2 = NULL;
+       void __iomem *mem_ptr0 = NULL;
+       void __iomem *mem_ptr1 = NULL;
+       void __iomem *mem_ptr2 = NULL;
 
-       unsigned long mem_base, mem_len;
+       u8 *db_ptr = NULL;
+       unsigned long mem_base, mem_len, db_base, db_len;
        int pci_using_dac, i, err;
        int ring;
        struct netxen_recv_context *recv_ctx = NULL;
        struct netxen_rcv_desc_ctx *rcv_desc = NULL;
        struct netxen_cmd_buffer *cmd_buf_arr = NULL;
        u64 mac_addr[FLASH_NUM_PORTS + 1];
-       int valid_mac;
+       int valid_mac = 0;
+       static int netxen_cards_found = 0;
 
        printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+       /* In current scheme, we use only PCI function 0 */
+       if (PCI_FUNC(pdev->devfn) != 0) {
+               DPRINTK(ERR, "NetXen function %d will not be enabled.\n",
+                       PCI_FUNC(pdev->devfn));
+               return -ENODEV;
+       }
        if ((err = pci_enable_device(pdev)))
                return err;
        if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
@@ -130,10 +149,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_disable_pdev;
 
        pci_set_master(pdev);
-       if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) &&
-           (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0))
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
+       if (nx_p2_id == NX_P2_C1 &&
+           (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
+           (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
                pci_using_dac = 1;
-       else {
+       else {
                if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
                    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
                        goto err_out_free_res;
@@ -153,21 +174,34 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
            ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
 
        if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) {
-               DPRINTK(1, ERR,
+               DPRINTK(ERR,
                        "Cannot remap adapter memory aborting.:"
                        "0 -> %p, 1 -> %p, 2 -> %p\n",
                        mem_ptr0, mem_ptr1, mem_ptr2);
 
                err = -EIO;
-               if (mem_ptr0)
-                       iounmap(mem_ptr0);
-               if (mem_ptr1)
-                       iounmap(mem_ptr1);
-               if (mem_ptr2)
-                       iounmap(mem_ptr2);
-
-               goto err_out_free_res;
+               goto err_out_iounmap;
+       }
+       db_base = pci_resource_start(pdev, 4);  /* doorbell is on bar 4 */
+       db_len = pci_resource_len(pdev, 4);
+
+       if (db_len == 0) {
+               printk(KERN_ERR "%s: doorbell is disabled\n",
+                      netxen_nic_driver_name);
+               err = -EIO;
+               goto err_out_iounmap;
+       }
+       DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base,
+               db_len);
+
+       db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
+       if (db_ptr == 0UL) {
+               printk(KERN_ERR "%s: Failed to allocate doorbell map.",
+                      netxen_nic_driver_name);
+               err = -EIO;
+               goto err_out_iounmap;
        }
+       DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
 
 /*
  *      Allocate a adapter structure which will manage all the initialization
@@ -183,17 +217,24 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                       netxen_nic_driver_name,
                       (int)sizeof(struct netxen_adapter));
                err = -ENOMEM;
-               goto err_out_iounmap;
+               goto err_out_dbunmap;
        }
 
+       if (netxen_cards_found == 0) {
+               g_adapter = adapter;
+       }
        adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS;
        adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
        adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+       adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
 
        pci_set_drvdata(pdev, adapter);
 
        cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
        if (cmd_buf_arr == NULL) {
+               printk(KERN_ERR
+                      "%s: Could not allocate cmd_buf_arr memory:%d\n",
+                      netxen_nic_driver_name, (int)TX_RINGSIZE);
                err = -ENOMEM;
                goto err_out_free_adapter;
        }
@@ -220,11 +261,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
                                break;
 
+                       case RCV_RING_LRO:
+                               rcv_desc->max_rx_desc_count =
+                                   adapter->max_lro_rx_desc_count;
+                               rcv_desc->flags = RCV_DESC_LRO;
+                               rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
+                               rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+                               break;
+
                        }
                        rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
                            vmalloc(RCV_BUFFSIZE);
 
                        if (rcv_desc->rx_buf_arr == NULL) {
+                               printk(KERN_ERR "%s: Could not allocate"
+                                      "rcv_desc->rx_buf_arr memory:%d\n",
+                                      netxen_nic_driver_name,
+                                      (int)RCV_BUFFSIZE);
                                err = -ENOMEM;
                                goto err_out_free_rx_buffer;
                        }
@@ -233,30 +286,21 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        }
 
-       adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL);
-       if (adapter->ops == NULL) {
-               printk(KERN_ERR
-                      "%s: Could not allocate memory for adapter->ops:%d\n",
-                      netxen_nic_driver_name,
-                      (int)sizeof(struct netxen_adapter));
-               err = -ENOMEM;
-               goto err_out_free_rx_buffer;
-       }
-
        adapter->cmd_buf_arr = cmd_buf_arr;
        adapter->ahw.pci_base0 = mem_ptr0;
        adapter->ahw.pci_base1 = mem_ptr1;
        adapter->ahw.pci_base2 = mem_ptr2;
+       adapter->ahw.db_base = db_ptr;
+       adapter->ahw.db_len = db_len;
        spin_lock_init(&adapter->tx_lock);
        spin_lock_init(&adapter->lock);
+       netxen_initialize_adapter_sw(adapter);  /* initialize the buffers in adapter */
 #ifdef CONFIG_IA64
        netxen_pinit_from_rom(adapter, 0);
        udelay(500);
        netxen_load_firmware(adapter);
 #endif
 
-       /* initialize the buffers in adapter */
-       netxen_initialize_adapter_sw(adapter);
        /*
         * Set the CRB window to invalid. If any register in window 0 is
         * accessed it should set the window to 0 and then reset it to 1.
@@ -274,11 +318,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        adapter->ahw.xg_linkup = 0;
        adapter->watchdog_timer.function = &netxen_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
-       INIT_WORK(&adapter->watchdog_task,
-                 (void (*)(void *))netxen_watchdog_task, adapter);
+       INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
        adapter->ahw.pdev = pdev;
        adapter->proc_cmd_buf_counter = 0;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id);
+       adapter->ahw.revision_id = nx_p2_id;
 
        if (pci_enable_msi(pdev)) {
                adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
@@ -300,6 +343,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
 
+       /* do this before waking up pegs so that we have valid dummy dma addr */
+       err = netxen_initialize_adapter_offload(adapter);
+       if (err) {
+               goto err_out_free_dev;
+       }
+
        /* Unlock the HW, prompting the boot sequence */
        writel(1,
               NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
@@ -308,6 +357,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
 
        /* initialize the all the ports */
+       adapter->active_ports = 0;
 
        for (i = 0; i < adapter->ahw.max_ports; i++) {
                netdev = alloc_etherdev(sizeof(struct netxen_port));
@@ -373,14 +423,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                       netdev->dev_addr[4],
                                       netdev->dev_addr[5]);
                        } else {
-                               if (adapter->ops->macaddr_set)
-                                       adapter->ops->macaddr_set(port,
-                                                                 netdev->
-                                                                 dev_addr);
+                               if (adapter->macaddr_set)
+                                       adapter->macaddr_set(port,
+                                                            netdev->dev_addr);
                        }
                }
-               INIT_WORK(&adapter->tx_timeout_task,
-                         (void (*)(void *))netxen_tx_timeout_task, netdev);
+               adapter->netdev = netdev;
+               INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
                netif_carrier_off(netdev);
                netif_stop_queue(netdev);
 
@@ -392,7 +441,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        goto err_out_free_dev;
                }
                adapter->port_count++;
-               adapter->active_ports = 0;
                adapter->port[i] = port;
        }
 
@@ -413,6 +461,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
+       adapter->number = netxen_cards_found;
        adapter->driver_mismatch = 0;
 
        return 0;
@@ -427,7 +476,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        free_netdev(port->netdev);
                }
        }
-       kfree(adapter->ops);
+
+       netxen_free_adapter_offload(adapter);
 
       err_out_free_rx_buffer:
        for (i = 0; i < MAX_RCV_CTX; ++i) {
@@ -440,19 +490,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        }
                }
        }
-
        vfree(cmd_buf_arr);
 
-       kfree(adapter->port);
-
       err_out_free_adapter:
        pci_set_drvdata(pdev, NULL);
        kfree(adapter);
 
+      err_out_dbunmap:
+       if (db_ptr)
+               iounmap(db_ptr);
+
       err_out_iounmap:
-       iounmap(mem_ptr0);
-       iounmap(mem_ptr1);
-       iounmap(mem_ptr2);
+       if (mem_ptr0)
+               iounmap(mem_ptr0);
+       if (mem_ptr1)
+               iounmap(mem_ptr1);
+       if (mem_ptr2)
+               iounmap(mem_ptr2);
 
       err_out_free_res:
        pci_release_regions(pdev);
@@ -477,12 +531,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        netxen_nic_stop_all_ports(adapter);
        /* leave the hw in the same state as reboot */
-       netxen_pinit_from_rom(adapter, 0);
-       udelay(500);
        netxen_load_firmware(adapter);
-
-       if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
-               netxen_nic_disable_int(adapter);
+       netxen_free_adapter_offload(adapter);
 
        udelay(500);            /* Delay for a while to drain the DMA engines */
        for (i = 0; i < adapter->port_count; i++) {
@@ -499,6 +549,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                netxen_free_hw_resources(adapter);
 
+       iounmap(adapter->ahw.db_base);
        iounmap(adapter->ahw.pci_base0);
        iounmap(adapter->ahw.pci_base1);
        iounmap(adapter->ahw.pci_base2);
@@ -525,7 +576,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        }
 
        vfree(adapter->cmd_buf_arr);
-       kfree(adapter->ops);
        kfree(adapter);
 }
 
@@ -547,6 +597,8 @@ static int netxen_nic_open(struct net_device *netdev)
                        return -EIO;
                }
                netxen_nic_flash_print(adapter);
+               if (adapter->init_niu)
+                       adapter->init_niu(adapter);
 
                /* setup all the resources for the Phantom... */
                /* this include the descriptors for rcv, tx, and status */
@@ -557,32 +609,31 @@ static int netxen_nic_open(struct net_device *netdev)
                               err);
                        return err;
                }
-               if (adapter->ops->init_port
-                   && adapter->ops->init_port(adapter, port->portnum) != 0) {
+               if (adapter->init_port
+                   && adapter->init_port(adapter, port->portnum) != 0) {
                        printk(KERN_ERR "%s: Failed to initialize port %d\n",
                               netxen_nic_driver_name, port->portnum);
                        netxen_free_hw_resources(adapter);
                        return -EIO;
                }
-               if (adapter->ops->init_niu)
-                       adapter->ops->init_niu(adapter);
                for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
                        for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
                                netxen_post_rx_buffers(adapter, ctx, ring);
                }
-               adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
-       }
-       adapter->active_ports++;
-       if (adapter->active_ports == 1) {
+               adapter->irq = adapter->ahw.pdev->irq;
                err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
                                  adapter);
                if (err) {
                        printk(KERN_ERR "request_irq failed with: %d\n", err);
-                       adapter->active_ports--;
+                       netxen_free_hw_resources(adapter);
                        return err;
                }
-               adapter->irq = adapter->ahw.pdev->irq;
+
+               adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+       }
+       adapter->active_ports++;
+       if (adapter->active_ports == 1) {
                if (!adapter->driver_mismatch)
                        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -591,11 +642,14 @@ static int netxen_nic_open(struct net_device *netdev)
 
        /* Done here again so that even if phantom sw overwrote it,
         * we set it */
-       if (adapter->ops->macaddr_set)
-               adapter->ops->macaddr_set(port, netdev->dev_addr);
+       if (adapter->macaddr_set)
+               adapter->macaddr_set(port, netdev->dev_addr);
        netxen_nic_set_link_parameters(port);
 
        netxen_nic_set_multi(netdev);
+       if (adapter->set_mtu)
+               adapter->set_mtu(port, netdev->mtu);
+
        if (!adapter->driver_mismatch)
                netif_start_queue(netdev);
 
@@ -648,6 +702,7 @@ static int netxen_nic_close(struct net_device *netdev)
                        }
                        cmd_buff++;
                }
+               FLUSH_SCHEDULED_WORK();
                del_timer_sync(&adapter->watchdog_timer);
        }
 
@@ -668,7 +723,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc;
        int k;
        struct netxen_cmd_buffer *pbuf = NULL;
-       unsigned int tries = 0;
        static int dropped_packet = 0;
        int frag_count;
        u32 local_producer = 0;
@@ -730,7 +784,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        if (((skb->nh.iph)->ihl * sizeof(u32)) +
                            ((skb->h.th)->doff * sizeof(u32)) +
                            sizeof(struct ethhdr) >
-                           (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
+                           (sizeof(struct cmd_desc_type0) - 2)) {
                                no_of_desc++;
                        }
                }
@@ -741,27 +795,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if ((k + no_of_desc) >=
            ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
             last_cmd_consumer)) {
+               port->stats.nocmddescriptor++;
+               DPRINTK(ERR, "No command descriptors available,"
+                       " producer = %d, consumer = %d count=%llu,"
+                       " dropping packet\n", producer,
+                       adapter->last_cmd_consumer,
+                       port->stats.nocmddescriptor);
+
+               netif_stop_queue(netdev);
+               port->flags |= NETXEN_NETDEV_STATUS;
                spin_unlock_bh(&adapter->tx_lock);
-               if (tries == 0) {
-                       local_bh_disable();
-                       netxen_process_cmd_ring((unsigned long)adapter);
-                       local_bh_enable();
-                       ++tries;
-                       goto retry_getting_window;
-               } else {
-                       port->stats.nocmddescriptor++;
-                       DPRINTK(ERR, "No command descriptors available,"
-                               " producer = %d, consumer = %d count=%llu,"
-                               " dropping packet\n", producer,
-                               adapter->last_cmd_consumer,
-                               port->stats.nocmddescriptor);
-
-                       spin_lock_bh(&adapter->tx_lock);
-                       netif_stop_queue(netdev);
-                       port->flags |= NETXEN_NETDEV_STATUS;
-                       spin_unlock_bh(&adapter->tx_lock);
-                       return NETDEV_TX_BUSY;
-               }
+               return NETDEV_TX_BUSY;
        }
        k = get_index_range(k, max_tx_desc_count, no_of_desc);
        adapter->cmd_producer = k;
@@ -783,7 +827,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                pbuf->mss = 0;
                hwdesc->mss = 0;
        }
-       pbuf->no_of_descriptors = no_of_desc;
        pbuf->total_length = skb->len;
        pbuf->skb = skb;
        pbuf->cmd = TX_ETHER_PKT;
@@ -793,11 +836,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len,
                                      PCI_DMA_TODEVICE);
        buffrag->length = first_seg_len;
-       CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len);
-       hwdesc->num_of_buffers = frag_count;
-       hwdesc->opcode = TX_ETHER_PKT;
+       netxen_set_cmd_desc_totallength(hwdesc, skb->len);
+       netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
+       netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
 
-       CMD_DESC_PORT_WRT(hwdesc, port->portnum);
+       netxen_set_cmd_desc_port(hwdesc, port->portnum);
        hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
        hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
 
@@ -856,12 +899,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* For LSO, we need to copy the MAC/IP/TCP headers into
         * the descriptor ring
         */
-       if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) {
+       if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
+           == TX_TCP_LSO) {
                int hdr_len, first_hdr_len, more_hdr;
                hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
-               if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
-                       first_hdr_len =
-                           sizeof(struct cmd_desc_type0) - NET_IP_ALIGN;
+               if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
+                       first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
                        more_hdr = 1;
                } else {
                        first_hdr_len = hdr_len;
@@ -871,7 +914,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                hwdesc = &hw->cmd_desc_head[producer];
 
                /* copy the first 64 bytes */
-               memcpy(((void *)hwdesc) + NET_IP_ALIGN,
+               memcpy(((void *)hwdesc) + 2,
                       (void *)(skb->data), first_hdr_len);
                producer = get_next_index(producer, max_tx_desc_count);
 
@@ -887,7 +930,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }
        spin_lock_bh(&adapter->tx_lock);
        port->stats.txbytes +=
-           CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]);
+           netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]);
        /* Code to update the adapter considering how many producer threads
           are currently working */
        if ((--adapter->num_threads) == 0) {
@@ -897,20 +940,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                       NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
                wmb();
                adapter->total_threads = 0;
-       } else {
-               u32 crb_producer = 0;
-               crb_producer =
-                   readl(NETXEN_CRB_NORMALIZE
-                         (adapter, CRB_CMD_PRODUCER_OFFSET));
-               if (crb_producer == local_producer) {
-                       crb_producer = get_index_range(crb_producer,
-                                                      max_tx_desc_count,
-                                                      no_of_desc);
-                       writel(crb_producer,
-                              NETXEN_CRB_NORMALIZE(adapter,
-                                                   CRB_CMD_PRODUCER_OFFSET));
-                       wmb();
-               }
        }
 
        port->stats.xmitfinished++;
@@ -927,29 +956,36 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 static void netxen_watchdog(unsigned long v)
 {
        struct netxen_adapter *adapter = (struct netxen_adapter *)v;
-       schedule_work(&adapter->watchdog_task);
+       if (adapter != g_adapter) {
+               printk("%s: ***BUG*** adapter[%p] != g_adapter[%p]\n",
+                      __FUNCTION__, adapter, g_adapter);
+               return;
+       }
+
+       SCHEDULE_WORK(&adapter->watchdog_task);
 }
 
 static void netxen_tx_timeout(struct net_device *netdev)
 {
        struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
-       struct netxen_adapter *adapter = port->adapter;
 
-       schedule_work(&adapter->tx_timeout_task);
+       SCHEDULE_WORK(&port->adapter->tx_timeout_task);
 }
 
-static void netxen_tx_timeout_task(struct net_device *netdev)
+static void netxen_tx_timeout_task(struct work_struct *work)
 {
-       struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+       struct netxen_adapter *adapter =
+               container_of(work, struct netxen_adapter, tx_timeout_task);
+       struct net_device *netdev = adapter->netdev;
        unsigned long flags;
 
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
               netxen_nic_driver_name, netdev->name);
 
-       spin_lock_irqsave(&port->adapter->lock, flags);
+       spin_lock_irqsave(&adapter->lock, flags);
        netxen_nic_close(netdev);
        netxen_nic_open(netdev);
-       spin_unlock_irqrestore(&port->adapter->lock, flags);
+       spin_unlock_irqrestore(&adapter->lock, flags);
        netdev->trans_start = jiffies;
        netif_wake_queue(netdev);
 }
@@ -966,6 +1002,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
        if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
                int count = 0;
                u32 mask;
+               mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+               if ((mask & 0x80) == 0) {
+                       /* not our interrupt */
+                       return ret;
+               }
                netxen_nic_disable_int(adapter);
                /* Window = 0 or 1 */
                do {
@@ -1025,7 +1066,10 @@ irqreturn_t netxen_intr(int irq, void *data)
                netdev = port->netdev;
 
                /* process our status queue (for all 4 ports) */
-               netxen_handle_int(adapter, netdev);
+               if (netif_running(netdev)) {
+                       netxen_handle_int(adapter, netdev);
+                       break;
+               }
        }
 
        return IRQ_HANDLED;
@@ -1039,11 +1083,12 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
        int done = 1;
        int ctx;
        int this_work_done;
+       int work_done = 0;
 
        DPRINTK(INFO, "polling for %d descriptors\n", *budget);
        port->stats.polled++;
 
-       adapter->work_done = 0;
+       work_done = 0;
        for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
                /*
                 * Fairness issue. This will give undue weight to the
@@ -1060,20 +1105,20 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
                this_work_done = netxen_process_rcv_ring(adapter, ctx,
                                                         work_to_do /
                                                         MAX_RCV_CTX);
-               adapter->work_done += this_work_done;
+               work_done += this_work_done;
        }
 
-       netdev->quota -= adapter->work_done;
-       *budget -= adapter->work_done;
+       netdev->quota -= work_done;
+       *budget -= work_done;
 
-       if (adapter->work_done >= work_to_do
-           && netxen_nic_rx_has_work(adapter) != 0)
+       if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
                done = 0;
 
-       netxen_process_cmd_ring((unsigned long)adapter);
+       if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
+               done = 0;
 
        DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
-               adapter->work_done, work_to_do);
+               work_done, work_to_do);
        if (done) {
                netif_rx_complete(netdev);
                netxen_nic_enable_int(adapter);
@@ -1116,8 +1161,9 @@ netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
                if (ifr->ifr_data) {
                        sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP,
                                port->portnum);
-                       nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name,
-                                               NETXEN_NIC_NAME_LEN);
+                       nr_bytes =
+                           copy_to_user((char __user *)ifr->ifr_data, dev_name,
+                                        NETXEN_NIC_NAME_LEN);
                        if (nr_bytes)
                                err = -EIO;
 
@@ -1144,6 +1190,9 @@ static struct pci_driver netxen_driver = {
 
 static int __init netxen_init_module(void)
 {
+       if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
+               return -ENOMEM;
+
        return pci_module_init(&netxen_driver);
 }
 
@@ -1154,7 +1203,7 @@ static void __exit netxen_exit_module(void)
        /*
         * Wait for some time to allow the dma to drain, if any.
         */
-       mdelay(5);
+       destroy_workqueue(netxen_workq);
        pci_unregister_driver(&netxen_driver);
 }
 
index 7950a04..4987dc7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
 
 static long phy_lock_timeout = 100000000;
 
-static inline int phy_lock(void)
+static inline int phy_lock(struct netxen_adapter *adapter)
 {
        int i;
        int done = 0, timeout = 0;
 
        while (!done) {
-               done = readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
+               done =
+                   readl(pci_base_offset
+                         (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
                if (done == 1)
                        break;
                if (timeout >= phy_lock_timeout) {
@@ -61,13 +63,15 @@ static inline int phy_lock(void)
                }
        }
 
-       writel(NETXEN_PHY_LOCK_ID, (void __iomem *)PHY_LOCK_DRIVER);
+       writel(PHY_LOCK_DRIVER,
+              NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
        return 0;
 }
 
-static inline int phy_unlock(void)
+static inline int phy_unlock(struct netxen_adapter *adapter)
 {
-       readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
+       readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
+
        return 0;
 }
 
@@ -95,7 +99,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
        __le32 status;
        __le32 mac_cfg0;
 
-       if (phy_lock() != 0) {
+       if (phy_lock(adapter) != 0) {
                return -1;
        }
 
@@ -162,7 +166,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
                                           NETXEN_NIU_GB_MAC_CONFIG_0(0),
                                           &mac_cfg0, 4))
                        return -EIO;
-       phy_unlock();
+       phy_unlock(adapter);
        return result;
 }
 
@@ -399,8 +403,8 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 {
        int result = 0;
        __le32 status;
-       if (adapter->ops->disable_phy_interrupts)
-               adapter->ops->disable_phy_interrupts(adapter, port);
+       if (adapter->disable_phy_interrupts)
+               adapter->disable_phy_interrupts(adapter, port);
        mdelay(2);
 
        if (0 ==
@@ -612,7 +616,7 @@ int netxen_niu_macaddr_set(struct netxen_port *port,
        __le32 temp = 0;
        struct netxen_adapter *adapter = port->adapter;
        int phy = port->portnum;
-       unsigned char mac_addr[MAX_ADDR_LEN];
+       unsigned char mac_addr[6];
        int i;
 
        for (i = 0; i < 10; i++) {
@@ -631,7 +635,7 @@ int netxen_niu_macaddr_set(struct netxen_port *port,
 
                netxen_niu_macaddr_get(adapter, phy,
                                       (netxen_ethernet_macaddr_t *) mac_addr);
-               if (memcmp(mac_addr, addr, MAX_ADDR_LEN == 0))
+               if (memcmp(mac_addr, addr, 6) == 0)
                        break;
        }
 
index 8181d43..7879f85 100644 (file)
 /* 
  * CRB Registers or queue message done only at initialization time.
  */
+#define NIC_CRB_BASE               NETXEN_CAM_RAM(0x200)
+#define NETXEN_NIC_REG(X)             (NIC_CRB_BASE+(X))
 
-/*
- * The following 2 are the base adresses for the CRB registers and their
- * offsets will be added to get addresses for the index addresses.
- */
-#define NIC_CRB_BASE_PORT1     NETXEN_CAM_RAM(0x200)
-#define NIC_CRB_BASE_PORT2     NETXEN_CAM_RAM(0x250)
+#define CRB_PHAN_CNTRL_LO_OFFSET    NETXEN_NIC_REG(0x00)
+#define CRB_PHAN_CNTRL_HI_OFFSET    NETXEN_NIC_REG(0x04)
+#define CRB_CMD_PRODUCER_OFFSET     NETXEN_NIC_REG(0x08)
+#define CRB_CMD_CONSUMER_OFFSET     NETXEN_NIC_REG(0x0c)
+#define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)       /* C0 EPG BUG  */
+#define CRB_PAUSE_ADDR_HI           NETXEN_NIC_REG(0x14)
+#define CRB_HOST_CMD_ADDR_HI        NETXEN_NIC_REG(0x18)       /* host add:cmd ring */
+#define CRB_HOST_CMD_ADDR_LO        NETXEN_NIC_REG(0x1c)
+#define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)       /* 4 regs for perf */
+#define CRB_CMD_DMA_LOOP            NETXEN_NIC_REG(0x24)
+#define CRB_RCV_INTR_LOOP           NETXEN_NIC_REG(0x28)
+#define CRB_RCV_DMA_LOOP            NETXEN_NIC_REG(0x2c)
+#define CRB_ENABLE_TX_INTR          NETXEN_NIC_REG(0x30)       /* phantom init status */
+#define CRB_MMAP_ADDR_3             NETXEN_NIC_REG(0x34)
+#define CRB_CMDPEG_CMDRING          NETXEN_NIC_REG(0x38)
+#define CRB_HOST_DUMMY_BUF_ADDR_HI  NETXEN_NIC_REG(0x3c)
+#define CRB_HOST_DUMMY_BUF_ADDR_LO  NETXEN_NIC_REG(0x40)
+#define CRB_MMAP_ADDR_0             NETXEN_NIC_REG(0x44)
+#define CRB_MMAP_ADDR_1             NETXEN_NIC_REG(0x48)
+#define CRB_MMAP_ADDR_2             NETXEN_NIC_REG(0x4c)
+#define CRB_CMDPEG_STATE            NETXEN_NIC_REG(0x50)
+#define CRB_MMAP_SIZE_0             NETXEN_NIC_REG(0x54)
+#define CRB_MMAP_SIZE_1             NETXEN_NIC_REG(0x58)
+#define CRB_MMAP_SIZE_2             NETXEN_NIC_REG(0x5c)
+#define CRB_MMAP_SIZE_3             NETXEN_NIC_REG(0x60)
+#define CRB_GLOBAL_INT_COAL         NETXEN_NIC_REG(0x64)       /* interrupt coalescing */
+#define CRB_INT_COAL_MODE           NETXEN_NIC_REG(0x68)
+#define CRB_MAX_RCV_BUFS            NETXEN_NIC_REG(0x6c)
+#define CRB_TX_INT_THRESHOLD        NETXEN_NIC_REG(0x70)
+#define CRB_RX_PKT_TIMER            NETXEN_NIC_REG(0x74)
+#define CRB_TX_PKT_TIMER            NETXEN_NIC_REG(0x78)
+#define CRB_RX_PKT_CNT              NETXEN_NIC_REG(0x7c)
+#define CRB_RX_TMR_CNT              NETXEN_NIC_REG(0x80)
+#define CRB_RX_LRO_TIMER            NETXEN_NIC_REG(0x84)
+#define CRB_RX_LRO_MID_TIMER        NETXEN_NIC_REG(0x88)
+#define CRB_DMA_MAX_RCV_BUFS        NETXEN_NIC_REG(0x8c)
+#define CRB_MAX_DMA_ENTRIES         NETXEN_NIC_REG(0x90)
+#define CRB_XG_STATE                NETXEN_NIC_REG(0x94)       /* XG Link status */
+#define CRB_AGENT_GO                NETXEN_NIC_REG(0x98)       /* NIC pkt gen agent */
+#define CRB_AGENT_TX_SIZE           NETXEN_NIC_REG(0x9c)
+#define CRB_AGENT_TX_TYPE           NETXEN_NIC_REG(0xa0)
+#define CRB_AGENT_TX_ADDR           NETXEN_NIC_REG(0xa4)
+#define CRB_AGENT_TX_MSS            NETXEN_NIC_REG(0xa8)
+#define CRB_TX_STATE                NETXEN_NIC_REG(0xac)       /* Debug -performance */
+#define CRB_TX_COUNT                NETXEN_NIC_REG(0xb0)
+#define CRB_RX_STATE                NETXEN_NIC_REG(0xb4)
+#define CRB_RX_PERF_DEBUG_1         NETXEN_NIC_REG(0xb8)
+#define CRB_RX_LRO_CONTROL          NETXEN_NIC_REG(0xbc)       /* LRO On/OFF */
+#define CRB_RX_LRO_START_NUM        NETXEN_NIC_REG(0xc0)
+#define CRB_MPORT_MODE              NETXEN_NIC_REG(0xc4)       /* Multiport Mode */
+#define CRB_CMD_RING_SIZE           NETXEN_NIC_REG(0xc8)
+#define CRB_INT_VECTOR              NETXEN_NIC_REG(0xd4)
+#define CRB_CTX_RESET               NETXEN_NIC_REG(0xd8)
+#define CRB_HOST_STS_PROD           NETXEN_NIC_REG(0xdc)
+#define CRB_HOST_STS_CONS           NETXEN_NIC_REG(0xe0)
+#define CRB_PEG_CMD_PROD            NETXEN_NIC_REG(0xe4)
+#define CRB_PEG_CMD_CONS            NETXEN_NIC_REG(0xe8)
+#define CRB_HOST_BUFFER_PROD        NETXEN_NIC_REG(0xec)
+#define CRB_HOST_BUFFER_CONS        NETXEN_NIC_REG(0xf0)
+#define CRB_JUMBO_BUFFER_PROD       NETXEN_NIC_REG(0xf4)
+#define CRB_JUMBO_BUFFER_CONS       NETXEN_NIC_REG(0xf8)
 
-#define NETXEN_NIC_REG(X)      (NIC_CRB_BASE_PORT1+(X))
+#define CRB_CMD_PRODUCER_OFFSET_1   NETXEN_NIC_REG(0x1ac)
+#define CRB_CMD_CONSUMER_OFFSET_1   NETXEN_NIC_REG(0x1b0)
+#define CRB_TEMP_STATE              NETXEN_NIC_REG(0x1b4)
 
 /*
  * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
  * on the Phantom.
  */
 
-#define CRB_PHAN_CNTRL_LO_OFFSET       NETXEN_NIC_REG(0x00)
-#define CRB_PHAN_CNTRL_HI_OFFSET       NETXEN_NIC_REG(0x04)
-
-/* point to the indexes */
-#define CRB_CMD_PRODUCER_OFFSET                NETXEN_NIC_REG(0x08)
-#define CRB_CMD_CONSUMER_OFFSET                NETXEN_NIC_REG(0x0c)
-
-#define CRB_PAUSE_ADDR_LO              NETXEN_NIC_REG(0x10)
-#define CRB_PAUSE_ADDR_HI              NETXEN_NIC_REG(0x14)
-
-/* address of command descriptors in the host memory */
-#define CRB_HOST_CMD_ADDR_HI           NETXEN_NIC_REG(0x30)
-#define CRB_HOST_CMD_ADDR_LO           NETXEN_NIC_REG(0x34)
-
-/* The following 4 CRB registers are for doing performance coal */
-#define CRB_CMD_INTR_LOOP              NETXEN_NIC_REG(0x38)
-#define CRB_CMD_DMA_LOOP               NETXEN_NIC_REG(0x3c)
-#define CRB_RCV_INTR_LOOP              NETXEN_NIC_REG(0x40)
-#define CRB_RCV_DMA_LOOP               NETXEN_NIC_REG(0x44)
-
-/* Needed by the host to find out the state of Phantom's initialization */
-#define CRB_ENABLE_TX_INTR             NETXEN_NIC_REG(0x4c)
-#define CRB_CMDPEG_STATE               NETXEN_NIC_REG(0x50)
-#define CRB_CMDPEG_CMDRING             NETXEN_NIC_REG(0x54)
-
-/* Interrupt coalescing parameters */
-#define CRB_GLOBAL_INT_COAL            NETXEN_NIC_REG(0x80)
-#define CRB_INT_COAL_MODE              NETXEN_NIC_REG(0x84)
-#define CRB_MAX_RCV_BUFS               NETXEN_NIC_REG(0x88)
-#define CRB_TX_INT_THRESHOLD           NETXEN_NIC_REG(0x8c)
-#define CRB_RX_PKT_TIMER               NETXEN_NIC_REG(0x90)
-#define CRB_TX_PKT_TIMER               NETXEN_NIC_REG(0x94)
-#define CRB_RX_PKT_CNT                 NETXEN_NIC_REG(0x98)
-#define CRB_RX_TMR_CNT                 NETXEN_NIC_REG(0x9c)
-#define CRB_INT_THRESH          NETXEN_NIC_REG(0xa4)
-
-/* Register for communicating XG link status */
-#define CRB_XG_STATE                   NETXEN_NIC_REG(0xa0)
-
-/* Register for communicating card temperature */
-/* Upper 16 bits are temperature value. Lower 16 bits are the state */
-#define CRB_TEMP_STATE          NETXEN_NIC_REG(0xa8)
-#define nx_get_temp_val(x)          ((x) >> 16)
-#define nx_get_temp_state(x)      ((x) & 0xffff)
-#define nx_encode_temp(val, state)     (((val) << 16) | (state))
-
-/* Debug registers for controlling NIC pkt gen agent */
-#define CRB_AGENT_GO                   NETXEN_NIC_REG(0xb0)
-#define CRB_AGENT_TX_SIZE              NETXEN_NIC_REG(0xb4)
-#define CRB_AGENT_TX_TYPE              NETXEN_NIC_REG(0xb8)
-#define CRB_AGENT_TX_ADDR              NETXEN_NIC_REG(0xbc)
-#define CRB_AGENT_TX_MSS               NETXEN_NIC_REG(0xc0)
-
-/* Debug registers for observing NIC performance */
-#define CRB_TX_STATE                   NETXEN_NIC_REG(0xd0)
-#define CRB_TX_COUNT                   NETXEN_NIC_REG(0xd4)
-#define CRB_RX_STATE                   NETXEN_NIC_REG(0xd8)
+#define nx_get_temp_val(x)             ((x) >> 16)
+#define nx_get_temp_state(x)           ((x) & 0xffff)
+#define nx_encode_temp(val, state)     (((val) << 16) | (state))
 
 /* CRB registers per Rcv Descriptor ring */
 struct netxen_rcv_desc_crb {
        u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
        u32 crb_rcv_consumer_offset;
        u32 crb_globalrcv_ring;
+       u32 crb_rcv_ring_size;
 };
 
 /*
- * CRB registers used by the receive peg logic. One instance of these
- * needs to be instantiated per instance of the receive peg.
+ * CRB registers used by the receive peg logic.
  */
 
 struct netxen_recv_crb {
@@ -127,6 +132,7 @@ struct netxen_recv_crb {
        u32 crb_rcv_status_producer;
        u32 crb_rcv_status_consumer;
        u32 crb_rcvpeg_state;
+       u32 crb_status_ring_size;
 };
 
 #if defined(DEFINE_GLOBAL_RECV_CRB)
@@ -139,30 +145,48 @@ struct netxen_recv_crb recv_crb_registers[] = {
         {
          {
           /* crb_rcv_producer_offset: */
-          NETXEN_NIC_REG(0x18),
+          NETXEN_NIC_REG(0x100),
           /* crb_rcv_consumer_offset: */
-          NETXEN_NIC_REG(0x1c),
+          NETXEN_NIC_REG(0x104),
           /* crb_gloablrcv_ring: */
-          NETXEN_NIC_REG(0x20),
+          NETXEN_NIC_REG(0x108),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x10c),
+
           },
          /* Jumbo frames */
          {
           /* crb_rcv_producer_offset: */
-          NETXEN_NIC_REG(0x100),
+          NETXEN_NIC_REG(0x110),
           /* crb_rcv_consumer_offset: */
-          NETXEN_NIC_REG(0x104),
+          NETXEN_NIC_REG(0x114),
           /* crb_gloablrcv_ring: */
-          NETXEN_NIC_REG(0x108),
+          NETXEN_NIC_REG(0x118),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x11c),
+          },
+         /* LRO */
+         {
+          /* crb_rcv_producer_offset: */
+          NETXEN_NIC_REG(0x120),
+          /* crb_rcv_consumer_offset: */
+          NETXEN_NIC_REG(0x124),
+          /* crb_gloablrcv_ring: */
+          NETXEN_NIC_REG(0x128),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x12c),
           }
          },
         /* crb_rcvstatus_ring: */
-        NETXEN_NIC_REG(0x24),
+        NETXEN_NIC_REG(0x130),
         /* crb_rcv_status_producer: */
-        NETXEN_NIC_REG(0x28),
+        NETXEN_NIC_REG(0x134),
         /* crb_rcv_status_consumer: */
-        NETXEN_NIC_REG(0x2c),
+        NETXEN_NIC_REG(0x138),
         /* crb_rcvpeg_state: */
-        NETXEN_NIC_REG(0x48),
+        NETXEN_NIC_REG(0x13c),
+        /* crb_status_ring_size */
+        NETXEN_NIC_REG(0x140),
 
         },
        /*
@@ -173,34 +197,66 @@ struct netxen_recv_crb recv_crb_registers[] = {
         {
          {
           /* crb_rcv_producer_offset: */
-          NETXEN_NIC_REG(0x80),
+          NETXEN_NIC_REG(0x144),
           /* crb_rcv_consumer_offset: */
-          NETXEN_NIC_REG(0x84),
+          NETXEN_NIC_REG(0x148),
           /* crb_globalrcv_ring: */
-          NETXEN_NIC_REG(0x88),
+          NETXEN_NIC_REG(0x14c),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x150),
+
           },
          /* Jumbo frames */
          {
           /* crb_rcv_producer_offset: */
-          NETXEN_NIC_REG(0x10C),
+          NETXEN_NIC_REG(0x154),
           /* crb_rcv_consumer_offset: */
-          NETXEN_NIC_REG(0x110),
+          NETXEN_NIC_REG(0x158),
           /* crb_globalrcv_ring: */
-          NETXEN_NIC_REG(0x114),
+          NETXEN_NIC_REG(0x15c),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x160),
+          },
+         /* LRO */
+         {
+          /* crb_rcv_producer_offset: */
+          NETXEN_NIC_REG(0x164),
+          /* crb_rcv_consumer_offset: */
+          NETXEN_NIC_REG(0x168),
+          /* crb_globalrcv_ring: */
+          NETXEN_NIC_REG(0x16c),
+          /* crb_rcv_ring_size */
+          NETXEN_NIC_REG(0x170),
           }
+
          },
         /* crb_rcvstatus_ring: */
-        NETXEN_NIC_REG(0x8c),
+        NETXEN_NIC_REG(0x174),
         /* crb_rcv_status_producer: */
-        NETXEN_NIC_REG(0x90),
+        NETXEN_NIC_REG(0x178),
         /* crb_rcv_status_consumer: */
-        NETXEN_NIC_REG(0x94),
+        NETXEN_NIC_REG(0x17c),
         /* crb_rcvpeg_state: */
-        NETXEN_NIC_REG(0x98),
+        NETXEN_NIC_REG(0x180),
+        /* crb_status_ring_size */
+        NETXEN_NIC_REG(0x184),
+
         },
 };
+
+u64 ctx_addr_sig_regs[][3] = {
+       {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
+       {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
+       {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
+       {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+};
+
 #else
 extern struct netxen_recv_crb recv_crb_registers[];
+extern u64 ctx_addr_sig_regs[][3];
+#define CRB_CTX_ADDR_REG_LO            (ctx_addr_sig_regs[0][0])
+#define CRB_CTX_ADDR_REG_HI            (ctx_addr_sig_regs[0][2])
+#define CRB_CTX_SIGNATURE_REG       (ctx_addr_sig_regs[0][1])
 #endif                         /* DEFINE_GLOBAL_RECEIVE_CRB */
 
 /*
index 26e42f6..196993a 100644 (file)
@@ -1335,7 +1335,7 @@ int __init init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(dev_ni52);
        release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE);
index 340ad0d..1578f4d 100644 (file)
@@ -1259,7 +1259,7 @@ int __init init_module(void)
        return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(dev_ni65);
        cleanup_card(dev_ni65);
index b0127c7..568daeb 100644 (file)
@@ -414,10 +414,10 @@ struct rx_info {
 
        struct sk_buff  *skbs[NR_RX_DESC];
 
-       u32             *next_rx_desc;
+       __le32          *next_rx_desc;
        u16             next_rx, next_empty;
 
-       u32             *descs;
+       __le32          *descs;
        dma_addr_t      phy_descs;
 };
 
@@ -427,6 +427,7 @@ struct ns83820 {
        u8                      __iomem *base;
 
        struct pci_dev          *pci_dev;
+       struct net_device       *ndev;
 
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
        struct vlan_group       *vlgrp;
@@ -459,7 +460,7 @@ struct ns83820 {
        struct sk_buff  *tx_skbs[NR_TX_DESC];
 
        char            pad[16] __attribute__((aligned(16)));
-       u32             *tx_descs;
+       __le32          *tx_descs;
        dma_addr_t      tx_phy_descs;
 
        struct timer_list       tx_watchdog;
@@ -533,7 +534,7 @@ static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid
  * conditions, still route realtime traffic with as low jitter as
  * possible.
  */
-static inline void build_rx_desc(struct ns83820 *dev, u32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts)
+static inline void build_rx_desc(struct ns83820 *dev, __le32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts)
 {
        desc_addr_set(desc + DESC_LINK, link);
        desc_addr_set(desc + DESC_BUFPTR, buf);
@@ -547,7 +548,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
 {
        unsigned next_empty;
        u32 cmdsts;
-       u32 *sg;
+       __le32 *sg;
        dma_addr_t buf;
 
        next_empty = dev->rx_info.next_empty;
@@ -631,10 +632,10 @@ static void fastcall rx_refill_atomic(struct net_device *ndev)
 }
 
 /* REFILL */
-static inline void queue_refill(void *_dev)
+static inline void queue_refill(struct work_struct *work)
 {
-       struct net_device *ndev = _dev;
-       struct ns83820 *dev = PRIV(ndev);
+       struct ns83820 *dev = container_of(work, struct ns83820, tq_refill);
+       struct net_device *ndev = dev->ndev;
 
        rx_refill(ndev, GFP_KERNEL);
        if (dev->rx_info.up)
@@ -874,7 +875,8 @@ static void fastcall rx_irq(struct net_device *ndev)
        struct rx_info *info = &dev->rx_info;
        unsigned next_rx;
        int rx_rc, len;
-       u32 cmdsts, *desc;
+       u32 cmdsts;
+       __le32 *desc;
        unsigned long flags;
        int nr = 0;
 
@@ -1010,7 +1012,8 @@ static inline void kick_tx(struct ns83820 *dev)
 static void do_tx_done(struct net_device *ndev)
 {
        struct ns83820 *dev = PRIV(ndev);
-       u32 cmdsts, tx_done_idx, *desc;
+       u32 cmdsts, tx_done_idx;
+       __le32 *desc;
 
        dprintk("do_tx_done(%p)\n", ndev);
        tx_done_idx = dev->tx_done_idx;
@@ -1077,7 +1080,7 @@ static void ns83820_cleanup_tx(struct ns83820 *dev)
                struct sk_buff *skb = dev->tx_skbs[i];
                dev->tx_skbs[i] = NULL;
                if (skb) {
-                       u32 *desc = dev->tx_descs + (i * DESC_SIZE);
+                       __le32 *desc = dev->tx_descs + (i * DESC_SIZE);
                        pci_unmap_single(dev->pci_dev,
                                        desc_addr_get(desc + DESC_BUFPTR),
                                        le32_to_cpu(desc[DESC_CMDSTS]) & CMDSTS_LEN_MASK,
@@ -1107,7 +1110,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        skb_frag_t *frag;
        int stopped = 0;
        int do_intr = 0;
-       volatile u32 *first_desc;
+       volatile __le32 *first_desc;
 
        dprintk("ns83820_hard_start_xmit\n");
 
@@ -1180,7 +1183,7 @@ again:
        first_desc = dev->tx_descs + (free_idx * DESC_SIZE);
 
        for (;;) {
-               volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
+               volatile __le32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
 
                dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,
                        (unsigned long long)buf);
@@ -1455,7 +1458,8 @@ static int ns83820_stop(struct net_device *ndev)
 static void ns83820_tx_timeout(struct net_device *ndev)
 {
        struct ns83820 *dev = PRIV(ndev);
-        u32 tx_done_idx, *desc;
+        u32 tx_done_idx;
+       __le32 *desc;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->tx_lock, flags);
@@ -1841,6 +1845,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
 
        ndev = alloc_etherdev(sizeof(struct ns83820));
        dev = PRIV(ndev);
+       dev->ndev = ndev;
        err = -ENOMEM;
        if (!dev)
                goto out;
@@ -1853,7 +1858,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
        SET_MODULE_OWNER(ndev);
        SET_NETDEV_DEV(ndev, &pci_dev->dev);
 
-       INIT_WORK(&dev->tq_refill, queue_refill, ndev);
+       INIT_WORK(&dev->tq_refill, queue_refill);
        tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev);
 
        err = pci_enable_device(pci_dev);
index 6981340..8478dca 100644 (file)
@@ -332,6 +332,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
  */
 
 typedef struct local_info_t {
+       struct net_device       *dev;
        struct pcmcia_device    *p_dev;
     dev_node_t node;
     struct net_device_stats stats;
@@ -353,7 +354,7 @@ typedef struct local_info_t {
  */
 static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void do_tx_timeout(struct net_device *dev);
-static void xirc2ps_tx_timeout_task(void *data);
+static void xirc2ps_tx_timeout_task(struct work_struct *work);
 static struct net_device_stats *do_get_stats(struct net_device *dev);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -567,6 +568,7 @@ xirc2ps_probe(struct pcmcia_device *link)
     if (!dev)
            return -ENOMEM;
     local = netdev_priv(dev);
+    local->dev = dev;
     local->p_dev = link;
     link->priv = dev;
 
@@ -591,7 +593,7 @@ xirc2ps_probe(struct pcmcia_device *link)
 #ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = do_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
-    INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
+    INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task);
 #endif
 
     return xirc2ps_config(link);
@@ -1324,9 +1326,11 @@ xirc2ps_interrupt(int irq, void *dev_id)
 /*====================================================================*/
 
 static void
-xirc2ps_tx_timeout_task(void *data)
+xirc2ps_tx_timeout_task(struct work_struct *work)
 {
-    struct net_device *dev = data;
+       local_info_t *local =
+               container_of(work, local_info_t, tx_timeout_task);
+       struct net_device *dev = local->dev;
     /* reset the card */
     do_reset(dev,1);
     dev->trans_start = jiffies;
index 88237bd..e175f39 100644 (file)
@@ -397,7 +397,7 @@ out_unlock:
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-static void phy_change(void *data);
+static void phy_change(struct work_struct *work);
 static void phy_timer(unsigned long data);
 
 /* phy_start_machine:
@@ -555,7 +555,7 @@ int phy_start_interrupts(struct phy_device *phydev)
 {
        int err = 0;
 
-       INIT_WORK(&phydev->phy_queue, phy_change, phydev);
+       INIT_WORK(&phydev->phy_queue, phy_change);
 
        if (request_irq(phydev->irq, phy_interrupt,
                                IRQF_SHARED,
@@ -587,8 +587,7 @@ int phy_stop_interrupts(struct phy_device *phydev)
         * Finish any pending work; we might have been scheduled
         * to be called from keventd ourselves, though.
         */
-       if (!current_is_keventd())
-               flush_scheduled_work();
+       run_scheduled_work(&phydev->phy_queue);
 
        free_irq(phydev->irq, phydev);
 
@@ -598,10 +597,11 @@ EXPORT_SYMBOL(phy_stop_interrupts);
 
 
 /* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void phy_change(void *data)
+static void phy_change(struct work_struct *work)
 {
        int err;
-       struct phy_device *phydev = data;
+       struct phy_device *phydev =
+               container_of(work, struct phy_device, phy_queue);
 
        err = phy_disable_interrupts(phydev);
 
index 71afb27..6bb085f 100644 (file)
@@ -138,9 +138,9 @@ static const unsigned int net_debug = NET_DEBUG;
 #define PLIP_NIBBLE_WAIT        3000
 
 /* Bottom halves */
-static void plip_kick_bh(struct net_device *dev);
-static void plip_bh(struct net_device *dev);
-static void plip_timer_bh(struct net_device *dev);
+static void plip_kick_bh(struct work_struct *work);
+static void plip_bh(struct work_struct *work);
+static void plip_timer_bh(struct work_struct *work);
 
 /* Interrupt handler */
 static void plip_interrupt(int irq, void *dev_id);
@@ -207,9 +207,10 @@ struct plip_local {
 
 struct net_local {
        struct net_device_stats enet_stats;
+       struct net_device *dev;
        struct work_struct immediate;
-       struct work_struct deferred;
-       struct work_struct timer;
+       struct delayed_work deferred;
+       struct delayed_work timer;
        struct plip_local snd_data;
        struct plip_local rcv_data;
        struct pardevice *pardev;
@@ -306,11 +307,11 @@ plip_init_netdev(struct net_device *dev)
        nl->nibble      = PLIP_NIBBLE_WAIT;
 
        /* Initialize task queue structures */
-       INIT_WORK(&nl->immediate, (void (*)(void *))plip_bh, dev);
-       INIT_WORK(&nl->deferred, (void (*)(void *))plip_kick_bh, dev);
+       INIT_WORK(&nl->immediate, plip_bh);
+       INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh);
 
        if (dev->irq == -1)
-               INIT_WORK(&nl->timer, (void (*)(void *))plip_timer_bh, dev);
+               INIT_DELAYED_WORK(&nl->timer, plip_timer_bh);
 
        spin_lock_init(&nl->lock);
 }
@@ -319,9 +320,10 @@ plip_init_netdev(struct net_device *dev)
    This routine is kicked by do_timer().
    Request `plip_bh' to be invoked. */
 static void
-plip_kick_bh(struct net_device *dev)
+plip_kick_bh(struct work_struct *work)
 {
-       struct net_local *nl = netdev_priv(dev);
+       struct net_local *nl =
+               container_of(work, struct net_local, deferred.work);
 
        if (nl->is_deferred)
                schedule_work(&nl->immediate);
@@ -362,9 +364,9 @@ static const plip_func connection_state_table[] =
 
 /* Bottom half handler of PLIP. */
 static void
-plip_bh(struct net_device *dev)
+plip_bh(struct work_struct *work)
 {
-       struct net_local *nl = netdev_priv(dev);
+       struct net_local *nl = container_of(work, struct net_local, immediate);
        struct plip_local *snd = &nl->snd_data;
        struct plip_local *rcv = &nl->rcv_data;
        plip_func f;
@@ -372,20 +374,21 @@ plip_bh(struct net_device *dev)
 
        nl->is_deferred = 0;
        f = connection_state_table[nl->connection];
-       if ((r = (*f)(dev, nl, snd, rcv)) != OK
-           && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) {
+       if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK
+           && (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) {
                nl->is_deferred = 1;
                schedule_delayed_work(&nl->deferred, 1);
        }
 }
 
 static void
-plip_timer_bh(struct net_device *dev)
+plip_timer_bh(struct work_struct *work)
 {
-       struct net_local *nl = netdev_priv(dev);
+       struct net_local *nl =
+               container_of(work, struct net_local, timer.work);
 
        if (!(atomic_read (&nl->kill_timer))) {
-               plip_interrupt (-1, dev);
+               plip_interrupt (-1, nl->dev);
 
                schedule_delayed_work(&nl->timer, 1);
        }
@@ -1284,6 +1287,7 @@ static void plip_attach (struct parport *port)
                }
 
                nl = netdev_priv(dev);
+               nl->dev = dev;
                nl->pardev = parport_register_device(port, name, plip_preempt,
                                                 plip_wakeup, plip_interrupt,
                                                 0, dev);
index ec640f6..d79d141 100644 (file)
@@ -2008,7 +2008,7 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
                               "%s: Another function issued a reset to the "
                               "chip. ISR value = %x.\n", ndev->name, value);
                }
-               queue_work(qdev->workqueue, &qdev->reset_work);
+               queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0);
                spin_unlock(&qdev->adapter_lock);
        } else if (value & ISP_IMR_DISABLE_CMPL_INT) {
                ql_disable_interrupts(qdev);
@@ -3182,11 +3182,13 @@ static void ql3xxx_tx_timeout(struct net_device *ndev)
        /*
         * Wake up the worker to process this event.
         */
-       queue_work(qdev->workqueue, &qdev->tx_timeout_work);
+       queue_delayed_work(qdev->workqueue, &qdev->tx_timeout_work, 0);
 }
 
-static void ql_reset_work(struct ql3_adapter *qdev)
+static void ql_reset_work(struct work_struct *work)
 {
+       struct ql3_adapter *qdev =
+               container_of(work, struct ql3_adapter, reset_work.work);
        struct net_device *ndev = qdev->ndev;
        u32 value;
        struct ql_tx_buf_cb *tx_cb;
@@ -3278,9 +3280,12 @@ static void ql_reset_work(struct ql3_adapter *qdev)
        }
 }
 
-static void ql_tx_timeout_work(struct ql3_adapter *qdev)
+static void ql_tx_timeout_work(struct work_struct *work)
 {
-       ql_cycle_adapter(qdev,QL_DO_RESET);
+       struct ql3_adapter *qdev =
+               container_of(work, struct ql3_adapter, tx_timeout_work.work);
+
+       ql_cycle_adapter(qdev, QL_DO_RESET);
 }
 
 static void ql_get_board_info(struct ql3_adapter *qdev)
@@ -3459,9 +3464,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        netif_stop_queue(ndev);
 
        qdev->workqueue = create_singlethread_workqueue(ndev->name);
-       INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev);
-       INIT_WORK(&qdev->tx_timeout_work,
-                 (void (*)(void *))ql_tx_timeout_work, qdev);
+       INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
+       INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
 
        init_timer(&qdev->adapter_timer);
        qdev->adapter_timer.function = ql3xxx_timer;
index 65da2c0..ea94de7 100644 (file)
@@ -1186,8 +1186,8 @@ struct ql3_adapter {
        u32 numPorts;
        struct net_device_stats stats;
        struct workqueue_struct *workqueue;
-       struct work_struct reset_work;
-       struct work_struct tx_timeout_work;
+       struct delayed_work reset_work;
+       struct delayed_work tx_timeout_work;
        u32 max_frame_size;
 };
 
index 45d3ca4..f83b41d 100644 (file)
@@ -225,6 +225,7 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_copybreak = 200;
 static int use_dac;
+static int ignore_parity_err;
 static struct {
        u32 msg_enable;
 } debug = { -1 };
@@ -424,6 +425,7 @@ struct ring_info {
 struct rtl8169_private {
        void __iomem *mmio_addr;        /* memory map physical address */
        struct pci_dev *pci_dev;        /* Index of PCI device */
+       struct net_device *dev;
        struct net_device_stats stats;  /* statistics of net device */
        spinlock_t lock;                /* spin lock flag */
        u32 msg_enable;
@@ -455,7 +457,7 @@ struct rtl8169_private {
        void (*phy_reset_enable)(void __iomem *);
        unsigned int (*phy_reset_pending)(void __iomem *);
        unsigned int (*link_ok)(void __iomem *);
-       struct work_struct task;
+       struct delayed_work task;
        unsigned wol_enabled : 1;
 };
 
@@ -469,6 +471,8 @@ module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+module_param_named(ignore_parity_err, ignore_parity_err, bool, 0);
+MODULE_PARM_DESC(ignore_parity_err, "Ignore PCI parity error as target. Default: false");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
 
@@ -1283,11 +1287,6 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
        /* Shazam ! */
 
        if (tp->mac_version == RTL_GIGA_MAC_VER_04) {
-               mdio_write(ioaddr, 31, 0x0001);
-               mdio_write(ioaddr,  9, 0x273a);
-               mdio_write(ioaddr, 14, 0x7bfb);
-               mdio_write(ioaddr, 27, 0x841e);
-
                mdio_write(ioaddr, 31, 0x0002);
                mdio_write(ioaddr,  1, 0x90d0);
                mdio_write(ioaddr, 31, 0x0000);
@@ -1510,6 +1509,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
        tp = netdev_priv(dev);
+       tp->dev = dev;
        tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
 
        /* enable device (incl. PCI PM wakeup and hotplug setup) */
@@ -1782,7 +1782,7 @@ static int rtl8169_open(struct net_device *dev)
        if (retval < 0)
                goto err_free_rx;
 
-       INIT_WORK(&tp->task, NULL, dev);
+       INIT_DELAYED_WORK(&tp->task, NULL);
 
        rtl8169_hw_start(dev);
 
@@ -1815,12 +1815,25 @@ static void rtl8169_hw_reset(void __iomem *ioaddr)
        RTL_R8(ChipCmd);
 }
 
-static void
-rtl8169_hw_start(struct net_device *dev)
+static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+{
+       void __iomem *ioaddr = tp->mmio_addr;
+       u32 cfg = rtl8169_rx_config;
+
+       cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
+       RTL_W32(RxConfig, cfg);
+
+       /* Set DMA burst size and Interframe Gap Time */
+       RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
+               (InterFrameGap << TxInterFrameGapShift));
+}
+
+static void rtl8169_hw_start(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
        struct pci_dev *pdev = tp->pci_dev;
+       u16 cmd;
        u32 i;
 
        /* Soft reset the chip. */
@@ -1833,6 +1846,11 @@ rtl8169_hw_start(struct net_device *dev)
                msleep_interruptible(1);
        }
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
+               RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
+               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
+       }
+
        if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
                pci_write_config_word(pdev, 0x68, 0x00);
                pci_write_config_word(pdev, 0x69, 0x08);
@@ -1840,8 +1858,6 @@ rtl8169_hw_start(struct net_device *dev)
 
        /* Undocumented stuff. */
        if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
-               u16 cmd;
-
                /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
                if ((RTL_R8(Config2) & 0x07) & 0x01)
                        RTL_W32(0x7c, 0x0007ffff);
@@ -1853,23 +1869,29 @@ rtl8169_hw_start(struct net_device *dev)
                pci_write_config_word(pdev, PCI_COMMAND, cmd);
        }
 
-
        RTL_W8(Cfg9346, Cfg9346_Unlock);
+       if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_04))
+               RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
        RTL_W8(EarlyTxThres, EarlyTxThld);
 
        /* Low hurts. Let's disable the filtering. */
        RTL_W16(RxMaxSize, 16383);
 
-       /* Set Rx Config register */
-       i = rtl8169_rx_config |
-               (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
-       RTL_W32(RxConfig, i);
+       if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_04))
+               RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+               rtl8169_set_rx_tx_config_registers(tp);
 
-       /* Set DMA burst size and Interframe Gap Time */
-       RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
-               (InterFrameGap << TxInterFrameGapShift));
+       cmd = RTL_R16(CPlusCmd);
+       RTL_W16(CPlusCmd, cmd);
 
-       tp->cp_cmd |= RTL_R16(CPlusCmd) | PCIMulRW;
+       tp->cp_cmd |= cmd | PCIMulRW;
 
        if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
            (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1895,7 +1917,15 @@ rtl8169_hw_start(struct net_device *dev)
        RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
        RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
        RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-       RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+       if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
+               RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+               rtl8169_set_rx_tx_config_registers(tp);
+       }
+
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
        /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
@@ -1990,7 +2020,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
        if (!skb)
                goto err_out;
 
-       skb_reserve(skb, align);
+       skb_reserve(skb, (align - 1) & (u32)skb->data);
        *sk_buff = skb;
 
        mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
@@ -2105,11 +2135,11 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
        tp->cur_tx = tp->dirty_tx = 0;
 }
 
-static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *))
+static void rtl8169_schedule_work(struct net_device *dev, work_func_t task)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       PREPARE_WORK(&tp->task, task, dev);
+       PREPARE_DELAYED_WORK(&tp->task, task);
        schedule_delayed_work(&tp->task, 4);
 }
 
@@ -2128,9 +2158,11 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
        netif_poll_enable(dev);
 }
 
-static void rtl8169_reinit_task(void *_data)
+static void rtl8169_reinit_task(struct work_struct *work)
 {
-       struct net_device *dev = _data;
+       struct rtl8169_private *tp =
+               container_of(work, struct rtl8169_private, task.work);
+       struct net_device *dev = tp->dev;
        int ret;
 
        if (netif_running(dev)) {
@@ -2153,10 +2185,11 @@ static void rtl8169_reinit_task(void *_data)
        }
 }
 
-static void rtl8169_reset_task(void *_data)
+static void rtl8169_reset_task(struct work_struct *work)
 {
-       struct net_device *dev = _data;
-       struct rtl8169_private *tp = netdev_priv(dev);
+       struct rtl8169_private *tp =
+               container_of(work, struct rtl8169_private, task.work);
+       struct net_device *dev = tp->dev;
 
        if (!netif_running(dev))
                return;
@@ -2350,12 +2383,17 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
        /*
         * The recovery sequence below admits a very elaborated explanation:
         * - it seems to work;
-        * - I did not see what else could be done.
+        * - I did not see what else could be done;
+        * - it makes iop3xx happy.
         *
         * Feel free to adjust to your needs.
         */
-       pci_write_config_word(pdev, PCI_COMMAND,
-                             pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+       if (ignore_parity_err)
+               pci_cmd &= ~PCI_COMMAND_PARITY;
+       else
+               pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+
+       pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
 
        pci_write_config_word(pdev, PCI_STATUS,
                pci_status & (PCI_STATUS_DETECTED_PARITY |
@@ -2369,10 +2407,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
                tp->cp_cmd &= ~PCIDAC;
                RTL_W16(CPlusCmd, tp->cp_cmd);
                dev->features &= ~NETIF_F_HIGHDMA;
-               rtl8169_schedule_work(dev, rtl8169_reinit_task);
        }
 
        rtl8169_hw_reset(ioaddr);
+
+       rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
 
 static void
@@ -2452,7 +2491,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
 
                skb = dev_alloc_skb(pkt_size + align);
                if (skb) {
-                       skb_reserve(skb, align);
+                       skb_reserve(skb, (align - 1) & (u32)skb->data);
                        eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
                        *sk_buff = skb;
                        rtl8169_mark_to_asic(desc, rx_buf_sz);
index 33569ec..250cdbe 100644 (file)
@@ -5872,9 +5872,9 @@ static void s2io_tasklet(unsigned long dev_addr)
  * Description: Sets the link status for the adapter
  */
 
-static void s2io_set_link(unsigned long data)
+static void s2io_set_link(struct work_struct *work)
 {
-       nic_t *nic = (nic_t *) data;
+       nic_t *nic = container_of(work, nic_t, set_link_task);
        struct net_device *dev = nic->dev;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64;
@@ -6379,10 +6379,10 @@ static int s2io_card_up(nic_t * sp)
  * spin lock.
  */
 
-static void s2io_restart_nic(unsigned long data)
+static void s2io_restart_nic(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *) data;
-       nic_t *sp = dev->priv;
+       nic_t *sp = container_of(work, nic_t, rst_timer_task);
+       struct net_device *dev = sp->dev;
 
        s2io_card_down(sp);
        if (s2io_card_up(sp)) {
@@ -6992,10 +6992,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
        dev->tx_timeout = &s2io_tx_watchdog;
        dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
-       INIT_WORK(&sp->rst_timer_task,
-                 (void (*)(void *)) s2io_restart_nic, dev);
-       INIT_WORK(&sp->set_link_task,
-                 (void (*)(void *)) s2io_set_link, sp);
+       INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
+       INIT_WORK(&sp->set_link_task, s2io_set_link);
 
        pci_save_state(sp->pdev);
 
index 12b719f..3b0bafd 100644 (file)
@@ -1000,7 +1000,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id);
 static irqreturn_t s2io_isr(int irq, void *dev_id);
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static const struct ethtool_ops netdev_ethtool_ops;
-static void s2io_set_link(unsigned long data);
+static void s2io_set_link(struct work_struct *work);
 static int s2io_set_swapper(nic_t * sp);
 static void s2io_card_down(nic_t *nic);
 static int s2io_card_up(nic_t *nic);
index d9d0a3a..0d6c95c 100644 (file)
@@ -750,7 +750,7 @@ int __init init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(dev_seeq);
        release_region(dev_seeq->base_addr, SEEQ8005_IO_EXTENT);
index aaba458..b70ed79 100644 (file)
@@ -280,6 +280,7 @@ enum sis190_feature {
 struct sis190_private {
        void __iomem *mmio_addr;
        struct pci_dev *pci_dev;
+       struct net_device *dev;
        struct net_device_stats stats;
        spinlock_t lock;
        u32 rx_buf_sz;
@@ -897,10 +898,11 @@ static void sis190_hw_start(struct net_device *dev)
        netif_start_queue(dev);
 }
 
-static void sis190_phy_task(void * data)
+static void sis190_phy_task(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct sis190_private *tp = netdev_priv(dev);
+       struct sis190_private *tp =
+               container_of(work, struct sis190_private, phy_task);
+       struct net_device *dev = tp->dev;
        void __iomem *ioaddr = tp->mmio_addr;
        int phy_id = tp->mii_if.phy_id;
        u16 val;
@@ -1047,7 +1049,7 @@ static int sis190_open(struct net_device *dev)
        if (rc < 0)
                goto err_free_rx_1;
 
-       INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+       INIT_WORK(&tp->phy_task, sis190_phy_task);
 
        sis190_request_timer(dev);
 
@@ -1436,6 +1438,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        tp = netdev_priv(dev);
+       tp->dev = dev;
        tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
 
        rc = pci_enable_device(pdev);
@@ -1798,7 +1801,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
 
        sis190_init_rxfilter(dev);
 
-       INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+       INIT_WORK(&tp->phy_task, sis190_phy_task);
 
        dev->open = sis190_open;
        dev->stop = sis190_close;
index ab66d80..3e7aa49 100644 (file)
@@ -1319,7 +1319,7 @@ SK_BOOL   AutoNeg)        /* Is Auto-negotiation used ? */
        SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
 
 #ifdef xDEBUG
-       if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
+       if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
                (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
 
                SK_U32  Stat1, Stat2, Stat3;
index 5513907..b60f045 100644 (file)
@@ -1327,10 +1327,11 @@ static void xm_check_link(struct net_device *dev)
  * 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)
+static void xm_link_timer(struct work_struct *work)
 {
-       struct net_device *dev = arg;
-       struct skge_port *skge = netdev_priv(arg);
+       struct skge_port *skge =
+               container_of(work, struct skge_port, link_thread.work);
+       struct net_device *dev = skge->netdev;
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
 
@@ -3072,9 +3073,9 @@ static void skge_error_irq(struct skge_hw *hw)
  * because accessing phy registers requires spin wait which might
  * cause excess interrupt latency.
  */
-static void skge_extirq(void *arg)
+static void skge_extirq(struct work_struct *work)
 {
-       struct skge_hw *hw = arg;
+       struct skge_hw *hw = container_of(work, struct skge_hw, phy_work);
        int port;
 
        mutex_lock(&hw->phy_mutex);
@@ -3456,7 +3457,7 @@ 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);
+       INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer);
 
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
@@ -3543,7 +3544,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
 
        hw->pdev = pdev;
        mutex_init(&hw->phy_mutex);
-       INIT_WORK(&hw->phy_work, skge_extirq, hw);
+       INIT_WORK(&hw->phy_work, skge_extirq);
        spin_lock_init(&hw->hw_lock);
 
        hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
index 537c0aa..f6223c5 100644 (file)
@@ -389,10 +389,10 @@ enum {
 /* Packet Arbiter Registers */
 /*     B3_PA_CTRL              16 bit  Packet Arbiter Ctrl Register */
 enum {
-       PA_CLR_TO_TX2   = 1<<13,        /* Clear IRQ Packet Timeout TX2 */
-       PA_CLR_TO_TX1   = 1<<12,        /* Clear IRQ Packet Timeout TX1 */
-       PA_CLR_TO_RX2   = 1<<11,        /* Clear IRQ Packet Timeout RX2 */
-       PA_CLR_TO_RX1   = 1<<10,        /* Clear IRQ Packet Timeout RX1 */
+       PA_CLR_TO_TX2   = 1<<13,/* Clear IRQ Packet Timeout TX2 */
+       PA_CLR_TO_TX1   = 1<<12,/* Clear IRQ Packet Timeout TX1 */
+       PA_CLR_TO_RX2   = 1<<11,/* Clear IRQ Packet Timeout RX2 */
+       PA_CLR_TO_RX1   = 1<<10,/* Clear IRQ Packet Timeout RX1 */
        PA_ENA_TO_TX2   = 1<<9, /* Enable  Timeout Timer TX2 */
        PA_DIS_TO_TX2   = 1<<8, /* Disable Timeout Timer TX2 */
        PA_ENA_TO_TX1   = 1<<7, /* Enable  Timeout Timer TX1 */
@@ -481,14 +481,14 @@ enum {
 /* RAM Buffer Register Offsets */
 enum {
 
-       RB_START        = 0x00,/* 32 bit        RAM Buffer Start Address */
+       RB_START= 0x00,/* 32 bit        RAM Buffer Start Address */
        RB_END  = 0x04,/* 32 bit        RAM Buffer End Address */
        RB_WP   = 0x08,/* 32 bit        RAM Buffer Write Pointer */
        RB_RP   = 0x0c,/* 32 bit        RAM Buffer Read Pointer */
-       RB_RX_UTPP      = 0x10,/* 32 bit        Rx Upper Threshold, Pause Packet */
-       RB_RX_LTPP      = 0x14,/* 32 bit        Rx Lower Threshold, Pause Packet */
-       RB_RX_UTHP      = 0x18,/* 32 bit        Rx Upper Threshold, High Prio */
-       RB_RX_LTHP      = 0x1c,/* 32 bit        Rx Lower Threshold, High Prio */
+       RB_RX_UTPP= 0x10,/* 32 bit      Rx Upper Threshold, Pause Packet */
+       RB_RX_LTPP= 0x14,/* 32 bit      Rx Lower Threshold, Pause Packet */
+       RB_RX_UTHP= 0x18,/* 32 bit      Rx Upper Threshold, High Prio */
+       RB_RX_LTHP= 0x1c,/* 32 bit      Rx Lower Threshold, High Prio */
        /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
        RB_PC   = 0x20,/* 32 bit        RAM Buffer Packet Counter */
        RB_LEV  = 0x24,/* 32 bit        RAM Buffer Level Register */
@@ -532,7 +532,7 @@ enum {
        PHY_ADDR_MARV   = 0,
 };
 
-#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+#define RB_ADDR(offs, queue) ((u16)B16_RAM_REGS + (u16)(queue) + (offs))
 
 /* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */
 enum {
@@ -578,15 +578,15 @@ enum {
        MFF_DIS_TIST    = 1<<2, /* Disable Time Stamp Gener */
        MFF_CLR_INTIST  = 1<<1, /* Clear IRQ No Time Stamp */
        MFF_CLR_INSTAT  = 1<<0, /* Clear IRQ No Status */
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+       MFF_RX_CTRL_DEF = MFF_ENA_TIM_PAT,
 };
 
 /*     TX_MFF_CTRL1    16 bit  Transmit MAC FIFO Control Reg 1 */
 enum {
-       MFF_CLR_PERR    = 1<<15,        /* Clear Parity Error IRQ */
-                                                               /* Bit 14:      reserved */
-       MFF_ENA_PKT_REC = 1<<13,        /* Enable  Packet Recovery */
-       MFF_DIS_PKT_REC = 1<<12,        /* Disable Packet Recovery */
+       MFF_CLR_PERR    = 1<<15, /* Clear Parity Error IRQ */
+
+       MFF_ENA_PKT_REC = 1<<13, /* Enable  Packet Recovery */
+       MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */
 
        MFF_ENA_W4E     = 1<<7, /* Enable  Wait for Empty */
        MFF_DIS_W4E     = 1<<6, /* Disable Wait for Empty */
@@ -595,9 +595,10 @@ enum {
        MFF_DIS_LOOPB   = 1<<2, /* Disable Loopback */
        MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */
        MFF_SET_MAC_RST = 1<<0, /* Set   XMAC Reset */
+
+       MFF_TX_CTRL_DEF  = MFF_ENA_PKT_REC | (u16) MFF_ENA_TIM_PAT | MFF_ENA_FLUSH,
 };
 
-#define MFF_TX_CTRL_DEF        (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
 
 /*     RX_MFF_TST2              8 bit  Receive MAC FIFO Test Register 2 */
 /*     TX_MFF_TST2              8 bit  Transmit MAC FIFO Test Register 2 */
@@ -1304,8 +1305,8 @@ enum {
 
 /* special defines for FIBER (88E1011S only) */
 enum {
-       PHY_M_AN_ASP_X  = 1<<8, /* Asymmetric Pause */
-       PHY_M_AN_PC_X   = 1<<7, /* MAC Pause implemented */
+       PHY_M_AN_ASP_X          = 1<<8, /* Asymmetric Pause */
+       PHY_M_AN_PC_X           = 1<<7, /* MAC Pause implemented */
        PHY_M_AN_1000X_AHD      = 1<<6, /* Advertise 10000Base-X Half Duplex */
        PHY_M_AN_1000X_AFD      = 1<<5, /* Advertise 10000Base-X Full Duplex */
 };
@@ -1320,7 +1321,7 @@ enum {
 
 /*****  PHY_MARV_1000T_CTRL    16 bit r/w      1000Base-T Control Reg *****/
 enum {
-       PHY_M_1000C_TEST        = 7<<13,/* Bit 15..13:  Test Modes */
+       PHY_M_1000C_TEST= 7<<13,/* Bit 15..13:  Test Modes */
        PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */
        PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */
        PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */
@@ -1349,7 +1350,7 @@ enum {
        PHY_M_PC_EN_DET_PLUS    = 3<<8, /* Energy Detect Plus (Mode 2) */
 };
 
-#define PHY_M_PC_MDI_XMODE(x)  (((x)<<5) & PHY_M_PC_MDIX_MSK)
+#define PHY_M_PC_MDI_XMODE(x)  ((((u16)(x)<<5) & PHY_M_PC_MDIX_MSK)
 
 enum {
        PHY_M_PC_MAN_MDI        = 0, /* 00 = Manual MDI configuration */
@@ -1432,24 +1433,24 @@ enum {
        PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
        PHY_M_EC_M_DSC_MSK  = 3<<10, /* Bit 11..10:     Master Downshift Counter */
                                        /* (88E1011 only) */
-       PHY_M_EC_S_DSC_MSK      = 3<<8,/* Bit  9.. 8:   Slave  Downshift Counter */
+       PHY_M_EC_S_DSC_MSK  = 3<<8,  /* Bit  9.. 8:     Slave  Downshift Counter */
                                       /* (88E1011 only) */
-       PHY_M_EC_M_DSC_MSK2     = 7<<9,/* Bit 11.. 9:   Master Downshift Counter */
+       PHY_M_EC_M_DSC_MSK2  = 7<<9, /* Bit 11.. 9:     Master Downshift Counter */
                                        /* (88E1111 only) */
-       PHY_M_EC_DOWN_S_ENA     = 1<<8, /* Downshift Enable (88E1111 only) */
+       PHY_M_EC_DOWN_S_ENA  = 1<<8, /* Downshift Enable (88E1111 only) */
                                        /* !!! Errata in spec. (1 = disable) */
-       PHY_M_EC_RX_TIM_CT      = 1<<7, /* RGMII Rx Timing Control*/
-       PHY_M_EC_MAC_S_MSK      = 7<<4,/* Bit  6.. 4:   Def. MAC interface speed */
-       PHY_M_EC_FIB_AN_ENA     = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
-       PHY_M_EC_DTE_D_ENA      = 1<<2, /* DTE Detect Enable (88E1111 only) */
-       PHY_M_EC_TX_TIM_CT      = 1<<1, /* RGMII Tx Timing Control */
-       PHY_M_EC_TRANS_DIS      = 1<<0, /* Transmitter Disable (88E1111 only) */};
-
-#define PHY_M_EC_M_DSC(x)      ((x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x)      ((x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x)      ((x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define PHY_M_EC_M_DSC_2(x)    ((x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */
+       PHY_M_EC_RX_TIM_CT   = 1<<7, /* RGMII Rx Timing Control*/
+       PHY_M_EC_MAC_S_MSK   = 7<<4, /* Bit  6.. 4:     Def. MAC interface speed */
+       PHY_M_EC_FIB_AN_ENA  = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+       PHY_M_EC_DTE_D_ENA   = 1<<2, /* DTE Detect Enable (88E1111 only) */
+       PHY_M_EC_TX_TIM_CT   = 1<<1, /* RGMII Tx Timing Control */
+       PHY_M_EC_TRANS_DIS   = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x)      ((u16)(x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x)      ((u16)(x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_MAC_S(x)      ((u16)(x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+#define PHY_M_EC_M_DSC_2(x)    ((u16)(x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */
                                                                                        /* 100=5x; 101=6x; 110=7x; 111=8x */
 enum {
        MAC_TX_CLK_0_MHZ        = 2,
@@ -1468,10 +1469,12 @@ enum {
        PHY_M_LEDC_LK_C_MSK     = 7<<3,/* Bit  5.. 3: Link Control Mask */
                                        /* (88E1111 only) */
 };
+#define PHY_M_LED_PULS_DUR(x)  (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK)
+#define PHY_M_LED_BLINK_RT(x)  (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK)
 
 enum {
-       PHY_M_LEDC_LINK_MSK     = 3<<3,/* Bit  4.. 3: Link Control Mask */
-                                                                       /* (88E1011 only) */
+       PHY_M_LEDC_LINK_MSK     = 3<<3, /* Bit  4.. 3: Link Control Mask */
+                                       /* (88E1011 only) */
        PHY_M_LEDC_DP_CTRL      = 1<<2, /* Duplex Control */
        PHY_M_LEDC_DP_C_MSB     = 1<<2, /* Duplex Control (MSB, 88E1111 only) */
        PHY_M_LEDC_RX_CTRL      = 1<<1, /* Rx Activity / Link */
@@ -1479,27 +1482,24 @@ enum {
        PHY_M_LEDC_TX_C_MSB     = 1<<0, /* Tx Control (MSB, 88E1111 only) */
 };
 
-#define PHY_M_LED_PULS_DUR(x)  (((x)<<12) & PHY_M_LEDC_PULS_MSK)
-
 enum {
-       PULS_NO_STR     = 0,/* no pulse stretching */
-       PULS_21MS       = 1,/* 21 ms to 42 ms */
-       PULS_42MS       = 2,/* 42 ms to 84 ms */
-       PULS_84MS       = 3,/* 84 ms to 170 ms */
-       PULS_170MS      = 4,/* 170 ms to 340 ms */
-       PULS_340MS      = 5,/* 340 ms to 670 ms */
-       PULS_670MS      = 6,/* 670 ms to 1.3 s */
-       PULS_1300MS     = 7,/* 1.3 s to 2.7 s */
+       PULS_NO_STR     = 0, /* no pulse stretching */
+       PULS_21MS       = 1, /* 21 ms to 42 ms */
+       PULS_42MS       = 2, /* 42 ms to 84 ms */
+       PULS_84MS       = 3, /* 84 ms to 170 ms */
+       PULS_170MS      = 4, /* 170 ms to 340 ms */
+       PULS_340MS      = 5, /* 340 ms to 670 ms */
+       PULS_670MS      = 6, /* 670 ms to 1.3 s */
+       PULS_1300MS     = 7, /* 1.3 s to 2.7 s */
 };
 
-#define PHY_M_LED_BLINK_RT(x)  (((x)<<8) & PHY_M_LEDC_BL_R_MSK)
 
 enum {
-       BLINK_42MS      = 0,/* 42 ms */
-       BLINK_84MS      = 1,/* 84 ms */
-       BLINK_170MS     = 2,/* 170 ms */
-       BLINK_340MS     = 3,/* 340 ms */
-       BLINK_670MS     = 4,/* 670 ms */
+       BLINK_42MS      = 0, /* 42 ms */
+       BLINK_84MS      = 1, /* 84 ms */
+       BLINK_170MS     = 2, /* 170 ms */
+       BLINK_340MS     = 3, /* 340 ms */
+       BLINK_670MS     = 4, /* 670 ms */
 };
 
 /*****  PHY_MARV_LED_OVER      16 bit r/w      Manual LED Override Reg *****/
@@ -1525,7 +1525,7 @@ enum {
        PHY_M_EC2_FO_IMPED      = 1<<5, /* Fiber Output Impedance */
        PHY_M_EC2_FO_M_CLK      = 1<<4, /* Fiber Mode Clock Enable */
        PHY_M_EC2_FO_BOOST      = 1<<3, /* Fiber Output Boost */
-       PHY_M_EC2_FO_AM_MSK     = 7,/* Bit  2.. 0:      Fiber Output Amplitude */
+       PHY_M_EC2_FO_AM_MSK     = 7, /* Bit  2.. 0:     Fiber Output Amplitude */
 };
 
 /*****  PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
@@ -1550,7 +1550,7 @@ enum {
        PHY_M_CABD_DIS_WAIT     = 1<<15, /* Disable Waiting Period (Page 1) */
                                        /* (88E1111 only) */
        PHY_M_CABD_STAT_MSK     = 3<<13, /* Bit 14..13: Status Mask */
-       PHY_M_CABD_AMPL_MSK     = 0x1f<<8,/* Bit 12.. 8: Amplitude Mask */
+       PHY_M_CABD_AMPL_MSK     = 0x1f<<8, /* Bit 12.. 8: Amplitude Mask */
                                        /* (88E1111 only) */
        PHY_M_CABD_DIST_MSK     = 0xff, /* Bit  7.. 0: Distance Mask */
 };
@@ -1605,9 +1605,9 @@ enum {
 
 /*****  PHY_MARV_PHY_CTRL (page 3)             16 bit r/w      LED Control Reg. *****/
 enum {
-       PHY_M_LEDC_LOS_MSK      = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+       PHY_M_LEDC_LOS_MSK      = 0xf<<12, /* Bit 15..12: LOS LED Ctrl. Mask */
        PHY_M_LEDC_INIT_MSK     = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
-       PHY_M_LEDC_STA1_MSK     = 0xf<<4,/* Bit  7.. 4: STAT1 LED Ctrl. Mask */
+       PHY_M_LEDC_STA1_MSK     = 0xf<<4, /* Bit  7.. 4: STAT1 LED Ctrl. Mask */
        PHY_M_LEDC_STA0_MSK     = 0xf, /* Bit  3.. 0: STAT0 LED Ctrl. Mask */
 };
 
@@ -1804,8 +1804,8 @@ enum {
 
 /*     GM_SMI_CTRL                     16 bit r/w      SMI Control Register */
 enum {
-       GM_SMI_CT_PHY_A_MSK     = 0x1f<<11,/* Bit 15..11:       PHY Device Address */
-       GM_SMI_CT_REG_A_MSK     = 0x1f<<6,/* Bit 10.. 6:        PHY Register Address */
+       GM_SMI_CT_PHY_A_MSK     = 0x1f<<11, /* Bit 15..11:      PHY Device Address */
+       GM_SMI_CT_REG_A_MSK     = 0x1f<<6, /* Bit 10.. 6:       PHY Register Address */
        GM_SMI_CT_OP_RD         = 1<<5, /* Bit  5:      OpCode Read (0=Write)*/
        GM_SMI_CT_RD_VAL        = 1<<4, /* Bit  4:      Read Valid (Read completed) */
        GM_SMI_CT_BUSY          = 1<<3, /* Bit  3:      Busy (Operation in progress) */
@@ -1875,9 +1875,9 @@ enum {
 
 /*     TX_GMF_CTRL_T   32 bit  Tx GMAC FIFO Control/Test */
 enum {
-       GMF_WSP_TST_ON  = 1<<18,/* Write Shadow Pointer Test On */
-       GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */
-       GMF_WSP_STEP    = 1<<16,/* Write Shadow Pointer Step/Increment */
+       GMF_WSP_TST_ON  = 1<<18, /* Write Shadow Pointer Test On */
+       GMF_WSP_TST_OFF = 1<<17, /* Write Shadow Pointer Test Off */
+       GMF_WSP_STEP    = 1<<16, /* Write Shadow Pointer Step/Increment */
 
        GMF_CLI_TX_FU   = 1<<6, /* Clear IRQ Tx FIFO Underrun */
        GMF_CLI_TX_FC   = 1<<5, /* Clear IRQ Tx Frame Complete */
@@ -2111,18 +2111,18 @@ enum {
 
 /*     XM_MMU_CMD      16 bit r/w      MMU Command Register */
 enum {
-       XM_MMU_PHY_RDY  = 1<<12,/* Bit 12:      PHY Read Ready */
-       XM_MMU_PHY_BUSY = 1<<11,/* Bit 11:      PHY Busy */
-       XM_MMU_IGN_PF   = 1<<10,/* Bit 10:      Ignore Pause Frame */
-       XM_MMU_MAC_LB   = 1<<9, /* Bit  9:      Enable MAC Loopback */
-       XM_MMU_FRC_COL  = 1<<7, /* Bit  7:      Force Collision */
-       XM_MMU_SIM_COL  = 1<<6, /* Bit  6:      Simulate Collision */
-       XM_MMU_NO_PRE   = 1<<5, /* Bit  5:      No MDIO Preamble */
-       XM_MMU_GMII_FD  = 1<<4, /* Bit  4:      GMII uses Full Duplex */
-       XM_MMU_RAT_CTRL = 1<<3, /* Bit  3:      Enable Rate Control */
-       XM_MMU_GMII_LOOP= 1<<2, /* Bit  2:      PHY is in Loopback Mode */
-       XM_MMU_ENA_RX   = 1<<1, /* Bit  1:      Enable Receiver */
-       XM_MMU_ENA_TX   = 1<<0, /* Bit  0:      Enable Transmitter */
+       XM_MMU_PHY_RDY  = 1<<12, /* Bit 12:     PHY Read Ready */
+       XM_MMU_PHY_BUSY = 1<<11, /* Bit 11:     PHY Busy */
+       XM_MMU_IGN_PF   = 1<<10, /* Bit 10:     Ignore Pause Frame */
+       XM_MMU_MAC_LB   = 1<<9,  /* Bit  9:     Enable MAC Loopback */
+       XM_MMU_FRC_COL  = 1<<7,  /* Bit  7:     Force Collision */
+       XM_MMU_SIM_COL  = 1<<6,  /* Bit  6:     Simulate Collision */
+       XM_MMU_NO_PRE   = 1<<5,  /* Bit  5:     No MDIO Preamble */
+       XM_MMU_GMII_FD  = 1<<4,  /* Bit  4:     GMII uses Full Duplex */
+       XM_MMU_RAT_CTRL = 1<<3,  /* Bit  3:     Enable Rate Control */
+       XM_MMU_GMII_LOOP= 1<<2,  /* Bit  2:     PHY is in Loopback Mode */
+       XM_MMU_ENA_RX   = 1<<1,  /* Bit  1:     Enable Receiver */
+       XM_MMU_ENA_TX   = 1<<0,  /* Bit  0:     Enable Transmitter */
 };
 
 
@@ -2456,7 +2456,7 @@ struct skge_port {
 
        struct net_device_stats net_stats;
 
-       struct work_struct   link_thread;
+       struct delayed_work  link_thread;
        enum pause_control   flow_control;
        enum pause_status    flow_status;
        u8                   rx_csum;
@@ -2506,7 +2506,7 @@ static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val)
 }
 
 /* MAC Related Registers inside the device. */
-#define SK_REG(port,reg)       (((port)<<7)+(reg))
+#define SK_REG(port,reg)       (((port)<<7)+(u16)(reg))
 #define SK_XMAC_REG(port, reg) \
        ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1)
 
index 842abd9..fb1d2c3 100644 (file)
@@ -100,33 +100,32 @@ module_param(idle_timeout, int, 0);
 MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
 
 static const struct pci_device_id sky2_id_table[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
-       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
+       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },    /* DGE-560T */
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) },    /* DGE-550SX */
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) },    /* DGE-560SX */
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, /* 88E8062 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, /* 88E8021 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, /* 88E8022 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, /* 88E8061 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, /* 88E8062 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, /* 88E8035 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
        { 0 }
 };
 
@@ -522,7 +521,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
                ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
                /* turn off the Rx LED (LED_RX) */
-               ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+               ledover &= ~PHY_M_LED_MO_RX;
        }
 
        if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
@@ -545,7 +544,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
                if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
                        /* turn on 100 Mbps LED (LED_LINK100) */
-                       ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+                       ledover |= PHY_M_LED_MO_100;
                }
 
                if (ledover)
@@ -697,10 +696,15 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 
 }
 
-/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
+/* Assign Ram Buffer allocation to queue */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
 {
-       pr_debug(PFX "q %d %#x %#x\n", q, start, end);
+       u32 end;
+
+       /* convert from K bytes to qwords used for hw register */
+       start *= 1024/8;
+       space *= 1024/8;
+       end = start + space - 1;
 
        sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
        sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -709,7 +713,6 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
        sky2_write32(hw, RB_ADDR(q, RB_RP), start);
 
        if (q == Q_R1 || q == Q_R2) {
-               u32 space = end - start + 1;
                u32 tp = space - space/4;
 
                /* On receive queue's set the thresholds
@@ -1059,11 +1062,16 @@ static int sky2_rx_start(struct sky2_port *sky2)
        sky2->rx_put = sky2->rx_next = 0;
        sky2_qset(hw, rxq);
 
+       /* On PCI express lowering the watermark gives better performance */
+       if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+               sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
+
+       /* These chips have no ram buffer?
+        * MAC Rx RAM Read is controlled by hardware */
        if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
-           (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) {
-               /* MAC Rx RAM Read is controlled by hardware */
+           (hw->chip_rev == CHIP_REV_YU_EC_U_A1
+            || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
                sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
-       }
 
        sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
 
@@ -1139,7 +1147,7 @@ static int sky2_up(struct net_device *dev)
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u32 ramsize, rxspace, imask;
+       u32 ramsize, imask;
        int cap, err = -ENOMEM;
        struct net_device *otherdev = hw->dev[sky2->port^1];
 
@@ -1192,20 +1200,25 @@ static int sky2_up(struct net_device *dev)
 
        sky2_mac_init(hw, port);
 
-       /* Determine available ram buffer space in qwords.  */
-       ramsize = sky2_read8(hw, B2_E_0) * 4096/8;
+       /* Register is number of 4K blocks on internal RAM buffer. */
+       ramsize = sky2_read8(hw, B2_E_0) * 4;
+       printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize);
 
-       if (ramsize > 6*1024/8)
-               rxspace = ramsize - (ramsize + 2) / 3;
-       else
-               rxspace = ramsize / 2;
+       if (ramsize > 0) {
+               u32 rxspace;
 
-       sky2_ramset(hw, rxqaddr[port], 0, rxspace-1);
-       sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1);
+               if (ramsize < 16)
+                       rxspace = ramsize / 2;
+               else
+                       rxspace = 8 + (2*(ramsize - 16))/3;
+
+               sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+               sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
 
-       /* Make sure SyncQ is disabled */
-       sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
-                   RB_RST_SET);
+               /* Make sure SyncQ is disabled */
+               sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
+                           RB_RST_SET);
+       }
 
        sky2_qset(hw, txqaddr[port]);
 
@@ -2917,18 +2930,8 @@ static void sky2_led(struct sky2_hw *hw, unsigned port, int on)
 
        default:
                gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER,
-                            on ? PHY_M_LED_MO_DUP(MO_LED_ON) |
-                            PHY_M_LED_MO_10(MO_LED_ON) |
-                            PHY_M_LED_MO_100(MO_LED_ON) |
-                            PHY_M_LED_MO_1000(MO_LED_ON) |
-                            PHY_M_LED_MO_RX(MO_LED_ON)
-                            : PHY_M_LED_MO_DUP(MO_LED_OFF) |
-                            PHY_M_LED_MO_10(MO_LED_OFF) |
-                            PHY_M_LED_MO_100(MO_LED_OFF) |
-                            PHY_M_LED_MO_1000(MO_LED_OFF) |
-                            PHY_M_LED_MO_RX(MO_LED_OFF));
-
+               gm_phy_write(hw, port, PHY_MARV_LED_OVER, 
+                            on ? PHY_M_LED_ALL : 0);
        }
 }
 
index 7760545..6ed1d47 100644 (file)
@@ -608,7 +608,7 @@ enum {
        PHY_ADDR_MARV   = 0,
 };
 
-#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+#define RB_ADDR(offs, queue) ((u16) B16_RAM_REGS + (queue) + (offs))
 
 
 enum {
@@ -680,6 +680,7 @@ enum {
                          BMU_FIFO_ENA | BMU_OP_ON,
 
        BMU_WM_DEFAULT = 0x600,
+       BMU_WM_PEX     = 0x80,
 };
 
 /* Tx BMU Control / Status Registers (Yukon-2) */
@@ -1060,7 +1061,7 @@ enum {
        PHY_M_PC_EN_DET_PLUS    = 3<<8, /* Energy Detect Plus (Mode 2) */
 };
 
-#define PHY_M_PC_MDI_XMODE(x)  (((x)<<5) & PHY_M_PC_MDIX_MSK)
+#define PHY_M_PC_MDI_XMODE(x)  (((u16)(x)<<5) & PHY_M_PC_MDIX_MSK)
 
 enum {
        PHY_M_PC_MAN_MDI        = 0, /* 00 = Manual MDI configuration */
@@ -1156,13 +1157,13 @@ enum {
        PHY_M_EC_TX_TIM_CT  = 1<<1, /* RGMII Tx Timing Control */
        PHY_M_EC_TRANS_DIS  = 1<<0, /* Transmitter Disable (88E1111 only) */};
 
-#define PHY_M_EC_M_DSC(x)      ((x)<<10 & PHY_M_EC_M_DSC_MSK)
+#define PHY_M_EC_M_DSC(x)      ((u16)(x)<<10 & PHY_M_EC_M_DSC_MSK)
                                        /* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x)      ((x)<<8 & PHY_M_EC_S_DSC_MSK)
+#define PHY_M_EC_S_DSC(x)      ((u16)(x)<<8 & PHY_M_EC_S_DSC_MSK)
                                        /* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_DSC_2(x)      ((x)<<9 & PHY_M_EC_M_DSC_MSK2)
+#define PHY_M_EC_DSC_2(x)      ((u16)(x)<<9 & PHY_M_EC_M_DSC_MSK2)
                                        /* 000=1x; 001=2x; 010=3x; 011=4x */
-#define PHY_M_EC_MAC_S(x)      ((x)<<4 & PHY_M_EC_MAC_S_MSK)
+#define PHY_M_EC_MAC_S(x)      ((u16)(x)<<4 & PHY_M_EC_MAC_S_MSK)
                                        /* 01X=0; 110=2.5; 111=25 (MHz) */
 
 /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
@@ -1173,7 +1174,7 @@ enum {
 };
 /* !!! Errata in spec. (1 = disable) */
 
-#define PHY_M_PC_DSC(x)                        (((x)<<12) & PHY_M_PC_DSC_MSK)
+#define PHY_M_PC_DSC(x)                        (((u16)(x)<<12) & PHY_M_PC_DSC_MSK)
                                                                                        /* 100=5x; 101=6x; 110=7x; 111=8x */
 enum {
        MAC_TX_CLK_0_MHZ        = 2,
@@ -1203,7 +1204,7 @@ enum {
        PHY_M_LEDC_TX_C_MSB     = 1<<0, /* Tx Control (MSB, 88E1111 only) */
 };
 
-#define PHY_M_LED_PULS_DUR(x)  (((x)<<12) & PHY_M_LEDC_PULS_MSK)
+#define PHY_M_LED_PULS_DUR(x)  (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK)
 
 /*****  PHY_MARV_PHY_STAT (page 3)16 bit r/w   Polarity Control Reg. *****/
 enum {
@@ -1233,7 +1234,7 @@ enum {
        PULS_1300MS     = 7,/* 1.3 s to 2.7 s */
 };
 
-#define PHY_M_LED_BLINK_RT(x)  (((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+#define PHY_M_LED_BLINK_RT(x)  (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK)
 
 enum {
        BLINK_42MS      = 0,/* 42 ms */
@@ -1243,21 +1244,18 @@ enum {
        BLINK_670MS     = 4,/* 670 ms */
 };
 
-/*****  PHY_MARV_LED_OVER      16 bit r/w      Manual LED Override Reg *****/
-#define PHY_M_LED_MO_SGMII(x)  ((x)<<14) /* Bit 15..14:  SGMII AN Timer */
-                                                                               /* Bit 13..12:  reserved */
-#define PHY_M_LED_MO_DUP(x)    ((x)<<10) /* Bit 11..10:  Duplex */
-#define PHY_M_LED_MO_10(x)     ((x)<<8) /* Bit  9.. 8:  Link 10 */
-#define PHY_M_LED_MO_100(x)    ((x)<<6) /* Bit  7.. 6:  Link 100 */
-#define PHY_M_LED_MO_1000(x)   ((x)<<4) /* Bit  5.. 4:  Link 1000 */
-#define PHY_M_LED_MO_RX(x)     ((x)<<2) /* Bit  3.. 2:  Rx */
-#define PHY_M_LED_MO_TX(x)     ((x)<<0) /* Bit  1.. 0:  Tx */
-
+/**** PHY_MARV_LED_OVER    16 bit r/w LED control */
 enum {
-       MO_LED_NORM     = 0,
-       MO_LED_BLINK    = 1,
-       MO_LED_OFF      = 2,
-       MO_LED_ON       = 3,
+       PHY_M_LED_MO_DUP  = 3<<10,/* Bit 11..10:  Duplex */
+       PHY_M_LED_MO_10   = 3<<8, /* Bit  9.. 8:  Link 10 */
+       PHY_M_LED_MO_100  = 3<<6, /* Bit  7.. 6:  Link 100 */
+       PHY_M_LED_MO_1000 = 3<<4, /* Bit  5.. 4:  Link 1000 */
+       PHY_M_LED_MO_RX   = 3<<2, /* Bit  3.. 2:  Rx */
+       PHY_M_LED_MO_TX   = 3<<0, /* Bit  1.. 0:  Tx */
+
+       PHY_M_LED_ALL     = PHY_M_LED_MO_DUP | PHY_M_LED_MO_10 
+                           | PHY_M_LED_MO_100 | PHY_M_LED_MO_1000
+                           | PHY_M_LED_MO_RX,
 };
 
 /*****  PHY_MARV_EXT_CTRL_2    16 bit r/w      Ext. PHY Specific Ctrl 2 *****/
@@ -1294,9 +1292,9 @@ enum {
        PHY_M_FELP_LED0_MSK = 0xf, /* Bit  3.. 0: LED0 Mask (SPEED) */
 };
 
-#define PHY_M_FELP_LED2_CTRL(x)        (((x)<<8) & PHY_M_FELP_LED2_MSK)
-#define PHY_M_FELP_LED1_CTRL(x)        (((x)<<4) & PHY_M_FELP_LED1_MSK)
-#define PHY_M_FELP_LED0_CTRL(x)        (((x)<<0) & PHY_M_FELP_LED0_MSK)
+#define PHY_M_FELP_LED2_CTRL(x)        (((u16)(x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x)        (((u16)(x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x)        (((u16)(x)<<0) & PHY_M_FELP_LED0_MSK)
 
 enum {
        LED_PAR_CTRL_COLX       = 0x00,
@@ -1552,8 +1550,8 @@ enum {
        GM_SMI_CT_BUSY          = 1<<3, /* Bit  3:      Busy (Operation in progress) */
 };
 
-#define GM_SMI_CT_PHY_AD(x)    (((x)<<11) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x)    (((x)<<6) & GM_SMI_CT_REG_A_MSK)
+#define GM_SMI_CT_PHY_AD(x)    (((u16)(x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x)    (((u16)(x)<<6) & GM_SMI_CT_REG_A_MSK)
 
 /*     GM_PHY_ADDR                             16 bit r/w      GPHY Address Register */
 enum {
index 889ef0d..d70bc97 100644 (file)
@@ -593,7 +593,7 @@ static void cleanup_card(struct net_device *dev)
        iounmap(ei_status.mem);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index e10755e..2c5319c 100644 (file)
@@ -437,7 +437,7 @@ int __init init_module(void)
        return -ENXIO;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int this_dev;
 
index c0d13d6..bd6e845 100644 (file)
@@ -1616,7 +1616,7 @@ int __init init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(devSMC9194);
        free_irq(devSMC9194->irq, devSMC9194);
index 95b6478..e62a958 100644 (file)
@@ -210,6 +210,7 @@ struct smc_local {
 
        /* work queue */
        struct work_struct phy_configure;
+       struct net_device *dev;
        int     work_pending;
 
        spinlock_t lock;
@@ -1114,10 +1115,11 @@ static void smc_phy_check_media(struct net_device *dev, int init)
  * of autonegotiation.)  If the RPC ANEG bit is cleared, the selection
  * is controlled by the RPC SPEED and RPC DPLX bits.
  */
-static void smc_phy_configure(void *data)
+static void smc_phy_configure(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct smc_local *lp = netdev_priv(dev);
+       struct smc_local *lp =
+               container_of(work, struct smc_local, phy_configure);
+       struct net_device *dev = lp->dev;
        void __iomem *ioaddr = lp->base;
        int phyaddr = lp->mii.phy_id;
        int my_phy_caps; /* My PHY capabilities */
@@ -1592,7 +1594,7 @@ smc_open(struct net_device *dev)
 
        /* Configure the PHY, initialize the link state */
        if (lp->phy_type != 0)
-               smc_phy_configure(dev);
+               smc_phy_configure(&lp->phy_configure);
        else {
                spin_lock_irq(&lp->lock);
                smc_10bt_check_media(dev, 1);
@@ -1972,7 +1974,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
 #endif
 
        tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
-       INIT_WORK(&lp->phy_configure, smc_phy_configure, dev);
+       INIT_WORK(&lp->phy_configure, smc_phy_configure);
+       lp->dev = dev;
        lp->mii.phy_id_mask = 0x1f;
        lp->mii.reg_num_mask = 0x1f;
        lp->mii.force_media = 0;
@@ -2322,7 +2325,7 @@ static int smc_drv_resume(struct platform_device *dev)
                        smc_reset(ndev);
                        smc_enable(ndev);
                        if (lp->phy_type != 0)
-                               smc_phy_configure(ndev);
+                               smc_phy_configure(&lp->phy_configure);
                        netif_device_attach(ndev);
                }
        }
index a864016..d2767e6 100644 (file)
@@ -238,7 +238,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_CAN_USE_16BIT      1
 #define SMC_CAN_USE_32BIT      0
 
-#define SMC_inb(a, r)          inb((u32)a) + (r))
+#define SMC_inb(a, r)          inb(((u32)a) + (r))
 #define SMC_inw(a, r)          inw(((u32)a) + (r))
 #define SMC_outb(v, a, r)      outb(v, ((u32)a) + (r))
 #define SMC_outw(v, a, r)      outw(v, ((u32)a) + (r))
@@ -362,78 +362,6 @@ 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)
-
-#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)
-
-#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)
-
-#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
@@ -1216,7 +1144,7 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_CAN_USE_32BIT) {                                \
                        void *__ptr = (p);                              \
                        int __len = (l);                                \
-                       void *__ioaddr = ioaddr;                        \
+                       void __iomem *__ioaddr = ioaddr;                \
                        if (__len >= 2 && (unsigned long)__ptr & 2) {   \
                                __len -= 2;                             \
                                SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \
@@ -1240,7 +1168,7 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_CAN_USE_32BIT) {                                \
                        void *__ptr = (p);                              \
                        int __len = (l);                                \
-                       void *__ioaddr = ioaddr;                        \
+                       void __iomem *__ioaddr = ioaddr;                \
                        if ((unsigned long)__ptr & 2) {                 \
                                /*                                      \
                                 * We want 32bit alignment here.        \
index 13e0a43..ebb6aa3 100644 (file)
@@ -1939,10 +1939,11 @@ spider_net_stop(struct net_device *netdev)
  * called as task when tx hangs, resets interface (if interface is up)
  */
 static void
-spider_net_tx_timeout_task(void *data)
+spider_net_tx_timeout_task(struct work_struct *work)
 {
-       struct net_device *netdev = data;
-       struct spider_net_card *card = netdev_priv(netdev);
+       struct spider_net_card *card =
+               container_of(work, struct spider_net_card, tx_timeout_task);
+       struct net_device *netdev = card->netdev;
 
        if (!(netdev->flags & IFF_UP))
                goto out;
@@ -2116,7 +2117,7 @@ spider_net_alloc_card(void)
        card = netdev_priv(netdev);
        card->netdev = netdev;
        card->msg_enable = SPIDER_NET_DEFAULT_MSG;
-       INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev);
+       INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task);
        init_waitqueue_head(&card->waitq);
        atomic_set(&card->tx_timeout_task_counter, 0);
 
index 47a1c09..c62e85d 100644 (file)
@@ -945,7 +945,7 @@ static void set_multicast_list( struct net_device *dev )
 
 static struct net_device *sun3lance_dev;
 
-int init_module(void)
+int __init init_module(void)
 {
        sun3lance_dev = sun3lance_probe(-1);
        if (IS_ERR(sun3lance_dev))
@@ -953,7 +953,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(sun3lance_dev);
 #ifdef CONFIG_SUN3
index cf44e72..785e4a5 100644 (file)
@@ -2282,9 +2282,9 @@ static void gem_do_stop(struct net_device *dev, int wol)
        }
 }
 
-static void gem_reset_task(void *data)
+static void gem_reset_task(struct work_struct *work)
 {
-       struct gem *gp = (struct gem *) data;
+       struct gem *gp = container_of(work, struct gem, reset_task);
 
        mutex_lock(&gp->pm_mutex);
 
@@ -3044,7 +3044,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        gp->link_timer.function = gem_link_timer;
        gp->link_timer.data = (unsigned long) gp;
 
-       INIT_WORK(&gp->reset_task, gem_reset_task, gp);
+       INIT_WORK(&gp->reset_task, gem_reset_task);
 
        gp->lstate = link_down;
        gp->timer_ticks = 0;
index c20bb99..571320a 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.69"
-#define DRV_MODULE_RELDATE     "November 15, 2006"
+#define DRV_MODULE_VERSION     "3.70"
+#define DRV_MODULE_RELDATE     "December 1, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -192,6 +192,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -1061,7 +1062,7 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 {
        struct tg3 *tp_peer = tp;
 
-       if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0)
+       if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
                return;
 
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
@@ -1212,8 +1213,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                                      power_control);
                udelay(100);    /* Delay after power state change */
 
-               /* Switch out of Vaux if it is not a LOM */
-               if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT))
+               /* Switch out of Vaux if it is a NIC */
+               if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
                        tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
 
                return 0;
@@ -1401,8 +1402,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 static void tg3_link_report(struct tg3 *tp)
 {
        if (!netif_carrier_ok(tp->dev)) {
-               printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name);
-       } else {
+               if (netif_msg_link(tp))
+                       printk(KERN_INFO PFX "%s: Link is down.\n",
+                              tp->dev->name);
+       } else if (netif_msg_link(tp)) {
                printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
                       tp->dev->name,
                       (tp->link_config.active_speed == SPEED_1000 ?
@@ -1557,12 +1560,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
 
                tg3_writephy(tp, MII_ADVERTISE, new_adv);
        } else if (tp->link_config.speed == SPEED_INVALID) {
-               tp->link_config.advertising =
-                       (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-                        ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-                        ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-                        ADVERTISED_Autoneg | ADVERTISED_MII);
-
                if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
                        tp->link_config.advertising &=
                                ~(ADVERTISED_1000baseT_Half |
@@ -1706,25 +1703,36 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp)
        return err;
 }
 
-static int tg3_copper_is_advertising_all(struct tg3 *tp)
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
 {
-       u32 adv_reg, all_mask;
+       u32 adv_reg, all_mask = 0;
+
+       if (mask & ADVERTISED_10baseT_Half)
+               all_mask |= ADVERTISE_10HALF;
+       if (mask & ADVERTISED_10baseT_Full)
+               all_mask |= ADVERTISE_10FULL;
+       if (mask & ADVERTISED_100baseT_Half)
+               all_mask |= ADVERTISE_100HALF;
+       if (mask & ADVERTISED_100baseT_Full)
+               all_mask |= ADVERTISE_100FULL;
 
        if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
                return 0;
 
-       all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL |
-                   ADVERTISE_100HALF | ADVERTISE_100FULL);
        if ((adv_reg & all_mask) != all_mask)
                return 0;
        if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
                u32 tg3_ctrl;
 
+               all_mask = 0;
+               if (mask & ADVERTISED_1000baseT_Half)
+                       all_mask |= ADVERTISE_1000HALF;
+               if (mask & ADVERTISED_1000baseT_Full)
+                       all_mask |= ADVERTISE_1000FULL;
+
                if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
                        return 0;
 
-               all_mask = (MII_TG3_CTRL_ADV_1000_HALF |
-                           MII_TG3_CTRL_ADV_1000_FULL);
                if ((tg3_ctrl & all_mask) != all_mask)
                        return 0;
        }
@@ -1884,7 +1892,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                                /* Force autoneg restart if we are exiting
                                 * low power mode.
                                 */
-                               if (!tg3_copper_is_advertising_all(tp))
+                               if (!tg3_copper_is_advertising_all(tp,
+                                               tp->link_config.advertising))
                                        current_link_up = 0;
                        } else {
                                current_link_up = 0;
@@ -3654,9 +3663,9 @@ static void tg3_poll_controller(struct net_device *dev)
 }
 #endif
 
-static void tg3_reset_task(void *_data)
+static void tg3_reset_task(struct work_struct *work)
 {
-       struct tg3 *tp = _data;
+       struct tg3 *tp = container_of(work, struct tg3, reset_task);
        unsigned int restart_timer;
 
        tg3_full_lock(tp, 0);
@@ -3703,8 +3712,9 @@ static void tg3_tx_timeout(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
-              dev->name);
+       if (netif_msg_tx_err(tp))
+               printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
+                      dev->name);
 
        schedule_work(&tp->reset_task);
 }
@@ -6396,16 +6406,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        udelay(40);
 
        /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
-        * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the
+        * If TG3_FLG2_IS_NIC is zero, we should read the
         * register to preserve the GPIO settings for LOMs. The GPIOs,
         * whether used as inputs or outputs, are set by boot code after
         * reset.
         */
-       if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+       if (!(tp->tg3_flags2 & TG3_FLG2_IS_NIC)) {
                u32 gpio_mask;
 
-               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 |
-                           GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2;
+               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+                           GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+                           GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
 
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                        gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
@@ -6417,8 +6428,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
 
                /* GPIO1 must be driven high for eeprom write protect */
-               tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
-                                      GRC_LCLCTRL_GPIO_OUTPUT1);
+               if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)
+                       tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+                                              GRC_LCLCTRL_GPIO_OUTPUT1);
        }
        tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        udelay(100);
@@ -8656,7 +8668,9 @@ static int tg3_test_registers(struct tg3 *tp)
        return 0;
 
 out:
-       printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
+       if (netif_msg_hw(tp))
+               printk(KERN_ERR PFX "Register test failed at offset %x\n",
+                      offset);
        tw32(offset, save_val);
        return -EIO;
 }
@@ -8781,17 +8795,20 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                                        tg3_writephy(tp, 0x10, phy & ~0x4000);
                                tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
                        }
-               }
-               val = BMCR_LOOPBACK | BMCR_FULLDPLX;
-               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-                       val |= BMCR_SPEED100;
-               else
-                       val |= BMCR_SPEED1000;
+                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
+               } else
+                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
 
                tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+
+               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+                          MAC_MODE_LINK_POLARITY;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                        tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+                       mac_mode |= MAC_MODE_PORT_MODE_MII;
+               } else
+                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
 
                /* reset to prevent losing 1st rx packet intermittently */
                if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
@@ -8799,12 +8816,6 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        udelay(10);
                        tw32_f(MAC_RX_MODE, tp->rx_mode);
                }
-               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_LINK_POLARITY;
-               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-                       mac_mode |= MAC_MODE_PORT_MODE_MII;
-               else
-                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
                if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
@@ -9456,16 +9467,12 @@ static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
-       int j;
-
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
              (EEPROM_DEFAULT_CLOCK_PERIOD <<
               EEPROM_ADDR_CLKPERD_SHIFT)));
 
-       /* XXX schedule_timeout() ... */
-       for (j = 0; j < 100; j++)
-               udelay(10);
+       msleep(1);
 
        /* Enable seeprom accesses. */
        tw32_f(GRC_LOCAL_CTRL,
@@ -9526,12 +9533,12 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
              EEPROM_ADDR_ADDR_MASK) |
             EEPROM_ADDR_READ | EEPROM_ADDR_START);
 
-       for (i = 0; i < 10000; i++) {
+       for (i = 0; i < 1000; i++) {
                tmp = tr32(GRC_EEPROM_ADDR);
 
                if (tmp & EEPROM_ADDR_COMPLETE)
                        break;
-               udelay(100);
+               msleep(1);
        }
        if (!(tmp & EEPROM_ADDR_COMPLETE))
                return -EBUSY;
@@ -9656,12 +9663,12 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
                        EEPROM_ADDR_START |
                        EEPROM_ADDR_WRITE);
 
-               for (j = 0; j < 10000; j++) {
+               for (j = 0; j < 1000; j++) {
                        val = tr32(GRC_EEPROM_ADDR);
 
                        if (val & EEPROM_ADDR_COMPLETE)
                                break;
-                       udelay(100);
+                       msleep(1);
                }
                if (!(val & EEPROM_ADDR_COMPLETE)) {
                        rc = -EBUSY;
@@ -9965,8 +9972,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM))
+               if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+                       tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+               }
                return;
        }
 
@@ -10066,10 +10075,17 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
                        tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
+               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
-               else
+                       if ((tp->pdev->subsystem_vendor ==
+                            PCI_VENDOR_ID_ARIMA) &&
+                           (tp->pdev->subsystem_device == 0x205a ||
+                            tp->pdev->subsystem_device == 0x2063))
+                               tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+               } else {
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+                       tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+               }
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
@@ -10147,7 +10163,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 
        if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
            !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-               u32 bmsr, adv_reg, tg3_ctrl;
+               u32 bmsr, adv_reg, tg3_ctrl, mask;
 
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
@@ -10171,7 +10187,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                                             MII_TG3_CTRL_ENABLE_AS_MASTER);
                }
 
-               if (!tg3_copper_is_advertising_all(tp)) {
+               mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                       ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                       ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+               if (!tg3_copper_is_advertising_all(tp, mask)) {
                        tg3_writephy(tp, MII_ADVERTISE, adv_reg);
 
                        if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
@@ -10695,7 +10714,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
 
        /* Get eeprom hw config before calling tg3_set_power_state().
-        * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
+        * In particular, the TG3_FLG2_IS_NIC flag must be
         * determined before calling tg3_set_power_state() so that
         * we know whether or not to switch out of Vaux power.
         * When the flag is set, it means that GPIO1 is used for eeprom
@@ -10862,7 +10881,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
              tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
            (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
             (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
@@ -11734,7 +11754,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 #endif
        spin_lock_init(&tp->lock);
        spin_lock_init(&tp->indirect_lock);
-       INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
+       INIT_WORK(&tp->reset_task, tg3_reset_task);
 
        tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
        if (tp->regs == 0UL) {
@@ -11912,13 +11932,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
               tg3_phy_string(tp),
               tg3_bus_string(tp, str),
-              (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
+              ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+               ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+                "10/100/1000Base-T")));
 
        for (i = 0; i < 6; i++)
                printk("%2.2x%c", dev->dev_addr[i],
index 92f5300..dfaf4ed 100644 (file)
@@ -2233,6 +2233,7 @@ struct tg3 {
 #define TG3_FLG2_PCI_EXPRESS           0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE     0x00000400
 #define TG3_FLG2_HW_AUTONEG            0x00000800
+#define TG3_FLG2_IS_NIC                        0x00001000
 #define TG3_FLG2_PHY_SERDES            0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING   0x00004000
 #define TG3_FLG2_FLASH                 0x00008000
index e14f5a0..f85f002 100644 (file)
@@ -296,6 +296,7 @@ static void TLan_SetMulticastList( struct net_device *);
 static int     TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);
 static int      TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent);
 static void    TLan_tx_timeout( struct net_device *dev);
+static void    TLan_tx_timeout_work(struct work_struct *work);
 static int     tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
 
 static u32     TLan_HandleInvalid( struct net_device *, u16 );
@@ -562,6 +563,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
        priv = netdev_priv(dev);
 
        priv->pciDev = pdev;
+       priv->dev = dev;
 
        /* Is this a PCI device? */
        if (pdev) {
@@ -634,7 +636,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 
        /* This will be used when we get an adapter error from
         * within our irq handler */
-       INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev);
+       INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work);
 
        spin_lock_init(&priv->lock);
 
@@ -1040,6 +1042,25 @@ static void TLan_tx_timeout(struct net_device *dev)
 }
 
 
+       /***************************************************************
+        *      TLan_tx_timeout_work
+        *
+        *      Returns: nothing
+        *
+        *      Params:
+        *              work    work item of device which timed out
+        *
+        **************************************************************/
+
+static void TLan_tx_timeout_work(struct work_struct *work)
+{
+       TLanPrivateInfo *priv =
+               container_of(work, TLanPrivateInfo, tlan_tqueue);
+
+       TLan_tx_timeout(priv->dev);
+}
+
+
 
        /***************************************************************
         *      TLan_StartTx
index a44e2f2..41ce0b6 100644 (file)
@@ -170,6 +170,7 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
 typedef struct tlan_private_tag {
        struct net_device       *nextDevice;
        struct pci_dev          *pciDev;
+       struct net_device       *dev;
        void                    *dmaStorage;
        dma_addr_t              dmaStorageDMA;
        unsigned int            dmaSize;
index 46dabdb..cec282a 100644 (file)
@@ -5706,7 +5706,7 @@ int __init init_module(void)
         return found ? 0 : -ENODEV;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
         int i;
 
index fa3a2bb..942b839 100644 (file)
@@ -26,10 +26,11 @@ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
 /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
    of available transceivers.  */
-void t21142_media_task(void *data)
+void t21142_media_task(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct tulip_private *tp = netdev_priv(dev);
+       struct tulip_private *tp =
+               container_of(work, struct tulip_private, media_work);
+       struct net_device *dev = tp->dev;
        void __iomem *ioaddr = tp->base_addr;
        int csr12 = ioread32(ioaddr + CSR12);
        int next_tick = 60*HZ;
index 066e5d6..df326fe 100644 (file)
 #include "tulip.h"
 
 
-void tulip_media_task(void *data)
+void tulip_media_task(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct tulip_private *tp = netdev_priv(dev);
+       struct tulip_private *tp =
+               container_of(work, struct tulip_private, media_work);
+       struct net_device *dev = tp->dev;
        void __iomem *ioaddr = tp->base_addr;
        u32 csr12 = ioread32(ioaddr + CSR12);
        int next_tick = 2*HZ;
index ad107f4..25f25da 100644 (file)
@@ -44,7 +44,7 @@ struct tulip_chip_table {
        int valid_intrs;        /* CSR7 interrupt enable settings */
        int flags;
        void (*media_timer) (unsigned long);
-       void (*media_task) (void *);
+       work_func_t media_task;
 };
 
 
@@ -392,6 +392,7 @@ struct tulip_private {
        int csr12_shadow;
        int pad0;               /* Used for 8-byte alignment */
        struct work_struct media_work;
+       struct net_device *dev;
 };
 
 
@@ -406,7 +407,7 @@ struct eeprom_fixup {
 
 /* 21142.c */
 extern u16 t21142_csr14[];
-void t21142_media_task(void *data);
+void t21142_media_task(struct work_struct *work);
 void t21142_start_nway(struct net_device *dev);
 void t21142_lnk_change(struct net_device *dev, int csr5);
 
@@ -444,7 +445,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5);
 void pnic_timer(unsigned long data);
 
 /* timer.c */
-void tulip_media_task(void *data);
+void tulip_media_task(struct work_struct *work);
 void mxic_timer(unsigned long data);
 void comet_timer(unsigned long data);
 
index 0aee618..5a35354 100644 (file)
@@ -1367,6 +1367,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
         * it is zeroed and aligned in alloc_etherdev
         */
        tp = netdev_priv(dev);
+       tp->dev = dev;
 
        tp->rx_ring = pci_alloc_consistent(pdev,
                                           sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
@@ -1389,7 +1390,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        tp->timer.data = (unsigned long)dev;
        tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
 
-       INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev);
+       INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task);
 
        dev->base_addr = (unsigned long)ioaddr;
 
index 1f05511..8243150 100644 (file)
@@ -194,9 +194,9 @@ static void enqueue(struct list_head *node, struct list_head *lh)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(ugeth_lock, flags);
+       spin_lock_irqsave(&ugeth_lock, flags);
        list_add_tail(node, lh);
-       spin_unlock_irqrestore(ugeth_lock, flags);
+       spin_unlock_irqrestore(&ugeth_lock, flags);
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
@@ -204,14 +204,14 @@ static struct list_head *dequeue(struct list_head *lh)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(ugeth_lock, flags);
+       spin_lock_irqsave(&ugeth_lock, flags);
        if (!list_empty(lh)) {
                struct list_head *node = lh->next;
                list_del(node);
-               spin_unlock_irqrestore(ugeth_lock, flags);
+               spin_unlock_irqrestore(&ugeth_lock, flags);
                return node;
        } else {
-               spin_unlock_irqrestore(ugeth_lock, flags);
+               spin_unlock_irqrestore(&ugeth_lock, flags);
                return NULL;
        }
 }
@@ -1852,6 +1852,8 @@ static int init_phy(struct net_device *dev)
        mii_info->mdio_read = &read_phy_reg;
        mii_info->mdio_write = &write_phy_reg;
 
+       spin_lock_init(&mii_info->mdio_lock);
+
        ugeth->mii_info = mii_info;
 
        spin_lock_irq(&ugeth->lock);
index 74f8947..4587f23 100644 (file)
@@ -3132,7 +3132,7 @@ static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
        }
        /*      Finally, invert the result once to get the correct data */
        crc = ~crc;
-       return bitreverse(crc) >> 16;
+       return bitrev32(crc) >> 16;
 }
 
 /**
index d5ab9cf..21f76f5 100644 (file)
@@ -382,7 +382,7 @@ config SDLA
 
 # Wan router core.
 config WAN_ROUTER_DRIVERS
-       bool "WAN router drivers"
+       tristate "WAN router drivers"
        depends on WAN && WAN_ROUTER
        ---help---
          Connect LAN to WAN via Linux box.
@@ -393,7 +393,8 @@ config WAN_ROUTER_DRIVERS
          <file:Documentation/networking/wan-router.txt>.
 
          Note that the answer to this question won't directly affect the
-         kernel: saying N will just cause the configurator to skip all
+         kernel except for how subordinate drivers may be built:
+         saying N will just cause the configurator to skip all
          the questions about WAN router drivers.
 
          If unsure, say N.
index e1bf8b9..6c7dfb5 100644 (file)
@@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file)
        unsigned long flags;
        int n;
 
-       if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS)
+       if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS)
                >= nr_cards)
                return -ENODEV;
        cosa = cosa_cards+n;
 
-       if ((n=iminor(file->f_dentry->d_inode)
+       if ((n=iminor(file->f_path.dentry->d_inode)
                & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
                return -ENODEV;
        chan = cosa->chan + n;
index 931cbdf..b2a23ae 100644 (file)
@@ -125,8 +125,8 @@ static int cpc_tty_write_room(struct tty_struct *tty);
 static int cpc_tty_chars_in_buffer(struct tty_struct *tty);
 static void cpc_tty_flush_buffer(struct tty_struct *tty);
 static void cpc_tty_hangup(struct tty_struct *tty);
-static void cpc_tty_rx_work(void *data);
-static void cpc_tty_tx_work(void *data);
+static void cpc_tty_rx_work(struct work_struct *work);
+static void cpc_tty_tx_work(struct work_struct *work);
 static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len);
 static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
 static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
@@ -261,8 +261,8 @@ void cpc_tty_init(pc300dev_t *pc300dev)
        cpc_tty->tty_minor = port + CPC_TTY_MINOR_START;
        cpc_tty->pc300dev = pc300dev; 
 
-       INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty);
-       INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port);
+       INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work);
+       INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work);
        
        cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL;
 
@@ -659,21 +659,23 @@ static void cpc_tty_hangup(struct tty_struct *tty)
  * o call the line disc. read
  * o free memory
  */
-static void cpc_tty_rx_work(void * data)
+static void cpc_tty_rx_work(struct work_struct *work)
 {
+       st_cpc_tty_area *cpc_tty;
        unsigned long port;
        int i, j;
-       st_cpc_tty_area *cpc_tty; 
        volatile st_cpc_rx_buf *buf;
        char flags=0,flg_rx=1; 
        struct tty_ldisc *ld;
 
        if (cpc_tty_cnt == 0) return;
-
        
        for (i=0; (i < 4) && flg_rx ; i++) {
                flg_rx = 0;
-               port = (unsigned long)data;
+
+               cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work);
+               port = cpc_tty - cpc_tty_area;
+
                for (j=0; j < CPC_TTY_NPORTS; j++) {
                        cpc_tty = &cpc_tty_area[port];
                
@@ -882,9 +884,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
  * o if need call line discipline wakeup
  * o call wake_up_interruptible
  */
-static void cpc_tty_tx_work(void *data)
+static void cpc_tty_tx_work(struct work_struct *work)
 {
-       st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; 
+       st_cpc_tty_area *cpc_tty =
+               container_of(work, st_cpc_tty_area, tty_tx_work);
        struct tty_struct *tty; 
 
        CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name);
index 41f1d67..7f38012 100644 (file)
@@ -538,7 +538,7 @@ static void cleanup_card(struct net_device *dev)
        iounmap(ei_status.mem);
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int this_dev;
index efcdaf1..44a2270 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/uaccess.h>
 #include <net/ieee80211.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include "airo.h"
 
index 94dfb92..8286678 100644 (file)
@@ -819,7 +819,7 @@ struct bcm43xx_private {
        struct tasklet_struct isr_tasklet;
 
        /* Periodic tasks */
-       struct work_struct periodic_work;
+       struct delayed_work periodic_work;
        unsigned int periodic_state;
 
        struct work_struct restart_work;
index 5b3c273..2ec2e5a 100644 (file)
@@ -3215,9 +3215,10 @@ static void do_periodic_work(struct bcm43xx_private *bcm)
        schedule_delayed_work(&bcm->periodic_work, HZ * 15);
 }
 
-static void bcm43xx_periodic_work_handler(void *d)
+static void bcm43xx_periodic_work_handler(struct work_struct *work)
 {
-       struct bcm43xx_private *bcm = d;
+       struct bcm43xx_private *bcm =
+               container_of(work, struct bcm43xx_private, periodic_work.work);
        struct net_device *net_dev = bcm->net_dev;
        unsigned long flags;
        u32 savedirqs = 0;
@@ -3279,11 +3280,11 @@ void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
 
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-       struct work_struct *work = &(bcm->periodic_work);
+       struct delayed_work *work = &bcm->periodic_work;
 
        assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-       INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
-       schedule_work(work);
+       INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
+       schedule_delayed_work(work, 0);
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3635,7 +3636,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
        bcm43xx_periodic_tasks_setup(bcm);
 
        /*FIXME: This should be handled by softmac instead. */
-       schedule_work(&bcm->softmac->associnfo.work);
+       schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
 
 out:
        mutex_unlock(&(bcm)->mutex);
@@ -4182,9 +4183,10 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
 /* Hard-reset the chip. Do not call this directly.
  * Use bcm43xx_controller_restart()
  */
-static void bcm43xx_chip_reset(void *_bcm)
+static void bcm43xx_chip_reset(struct work_struct *work)
 {
-       struct bcm43xx_private *bcm = _bcm;
+       struct bcm43xx_private *bcm =
+               container_of(work, struct bcm43xx_private, restart_work);
        struct bcm43xx_phyinfo *phy;
        int err = -ENODEV;
 
@@ -4211,7 +4213,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
                return;
        printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
-       INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
+       INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
        schedule_work(&bcm->restart_work);
 }
 
index e663518..e89c890 100644 (file)
@@ -35,7 +35,7 @@ int hostap_80211_get_hdrlen(u16 fc);
 struct net_device_stats *hostap_get_stats(struct net_device *dev);
 void hostap_setup_dev(struct net_device *dev, local_info_t *local,
                      int main_dev);
-void hostap_set_multicast_list_queue(void *data);
+void hostap_set_multicast_list_queue(struct work_struct *work);
 int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked);
 int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked);
 void hostap_cleanup(local_info_t *local);
index ba13125..974a8e5 100644 (file)
@@ -49,10 +49,10 @@ MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs "
 static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta);
 static void hostap_event_expired_sta(struct net_device *dev,
                                     struct sta_info *sta);
-static void handle_add_proc_queue(void *data);
+static void handle_add_proc_queue(struct work_struct *work);
 
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-static void handle_wds_oper_queue(void *data);
+static void handle_wds_oper_queue(struct work_struct *work);
 static void prism2_send_mgmt(struct net_device *dev,
                             u16 type_subtype, char *body,
                             int body_len, u8 *addr, u16 tx_cb_idx);
@@ -807,7 +807,7 @@ void hostap_init_data(local_info_t *local)
        INIT_LIST_HEAD(&ap->sta_list);
 
        /* Initialize task queue structure for AP management */
-       INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap);
+       INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue);
 
        ap->tx_callback_idx =
                hostap_tx_callback_register(local, hostap_ap_tx_cb, ap);
@@ -815,7 +815,7 @@ void hostap_init_data(local_info_t *local)
                printk(KERN_WARNING "%s: failed to register TX callback for "
                       "AP\n", local->dev->name);
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-       INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local);
+       INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue);
 
        ap->tx_callback_auth =
                hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap);
@@ -1062,9 +1062,10 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
 }
 
 
-static void handle_add_proc_queue(void *data)
+static void handle_add_proc_queue(struct work_struct *work)
 {
-       struct ap_data *ap = (struct ap_data *) data;
+       struct ap_data *ap = container_of(work, struct ap_data,
+                                         add_sta_proc_queue);
        struct sta_info *sta;
        char name[20];
        struct add_sta_proc_data *entry, *prev;
@@ -1099,15 +1100,13 @@ static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr)
 {
        struct sta_info *sta;
 
-       sta = (struct sta_info *)
-               kmalloc(sizeof(struct sta_info), GFP_ATOMIC);
+       sta = kzalloc(sizeof(struct sta_info), GFP_ATOMIC);
        if (sta == NULL) {
                PDEBUG(DEBUG_AP, "AP: kmalloc failed\n");
                return NULL;
        }
 
        /* initialize STA info data */
-       memset(sta, 0, sizeof(struct sta_info));
        sta->local = ap->local;
        skb_queue_head_init(&sta->tx_buf);
        memcpy(sta->addr, addr, ETH_ALEN);
@@ -1952,9 +1951,11 @@ static void handle_pspoll(local_info_t *local,
 
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
 
-static void handle_wds_oper_queue(void *data)
+static void handle_wds_oper_queue(struct work_struct *work)
 {
-       local_info_t *local = data;
+       struct ap_data *ap = container_of(work, struct ap_data,
+                                         wds_oper_queue);
+       local_info_t *local = ap->local;
        struct wds_oper_data *entry, *prev;
 
        spin_lock_bh(&local->lock);
index ee542ec..8d8f4b9 100644 (file)
@@ -563,12 +563,11 @@ static int prism2_config(struct pcmcia_device *link)
        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
        parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
-       hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+       hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
        if (parse == NULL || hw_priv == NULL) {
                ret = -ENOMEM;
                goto failed;
        }
-       memset(hw_priv, 0, sizeof(*hw_priv));
 
        tuple.Attributes = 0;
        tuple.TupleData = buf;
index ab26b52..24fc387 100644 (file)
@@ -685,14 +685,12 @@ static int prism2_download(local_info_t *local,
                goto out;
        }
 
-       dl = kmalloc(sizeof(*dl) + param->num_areas *
+       dl = kzalloc(sizeof(*dl) + param->num_areas *
                     sizeof(struct prism2_download_data_area), GFP_KERNEL);
        if (dl == NULL) {
                ret = -ENOMEM;
                goto out;
        }
-       memset(dl, 0, sizeof(*dl) + param->num_areas *
-              sizeof(struct prism2_download_data_area));
        dl->dl_cmd = param->dl_cmd;
        dl->start_addr = param->start_addr;
        dl->num_areas = param->num_areas;
index ed00ebb..a394a23 100644 (file)
@@ -347,14 +347,12 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
        if (signal_pending(current))
                return -EINTR;
 
-       entry = (struct hostap_cmd_queue *)
-               kmalloc(sizeof(*entry), GFP_ATOMIC);
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL) {
                printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n",
                       dev->name);
                return -ENOMEM;
        }
-       memset(entry, 0, sizeof(*entry));
        atomic_set(&entry->usecnt, 1);
        entry->type = CMD_SLEEP;
        entry->cmd = cmd;
@@ -517,14 +515,12 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
                return -1;
        }
 
-       entry = (struct hostap_cmd_queue *)
-               kmalloc(sizeof(*entry), GFP_ATOMIC);
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL) {
                printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc "
                       "failed\n", dev->name);
                return -ENOMEM;
        }
-       memset(entry, 0, sizeof(*entry));
        atomic_set(&entry->usecnt, 1);
        entry->type = CMD_CALLBACK;
        entry->cmd = cmd;
@@ -1645,9 +1641,9 @@ static void prism2_schedule_reset(local_info_t *local)
 
 /* Called only as scheduled task after noticing card timeout in interrupt
  * context */
-static void handle_reset_queue(void *data)
+static void handle_reset_queue(struct work_struct *work)
 {
-       local_info_t *local = (local_info_t *) data;
+       local_info_t *local = container_of(work, local_info_t, reset_queue);
 
        printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name);
        prism2_hw_reset(local->dev);
@@ -2896,9 +2892,10 @@ static void hostap_passive_scan(unsigned long data)
 
 /* Called only as a scheduled task when communications quality values should
  * be updated. */
-static void handle_comms_qual_update(void *data)
+static void handle_comms_qual_update(struct work_struct *work)
 {
-       local_info_t *local = data;
+       local_info_t *local =
+               container_of(work, local_info_t, comms_qual_update);
        prism2_update_comms_qual(local->dev);
 }
 
@@ -3015,14 +3012,12 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set)
        iface = netdev_priv(dev);
        local = iface->local;
 
-       new_entry = (struct set_tim_data *)
-               kmalloc(sizeof(*new_entry), GFP_ATOMIC);
+       new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC);
        if (new_entry == NULL) {
                printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n",
                       local->dev->name);
                return -ENOMEM;
        }
-       memset(new_entry, 0, sizeof(*new_entry));
        new_entry->aid = aid;
        new_entry->set = set;
 
@@ -3050,9 +3045,9 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set)
 }
 
 
-static void handle_set_tim_queue(void *data)
+static void handle_set_tim_queue(struct work_struct *work)
 {
-       local_info_t *local = (local_info_t *) data;
+       local_info_t *local = container_of(work, local_info_t, set_tim_queue);
        struct set_tim_data *entry;
        u16 val;
 
@@ -3209,15 +3204,15 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
        local->scan_channel_mask = 0xffff;
 
        /* Initialize task queue structures */
-       INIT_WORK(&local->reset_queue, handle_reset_queue, local);
+       INIT_WORK(&local->reset_queue, handle_reset_queue);
        INIT_WORK(&local->set_multicast_list_queue,
-                 hostap_set_multicast_list_queue, local->dev);
+                 hostap_set_multicast_list_queue);
 
-       INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local);
+       INIT_WORK(&local->set_tim_queue, handle_set_tim_queue);
        INIT_LIST_HEAD(&local->set_tim_list);
        spin_lock_init(&local->set_tim_lock);
 
-       INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local);
+       INIT_WORK(&local->comms_qual_update, handle_comms_qual_update);
 
        /* Initialize tasklets for handling hardware IRQ related operations
         * outside hw IRQ handler */
index 50f72d8..b6a02a0 100644 (file)
@@ -327,11 +327,10 @@ static void prism2_info_hostscanresults(local_info_t *local,
        ptr = (u8 *) pos;
 
        new_count = left / result_size;
-       results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+       results = kcalloc(new_count, sizeof(struct hfa384x_hostscan_result),
                          GFP_ATOMIC);
        if (results == NULL)
                return;
-       memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result));
 
        for (i = 0; i < new_count; i++) {
                memcpy(&results[i], ptr, copy_len);
@@ -474,9 +473,9 @@ static void handle_info_queue_scanresults(local_info_t *local)
 
 /* Called only as scheduled task after receiving info frames (used to avoid
  * pending too much time in HW IRQ handler). */
-static void handle_info_queue(void *data)
+static void handle_info_queue(struct work_struct *work)
 {
-       local_info_t *local = (local_info_t *) data;
+       local_info_t *local = container_of(work, local_info_t, info_queue);
 
        if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS,
                               &local->pending_info))
@@ -493,7 +492,7 @@ void hostap_info_init(local_info_t *local)
 {
        skb_queue_head_init(&local->info_list);
 #ifndef PRISM2_NO_STATION_MODES
-       INIT_WORK(&local->info_queue, handle_info_queue, local);
+       INIT_WORK(&local->info_queue, handle_info_queue);
 #endif /* PRISM2_NO_STATION_MODES */
 }
 
index d061fb3..3b7b806 100644 (file)
@@ -181,12 +181,10 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
                struct ieee80211_crypt_data *new_crypt;
 
                /* take WEP into use */
-               new_crypt = (struct ieee80211_crypt_data *)
-                       kmalloc(sizeof(struct ieee80211_crypt_data),
+               new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
                                GFP_KERNEL);
                if (new_crypt == NULL)
                        return -ENOMEM;
-               memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
                if (!new_crypt->ops) {
                        request_module("ieee80211_crypt_wep");
@@ -3320,14 +3318,12 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
 
                prism2_crypt_delayed_deinit(local, crypt);
 
-               new_crypt = (struct ieee80211_crypt_data *)
-                       kmalloc(sizeof(struct ieee80211_crypt_data),
+               new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
                                GFP_KERNEL);
                if (new_crypt == NULL) {
                        ret = -ENOMEM;
                        goto done;
                }
-               memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
                new_crypt->priv = new_crypt->ops->init(i);
                if (new_crypt->priv == NULL) {
@@ -3538,14 +3534,12 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
 
                prism2_crypt_delayed_deinit(local, crypt);
 
-               new_crypt = (struct ieee80211_crypt_data *)
-                       kmalloc(sizeof(struct ieee80211_crypt_data),
+               new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
                                GFP_KERNEL);
                if (new_crypt == NULL) {
                        ret = -ENOMEM;
                        goto done;
                }
-               memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
                new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
                if (new_crypt->priv == NULL) {
index 53374fc..0796be9 100644 (file)
@@ -767,14 +767,14 @@ static int prism2_set_mac_address(struct net_device *dev, void *p)
 
 /* TODO: to be further implemented as soon as Prism2 fully supports
  *       GroupAddresses and correct documentation is available */
-void hostap_set_multicast_list_queue(void *data)
+void hostap_set_multicast_list_queue(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *) data;
+       local_info_t *local =
+               container_of(work, local_info_t, set_multicast_list_queue);
+       struct net_device *dev = local->dev;
        struct hostap_interface *iface;
-       local_info_t *local;
 
        iface = netdev_priv(dev);
-       local = iface->local;
        if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
                            local->is_promisc)) {
                printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",
index d1de976..c4f6020 100644 (file)
@@ -300,10 +300,9 @@ static int prism2_pci_probe(struct pci_dev *pdev,
        struct hostap_interface *iface;
        struct hostap_pci_priv *hw_priv;
 
-       hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+       hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
        if (hw_priv == NULL)
                return -ENOMEM;
-       memset(hw_priv, 0, sizeof(*hw_priv));
 
        if (pci_enable_device(pdev))
                goto err_out_free;
index bc81b13..e235e06 100644 (file)
@@ -447,10 +447,9 @@ static int prism2_plx_probe(struct pci_dev *pdev,
        int tmd7160;
        struct hostap_plx_priv *hw_priv;
 
-       hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+       hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
        if (hw_priv == NULL)
                return -ENOMEM;
-       memset(hw_priv, 0, sizeof(*hw_priv));
 
        if (pci_enable_device(pdev))
                goto err_out_free;
index 79607b8..dd9ba4a 100644 (file)
@@ -316,7 +316,7 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv,
                                     struct ipw2100_fw *fw);
 static int ipw2100_ucode_download(struct ipw2100_priv *priv,
                                  struct ipw2100_fw *fw);
-static void ipw2100_wx_event_work(struct ipw2100_priv *priv);
+static void ipw2100_wx_event_work(struct work_struct *work);
 static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev);
 static struct iw_handler_def ipw2100_wx_handler_def;
 
@@ -679,7 +679,8 @@ static void schedule_reset(struct ipw2100_priv *priv)
                        queue_delayed_work(priv->workqueue, &priv->reset_work,
                                           priv->reset_backoff * HZ);
                else
-                       queue_work(priv->workqueue, &priv->reset_work);
+                       queue_delayed_work(priv->workqueue, &priv->reset_work,
+                                          0);
 
                if (priv->reset_backoff < MAX_RESET_BACKOFF)
                        priv->reset_backoff++;
@@ -1873,8 +1874,10 @@ static void ipw2100_down(struct ipw2100_priv *priv)
        netif_stop_queue(priv->net_dev);
 }
 
-static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
+static void ipw2100_reset_adapter(struct work_struct *work)
 {
+       struct ipw2100_priv *priv =
+               container_of(work, struct ipw2100_priv, reset_work.work);
        unsigned long flags;
        union iwreq_data wrqu = {
                .ap_addr = {
@@ -2071,9 +2074,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
                return;
 
        if (priv->status & STATUS_SECURITY_UPDATED)
-               queue_work(priv->workqueue, &priv->security_work);
+               queue_delayed_work(priv->workqueue, &priv->security_work, 0);
 
-       queue_work(priv->workqueue, &priv->wx_event_work);
+       queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0);
 }
 
 static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
@@ -5524,8 +5527,11 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode)
        return err;
 }
 
-static void ipw2100_security_work(struct ipw2100_priv *priv)
+static void ipw2100_security_work(struct work_struct *work)
 {
+       struct ipw2100_priv *priv =
+               container_of(work, struct ipw2100_priv, security_work.work);
+
        /* If we happen to have reconnected before we get a chance to
         * process this, then update the security settings--which causes
         * a disassociation to occur */
@@ -5748,7 +5754,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
 
        priv->reset_backoff = 0;
        mutex_unlock(&priv->action_mutex);
-       ipw2100_reset_adapter(priv);
+       ipw2100_reset_adapter(&priv->reset_work.work);
        return 0;
 
       done:
@@ -5910,9 +5916,10 @@ static const struct ethtool_ops ipw2100_ethtool_ops = {
        .get_drvinfo = ipw_ethtool_get_drvinfo,
 };
 
-static void ipw2100_hang_check(void *adapter)
+static void ipw2100_hang_check(struct work_struct *work)
 {
-       struct ipw2100_priv *priv = adapter;
+       struct ipw2100_priv *priv =
+               container_of(work, struct ipw2100_priv, hang_check.work);
        unsigned long flags;
        u32 rtc = 0xa5a5a5a5;
        u32 len = sizeof(rtc);
@@ -5952,9 +5959,10 @@ static void ipw2100_hang_check(void *adapter)
        spin_unlock_irqrestore(&priv->low_lock, flags);
 }
 
-static void ipw2100_rf_kill(void *adapter)
+static void ipw2100_rf_kill(struct work_struct *work)
 {
-       struct ipw2100_priv *priv = adapter;
+       struct ipw2100_priv *priv =
+               container_of(work, struct ipw2100_priv, rf_kill.work);
        unsigned long flags;
 
        spin_lock_irqsave(&priv->low_lock, flags);
@@ -6103,14 +6111,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
 
        priv->workqueue = create_workqueue(DRV_NAME);
 
-       INIT_WORK(&priv->reset_work,
-                 (void (*)(void *))ipw2100_reset_adapter, priv);
-       INIT_WORK(&priv->security_work,
-                 (void (*)(void *))ipw2100_security_work, priv);
-       INIT_WORK(&priv->wx_event_work,
-                 (void (*)(void *))ipw2100_wx_event_work, priv);
-       INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv);
-       INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv);
+       INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter);
+       INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work);
+       INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work);
+       INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check);
+       INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill);
 
        tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
                     ipw2100_irq_tasklet, (unsigned long)priv);
@@ -6215,7 +6220,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
        /* Allocate and initialize the Tx/Rx queues and lists */
        if (ipw2100_queues_allocate(priv)) {
                printk(KERN_WARNING DRV_NAME
-                      "Error calilng ipw2100_queues_allocate.\n");
+                      "Error calling ipw2100_queues_allocate.\n");
                err = -ENOMEM;
                goto fail;
        }
@@ -8281,8 +8286,10 @@ static struct iw_handler_def ipw2100_wx_handler_def = {
        .get_wireless_stats = ipw2100_wx_wireless_stats,
 };
 
-static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
+static void ipw2100_wx_event_work(struct work_struct *work)
 {
+       struct ipw2100_priv *priv =
+               container_of(work, struct ipw2100_priv, wx_event_work.work);
        union iwreq_data wrqu;
        int len = ETH_ALEN;
 
index 55b7227..de7d384 100644 (file)
@@ -583,11 +583,11 @@ struct ipw2100_priv {
        struct tasklet_struct irq_tasklet;
 
        struct workqueue_struct *workqueue;
-       struct work_struct reset_work;
-       struct work_struct security_work;
-       struct work_struct wx_event_work;
-       struct work_struct hang_check;
-       struct work_struct rf_kill;
+       struct delayed_work reset_work;
+       struct delayed_work security_work;
+       struct delayed_work wx_event_work;
+       struct delayed_work hang_check;
+       struct delayed_work rf_kill;
 
        u32 interrupts;
        int tx_interrupts;
index c692d01..22cb3fb 100644 (file)
@@ -70,7 +70,7 @@
 #define VQ
 #endif
 
-#define IPW2200_VERSION "1.1.4" VK VD VM VP VR VQ
+#define IPW2200_VERSION "1.2.0" VK VD VM VP VR VQ
 #define DRV_DESCRIPTION        "Intel(R) PRO/Wireless 2200/2915 Network Driver"
 #define DRV_COPYRIGHT  "Copyright(c) 2003-2006 Intel Corporation"
 #define DRV_VERSION     IPW2200_VERSION
@@ -187,9 +187,9 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *);
 static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *);
 static void ipw_rx_queue_replenish(void *);
 static int ipw_up(struct ipw_priv *);
-static void ipw_bg_up(void *);
+static void ipw_bg_up(struct work_struct *work);
 static void ipw_down(struct ipw_priv *);
-static void ipw_bg_down(void *);
+static void ipw_bg_down(struct work_struct *work);
 static int ipw_config(struct ipw_priv *);
 static int init_supported_rates(struct ipw_priv *priv,
                                struct ipw_supported_rates *prates);
@@ -862,11 +862,12 @@ static void ipw_led_link_on(struct ipw_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void ipw_bg_led_link_on(void *data)
+static void ipw_bg_led_link_on(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, led_link_on.work);
        mutex_lock(&priv->mutex);
-       ipw_led_link_on(data);
+       ipw_led_link_on(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -906,11 +907,12 @@ static void ipw_led_link_off(struct ipw_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void ipw_bg_led_link_off(void *data)
+static void ipw_bg_led_link_off(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, led_link_off.work);
        mutex_lock(&priv->mutex);
-       ipw_led_link_off(data);
+       ipw_led_link_off(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -985,11 +987,12 @@ static void ipw_led_activity_off(struct ipw_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void ipw_bg_led_activity_off(void *data)
+static void ipw_bg_led_activity_off(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, led_act_off.work);
        mutex_lock(&priv->mutex);
-       ipw_led_activity_off(data);
+       ipw_led_activity_off(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -2228,11 +2231,12 @@ static void ipw_adapter_restart(void *adapter)
        }
 }
 
-static void ipw_bg_adapter_restart(void *data)
+static void ipw_bg_adapter_restart(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, adapter_restart);
        mutex_lock(&priv->mutex);
-       ipw_adapter_restart(data);
+       ipw_adapter_restart(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -2249,11 +2253,12 @@ static void ipw_scan_check(void *data)
        }
 }
 
-static void ipw_bg_scan_check(void *data)
+static void ipw_bg_scan_check(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, scan_check.work);
        mutex_lock(&priv->mutex);
-       ipw_scan_check(data);
+       ipw_scan_check(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -3831,17 +3836,19 @@ static int ipw_disassociate(void *data)
        return 1;
 }
 
-static void ipw_bg_disassociate(void *data)
+static void ipw_bg_disassociate(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, disassociate);
        mutex_lock(&priv->mutex);
-       ipw_disassociate(data);
+       ipw_disassociate(priv);
        mutex_unlock(&priv->mutex);
 }
 
-static void ipw_system_config(void *data)
+static void ipw_system_config(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, system_config);
 
 #ifdef CONFIG_IPW2200_PROMISCUOUS
        if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) {
@@ -4208,11 +4215,12 @@ static void ipw_gather_stats(struct ipw_priv *priv)
                           IPW_STATS_INTERVAL);
 }
 
-static void ipw_bg_gather_stats(void *data)
+static void ipw_bg_gather_stats(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, gather_stats.work);
        mutex_lock(&priv->mutex);
-       ipw_gather_stats(data);
+       ipw_gather_stats(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -4268,8 +4276,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
                if (!(priv->status & STATUS_ROAMING)) {
                        priv->status |= STATUS_ROAMING;
                        if (!(priv->status & STATUS_SCANNING))
-                               queue_work(priv->workqueue,
-                                          &priv->request_scan);
+                               queue_delayed_work(priv->workqueue,
+                                                  &priv->request_scan, 0);
                }
                return;
        }
@@ -4607,8 +4615,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 #ifdef CONFIG_IPW2200_MONITOR
                        if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
                                priv->status |= STATUS_SCAN_FORCED;
-                               queue_work(priv->workqueue,
-                                          &priv->request_scan);
+                               queue_delayed_work(priv->workqueue,
+                                                  &priv->request_scan, 0);
                                break;
                        }
                        priv->status &= ~STATUS_SCAN_FORCED;
@@ -4631,8 +4639,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                                        /* Don't schedule if we aborted the scan */
                                        priv->status &= ~STATUS_ROAMING;
                        } else if (priv->status & STATUS_SCAN_PENDING)
-                               queue_work(priv->workqueue,
-                                          &priv->request_scan);
+                               queue_delayed_work(priv->workqueue,
+                                                  &priv->request_scan, 0);
                        else if (priv->config & CFG_BACKGROUND_SCAN
                                 && priv->status & STATUS_ASSOCIATED)
                                queue_delayed_work(priv->workqueue,
@@ -5055,11 +5063,12 @@ static void ipw_rx_queue_replenish(void *data)
        ipw_rx_queue_restock(priv);
 }
 
-static void ipw_bg_rx_queue_replenish(void *data)
+static void ipw_bg_rx_queue_replenish(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, rx_replenish);
        mutex_lock(&priv->mutex);
-       ipw_rx_queue_replenish(data);
+       ipw_rx_queue_replenish(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -5489,9 +5498,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        return 1;
 }
 
-static void ipw_merge_adhoc_network(void *data)
+static void ipw_merge_adhoc_network(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, merge_networks);
        struct ieee80211_network *network = NULL;
        struct ipw_network_match match = {
                .network = priv->assoc_network
@@ -5948,11 +5958,12 @@ static void ipw_adhoc_check(void *data)
                           priv->assoc_request.beacon_interval);
 }
 
-static void ipw_bg_adhoc_check(void *data)
+static void ipw_bg_adhoc_check(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, adhoc_check.work);
        mutex_lock(&priv->mutex);
-       ipw_adhoc_check(data);
+       ipw_adhoc_check(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -6299,19 +6310,26 @@ done:
        return err;
 }
 
-static int ipw_request_passive_scan(struct ipw_priv *priv) {
-       return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE);
+static void ipw_request_passive_scan(struct work_struct *work)
+{
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, request_passive_scan);
+       ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE);
 }
 
-static int ipw_request_scan(struct ipw_priv *priv) {
-       return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE);
+static void ipw_request_scan(struct work_struct *work)
+{
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, request_scan.work);
+       ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE);
 }
 
-static void ipw_bg_abort_scan(void *data)
+static void ipw_bg_abort_scan(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, abort_scan);
        mutex_lock(&priv->mutex);
-       ipw_abort_scan(data);
+       ipw_abort_scan(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -7084,9 +7102,10 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
 /*
 * background support to run QoS activate functionality
 */
-static void ipw_bg_qos_activate(void *data)
+static void ipw_bg_qos_activate(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, qos_activate);
 
        if (priv == NULL)
                return;
@@ -7394,11 +7413,12 @@ static void ipw_roam(void *data)
        priv->status &= ~STATUS_ROAMING;
 }
 
-static void ipw_bg_roam(void *data)
+static void ipw_bg_roam(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, roam);
        mutex_lock(&priv->mutex);
-       ipw_roam(data);
+       ipw_roam(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -7479,8 +7499,8 @@ static int ipw_associate(void *data)
                                                   &priv->request_scan,
                                                   SCAN_INTERVAL);
                        else
-                               queue_work(priv->workqueue,
-                                          &priv->request_scan);
+                               queue_delayed_work(priv->workqueue,
+                                                  &priv->request_scan, 0);
                }
 
                return 0;
@@ -7491,11 +7511,12 @@ static int ipw_associate(void *data)
        return 1;
 }
 
-static void ipw_bg_associate(void *data)
+static void ipw_bg_associate(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, associate);
        mutex_lock(&priv->mutex);
-       ipw_associate(data);
+       ipw_associate(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -7656,7 +7677,8 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
 
        /* Big bitfield of all the fields we provide in radiotap */
        ipw_rt->rt_hdr.it_present =
-           ((1 << IEEE80211_RADIOTAP_FLAGS) |
+           ((1 << IEEE80211_RADIOTAP_TSFT) |
+            (1 << IEEE80211_RADIOTAP_FLAGS) |
             (1 << IEEE80211_RADIOTAP_RATE) |
             (1 << IEEE80211_RADIOTAP_CHANNEL) |
             (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
@@ -7665,10 +7687,14 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
 
        /* Zero the flags, we'll add to them as we go */
        ipw_rt->rt_flags = 0;
-       ipw_rt->rt_tsf = 0ULL;
+       ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 |
+                              frame->parent_tsf[2] << 16 |
+                              frame->parent_tsf[1] << 8  |
+                              frame->parent_tsf[0]);
 
        /* Convert signal to DBM */
        ipw_rt->rt_dbmsignal = antsignal;
+       ipw_rt->rt_dbmnoise = frame->noise;
 
        /* Convert the channel data and set the flags */
        ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel));
@@ -7868,7 +7894,8 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
 
        /* Big bitfield of all the fields we provide in radiotap */
        ipw_rt->rt_hdr.it_present =
-           ((1 << IEEE80211_RADIOTAP_FLAGS) |
+           ((1 << IEEE80211_RADIOTAP_TSFT) |
+            (1 << IEEE80211_RADIOTAP_FLAGS) |
             (1 << IEEE80211_RADIOTAP_RATE) |
             (1 << IEEE80211_RADIOTAP_CHANNEL) |
             (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
@@ -7877,7 +7904,10 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
 
        /* Zero the flags, we'll add to them as we go */
        ipw_rt->rt_flags = 0;
-       ipw_rt->rt_tsf = 0ULL;
+       ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 |
+                              frame->parent_tsf[2] << 16 |
+                              frame->parent_tsf[1] << 8  |
+                              frame->parent_tsf[0]);
 
        /* Convert to DBM */
        ipw_rt->rt_dbmsignal = signal;
@@ -8276,7 +8306,7 @@ static void ipw_rx(struct ipw_priv *priv)
                                    ("Notification: subtype=%02X flags=%02X size=%d\n",
                                     pkt->u.notification.subtype,
                                     pkt->u.notification.flags,
-                                    pkt->u.notification.size);
+                                    le16_to_cpu(pkt->u.notification.size));
                                ipw_rx_notification(priv, &pkt->u.notification);
                                break;
                        }
@@ -9410,7 +9440,7 @@ static int ipw_wx_set_scan(struct net_device *dev,
 
        IPW_DEBUG_WX("Start scan\n");
 
-       queue_work(priv->workqueue, &priv->request_scan);
+       queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
 
        return 0;
 }
@@ -10547,11 +10577,12 @@ static void ipw_rf_kill(void *adapter)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void ipw_bg_rf_kill(void *data)
+static void ipw_bg_rf_kill(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, rf_kill.work);
        mutex_lock(&priv->mutex);
-       ipw_rf_kill(data);
+       ipw_rf_kill(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -10582,11 +10613,12 @@ static void ipw_link_up(struct ipw_priv *priv)
                queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
 }
 
-static void ipw_bg_link_up(void *data)
+static void ipw_bg_link_up(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, link_up);
        mutex_lock(&priv->mutex);
-       ipw_link_up(data);
+       ipw_link_up(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -10606,15 +10638,16 @@ static void ipw_link_down(struct ipw_priv *priv)
 
        if (!(priv->status & STATUS_EXIT_PENDING)) {
                /* Queue up another scan... */
-               queue_work(priv->workqueue, &priv->request_scan);
+               queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
        }
 }
 
-static void ipw_bg_link_down(void *data)
+static void ipw_bg_link_down(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, link_down);
        mutex_lock(&priv->mutex);
-       ipw_link_down(data);
+       ipw_link_down(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -10626,38 +10659,30 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv)
        init_waitqueue_head(&priv->wait_command_queue);
        init_waitqueue_head(&priv->wait_state);
 
-       INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv);
-       INIT_WORK(&priv->associate, ipw_bg_associate, priv);
-       INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv);
-       INIT_WORK(&priv->system_config, ipw_system_config, priv);
-       INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv);
-       INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv);
-       INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv);
-       INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv);
-       INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv);
-       INIT_WORK(&priv->request_scan,
-                 (void (*)(void *))ipw_request_scan, priv);
-       INIT_WORK(&priv->request_passive_scan,
-                 (void (*)(void *))ipw_request_passive_scan, priv);
-       INIT_WORK(&priv->gather_stats,
-                 (void (*)(void *))ipw_bg_gather_stats, priv);
-       INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv);
-       INIT_WORK(&priv->roam, ipw_bg_roam, priv);
-       INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv);
-       INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv);
-       INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv);
-       INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on,
-                 priv);
-       INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off,
-                 priv);
-       INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off,
-                 priv);
-       INIT_WORK(&priv->merge_networks,
-                 (void (*)(void *))ipw_merge_adhoc_network, priv);
+       INIT_DELAYED_WORK(&priv->adhoc_check, ipw_bg_adhoc_check);
+       INIT_WORK(&priv->associate, ipw_bg_associate);
+       INIT_WORK(&priv->disassociate, ipw_bg_disassociate);
+       INIT_WORK(&priv->system_config, ipw_system_config);
+       INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish);
+       INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart);
+       INIT_DELAYED_WORK(&priv->rf_kill, ipw_bg_rf_kill);
+       INIT_WORK(&priv->up, ipw_bg_up);
+       INIT_WORK(&priv->down, ipw_bg_down);
+       INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan);
+       INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan);
+       INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats);
+       INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan);
+       INIT_WORK(&priv->roam, ipw_bg_roam);
+       INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check);
+       INIT_WORK(&priv->link_up, ipw_bg_link_up);
+       INIT_WORK(&priv->link_down, ipw_bg_link_down);
+       INIT_DELAYED_WORK(&priv->led_link_on, ipw_bg_led_link_on);
+       INIT_DELAYED_WORK(&priv->led_link_off, ipw_bg_led_link_off);
+       INIT_DELAYED_WORK(&priv->led_act_off, ipw_bg_led_activity_off);
+       INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network);
 
 #ifdef CONFIG_IPW2200_QOS
-       INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate,
-                 priv);
+       INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate);
 #endif                         /* CONFIG_IPW2200_QOS */
 
        tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
@@ -11129,14 +11154,13 @@ static int ipw_up(struct ipw_priv *priv)
                return -EIO;
 
        if (cmdlog && !priv->cmdlog) {
-               priv->cmdlog = kmalloc(sizeof(*priv->cmdlog) * cmdlog,
+               priv->cmdlog = kcalloc(cmdlog, sizeof(*priv->cmdlog),
                                       GFP_KERNEL);
                if (priv->cmdlog == NULL) {
                        IPW_ERROR("Error allocating %d command log entries.\n",
                                  cmdlog);
                        return -ENOMEM;
                } else {
-                       memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog);
                        priv->cmdlog_len = cmdlog;
                }
        }
@@ -11190,7 +11214,8 @@ static int ipw_up(struct ipw_priv *priv)
 
                        /* If configure to try and auto-associate, kick
                         * off a scan. */
-                       queue_work(priv->workqueue, &priv->request_scan);
+                       queue_delayed_work(priv->workqueue,
+                                          &priv->request_scan, 0);
 
                        return 0;
                }
@@ -11211,11 +11236,12 @@ static int ipw_up(struct ipw_priv *priv)
        return -EIO;
 }
 
-static void ipw_bg_up(void *data)
+static void ipw_bg_up(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, up);
        mutex_lock(&priv->mutex);
-       ipw_up(data);
+       ipw_up(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -11282,11 +11308,12 @@ static void ipw_down(struct ipw_priv *priv)
        ipw_led_radio_off(priv);
 }
 
-static void ipw_bg_down(void *data)
+static void ipw_bg_down(struct work_struct *work)
 {
-       struct ipw_priv *priv = data;
+       struct ipw_priv *priv =
+               container_of(work, struct ipw_priv, down);
        mutex_lock(&priv->mutex);
-       ipw_down(data);
+       ipw_down(priv);
        mutex_unlock(&priv->mutex);
 }
 
index dad5eed..626a240 100644 (file)
@@ -1290,21 +1290,21 @@ struct ipw_priv {
 
        struct workqueue_struct *workqueue;
 
-       struct work_struct adhoc_check;
+       struct delayed_work adhoc_check;
        struct work_struct associate;
        struct work_struct disassociate;
        struct work_struct system_config;
        struct work_struct rx_replenish;
-       struct work_struct request_scan;
+       struct delayed_work request_scan;
        struct work_struct request_passive_scan;
        struct work_struct adapter_restart;
-       struct work_struct rf_kill;
+       struct delayed_work rf_kill;
        struct work_struct up;
        struct work_struct down;
-       struct work_struct gather_stats;
+       struct delayed_work gather_stats;
        struct work_struct abort_scan;
        struct work_struct roam;
-       struct work_struct scan_check;
+       struct delayed_work scan_check;
        struct work_struct link_up;
        struct work_struct link_down;
 
@@ -1319,9 +1319,9 @@ struct ipw_priv {
        u32 led_ofdm_on;
        u32 led_ofdm_off;
 
-       struct work_struct led_link_on;
-       struct work_struct led_link_off;
-       struct work_struct led_act_off;
+       struct delayed_work led_link_on;
+       struct delayed_work led_link_off;
+       struct delayed_work led_act_off;
        struct work_struct merge_networks;
 
        struct ipw_cmd_log *cmdlog;
index 336caba..936c888 100644 (file)
@@ -980,9 +980,11 @@ static void print_linkstatus(struct net_device *dev, u16 status)
 }
 
 /* Search scan results for requested BSSID, join it if found */
-static void orinoco_join_ap(struct net_device *dev)
+static void orinoco_join_ap(struct work_struct *work)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv =
+               container_of(work, struct orinoco_private, join_work);
+       struct net_device *dev = priv->ndev;
        struct hermes *hw = &priv->hw;
        int err;
        unsigned long flags;
@@ -1055,9 +1057,11 @@ static void orinoco_join_ap(struct net_device *dev)
 }
 
 /* Send new BSSID to userspace */
-static void orinoco_send_wevents(struct net_device *dev)
+static void orinoco_send_wevents(struct work_struct *work)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv =
+               container_of(work, struct orinoco_private, wevent_work);
+       struct net_device *dev = priv->ndev;
        struct hermes *hw = &priv->hw;
        union iwreq_data wrqu;
        int err;
@@ -1864,9 +1868,11 @@ __orinoco_set_multicast_list(struct net_device *dev)
 
 /* This must be called from user context, without locks held - use
  * schedule_work() */
-static void orinoco_reset(struct net_device *dev)
+static void orinoco_reset(struct work_struct *work)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv =
+               container_of(work, struct orinoco_private, reset_work);
+       struct net_device *dev = priv->ndev;
        struct hermes *hw = &priv->hw;
        int err;
        unsigned long flags;
@@ -2434,9 +2440,9 @@ struct net_device *alloc_orinocodev(int sizeof_card,
        priv->hw_unavailable = 1; /* orinoco_init() must clear this
                                   * before anything else touches the
                                   * hardware */
-       INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
-       INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev);
-       INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev);
+       INIT_WORK(&priv->reset_work, orinoco_reset);
+       INIT_WORK(&priv->join_work, orinoco_join_ap);
+       INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
 
        netif_carrier_off(dev);
        priv->last_linkstatus = 0xffff;
@@ -3608,7 +3614,7 @@ static int orinoco_ioctl_reset(struct net_device *dev,
                printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
 
                /* Firmware reset */
-               orinoco_reset(dev);
+               orinoco_reset(&priv->reset_work);
        } else {
                printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
 
@@ -4154,7 +4160,7 @@ static int orinoco_ioctl_commit(struct net_device *dev,
                return 0;
 
        if (priv->broken_disableport) {
-               orinoco_reset(dev);
+               orinoco_reset(&priv->reset_work);
                return 0;
        }
 
index 4a20e45..96606ed 100644 (file)
@@ -157,8 +157,9 @@ prism54_mib_init(islpci_private *priv)
  * schedule_work(), thus we can as well use sleeping semaphore
  * locking */
 void
-prism54_update_stats(islpci_private *priv)
+prism54_update_stats(struct work_struct *work)
 {
+       islpci_private *priv = container_of(work, islpci_private, stats_work);
        char *data;
        int j;
        struct obj_bss bss, *bss2;
@@ -2140,11 +2141,9 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
                                         struct islpci_bss_wpa_ie, list);
                        list_del(&bss->list);
                } else {
-                       bss = kmalloc(sizeof (*bss), GFP_ATOMIC);
-                       if (bss != NULL) {
+                       bss = kzalloc(sizeof (*bss), GFP_ATOMIC);
+                       if (bss != NULL)
                                priv->num_bss_wpa++;
-                               memset(bss, 0, sizeof (*bss));
-                       }
                }
                if (bss != NULL) {
                        memcpy(bss->bssid, bssid, ETH_ALEN);
@@ -2493,9 +2492,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
  * interrupt context, no locks held.
  */
 void
-prism54_process_trap(void *data)
+prism54_process_trap(struct work_struct *work)
 {
-       struct islpci_mgmtframe *frame = data;
+       struct islpci_mgmtframe *frame =
+               container_of(work, struct islpci_mgmtframe, ws);
        struct net_device *ndev = frame->ndev;
        enum oid_num_t n = mgt_oidtonum(frame->header->oid);
 
@@ -2684,11 +2684,10 @@ prism2_ioctl_set_generic_element(struct net_device *ndev,
                return -EINVAL;
 
        alen = sizeof(*attach) + len;
-       attach = kmalloc(alen, GFP_KERNEL);
+       attach = kzalloc(alen, GFP_KERNEL);
        if (attach == NULL)
                return -ENOMEM;
 
-       memset(attach, 0, alen);
 #define WLAN_FC_TYPE_MGMT 0
 #define WLAN_FC_STYPE_ASSOC_REQ 0
 #define WLAN_FC_STYPE_REASSOC_REQ 2
index e8183d3..bcfbfb9 100644 (file)
 void prism54_mib_init(islpci_private *);
 
 struct iw_statistics *prism54_get_wireless_stats(struct net_device *);
-void prism54_update_stats(islpci_private *);
+void prism54_update_stats(struct work_struct *);
 
 void prism54_acl_init(struct islpci_acl *);
 void prism54_acl_clean(struct islpci_acl *);
 
-void prism54_process_trap(void *);
+void prism54_process_trap(struct work_struct *);
 
 void prism54_wpa_bss_ie_init(islpci_private *priv);
 void prism54_wpa_bss_ie_clean(islpci_private *priv);
index 1e0603c..f057fd9 100644 (file)
@@ -860,11 +860,10 @@ islpci_setup(struct pci_dev *pdev)
        priv->state_off = 1;
 
        /* initialize workqueue's */
-       INIT_WORK(&priv->stats_work,
-                 (void (*)(void *)) prism54_update_stats, priv);
+       INIT_WORK(&priv->stats_work, prism54_update_stats);
        priv->stats_timestamp = 0;
 
-       INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv);
+       INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake);
        priv->reset_task_pending = 0;
 
        /* allocate various memory areas */
index 676d838..b112291 100644 (file)
@@ -480,9 +480,9 @@ islpci_eth_receive(islpci_private *priv)
 }
 
 void
-islpci_do_reset_and_wake(void *data)
+islpci_do_reset_and_wake(struct work_struct *work)
 {
-       islpci_private *priv = data;
+       islpci_private *priv = container_of(work, islpci_private, reset_task);
 
        islpci_reset(priv, 1);
        priv->reset_task_pending = 0;
index 2678945..5bf820d 100644 (file)
@@ -67,6 +67,6 @@ void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *);
 int islpci_eth_transmit(struct sk_buff *, struct net_device *);
 int islpci_eth_receive(islpci_private *);
 void islpci_eth_tx_timeout(struct net_device *);
-void islpci_do_reset_and_wake(void *data);
+void islpci_do_reset_and_wake(struct work_struct *);
 
 #endif                         /* _ISL_GEN_H */
index 036a875..2246f79 100644 (file)
@@ -386,7 +386,7 @@ islpci_mgt_receive(struct net_device *ndev)
 
                        /* Create work to handle trap out of interrupt
                         * context. */
-                       INIT_WORK(&frame->ws, prism54_process_trap, frame);
+                       INIT_WORK(&frame->ws, prism54_process_trap);
                        schedule_work(&frame->ws);
 
                } else {
index fbc52b6..e6cf9df 100644 (file)
@@ -235,12 +235,10 @@ mgt_init(islpci_private *priv)
 {
        int i;
 
-       priv->mib = kmalloc(OID_NUM_LAST * sizeof (void *), GFP_KERNEL);
+       priv->mib = kcalloc(OID_NUM_LAST, sizeof (void *), GFP_KERNEL);
        if (!priv->mib)
                return -ENOMEM;
 
-       memset(priv->mib, 0, OID_NUM_LAST * sizeof (void *));
-
        /* Alloc the cache */
        for (i = 0; i < OID_NUM_LAST; i++) {
                if (isl_oid[i].flags & OID_FLAG_CACHED) {
index 337c692..ce3a8ba 100644 (file)
@@ -798,7 +798,7 @@ static unsigned int get_baud(struct tty_struct *tty)
  */
 static void set_baud(struct tty_struct *tty, unsigned int baudcode)
 {
-       struct termios old_termios = *(tty->termios);
+       struct ktermios old_termios = *(tty->termios);
        tty->termios->c_cflag &= ~CBAUD;        /* Clear the old baud setting */
        tty->termios->c_cflag |= baudcode;      /* Set the new baud setting */
        tty->driver->set_termios(tty, &old_termios);
index 8be99eb..77e11dd 100644 (file)
@@ -1673,3 +1673,16 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip,
 
        return 0;
 }
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+                              struct zd_mc_hash *hash)
+{
+       struct zd_ioreq32 ioreqs[] = {
+               { CR_GROUP_HASH_P1, hash->low },
+               { CR_GROUP_HASH_P2, hash->high },
+       };
+
+       dev_dbg_f(zd_chip_dev(chip), "hash l 0x%08x h 0x%08x\n",
+               ioreqs[0].value, ioreqs[1].value);
+       return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
index ca892b9..a4e3cee 100644 (file)
 #define CR_BSSID_P1                    CTL_REG(0x0618)
 #define CR_BSSID_P2                    CTL_REG(0x061C)
 #define CR_BCN_PLCP_CFG                        CTL_REG(0x0620)
+
+/* Group hash table for filtering incoming packets.
+ *
+ * The group hash table is 64 bit large and split over two parts. The first
+ * part is the lower part. The upper 6 bits of the last byte of the target
+ * address are used as index. Packets are received if the hash table bit is
+ * set. This is used for multicast handling, but for broadcasts (address
+ * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set.
+ */
 #define CR_GROUP_HASH_P1               CTL_REG(0x0624)
 #define CR_GROUP_HASH_P2               CTL_REG(0x0628)
-#define CR_RX_TIMEOUT                  CTL_REG(0x062C)
 
+#define CR_RX_TIMEOUT                  CTL_REG(0x062C)
 /* Basic rates supported by the BSS. When producing ACK or CTS messages, the
  * device will use a rate in this table that is less than or equal to the rate
  * of the incoming frame which prompted the response */
@@ -864,4 +873,36 @@ u8 zd_rx_strength_percent(u8 rssi);
 
 u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
 
+struct zd_mc_hash {
+       u32 low;
+       u32 high;
+};
+
+static inline void zd_mc_clear(struct zd_mc_hash *hash)
+{
+       hash->low = 0;
+       /* The interfaces must always received broadcasts.
+        * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63.
+        */
+       hash->high = 0x80000000;
+}
+
+static inline void zd_mc_add_all(struct zd_mc_hash *hash)
+{
+       hash->low = hash->high = 0xffffffff;
+}
+
+static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr)
+{
+       unsigned int i = addr[5] >> 2;
+       if (i < 32) {
+               hash->low |= 1 << i;
+       } else {
+               hash->high |= 1 << (i-32);
+       }
+}
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+                              struct zd_mc_hash *hash);
+
 #endif /* _ZD_CHIP_H */
index 2696f95..00ca704 100644 (file)
 
 static void ieee_init(struct ieee80211_device *ieee);
 static void softmac_init(struct ieee80211softmac_device *sm);
-static void set_rts_cts_work(void *d);
-static void set_basic_rates_work(void *d);
+static void set_rts_cts_work(struct work_struct *work);
+static void set_basic_rates_work(struct work_struct *work);
 
 static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
 
+static void set_multicast_hash_handler(struct work_struct *work);
+
 int zd_mac_init(struct zd_mac *mac,
                struct net_device *netdev,
                struct usb_interface *intf)
@@ -48,13 +50,14 @@ int zd_mac_init(struct zd_mac *mac,
        memset(mac, 0, sizeof(*mac));
        spin_lock_init(&mac->lock);
        mac->netdev = netdev;
-       INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac);
-       INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac);
+       INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
+       INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work);
 
        ieee_init(ieee);
        softmac_init(ieee80211_priv(netdev));
        zd_chip_init(&mac->chip, netdev, intf);
        housekeeping_init(mac);
+       INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
        return 0;
 }
 
@@ -136,6 +139,7 @@ out:
 
 void zd_mac_clear(struct zd_mac *mac)
 {
+       flush_workqueue(zd_workqueue);
        zd_chip_clear(&mac->chip);
        ZD_ASSERT(!spin_is_locked(&mac->lock));
        ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -256,6 +260,43 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p)
        return 0;
 }
 
+static void set_multicast_hash_handler(struct work_struct *work)
+{
+       struct zd_mac *mac = container_of(work, struct zd_mac,
+                                         set_multicast_hash_work);
+       struct zd_mc_hash hash;
+
+       spin_lock_irq(&mac->lock);
+       hash = mac->multicast_hash;
+       spin_unlock_irq(&mac->lock);
+
+       zd_chip_set_multicast_hash(&mac->chip, &hash);
+}
+
+void zd_mac_set_multicast_list(struct net_device *dev)
+{
+       struct zd_mc_hash hash;
+       struct zd_mac *mac = zd_netdev_mac(dev);
+       struct dev_mc_list *mc;
+       unsigned long flags;
+
+       if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
+               zd_mc_add_all(&hash);
+       } else {
+               zd_mc_clear(&hash);
+               for (mc = dev->mc_list; mc; mc = mc->next) {
+                       dev_dbg_f(zd_mac_dev(mac), "mc addr " MAC_FMT "\n",
+                                 MAC_ARG(mc->dmi_addr));
+                       zd_mc_add_addr(&hash, mc->dmi_addr);
+               }
+       }
+
+       spin_lock_irqsave(&mac->lock, flags);
+       mac->multicast_hash = hash;
+       spin_unlock_irqrestore(&mac->lock, flags);
+       queue_work(zd_workqueue, &mac->set_multicast_hash_work);
+}
+
 int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain)
 {
        int r;
@@ -366,9 +407,10 @@ static void try_enable_tx(struct zd_mac *mac)
        spin_unlock_irqrestore(&mac->lock, flags);
 }
 
-static void set_rts_cts_work(void *d)
+static void set_rts_cts_work(struct work_struct *work)
 {
-       struct zd_mac *mac = d;
+       struct zd_mac *mac =
+               container_of(work, struct zd_mac, set_rts_cts_work.work);
        unsigned long flags;
        u8 rts_rate;
        unsigned int short_preamble;
@@ -387,9 +429,10 @@ static void set_rts_cts_work(void *d)
        try_enable_tx(mac);
 }
 
-static void set_basic_rates_work(void *d)
+static void set_basic_rates_work(struct work_struct *work)
 {
-       struct zd_mac *mac = d;
+       struct zd_mac *mac =
+               container_of(work, struct zd_mac, set_basic_rates_work.work);
        unsigned long flags;
        u16 basic_rates;
 
@@ -467,12 +510,13 @@ static void bssinfo_change(struct net_device *netdev, u32 changes)
        if (need_set_rts_cts && !mac->updating_rts_rate) {
                mac->updating_rts_rate = 1;
                netif_stop_queue(mac->netdev);
-               queue_work(zd_workqueue, &mac->set_rts_cts_work);
+               queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0);
        }
        if (need_set_rates && !mac->updating_basic_rates) {
                mac->updating_basic_rates = 1;
                netif_stop_queue(mac->netdev);
-               queue_work(zd_workqueue, &mac->set_basic_rates_work);
+               queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work,
+                                  0);
        }
        spin_unlock_irqrestore(&mac->lock, flags);
 }
@@ -615,6 +659,9 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range)
        range->we_version_compiled = WIRELESS_EXT;
        range->we_version_source = 20;
 
+       range->enc_capa = IW_ENC_CAPA_WPA |  IW_ENC_CAPA_WPA2 |
+                         IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
        ZD_ASSERT(!irqs_disabled());
        spin_lock_irq(&mac->lock);
        regdomain = mac->regdomain;
@@ -927,7 +974,8 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
        }
 
        return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
-              is_multicast_ether_addr(hdr->addr1) ||
+              (is_multicast_ether_addr(hdr->addr1) &&
+               memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) ||
               (netdev->flags & IFF_PROMISC);
 }
 
@@ -1059,10 +1107,8 @@ int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
        memcpy(skb_put(skb, length), buffer, length);
 
        r = ieee80211_rx(ieee, skb, &stats);
-       if (!r) {
-               ZD_ASSERT(in_irq());
-               dev_kfree_skb_irq(skb);
-       }
+       if (!r)
+               dev_kfree_skb_any(skb);
        return 0;
 }
 
@@ -1182,9 +1228,10 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)
 
 #define LINK_LED_WORK_DELAY HZ
 
-static void link_led_handler(void *p)
+static void link_led_handler(struct work_struct *work)
 {
-       struct zd_mac *mac = p;
+       struct zd_mac *mac =
+               container_of(work, struct zd_mac, housekeeping.link_led_work.work);
        struct zd_chip *chip = &mac->chip;
        struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev);
        int is_associated;
@@ -1205,7 +1252,7 @@ static void link_led_handler(void *p)
 
 static void housekeeping_init(struct zd_mac *mac)
 {
-       INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac);
+       INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
 }
 
 static void housekeeping_enable(struct zd_mac *mac)
index 5dcfb25..f0cf05d 100644 (file)
@@ -119,7 +119,7 @@ struct rx_status {
 #define ZD_RX_ERROR                    0x80
 
 struct housekeeping {
-       struct work_struct link_led_work;
+       struct delayed_work link_led_work;
 };
 
 #define ZD_MAC_STATS_BUFFER_SIZE 16
@@ -133,8 +133,10 @@ struct zd_mac {
        struct iw_statistics iw_stats;
 
        struct housekeeping housekeeping;
-       struct work_struct set_rts_cts_work;
-       struct work_struct set_basic_rates_work;
+       struct work_struct set_multicast_hash_work;
+       struct zd_mc_hash multicast_hash;
+       struct delayed_work set_rts_cts_work;
+       struct delayed_work set_basic_rates_work;
 
        unsigned int stats_count;
        u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
@@ -189,6 +191,7 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
 int zd_mac_open(struct net_device *netdev);
 int zd_mac_stop(struct net_device *netdev);
 int zd_mac_set_mac_address(struct net_device *dev, void *p);
+void zd_mac_set_multicast_list(struct net_device *netdev);
 
 int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
 
index 60f1b0f..8bda48d 100644 (file)
@@ -242,7 +242,7 @@ struct net_device *zd_netdev_alloc(struct usb_interface *intf)
        netdev->open = zd_mac_open;
        netdev->stop = zd_mac_stop;
        /* netdev->get_stats = */
-       /* netdev->set_multicast_list = */
+       netdev->set_multicast_list = zd_mac_set_multicast_list;
        netdev->set_mac_address = zd_mac_set_mac_address;
        netdev->wireless_handlers = &iw_handler_def;
        /* netdev->ethtool_ops = */
index 43e521e..78c2e6e 100644 (file)
@@ -220,8 +220,8 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm)
                        continue;
                if (!(vma->vm_flags & VM_EXECUTABLE))
                        continue;
-               cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                       vma->vm_file->f_vfsmnt);
+               cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
+                       vma->vm_file->f_path.mnt);
                break;
        }
 
@@ -246,8 +246,8 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
                        continue;
 
                if (vma->vm_file) {
-                       cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                               vma->vm_file->f_vfsmnt);
+                       cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
+                               vma->vm_file->f_path.mnt);
                        *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
                                vma->vm_start;
                } else {
index fc4bc9b..a83c3db 100644 (file)
@@ -29,7 +29,7 @@
 
 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
 
-static void wq_sync_buffer(void *);
+static void wq_sync_buffer(struct work_struct *work);
 
 #define DEFAULT_TIMER_EXPIRE (HZ / 10)
 static int work_enabled;
@@ -65,7 +65,7 @@ int alloc_cpu_buffers(void)
                b->sample_received = 0;
                b->sample_lost_overflow = 0;
                b->cpu = i;
-               INIT_WORK(&b->work, wq_sync_buffer, b);
+               INIT_DELAYED_WORK(&b->work, wq_sync_buffer);
        }
        return 0;
 
@@ -282,9 +282,10 @@ void oprofile_add_trace(unsigned long pc)
  * By using schedule_delayed_work_on and then schedule_delayed_work
  * we guarantee this will stay on the correct cpu
  */
-static void wq_sync_buffer(void * data)
+static void wq_sync_buffer(struct work_struct *work)
 {
-       struct oprofile_cpu_buffer * b = data;
+       struct oprofile_cpu_buffer * b =
+               container_of(work, struct oprofile_cpu_buffer, work.work);
        if (b->cpu != smp_processor_id()) {
                printk("WQ on CPU%d, prefer CPU%d\n",
                       smp_processor_id(), b->cpu);
index 09abb80..49900d9 100644 (file)
@@ -43,7 +43,7 @@ struct oprofile_cpu_buffer {
        unsigned long sample_lost_overflow;
        unsigned long backtrace_aborted;
        int cpu;
-       struct work_struct work;
+       struct delayed_work work;
 } ____cacheline_aligned;
 
 extern struct oprofile_cpu_buffer cpu_buffer[];
index c7fa28a..36c6a1b 100644 (file)
@@ -82,9 +82,6 @@ config PARPORT_PC_PCMCIA
          Say Y here if you need PCMCIA support for your PC-style parallel
          ports. If unsure, say N.
 
-config PARPORT_NOT_PC
-       bool
-
 config PARPORT_IP32
        tristate "SGI IP32 builtin port (EXPERIMENTAL)"
        depends on SGI_IP32 && PARPORT && EXPERIMENTAL
@@ -158,5 +155,8 @@ config PARPORT_1284
          transfer modes. Also say Y if you want device ID information to
          appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
 
+config PARPORT_NOT_PC
+       bool
+
 endmenu
 
index 39c9664..b61c17b 100644 (file)
@@ -1975,7 +1975,7 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}
 /* --- IRQ detection -------------------------------------- */
 
 /* Only if supports ECP mode */
-static int __devinit programmable_irq_support(struct parport *pb)
+static int programmable_irq_support(struct parport *pb)
 {
        int irq, intrLine;
        unsigned char oecr = inb (ECONTROL (pb));
@@ -1992,7 +1992,7 @@ static int __devinit programmable_irq_support(struct parport *pb)
        return irq;
 }
 
-static int __devinit irq_probe_ECP(struct parport *pb)
+static int irq_probe_ECP(struct parport *pb)
 {
        int i;
        unsigned long irqs;
@@ -2020,7 +2020,7 @@ static int __devinit irq_probe_ECP(struct parport *pb)
  * This detection seems that only works in National Semiconductors
  * This doesn't work in SMC, LGS, and Winbond 
  */
-static int __devinit irq_probe_EPP(struct parport *pb)
+static int irq_probe_EPP(struct parport *pb)
 {
 #ifndef ADVANCED_DETECT
        return PARPORT_IRQ_NONE;
@@ -2059,7 +2059,7 @@ static int __devinit irq_probe_EPP(struct parport *pb)
 #endif /* Advanced detection */
 }
 
-static int __devinit irq_probe_SPP(struct parport *pb)
+static int irq_probe_SPP(struct parport *pb)
 {
        /* Don't even try to do this. */
        return PARPORT_IRQ_NONE;
@@ -2747,6 +2747,7 @@ enum parport_pc_pci_cards {
        titan_1284p2,
        avlab_1p,
        avlab_2p,
+       oxsemi_952,
        oxsemi_954,
        oxsemi_840,
        aks_0100,
@@ -2822,6 +2823,7 @@ static struct parport_pc_pci {
        /* avlab_2p             */      { 2, { { 0, 1}, { 2, 3 },} },
        /* The Oxford Semi cards are unusual: 954 doesn't support ECP,
         * and 840 locks up if you write 1 to bit 2! */
+       /* oxsemi_952 */                { 1, { { 0, 1 }, } },
        /* oxsemi_954 */                { 1, { { 0, -1 }, } },
        /* oxsemi_840 */                { 1, { { 0, -1 }, } },
        /* aks_0100 */                  { 1, { { 0, -1 }, } },
@@ -2895,6 +2897,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
        /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
        { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */
        { 0x14db, 0x2121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2p},
+       { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952PP,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_952 },
        { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954PP,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_954 },
        { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_12PCI840,
index 6e780db..adce420 100644 (file)
@@ -76,7 +76,8 @@ config HOTPLUG_PCI_IBM
 
 config HOTPLUG_PCI_ACPI
        tristate "ACPI PCI Hotplug driver"
-       depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI)
+       depends on HOTPLUG_PCI
+       depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
        help
          Say Y here if you have a system that supports PCI Hotplug using
          ACPI.
index ea2087c..5075769 100644 (file)
@@ -70,7 +70,7 @@ struct slot {
        struct hotplug_slot *hotplug_slot;
        struct list_head        slot_list;
        char name[SLOT_NAME_SIZE];
-       struct work_struct work;        /* work for button event */
+       struct delayed_work work;       /* work for button event */
        struct mutex lock;
 };
 
@@ -187,7 +187,7 @@ extern int  shpchp_configure_device(struct slot *p_slot);
 extern int     shpchp_unconfigure_device(struct slot *p_slot);
 extern void    shpchp_remove_ctrl_files(struct controller *ctrl);
 extern void    cleanup_slots(struct controller *ctrl);
-extern void    queue_pushbutton_work(void *data);
+extern void    queue_pushbutton_work(struct work_struct *work);
 
 
 #ifdef CONFIG_ACPI
index 235c18a..4eac85b 100644 (file)
@@ -159,7 +159,7 @@ static int init_slots(struct controller *ctrl)
                        goto error_info;
 
                slot->number = sun;
-               INIT_WORK(&slot->work, queue_pushbutton_work, slot);
+               INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
 
                /* register this slot with the hotplug pci core */
                hotplug_slot->private = slot;
index c39901d..158ac78 100644 (file)
@@ -36,7 +36,7 @@
 #include "../pci.h"
 #include "shpchp.h"
 
-static void interrupt_event_handler(void *data);
+static void interrupt_event_handler(struct work_struct *work);
 static int shpchp_enable_slot(struct slot *p_slot);
 static int shpchp_disable_slot(struct slot *p_slot);
 
@@ -50,7 +50,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 
        info->event_type = event_type;
        info->p_slot = p_slot;
-       INIT_WORK(&info->work, interrupt_event_handler, info);
+       INIT_WORK(&info->work, interrupt_event_handler);
 
        schedule_work(&info->work);
 
@@ -408,9 +408,10 @@ struct pushbutton_work_info {
  * Handles all pending events and exits.
  *
  */
-static void shpchp_pushbutton_thread(void *data)
+static void shpchp_pushbutton_thread(struct work_struct *work)
 {
-       struct pushbutton_work_info *info = data;
+       struct pushbutton_work_info *info =
+               container_of(work, struct pushbutton_work_info, work);
        struct slot *p_slot = info->p_slot;
 
        mutex_lock(&p_slot->lock);
@@ -436,9 +437,9 @@ static void shpchp_pushbutton_thread(void *data)
        kfree(info);
 }
 
-void queue_pushbutton_work(void *data)
+void queue_pushbutton_work(struct work_struct *work)
 {
-       struct slot *p_slot = data;
+       struct slot *p_slot = container_of(work, struct slot, work.work);
        struct pushbutton_work_info *info;
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -447,7 +448,7 @@ void queue_pushbutton_work(void *data)
                return;
        }
        info->p_slot = p_slot;
-       INIT_WORK(&info->work, shpchp_pushbutton_thread, info);
+       INIT_WORK(&info->work, shpchp_pushbutton_thread);
 
        mutex_lock(&p_slot->lock);
        switch (p_slot->state) {
@@ -541,9 +542,9 @@ static void handle_button_press_event(struct slot *p_slot)
        }
 }
 
-static void interrupt_event_handler(void *data)
+static void interrupt_event_handler(struct work_struct *work)
 {
-       struct event_info *info = data;
+       struct event_info *info = container_of(work, struct event_info, work);
        struct slot *p_slot = info->p_slot;
 
        mutex_lock(&p_slot->lock);
index 9fc9a34..ed3f7e1 100644 (file)
@@ -26,7 +26,7 @@
 
 static DEFINE_SPINLOCK(msi_lock);
 static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
-static kmem_cache_t* msi_cachep;
+static struct kmem_cache* msi_cachep;
 
 static int pci_msi_enable = 1;
 
@@ -255,10 +255,8 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
                pci_write_config_word(dev, msi_control_reg(pos), control);
                dev->msix_enabled = 1;
        }
-       if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
-               /* PCI Express Endpoint device detected */
-               pci_intx(dev, 0);  /* disable intx */
-       }
+
+       pci_intx(dev, 0);  /* disable intx */
 }
 
 void disable_msi_mode(struct pci_dev *dev, int pos, int type)
@@ -276,10 +274,8 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type)
                pci_write_config_word(dev, msi_control_reg(pos), control);
                dev->msix_enabled = 0;
        }
-       if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
-               /* PCI Express Endpoint device detected */
-               pci_intx(dev, 1);  /* enable intx */
-       }
+
+       pci_intx(dev, 1);  /* enable intx */
 }
 
 static int msi_lookup_irq(struct pci_dev *dev, int type)
index 04c43ef..55866b6 100644 (file)
@@ -160,7 +160,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
        rpc->e_lock = SPIN_LOCK_UNLOCKED;
 
        rpc->rpd = dev;
-       INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev);
+       INIT_WORK(&rpc->dpc_handler, aer_isr);
        rpc->prod_idx = rpc->cons_idx = 0;
        mutex_init(&rpc->rpc_mutex);
        init_waitqueue_head(&rpc->wait_release);
index daf0cad..3c0a58f 100644 (file)
@@ -118,7 +118,7 @@ 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_isr(struct work_struct *work);
 extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
 extern int aer_osc_setup(struct pci_dev *dev);
 
index 1c7e660..08e1303 100644 (file)
@@ -690,14 +690,14 @@ static void aer_isr_one_error(struct pcie_device *p_device,
 
 /**
  * aer_isr - consume errors detected by root port
- * @context: pointer to a private data of pcie device
+ * @work: definition of this work item
  *
  * Invoked, as DPC, when root port records new detected error
  **/
-void aer_isr(void *context)
+void aer_isr(struct work_struct *work)
 {
-       struct pcie_device *p_device = (struct pcie_device *) context;
-       struct aer_rpc *rpc = get_service_data(p_device);
+       struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
+       struct pcie_device *p_device = rpc->rpd;
        struct aer_err_source *e_src;
 
        mutex_lock(&rpc->rpc_mutex);
index 0eeac60..6a3c1e7 100644 (file)
@@ -873,6 +873,7 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.release = pci_release_dev;
        pci_dev_get(dev);
 
+       set_dev_node(&dev->dev, pcibus_to_node(bus));
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.coherent_dma_mask = 0xffffffffull;
 
index 99cf333..4a6760a 100644 (file)
@@ -23,7 +23,7 @@ static loff_t
 proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
 {
        loff_t new = -1;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        mutex_lock(&inode->i_mutex);
        switch (whence) {
@@ -48,7 +48,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
 static ssize_t
 proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       const struct inode *ino = file->f_dentry->d_inode;
+       const struct inode *ino = file->f_path.dentry->d_inode;
        const struct proc_dir_entry *dp = PDE(ino);
        struct pci_dev *dev = dp->data;
        unsigned int pos = *ppos;
@@ -130,7 +130,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 static ssize_t
 proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       const struct inode *ino = file->f_dentry->d_inode;
+       const struct inode *ino = file->f_path.dentry->d_inode;
        const struct proc_dir_entry *dp = PDE(ino);
        struct pci_dev *dev = dp->data;
        int pos = *ppos;
@@ -245,7 +245,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
 #ifdef HAVE_PCI_MMAP
 static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        const struct proc_dir_entry *dp = PDE(inode);
        struct pci_dev *dev = dp->data;
        struct pci_filp_private *fpriv = file->private_data;
index b674630..52d4a38 100644 (file)
@@ -23,9 +23,9 @@
 #include <asm/io.h>
 #include <asm/sizes.h>
 
-#include <asm/arch/at91rm9200.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
 
 
 /*
index f9cd831..606a467 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
index 45df12e..7355eb4 100644 (file)
@@ -675,9 +675,10 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
 }
 
 
-static void pcmcia_delayed_add_device(void *data)
+static void pcmcia_delayed_add_device(struct work_struct *work)
 {
-       struct pcmcia_socket *s = data;
+       struct pcmcia_socket *s =
+               container_of(work, struct pcmcia_socket, device_add);
        ds_dbg(1, "adding additional device to %d\n", s->sock);
        pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
        s->pcmcia_state.device_add_pending = 0;
@@ -1349,7 +1350,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
        init_waitqueue_head(&socket->queue);
 #endif
        INIT_LIST_HEAD(&socket->devices_list);
-       INIT_WORK(&socket->device_add, pcmcia_delayed_add_device, socket);
+       INIT_WORK(&socket->device_add, pcmcia_delayed_add_device);
        memset(&socket->pcmcia_state, 0, sizeof(u8));
        socket->device_count = 0;
 
index d077870..327372b 100644 (file)
@@ -486,7 +486,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,
     user_info_t *user;
     int ret;
 
-    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));
+    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 
     if (count < 4)
        return -EINVAL;
@@ -511,7 +511,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,
 static ssize_t ds_write(struct file *file, const char __user *buf,
                        size_t count, loff_t *ppos)
 {
-    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
+    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 
     if (count != 4)
        return -EINVAL;
@@ -529,7 +529,7 @@ static u_int ds_poll(struct file *file, poll_table *wait)
     struct pcmcia_socket *s;
     user_info_t *user;
 
-    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));
+    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 
     user = file->private_data;
     if (CHECK_USER(user))
index 227600c..91c047a 100644 (file)
@@ -164,9 +164,17 @@ static DEVICE_ATTR(card_id,S_IRUGO,pnp_show_card_ids,NULL);
 
 static int pnp_interface_attach_card(struct pnp_card *card)
 {
-       device_create_file(&card->dev,&dev_attr_name);
-       device_create_file(&card->dev,&dev_attr_card_id);
+       int rc = device_create_file(&card->dev,&dev_attr_name);
+       if (rc) return rc;
+
+       rc = device_create_file(&card->dev,&dev_attr_card_id);
+       if (rc) goto err_name;
+
        return 0;
+
+err_name:
+       device_remove_file(&card->dev,&dev_attr_name);
+       return rc;
 }
 
 /**
@@ -306,16 +314,20 @@ found:
        down_write(&dev->dev.bus->subsys.rwsem);
        dev->card_link = clink;
        dev->dev.driver = &drv->link.driver;
-       if (pnp_bus_type.probe(&dev->dev)) {
-               dev->dev.driver = NULL;
-               dev->card_link = NULL;
-               up_write(&dev->dev.bus->subsys.rwsem);
-               return NULL;
-       }
-       device_bind_driver(&dev->dev);
+       if (pnp_bus_type.probe(&dev->dev))
+               goto err_out;
+       if (device_bind_driver(&dev->dev))
+               goto err_out;
+
        up_write(&dev->dev.bus->subsys.rwsem);
 
        return dev;
+
+err_out:
+       dev->dev.driver = NULL;
+       dev->card_link = NULL;
+       up_write(&dev->dev.bus->subsys.rwsem);
+       return NULL;
 }
 
 /**
index 9d8b415..ac9fcd4 100644 (file)
@@ -461,8 +461,19 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL);
 
 int pnp_interface_attach_device(struct pnp_dev *dev)
 {
-       device_create_file(&dev->dev,&dev_attr_options);
-       device_create_file(&dev->dev,&dev_attr_resources);
-       device_create_file(&dev->dev,&dev_attr_id);
+       int rc = device_create_file(&dev->dev,&dev_attr_options);
+       if (rc) goto err;
+       rc = device_create_file(&dev->dev,&dev_attr_resources);
+       if (rc) goto err_opt;
+       rc = device_create_file(&dev->dev,&dev_attr_id);
+       if (rc) goto err_res;
+
        return 0;
+
+err_res:
+       device_remove_file(&dev->dev,&dev_attr_resources);
+err_opt:
+       device_remove_file(&dev->dev,&dev_attr_options);
+err:
+       return rc;
 }
index 958c11b..d21f3c1 100644 (file)
@@ -56,7 +56,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       struct inode *ino = file->f_dentry->d_inode;
+       struct inode *ino = file->f_path.dentry->d_inode;
        struct proc_dir_entry *dp = PDE(ino);
        struct pnp_dev *dev = dp->data;
        int pos = *ppos;
index 81a6c83..33adeba 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/dmi.h>
 #include <linux/delay.h>
 #include <linux/acpi.h>
+#include <linux/freezer.h>
 
 #include <asm/page.h>
 #include <asm/desc.h>
@@ -530,7 +531,8 @@ static int __init pnpbios_init(void)
        if (check_legacy_ioport(PNPBIOS_BASE))
                return -ENODEV;
 #endif
-       if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table)) {
+       if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table) ||
+           paravirt_enabled()) {
                printk(KERN_INFO "PnPBIOS: Disabled\n");
                return -ENODEV;
        }
index b52d547..8433eb7 100644 (file)
@@ -1 +1,2 @@
 obj-y += system-bus.o
+obj-$(CONFIG_PS3_VUART) += vuart.o
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
new file mode 100644 (file)
index 0000000..6974f65
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ *  PS3 virtual uart
+ *
+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *  Copyright 2006 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <asm/ps3.h>
+
+#include <asm/lv1call.h>
+#include <asm/bitops.h>
+
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ps3 vuart");
+
+/**
+ * vuart - An inter-partition data link service.
+ *  port 0: PS3 AV Settings.
+ *  port 2: PS3 System Manager.
+ *
+ * The vuart provides a bi-directional byte stream data link between logical
+ * partitions.  Its primary role is as a communications link between the guest
+ * OS and the system policy module.  The current HV does not support any
+ * connections other than those listed.
+ */
+
+enum {PORT_COUNT = 3,};
+
+enum vuart_param {
+       PARAM_TX_TRIGGER = 0,
+       PARAM_RX_TRIGGER = 1,
+       PARAM_INTERRUPT_MASK = 2,
+       PARAM_RX_BUF_SIZE = 3, /* read only */
+       PARAM_RX_BYTES = 4, /* read only */
+       PARAM_TX_BUF_SIZE = 5, /* read only */
+       PARAM_TX_BYTES = 6, /* read only */
+       PARAM_INTERRUPT_STATUS = 7, /* read only */
+};
+
+enum vuart_interrupt_bit {
+       INTERRUPT_BIT_TX = 0,
+       INTERRUPT_BIT_RX = 1,
+       INTERRUPT_BIT_DISCONNECT = 2,
+};
+
+enum vuart_interrupt_mask {
+       INTERRUPT_MASK_TX = 1,
+       INTERRUPT_MASK_RX = 2,
+       INTERRUPT_MASK_DISCONNECT = 4,
+};
+
+/**
+ * struct ports_bmp - bitmap indicating ports needing service.
+ *
+ * A 256 bit read only bitmap indicating ports needing service.  Do not write
+ * to these bits.  Must not cross a page boundary.
+ */
+
+struct ports_bmp {
+       u64 status;
+       u64 unused[3];
+} __attribute__ ((aligned (32)));
+
+/* redefine dev_dbg to do a syntax check */
+
+#if !defined(DEBUG)
+#undef dev_dbg
+static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
+       const struct device *_dev, const char *fmt, ...) {return 0;}
+#endif
+
+#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_ports_bmp(
+       const struct ports_bmp* bmp, const char* func, int line)
+{
+       pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
+}
+
+static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
+       unsigned int *port_number)
+{
+       switch(match_id) {
+       case PS3_MATCH_ID_AV_SETTINGS:
+               *port_number = 0;
+               return 0;
+       case PS3_MATCH_ID_SYSTEM_MANAGER:
+               *port_number = 2;
+               return 0;
+       default:
+               WARN_ON(1);
+               *port_number = UINT_MAX;
+               return -EINVAL;
+       };
+}
+
+#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+       const char* func, int line)
+{
+#if defined(DEBUG)
+       static const char *strings[] = {
+               "tx_trigger      ",
+               "rx_trigger      ",
+               "interrupt_mask  ",
+               "rx_buf_size     ",
+               "rx_bytes        ",
+               "tx_buf_size     ",
+               "tx_bytes        ",
+               "interrupt_status",
+       };
+       int result;
+       unsigned int i;
+       u64 value;
+
+       for (i = 0; i < ARRAY_SIZE(strings); i++) {
+               result = lv1_get_virtual_uart_param(port_number, i, &value);
+
+               if (result) {
+                       pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line,
+                               port_number, strings[i], ps3_result(result));
+                       continue;
+               }
+               pr_debug("%s:%d: port_%u: %s = %lxh\n",
+                       func, line, port_number, strings[i], value);
+       }
+#endif
+}
+
+struct vuart_triggers {
+       unsigned long rx;
+       unsigned long tx;
+};
+
+int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+       struct vuart_triggers *trig)
+{
+       int result;
+       unsigned long size;
+       unsigned long val;
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_TX_TRIGGER, &trig->tx);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_RX_BUF_SIZE, &size);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_RX_TRIGGER, &val);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       trig->rx = size - val;
+
+       dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__,
+               trig->tx, trig->rx);
+
+       return result;
+}
+
+int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+       unsigned int rx)
+{
+       int result;
+       unsigned long size;
+
+       result = lv1_set_virtual_uart_param(dev->port_number,
+               PARAM_TX_TRIGGER, tx);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_RX_BUF_SIZE, &size);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       result = lv1_set_virtual_uart_param(dev->port_number,
+               PARAM_RX_TRIGGER, size - rx);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__,
+               tx, rx);
+
+       return result;
+}
+
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+       unsigned long *bytes_waiting)
+{
+       int result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_RX_BYTES, bytes_waiting);
+
+       if (result)
+               dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
+       dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__,
+               *bytes_waiting);
+       return result;
+}
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+       unsigned long mask)
+{
+       int result;
+
+       dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
+
+       dev->interrupt_mask = mask;
+
+       result = lv1_set_virtual_uart_param(dev->port_number,
+               PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+
+       if (result)
+               dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
+       return result;
+}
+
+static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+       unsigned long *status)
+{
+       int result = lv1_get_virtual_uart_param(dev->port_number,
+               PARAM_INTERRUPT_STATUS, status);
+
+       if (result)
+               dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
+       dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
+               __func__, __LINE__, dev->interrupt_mask, *status,
+               dev->interrupt_mask & *status);
+
+       return result;
+}
+
+int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               | INTERRUPT_MASK_TX);
+}
+
+int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               | INTERRUPT_MASK_RX);
+}
+
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               | INTERRUPT_MASK_DISCONNECT);
+}
+
+int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_TX)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               & ~INTERRUPT_MASK_TX) : 0;
+}
+
+int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_RX)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               & ~INTERRUPT_MASK_RX) : 0;
+}
+
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+{
+       return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+               ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+               & ~INTERRUPT_MASK_DISCONNECT) : 0;
+}
+
+/**
+ * ps3_vuart_raw_write - Low level write helper.
+ *
+ * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
+ */
+
+static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+       const void* buf, unsigned int bytes, unsigned long *bytes_written)
+{
+       int result;
+
+       dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+       result = lv1_write_virtual_uart(dev->port_number,
+               ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: "
+                       "%s\n", __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       dev->stats.bytes_written += *bytes_written;
+
+       dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__,
+               __LINE__, *bytes_written, bytes, dev->stats.bytes_written);
+
+       return result;
+}
+
+/**
+ * ps3_vuart_raw_read - Low level read helper.
+ *
+ * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
+ */
+
+static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+       unsigned int bytes, unsigned long *bytes_read)
+{
+       int result;
+
+       dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+       result = lv1_read_virtual_uart(dev->port_number,
+               ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               return result;
+       }
+
+       dev->stats.bytes_read += *bytes_read;
+
+       dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
+               *bytes_read, bytes, dev->stats.bytes_read);
+
+       return result;
+}
+
+/**
+ * struct list_buffer - An element for a port device fifo buffer list.
+ */
+
+struct list_buffer {
+       struct list_head link;
+       const unsigned char *head;
+       const unsigned char *tail;
+       unsigned long dbg_number;
+       unsigned char data[];
+};
+
+/**
+ * ps3_vuart_write - the entry point for writing data to a port
+ *
+ * If the port is idle on entry as much of the incoming data is written to
+ * the port as the port will accept.  Otherwise a list buffer is created
+ * and any remaning incoming data is copied to that buffer.  The buffer is
+ * then enqueued for transmision via the transmit interrupt.
+ */
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+       unsigned int bytes)
+{
+       static unsigned long dbg_number;
+       int result;
+       unsigned long flags;
+       struct list_buffer *lb;
+
+       dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+               bytes, bytes);
+
+       spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+       if (list_empty(&dev->tx_list.head)) {
+               unsigned long bytes_written;
+
+               result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
+
+               spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+               if (result) {
+                       dev_dbg(&dev->core,
+                               "%s:%d: ps3_vuart_raw_write failed\n",
+                               __func__, __LINE__);
+                       return result;
+               }
+
+               if (bytes_written == bytes) {
+                       dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n",
+                               __func__, __LINE__, bytes);
+                       return 0;
+               }
+
+               bytes -= bytes_written;
+               buf += bytes_written;
+       } else
+               spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+       lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
+
+       if (!lb) {
+               return -ENOMEM;
+       }
+
+       memcpy(lb->data, buf, bytes);
+       lb->head = lb->data;
+       lb->tail = lb->data + bytes;
+       lb->dbg_number = ++dbg_number;
+
+       spin_lock_irqsave(&dev->tx_list.lock, flags);
+       list_add_tail(&lb->link, &dev->tx_list.head);
+       ps3_vuart_enable_interrupt_tx(dev);
+       spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+       dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
+               __func__, __LINE__, lb->dbg_number, bytes);
+
+       return 0;
+}
+
+/**
+ * ps3_vuart_read - the entry point for reading data from a port
+ *
+ * If enough bytes to satisfy the request are held in the buffer list those
+ * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
+ * are retiered.  If the request cannot be statified by bytes held in the list
+ * buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+       unsigned int bytes)
+{
+       unsigned long flags;
+       struct list_buffer *lb, *n;
+       unsigned long bytes_read;
+
+       dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+               bytes, bytes);
+
+       spin_lock_irqsave(&dev->rx_list.lock, flags);
+
+       if (dev->rx_list.bytes_held < bytes) {
+               spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+               dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+                       __func__, __LINE__, bytes - dev->rx_list.bytes_held);
+               return -EAGAIN;
+       }
+
+       list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) {
+               bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
+
+               memcpy(buf, lb->head, bytes_read);
+               buf += bytes_read;
+               bytes -= bytes_read;
+               dev->rx_list.bytes_held -= bytes_read;
+
+               if (bytes_read < lb->tail - lb->head) {
+                       lb->head += bytes_read;
+                       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+                       dev_dbg(&dev->core,
+                               "%s:%d: dequeued buf_%lu, %lxh bytes\n",
+                               __func__, __LINE__, lb->dbg_number, bytes_read);
+                       return 0;
+               }
+
+               dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+                       lb->dbg_number);
+
+               list_del(&lb->link);
+               kfree(lb);
+       }
+       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+       dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n",
+               __func__, __LINE__, lb->dbg_number, bytes);
+
+       return 0;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
+ *
+ * Services the transmit interrupt for the port.  Writes as much data from the
+ * buffer list as the port will accept.  Retires any emptied list buffers and
+ * adjusts the final list buffer state for a partial write.
+ */
+
+static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+       int result = 0;
+       unsigned long flags;
+       struct list_buffer *lb, *n;
+       unsigned long bytes_total = 0;
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+       list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+
+               unsigned long bytes_written;
+
+               result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head,
+                       &bytes_written);
+
+               if (result) {
+                       dev_dbg(&dev->core,
+                               "%s:%d: ps3_vuart_raw_write failed\n",
+                               __func__, __LINE__);
+                       break;
+               }
+
+               bytes_total += bytes_written;
+
+               if (bytes_written < lb->tail - lb->head) {
+                       lb->head += bytes_written;
+                       dev_dbg(&dev->core,
+                               "%s:%d cleared buf_%lu, %lxh bytes\n",
+                               __func__, __LINE__, lb->dbg_number,
+                               bytes_written);
+                       goto port_full;
+               }
+
+               dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+                       lb->dbg_number);
+
+               list_del(&lb->link);
+               kfree(lb);
+       }
+
+       ps3_vuart_disable_interrupt_tx(dev);
+port_full:
+       spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+       dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
+               __func__, __LINE__, bytes_total);
+       return result;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler
+ *
+ * Services the receive interrupt for the port.  Creates a list buffer and
+ * copies all waiting port data to that buffer and enqueues the buffer in the
+ * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
+ */
+
+static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+       static unsigned long dbg_number;
+       int result = 0;
+       unsigned long flags;
+       struct list_buffer *lb;
+       unsigned long bytes;
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+
+       if (result)
+               return -EIO;
+
+       BUG_ON(!bytes);
+
+       /* add some extra space for recently arrived data */
+
+       bytes += 128;
+
+       lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+       if (!lb)
+               return -ENOMEM;
+
+       ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+       lb->head = lb->data;
+       lb->tail = lb->data + bytes;
+       lb->dbg_number = ++dbg_number;
+
+       spin_lock_irqsave(&dev->rx_list.lock, flags);
+       list_add_tail(&lb->link, &dev->rx_list.head);
+       dev->rx_list.bytes_held += bytes;
+       spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+       dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+               __func__, __LINE__, lb->dbg_number, bytes);
+
+       return 0;
+}
+
+static int ps3_vuart_handle_interrupt_disconnect(
+       struct ps3_vuart_port_device *dev)
+{
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+       BUG_ON("no support");
+       return -1;
+}
+
+/**
+ * ps3_vuart_handle_port_interrupt - second stage interrupt handler
+ *
+ * Services any pending interrupt types for the port.  Passes control to the
+ * third stage type specific interrupt handler.  Returns control to the first
+ * stage handler after one iteration.
+ */
+
+static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+{
+       int result;
+       unsigned long status;
+
+       result = ps3_vuart_get_interrupt_mask(dev, &status);
+
+       if (result)
+               return result;
+
+       dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__,
+               status);
+
+       if (status & INTERRUPT_MASK_DISCONNECT) {
+               dev->stats.disconnect_interrupts++;
+               result = ps3_vuart_handle_interrupt_disconnect(dev);
+               if (result)
+                       ps3_vuart_disable_interrupt_disconnect(dev);
+       }
+
+       if (status & INTERRUPT_MASK_TX) {
+               dev->stats.tx_interrupts++;
+               result = ps3_vuart_handle_interrupt_tx(dev);
+               if (result)
+                       ps3_vuart_disable_interrupt_tx(dev);
+       }
+
+       if (status & INTERRUPT_MASK_RX) {
+               dev->stats.rx_interrupts++;
+               result = ps3_vuart_handle_interrupt_rx(dev);
+               if (result)
+                       ps3_vuart_disable_interrupt_rx(dev);
+       }
+
+       return 0;
+}
+
+struct vuart_private {
+       unsigned int in_use;
+       unsigned int virq;
+       struct ps3_vuart_port_device *devices[PORT_COUNT];
+       const struct ports_bmp bmp;
+};
+
+/**
+ * ps3_vuart_irq_handler - first stage interrupt handler
+ *
+ * Loops finding any interrupting port and its associated instance data.
+ * Passes control to the second stage port specific interrupt handler.  Loops
+ * until all outstanding interrupts are serviced.
+ */
+
+static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
+{
+       struct vuart_private *private;
+
+       BUG_ON(!_private);
+       private = (struct vuart_private *)_private;
+
+       while (1) {
+               unsigned int port;
+
+               dump_ports_bmp(&private->bmp);
+
+               port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+
+               if (port == BITS_PER_LONG)
+                       break;
+
+               BUG_ON(port >= PORT_COUNT);
+               BUG_ON(!private->devices[port]);
+
+               ps3_vuart_handle_port_interrupt(private->devices[port]);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+{
+       int result;
+       struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
+       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+       result = dev->match_id == drv->match_id;
+
+       dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
+               __LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
+               drv->core.name, (result ? "match" : "miss"));
+
+       return result;
+}
+
+static struct vuart_private vuart_private;
+
+static int ps3_vuart_probe(struct device *_dev)
+{
+       int result;
+       unsigned long tmp;
+       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+       struct ps3_vuart_port_driver *drv =
+               to_ps3_vuart_port_driver(_dev->driver);
+
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       BUG_ON(!drv);
+
+       result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
+                       __func__, __LINE__, dev->match_id);
+               result = -EINVAL;
+               goto fail_match;
+       }
+
+       if (vuart_private.devices[dev->port_number]) {
+               dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
+                       __LINE__, dev->port_number);
+               result = -EBUSY;
+               goto fail_match;
+       }
+
+       vuart_private.devices[dev->port_number] = dev;
+
+       INIT_LIST_HEAD(&dev->tx_list.head);
+       spin_lock_init(&dev->tx_list.lock);
+       INIT_LIST_HEAD(&dev->rx_list.head);
+       spin_lock_init(&dev->rx_list.lock);
+
+       vuart_private.in_use++;
+       if (vuart_private.in_use == 1) {
+               result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status,
+                       &vuart_private.virq);
+
+               if (result) {
+                       dev_dbg(&dev->core,
+                               "%s:%d: ps3_alloc_vuart_irq failed (%d)\n",
+                               __func__, __LINE__, result);
+                       result = -EPERM;
+                       goto fail_alloc_irq;
+               }
+
+               result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
+                       IRQF_DISABLED, "vuart", &vuart_private);
+
+               if (result) {
+                       dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
+                               __func__, __LINE__, result);
+                       goto fail_request_irq;
+               }
+       }
+
+       ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
+
+       /* clear stale pending interrupts */
+       ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+       ps3_vuart_set_triggers(dev, 1, 1);
+
+       if (drv->probe)
+               result = drv->probe(dev);
+       else {
+               result = 0;
+               dev_info(&dev->core, "%s:%d: no probe method\n", __func__,
+                       __LINE__);
+       }
+
+       if (result) {
+               dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
+                       __func__, __LINE__);
+               goto fail_probe;
+       }
+
+       return result;
+
+fail_probe:
+fail_request_irq:
+       vuart_private.in_use--;
+       if (!vuart_private.in_use) {
+               ps3_free_vuart_irq(vuart_private.virq);
+               vuart_private.virq = NO_IRQ;
+       }
+fail_alloc_irq:
+fail_match:
+       dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+       return result;
+}
+
+static int ps3_vuart_remove(struct device *_dev)
+{
+       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+       struct ps3_vuart_port_driver *drv =
+               to_ps3_vuart_port_driver(_dev->driver);
+
+       dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
+               dev->core.bus_id);
+
+       BUG_ON(vuart_private.in_use < 1);
+
+       if (drv->remove)
+               drv->remove(dev);
+       else
+               dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
+                       __LINE__, dev->core.bus_id);
+
+       vuart_private.in_use--;
+
+       if (!vuart_private.in_use) {
+               free_irq(vuart_private.virq, &vuart_private);
+               ps3_free_vuart_irq(vuart_private.virq);
+               vuart_private.virq = NO_IRQ;
+       }
+       return 0;
+}
+
+/**
+ * ps3_vuart - The vuart instance.
+ *
+ * The vuart is managed as a bus that port devices connect to.
+ */
+
+struct bus_type ps3_vuart = {
+        .name = "ps3_vuart",
+       .match = ps3_vuart_match,
+       .probe = ps3_vuart_probe,
+       .remove = ps3_vuart_remove,
+};
+
+int __init ps3_vuart_init(void)
+{
+       int result;
+
+       pr_debug("%s:%d:\n", __func__, __LINE__);
+       result = bus_register(&ps3_vuart);
+       BUG_ON(result);
+       return result;
+}
+
+void __exit ps3_vuart_exit(void)
+{
+       pr_debug("%s:%d:\n", __func__, __LINE__);
+       bus_unregister(&ps3_vuart);
+}
+
+core_initcall(ps3_vuart_init);
+module_exit(ps3_vuart_exit);
+
+/**
+ * ps3_vuart_port_release_device - Remove a vuart port device.
+ */
+
+static void ps3_vuart_port_release_device(struct device *_dev)
+{
+       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+#if defined(DEBUG)
+       memset(dev, 0xad, sizeof(struct ps3_vuart_port_device));
+#endif
+       kfree(dev);
+}
+
+/**
+ * ps3_vuart_port_device_register - Add a vuart port device.
+ */
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+{
+       int result;
+       static unsigned int dev_count = 1;
+
+       dev->core.parent = NULL;
+       dev->core.bus = &ps3_vuart;
+       dev->core.release = ps3_vuart_port_release_device;
+
+       snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
+               dev_count++);
+
+       dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+
+       result = device_register(&dev->core);
+
+       return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+
+/**
+ * ps3_vuart_port_driver_register - Add a vuart port device driver.
+ */
+
+int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
+{
+       int result;
+
+       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
+       drv->core.bus = &ps3_vuart;
+       result = driver_register(&drv->core);
+       return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
+
+/**
+ * ps3_vuart_port_driver_unregister - Remove a vuart port device driver.
+ */
+
+void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
+{
+       driver_unregister(&drv->core);
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
new file mode 100644 (file)
index 0000000..28fd89f
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  PS3 virtual uart
+ *
+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *  Copyright 2006 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_PS3_VUART_H)
+#define _PS3_VUART_H
+
+struct ps3_vuart_stats {
+       unsigned long bytes_written;
+       unsigned long bytes_read;
+       unsigned long tx_interrupts;
+       unsigned long rx_interrupts;
+       unsigned long disconnect_interrupts;
+};
+
+/**
+ * struct ps3_vuart_port_device - a device on a vuart port
+ */
+
+struct ps3_vuart_port_device {
+       enum ps3_match_id match_id;
+       struct device core;
+
+       /* private driver variables */
+       unsigned int port_number;
+       unsigned long interrupt_mask;
+       struct {
+               spinlock_t lock;
+               struct list_head head;
+       } tx_list;
+       struct {
+               unsigned long bytes_held;
+               spinlock_t lock;
+               struct list_head head;
+       } rx_list;
+       struct ps3_vuart_stats stats;
+};
+
+/**
+ * struct ps3_vuart_port_driver - a driver for a device on a vuart port
+ */
+
+struct ps3_vuart_port_driver {
+       enum ps3_match_id match_id;
+       struct device_driver core;
+       int (*probe)(struct ps3_vuart_port_device *);
+       int (*remove)(struct ps3_vuart_port_device *);
+       int (*tx_event)(struct ps3_vuart_port_device *dev);
+       int (*rx_event)(struct ps3_vuart_port_device *dev);
+       int (*disconnect_event)(struct ps3_vuart_port_device *dev);
+       /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
+       /* int (*resume)(struct ps3_vuart_port_device *); */
+};
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
+int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
+void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
+int ps3_vuart_write(struct ps3_vuart_port_device *dev,
+       const void* buf, unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+       unsigned int bytes);
+static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
+       struct device_driver *_drv)
+{
+       return container_of(_drv, struct ps3_vuart_port_driver, core);
+}
+static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
+       struct device *_dev)
+{
+       return container_of(_dev, struct ps3_vuart_port_device, core);
+}
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+       unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+       unsigned int bytes);
+
+#endif
index fc766a7..09660e2 100644 (file)
@@ -154,15 +154,23 @@ config RTC_DRV_DS1672
          will be called rtc-ds1672.
 
 config RTC_DRV_DS1742
-       tristate "Dallas DS1742"
+       tristate "Dallas DS1742/1743"
        depends on RTC_CLASS
        help
          If you say yes here you get support for the
-         Dallas DS1742 timekeeping chip.
+         Dallas DS1742/1743 timekeeping chip.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1742.
 
+config RTC_DRV_OMAP
+       tristate "TI OMAP1"
+       depends on RTC_CLASS && ( \
+               ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 )
+       help
+         Say "yes" here to support the real time clock on TI OMAP1 chips.
+         This driver can also be built as a module called rtc-omap.
+
 config RTC_DRV_PCF8563
        tristate "Philips PCF8563/Epson RTC8564"
        depends on RTC_CLASS && I2C
@@ -280,7 +288,7 @@ config RTC_DRV_PL031
          To compile this driver as a module, choose M here: the
          module will be called rtc-pl031.
 
-config RTC_DRV_AT91
+config RTC_DRV_AT91RM9200
        tristate "AT91RM9200"
        depends on RTC_CLASS && ARCH_AT91RM9200
        help
index 3ba5ff6..e6beeda 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_RTC_DRV_TEST)    += rtc-test.o
 obj-$(CONFIG_RTC_DRV_DS1307)   += rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1672)   += rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)   += rtc-ds1742.o
+obj-$(CONFIG_RTC_DRV_OMAP)     += rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCF8563)  += rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)  += rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_RS5C372)  += rtc-rs5c372.o
@@ -34,5 +35,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX)  += rtc-vr41xx.o
 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_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
index 814b9e1..828b329 100644 (file)
@@ -53,9 +53,10 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
  * Routine to poll RTC seconds field for change as often as possible,
  * after first RTC_UIE use timer to reduce polling
  */
-static void rtc_uie_task(void *data)
+static void rtc_uie_task(struct work_struct *work)
 {
-       struct rtc_device *rtc = data;
+       struct rtc_device *rtc =
+               container_of(work, struct rtc_device, uie_task);
        struct rtc_time tm;
        int num = 0;
        int err;
@@ -411,7 +412,7 @@ static int rtc_dev_add_device(struct class_device *class_dev,
        spin_lock_init(&rtc->irq_lock);
        init_waitqueue_head(&rtc->irq_queue);
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
-       INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc);
+       INIT_WORK(&rtc->uie_task, rtc_uie_task);
        setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
 #endif
 
index 67e816a..205fa28 100644 (file)
@@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
        struct i2c_client *client;
        struct rtc_device *rtc;
 
-       dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+       dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
@@ -237,17 +237,22 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
        /* read control register */
        err = ds1672_get_control(client, &control);
        if (err)
-               goto exit_detach;
+               goto exit_devreg;
 
        if (control & DS1672_REG_CONTROL_EOSC)
                dev_warn(&client->dev, "Oscillator not enabled. "
                                        "Set time to enable.\n");
 
        /* Register sysfs hooks */
-       device_create_file(&client->dev, &dev_attr_control);
+       err = device_create_file(&client->dev, &dev_attr_control);
+       if (err)
+               goto exit_devreg;
 
        return 0;
 
+exit_devreg:
+       rtc_device_unregister(rtc);
+
 exit_detach:
        i2c_detach_client(client);
 
index 6273a3d..17633bf 100644 (file)
@@ -6,6 +6,10 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2006 Torsten Ertbjerg Rasmussen <tr@newtec.dk>
+ *  - nvram size determined from resource
+ *  - this ds1742 driver now supports ds1743.
  */
 
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
 
-#define RTC_REG_SIZE           0x800
-#define RTC_OFFSET             0x7f8
+#define RTC_SIZE               8
 
-#define RTC_CONTROL            (RTC_OFFSET + 0)
-#define RTC_CENTURY            (RTC_OFFSET + 0)
-#define RTC_SECONDS            (RTC_OFFSET + 1)
-#define RTC_MINUTES            (RTC_OFFSET + 2)
-#define RTC_HOURS              (RTC_OFFSET + 3)
-#define RTC_DAY                        (RTC_OFFSET + 4)
-#define RTC_DATE               (RTC_OFFSET + 5)
-#define RTC_MONTH              (RTC_OFFSET + 6)
-#define RTC_YEAR               (RTC_OFFSET + 7)
+#define RTC_CONTROL            0
+#define RTC_CENTURY            0
+#define RTC_SECONDS            1
+#define RTC_MINUTES            2
+#define RTC_HOURS              3
+#define RTC_DAY                        4
+#define RTC_DATE               5
+#define RTC_MONTH              6
+#define RTC_YEAR               7
 
 #define RTC_CENTURY_MASK       0x3f
 #define RTC_SECONDS_MASK       0x7f
 
 struct rtc_plat_data {
        struct rtc_device *rtc;
-       void __iomem *ioaddr;
+       void __iomem *ioaddr_nvram;
+       void __iomem *ioaddr_rtc;
+       size_t size_nvram;
+       size_t size;
        unsigned long baseaddr;
        unsigned long last_jiffies;
 };
@@ -57,7 +63,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       void __iomem *ioaddr = pdata->ioaddr;
+       void __iomem *ioaddr = pdata->ioaddr_rtc;
        u8 century;
 
        century = BIN2BCD((tm->tm_year + 1900) / 100);
@@ -82,7 +88,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       void __iomem *ioaddr = pdata->ioaddr;
+       void __iomem *ioaddr = pdata->ioaddr_rtc;
        unsigned int year, month, day, hour, minute, second, week;
        unsigned int century;
 
@@ -127,10 +133,10 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       void __iomem *ioaddr = pdata->ioaddr;
+       void __iomem *ioaddr = pdata->ioaddr_nvram;
        ssize_t count;
 
-       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+       for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
                *buf++ = readb(ioaddr + pos++);
        return count;
 }
@@ -141,10 +147,10 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
        struct platform_device *pdev =
                to_platform_device(container_of(kobj, struct device, kobj));
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       void __iomem *ioaddr = pdata->ioaddr;
+       void __iomem *ioaddr = pdata->ioaddr_nvram;
        ssize_t count;
 
-       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+       for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
                writeb(*buf++, ioaddr + pos++);
        return count;
 }
@@ -155,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = {
                .mode = S_IRUGO | S_IWUGO,
                .owner = THIS_MODULE,
        },
-       .size = RTC_OFFSET,
        .read = ds1742_nvram_read,
        .write = ds1742_nvram_write,
 };
@@ -175,19 +180,23 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev)
        pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return -ENOMEM;
-       if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+       pdata->size = res->end - res->start + 1;
+       if (!request_mem_region(res->start, pdata->size, pdev->name)) {
                ret = -EBUSY;
                goto out;
        }
        pdata->baseaddr = res->start;
-       ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+       ioaddr = ioremap(pdata->baseaddr, pdata->size);
        if (!ioaddr) {
                ret = -ENOMEM;
                goto out;
        }
-       pdata->ioaddr = ioaddr;
+       pdata->ioaddr_nvram = ioaddr;
+       pdata->size_nvram = pdata->size - RTC_SIZE;
+       pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
 
        /* turn RTC on if it was not on */
+       ioaddr = pdata->ioaddr_rtc;
        sec = readb(ioaddr + RTC_SECONDS);
        if (sec & RTC_STOP) {
                sec &= RTC_SECONDS_MASK;
@@ -208,6 +217,8 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev)
        pdata->rtc = rtc;
        pdata->last_jiffies = jiffies;
        platform_set_drvdata(pdev, pdata);
+       ds1742_nvram_attr.size = max(ds1742_nvram_attr.size,
+                                    pdata->size_nvram);
        ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
        if (ret)
                goto out;
@@ -215,10 +226,10 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev)
  out:
        if (pdata->rtc)
                rtc_device_unregister(pdata->rtc);
-       if (ioaddr)
-               iounmap(ioaddr);
+       if (pdata->ioaddr_nvram)
+               iounmap(pdata->ioaddr_nvram);
        if (pdata->baseaddr)
-               release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+               release_mem_region(pdata->baseaddr, pdata->size);
        kfree(pdata);
        return ret;
 }
@@ -229,8 +240,8 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
 
        sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
        rtc_device_unregister(pdata->rtc);
-       iounmap(pdata->ioaddr);
-       release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+       iounmap(pdata->ioaddr_nvram);
+       release_mem_region(pdata->baseaddr, pdata->size);
        kfree(pdata);
        return 0;
 }
index ba795a4..7bbc26a 100644 (file)
@@ -117,4 +117,85 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
 }
 EXPORT_SYMBOL(rtc_tm_to_time);
 
+
+/* Merge the valid (i.e. non-negative) fields of alarm into the current
+ * time.  If the valid alarm fields are earlier than the equivalent
+ * fields in the time, carry one into the least significant invalid
+ * field, so that the alarm expiry is in the future.  It assumes that the
+ * least significant invalid field is more significant than the most
+ * significant valid field, and that the seconds field is valid.
+ *
+ * This is used by alarms that take relative (rather than absolute)
+ * times, and/or have a simple binary second counter instead of
+ * day/hour/minute/sec registers.
+ */
+void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm)
+{
+       int *alarmp = &alarm->tm_sec;
+       int *timep = &now->tm_sec;
+       int carry_into, i;
+
+       /* Ignore everything past the 6th element (tm_year). */
+       for (i = 5; i > 0; i--) {
+               if (alarmp[i] < 0)
+                       alarmp[i] = timep[i];
+               else
+                       break;
+       }
+
+       /* No carry needed if all fields are valid. */
+       if (i == 5)
+               return;
+
+       for (carry_into = i + 1; i >= 0; i--) {
+               if (alarmp[i] < timep[i])
+                       break;
+
+               if (alarmp[i] > timep[i])
+                       return;
+       }
+
+       switch (carry_into) {
+               case 1:
+                       alarm->tm_min++;
+
+                       if (alarm->tm_min < 60)
+                               return;
+
+                       alarm->tm_min = 0;
+                       /* fall-through */
+
+               case 2:
+                       alarm->tm_hour++;
+
+                       if (alarm->tm_hour < 60)
+                               return;
+
+                       alarm->tm_hour = 0;
+                       /* fall-through */
+
+               case 3:
+                       alarm->tm_mday++;
+
+                       if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon])
+                               return;
+
+                       alarm->tm_mday = 1;
+                       /* fall-through */
+
+               case 4:
+                       alarm->tm_mon++;
+
+                       if (alarm->tm_mon <= 12)
+                               return;
+
+                       alarm->tm_mon = 1;
+                       /* fall-through */
+
+               case 5:
+                       alarm->tm_year++;
+       }
+}
+EXPORT_SYMBOL(rtc_merge_alarm);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
new file mode 100644 (file)
index 0000000..eac5fb1
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * TI OMAP1 Real Time Clock interface for Linux
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * Copyright (C) 2006 David Brownell (new RTC framework)
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+
+/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
+ * with century-range alarm matching, driven by the 32kHz clock.
+ *
+ * The main user-visible ways it differs from PC RTCs are by omitting
+ * "don't care" alarm fields and sub-second periodic IRQs, and having
+ * an autoadjust mechanism to calibrate to the true oscillator rate.
+ *
+ * Board-specific wiring options include using split power mode with
+ * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset),
+ * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from
+ * low power modes).  See the BOARD-SPECIFIC CUSTOMIZATION comment.
+ */
+
+#define OMAP_RTC_BASE                  0xfffb4800
+
+/* RTC registers */
+#define OMAP_RTC_SECONDS_REG           0x00
+#define OMAP_RTC_MINUTES_REG           0x04
+#define OMAP_RTC_HOURS_REG             0x08
+#define OMAP_RTC_DAYS_REG              0x0C
+#define OMAP_RTC_MONTHS_REG            0x10
+#define OMAP_RTC_YEARS_REG             0x14
+#define OMAP_RTC_WEEKS_REG             0x18
+
+#define OMAP_RTC_ALARM_SECONDS_REG     0x20
+#define OMAP_RTC_ALARM_MINUTES_REG     0x24
+#define OMAP_RTC_ALARM_HOURS_REG       0x28
+#define OMAP_RTC_ALARM_DAYS_REG                0x2c
+#define OMAP_RTC_ALARM_MONTHS_REG      0x30
+#define OMAP_RTC_ALARM_YEARS_REG       0x34
+
+#define OMAP_RTC_CTRL_REG              0x40
+#define OMAP_RTC_STATUS_REG            0x44
+#define OMAP_RTC_INTERRUPTS_REG                0x48
+
+#define OMAP_RTC_COMP_LSB_REG          0x4c
+#define OMAP_RTC_COMP_MSB_REG          0x50
+#define OMAP_RTC_OSC_REG               0x54
+
+/* OMAP_RTC_CTRL_REG bit fields: */
+#define OMAP_RTC_CTRL_SPLIT            (1<<7)
+#define OMAP_RTC_CTRL_DISABLE          (1<<6)
+#define OMAP_RTC_CTRL_SET_32_COUNTER   (1<<5)
+#define OMAP_RTC_CTRL_TEST             (1<<4)
+#define OMAP_RTC_CTRL_MODE_12_24       (1<<3)
+#define OMAP_RTC_CTRL_AUTO_COMP                (1<<2)
+#define OMAP_RTC_CTRL_ROUND_30S                (1<<1)
+#define OMAP_RTC_CTRL_STOP             (1<<0)
+
+/* OMAP_RTC_STATUS_REG bit fields: */
+#define OMAP_RTC_STATUS_POWER_UP        (1<<7)
+#define OMAP_RTC_STATUS_ALARM           (1<<6)
+#define OMAP_RTC_STATUS_1D_EVENT        (1<<5)
+#define OMAP_RTC_STATUS_1H_EVENT        (1<<4)
+#define OMAP_RTC_STATUS_1M_EVENT        (1<<3)
+#define OMAP_RTC_STATUS_1S_EVENT        (1<<2)
+#define OMAP_RTC_STATUS_RUN             (1<<1)
+#define OMAP_RTC_STATUS_BUSY            (1<<0)
+
+/* OMAP_RTC_INTERRUPTS_REG bit fields: */
+#define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
+#define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
+
+
+#define rtc_read(addr)         omap_readb(OMAP_RTC_BASE + (addr))
+#define rtc_write(val, addr)   omap_writeb(val, OMAP_RTC_BASE + (addr))
+
+
+/* platform_bus isn't hotpluggable, so for static linkage it'd be safe
+ * to get rid of probe() and remove() code ... too bad the driver struct
+ * remembers probe(), that's about 25% of the runtime footprint!!
+ */
+#ifndef        MODULE
+#undef __devexit
+#undef __devexit_p
+#define        __devexit       __exit
+#define        __devexit_p     __exit_p
+#endif
+
+
+/* we rely on the rtc framework to handle locking (rtc->ops_lock),
+ * so the only other requirement is that register accesses which
+ * require BUSY to be clear are made with IRQs locally disabled
+ */
+static void rtc_wait_not_busy(void)
+{
+       int     count = 0;
+       u8      status;
+
+       /* BUSY may stay active for 1/32768 second (~30 usec) */
+       for (count = 0; count < 50; count++) {
+               status = rtc_read(OMAP_RTC_STATUS_REG);
+               if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
+                       break;
+               udelay(1);
+       }
+       /* now we have ~15 usec to read/write various registers */
+}
+
+static irqreturn_t rtc_irq(int irq, void *class_dev)
+{
+       unsigned long           events = 0;
+       u8                      irq_data;
+
+       irq_data = rtc_read(OMAP_RTC_STATUS_REG);
+
+       /* alarm irq? */
+       if (irq_data & OMAP_RTC_STATUS_ALARM) {
+               rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+               events |= RTC_IRQF | RTC_AF;
+       }
+
+       /* 1/sec periodic/update irq? */
+       if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
+               events |= RTC_IRQF | RTC_UF;
+
+       rtc_update_irq(class_dev, 1, events);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static int
+omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       u8 reg;
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+       case RTC_AIE_ON:
+       case RTC_UIE_OFF:
+       case RTC_UIE_ON:
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       local_irq_disable();
+       rtc_wait_not_busy();
+       reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
+       switch (cmd) {
+       /* AIE = Alarm Interrupt Enable */
+       case RTC_AIE_OFF:
+               reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
+               break;
+       case RTC_AIE_ON:
+               reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
+               break;
+       /* UIE = Update Interrupt Enable (1/second) */
+       case RTC_UIE_OFF:
+               reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER;
+               break;
+       case RTC_UIE_ON:
+               reg |= OMAP_RTC_INTERRUPTS_IT_TIMER;
+               break;
+       }
+       rtc_wait_not_busy();
+       rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
+       local_irq_enable();
+
+       return 0;
+}
+
+#else
+#define        omap_rtc_ioctl  NULL
+#endif
+
+/* this hardware doesn't support "don't care" alarm fields */
+static int tm2bcd(struct rtc_time *tm)
+{
+       if (rtc_valid_tm(tm) != 0)
+               return -EINVAL;
+
+       tm->tm_sec = BIN2BCD(tm->tm_sec);
+       tm->tm_min = BIN2BCD(tm->tm_min);
+       tm->tm_hour = BIN2BCD(tm->tm_hour);
+       tm->tm_mday = BIN2BCD(tm->tm_mday);
+
+       tm->tm_mon = BIN2BCD(tm->tm_mon + 1);
+
+       /* epoch == 1900 */
+       if (tm->tm_year < 100 || tm->tm_year > 199)
+               return -EINVAL;
+       tm->tm_year = BIN2BCD(tm->tm_year - 100);
+
+       return 0;
+}
+
+static void bcd2tm(struct rtc_time *tm)
+{
+       tm->tm_sec = BCD2BIN(tm->tm_sec);
+       tm->tm_min = BCD2BIN(tm->tm_min);
+       tm->tm_hour = BCD2BIN(tm->tm_hour);
+       tm->tm_mday = BCD2BIN(tm->tm_mday);
+       tm->tm_mon = BCD2BIN(tm->tm_mon) - 1;
+       /* epoch == 1900 */
+       tm->tm_year = BCD2BIN(tm->tm_year) + 100;
+}
+
+
+static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       /* we don't report wday/yday/isdst ... */
+       local_irq_disable();
+       rtc_wait_not_busy();
+
+       tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
+       tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
+       tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
+       tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
+       tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
+       tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
+
+       local_irq_enable();
+
+       bcd2tm(tm);
+       return 0;
+}
+
+static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       if (tm2bcd(tm) < 0)
+               return -EINVAL;
+       local_irq_disable();
+       rtc_wait_not_busy();
+
+       rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
+       rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
+       rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
+       rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
+       rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
+       rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
+
+       local_irq_enable();
+
+       return 0;
+}
+
+static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       local_irq_disable();
+       rtc_wait_not_busy();
+
+       alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
+       alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
+       alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
+       alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
+       alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
+       alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);
+
+       local_irq_enable();
+
+       bcd2tm(&alm->time);
+       alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+                       & OMAP_RTC_INTERRUPTS_IT_ALARM);
+       alm->enabled = alm->pending && device_may_wakeup(dev);
+
+       return 0;
+}
+
+static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       u8 reg;
+
+       /* Much userspace code uses RTC_ALM_SET, thus "don't care" for
+        * day/month/year specifies alarms up to 24 hours in the future.
+        * So we need to handle that ... but let's ignore the "don't care"
+        * values for hours/minutes/seconds.
+        */
+       if (alm->time.tm_mday <= 0
+                       && alm->time.tm_mon < 0
+                       && alm->time.tm_year < 0) {
+               struct rtc_time tm;
+               unsigned long now, then;
+
+               omap_rtc_read_time(dev, &tm);
+               rtc_tm_to_time(&tm, &now);
+
+               alm->time.tm_mday = tm.tm_mday;
+               alm->time.tm_mon = tm.tm_mon;
+               alm->time.tm_year = tm.tm_year;
+               rtc_tm_to_time(&alm->time, &then);
+
+               /* sometimes the alarm wraps into tomorrow */
+               if (then < now) {
+                       rtc_time_to_tm(now + 24 * 60 * 60, &tm);
+                       alm->time.tm_mday = tm.tm_mday;
+                       alm->time.tm_mon = tm.tm_mon;
+                       alm->time.tm_year = tm.tm_year;
+               }
+       }
+
+       if (tm2bcd(&alm->time) < 0)
+               return -EINVAL;
+
+       local_irq_disable();
+       rtc_wait_not_busy();
+
+       rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
+       rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
+       rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
+       rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
+       rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
+       rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
+
+       reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
+       if (alm->enabled)
+               reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
+       else
+               reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
+       rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
+
+       local_irq_enable();
+
+       return 0;
+}
+
+static struct rtc_class_ops omap_rtc_ops = {
+       .ioctl          = omap_rtc_ioctl,
+       .read_time      = omap_rtc_read_time,
+       .set_time       = omap_rtc_set_time,
+       .read_alarm     = omap_rtc_read_alarm,
+       .set_alarm      = omap_rtc_set_alarm,
+};
+
+static int omap_rtc_alarm;
+static int omap_rtc_timer;
+
+static int __devinit omap_rtc_probe(struct platform_device *pdev)
+{
+       struct resource         *res, *mem;
+       struct rtc_device       *rtc;
+       u8                      reg, new_ctrl;
+
+       omap_rtc_timer = platform_get_irq(pdev, 0);
+       if (omap_rtc_timer <= 0) {
+               pr_debug("%s: no update irq?\n", pdev->name);
+               return -ENOENT;
+       }
+
+       omap_rtc_alarm = platform_get_irq(pdev, 1);
+       if (omap_rtc_alarm <= 0) {
+               pr_debug("%s: no alarm irq?\n", pdev->name);
+               return -ENOENT;
+       }
+
+       /* NOTE:  using static mapping for RTC registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res && res->start != OMAP_RTC_BASE) {
+               pr_debug("%s: RTC registers at %08x, expected %08x\n",
+                       pdev->name, (unsigned) res->start, OMAP_RTC_BASE);
+               return -ENOENT;
+       }
+
+       if (res)
+               mem = request_mem_region(res->start,
+                               res->end - res->start + 1,
+                               pdev->name);
+       else
+               mem = NULL;
+       if (!mem) {
+               pr_debug("%s: RTC registers at %08x are not free\n",
+                       pdev->name, OMAP_RTC_BASE);
+               return -EBUSY;
+       }
+
+       rtc = rtc_device_register(pdev->name, &pdev->dev,
+                       &omap_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               pr_debug("%s: can't register RTC device, err %ld\n",
+                       pdev->name, PTR_ERR(rtc));
+               goto fail;
+       }
+       platform_set_drvdata(pdev, rtc);
+       class_set_devdata(&rtc->class_dev, mem);
+
+       /* clear pending irqs, and set 1/second periodic,
+        * which we'll use instead of update irqs
+        */
+       rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+
+       /* clear old status */
+       reg = rtc_read(OMAP_RTC_STATUS_REG);
+       if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
+               pr_info("%s: RTC power up reset detected\n",
+                       pdev->name);
+               rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
+       }
+       if (reg & (u8) OMAP_RTC_STATUS_ALARM)
+               rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+
+       /* handle periodic and alarm irqs */
+       if (request_irq(omap_rtc_timer, rtc_irq, SA_INTERRUPT,
+                       rtc->class_dev.class_id, &rtc->class_dev)) {
+               pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
+                       pdev->name, omap_rtc_timer);
+               goto fail0;
+       }
+       if (request_irq(omap_rtc_alarm, rtc_irq, SA_INTERRUPT,
+                       rtc->class_dev.class_id, &rtc->class_dev)) {
+               pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
+                       pdev->name, omap_rtc_alarm);
+               goto fail1;
+       }
+
+       /* On boards with split power, RTC_ON_NOFF won't reset the RTC */
+       reg = rtc_read(OMAP_RTC_CTRL_REG);
+       if (reg & (u8) OMAP_RTC_CTRL_STOP)
+               pr_info("%s: already running\n", pdev->name);
+
+       /* force to 24 hour mode */
+       new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
+       new_ctrl |= OMAP_RTC_CTRL_STOP;
+
+       /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
+        *
+        *  - Boards wired so that RTC_WAKE_INT does something, and muxed
+        *    right (W13_1610_RTC_WAKE_INT is the default after chip reset),
+        *    should initialize the device wakeup flag appropriately.
+        *
+        *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
+        *    rather than nPWRON_RESET, should forcibly enable split
+        *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
+        *    is write-only, and always reads as zero...)
+        */
+       device_init_wakeup(&pdev->dev, 0);
+
+       if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT)
+               pr_info("%s: split power mode\n", pdev->name);
+
+       if (reg != new_ctrl)
+               rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);
+
+       return 0;
+
+fail1:
+       free_irq(omap_rtc_timer, NULL);
+fail0:
+       rtc_device_unregister(rtc);
+fail:
+       release_resource(mem);
+       return -EIO;
+}
+
+static int __devexit omap_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_device       *rtc = platform_get_drvdata(pdev);;
+
+       device_init_wakeup(&pdev->dev, 0);
+
+       /* leave rtc running, but disable irqs */
+       rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+
+       free_irq(omap_rtc_timer, rtc);
+       free_irq(omap_rtc_alarm, rtc);
+
+       release_resource(class_get_devdata(&rtc->class_dev));
+       rtc_device_unregister(rtc);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static struct timespec rtc_delta;
+static u8 irqstat;
+
+static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rtc_time rtc_tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+       omap_rtc_read_time(NULL, &rtc_tm);
+       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+       save_time_delta(&rtc_delta, &time);
+       irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
+
+       /* FIXME the RTC alarm is not currently acting as a wakeup event
+        * source, and in fact this enable() call is just saving a flag
+        * that's never used...
+        */
+       if (device_may_wakeup(&pdev->dev))
+               enable_irq_wake(omap_rtc_alarm);
+       else
+               rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+
+       return 0;
+}
+
+static int omap_rtc_resume(struct platform_device *pdev)
+{
+       struct rtc_time rtc_tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+       omap_rtc_read_time(NULL, &rtc_tm);
+       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+       restore_time_delta(&rtc_delta, &time);
+       if (device_may_wakeup(&pdev->dev))
+               disable_irq_wake(omap_rtc_alarm);
+       else
+               rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
+       return 0;
+}
+
+#else
+#define omap_rtc_suspend NULL
+#define omap_rtc_resume  NULL
+#endif
+
+static void omap_rtc_shutdown(struct platform_device *pdev)
+{
+       rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+}
+
+MODULE_ALIAS("omap_rtc");
+static struct platform_driver omap_rtc_driver = {
+       .probe          = omap_rtc_probe,
+       .remove         = __devexit_p(omap_rtc_remove),
+       .suspend        = omap_rtc_suspend,
+       .resume         = omap_rtc_resume,
+       .shutdown       = omap_rtc_shutdown,
+       .driver         = {
+               .name   = "omap_rtc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init rtc_init(void)
+{
+       return platform_driver_register(&omap_rtc_driver);
+}
+module_init(rtc_init);
+
+static void __exit rtc_exit(void)
+{
+       platform_driver_unregister(&omap_rtc_driver);
+}
+module_exit(rtc_exit);
+
+MODULE_AUTHOR("George G. Davis (and others)");
+MODULE_LICENSE("GPL");
index a760cf6..4b72b8e 100644 (file)
@@ -192,7 +192,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
                xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 
                if (xfer != ARRAY_SIZE(msgs)) {
-                       dev_err(&client->adapter->dev,
+                       dev_err(&client->dev,
                                "%s: could not read register 0x%02X\n",
                                __FUNCTION__, pattern[i].reg);
 
@@ -203,7 +203,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
 
                if (value > pattern[i].max ||
                        value < pattern[i].min) {
-                       dev_dbg(&client->adapter->dev,
+                       dev_dbg(&client->dev,
                                "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
                                "max=%d, value=%d, raw=0x%02X\n",
                                __FUNCTION__, i, pattern[i].reg, pattern[i].mask,
@@ -253,7 +253,7 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
 
        int err = 0;
 
-       dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+       dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
index a44fe4e..1460f6b 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
@@ -39,6 +39,14 @@ static int rs5c372_attach(struct i2c_adapter *adapter);
 static int rs5c372_detach(struct i2c_client *client);
 static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind);
 
+struct rs5c372 {
+       u8 reg_addr;
+       u8 regs[17];
+       struct i2c_msg msg[1];
+       struct i2c_client client;
+       struct rtc_device *rtc;
+};
+
 static struct i2c_driver rs5c372_driver = {
        .driver         = {
                .name   = "rs5c372",
@@ -49,18 +57,16 @@ static struct i2c_driver rs5c372_driver = {
 
 static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-       unsigned char buf[7] = { RS5C372_REG_BASE };
 
-       /* this implements the 1st reading method, according
-        * to the datasheet. buf[0] is initialized with
-        * address ptr and transmission format register.
+       struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
+       u8 *buf = &(rs5c372->regs[1]);
+
+       /* this implements the 3rd reading method, according
+        * to the datasheet. rs5c372 defaults to internal
+        * address 0xF, so 0x0 is in regs[1]
         */
-       struct i2c_msg msgs[] = {
-               { client->addr, 0, 1, buf },
-               { client->addr, I2C_M_RD, 7, buf },
-       };
 
-       if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+       if ((i2c_transfer(client->adapter, rs5c372->msg, 1)) != 1) {
                dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
                return -EIO;
        }
@@ -114,23 +120,14 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 
 static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
 {
-       unsigned char buf = RS5C372_REG_TRIM;
-
-       struct i2c_msg msgs[] = {
-               { client->addr, 0, 1, &buf },
-               { client->addr, I2C_M_RD, 1, &buf },
-       };
-
-       if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
-               dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
-               return -EIO;
-       }
+       struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
+       u8 tmp = rs5c372->regs[RS5C372_REG_TRIM + 1];
 
        if (osc)
-               *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768;
+               *osc = (tmp & RS5C372_TRIM_XSL) ? 32000 : 32768;
 
        if (trim) {
-               *trim = buf & RS5C372_TRIM_MASK;
+               *trim = tmp & RS5C372_TRIM_MASK;
                dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim);
        }
 
@@ -201,19 +198,20 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
 {
        int err = 0;
        struct i2c_client *client;
-       struct rtc_device *rtc;
+       struct rs5c372 *rs5c372;
 
-       dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+       dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
                goto exit;
        }
 
-       if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+       if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
                err = -ENOMEM;
                goto exit;
        }
+       client = &rs5c372->client;
 
        /* I2C client */
        client->addr = address;
@@ -222,32 +220,47 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
 
        strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
 
+       i2c_set_clientdata(client, rs5c372);
+
+       rs5c372->msg[0].addr = address;
+       rs5c372->msg[0].flags = I2C_M_RD;
+       rs5c372->msg[0].len = sizeof(rs5c372->regs);
+       rs5c372->msg[0].buf = rs5c372->regs;
+
        /* Inform the i2c layer */
        if ((err = i2c_attach_client(client)))
                goto exit_kfree;
 
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
-       rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev,
-                               &rs5c372_rtc_ops, THIS_MODULE);
+       rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
+                               &client->dev, &rs5c372_rtc_ops, THIS_MODULE);
 
-       if (IS_ERR(rtc)) {
-               err = PTR_ERR(rtc);
+       if (IS_ERR(rs5c372->rtc)) {
+               err = PTR_ERR(rs5c372->rtc);
                goto exit_detach;
        }
 
-       i2c_set_clientdata(client, rtc);
-
-       device_create_file(&client->dev, &dev_attr_trim);
-       device_create_file(&client->dev, &dev_attr_osc);
+       err = device_create_file(&client->dev, &dev_attr_trim);
+       if (err)
+               goto exit_devreg;
+       err = device_create_file(&client->dev, &dev_attr_osc);
+       if (err)
+               goto exit_trim;
 
        return 0;
 
+exit_trim:
+       device_remove_file(&client->dev, &dev_attr_trim);
+
+exit_devreg:
+       rtc_device_unregister(rs5c372->rtc);
+
 exit_detach:
        i2c_detach_client(client);
 
 exit_kfree:
-       kfree(client);
+       kfree(rs5c372);
 
 exit:
        return err;
@@ -256,16 +269,15 @@ exit:
 static int rs5c372_detach(struct i2c_client *client)
 {
        int err;
-       struct rtc_device *rtc = i2c_get_clientdata(client);
+       struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
 
-       if (rtc)
-               rtc_device_unregister(rtc);
+       if (rs5c372->rtc)
+               rtc_device_unregister(rs5c372->rtc);
 
        if ((err = i2c_detach_client(client)))
                return err;
 
-       kfree(client);
-
+       kfree(rs5c372);
        return 0;
 }
 
index 6ef9c62..f50a1b8 100644 (file)
@@ -123,11 +123,18 @@ static int test_probe(struct platform_device *plat_dev)
                err = PTR_ERR(rtc);
                return err;
        }
-       device_create_file(&plat_dev->dev, &dev_attr_irq);
+
+       err = device_create_file(&plat_dev->dev, &dev_attr_irq);
+       if (err)
+               goto err;
 
        platform_set_drvdata(plat_dev, rtc);
 
        return 0;
+
+err:
+       rtc_device_unregister(rtc);
+       return err;
 }
 
 static int __devexit test_remove(struct platform_device *plat_dev)
index 522c697..019ae25 100644 (file)
@@ -372,7 +372,7 @@ static int x1205_validate_client(struct i2c_client *client)
                };
 
                if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
-                       dev_err(&client->adapter->dev,
+                       dev_err(&client->dev,
                                "%s: could not read register %x\n",
                                __FUNCTION__, probe_zero_pattern[i]);
 
@@ -380,7 +380,7 @@ static int x1205_validate_client(struct i2c_client *client)
                }
 
                if ((buf & probe_zero_pattern[i+1]) != 0) {
-                       dev_err(&client->adapter->dev,
+                       dev_err(&client->dev,
                                "%s: register=%02x, zero pattern=%d, value=%x\n",
                                __FUNCTION__, probe_zero_pattern[i], i, buf);
 
@@ -400,7 +400,7 @@ static int x1205_validate_client(struct i2c_client *client)
                };
 
                if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
-                       dev_err(&client->adapter->dev,
+                       dev_err(&client->dev,
                                "%s: could not read register %x\n",
                                __FUNCTION__, probe_limits_pattern[i].reg);
 
@@ -411,7 +411,7 @@ static int x1205_validate_client(struct i2c_client *client)
 
                if (value > probe_limits_pattern[i].max ||
                        value < probe_limits_pattern[i].min) {
-                       dev_dbg(&client->adapter->dev,
+                       dev_dbg(&client->dev,
                                "%s: register=%x, lim pattern=%d, value=%d\n",
                                __FUNCTION__, probe_limits_pattern[i].reg,
                                i, value);
@@ -506,7 +506,7 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
        struct i2c_client *client;
        struct rtc_device *rtc;
 
-       dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+       dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
                err = -ENODEV;
@@ -562,11 +562,19 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
        else
                dev_err(&client->dev, "couldn't read status\n");
 
-       device_create_file(&client->dev, &dev_attr_atrim);
-       device_create_file(&client->dev, &dev_attr_dtrim);
+       err = device_create_file(&client->dev, &dev_attr_atrim);
+       if (err) goto exit_devreg;
+       err = device_create_file(&client->dev, &dev_attr_dtrim);
+       if (err) goto exit_atrim;
 
        return 0;
 
+exit_atrim:
+       device_remove_file(&client->dev, &dev_attr_atrim);
+
+exit_devreg:
+       rtc_device_unregister(rtc);
+
 exit_detach:
        i2c_detach_client(client);
 
index a2cef57..492b68b 100644 (file)
@@ -54,7 +54,7 @@ static void dasd_flush_request_queue(struct dasd_device *);
 static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 static int dasd_flush_ccw_queue(struct dasd_device *, int);
 static void dasd_tasklet(struct dasd_device *);
-static void do_kick_device(void *data);
+static void do_kick_device(struct work_struct *);
 
 /*
  * SECTION: Operations on the device structure.
@@ -100,7 +100,7 @@ dasd_alloc_device(void)
                     (unsigned long) device);
        INIT_LIST_HEAD(&device->ccw_queue);
        init_timer(&device->timer);
-       INIT_WORK(&device->kick_work, do_kick_device, device);
+       INIT_WORK(&device->kick_work, do_kick_device);
        device->state = DASD_STATE_NEW;
        device->target = DASD_STATE_NEW;
 
@@ -407,11 +407,9 @@ dasd_change_state(struct dasd_device *device)
  * event daemon.
  */
 static void
-do_kick_device(void *data)
+do_kick_device(struct work_struct *work)
 {
-       struct dasd_device *device;
-
-       device = (struct dasd_device *) data;
+       struct dasd_device *device = container_of(work, struct dasd_device, kick_work);
        dasd_change_state(device);
        dasd_schedule_bh(device);
        dasd_put_device(device);
@@ -1052,10 +1050,10 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                }
        } else {                /* error */
                memcpy(&cqr->irb, irb, sizeof (struct irb));
-#ifdef ERP_DEBUG
-               /* dump sense data */
-               dasd_log_sense(cqr, irb);
-#endif
+               if (device->features & DASD_FEATURE_ERPLOG) {
+                       /* dump sense data */
+                       dasd_log_sense(cqr, irb);
+               }
                switch (era) {
                case dasd_era_fatal:
                        cqr->status = DASD_CQR_FAILED;
index 669805d..4d01040 100644 (file)
@@ -2641,14 +2641,12 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
        struct dasd_ccw_req *erp = NULL;
        struct dasd_device *device = cqr->device;
        __u32 cpa = cqr->irb.scsw.cpa;
+       struct dasd_ccw_req *temp_erp = NULL;
 
-#ifdef ERP_DEBUG
-       /* print current erp_chain */
-       DEV_MESSAGE(KERN_ERR, device, "%s",
-                   "ERP chain at BEGINNING of ERP-ACTION");
-       {
-               struct dasd_ccw_req *temp_erp = NULL;
-
+       if (device->features & DASD_FEATURE_ERPLOG) {
+               /* print current erp_chain */
+               DEV_MESSAGE(KERN_ERR, device, "%s",
+                           "ERP chain at BEGINNING of ERP-ACTION");
                for (temp_erp = cqr;
                     temp_erp != NULL; temp_erp = temp_erp->refers) {
 
@@ -2658,7 +2656,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                                    temp_erp->refers);
                }
        }
-#endif                         /* ERP_DEBUG */
 
        /* double-check if current erp/cqr was successfull */
        if ((cqr->irb.scsw.cstat == 0x00) &&
@@ -2695,11 +2692,10 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                erp = dasd_3990_erp_handle_match_erp(cqr, erp);
        }
 
-#ifdef ERP_DEBUG
-       /* print current erp_chain */
-       DEV_MESSAGE(KERN_ERR, device, "%s", "ERP chain at END of ERP-ACTION");
-       {
-               struct dasd_ccw_req *temp_erp = NULL;
+       if (device->features & DASD_FEATURE_ERPLOG) {
+               /* print current erp_chain */
+               DEV_MESSAGE(KERN_ERR, device, "%s",
+                           "ERP chain at END of ERP-ACTION");
                for (temp_erp = erp;
                     temp_erp != NULL; temp_erp = temp_erp->refers) {
 
@@ -2709,7 +2705,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                                    temp_erp->refers);
                }
        }
-#endif                         /* ERP_DEBUG */
 
        if (erp->status == DASD_CQR_FAILED)
                dasd_log_ccw(erp, 1, cpa);
index 17fdd8c..5943266 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "dasd_int.h"
 
-kmem_cache_t *dasd_page_cache;
+struct kmem_cache *dasd_page_cache;
 EXPORT_SYMBOL_GPL(dasd_page_cache);
 
 /*
@@ -202,6 +202,8 @@ dasd_feature_list(char *str, char **endp)
                        features |= DASD_FEATURE_READONLY;
                else if (len == 4 && !strncmp(str, "diag", 4))
                        features |= DASD_FEATURE_USEDIAG;
+               else if (len == 6 && !strncmp(str, "erplog", 6))
+                       features |= DASD_FEATURE_ERPLOG;
                else {
                        MESSAGE(KERN_WARNING,
                                "unsupported feature: %*s, "
@@ -709,6 +711,52 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
 }
 
 static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
+/*
+ * erplog controls the logging of ERP related data
+ * (e.g. failing channel programs).
+ */
+static ssize_t
+dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct dasd_devmap *devmap;
+       int erplog;
+
+       devmap = dasd_find_busid(dev->bus_id);
+       if (!IS_ERR(devmap))
+               erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
+       else
+               erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
+       return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
+}
+
+static ssize_t
+dasd_erplog_store(struct device *dev, struct device_attribute *attr,
+             const char *buf, size_t count)
+{
+       struct dasd_devmap *devmap;
+       int val;
+       char *endp;
+
+       devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+       if (IS_ERR(devmap))
+               return PTR_ERR(devmap);
+
+       val = simple_strtoul(buf, &endp, 0);
+       if (((endp + 1) < (buf + count)) || (val > 1))
+               return -EINVAL;
+
+       spin_lock(&dasd_devmap_lock);
+       if (val)
+               devmap->features |= DASD_FEATURE_ERPLOG;
+       else
+               devmap->features &= ~DASD_FEATURE_ERPLOG;
+       if (devmap->device)
+               devmap->device->features = devmap->features;
+       spin_unlock(&dasd_devmap_lock);
+       return count;
+}
+
+static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
 
 /*
  * use_diag controls whether the driver should use diag rather than ssch
@@ -896,6 +944,7 @@ static struct attribute * dasd_attrs[] = {
        &dev_attr_uid.attr,
        &dev_attr_use_diag.attr,
        &dev_attr_eer_enabled.attr,
+       &dev_attr_erplog.attr,
        NULL,
 };
 
index 5ecea3e..fdaa471 100644 (file)
@@ -1215,7 +1215,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
                dst = page_address(bv->bv_page) + bv->bv_offset;
                if (dasd_page_cache) {
                        char *copy = kmem_cache_alloc(dasd_page_cache,
-                                                     SLAB_DMA | __GFP_NOWARN);
+                                                     GFP_DMA | __GFP_NOWARN);
                        if (copy && rq_data_dir(req) == WRITE)
                                memcpy(copy + bv->bv_offset, dst, bv->bv_len);
                        if (copy)
index 80926c5..b857fd5 100644 (file)
@@ -308,7 +308,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
                dst = page_address(bv->bv_page) + bv->bv_offset;
                if (dasd_page_cache) {
                        char *copy = kmem_cache_alloc(dasd_page_cache,
-                                                     SLAB_DMA | __GFP_NOWARN);
+                                                     GFP_DMA | __GFP_NOWARN);
                        if (copy && rq_data_dir(req) == WRITE)
                                memcpy(copy + bv->bv_offset, dst, bv->bv_len);
                        if (copy)
index 9f52004..fb725e3 100644 (file)
 
 #ifdef __KERNEL__
 
-/* erp debugging in dasd.c and dasd_3990_erp.c */
-#define ERP_DEBUG
-
-
 /* we keep old device allocation scheme; IOW, minors are still in 0..255 */
 #define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS))
 #define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
@@ -474,7 +470,7 @@ extern struct dasd_profile_info_t dasd_global_profile;
 extern unsigned int dasd_profile_level;
 extern struct block_device_operations dasd_device_operations;
 
-extern kmem_cache_t *dasd_page_cache;
+extern struct kmem_cache *dasd_page_cache;
 
 struct dasd_ccw_req *
 dasd_kmalloc_request(char *, int, int, struct dasd_device *);
index 8fed360..758cfb5 100644 (file)
@@ -430,7 +430,7 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int rval;
 
        lock_kernel();
-       rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+       rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
        unlock_kernel();
 
        return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
index 49e9628..c6cbcb3 100644 (file)
 
 #ifdef CONFIG_MAGIC_SYSRQ
 static int ctrlchar_sysrq_key;
+static struct tty_struct *sysrq_tty;
 
 static void
-ctrlchar_handle_sysrq(void *tty)
+ctrlchar_handle_sysrq(struct work_struct *work)
 {
-       handle_sysrq(ctrlchar_sysrq_key, (struct tty_struct *) tty);
+       handle_sysrq(ctrlchar_sysrq_key, sysrq_tty);
 }
 
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, NULL);
+static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
 #endif
 
 
@@ -53,7 +54,7 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
        /* racy */
        if (len == 3 && buf[1] == '-') {
                ctrlchar_sysrq_key = buf[2];
-               ctrlchar_work.data = tty;
+               sysrq_tty = tty;
                schedule_work(&ctrlchar_work);
                return CTRLCHAR_SYSRQ;
        }
index 78f8bda..0893d30 100644 (file)
@@ -419,16 +419,20 @@ fs3270_open(struct inode *inode, struct file *filp)
        struct idal_buffer *ib;
        int minor, rc;
 
-       if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
+       if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
                return -ENODEV;
-       minor = iminor(filp->f_dentry->d_inode);
+       minor = iminor(filp->f_path.dentry->d_inode);
        /* Check for minor 0 multiplexer. */
        if (minor == 0) {
-               if (!current->signal->tty)
+               struct tty_struct *tty;
+               mutex_lock(&tty_mutex);
+               tty = get_current_tty();
+               if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
+                       mutex_unlock(&tty_mutex);
                        return -ENODEV;
-               if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
-                       return -ENODEV;
-               minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+               }
+               minor = tty->index + RAW3270_FIRSTMINOR;
+               mutex_unlock(&tty_mutex);
        }
        /* Check if some other program is already using fullscreen mode. */
        fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
index 6f43e04..2d173e5 100644 (file)
@@ -60,8 +60,6 @@ static unsigned short int sclp_tty_chars_count;
 
 struct tty_driver *sclp_tty_driver;
 
-extern struct termios  tty_std_termios;
-
 static struct sclp_ioctls sclp_ioctls;
 static struct sclp_ioctls sclp_ioctls_init =
 {
index 1f4c899..c9f1c4c 100644 (file)
@@ -179,6 +179,7 @@ struct tape_char_data {
 /* Block Frontend Data */
 struct tape_blk_data
 {
+       struct tape_device *    device;
        /* Block device request queue. */
        request_queue_t *       request_queue;
        spinlock_t              request_queue_lock;
@@ -240,7 +241,7 @@ struct tape_device {
 #endif
 
        /* Function to start or stop the next request later. */
-       struct work_struct              tape_dnr;
+       struct delayed_work             tape_dnr;
 };
 
 /* Externals from tape_core.c */
index 7b95dab..e765875 100644 (file)
@@ -95,6 +95,12 @@ tape_34xx_medium_sense(struct tape_device *device)
        return rc;
 }
 
+struct tape_34xx_work {
+       struct tape_device      *device;
+       enum tape_op             op;
+       struct work_struct       work;
+};
+
 /*
  * These functions are currently used only to schedule a medium_sense for
  * later execution. This is because we get an interrupt whenever a medium
@@ -103,13 +109,10 @@ tape_34xx_medium_sense(struct tape_device *device)
  * interrupt handler.
  */
 static void
-tape_34xx_work_handler(void *data)
+tape_34xx_work_handler(struct work_struct *work)
 {
-       struct {
-               struct tape_device      *device;
-               enum tape_op             op;
-               struct work_struct       work;
-       } *p = data;
+       struct tape_34xx_work *p =
+               container_of(work, struct tape_34xx_work, work);
 
        switch(p->op) {
                case TO_MSEN:
@@ -126,17 +129,13 @@ tape_34xx_work_handler(void *data)
 static int
 tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
 {
-       struct {
-               struct tape_device      *device;
-               enum tape_op             op;
-               struct work_struct       work;
-       } *p;
+       struct tape_34xx_work *p;
 
        if ((p = kmalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
                return -ENOMEM;
 
        memset(p, 0, sizeof(*p));
-       INIT_WORK(&p->work, tape_34xx_work_handler, p);
+       INIT_WORK(&p->work, tape_34xx_work_handler);
 
        p->device = tape_get_device_reference(device);
        p->op     = op;
index 928cbef..9df912f 100644 (file)
@@ -236,9 +236,10 @@ struct work_handler_data {
 };
 
 static void
-tape_3590_work_handler(void *data)
+tape_3590_work_handler(struct work_struct *work)
 {
-       struct work_handler_data *p = data;
+       struct work_handler_data *p =
+               container_of(work, struct work_handler_data, work);
 
        switch (p->op) {
        case TO_MSEN:
@@ -263,7 +264,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
        if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
                return -ENOMEM;
 
-       INIT_WORK(&p->work, tape_3590_work_handler, p);
+       INIT_WORK(&p->work, tape_3590_work_handler);
 
        p->device = tape_get_device_reference(device);
        p->op = op;
index 3225fcd..c8a89b3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
+#include <linux/kernel.h>
 
 #include <asm/debug.h>
 
@@ -143,7 +144,8 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
  * queue.
  */
 static void
-tapeblock_requeue(void *data) {
+tapeblock_requeue(struct work_struct *work) {
+       struct tape_blk_data *  blkdat;
        struct tape_device *    device;
        request_queue_t *       queue;
        int                     nr_queued;
@@ -151,7 +153,8 @@ tapeblock_requeue(void *data) {
        struct list_head *      l;
        int                     rc;
 
-       device = (struct tape_device *) data;
+       blkdat = container_of(work, struct tape_blk_data, requeue_task);
+       device = blkdat->device;
        if (!device)
                return;
 
@@ -212,6 +215,7 @@ tapeblock_setup_device(struct tape_device * device)
        int                     rc;
 
        blkdat = &device->blk_data;
+       blkdat->device = device;
        spin_lock_init(&blkdat->request_queue_lock);
        atomic_set(&blkdat->requeue_scheduled, 0);
 
@@ -255,8 +259,8 @@ tapeblock_setup_device(struct tape_device * device)
 
        add_disk(disk);
 
-       INIT_WORK(&blkdat->requeue_task, tapeblock_requeue,
-               tape_get_device_reference(device));
+       tape_get_device_reference(device);
+       INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);
 
        return 0;
 
@@ -271,7 +275,7 @@ void
 tapeblock_cleanup_device(struct tape_device *device)
 {
        flush_scheduled_work();
-       device->blk_data.requeue_task.data = tape_put_device(device);
+       tape_put_device(device);
 
        if (!device->blk_data.disk) {
                PRINT_ERR("(%s): No gendisk to clean up!\n",
index 97f7523..31198c8 100644 (file)
@@ -298,13 +298,13 @@ tapechar_open (struct inode *inode, struct file *filp)
        int minor, rc;
 
        DBF_EVENT(6, "TCHAR:open: %i:%i\n",
-               imajor(filp->f_dentry->d_inode),
-               iminor(filp->f_dentry->d_inode));
+               imajor(filp->f_path.dentry->d_inode),
+               iminor(filp->f_path.dentry->d_inode));
 
-       if (imajor(filp->f_dentry->d_inode) != tapechar_major)
+       if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
                return -ENODEV;
 
-       minor = iminor(filp->f_dentry->d_inode);
+       minor = iminor(filp->f_path.dentry->d_inode);
        device = tape_get_device(minor / TAPE_MINORS_PER_DEV);
        if (IS_ERR(device)) {
                DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n");
index 2826aed..c6c2e91 100644 (file)
@@ -28,7 +28,7 @@
 #define PRINTK_HEADER "TAPE_CORE: "
 
 static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
-static void tape_delayed_next_request(void * data);
+static void tape_delayed_next_request(struct work_struct *);
 
 /*
  * One list to contain all tape devices of all disciplines, so
@@ -272,7 +272,7 @@ __tape_cancel_io(struct tape_device *device, struct tape_request *request)
                                return 0;
                        case -EBUSY:
                                request->status = TAPE_REQUEST_CANCEL;
-                               schedule_work(&device->tape_dnr);
+                               schedule_delayed_work(&device->tape_dnr, 0);
                                return 0;
                        case -ENODEV:
                                DBF_EXCEPTION(2, "device gone, retry\n");
@@ -470,7 +470,7 @@ tape_alloc_device(void)
        *device->modeset_byte = 0;
        device->first_minor = -1;
        atomic_set(&device->ref_count, 1);
-       INIT_WORK(&device->tape_dnr, tape_delayed_next_request, device);
+       INIT_DELAYED_WORK(&device->tape_dnr, tape_delayed_next_request);
 
        return device;
 }
@@ -724,7 +724,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
        } else if (rc == -EBUSY) {
                /* The common I/O subsystem is currently busy. Retry later. */
                request->status = TAPE_REQUEST_QUEUED;
-               schedule_work(&device->tape_dnr);
+               schedule_delayed_work(&device->tape_dnr, 0);
                rc = 0;
        } else {
                /* Start failed. Remove request and indicate failure. */
@@ -790,11 +790,11 @@ __tape_start_next_request(struct tape_device *device)
 }
 
 static void
-tape_delayed_next_request(void *data)
+tape_delayed_next_request(struct work_struct *work)
 {
-       struct tape_device *    device;
+       struct tape_device *device =
+               container_of(work, struct tape_device, tape_dnr.work);
 
-       device = (struct tape_device *) data;
        DBF_LH(6, "tape_delayed_next_request(%p)\n", device);
        spin_lock_irq(get_ccwdev_lock(device->cdev));
        __tape_start_next_request(device);
index 4717c36..0984462 100644 (file)
@@ -1659,7 +1659,7 @@ tty3270_flush_buffer(struct tty_struct *tty)
  * Check for visible/invisible input switches
  */
 static void
-tty3270_set_termios(struct tty_struct *tty, struct termios *old)
+tty3270_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
        struct tty3270 *tp;
        int new;
index dbfb77b..cbab8d2 100644 (file)
@@ -183,7 +183,7 @@ css_get_ssd_info(struct subchannel *sch)
        page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!page)
                return -ENOMEM;
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        ret = chsc_get_sch_desc_irq(sch, page);
        if (ret) {
                static int cio_chsc_err_msg;
@@ -197,7 +197,7 @@ css_get_ssd_info(struct subchannel *sch)
                        cio_chsc_err_msg = 1;
                }
        }
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        free_page((unsigned long)page);
        if (!ret) {
                int j, chpid, mask;
@@ -233,7 +233,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
        if (j >= 8)
                return 0;
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
 
        stsch(sch->schid, &schib);
        if (!schib.pmcw.dnv)
@@ -265,10 +265,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
        else if (sch->lpm == mask)
                goto out_unreg;
 out_unlock:
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        return 0;
 out_unreg:
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        sch->lpm = 0;
        if (css_enqueue_subchannel_slow(sch->schid)) {
                css_clear_subchannel_slow_list();
@@ -378,12 +378,12 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
                /* Check if a subchannel is newly available. */
                return s390_process_res_acc_new_sch(schid);
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
 
        chp_mask = s390_process_res_acc_sch(res_data, sch);
 
        if (chp_mask == 0) {
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                put_device(&sch->dev);
                return 0;
        }
@@ -397,7 +397,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
        else if (sch->driver && sch->driver->verify)
                sch->driver->verify(&sch->dev);
 
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        put_device(&sch->dev);
        return 0;
 }
@@ -635,21 +635,21 @@ __chp_add(struct subchannel_id schid, void *data)
        if (!sch)
                /* Check if the subchannel is now available. */
                return __chp_add_new_sch(schid);
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        for (i=0; i<8; i++) {
                mask = 0x80 >> i;
                if ((sch->schib.pmcw.pim & mask) &&
                    (sch->schib.pmcw.chpid[i] == chp->id)) {
                        if (stsch(sch->schid, &sch->schib) != 0) {
                                /* Endgame. */
-                               spin_unlock_irq(&sch->lock);
+                               spin_unlock_irq(sch->lock);
                                return -ENXIO;
                        }
                        break;
                }
        }
        if (i==8) {
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                return 0;
        }
        sch->lpm = ((sch->schib.pmcw.pim &
@@ -660,7 +660,7 @@ __chp_add(struct subchannel_id schid, void *data)
        if (sch->driver && sch->driver->verify)
                sch->driver->verify(&sch->dev);
 
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        put_device(&sch->dev);
        return 0;
 }
@@ -750,7 +750,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
        if (!sch->ssd_info.valid)
                return;
        
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        old_lpm = sch->lpm;
        for (chp = 0; chp < 8; chp++) {
                if (sch->ssd_info.chpid[chp] != chpid)
@@ -785,7 +785,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
                        sch->driver->verify(&sch->dev);
                break;
        }
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
 }
 
 static int
index 20aee27..7835a71 100644 (file)
@@ -143,11 +143,11 @@ cio_tpi(void)
                return 1;
        local_bh_disable();
        irq_enter ();
-       spin_lock(&sch->lock);
+       spin_lock(sch->lock);
        memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
        if (sch->driver && sch->driver->irq)
                sch->driver->irq(&sch->dev);
-       spin_unlock(&sch->lock);
+       spin_unlock(sch->lock);
        irq_exit ();
        _local_bh_enable();
        return 1;
@@ -415,6 +415,8 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
        CIO_TRACE_EVENT (2, "ensch");
        CIO_TRACE_EVENT (2, sch->dev.bus_id);
 
+       if (sch_is_pseudo_sch(sch))
+               return -EINVAL;
        ccode = stsch (sch->schid, &sch->schib);
        if (ccode)
                return -ENODEV;
@@ -462,6 +464,8 @@ cio_disable_subchannel (struct subchannel *sch)
        CIO_TRACE_EVENT (2, "dissch");
        CIO_TRACE_EVENT (2, sch->dev.bus_id);
 
+       if (sch_is_pseudo_sch(sch))
+               return 0;
        ccode = stsch (sch->schid, &sch->schib);
        if (ccode == 3)         /* Not operational. */
                return -ENODEV;
@@ -496,6 +500,15 @@ cio_disable_subchannel (struct subchannel *sch)
        return ret;
 }
 
+int cio_create_sch_lock(struct subchannel *sch)
+{
+       sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+       if (!sch->lock)
+               return -ENOMEM;
+       spin_lock_init(sch->lock);
+       return 0;
+}
+
 /*
  * cio_validate_subchannel()
  *
@@ -513,6 +526,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
 {
        char dbf_txt[15];
        int ccode;
+       int err;
 
        sprintf (dbf_txt, "valsch%x", schid.sch_no);
        CIO_TRACE_EVENT (4, dbf_txt);
@@ -520,9 +534,15 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        /* Nuke all fields. */
        memset(sch, 0, sizeof(struct subchannel));
 
-       spin_lock_init(&sch->lock);
+       sch->schid = schid;
+       if (cio_is_console(schid)) {
+               sch->lock = cio_get_console_lock();
+       } else {
+               err = cio_create_sch_lock(sch);
+               if (err)
+                       goto out;
+       }
        mutex_init(&sch->reg_mutex);
-
        /* Set a name for the subchannel */
        snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
                  schid.sch_no);
@@ -534,10 +554,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
         *  is not valid.
         */
        ccode = stsch_err (schid, &sch->schib);
-       if (ccode)
-               return (ccode == 3) ? -ENXIO : ccode;
-
-       sch->schid = schid;
+       if (ccode) {
+               err = (ccode == 3) ? -ENXIO : ccode;
+               goto out;
+       }
        /* Copy subchannel type from path management control word. */
        sch->st = sch->schib.pmcw.st;
 
@@ -550,14 +570,16 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
                          "non-I/O subchannel type %04X\n",
                          sch->schid.ssid, sch->schid.sch_no, sch->st);
                /* We stop here for non-io subchannels. */
-               return sch->st;
+               err = sch->st;
+               goto out;
        }
 
        /* Initialization for io subchannels. */
-       if (!sch->schib.pmcw.dnv)
+       if (!sch->schib.pmcw.dnv) {
                /* io subchannel but device number is invalid. */
-               return -ENODEV;
-
+               err = -ENODEV;
+               goto out;
+       }
        /* Devno is valid. */
        if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
                /*
@@ -567,7 +589,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
                CIO_MSG_EVENT(0, "Blacklisted device detected "
                              "at devno %04X, subchannel set %x\n",
                              sch->schib.pmcw.dev, sch->schid.ssid);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out;
        }
        sch->opm = 0xff;
        if (!cio_is_console(sch->schid))
@@ -595,6 +618,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        if ((sch->lpm & (sch->lpm - 1)) != 0)
                sch->schib.pmcw.mp = 1; /* multipath mode */
        return 0;
+out:
+       if (!cio_is_console(schid))
+               kfree(sch->lock);
+       sch->lock = NULL;
+       return err;
 }
 
 /*
@@ -637,7 +665,7 @@ do_IRQ (struct pt_regs *regs)
                }
                sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
                if (sch)
-                       spin_lock(&sch->lock);
+                       spin_lock(sch->lock);
                /* Store interrupt response block to lowcore. */
                if (tsch (tpi_info->schid, irb) == 0 && sch) {
                        /* Keep subchannel information word up to date. */
@@ -648,7 +676,7 @@ do_IRQ (struct pt_regs *regs)
                                sch->driver->irq(&sch->dev);
                }
                if (sch)
-                       spin_unlock(&sch->lock);
+                       spin_unlock(sch->lock);
                /*
                 * Are more interrupts pending?
                 * If so, the tpi instruction will update the lowcore
@@ -687,10 +715,10 @@ wait_cons_dev (void)
        __ctl_load (cr6, 6, 6);
 
        do {
-               spin_unlock(&console_subchannel.lock);
+               spin_unlock(console_subchannel.lock);
                if (!cio_tpi())
                        cpu_relax();
-               spin_lock(&console_subchannel.lock);
+               spin_lock(console_subchannel.lock);
        } while (console_subchannel.schib.scsw.actl != 0);
        /*
         * restore previous isc value
index 4541c1a..35154a2 100644 (file)
@@ -87,7 +87,7 @@ struct orb {
 /* subchannel data structure used by I/O subroutines */
 struct subchannel {
        struct subchannel_id schid;
-       spinlock_t lock;        /* subchannel lock */
+       spinlock_t *lock;       /* subchannel lock */
        struct mutex reg_mutex;
        enum {
                SUBCHANNEL_TYPE_IO = 0,
@@ -131,15 +131,19 @@ extern int cio_set_options (struct subchannel *, int);
 extern int cio_get_options (struct subchannel *);
 extern int cio_modify (struct subchannel *);
 
+int cio_create_sch_lock(struct subchannel *);
+
 /* Use with care. */
 #ifdef CONFIG_CCW_CONSOLE
 extern struct subchannel *cio_probe_console(void);
 extern void cio_release_console(void);
 extern int cio_is_console(struct subchannel_id);
 extern struct subchannel *cio_get_console_subchannel(void);
+extern spinlock_t * cio_get_console_lock(void);
 #else
 #define cio_is_console(schid) 0
 #define cio_get_console_subchannel() NULL
+#define cio_get_console_lock() NULL;
 #endif
 
 extern int cio_show_msg;
index ad7f7e1..4c81d89 100644 (file)
@@ -91,9 +91,9 @@ css_free_subchannel(struct subchannel *sch)
                /* Reset intparm to zeroes. */
                sch->schib.pmcw.intparm = 0;
                cio_modify(sch);
+               kfree(sch->lock);
                kfree(sch);
        }
-       
 }
 
 static void
@@ -102,8 +102,10 @@ css_subchannel_release(struct device *dev)
        struct subchannel *sch;
 
        sch = to_subchannel(dev);
-       if (!cio_is_console(sch->schid))
+       if (!cio_is_console(sch->schid)) {
+               kfree(sch->lock);
                kfree(sch);
+       }
 }
 
 extern int css_get_ssd_info(struct subchannel *sch);
@@ -135,14 +137,16 @@ css_register_subchannel(struct subchannel *sch)
        sch->dev.parent = &css[0]->device;
        sch->dev.bus = &css_bus_type;
        sch->dev.release = &css_subchannel_release;
-       
+       sch->dev.groups = subch_attr_groups;
+
        /* make it known to the system */
        ret = css_sch_device_register(sch);
-       if (ret)
+       if (ret) {
                printk (KERN_WARNING "%s: could not register %s\n",
                        __func__, sch->dev.bus_id);
-       else
-               css_get_ssd_info(sch);
+               return ret;
+       }
+       css_get_ssd_info(sch);
        return ret;
 }
 
@@ -201,18 +205,18 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
        unsigned long flags;
        enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action;
 
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        disc = device_is_disconnected(sch);
        if (disc && slow) {
                /* Disconnected devices are evaluated directly only.*/
-               spin_unlock_irqrestore(&sch->lock, flags);
+               spin_unlock_irqrestore(sch->lock, flags);
                return 0;
        }
        /* No interrupt after machine check - kill pending timers. */
        device_kill_pending_timer(sch);
        if (!disc && !slow) {
                /* Non-disconnected devices are evaluated on the slow path. */
-               spin_unlock_irqrestore(&sch->lock, flags);
+               spin_unlock_irqrestore(sch->lock, flags);
                return -EAGAIN;
        }
        event = css_get_subchannel_status(sch);
@@ -237,9 +241,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
                /* Ask driver what to do with device. */
                action = UNREGISTER;
                if (sch->driver && sch->driver->notify) {
-                       spin_unlock_irqrestore(&sch->lock, flags);
+                       spin_unlock_irqrestore(sch->lock, flags);
                        ret = sch->driver->notify(&sch->dev, event);
-                       spin_lock_irqsave(&sch->lock, flags);
+                       spin_lock_irqsave(sch->lock, flags);
                        if (ret)
                                action = NONE;
                }
@@ -264,9 +268,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
        case UNREGISTER:
        case UNREGISTER_PROBE:
                /* Unregister device (will use subchannel lock). */
-               spin_unlock_irqrestore(&sch->lock, flags);
+               spin_unlock_irqrestore(sch->lock, flags);
                css_sch_device_unregister(sch);
-               spin_lock_irqsave(&sch->lock, flags);
+               spin_lock_irqsave(sch->lock, flags);
 
                /* Reset intparm to zeroes. */
                sch->schib.pmcw.intparm = 0;
@@ -278,7 +282,7 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
        default:
                break;
        }
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
        /* Probe if necessary. */
        if (action == UNREGISTER_PROBE)
                ret = css_probe_device(sch->schid);
@@ -334,7 +338,7 @@ static LIST_HEAD(slow_subchannels_head);
 static DEFINE_SPINLOCK(slow_subchannel_lock);
 
 static void
-css_trigger_slow_path(void)
+css_trigger_slow_path(struct work_struct *unused)
 {
        CIO_TRACE_EVENT(4, "slowpath");
 
@@ -359,8 +363,7 @@ css_trigger_slow_path(void)
        spin_unlock_irq(&slow_subchannel_lock);
 }
 
-typedef void (*workfunc)(void *);
-DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL);
+DECLARE_WORK(slow_path_work, css_trigger_slow_path);
 struct workqueue_struct *slow_path_wq;
 
 /* Reprobe subchannel if unregistered. */
@@ -397,7 +400,7 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
 }
 
 /* Work function used to reprobe all unregistered subchannels. */
-static void reprobe_all(void *data)
+static void reprobe_all(struct work_struct *unused)
 {
        int ret;
 
@@ -413,7 +416,7 @@ static void reprobe_all(void *data)
                      need_reprobe);
 }
 
-DECLARE_WORK(css_reprobe_work, reprobe_all, NULL);
+DECLARE_WORK(css_reprobe_work, reprobe_all);
 
 /* Schedule reprobing of all unregistered subchannels. */
 void css_schedule_reprobe(void)
@@ -574,12 +577,24 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store);
 
-static inline void __init
-setup_css(int nr)
+static inline int __init setup_css(int nr)
 {
        u32 tod_high;
+       int ret;
 
        memset(css[nr], 0, sizeof(struct channel_subsystem));
+       css[nr]->pseudo_subchannel =
+               kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL);
+       if (!css[nr]->pseudo_subchannel)
+               return -ENOMEM;
+       css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device;
+       css[nr]->pseudo_subchannel->dev.release = css_subchannel_release;
+       sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct");
+       ret = cio_create_sch_lock(css[nr]->pseudo_subchannel);
+       if (ret) {
+               kfree(css[nr]->pseudo_subchannel);
+               return ret;
+       }
        mutex_init(&css[nr]->mutex);
        css[nr]->valid = 1;
        css[nr]->cssid = nr;
@@ -587,6 +602,7 @@ setup_css(int nr)
        css[nr]->device.release = channel_subsystem_release;
        tod_high = (u32) (get_clock() >> 32);
        css_generate_pgid(css[nr], tod_high);
+       return 0;
 }
 
 /*
@@ -623,10 +639,12 @@ init_channel_subsystem (void)
                        ret = -ENOMEM;
                        goto out_unregister;
                }
-               setup_css(i);
-               ret = device_register(&css[i]->device);
+               ret = setup_css(i);
                if (ret)
                        goto out_free;
+               ret = device_register(&css[i]->device);
+               if (ret)
+                       goto out_free_all;
                if (css_characteristics_avail &&
                    css_chsc_characteristics.secm) {
                        ret = device_create_file(&css[i]->device,
@@ -634,6 +652,9 @@ init_channel_subsystem (void)
                        if (ret)
                                goto out_device;
                }
+               ret = device_register(&css[i]->pseudo_subchannel->dev);
+               if (ret)
+                       goto out_file;
        }
        css_init_done = 1;
 
@@ -641,13 +662,19 @@ init_channel_subsystem (void)
 
        for_each_subchannel(__init_channel_subsystem, NULL);
        return 0;
+out_file:
+       device_remove_file(&css[i]->device, &dev_attr_cm_enable);
 out_device:
        device_unregister(&css[i]->device);
+out_free_all:
+       kfree(css[i]->pseudo_subchannel->lock);
+       kfree(css[i]->pseudo_subchannel);
 out_free:
        kfree(css[i]);
 out_unregister:
        while (i > 0) {
                i--;
+               device_unregister(&css[i]->pseudo_subchannel->dev);
                if (css_characteristics_avail && css_chsc_characteristics.secm)
                        device_remove_file(&css[i]->device,
                                           &dev_attr_cm_enable);
@@ -659,6 +686,11 @@ out:
        return ret;
 }
 
+int sch_is_pseudo_sch(struct subchannel *sch)
+{
+       return sch == to_css(sch->dev.parent)->pseudo_subchannel;
+}
+
 /*
  * find a driver for a subchannel. They identify by the subchannel
  * type with the exception that the console subchannel driver has its own
index 9ff064e..3464c5b 100644 (file)
@@ -73,6 +73,8 @@ struct senseid {
 }  __attribute__ ((packed,aligned(4)));
 
 struct ccw_device_private {
+       struct ccw_device *cdev;
+       struct subchannel *sch;
        int state;              /* device state */
        atomic_t onoff;
        unsigned long registered;
@@ -158,6 +160,8 @@ struct channel_subsystem {
        int cm_enabled;
        void *cub_addr1;
        void *cub_addr2;
+       /* for orphaned ccw devices */
+       struct subchannel *pseudo_subchannel;
 };
 #define to_css(dev) container_of(dev, struct channel_subsystem, device)
 
@@ -185,6 +189,11 @@ void css_clear_subchannel_slow_list(void);
 int css_slow_subchannels_exist(void);
 extern int need_rescan;
 
+int sch_is_pseudo_sch(struct subchannel *);
+
 extern struct workqueue_struct *slow_path_wq;
 extern struct work_struct slow_path_work;
+
+int subchannel_add_files (struct device *);
+extern struct attribute_group *subch_attr_groups[];
 #endif
index d3d3716..8035790 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/param.h>         /* HZ */
 
 #include "cio.h"
+#include "cio_debug.h"
 #include "css.h"
 #include "device.h"
 #include "ioasm.h"
@@ -234,9 +235,11 @@ chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
        ssize_t ret = 0;
        int chp;
 
-       for (chp = 0; chp < 8; chp++)
-               ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
-
+       if (ssd)
+               for (chp = 0; chp < 8; chp++)
+                       ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
+       else
+               ret += sprintf (buf, "n/a");
        ret += sprintf (buf+ret, "\n");
        return min((ssize_t)PAGE_SIZE, ret);
 }
@@ -294,14 +297,44 @@ online_show (struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, cdev->online ? "1\n" : "0\n");
 }
 
+int ccw_device_is_orphan(struct ccw_device *cdev)
+{
+       return sch_is_pseudo_sch(to_subchannel(cdev->dev.parent));
+}
+
+static void ccw_device_unregister(struct work_struct *work)
+{
+       struct ccw_device_private *priv;
+       struct ccw_device *cdev;
+
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
+       if (test_and_clear_bit(1, &cdev->private->registered))
+               device_unregister(&cdev->dev);
+       put_device(&cdev->dev);
+}
+
 static void
 ccw_device_remove_disconnected(struct ccw_device *cdev)
 {
        struct subchannel *sch;
+       unsigned long flags;
        /*
         * Forced offline in disconnected state means
         * 'throw away device'.
         */
+       if (ccw_device_is_orphan(cdev)) {
+               /* Deregister ccw device. */
+               spin_lock_irqsave(cdev->ccwlock, flags);
+               cdev->private->state = DEV_STATE_NOT_OPER;
+               spin_unlock_irqrestore(cdev->ccwlock, flags);
+               if (get_device(&cdev->dev)) {
+                       PREPARE_WORK(&cdev->private->kick_work,
+                                    ccw_device_unregister);
+                       queue_work(ccw_device_work, &cdev->private->kick_work);
+               }
+               return ;
+       }
        sch = to_subchannel(cdev->dev.parent);
        css_sch_device_unregister(sch);
        /* Reset intparm to zeroes. */
@@ -462,6 +495,8 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf)
        struct ccw_device *cdev = to_ccwdev(dev);
        struct subchannel *sch;
 
+       if (ccw_device_is_orphan(cdev))
+               return sprintf(buf, "no device\n");
        switch (cdev->private->state) {
        case DEV_STATE_BOXED:
                return sprintf(buf, "boxed\n");
@@ -498,11 +533,10 @@ static struct attribute_group subch_attr_group = {
        .attrs = subch_attrs,
 };
 
-static inline int
-subchannel_add_files (struct device *dev)
-{
-       return sysfs_create_group(&dev->kobj, &subch_attr_group);
-}
+struct attribute_group *subch_attr_groups[] = {
+       &subch_attr_group,
+       NULL,
+};
 
 static struct attribute * ccwdev_attrs[] = {
        &dev_attr_devtype.attr,
@@ -563,11 +597,10 @@ match_devno(struct device * dev, void * data)
 
        cdev = to_ccwdev(dev);
        if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
+           !ccw_device_is_orphan(cdev) &&
            ccw_dev_id_is_equal(&cdev->private->dev_id, &d->dev_id) &&
-           (cdev != d->sibling)) {
-               cdev->private->state = DEV_STATE_NOT_OPER;
+           (cdev != d->sibling))
                return 1;
-       }
        return 0;
 }
 
@@ -584,13 +617,36 @@ static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
        return dev ? to_ccwdev(dev) : NULL;
 }
 
-static void
-ccw_device_add_changed(void *data)
+static int match_orphan(struct device *dev, void *data)
+{
+       struct ccw_dev_id *dev_id;
+       struct ccw_device *cdev;
+
+       dev_id = data;
+       cdev = to_ccwdev(dev);
+       return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
+}
+
+static struct ccw_device *
+get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
+                             struct ccw_dev_id *dev_id)
 {
+       struct device *dev;
 
+       dev = device_find_child(&css->pseudo_subchannel->dev, dev_id,
+                               match_orphan);
+
+       return dev ? to_ccwdev(dev) : NULL;
+}
+
+static void
+ccw_device_add_changed(struct work_struct *work)
+{
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
 
-       cdev = data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        if (device_add(&cdev->dev)) {
                put_device(&cdev->dev);
                return;
@@ -602,64 +658,21 @@ ccw_device_add_changed(void *data)
        }
 }
 
-extern int css_get_ssd_info(struct subchannel *sch);
-
-void
-ccw_device_do_unreg_rereg(void *data)
+void ccw_device_do_unreg_rereg(struct work_struct *work)
 {
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
-       int need_rename;
 
-       cdev = data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
-       if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
-               /*
-                * The device number has changed. This is usually only when
-                * a device has been detached under VM and then re-appeared
-                * on another subchannel because of a different attachment
-                * order than before. Ideally, we should should just switch
-                * subchannels, but unfortunately, this is not possible with
-                * the current implementation.
-                * Instead, we search for the old subchannel for this device
-                * number and deregister so there are no collisions with the
-                * newly registered ccw_device.
-                * FIXME: Find another solution so the block layer doesn't
-                *        get possibly sick...
-                */
-               struct ccw_device *other_cdev;
-               struct ccw_dev_id dev_id;
-
-               need_rename = 1;
-               dev_id.devno = sch->schib.pmcw.dev;
-               dev_id.ssid = sch->schid.ssid;
-               other_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
-               if (other_cdev) {
-                       struct subchannel *other_sch;
-
-                       other_sch = to_subchannel(other_cdev->dev.parent);
-                       if (get_device(&other_sch->dev)) {
-                               stsch(other_sch->schid, &other_sch->schib);
-                               if (other_sch->schib.pmcw.dnv) {
-                                       other_sch->schib.pmcw.intparm = 0;
-                                       cio_modify(other_sch);
-                               }
-                               css_sch_device_unregister(other_sch);
-                       }
-               }
-               /* Update ssd info here. */
-               css_get_ssd_info(sch);
-               cdev->private->dev_id.devno = sch->schib.pmcw.dev;
-       } else
-               need_rename = 0;
+
        device_remove_files(&cdev->dev);
        if (test_and_clear_bit(1, &cdev->private->registered))
                device_del(&cdev->dev);
-       if (need_rename)
-               snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
-                         sch->schid.ssid, sch->schib.pmcw.dev);
        PREPARE_WORK(&cdev->private->kick_work,
-                    ccw_device_add_changed, cdev);
+                    ccw_device_add_changed);
        queue_work(ccw_device_work, &cdev->private->kick_work);
 }
 
@@ -673,18 +686,194 @@ ccw_device_release(struct device *dev)
        kfree(cdev);
 }
 
+static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch)
+{
+       struct ccw_device *cdev;
+
+       cdev  = kzalloc(sizeof(*cdev), GFP_KERNEL);
+       if (cdev) {
+               cdev->private = kzalloc(sizeof(struct ccw_device_private),
+                                       GFP_KERNEL | GFP_DMA);
+               if (cdev->private)
+                       return cdev;
+       }
+       kfree(cdev);
+       return ERR_PTR(-ENOMEM);
+}
+
+static int io_subchannel_initialize_dev(struct subchannel *sch,
+                                       struct ccw_device *cdev)
+{
+       cdev->private->cdev = cdev;
+       atomic_set(&cdev->private->onoff, 0);
+       cdev->dev.parent = &sch->dev;
+       cdev->dev.release = ccw_device_release;
+       INIT_LIST_HEAD(&cdev->private->kick_work.entry);
+       /* Do first half of device_register. */
+       device_initialize(&cdev->dev);
+       if (!get_device(&sch->dev)) {
+               if (cdev->dev.release)
+                       cdev->dev.release(&cdev->dev);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
+{
+       struct ccw_device *cdev;
+       int ret;
+
+       cdev = io_subchannel_allocate_dev(sch);
+       if (!IS_ERR(cdev)) {
+               ret = io_subchannel_initialize_dev(sch, cdev);
+               if (ret) {
+                       kfree(cdev);
+                       cdev = ERR_PTR(ret);
+               }
+       }
+       return cdev;
+}
+
+static int io_subchannel_recog(struct ccw_device *, struct subchannel *);
+
+static void sch_attach_device(struct subchannel *sch,
+                             struct ccw_device *cdev)
+{
+       spin_lock_irq(sch->lock);
+       sch->dev.driver_data = cdev;
+       cdev->private->schid = sch->schid;
+       cdev->ccwlock = sch->lock;
+       device_trigger_reprobe(sch);
+       spin_unlock_irq(sch->lock);
+}
+
+static void sch_attach_disconnected_device(struct subchannel *sch,
+                                          struct ccw_device *cdev)
+{
+       struct subchannel *other_sch;
+       int ret;
+
+       other_sch = to_subchannel(get_device(cdev->dev.parent));
+       ret = device_move(&cdev->dev, &sch->dev);
+       if (ret) {
+               CIO_MSG_EVENT(2, "Moving disconnected device 0.%x.%04x failed "
+                             "(ret=%d)!\n", cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno, ret);
+               put_device(&other_sch->dev);
+               return;
+       }
+       other_sch->dev.driver_data = NULL;
+       /* No need to keep a subchannel without ccw device around. */
+       css_sch_device_unregister(other_sch);
+       put_device(&other_sch->dev);
+       sch_attach_device(sch, cdev);
+}
+
+static void sch_attach_orphaned_device(struct subchannel *sch,
+                                      struct ccw_device *cdev)
+{
+       int ret;
+
+       /* Try to move the ccw device to its new subchannel. */
+       ret = device_move(&cdev->dev, &sch->dev);
+       if (ret) {
+               CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage "
+                             "failed (ret=%d)!\n",
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno, ret);
+               return;
+       }
+       sch_attach_device(sch, cdev);
+}
+
+static void sch_create_and_recog_new_device(struct subchannel *sch)
+{
+       struct ccw_device *cdev;
+
+       /* Need to allocate a new ccw device. */
+       cdev = io_subchannel_create_ccwdev(sch);
+       if (IS_ERR(cdev)) {
+               /* OK, we did everything we could... */
+               css_sch_device_unregister(sch);
+               return;
+       }
+       spin_lock_irq(sch->lock);
+       sch->dev.driver_data = cdev;
+       spin_unlock_irq(sch->lock);
+       /* Start recognition for the new ccw device. */
+       if (io_subchannel_recog(cdev, sch)) {
+               spin_lock_irq(sch->lock);
+               sch->dev.driver_data = NULL;
+               spin_unlock_irq(sch->lock);
+               if (cdev->dev.release)
+                       cdev->dev.release(&cdev->dev);
+               css_sch_device_unregister(sch);
+       }
+}
+
+
+void ccw_device_move_to_orphanage(struct work_struct *work)
+{
+       struct ccw_device_private *priv;
+       struct ccw_device *cdev;
+       struct ccw_device *replacing_cdev;
+       struct subchannel *sch;
+       int ret;
+       struct channel_subsystem *css;
+       struct ccw_dev_id dev_id;
+
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
+       sch = to_subchannel(cdev->dev.parent);
+       css = to_css(sch->dev.parent);
+       dev_id.devno = sch->schib.pmcw.dev;
+       dev_id.ssid = sch->schid.ssid;
+
+       /*
+        * Move the orphaned ccw device to the orphanage so the replacing
+        * ccw device can take its place on the subchannel.
+        */
+       ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev);
+       if (ret) {
+               CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed "
+                             "(ret=%d)!\n", cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno, ret);
+               return;
+       }
+       cdev->ccwlock = css->pseudo_subchannel->lock;
+       /*
+        * Search for the replacing ccw device
+        * - among the disconnected devices
+        * - in the orphanage
+        */
+       replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
+       if (replacing_cdev) {
+               sch_attach_disconnected_device(sch, replacing_cdev);
+               return;
+       }
+       replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id);
+       if (replacing_cdev) {
+               sch_attach_orphaned_device(sch, replacing_cdev);
+               return;
+       }
+       sch_create_and_recog_new_device(sch);
+}
+
 /*
  * Register recognized device.
  */
 static void
-io_subchannel_register(void *data)
+io_subchannel_register(struct work_struct *work)
 {
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
        unsigned long flags;
 
-       cdev = data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
 
        /*
@@ -709,9 +898,9 @@ io_subchannel_register(void *data)
                printk (KERN_WARNING "%s: could not register %s\n",
                        __func__, cdev->dev.bus_id);
                put_device(&cdev->dev);
-               spin_lock_irqsave(&sch->lock, flags);
+               spin_lock_irqsave(sch->lock, flags);
                sch->dev.driver_data = NULL;
-               spin_unlock_irqrestore(&sch->lock, flags);
+               spin_unlock_irqrestore(sch->lock, flags);
                kfree (cdev->private);
                kfree (cdev);
                put_device(&sch->dev);
@@ -719,11 +908,6 @@ io_subchannel_register(void *data)
                        wake_up(&ccw_device_init_wq);
                return;
        }
-
-       ret = subchannel_add_files(cdev->dev.parent);
-       if (ret)
-               printk(KERN_WARNING "%s: could not add attributes to %s\n",
-                      __func__, sch->dev.bus_id);
        put_device(&cdev->dev);
 out:
        cdev->private->flags.recog_done = 1;
@@ -734,11 +918,14 @@ out:
 }
 
 void
-ccw_device_call_sch_unregister(void *data)
+ccw_device_call_sch_unregister(struct work_struct *work)
 {
-       struct ccw_device *cdev = data;
+       struct ccw_device_private *priv;
+       struct ccw_device *cdev;
        struct subchannel *sch;
 
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
        css_sch_device_unregister(sch);
        /* Reset intparm to zeroes. */
@@ -768,7 +955,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
                        break;
                sch = to_subchannel(cdev->dev.parent);
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister, cdev);
+                            ccw_device_call_sch_unregister);
                queue_work(slow_path_wq, &cdev->private->kick_work);
                if (atomic_dec_and_test(&ccw_device_init_count))
                        wake_up(&ccw_device_init_wq);
@@ -783,7 +970,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
                if (!get_device(&cdev->dev))
                        break;
                PREPARE_WORK(&cdev->private->kick_work,
-                            io_subchannel_register, cdev);
+                            io_subchannel_register);
                queue_work(slow_path_wq, &cdev->private->kick_work);
                break;
        }
@@ -797,7 +984,7 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 
        sch->dev.driver_data = cdev;
        sch->driver = &io_subchannel_driver;
-       cdev->ccwlock = &sch->lock;
+       cdev->ccwlock = sch->lock;
 
        /* Init private data. */
        priv = cdev->private;
@@ -817,9 +1004,9 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
        atomic_inc(&ccw_device_init_count);
 
        /* Start async. device sensing. */
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        rc = ccw_device_recognition(cdev);
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
        if (rc) {
                if (atomic_dec_and_test(&ccw_device_init_count))
                        wake_up(&ccw_device_init_wq);
@@ -827,12 +1014,55 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
        return rc;
 }
 
+static void ccw_device_move_to_sch(struct work_struct *work)
+{
+       struct ccw_device_private *priv;
+       int rc;
+       struct subchannel *sch;
+       struct ccw_device *cdev;
+       struct subchannel *former_parent;
+
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       sch = priv->sch;
+       cdev = priv->cdev;
+       former_parent = ccw_device_is_orphan(cdev) ?
+               NULL : to_subchannel(get_device(cdev->dev.parent));
+       mutex_lock(&sch->reg_mutex);
+       /* Try to move the ccw device to its new subchannel. */
+       rc = device_move(&cdev->dev, &sch->dev);
+       mutex_unlock(&sch->reg_mutex);
+       if (rc) {
+               CIO_MSG_EVENT(2, "Moving device 0.%x.%04x to subchannel "
+                             "0.%x.%04x failed (ret=%d)!\n",
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno, sch->schid.ssid,
+                             sch->schid.sch_no, rc);
+               css_sch_device_unregister(sch);
+               goto out;
+       }
+       if (former_parent) {
+               spin_lock_irq(former_parent->lock);
+               former_parent->dev.driver_data = NULL;
+               spin_unlock_irq(former_parent->lock);
+               css_sch_device_unregister(former_parent);
+               /* Reset intparm to zeroes. */
+               former_parent->schib.pmcw.intparm = 0;
+               cio_modify(former_parent);
+       }
+       sch_attach_device(sch, cdev);
+out:
+       if (former_parent)
+               put_device(&former_parent->dev);
+       put_device(&cdev->dev);
+}
+
 static int
 io_subchannel_probe (struct subchannel *sch)
 {
        struct ccw_device *cdev;
        int rc;
        unsigned long flags;
+       struct ccw_dev_id dev_id;
 
        if (sch->dev.driver_data) {
                /*
@@ -843,7 +1073,6 @@ io_subchannel_probe (struct subchannel *sch)
                cdev = sch->dev.driver_data;
                device_initialize(&cdev->dev);
                ccw_device_register(cdev);
-               subchannel_add_files(&sch->dev);
                /*
                 * Check if the device is already online. If it is
                 * the reference count needs to be corrected
@@ -856,33 +1085,37 @@ io_subchannel_probe (struct subchannel *sch)
                        get_device(&cdev->dev);
                return 0;
        }
-       cdev = kzalloc (sizeof(*cdev), GFP_KERNEL);
+       /*
+        * First check if a fitting device may be found amongst the
+        * disconnected devices or in the orphanage.
+        */
+       dev_id.devno = sch->schib.pmcw.dev;
+       dev_id.ssid = sch->schid.ssid;
+       cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
        if (!cdev)
-               return -ENOMEM;
-       cdev->private = kzalloc(sizeof(struct ccw_device_private),
-                               GFP_KERNEL | GFP_DMA);
-       if (!cdev->private) {
-               kfree(cdev);
-               return -ENOMEM;
-       }
-       atomic_set(&cdev->private->onoff, 0);
-       cdev->dev.parent = &sch->dev;
-       cdev->dev.release = ccw_device_release;
-       INIT_LIST_HEAD(&cdev->private->kick_work.entry);
-       /* Do first half of device_register. */
-       device_initialize(&cdev->dev);
-
-       if (!get_device(&sch->dev)) {
-               if (cdev->dev.release)
-                       cdev->dev.release(&cdev->dev);
-               return -ENODEV;
+               cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
+                                                    &dev_id);
+       if (cdev) {
+               /*
+                * Schedule moving the device until when we have a registered
+                * subchannel to move to and succeed the probe. We can
+                * unregister later again, when the probe is through.
+                */
+               cdev->private->sch = sch;
+               PREPARE_WORK(&cdev->private->kick_work,
+                            ccw_device_move_to_sch);
+               queue_work(slow_path_wq, &cdev->private->kick_work);
+               return 0;
        }
+       cdev = io_subchannel_create_ccwdev(sch);
+       if (IS_ERR(cdev))
+               return PTR_ERR(cdev);
 
        rc = io_subchannel_recog(cdev, sch);
        if (rc) {
-               spin_lock_irqsave(&sch->lock, flags);
+               spin_lock_irqsave(sch->lock, flags);
                sch->dev.driver_data = NULL;
-               spin_unlock_irqrestore(&sch->lock, flags);
+               spin_unlock_irqrestore(sch->lock, flags);
                if (cdev->dev.release)
                        cdev->dev.release(&cdev->dev);
        }
@@ -890,17 +1123,6 @@ io_subchannel_probe (struct subchannel *sch)
        return rc;
 }
 
-static void
-ccw_device_unregister(void *data)
-{
-       struct ccw_device *cdev;
-
-       cdev = (struct ccw_device *)data;
-       if (test_and_clear_bit(1, &cdev->private->registered))
-               device_unregister(&cdev->dev);
-       put_device(&cdev->dev);
-}
-
 static int
 io_subchannel_remove (struct subchannel *sch)
 {
@@ -921,7 +1143,7 @@ io_subchannel_remove (struct subchannel *sch)
         */
        if (get_device(&cdev->dev)) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_unregister, cdev);
+                            ccw_device_unregister);
                queue_work(ccw_device_work, &cdev->private->kick_work);
        }
        return 0;
@@ -1003,6 +1225,13 @@ static struct ccw_device console_cdev;
 static struct ccw_device_private console_private;
 static int console_cdev_in_use;
 
+static DEFINE_SPINLOCK(ccw_console_lock);
+
+spinlock_t * cio_get_console_lock(void)
+{
+       return &ccw_console_lock;
+}
+
 static int
 ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
 {
@@ -1048,6 +1277,7 @@ ccw_device_probe_console(void)
        memset(&console_cdev, 0, sizeof(struct ccw_device));
        memset(&console_private, 0, sizeof(struct ccw_device_private));
        console_cdev.private = &console_private;
+       console_private.cdev = &console_cdev;
        ret = ccw_device_console_enable(&console_cdev, sch);
        if (ret) {
                cio_release_console();
index 9233b5c..29db634 100644 (file)
@@ -78,8 +78,10 @@ void io_subchannel_recog_done(struct ccw_device *cdev);
 
 int ccw_device_cancel_halt_clear(struct ccw_device *);
 
-void ccw_device_do_unreg_rereg(void *);
-void ccw_device_call_sch_unregister(void *);
+void ccw_device_do_unreg_rereg(struct work_struct *);
+void ccw_device_call_sch_unregister(struct work_struct *);
+void ccw_device_move_to_orphanage(struct work_struct *);
+int ccw_device_is_orphan(struct ccw_device *);
 
 int ccw_device_recognition(struct ccw_device *);
 int ccw_device_online(struct ccw_device *);
index 09c7672..eed1457 100644 (file)
@@ -186,15 +186,14 @@ ccw_device_handle_oper(struct ccw_device *cdev)
        /*
         * Check if cu type and device type still match. If
         * not, it is certainly another device and we have to
-        * de- and re-register. Also check here for non-matching devno.
+        * de- and re-register.
         */
        if (cdev->id.cu_type != cdev->private->senseid.cu_type ||
            cdev->id.cu_model != cdev->private->senseid.cu_model ||
            cdev->id.dev_type != cdev->private->senseid.dev_type ||
-           cdev->id.dev_model != cdev->private->senseid.dev_model ||
-           cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
+           cdev->id.dev_model != cdev->private->senseid.dev_model) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_do_unreg_rereg, cdev);
+                            ccw_device_do_unreg_rereg);
                queue_work(ccw_device_work, &cdev->private->kick_work);
                return 0;
        }
@@ -329,19 +328,21 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
 }
 
 static void
-ccw_device_oper_notify(void *data)
+ccw_device_oper_notify(struct work_struct *work)
 {
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
 
-       cdev = data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
        ret = (sch->driver && sch->driver->notify) ?
                sch->driver->notify(&sch->dev, CIO_OPER) : 0;
        if (!ret)
                /* Driver doesn't want device back. */
-               ccw_device_do_unreg_rereg(cdev);
+               ccw_device_do_unreg_rereg(work);
        else {
                /* Reenable channel measurements, if needed. */
                cmf_reenable(cdev);
@@ -377,8 +378,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
 
        if (cdev->private->flags.donotify) {
                cdev->private->flags.donotify = 0;
-               PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify,
-                            cdev);
+               PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -528,13 +528,15 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
 
 
 static void
-ccw_device_nopath_notify(void *data)
+ccw_device_nopath_notify(struct work_struct *work)
 {
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
        int ret;
 
-       cdev = data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
        /* Extra sanity. */
        if (sch->lpm)
@@ -547,8 +549,7 @@ ccw_device_nopath_notify(void *data)
                        cio_disable_subchannel(sch);
                        if (get_device(&cdev->dev)) {
                                PREPARE_WORK(&cdev->private->kick_work,
-                                            ccw_device_call_sch_unregister,
-                                            cdev);
+                                            ccw_device_call_sch_unregister);
                                queue_work(ccw_device_work,
                                           &cdev->private->kick_work);
                        } else
@@ -607,7 +608,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
                /* Reset oper notify indication after verify error. */
                cdev->private->flags.donotify = 0;
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, cdev);
+                            ccw_device_nopath_notify);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
@@ -674,6 +675,10 @@ ccw_device_offline(struct ccw_device *cdev)
 {
        struct subchannel *sch;
 
+       if (ccw_device_is_orphan(cdev)) {
+               ccw_device_done(cdev, DEV_STATE_OFFLINE);
+               return 0;
+       }
        sch = to_subchannel(cdev->dev.parent);
        if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
                return -ENODEV;
@@ -738,7 +743,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
        sch = to_subchannel(cdev->dev.parent);
        if (get_device(&cdev->dev)) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister, cdev);
+                            ccw_device_call_sch_unregister);
                queue_work(ccw_device_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -769,7 +774,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
        }
        if (get_device(&cdev->dev)) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister, cdev);
+                            ccw_device_call_sch_unregister);
                queue_work(ccw_device_work, &cdev->private->kick_work);
        }
        wake_up(&cdev->private->wait_q);
@@ -874,7 +879,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                sch = to_subchannel(cdev->dev.parent);
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, cdev);
+                                    ccw_device_nopath_notify);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -969,7 +974,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
                              ERR_PTR(-EIO));
        if (!sch->lpm) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, cdev);
+                            ccw_device_nopath_notify);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
        } else if (cdev->private->flags.doverify)
                /* Start delayed path verification. */
@@ -992,7 +997,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                sch = to_subchannel(cdev->dev.parent);
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, cdev);
+                                    ccw_device_nopath_notify);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -1021,7 +1026,7 @@ void device_kill_io(struct subchannel *sch)
        if (ret == -ENODEV) {
                if (!sch->lpm) {
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify, cdev);
+                                    ccw_device_nopath_notify);
                        queue_work(ccw_device_notify_work,
                                   &cdev->private->kick_work);
                } else
@@ -1033,7 +1038,7 @@ void device_kill_io(struct subchannel *sch)
                              ERR_PTR(-EIO));
        if (!sch->lpm) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_nopath_notify, cdev);
+                            ccw_device_nopath_notify);
                queue_work(ccw_device_notify_work, &cdev->private->kick_work);
        } else
                /* Start delayed path verification. */
@@ -1104,7 +1109,8 @@ device_trigger_reprobe(struct subchannel *sch)
        /* Update some values. */
        if (stsch(sch->schid, &sch->schib))
                return;
-
+       if (!sch->schib.pmcw.dnv)
+               return;
        /*
         * The pim, pam, pom values may not be accurate, but they are the best
         * we have before performing device selection :/
@@ -1118,7 +1124,13 @@ device_trigger_reprobe(struct subchannel *sch)
                sch->schib.pmcw.mp = 1;
        sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
        /* We should also udate ssd info, but this has to wait. */
-       ccw_device_start_id(cdev, 0);
+       /* Check if this is another device which appeared on the same sch. */
+       if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
+               PREPARE_WORK(&cdev->private->kick_work,
+                            ccw_device_move_to_orphanage);
+               queue_work(ccw_device_work, &cdev->private->kick_work);
+       } else
+               ccw_device_start_id(cdev, 0);
 }
 
 static void
index b39c1fa..d269607 100644 (file)
@@ -316,9 +316,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        ccw_device_set_timeout(cdev, 0);
                if (ret == -EBUSY) {
                        /* Try again later. */
-                       spin_unlock_irq(&sch->lock);
+                       spin_unlock_irq(sch->lock);
                        msleep(10);
-                       spin_lock_irq(&sch->lock);
+                       spin_lock_irq(sch->lock);
                        continue;
                }
                if (ret != 0)
@@ -326,12 +326,12 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        break;
                /* Wait for end of request. */
                cdev->private->intparm = magic;
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                wait_event(cdev->private->wait_q,
                           (cdev->private->intparm == -EIO) ||
                           (cdev->private->intparm == -EAGAIN) ||
                           (cdev->private->intparm == 0));
-               spin_lock_irq(&sch->lock);
+               spin_lock_irq(sch->lock);
                /* Check at least for channel end / device end */
                if (cdev->private->intparm == -EIO) {
                        /* Non-retryable error. */
@@ -342,9 +342,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
                        /* Success. */
                        break;
                /* Try again later. */
-               spin_unlock_irq(&sch->lock);
+               spin_unlock_irq(sch->lock);
                msleep(10);
-               spin_lock_irq(&sch->lock);
+               spin_lock_irq(sch->lock);
        } while (1);
 
        return ret;
@@ -389,7 +389,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
                return ret;
        }
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        /* Save interrupt handler. */
        handler = cdev->handler;
        /* Temporarily install own handler. */
@@ -406,7 +406,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
 
        /* Restore interrupt handler. */
        cdev->handler = handler;
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
 
        clear_normalized_cda (rdc_ccw);
        kfree(rdc_ccw);
@@ -463,7 +463,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
        rcd_ccw->count = ciw->count;
        rcd_ccw->flags = CCW_FLAG_SLI;
 
-       spin_lock_irq(&sch->lock);
+       spin_lock_irq(sch->lock);
        /* Save interrupt handler. */
        handler = cdev->handler;
        /* Temporarily install own handler. */
@@ -480,7 +480,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
 
        /* Restore interrupt handler. */
        cdev->handler = handler;
-       spin_unlock_irq(&sch->lock);
+       spin_unlock_irq(sch->lock);
 
        /*
         * on success we update the user input parms
@@ -537,7 +537,7 @@ ccw_device_stlck(struct ccw_device *cdev)
                kfree(buf);
                return -ENOMEM;
        }
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        ret = cio_enable_subchannel(sch, 3);
        if (ret)
                goto out_unlock;
@@ -559,9 +559,9 @@ ccw_device_stlck(struct ccw_device *cdev)
                goto out_unlock;
        }
        cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
        wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
-       spin_lock_irqsave(&sch->lock, flags);
+       spin_lock_irqsave(sch->lock, flags);
        cio_disable_subchannel(sch); //FIXME: return code?
        if ((cdev->private->irb.scsw.dstat !=
             (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
@@ -572,7 +572,7 @@ ccw_device_stlck(struct ccw_device *cdev)
 out_unlock:
        kfree(buf);
        kfree(buf2);
-       spin_unlock_irqrestore(&sch->lock, flags);
+       spin_unlock_irqrestore(sch->lock, flags);
        return ret;
 }
 
index 8d5fa1b..9d4ea44 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/timex.h>
 
 #include <asm/debug.h>
+#include <asm/s390_rdev.h>
 #include <asm/qdio.h>
 
 #include "cio.h"
@@ -65,12 +66,12 @@ MODULE_LICENSE("GPL");
 /******************** HERE WE GO ***********************************/
 
 static const char version[] = "QDIO base support version 2";
+extern struct bus_type ccw_bus_type;
 
-#ifdef QDIO_PERFORMANCE_STATS
+static int qdio_performance_stats = 0;
 static int proc_perf_file_registration;
 static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc;
 static struct qdio_perf_stats perf_stats;
-#endif /* QDIO_PERFORMANCE_STATS */
 
 static int hydra_thinints;
 static int is_passthrough = 0;
@@ -275,9 +276,8 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
        QDIO_DBF_TEXT4(0,trace,"sigasync");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.siga_syncs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               perf_stats.siga_syncs++;
 
        cc = do_siga_sync(q->schid, gpr2, gpr3);
        if (cc)
@@ -322,9 +322,8 @@ qdio_siga_output(struct qdio_q *q)
        __u32 busy_bit;
        __u64 start_time=0;
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.siga_outs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               perf_stats.siga_outs++;
 
        QDIO_DBF_TEXT4(0,trace,"sigaout");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -358,9 +357,8 @@ qdio_siga_input(struct qdio_q *q)
        QDIO_DBF_TEXT4(0,trace,"sigain");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.siga_ins++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               perf_stats.siga_ins++;
 
        cc = do_siga_input(q->schid, q->mask);
        
@@ -954,9 +952,8 @@ __qdio_outbound_processing(struct qdio_q *q)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
-               o_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+               if (qdio_performance_stats)
+                       o_p_c++;
                /* as we're sissies, we'll check next time */
                if (likely(!atomic_read(&q->is_in_shutdown))) {
                        qdio_mark_q(q);
@@ -964,10 +961,10 @@ __qdio_outbound_processing(struct qdio_q *q)
                }
                return;
        }
-#ifdef QDIO_PERFORMANCE_STATS
-       o_p_nc++;
-       perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               o_p_nc++;
+               perf_stats.tl_runs++;
+       }
 
        /* see comment in qdio_kick_outbound_q */
        siga_attempts=atomic_read(&q->busy_siga_counter);
@@ -1142,15 +1139,16 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
 {
        int i;
 
-#ifdef QDIO_PERFORMANCE_STATS
        static int old_pcis=0;
        static int old_thinints=0;
 
-       if ((old_pcis==perf_stats.pcis)&&(old_thinints==perf_stats.thinints))
-               perf_stats.start_time_inbound=NOW;
-       else
-               old_pcis=perf_stats.pcis;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               if ((old_pcis==perf_stats.pcis)&&
+                   (old_thinints==perf_stats.thinints))
+                       perf_stats.start_time_inbound=NOW;
+               else
+                       old_pcis=perf_stats.pcis;
+       }
 
        i=qdio_get_inbound_buffer_frontier(q);
        if ( (i!=GET_SAVED_FRONTIER(q)) ||
@@ -1340,10 +1338,10 @@ qdio_kick_inbound_handler(struct qdio_q *q)
        q->siga_error=0;
        q->error_status_flags=0;
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
-       perf_stats.inbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
+               perf_stats.inbound_cnt++;
+       }
 }
 
 static inline void
@@ -1363,9 +1361,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
         */
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
-               ii_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+               if (qdio_performance_stats)
+                       ii_p_c++;
                /* 
                 * as we might just be about to stop polling, we make
                 * sure that we check again at least once more 
@@ -1373,9 +1370,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
                tiqdio_sched_tl();
                return;
        }
-#ifdef QDIO_PERFORMANCE_STATS
-       ii_p_nc++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               ii_p_nc++;
        if (unlikely(atomic_read(&q->is_in_shutdown))) {
                qdio_unmark_q(q);
                goto out;
@@ -1416,11 +1412,11 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
                irq_ptr = (struct qdio_irq*)q->irq_ptr;
                for (i=0;i<irq_ptr->no_output_qs;i++) {
                        oq = irq_ptr->output_qs[i];
-#ifdef QDIO_PERFORMANCE_STATS
-                       perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
-                       if (!qdio_is_outbound_q_done(oq))
+                       if (!qdio_is_outbound_q_done(oq)) {
+                               if (qdio_performance_stats)
+                                       perf_stats.tl_runs--;
                                __qdio_outbound_processing(oq);
+                       }
                }
        }
 
@@ -1457,9 +1453,8 @@ __qdio_inbound_processing(struct qdio_q *q)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
-               i_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+               if (qdio_performance_stats)
+                       i_p_c++;
                /* as we're sissies, we'll check next time */
                if (likely(!atomic_read(&q->is_in_shutdown))) {
                        qdio_mark_q(q);
@@ -1467,10 +1462,10 @@ __qdio_inbound_processing(struct qdio_q *q)
                }
                return;
        }
-#ifdef QDIO_PERFORMANCE_STATS
-       i_p_nc++;
-       perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               i_p_nc++;
+               perf_stats.tl_runs++;
+       }
 
 again:
        if (qdio_has_inbound_q_moved(q)) {
@@ -1516,9 +1511,8 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
-               ii_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+               if (qdio_performance_stats)
+                       ii_p_c++;
                /* 
                 * as we might just be about to stop polling, we make
                 * sure that we check again at least once more 
@@ -1609,9 +1603,8 @@ tiqdio_tl(unsigned long data)
 {
        QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               perf_stats.tl_runs++;
 
        tiqdio_inbound_checks();
 }
@@ -1918,10 +1911,10 @@ tiqdio_thinint_handler(void)
 {
        QDIO_DBF_TEXT4(0,trace,"thin_int");
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.thinints++;
-       perf_stats.start_time_inbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               perf_stats.thinints++;
+               perf_stats.start_time_inbound=NOW;
+       }
 
        /* SVS only when needed:
         * issue SVS to benefit from iqdio interrupt avoidance
@@ -1976,18 +1969,17 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
        int i;
        struct qdio_q *q;
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.pcis++;
-       perf_stats.start_time_inbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               perf_stats.pcis++;
+               perf_stats.start_time_inbound=NOW;
+       }
        for (i=0;i<irq_ptr->no_input_qs;i++) {
                q=irq_ptr->input_qs[i];
                if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
                        qdio_mark_q(q);
                else {
-#ifdef QDIO_PERFORMANCE_STATS
-                       perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
+                       if (qdio_performance_stats)
+                               perf_stats.tl_runs--;
                        __qdio_inbound_processing(q);
                }
        }
@@ -1995,11 +1987,10 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
                return;
        for (i=0;i<irq_ptr->no_output_qs;i++) {
                q=irq_ptr->output_qs[i];
-#ifdef QDIO_PERFORMANCE_STATS
-               perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
                if (qdio_is_outbound_q_done(q))
                        continue;
+               if (qdio_performance_stats)
+                       perf_stats.tl_runs--;
                if (!irq_ptr->sync_done_on_outb_pcis)
                        SYNC_MEMORY;
                __qdio_outbound_processing(q);
@@ -2045,11 +2036,13 @@ omit_handler_call:
 }
 
 static void
-qdio_call_shutdown(void *data)
+qdio_call_shutdown(struct work_struct *work)
 {
+       struct ccw_device_private *priv;
        struct ccw_device *cdev;
 
-       cdev = (struct ccw_device *)data;
+       priv = container_of(work, struct ccw_device_private, kick_work);
+       cdev = priv->cdev;
        qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
        put_device(&cdev->dev);
 }
@@ -2091,7 +2084,7 @@ qdio_timeout_handler(struct ccw_device *cdev)
                if (get_device(&cdev->dev)) {
                        /* Can't call shutdown from interrupt context. */
                        PREPARE_WORK(&cdev->private->kick_work,
-                                    qdio_call_shutdown, (void *)cdev);
+                                    qdio_call_shutdown);
                        queue_work(ccw_device_work, &cdev->private->kick_work);
                }
                break;
@@ -3458,19 +3451,18 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
        struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
 
        /* This is the outbound handling of queues */
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.start_time_outbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats)
+               perf_stats.start_time_outbound=NOW;
 
        qdio_do_qdio_fill_output(q,qidx,count,buffers);
 
        used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count;
 
        if (callflags&QDIO_FLAG_DONT_SIGA) {
-#ifdef QDIO_PERFORMANCE_STATS
-               perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-               perf_stats.outbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+               if (qdio_performance_stats) {
+                       perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
+                       perf_stats.outbound_cnt++;
+               }
                return;
        }
        if (q->is_iqdio_q) {
@@ -3500,9 +3492,8 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                                qdio_kick_outbound_q(q);
                        } else {
                                QDIO_DBF_TEXT3(0,trace, "fast-req");
-#ifdef QDIO_PERFORMANCE_STATS
-                               perf_stats.fast_reqs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+                               if (qdio_performance_stats)
+                                       perf_stats.fast_reqs++;
                        }
                }
                /* 
@@ -3513,10 +3504,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                __qdio_outbound_processing(q);
        }
 
-#ifdef QDIO_PERFORMANCE_STATS
-       perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-       perf_stats.outbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+       if (qdio_performance_stats) {
+               perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
+               perf_stats.outbound_cnt++;
+       }
 }
 
 /* count must be 1 in iqdio */
@@ -3574,7 +3565,6 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags,
        return 0;
 }
 
-#ifdef QDIO_PERFORMANCE_STATS
 static int
 qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
                        int buffer_length, int *eof, void *data)
@@ -3590,29 +3580,29 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
        _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
        _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
        _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
-       _OUTP_IT("Number of tasklet runs (total)                  : %u\n",
+       _OUTP_IT("Number of tasklet runs (total)                  : %lu\n",
                 perf_stats.tl_runs);
        _OUTP_IT("\n");
-       _OUTP_IT("Number of SIGA sync's issued                    : %u\n",
+       _OUTP_IT("Number of SIGA sync's issued                    : %lu\n",
                 perf_stats.siga_syncs);
-       _OUTP_IT("Number of SIGA in's issued                      : %u\n",
+       _OUTP_IT("Number of SIGA in's issued                      : %lu\n",
                 perf_stats.siga_ins);
-       _OUTP_IT("Number of SIGA out's issued                     : %u\n",
+       _OUTP_IT("Number of SIGA out's issued                     : %lu\n",
                 perf_stats.siga_outs);
-       _OUTP_IT("Number of PCIs caught                           : %u\n",
+       _OUTP_IT("Number of PCIs caught                           : %lu\n",
                 perf_stats.pcis);
-       _OUTP_IT("Number of adapter interrupts caught             : %u\n",
+       _OUTP_IT("Number of adapter interrupts caught             : %lu\n",
                 perf_stats.thinints);
-       _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %u\n",
+       _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %lu\n",
                 perf_stats.fast_reqs);
        _OUTP_IT("\n");
-       _OUTP_IT("Total time of all inbound actions (us) incl. UL : %u\n",
+       _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n",
                 perf_stats.inbound_time);
-       _OUTP_IT("Number of inbound transfers                     : %u\n",
+       _OUTP_IT("Number of inbound transfers                     : %lu\n",
                 perf_stats.inbound_cnt);
-       _OUTP_IT("Total time of all outbound do_QDIOs (us)        : %u\n",
+       _OUTP_IT("Total time of all outbound do_QDIOs (us)        : %lu\n",
                 perf_stats.outbound_time);
-       _OUTP_IT("Number of do_QDIOs outbound                     : %u\n",
+       _OUTP_IT("Number of do_QDIOs outbound                     : %lu\n",
                 perf_stats.outbound_cnt);
        _OUTP_IT("\n");
 
@@ -3620,12 +3610,10 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
 }
 
 static struct proc_dir_entry *qdio_perf_proc_file;
-#endif /* QDIO_PERFORMANCE_STATS */
 
 static void
 qdio_add_procfs_entry(void)
 {
-#ifdef QDIO_PERFORMANCE_STATS
         proc_perf_file_registration=0;
        qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
                                              S_IFREG|0444,&proc_root);
@@ -3637,20 +3625,58 @@ qdio_add_procfs_entry(void)
                 QDIO_PRINT_WARN("was not able to register perf. " \
                                "proc-file (%i).\n",
                                proc_perf_file_registration);
-#endif /* QDIO_PERFORMANCE_STATS */
 }
 
 static void
 qdio_remove_procfs_entry(void)
 {
-#ifdef QDIO_PERFORMANCE_STATS
        perf_stats.tl_runs=0;
 
         if (!proc_perf_file_registration) /* means if it went ok earlier */
                remove_proc_entry(QDIO_PERF,&proc_root);
-#endif /* QDIO_PERFORMANCE_STATS */
 }
 
+/**
+ * attributes in sysfs
+ *****************************************************************************/
+
+static ssize_t
+qdio_performance_stats_show(struct bus_type *bus, char *buf)
+{
+       return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
+}
+
+static ssize_t
+qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
+{
+       char *tmp;
+       int i;
+
+       i = simple_strtoul(buf, &tmp, 16);
+       if ((i == 0) || (i == 1)) {
+               if (i == qdio_performance_stats)
+                       return count;
+               qdio_performance_stats = i;
+               if (i==0) {
+                       /* reset perf. stat. info */
+                       i_p_nc = 0;
+                       i_p_c = 0;
+                       ii_p_nc = 0;
+                       ii_p_c = 0;
+                       o_p_nc = 0;
+                       o_p_c = 0;
+                       memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
+               }
+       } else {
+               QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
+               return -EINVAL;
+       }
+       return count;
+}
+
+static BUS_ATTR(qdio_performance_stats, 0644, qdio_performance_stats_show,
+                       qdio_performance_stats_store);
+
 static void
 tiqdio_register_thinints(void)
 {
@@ -3695,6 +3721,7 @@ qdio_release_qdio_memory(void)
        kfree(indicators);
 }
 
+
 static void
 qdio_unregister_dbf_views(void)
 {
@@ -3796,9 +3823,7 @@ static int __init
 init_QDIO(void)
 {
        int res;
-#ifdef QDIO_PERFORMANCE_STATS
        void *ptr;
-#endif /* QDIO_PERFORMANCE_STATS */
 
        printk("qdio: loading %s\n",version);
 
@@ -3811,13 +3836,12 @@ init_QDIO(void)
                return res;
 
        QDIO_DBF_TEXT0(0,setup,"initQDIO");
+       res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
 
-#ifdef QDIO_PERFORMANCE_STATS
-               memset((void*)&perf_stats,0,sizeof(perf_stats));
+       memset((void*)&perf_stats,0,sizeof(perf_stats));
        QDIO_DBF_TEXT0(0,setup,"perfstat");
        ptr=&perf_stats;
        QDIO_DBF_HEX0(0,setup,&ptr,sizeof(void*));
-#endif /* QDIO_PERFORMANCE_STATS */
 
        qdio_add_procfs_entry();
 
@@ -3841,7 +3865,7 @@ cleanup_QDIO(void)
        qdio_release_qdio_memory();
        qdio_unregister_dbf_views();
        mempool_destroy(qdio_mempool_scssc);
-
+       bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
        printk("qdio: %s: module removed\n",version);
 }
 
index 42927c1..ec9af72 100644 (file)
 #endif /* CONFIG_QDIO_DEBUG */
 #define QDIO_USE_PROCESSING_STATE
 
-#ifdef CONFIG_QDIO_PERF_STATS
-#define QDIO_PERFORMANCE_STATS
-#endif /* CONFIG_QDIO_PERF_STATS */
-
 #define QDIO_MINIMAL_BH_RELIEF_TIME 16
 #define QDIO_TIMER_POLL_VALUE 1
 #define IQDIO_TIMER_POLL_VALUE 1
@@ -409,25 +405,23 @@ do_clear_global_summary(void)
 #define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
 #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
 
-#ifdef QDIO_PERFORMANCE_STATS
 struct qdio_perf_stats {
-       unsigned int tl_runs;
+       unsigned long tl_runs;
 
-       unsigned int siga_outs;
-       unsigned int siga_ins;
-       unsigned int siga_syncs;
-       unsigned int pcis;
-       unsigned int thinints;
-       unsigned int fast_reqs;
+       unsigned long siga_outs;
+       unsigned long siga_ins;
+       unsigned long siga_syncs;
+       unsigned long pcis;
+       unsigned long thinints;
+       unsigned long fast_reqs;
 
        __u64 start_time_outbound;
-       unsigned int outbound_cnt;
-       unsigned int outbound_time;
+       unsigned long outbound_cnt;
+       unsigned long outbound_time;
        __u64 start_time_inbound;
-       unsigned int inbound_cnt;
-       unsigned int inbound_time;
+       unsigned long inbound_cnt;
+       unsigned long inbound_time;
 };
-#endif /* QDIO_PERFORMANCE_STATS */
 
 /* unlikely as the later the better */
 #define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
index 6a54334..ad60afe 100644 (file)
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <asm/s390_rdev.h>
+#include <asm/reset.h>
 
 #include "ap_bus.h"
 
 /* Some prototypes. */
-static void ap_scan_bus(void *);
+static void ap_scan_bus(struct work_struct *);
 static void ap_poll_all(unsigned long);
 static void ap_poll_timeout(unsigned long);
 static int ap_poll_thread_start(void);
@@ -71,7 +72,7 @@ static struct device *ap_root_device = NULL;
 static struct workqueue_struct *ap_work_queue;
 static struct timer_list ap_config_timer;
 static int ap_config_time = AP_CONFIG_TIME;
-static DECLARE_WORK(ap_config_work, ap_scan_bus, NULL);
+static DECLARE_WORK(ap_config_work, ap_scan_bus);
 
 /**
  * Tasklet & timer for AP request polling.
@@ -732,7 +733,7 @@ static void ap_device_release(struct device *dev)
        kfree(ap_dev);
 }
 
-static void ap_scan_bus(void *data)
+static void ap_scan_bus(struct work_struct *unused)
 {
        struct ap_device *ap_dev;
        struct device *dev;
@@ -1128,6 +1129,19 @@ static void ap_poll_thread_stop(void)
        mutex_unlock(&ap_poll_thread_mutex);
 }
 
+static void ap_reset(void)
+{
+       int i, j;
+
+       for (i = 0; i < AP_DOMAINS; i++)
+               for (j = 0; j < AP_DEVICES; j++)
+                       ap_reset_queue(AP_MKQID(j, i));
+}
+
+static struct reset_call ap_reset_call = {
+       .fn = ap_reset,
+};
+
 /**
  * The module initialization code.
  */
@@ -1144,6 +1158,7 @@ int __init ap_module_init(void)
                printk(KERN_WARNING "AP instructions not installed.\n");
                return -ENODEV;
        }
+       register_reset_call(&ap_reset_call);
 
        /* Create /sys/bus/ap. */
        rc = bus_register(&ap_bus_type);
@@ -1197,6 +1212,7 @@ out_bus:
                bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
        bus_unregister(&ap_bus_type);
 out:
+       unregister_reset_call(&ap_reset_call);
        return rc;
 }
 
@@ -1227,6 +1243,7 @@ void ap_module_exit(void)
        for (i = 0; ap_bus_attrs[i]; i++)
                bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
        bus_unregister(&ap_bus_type);
+       unregister_reset_call(&ap_reset_call);
 }
 
 #ifndef CONFIG_ZCRYPT_MONOLITHIC
index 08d4e47..e5665b6 100644 (file)
@@ -67,7 +67,7 @@ static char debug_buffer[255];
  * Some prototypes.
  */
 static void lcs_tasklet(unsigned long);
-static void lcs_start_kernel_thread(struct lcs_card *card);
+static void lcs_start_kernel_thread(struct work_struct *);
 static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
 static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
 static int lcs_recovery(void *ptr);
@@ -1724,8 +1724,9 @@ lcs_stopcard(struct lcs_card *card)
  * Kernel Thread helper functions for LGW initiated commands
  */
 static void
-lcs_start_kernel_thread(struct lcs_card *card)
+lcs_start_kernel_thread(struct work_struct *work)
 {
+       struct lcs_card *card = container_of(work, struct lcs_card, kernel_thread_starter);
        LCS_DBF_TEXT(5, trace, "krnthrd");
        if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD))
                kernel_thread(lcs_recovery, (void *) card, SIGCHLD);
@@ -2053,8 +2054,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
        ccwgdev->cdev[0]->handler = lcs_irq;
        ccwgdev->cdev[1]->handler = lcs_irq;
        card->gdev = ccwgdev;
-       INIT_WORK(&card->kernel_thread_starter,
-                 (void *) lcs_start_kernel_thread, card);
+       INIT_WORK(&card->kernel_thread_starter, lcs_start_kernel_thread);
        card->thread_start_mask = 0;
        card->thread_allowed_mask = 0;
        card->thread_running_mask = 0;
index 7fdc527..2bde4f1 100644 (file)
@@ -1039,8 +1039,9 @@ qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
 }
 
 static void
-qeth_start_kernel_thread(struct qeth_card *card)
+qeth_start_kernel_thread(struct work_struct *work)
 {
+       struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter);
        QETH_DBF_TEXT(trace , 2, "strthrd");
 
        if (card->read.state != CH_STATE_UP &&
@@ -1103,8 +1104,7 @@ qeth_setup_card(struct qeth_card *card)
        card->thread_start_mask = 0;
        card->thread_allowed_mask = 0;
        card->thread_running_mask = 0;
-       INIT_WORK(&card->kernel_thread_starter,
-                 (void *)qeth_start_kernel_thread,card);
+       INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
        INIT_LIST_HEAD(&card->ip_list);
        card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
        if (!card->ip_tbd_list) {
index 74c0eac..32933ed 100644 (file)
@@ -1032,9 +1032,9 @@ struct zfcp_data {
        wwn_t                   init_wwpn;
        fcp_lun_t               init_fcp_lun;
        char                    *driver_version;
-       kmem_cache_t            *fsf_req_qtcb_cache;
-       kmem_cache_t            *sr_buffer_cache;
-       kmem_cache_t            *gid_pn_cache;
+       struct kmem_cache               *fsf_req_qtcb_cache;
+       struct kmem_cache               *sr_buffer_cache;
+       struct kmem_cache               *gid_pn_cache;
 };
 
 /**
index 277826c..067f151 100644 (file)
@@ -109,7 +109,7 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
                        ptr = kmalloc(size, GFP_ATOMIC);
                else
                        ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
-                                              SLAB_ATOMIC);
+                                              GFP_ATOMIC);
        }
 
        if (unlikely(!ptr))
index 385f4f7..ac7d125 100644 (file)
@@ -621,7 +621,7 @@ static long read_ecp(unsigned minor, char __user *c, unsigned long cnt)
 static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos)
 {
       long rc;
-      unsigned minor = iminor(f->f_dentry->d_inode);
+      unsigned minor = iminor(f->f_path.dentry->d_inode);
       if (minor >= BPP_NO) return -ENODEV;
       if (!instances[minor].present) return -ENODEV;
 
@@ -774,7 +774,7 @@ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt)
 static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos)
 {
       long errno = 0;
-      unsigned minor = iminor(f->f_dentry->d_inode);
+      unsigned minor = iminor(f->f_path.dentry->d_inode);
       if (minor >= BPP_NO) return -ENODEV;
       if (!instances[minor].present) return -ENODEV;
 
index f5803ec..ad1c7db 100644 (file)
@@ -404,7 +404,7 @@ static long wd_compat_ioctl(struct file *file, unsigned int cmd,
        case WIOCSTOP:
        case WIOCGSTAT:
                lock_kernel();
-               rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+               rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
                unlock_kernel();
                break;
        /* everything else is handled by the generic compat layer */
index d92bc88..a4909e0 100644 (file)
@@ -121,7 +121,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        __u8 ireg = 0;
        int error = 0;
 
-       if (D7S_MINOR != iminor(file->f_dentry->d_inode))
+       if (D7S_MINOR != iminor(file->f_path.dentry->d_inode))
                return -ENODEV;
 
        lock_kernel();
index 81ba2d7..4e2a0e2 100644 (file)
@@ -676,7 +676,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
        case OPROMSETCUR:
        case OPROMPCI2NODE:
        case OPROMPATH2NODE:
-               rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+               rval = openprom_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
                break;
        }
 
index 55b2b31..2722af5 100644 (file)
@@ -610,7 +610,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned int map_size, ret, map_offset;
        struct vfc_dev *dev;
        
-       dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode));
+       dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode));
        if(dev == NULL)
                return -ENODEV;
 
index 335a255..68103e5 100644 (file)
@@ -313,7 +313,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        hostdata->status = memory + STATUS_OFFSET;
        /* all of these offsets are L1_CACHE_BYTES separated.  It is fatal
         * if this isn't sufficient separation to avoid dma flushing issues */
-       BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment());
+       BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment());
        hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET);
        hostdata->dev = dev;
 
@@ -362,11 +362,11 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        for (j = 0; j < PATCHES; j++)
                script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]);
        /* now patch up fixed addresses. */
-       script_patch_32(script, MessageLocation,
+       script_patch_32(hostdata->dev, script, MessageLocation,
                        pScript + MSGOUT_OFFSET);
-       script_patch_32(script, StatusAddress,
+       script_patch_32(hostdata->dev, script, StatusAddress,
                        pScript + STATUS_OFFSET);
-       script_patch_32(script, ReceiveMsgAddress,
+       script_patch_32(hostdata->dev, script, ReceiveMsgAddress,
                        pScript + MSGIN_OFFSET);
 
        hostdata->script = script;
@@ -821,8 +821,9 @@ process_extended_message(struct Scsi_Host *host,
                        shost_printk(KERN_WARNING, host,
                                "Unexpected SDTR msg\n");
                        hostdata->msgout[0] = A_REJECT_MSG;
-                       dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE);
-                       script_patch_16(hostdata->script, MessageCount, 1);
+                       dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
+                       script_patch_16(hostdata->dev, hostdata->script,
+                                       MessageCount, 1);
                        /* SendMsgOut returns, so set up the return
                         * address */
                        resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
@@ -833,8 +834,9 @@ process_extended_message(struct Scsi_Host *host,
                printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n",
                       host->host_no, pun, lun);
                hostdata->msgout[0] = A_REJECT_MSG;
-               dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE);
-               script_patch_16(hostdata->script, MessageCount, 1);
+               dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
+               script_patch_16(hostdata->dev, hostdata->script, MessageCount,
+                               1);
                resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
 
                break;
@@ -847,8 +849,9 @@ process_extended_message(struct Scsi_Host *host,
                printk("\n");
                /* just reject it */
                hostdata->msgout[0] = A_REJECT_MSG;
-               dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE);
-               script_patch_16(hostdata->script, MessageCount, 1);
+               dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
+               script_patch_16(hostdata->dev, hostdata->script, MessageCount,
+                               1);
                /* SendMsgOut returns, so set up the return
                 * address */
                resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
@@ -929,8 +932,9 @@ process_message(struct Scsi_Host *host,     struct NCR_700_Host_Parameters *hostdata
                printk("\n");
                /* just reject it */
                hostdata->msgout[0] = A_REJECT_MSG;
-               dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE);
-               script_patch_16(hostdata->script, MessageCount, 1);
+               dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
+               script_patch_16(hostdata->dev, hostdata->script, MessageCount,
+                               1);
                /* SendMsgOut returns, so set up the return
                 * address */
                resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
@@ -939,7 +943,7 @@ process_message(struct Scsi_Host *host,     struct NCR_700_Host_Parameters *hostdata
        }
        NCR_700_writel(temp, host, TEMP_REG);
        /* set us up to receive another message */
-       dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE);
+       dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE);
        return resume_offset;
 }
 
@@ -1019,9 +1023,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                                slot->SG[1].ins = bS_to_host(SCRIPT_RETURN);
                                slot->SG[1].pAddr = 0;
                                slot->resume_offset = hostdata->pScript;
-                               dma_cache_sync(slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE);
-                               dma_cache_sync(SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
-                               
+                               dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE);
+                               dma_cache_sync(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
+
                                /* queue the command for reissue */
                                slot->state = NCR_700_SLOT_QUEUED;
                                slot->flags = NCR_700_FLAG_AUTOSENSE;
@@ -1136,11 +1140,12 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                        hostdata->cmd = slot->cmnd;
 
                        /* re-patch for this command */
-                       script_patch_32_abs(hostdata->script, CommandAddress, 
-                                           slot->pCmd);
-                       script_patch_16(hostdata->script,
+                       script_patch_32_abs(hostdata->dev, hostdata->script,
+                                           CommandAddress, slot->pCmd);
+                       script_patch_16(hostdata->dev, hostdata->script,
                                        CommandCount, slot->cmnd->cmd_len);
-                       script_patch_32_abs(hostdata->script, SGScriptStartAddress,
+                       script_patch_32_abs(hostdata->dev, hostdata->script,
+                                           SGScriptStartAddress,
                                            to32bit(&slot->pSG[0].ins));
 
                        /* Note: setting SXFER only works if we're
@@ -1150,13 +1155,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                         * should therefore always clear ACK */
                        NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device),
                                       host, SXFER_REG);
-                       dma_cache_sync(hostdata->msgin,
+                       dma_cache_sync(hostdata->dev, hostdata->msgin,
                                       MSG_ARRAY_SIZE, DMA_FROM_DEVICE);
-                       dma_cache_sync(hostdata->msgout,
+                       dma_cache_sync(hostdata->dev, hostdata->msgout,
                                       MSG_ARRAY_SIZE, DMA_TO_DEVICE);
                        /* I'm just being paranoid here, the command should
                         * already have been flushed from the cache */
-                       dma_cache_sync(slot->cmnd->cmnd,
+                       dma_cache_sync(hostdata->dev, slot->cmnd->cmnd,
                                       slot->cmnd->cmd_len, DMA_TO_DEVICE);
 
 
@@ -1220,7 +1225,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                hostdata->reselection_id = reselection_id;
                /* just in case we have a stale simple tag message, clear it */
                hostdata->msgin[1] = 0;
-               dma_cache_sync(hostdata->msgin,
+               dma_cache_sync(hostdata->dev, hostdata->msgin,
                               MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL);
                if(hostdata->tag_negotiated & (1<<reselection_id)) {
                        resume_offset = hostdata->pScript + Ent_GetReselectionWithTag;
@@ -1336,7 +1341,7 @@ process_selection(struct Scsi_Host *host, __u32 dsp)
        hostdata->cmd = NULL;
        /* clear any stale simple tag message */
        hostdata->msgin[1] = 0;
-       dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE,
+       dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE,
                       DMA_BIDIRECTIONAL);
 
        if(id == 0xff) {
@@ -1433,29 +1438,30 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
                NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
        }
 
-       script_patch_16(hostdata->script, MessageCount, count);
+       script_patch_16(hostdata->dev, hostdata->script, MessageCount, count);
 
 
-       script_patch_ID(hostdata->script,
+       script_patch_ID(hostdata->dev, hostdata->script,
                        Device_ID, 1<<scmd_id(SCp));
 
-       script_patch_32_abs(hostdata->script, CommandAddress, 
+       script_patch_32_abs(hostdata->dev, hostdata->script, CommandAddress,
                            slot->pCmd);
-       script_patch_16(hostdata->script, CommandCount, SCp->cmd_len);
+       script_patch_16(hostdata->dev, hostdata->script, CommandCount,
+                       SCp->cmd_len);
        /* finally plumb the beginning of the SG list into the script
         * */
-       script_patch_32_abs(hostdata->script, SGScriptStartAddress,
-                           to32bit(&slot->pSG[0].ins));
+       script_patch_32_abs(hostdata->dev, hostdata->script,
+                           SGScriptStartAddress, to32bit(&slot->pSG[0].ins));
        NCR_700_clear_fifo(SCp->device->host);
 
        if(slot->resume_offset == 0)
                slot->resume_offset = hostdata->pScript;
        /* now perform all the writebacks and invalidates */
-       dma_cache_sync(hostdata->msgout, count, DMA_TO_DEVICE);
-       dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE,
+       dma_cache_sync(hostdata->dev, hostdata->msgout, count, DMA_TO_DEVICE);
+       dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE,
                       DMA_FROM_DEVICE);
-       dma_cache_sync(SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE);
-       dma_cache_sync(hostdata->status, 1, DMA_FROM_DEVICE);
+       dma_cache_sync(hostdata->dev, SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE);
+       dma_cache_sync(hostdata->dev, hostdata->status, 1, DMA_FROM_DEVICE);
 
        /* set the synchronous period/offset */
        NCR_700_writeb(NCR_700_get_SXFER(SCp->device),
@@ -1631,7 +1637,7 @@ NCR_700_intr(int irq, void *dev_id)
                                        slot->SG[i].ins = bS_to_host(SCRIPT_NOP);
                                        slot->SG[i].pAddr = 0;
                                }
-                               dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
+                               dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
                                /* and pretend we disconnected after
                                 * the command phase */
                                resume_offset = hostdata->pScript + Ent_MsgInDuringData;
@@ -1897,9 +1903,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
                }
                slot->SG[i].ins = bS_to_host(SCRIPT_RETURN);
                slot->SG[i].pAddr = 0;
-               dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
+               dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
                DEBUG((" SETTING %08lx to %x\n",
-                      (&slot->pSG[i].ins), 
+                      (&slot->pSG[i].ins),
                       slot->SG[i].ins));
        }
        slot->resume_offset = 0;
index f5c3caf..f38822d 100644 (file)
@@ -415,31 +415,31 @@ struct NCR_700_Host_Parameters {
 #define NCR_710_MIN_XFERP      0
 #define NCR_700_MIN_PERIOD     25 /* for SDTR message, 100ns */
 
-#define script_patch_32(script, symbol, value) \
+#define script_patch_32(dev, script, symbol, value) \
 { \
        int i; \
        for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
                __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]) + value; \
                (script)[A_##symbol##_used[i]] = bS_to_host(val); \
-               dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+               dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
                DEBUG((" script, patching %s at %d to 0x%lx\n", \
                       #symbol, A_##symbol##_used[i], (value))); \
        } \
 }
 
-#define script_patch_32_abs(script, symbol, value) \
+#define script_patch_32_abs(dev, script, symbol, value) \
 { \
        int i; \
        for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
                (script)[A_##symbol##_used[i]] = bS_to_host(value); \
-               dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+               dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
                DEBUG((" script, patching %s at %d to 0x%lx\n", \
                       #symbol, A_##symbol##_used[i], (value))); \
        } \
 }
 
 /* Used for patching the SCSI ID in the SELECT instruction */
-#define script_patch_ID(script, symbol, value) \
+#define script_patch_ID(dev, script, symbol, value) \
 { \
        int i; \
        for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
@@ -447,13 +447,13 @@ struct NCR_700_Host_Parameters {
                val &= 0xff00ffff; \
                val |= ((value) & 0xff) << 16; \
                (script)[A_##symbol##_used[i]] = bS_to_host(val); \
-               dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+               dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
                DEBUG((" script, patching ID field %s at %d to 0x%x\n", \
                       #symbol, A_##symbol##_used[i], val)); \
        } \
 }
 
-#define script_patch_16(script, symbol, value) \
+#define script_patch_16(dev, script, symbol, value) \
 { \
        int i; \
        for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
@@ -461,7 +461,7 @@ struct NCR_700_Host_Parameters {
                val &= 0xffff0000; \
                val |= ((value) & 0xffff); \
                (script)[A_##symbol##_used[i]] = bS_to_host(val); \
-               dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+               dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
                DEBUG((" script, patching short field %s at %d to 0x%x\n", \
                       #symbol, A_##symbol##_used[i], val)); \
        } \
index 6956909..60f5827 100644 (file)
@@ -1737,7 +1737,7 @@ config SCSI_NCR53C7xx_FAST
 
 config SUN3_SCSI
        tristate "Sun3 NCR5380 SCSI"
-       depends on SUN3 && SCSI && BROKEN
+       depends on SUN3 && SCSI
        select SCSI_SPI_ATTRS
        help
          This option will enable support for the OBIO (onboard io) NCR5380
index a6aa910..bb3cb33 100644 (file)
@@ -849,7 +849,7 @@ static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
        hostdata->issue_queue = NULL;
        hostdata->disconnected_queue = NULL;
        
-       INIT_WORK(&hostdata->coroutine, NCR5380_main, hostdata);
+       INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
        
 #ifdef NCR5380_STATS
        for (i = 0; i < 8; ++i) {
@@ -1016,7 +1016,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 
        /* Run the coroutine if it isn't already running. */
        /* Kick off command processing */
-       schedule_work(&hostdata->coroutine);
+       schedule_delayed_work(&hostdata->coroutine, 0);
        return 0;
 }
 
@@ -1033,9 +1033,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
  *     host lock and called routines may take the isa dma lock.
  */
 
-static void NCR5380_main(void *p)
+static void NCR5380_main(struct work_struct *work)
 {
-       struct NCR5380_hostdata *hostdata = p;
+       struct NCR5380_hostdata *hostdata =
+               container_of(work, struct NCR5380_hostdata, coroutine.work);
        struct Scsi_Host *instance = hostdata->host;
        Scsi_Cmnd *tmp, *prev;
        int done;
@@ -1221,7 +1222,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
                }       /* if BASR_IRQ */
                spin_unlock_irqrestore(instance->host_lock, flags);
                if(!done)
-                       schedule_work(&hostdata->coroutine);
+                       schedule_delayed_work(&hostdata->coroutine, 0);
        } while (!done);
        return IRQ_HANDLED;
 }
index 1bc73de..713a108 100644 (file)
@@ -271,7 +271,7 @@ struct NCR5380_hostdata {
        unsigned long time_expires;             /* in jiffies, set prior to sleeping */
        int select_time;                        /* timer in select for target response */
        volatile Scsi_Cmnd *selecting;
-       struct work_struct coroutine;           /* our co-routine */
+       struct delayed_work coroutine;          /* our co-routine */
 #ifdef NCR5380_STATS
        unsigned timebase;                      /* Base for time calcs */
        long time_read[8];                      /* time to do reads */
@@ -298,7 +298,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
 static irqreturn_t NCR5380_intr(int irq, void *dev_id);
 #endif
-static void NCR5380_main(void *ptr);
+static void NCR5380_main(struct work_struct *work);
 static void NCR5380_print_options(struct Scsi_Host *instance);
 #ifdef NDEBUG
 static void NCR5380_print_phase(struct Scsi_Host *instance);
index 306f46b..0cec742 100644 (file)
@@ -1443,7 +1443,7 @@ static struct work_struct aha152x_tq;
  * Run service completions on the card with interrupts enabled.
  *
  */
-static void run(void)
+static void run(struct work_struct *work)
 {
        struct aha152x_hostdata *hd;
 
@@ -1499,7 +1499,7 @@ static irqreturn_t intr(int irqno, void *dev_id)
                HOSTDATA(shpnt)->service=1;
 
                /* Poke the BH handler */
-               INIT_WORK(&aha152x_tq, (void *) run, NULL);
+               INIT_WORK(&aha152x_tq, run);
                schedule_work(&aha152x_tq);
        }
        DO_UNLOCK(flags);
index 71a031d..32f513b 100644 (file)
@@ -56,8 +56,8 @@
 /* 2*ITNL timeout + 1 second */
 #define AIC94XX_SCB_TIMEOUT  (5*HZ)
 
-extern kmem_cache_t *asd_dma_token_cache;
-extern kmem_cache_t *asd_ascb_cache;
+extern struct kmem_cache *asd_dma_token_cache;
+extern struct kmem_cache *asd_ascb_cache;
 extern char sas_addr_str[2*SAS_ADDR_SIZE + 1];
 
 static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
index af7e011..da94e12 100644 (file)
@@ -1047,7 +1047,7 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
 static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
                                              gfp_t gfp_flags)
 {
-       extern kmem_cache_t *asd_ascb_cache;
+       extern struct kmem_cache *asd_ascb_cache;
        struct asd_seq_data *seq = &asd_ha->seq;
        struct asd_ascb *ascb;
        unsigned long flags;
index 42302ef..fbc82b0 100644 (file)
@@ -450,8 +450,8 @@ static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
        asd_ha->scb_pool = NULL;
 }
 
-kmem_cache_t *asd_dma_token_cache;
-kmem_cache_t *asd_ascb_cache;
+struct kmem_cache *asd_dma_token_cache;
+struct kmem_cache *asd_ascb_cache;
 
 static int asd_create_global_caches(void)
 {
index 14d5d8c..75ed6b0 100644 (file)
@@ -414,9 +414,10 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
 }
 
 /* hard reset a phy later */
-static void do_phy_reset_later(void *data)
+static void do_phy_reset_later(struct work_struct *work)
 {
-       struct sas_phy *sas_phy = data;
+       struct sas_phy *sas_phy =
+               container_of(work, struct sas_phy, reset_work);
        int error;
 
        ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__,
@@ -430,7 +431,7 @@ static void do_phy_reset_later(void *data)
 
 static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost)
 {
-       INIT_WORK(&sas_phy->reset_work, do_phy_reset_later, sas_phy);
+       INIT_WORK(&sas_phy->reset_work, do_phy_reset_later);
        queue_work(shost->work_q, &sas_phy->reset_work);
 }
 
@@ -442,7 +443,7 @@ static void task_kill_later(struct asd_ascb *ascb)
        struct Scsi_Host *shost = sas_ha->core.shost;
        struct sas_task *task = ascb->uldd_task;
 
-       INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task);
+       INIT_WORK(&task->abort_work, sas_task_abort);
        queue_work(shost->work_q, &task->abort_work);
 }
 
index 0e74174..e28260f 100644 (file)
@@ -67,6 +67,7 @@ struct vio_port {
 
        unsigned long liobn;
        unsigned long riobn;
+       struct srp_target *target;
 };
 
 static struct workqueue_struct *vtgtd;
@@ -685,10 +686,10 @@ static inline struct viosrp_crq *next_crq(struct crq_queue *queue)
        return crq;
 }
 
-static void handle_crq(void *data)
+static void handle_crq(struct work_struct *work)
 {
-       struct srp_target *target = (struct srp_target *) data;
-       struct vio_port *vport = target_to_port(target);
+       struct vio_port *vport = container_of(work, struct vio_port, crq_work);
+       struct srp_target *target = vport->target;
        struct viosrp_crq *crq;
        int done = 0;
 
@@ -822,6 +823,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        target->shost = shost;
        vport->dma_dev = dev;
        target->ldata = vport;
+       vport->target = target;
        err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT,
                               SRP_MAX_IU_LEN);
        if (err)
@@ -837,7 +839,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        vport->liobn = dma[0];
        vport->riobn = dma[5];
 
-       INIT_WORK(&vport->crq_work, handle_crq, target);
+       INIT_WORK(&vport->crq_work, handle_crq);
 
        err = crq_queue_create(&vport->crq_queue, target);
        if (err)
index 1427a41..8f6b5bf 100644 (file)
@@ -110,6 +110,7 @@ typedef struct ide_scsi_obj {
 } idescsi_scsi_t;
 
 static DEFINE_MUTEX(idescsi_ref_mutex);
+static int idescsi_nocd;                       /* Set by module param to skip cd */
 
 #define ide_scsi_g(disk) \
        container_of((disk)->private_data, struct ide_scsi_obj, driver)
@@ -1127,6 +1128,9 @@ static int ide_scsi_probe(ide_drive_t *drive)
                warned = 1;
        }
 
+       if (idescsi_nocd && drive->media == ide_cdrom)
+               return -ENODEV;
+
        if (!strstr("ide-scsi", drive->driver_req) ||
            !drive->present ||
            drive->media == ide_disk ||
@@ -1187,6 +1191,8 @@ static void __exit exit_idescsi_module(void)
        driver_unregister(&idescsi_driver.gen_driver);
 }
 
+module_param(idescsi_nocd, int, 0600);
+MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd");
 module_init(init_idescsi_module);
 module_exit(exit_idescsi_module);
 MODULE_LICENSE("GPL");
index e31f612..0464c18 100644 (file)
@@ -36,7 +36,7 @@ typedef struct {
        int base_hi;            /* Hi Base address for ECP-ISA chipset */
        int mode;               /* Transfer mode                */
        struct scsi_cmnd *cur_cmd;      /* Current queued command       */
-       struct work_struct imm_tq;      /* Polling interrupt stuff       */
+       struct delayed_work imm_tq;     /* Polling interrupt stuff       */
        unsigned long jstart;   /* Jiffies at start             */
        unsigned failed:1;      /* Failure flag                 */
        unsigned dp:1;          /* Data phase present           */
@@ -733,9 +733,9 @@ static int imm_completion(struct scsi_cmnd *cmd)
  * the scheduler's task queue to generate a stream of call-backs and
  * complete the request when the drive is ready.
  */
-static void imm_interrupt(void *data)
+static void imm_interrupt(struct work_struct *work)
 {
-       imm_struct *dev = (imm_struct *) data;
+       imm_struct *dev = container_of(work, imm_struct, imm_tq.work);
        struct scsi_cmnd *cmd = dev->cur_cmd;
        struct Scsi_Host *host = cmd->device->host;
        unsigned long flags;
@@ -745,7 +745,6 @@ static void imm_interrupt(void *data)
                return;
        }
        if (imm_engine(dev, cmd)) {
-               INIT_WORK(&dev->imm_tq, imm_interrupt, (void *) dev);
                schedule_delayed_work(&dev->imm_tq, 1);
                return;
        }
@@ -953,8 +952,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
        cmd->result = DID_ERROR << 16;  /* default return code */
        cmd->SCp.phase = 0;     /* bus free */
 
-       INIT_WORK(&dev->imm_tq, imm_interrupt, dev);
-       schedule_work(&dev->imm_tq);
+       schedule_delayed_work(&dev->imm_tq, 0);
 
        imm_pb_claim(dev);
 
@@ -1225,7 +1223,7 @@ static int __imm_attach(struct parport *pb)
        else
                ports = 8;
 
-       INIT_WORK(&dev->imm_tq, imm_interrupt, dev);
+       INIT_DELAYED_WORK(&dev->imm_tq, imm_interrupt);
 
        err = -ENOMEM;
        host = scsi_host_alloc(&imm_template, sizeof(imm_struct *));
index 2d83fbb..b318500 100644 (file)
@@ -2307,7 +2307,7 @@ static void ipr_release_dump(struct kref *kref)
 
 /**
  * ipr_worker_thread - Worker thread
- * @data:              ioa config struct
+ * @work:              ioa config struct
  *
  * Called at task level from a work thread. This function takes care
  * of adding and removing device from the mid-layer as configuration
@@ -2316,13 +2316,14 @@ static void ipr_release_dump(struct kref *kref)
  * Return value:
  *     nothing
  **/
-static void ipr_worker_thread(void *data)
+static void ipr_worker_thread(struct work_struct *work)
 {
        unsigned long lock_flags;
        struct ipr_resource_entry *res;
        struct scsi_device *sdev;
        struct ipr_dump *dump;
-       struct ipr_ioa_cfg *ioa_cfg = data;
+       struct ipr_ioa_cfg *ioa_cfg =
+               container_of(work, struct ipr_ioa_cfg, work_q);
        u8 bus, target, lun;
        int did_work;
 
@@ -6939,7 +6940,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
                return -ENOMEM;
 
        for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
-               ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, SLAB_KERNEL, &dma_addr);
+               ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
 
                if (!ipr_cmd) {
                        ipr_free_cmd_blks(ioa_cfg);
@@ -7121,7 +7122,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
        INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q);
        INIT_LIST_HEAD(&ioa_cfg->free_res_q);
        INIT_LIST_HEAD(&ioa_cfg->used_res_q);
-       INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread, ioa_cfg);
+       INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
        init_waitqueue_head(&ioa_cfg->reset_wait_q);
        ioa_cfg->sdt_state = INACTIVE;
        if (ipr_enable_cache)
index 5d88621..e11b23c 100644 (file)
@@ -719,9 +719,10 @@ again:
        return rc;
 }
 
-static void iscsi_xmitworker(void *data)
+static void iscsi_xmitworker(struct work_struct *work)
 {
-       struct iscsi_conn *conn = data;
+       struct iscsi_conn *conn =
+               container_of(work, struct iscsi_conn, xmitwork);
        int rc;
        /*
         * serialize Xmit worker on a per-connection basis.
@@ -1512,7 +1513,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
        if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
                goto mgmtqueue_alloc_fail;
 
-       INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn);
+       INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
 
        /* allocate login_mtask used for the login/text sequences */
        spin_lock_bh(&session->lock);
index d977bd4..fb7df7b 100644 (file)
@@ -647,10 +647,12 @@ void sas_unregister_domain_devices(struct asd_sas_port *port)
  * Discover process only interrogates devices in order to discover the
  * domain.
  */
-static void sas_discover_domain(void *data)
+static void sas_discover_domain(struct work_struct *work)
 {
        int error = 0;
-       struct asd_sas_port *port = data;
+       struct sas_discovery_event *ev =
+               container_of(work, struct sas_discovery_event, work);
+       struct asd_sas_port *port = ev->port;
 
        sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock,
                        &port->disc.pending);
@@ -692,10 +694,12 @@ static void sas_discover_domain(void *data)
                    current->pid, error);
 }
 
-static void sas_revalidate_domain(void *data)
+static void sas_revalidate_domain(struct work_struct *work)
 {
        int res = 0;
-       struct asd_sas_port *port = data;
+       struct sas_discovery_event *ev =
+               container_of(work, struct sas_discovery_event, work);
+       struct asd_sas_port *port = ev->port;
 
        sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock,
                        &port->disc.pending);
@@ -722,7 +726,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
        BUG_ON(ev >= DISC_NUM_EVENTS);
 
        sas_queue_event(ev, &disc->disc_event_lock, &disc->pending,
-                       &disc->disc_work[ev], port->ha->core.shost);
+                       &disc->disc_work[ev].work, port->ha->core.shost);
 
        return 0;
 }
@@ -737,13 +741,15 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
 {
        int i;
 
-       static void (*sas_event_fns[DISC_NUM_EVENTS])(void *) = {
+       static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
                [DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
                [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
        };
 
        spin_lock_init(&disc->disc_event_lock);
        disc->pending = 0;
-       for (i = 0; i < DISC_NUM_EVENTS; i++)
-               INIT_WORK(&disc->disc_work[i], sas_event_fns[i], port);
+       for (i = 0; i < DISC_NUM_EVENTS; i++) {
+               INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
+               disc->disc_work[i].port = port;
+       }
 }
index 19110ed..d83392e 100644 (file)
@@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
        BUG_ON(event >= HA_NUM_EVENTS);
 
        sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending,
-                       &sas_ha->ha_events[event], sas_ha->core.shost);
+                       &sas_ha->ha_events[event].work, sas_ha->core.shost);
 }
 
 static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
@@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
        BUG_ON(event >= PORT_NUM_EVENTS);
 
        sas_queue_event(event, &ha->event_lock, &phy->port_events_pending,
-                       &phy->port_events[event], ha->core.shost);
+                       &phy->port_events[event].work, ha->core.shost);
 }
 
 static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
@@ -51,12 +51,12 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
        BUG_ON(event >= PHY_NUM_EVENTS);
 
        sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending,
-                       &phy->phy_events[event], ha->core.shost);
+                       &phy->phy_events[event].work, ha->core.shost);
 }
 
 int sas_init_events(struct sas_ha_struct *sas_ha)
 {
-       static void (*sas_ha_event_fns[HA_NUM_EVENTS])(void *) = {
+       static const work_func_t sas_ha_event_fns[HA_NUM_EVENTS] = {
                [HAE_RESET] = sas_hae_reset,
        };
 
@@ -64,8 +64,10 @@ int sas_init_events(struct sas_ha_struct *sas_ha)
 
        spin_lock_init(&sas_ha->event_lock);
 
-       for (i = 0; i < HA_NUM_EVENTS; i++)
-               INIT_WORK(&sas_ha->ha_events[i], sas_ha_event_fns[i], sas_ha);
+       for (i = 0; i < HA_NUM_EVENTS; i++) {
+               INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
+               sas_ha->ha_events[i].ha = sas_ha;
+       }
 
        sas_ha->notify_ha_event = notify_ha_event;
        sas_ha->notify_port_event = notify_port_event;
index 0fb347b..2f0c07f 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "../scsi_sas_internal.h"
 
-kmem_cache_t *sas_task_cache;
+struct kmem_cache *sas_task_cache;
 
 /*------------ SAS addr hash -----------*/
 void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
@@ -65,9 +65,11 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
 
 /* ---------- HA events ---------- */
 
-void sas_hae_reset(void *data)
+void sas_hae_reset(struct work_struct *work)
 {
-       struct sas_ha_struct *ha = data;
+       struct sas_ha_event *ev =
+               container_of(work, struct sas_ha_event, work);
+       struct sas_ha_struct *ha = ev->ha;
 
        sas_begin_event(HAE_RESET, &ha->event_lock,
                        &ha->pending);
index bffcee4..137d7e4 100644 (file)
@@ -60,11 +60,11 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
 
 void sas_deform_port(struct asd_sas_phy *phy);
 
-void sas_porte_bytes_dmaed(void *);
-void sas_porte_broadcast_rcvd(void *);
-void sas_porte_link_reset_err(void *);
-void sas_porte_timer_event(void *);
-void sas_porte_hard_reset(void *);
+void sas_porte_bytes_dmaed(struct work_struct *work);
+void sas_porte_broadcast_rcvd(struct work_struct *work);
+void sas_porte_link_reset_err(struct work_struct *work);
+void sas_porte_timer_event(struct work_struct *work);
+void sas_porte_hard_reset(struct work_struct *work);
 
 int sas_notify_lldd_dev_found(struct domain_device *);
 void sas_notify_lldd_dev_gone(struct domain_device *);
@@ -75,7 +75,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy);
 
 struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
 
-void sas_hae_reset(void *);
+void sas_hae_reset(struct work_struct *work);
 
 static inline void sas_queue_event(int event, spinlock_t *lock,
                                   unsigned long *pending,
index 9340cdb..b459c4b 100644 (file)
 
 /* ---------- Phy events ---------- */
 
-static void sas_phye_loss_of_signal(void *data)
+static void sas_phye_loss_of_signal(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock,
                        &phy->phy_events_pending);
@@ -40,18 +42,22 @@ static void sas_phye_loss_of_signal(void *data)
        sas_deform_port(phy);
 }
 
-static void sas_phye_oob_done(void *data)
+static void sas_phye_oob_done(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PHYE_OOB_DONE, &phy->ha->event_lock,
                        &phy->phy_events_pending);
        phy->error = 0;
 }
 
-static void sas_phye_oob_error(void *data)
+static void sas_phye_oob_error(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
        struct sas_ha_struct *sas_ha = phy->ha;
        struct asd_sas_port *port = phy->port;
        struct sas_internal *i =
@@ -80,9 +86,11 @@ static void sas_phye_oob_error(void *data)
        }
 }
 
-static void sas_phye_spinup_hold(void *data)
+static void sas_phye_spinup_hold(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
        struct sas_ha_struct *sas_ha = phy->ha;
        struct sas_internal *i =
                to_sas_internal(sas_ha->core.shost->transportt);
@@ -100,14 +108,14 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
 {
        int i;
 
-       static void (*sas_phy_event_fns[PHY_NUM_EVENTS])(void *) = {
+       static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
                [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
                [PHYE_OOB_DONE] = sas_phye_oob_done,
                [PHYE_OOB_ERROR] = sas_phye_oob_error,
                [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
        };
 
-       static void (*sas_port_event_fns[PORT_NUM_EVENTS])(void *) = {
+       static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = {
                [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed,
                [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd,
                [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err,
@@ -122,13 +130,18 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
 
                phy->error = 0;
                INIT_LIST_HEAD(&phy->port_phy_el);
-               for (k = 0; k < PORT_NUM_EVENTS; k++)
-                       INIT_WORK(&phy->port_events[k], sas_port_event_fns[k],
-                                 phy);
+               for (k = 0; k < PORT_NUM_EVENTS; k++) {
+                       INIT_WORK(&phy->port_events[k].work,
+                                 sas_port_event_fns[k]);
+                       phy->port_events[k].phy = phy;
+               }
+
+               for (k = 0; k < PHY_NUM_EVENTS; k++) {
+                       INIT_WORK(&phy->phy_events[k].work,
+                                 sas_phy_event_fns[k]);
+                       phy->phy_events[k].phy = phy;
+               }
 
-               for (k = 0; k < PHY_NUM_EVENTS; k++)
-                       INIT_WORK(&phy->phy_events[k], sas_phy_event_fns[k],
-                                 phy);
                phy->port = NULL;
                phy->ha = sas_ha;
                spin_lock_init(&phy->frame_rcvd_lock);
index 253cdcf..971c37c 100644 (file)
@@ -181,9 +181,11 @@ void sas_deform_port(struct asd_sas_phy *phy)
 
 /* ---------- SAS port events ---------- */
 
-void sas_porte_bytes_dmaed(void *data)
+void sas_porte_bytes_dmaed(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock,
                        &phy->port_events_pending);
@@ -191,11 +193,13 @@ void sas_porte_bytes_dmaed(void *data)
        sas_form_port(phy);
 }
 
-void sas_porte_broadcast_rcvd(void *data)
+void sas_porte_broadcast_rcvd(struct work_struct *work)
 {
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
        unsigned long flags;
        u32 prim;
-       struct asd_sas_phy *phy = data;
 
        sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock,
                        &phy->port_events_pending);
@@ -208,9 +212,11 @@ void sas_porte_broadcast_rcvd(void *data)
        sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN);
 }
 
-void sas_porte_link_reset_err(void *data)
+void sas_porte_link_reset_err(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock,
                        &phy->port_events_pending);
@@ -218,9 +224,11 @@ void sas_porte_link_reset_err(void *data)
        sas_deform_port(phy);
 }
 
-void sas_porte_timer_event(void *data)
+void sas_porte_timer_event(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock,
                        &phy->port_events_pending);
@@ -228,9 +236,11 @@ void sas_porte_timer_event(void *data)
        sas_deform_port(phy);
 }
 
-void sas_porte_hard_reset(void *data)
+void sas_porte_hard_reset(struct work_struct *work)
 {
-       struct asd_sas_phy *phy = data;
+       struct asd_sas_event *ev =
+               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_phy *phy = ev->phy;
 
        sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock,
                        &phy->port_events_pending);
index e064aac..22672d5 100644 (file)
@@ -846,8 +846,10 @@ static int do_sas_task_abort(struct sas_task *task)
        return -EAGAIN;
 }
 
-void sas_task_abort(struct sas_task *task)
+void sas_task_abort(struct work_struct *work)
 {
+       struct sas_task *task =
+               container_of(work, struct sas_task, abort_work);
        int i;
 
        for (i = 0; i < 5; i++)
index dd67a68..c116a6a 100644 (file)
@@ -72,12 +72,12 @@ static void dma_advance_sg(Scsi_Cmnd *);
 static int  oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x);
 
 #ifdef USE_BOTTOM_HALF
-static void dma_commit(void *opaque);
+static void dma_commit(struct work_struct *unused);
 
 long oktag_to_io(long *paddr, long *addr, long len);
 long oktag_from_io(long *addr, long *paddr, long len);
 
-static DECLARE_WORK(tq_fake_dma, dma_commit, NULL);
+static DECLARE_WORK(tq_fake_dma, dma_commit);
 
 #define DMA_MAXTRANSFER 0x8000
 
@@ -266,7 +266,7 @@ oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
  */
  
  
-static void dma_commit(void *opaque)
+static void dma_commit(struct work_struct *unused)
 {
     long wait,len2,pos;
     struct NCR_ESP *esp;
index 89a2a9f..584ba4d 100644 (file)
@@ -31,7 +31,7 @@ typedef struct {
        int base;               /* Actual port address          */
        int mode;               /* Transfer mode                */
        struct scsi_cmnd *cur_cmd;      /* Current queued command       */
-       struct work_struct ppa_tq;      /* Polling interrupt stuff       */
+       struct delayed_work ppa_tq;     /* Polling interrupt stuff       */
        unsigned long jstart;   /* Jiffies at start             */
        unsigned long recon_tmo;        /* How many usecs to wait for reconnection (6th bit) */
        unsigned int failed:1;  /* Failure flag                 */
@@ -627,9 +627,9 @@ static int ppa_completion(struct scsi_cmnd *cmd)
  * the scheduler's task queue to generate a stream of call-backs and
  * complete the request when the drive is ready.
  */
-static void ppa_interrupt(void *data)
+static void ppa_interrupt(struct work_struct *work)
 {
-       ppa_struct *dev = (ppa_struct *) data;
+       ppa_struct *dev = container_of(work, ppa_struct, ppa_tq.work);
        struct scsi_cmnd *cmd = dev->cur_cmd;
 
        if (!cmd) {
@@ -637,7 +637,6 @@ static void ppa_interrupt(void *data)
                return;
        }
        if (ppa_engine(dev, cmd)) {
-               dev->ppa_tq.data = (void *) dev;
                schedule_delayed_work(&dev->ppa_tq, 1);
                return;
        }
@@ -822,8 +821,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
        cmd->result = DID_ERROR << 16;  /* default return code */
        cmd->SCp.phase = 0;     /* bus free */
 
-       dev->ppa_tq.data = dev;
-       schedule_work(&dev->ppa_tq);
+       schedule_delayed_work(&dev->ppa_tq, 0);
 
        ppa_pb_claim(dev);
 
@@ -1086,7 +1084,7 @@ static int __ppa_attach(struct parport *pb)
        else
                ports = 8;
 
-       INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev);
+       INIT_DELAYED_WORK(&dev->ppa_tq, ppa_interrupt);
 
        err = -ENOMEM;
        host = scsi_host_alloc(&ppa_template, sizeof(ppa_struct *));
index cbe0cad..d03523d 100644 (file)
@@ -24,7 +24,7 @@ char qla2x00_version_str[40];
 /*
  * SRB allocation cache
  */
-static kmem_cache_t *srb_cachep;
+static struct kmem_cache *srb_cachep;
 
 /*
  * Ioctl related information.
index db9d88e..9ef693c 100644 (file)
@@ -19,7 +19,7 @@ char qla4xxx_version_str[40];
 /*
  * SRB allocation cache
  */
-static kmem_cache_t *srb_cachep;
+static struct kmem_cache *srb_cachep;
 
 /*
  * Module parameter information and variables
@@ -961,9 +961,10 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
  * the mid-level tries to sleep when it reaches the driver threshold
  * "host->can_queue". This can cause a panic if we were in our interrupt code.
  **/
-static void qla4xxx_do_dpc(void *data)
+static void qla4xxx_do_dpc(struct work_struct *work)
 {
-       struct scsi_qla_host *ha = (struct scsi_qla_host *) data;
+       struct scsi_qla_host *ha =
+               container_of(work, struct scsi_qla_host, dpc_work);
        struct ddb_entry *ddb_entry, *dtemp;
 
        DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
@@ -1253,7 +1254,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
                ret = -ENODEV;
                goto probe_failed;
        }
-       INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc, ha);
+       INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
 
        ret = request_irq(pdev->irq, qla4xxx_intr_handler,
                          SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha);
index fafc00d..24cffd9 100644 (file)
@@ -136,7 +136,7 @@ const char * scsi_device_type(unsigned type)
 EXPORT_SYMBOL(scsi_device_type);
 
 struct scsi_host_cmd_pool {
-       kmem_cache_t    *slab;
+       struct kmem_cache       *slab;
        unsigned int    users;
        char            *name;
        unsigned int    slab_flags;
index fb616c6..1748e27 100644 (file)
@@ -36,7 +36,7 @@
 struct scsi_host_sg_pool {
        size_t          size;
        char            *name; 
-       kmem_cache_t    *slab;
+       struct kmem_cache       *slab;
        mempool_t       *pool;
 };
 
@@ -241,7 +241,7 @@ struct scsi_io_context {
        char sense[SCSI_SENSE_BUFFERSIZE];
 };
 
-static kmem_cache_t *scsi_io_context_cache;
+static struct kmem_cache *scsi_io_context_cache;
 
 static void scsi_end_async(struct request *req, int uptodate)
 {
index 4d65614..14e635a 100644 (file)
@@ -437,9 +437,10 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        goto retry;
 }
 
-static void scsi_target_reap_usercontext(void *data)
+static void scsi_target_reap_usercontext(struct work_struct *work)
 {
-       struct scsi_target *starget = data;
+       struct scsi_target *starget =
+               container_of(work, struct scsi_target, ew.work);
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
 
@@ -475,7 +476,7 @@ void scsi_target_reap(struct scsi_target *starget)
                starget->state = STARGET_DEL;
                spin_unlock_irqrestore(shost->host_lock, flags);
                execute_in_process_context(scsi_target_reap_usercontext,
-                                          starget, &starget->ew);
+                                          &starget->ew);
                return;
 
        }
index e1a9166..259c90c 100644 (file)
@@ -218,16 +218,16 @@ static void scsi_device_cls_release(struct class_device *class_dev)
        put_device(&sdev->sdev_gendev);
 }
 
-static void scsi_device_dev_release_usercontext(void *data)
+static void scsi_device_dev_release_usercontext(struct work_struct *work)
 {
-       struct device *dev = data;
        struct scsi_device *sdev;
        struct device *parent;
        struct scsi_target *starget;
        unsigned long flags;
 
-       parent = dev->parent;
-       sdev = to_scsi_device(dev);
+       sdev = container_of(work, struct scsi_device, ew.work);
+
+       parent = sdev->sdev_gendev.parent;
        starget = to_scsi_target(parent);
 
        spin_lock_irqsave(sdev->host->host_lock, flags);
@@ -258,7 +258,7 @@ static void scsi_device_dev_release_usercontext(void *data)
 static void scsi_device_dev_release(struct device *dev)
 {
        struct scsi_device *sdp = to_scsi_device(dev);
-       execute_in_process_context(scsi_device_dev_release_usercontext, dev,
+       execute_in_process_context(scsi_device_dev_release_usercontext,
                                   &sdp->ew);
 }
 
index 39da5cd..d402aff 100644 (file)
@@ -33,7 +33,7 @@
 #include "scsi_tgt_priv.h"
 
 static struct workqueue_struct *scsi_tgtd;
-static kmem_cache_t *scsi_tgt_cmd_cache;
+static struct kmem_cache *scsi_tgt_cmd_cache;
 
 /*
  * TODO: this struct will be killed when the block layer supports large bios
@@ -185,10 +185,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd)
        spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
 }
 
-static void scsi_tgt_cmd_destroy(void *data)
+static void scsi_tgt_cmd_destroy(struct work_struct *work)
 {
-       struct scsi_cmnd *cmd = data;
-       struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
+       struct scsi_tgt_cmd *tcmd =
+               container_of(work, struct scsi_tgt_cmd, work);
+       struct scsi_cmnd *cmd = tcmd->rq->special;
 
        dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
                rq_data_dir(cmd->request));
@@ -214,6 +215,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
        struct list_head *head;
 
        tcmd->tag = tag;
+       INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
        spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
        head = &qdata->cmd_hash[cmd_hashfn(tag)];
        list_add(&tcmd->hash_list, head);
@@ -303,7 +305,7 @@ void scsi_tgt_free_queue(struct Scsi_Host *shost)
                cmd = tcmd->rq->special;
 
                shost->hostt->eh_abort_handler(cmd);
-               scsi_tgt_cmd_destroy(cmd);
+               scsi_tgt_cmd_destroy(&tcmd->work);
        }
 }
 EXPORT_SYMBOL_GPL(scsi_tgt_free_queue);
@@ -347,7 +349,6 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
        dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
 
        scsi_tgt_uspace_send_status(cmd, tcmd->tag);
-       INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy, cmd);
        queue_work(scsi_tgtd, &tcmd->work);
 }
 
@@ -549,13 +550,15 @@ static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,
 
 static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 {
+       struct scsi_tgt_cmd *tcmd;
        int err;
 
        err = shost->hostt->eh_abort_handler(cmd);
        if (err)
                eprintk("fail to abort %p\n", cmd);
 
-       scsi_tgt_cmd_destroy(cmd);
+       tcmd = cmd->request->end_io_data;
+       scsi_tgt_cmd_destroy(&tcmd->work);
        return err;
 }
 
index 38c215a..3571ce8 100644 (file)
@@ -241,9 +241,9 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
 #define FC_MGMTSRVR_PORTID             0x00000a
 
 
-static void fc_timeout_deleted_rport(void *data);
-static void fc_timeout_fail_rport_io(void *data);
-static void fc_scsi_scan_rport(void *data);
+static void fc_timeout_deleted_rport(struct work_struct *work);
+static void fc_timeout_fail_rport_io(struct work_struct *work);
+static void fc_scsi_scan_rport(struct work_struct *work);
 
 /*
  * Attribute counts pre object type...
@@ -1613,7 +1613,7 @@ fc_flush_work(struct Scsi_Host *shost)
  *     1 on success / 0 already queued / < 0 for error
  **/
 static int
-fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
+fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
                                unsigned long delay)
 {
        if (unlikely(!fc_host_devloss_work_q(shost))) {
@@ -1625,9 +1625,6 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
                return -EINVAL;
        }
 
-       if (delay == 0)
-               return queue_work(fc_host_devloss_work_q(shost), work);
-
        return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
 }
 
@@ -1712,12 +1709,13 @@ EXPORT_SYMBOL(fc_remove_host);
  * fc_starget_delete - called to delete the scsi decendents of an rport
  *                  (target and all sdevs)
  *
- * @data:      remote port to be operated on.
+ * @work:      remote port to be operated on.
  **/
 static void
-fc_starget_delete(void *data)
+fc_starget_delete(struct work_struct *work)
 {
-       struct fc_rport *rport = (struct fc_rport *)data;
+       struct fc_rport *rport =
+               container_of(work, struct fc_rport, stgt_delete_work);
        struct Scsi_Host *shost = rport_to_shost(rport);
        unsigned long flags;
        struct fc_internal *i = to_fc_internal(shost->transportt);
@@ -1751,12 +1749,13 @@ fc_starget_delete(void *data)
 /**
  * fc_rport_final_delete - finish rport termination and delete it.
  *
- * @data:      remote port to be deleted.
+ * @work:      remote port to be deleted.
  **/
 static void
-fc_rport_final_delete(void *data)
+fc_rport_final_delete(struct work_struct *work)
 {
-       struct fc_rport *rport = (struct fc_rport *)data;
+       struct fc_rport *rport =
+               container_of(work, struct fc_rport, rport_delete_work);
        struct device *dev = &rport->dev;
        struct Scsi_Host *shost = rport_to_shost(rport);
        struct fc_internal *i = to_fc_internal(shost->transportt);
@@ -1770,7 +1769,7 @@ fc_rport_final_delete(void *data)
 
        /* Delete SCSI target and sdevs */
        if (rport->scsi_target_id != -1)
-               fc_starget_delete(data);
+               fc_starget_delete(&rport->stgt_delete_work);
        else if (i->f->dev_loss_tmo_callbk)
                i->f->dev_loss_tmo_callbk(rport);
        else if (i->f->terminate_rport_io)
@@ -1829,11 +1828,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
        rport->channel = channel;
        rport->fast_io_fail_tmo = -1;
 
-       INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
-       INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport);
-       INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
-       INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
-       INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
+       INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport);
+       INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io);
+       INIT_WORK(&rport->scan_work, fc_scsi_scan_rport);
+       INIT_WORK(&rport->stgt_delete_work, fc_starget_delete);
+       INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete);
 
        spin_lock_irqsave(shost->host_lock, flags);
 
@@ -1963,7 +1962,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                        }
 
                        if (match) {
-                               struct work_struct *work = 
+                               struct delayed_work *work =
                                                        &rport->dev_loss_work;
 
                                memcpy(&rport->node_name, &ids->node_name,
@@ -2267,12 +2266,13 @@ EXPORT_SYMBOL(fc_remote_port_rolechg);
  *                       was a SCSI target (thus was blocked), and failed
  *                       to return in the alloted time.
  * 
- * @data:      rport target that failed to reappear in the alloted time.
+ * @work:      rport target that failed to reappear in the alloted time.
  **/
 static void
-fc_timeout_deleted_rport(void  *data)
+fc_timeout_deleted_rport(struct work_struct *work)
 {
-       struct fc_rport *rport = (struct fc_rport *)data;
+       struct fc_rport *rport =
+               container_of(work, struct fc_rport, dev_loss_work.work);
        struct Scsi_Host *shost = rport_to_shost(rport);
        struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
        unsigned long flags;
@@ -2366,15 +2366,16 @@ fc_timeout_deleted_rport(void  *data)
  * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a
  *                       disconnected SCSI target.
  *
- * @data:      rport to terminate io on.
+ * @work:      rport to terminate io on.
  *
  * Notes: Only requests the failure of the io, not that all are flushed
  *    prior to returning.
  **/
 static void
-fc_timeout_fail_rport_io(void  *data)
+fc_timeout_fail_rport_io(struct work_struct *work)
 {
-       struct fc_rport *rport = (struct fc_rport *)data;
+       struct fc_rport *rport =
+               container_of(work, struct fc_rport, fail_io_work.work);
        struct Scsi_Host *shost = rport_to_shost(rport);
        struct fc_internal *i = to_fc_internal(shost->transportt);
 
@@ -2387,12 +2388,13 @@ fc_timeout_fail_rport_io(void  *data)
 /**
  * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
  *
- * @data:      remote port to be scanned.
+ * @work:      remote port to be scanned.
  **/
 static void
-fc_scsi_scan_rport(void *data)
+fc_scsi_scan_rport(struct work_struct *work)
 {
-       struct fc_rport *rport = (struct fc_rport *)data;
+       struct fc_rport *rport =
+               container_of(work, struct fc_rport, scan_work);
        struct Scsi_Host *shost = rport_to_shost(rport);
        unsigned long flags;
 
index 9b25124..9c22f13 100644 (file)
@@ -234,9 +234,11 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
        return 0;
 }
 
-static void session_recovery_timedout(void *data)
+static void session_recovery_timedout(struct work_struct *work)
 {
-       struct iscsi_cls_session *session = data;
+       struct iscsi_cls_session *session =
+               container_of(work, struct iscsi_cls_session,
+                            recovery_work.work);
 
        dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
                  "out after %d secs\n", session->recovery_tmo);
@@ -276,7 +278,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
 
        session->transport = transport;
        session->recovery_tmo = 120;
-       INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
+       INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
        INIT_LIST_HEAD(&session->host_list);
        INIT_LIST_HEAD(&session->sess_list);
 
index 9f070f0..3fded48 100644 (file)
@@ -964,9 +964,10 @@ struct work_queue_wrapper {
 };
 
 static void
-spi_dv_device_work_wrapper(void *data)
+spi_dv_device_work_wrapper(struct work_struct *work)
 {
-       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct work_queue_wrapper *wqw =
+               container_of(work, struct work_queue_wrapper, work);
        struct scsi_device *sdev = wqw->sdev;
 
        kfree(wqw);
@@ -1006,7 +1007,7 @@ spi_schedule_dv_device(struct scsi_device *sdev)
                return;
        }
 
-       INIT_WORK(&wqw->work, spi_dv_device_work_wrapper, wqw);
+       INIT_WORK(&wqw->work, spi_dv_device_work_wrapper);
        wqw->sdev = sdev;
 
        schedule_work(&wqw->work);
index f6a4528..978bfc1 100644 (file)
@@ -863,7 +863,7 @@ static void sd_rescan(struct device *dev)
  */
 static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+       struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
        struct gendisk *disk = bdev->bd_disk;
        struct scsi_device *sdev = scsi_disk(disk)->device;
 
index 587274d..e016e09 100644 (file)
@@ -922,7 +922,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
        struct st_modedef *STm;
        struct st_partstat *STps;
        char *name = tape_name(STp);
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int mode = TAPE_MODE(inode);
 
        STp->ready = ST_READY;
index 3b3f305..43f5b6a 100644 (file)
@@ -1271,7 +1271,7 @@ static irqreturn_t NCR5380_intr (int irq, void *dev_id)
        NCR_PRINT(NDEBUG_INTR);
        if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
            done = 0;
-           ENABLE_IRQ();
+//         ENABLE_IRQ();
            INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
            NCR5380_reselect(instance);
            (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
@@ -1304,7 +1304,7 @@ static irqreturn_t NCR5380_intr (int irq, void *dev_id)
                INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
                NCR5380_dma_complete( instance );
                done = 0;
-               ENABLE_IRQ();
+//             ENABLE_IRQ();
            } else
 #endif /* REAL_DMA */
            {
index d56d85d..69ee3e4 100644 (file)
@@ -75,9 +75,9 @@
 #define REAL_DMA
 
 #include "scsi.h"
+#include "initio.h"
 #include <scsi/scsi_host.h>
 #include "sun3_scsi.h"
-#include "NCR5380.h"
 
 static void NCR5380_print(struct Scsi_Host *instance);
 
index a1103b3..b29a9d6 100644 (file)
@@ -221,7 +221,7 @@ struct sun3_udc_regs {
  *
  */
 
-
+#include "NCR5380.h"
 
 #if NDEBUG & NDEBUG_ARBITRATION
 #define ARB_PRINTK(format, args...) \
index 92def31..bb0c9fd 100644 (file)
@@ -41,9 +41,9 @@
 #define REAL_DMA
 
 #include "scsi.h"
+#include "initio.h"
 #include <scsi/scsi_host.h>
 #include "sun3_scsi.h"
-#include "NCR5380.h"
 
 extern int sun3_map_test(unsigned long, char *);
 
index 6a1a568..facb678 100644 (file)
@@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port)
 }
 
 static void
-serial21285_set_termios(struct uart_port *port, struct termios *termios,
-                       struct termios *old)
+serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
+                       struct ktermios *old)
 {
        unsigned long flags;
        unsigned int baud, quot, h_lcr;
index 9b8b585..cad426c 100644 (file)
@@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        return 0;
 }
 
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
 
index 634ecca..68817a7 100644 (file)
@@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
 
 /* FIX UP modem control here someday......
 */
-static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        ser_info_t *info = (ser_info_t *)tty->driver_data;
 
index e34bd03..51f3c73 100644 (file)
@@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
 }
 
 static void
-serial8250_set_termios(struct uart_port *port, struct termios *termios,
-                      struct termios *old)
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
        unsigned char cval, fcr = 0;
diff --git a/drivers/serial/8250_exar_st16c554.c b/drivers/serial/8250_exar_st16c554.c
new file mode 100644 (file)
index 0000000..567143a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  linux/drivers/serial/8250_exar.c
+ *
+ *  Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
+ *  Based on 8250_boca.
+ *
+ *  Copyright (C) 2005 Russell King.
+ *  Data taken from include/asm-i386/serial.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(_base,_irq)                               \
+       {                                               \
+               .iobase         = _base,                \
+               .irq            = _irq,                 \
+               .uartclk        = 1843200,              \
+               .iotype         = UPIO_PORT,            \
+               .flags          = UPF_BOOT_AUTOCONF,    \
+       }
+
+static struct plat_serial8250_port exar_data[] = {
+       PORT(0x100, 5),
+       PORT(0x108, 5),
+       PORT(0x110, 5),
+       PORT(0x118, 5),
+       { },
+};
+
+static struct platform_device exar_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_EXAR_ST16C554,
+       .dev                    = {
+               .platform_data  = exar_data,
+       },
+};
+
+static int __init exar_init(void)
+{
+       return platform_device_register(&exar_device);
+}
+
+module_init(exar_init);
+
+MODULE_AUTHOR("Paul B Schroeder");
+MODULE_DESCRIPTION("8250 serial probe module for Exar cards");
+MODULE_LICENSE("GPL");
index 71d907c..d3d6b82 100644 (file)
@@ -464,11 +464,38 @@ static void __devexit serial_pnp_remove(struct pnp_dev *dev)
                serial8250_unregister_port(line - 1);
 }
 
+#ifdef CONFIG_PM
+static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+       long line = (long)pnp_get_drvdata(dev);
+
+       if (!line)
+               return -ENODEV;
+       serial8250_suspend_port(line - 1);
+       return 0;
+}
+
+static int serial_pnp_resume(struct pnp_dev *dev)
+{
+       long line = (long)pnp_get_drvdata(dev);
+
+       if (!line)
+               return -ENODEV;
+       serial8250_resume_port(line - 1);
+       return 0;
+}
+#else
+#define serial_pnp_suspend NULL
+#define serial_pnp_resume NULL
+#endif /* CONFIG_PM */
+
 static struct pnp_driver serial_pnp_driver = {
        .name           = "serial",
-       .id_table       = pnp_dev_table,
        .probe          = serial_pnp_probe,
        .remove         = __devexit_p(serial_pnp_remove),
+       .suspend        = serial_pnp_suspend,
+       .resume         = serial_pnp_resume,
+       .id_table       = pnp_dev_table,
 };
 
 static int __init serial8250_pnp_init(void)
index 0b71e7d..0b36dd5 100644 (file)
@@ -151,32 +151,6 @@ config SERIAL_8250_MANY_PORTS
          say N here to save some memory. You can also say Y if you have an
          "intelligent" multiport card such as Cyclades, Digiboards, etc.
 
-config SERIAL_8250_SHARE_IRQ
-       bool "Support for sharing serial interrupts"
-       depends on SERIAL_8250_EXTENDED
-       help
-         Some serial boards have hardware support which allows multiple dumb
-         serial ports on the same board to share a single IRQ. To enable
-         support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
-       bool "Autodetect IRQ on standard ports (unsafe)"
-       depends on SERIAL_8250_EXTENDED
-       help
-         Say Y here if you want the kernel to try to guess which IRQ
-         to use for your serial port.
-
-         This is considered unsafe; it is far better to configure the IRQ in
-         a boot script using the setserial command.
-
-         If unsure, say N.
-
-config SERIAL_8250_RSA
-       bool "Support RSA serial ports"
-       depends on SERIAL_8250_EXTENDED
-       help
-         ::: To be written :::
-
 #
 # Multi-port serial cards
 #
@@ -199,7 +173,6 @@ config SERIAL_8250_ACCENT
          To compile this driver as a module, choose M here: the module
          will be called 8250_accent.
 
-
 config SERIAL_8250_BOCA
        tristate "Support Boca cards"
        depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -210,6 +183,17 @@ config SERIAL_8250_BOCA
          To compile this driver as a module, choose M here: the module
          will be called 8250_boca.
 
+config SERIAL_8250_EXAR_ST16C554
+       tristate "Support Exar ST16C554/554D Quad UART"
+       depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+       help
+         The Uplogix Envoy TU301 uses this Exar Quad UART.  If you are
+         tinkering with your Envoy TU301, or have a machine with this UART,
+         say Y here.
+
+         To compile this driver as a module, choose M here: the module
+         will be called 8250_exar_st16c554.
+
 config SERIAL_8250_HUB6
        tristate "Support Hub6 cards"
        depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -219,6 +203,32 @@ config SERIAL_8250_HUB6
          To compile this driver as a module, choose M here: the module
          will be called 8250_hub6.
 
+config SERIAL_8250_SHARE_IRQ
+       bool "Support for sharing serial interrupts"
+       depends on SERIAL_8250_EXTENDED
+       help
+         Some serial boards have hardware support which allows multiple dumb
+         serial ports on the same board to share a single IRQ. To enable
+         support for this in the serial driver, say Y here.
+
+config SERIAL_8250_DETECT_IRQ
+       bool "Autodetect IRQ on standard ports (unsafe)"
+       depends on SERIAL_8250_EXTENDED
+       help
+         Say Y here if you want the kernel to try to guess which IRQ
+         to use for your serial port.
+
+         This is considered unsafe; it is far better to configure the IRQ in
+         a boot script using the setserial command.
+
+         If unsure, say N.
+
+config SERIAL_8250_RSA
+       bool "Support RSA serial ports"
+       depends on SERIAL_8250_EXTENDED
+       help
+         ::: To be written :::
+
 config SERIAL_8250_MCA
        tristate "Support 8250-type ports on MCA buses"
        depends on SERIAL_8250 != n && MCA
@@ -511,6 +521,25 @@ config SERIAL_IMX_CONSOLE
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
+config SERIAL_UARTLITE
+       tristate "Xilinx uartlite serial port support"
+       depends on PPC32
+       select SERIAL_CORE
+       help
+         Say Y here if you want to use the Xilinx uartlite serial controller.
+
+         To compile this driver as a module, choose M here: the
+         module will be called uartlite.ko.
+
+config SERIAL_UARTLITE_CONSOLE
+       bool "Support for console on Xilinx uartlite serial port"
+       depends on SERIAL_UARTLITE=y
+       select SERIAL_CORE_CONSOLE
+       help
+         Say Y here if you wish to use a Xilinx uartlite as the system
+         console (the system console is the device which receives all kernel
+         messages and warnings and which allows logins in single user mode).
+
 config SERIAL_SUNCORE
        bool
        depends on SPARC
index b4d8a7c..df3632c 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
 obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
 obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
 obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
 obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
@@ -55,4 +56,5 @@ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
 obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
 obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
 obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
+obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
 obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
index 4213fab..61db697 100644 (file)
@@ -129,6 +129,8 @@ static void pl010_rx_chars(struct uart_port *port)
                 */
                rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
                if (unlikely(rsr & UART01x_RSR_ANY)) {
+                       writel(0, port->membase + UART01x_ECR);
+
                        if (rsr & UART01x_RSR_BE) {
                                rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
                                port->icount.brk++;
@@ -343,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port)
 }
 
 static void
-pl010_set_termios(struct uart_port *port, struct termios *termios,
-                    struct termios *old)
+pl010_set_termios(struct uart_port *port, struct ktermios *termios,
+                    struct ktermios *old)
 {
        unsigned int lcr_h, old_cr;
        unsigned long flags;
index d503625..9a3b374 100644 (file)
@@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port)
 }
 
 static void
-pl011_set_termios(struct uart_port *port, struct termios *termios,
-                    struct termios *old)
+pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+                    struct ktermios *old)
 {
        unsigned int lcr_h, old_cr;
        unsigned long flags;
index 391a1f4..ed7f720 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/char/at91_serial.c
+ *  linux/drivers/char/atmel_serial.c
  *
  *  Driver for Atmel AT91 / AT32 Serial ports
  *  Copyright (C) 2003 Rick Bronson
 
 #include <asm/io.h>
 
-#include <asm/arch/at91rm9200_pdc.h>
 #include <asm/mach/serial_at91.h>
 #include <asm/arch/board.h>
+#include <asm/arch/at91_pdc.h>
 #ifdef CONFIG_ARM
-#include <asm/arch/system.h>
+#include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #endif
 
@@ -137,8 +137,8 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
        unsigned int control = 0;
        unsigned int mode;
 
-#ifdef CONFIG_ARM
-       if (arch_identify() == ARCH_ID_AT91RM9200) {
+#ifdef CONFIG_ARCH_AT91RM9200
+       if (cpu_is_at91rm9200()) {
                /*
                 * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
                 *  We need to drive the pin manually.
@@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned
 /*
  * Change the port parameters
  */
-static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old)
+static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old)
 {
        unsigned long flags;
        unsigned int mode, imr, quot, baud;
index eced2ad..fe1763b 100644 (file)
@@ -31,8 +31,8 @@
 #define                ATMEL_US_RSTIT          (1 << 13)               /* Reset Iterations */
 #define                ATMEL_US_RSTNACK        (1 << 14)               /* Reset Non Acknowledge */
 #define                ATMEL_US_RETTO          (1 << 15)               /* Rearm Time-out */
-#define                ATMEL_US_DTREN          (1 << 16)               /* Data Terminal Ready Enable */
-#define                ATMEL_US_DTRDIS         (1 << 17)               /* Data Terminal Ready Disable */
+#define                ATMEL_US_DTREN          (1 << 16)               /* Data Terminal Ready Enable [AT91RM9200 only] */
+#define                ATMEL_US_DTRDIS         (1 << 17)               /* Data Terminal Ready Disable [AT91RM9200 only] */
 #define                ATMEL_US_RTSEN          (1 << 18)               /* Request To Send Enable */
 #define                ATMEL_US_RTSDIS         (1 << 19)               /* Request To Send Disable */
 
@@ -92,9 +92,9 @@
 #define                ATMEL_US_TXBUFE         (1 << 11)               /* Transmission Buffer Empty */
 #define                ATMEL_US_RXBUFF         (1 << 12)               /* Reception Buffer Full */
 #define                ATMEL_US_NACK           (1 << 13)               /* Non Acknowledge */
-#define                ATMEL_US_RIIC           (1 << 16)               /* Ring Indicator Input Change */
-#define                ATMEL_US_DSRIC          (1 << 17)               /* Data Set Ready Input Change */
-#define                ATMEL_US_DCDIC          (1 << 18)               /* Data Carrier Detect Input Change */
+#define                ATMEL_US_RIIC           (1 << 16)               /* Ring Indicator Input Change [AT91RM9200 only] */
+#define                ATMEL_US_DSRIC          (1 << 17)               /* Data Set Ready Input Change [AT91RM9200 only] */
+#define                ATMEL_US_DCDIC          (1 << 18)               /* Data Carrier Detect Input Change [AT91RM9200 only] */
 #define                ATMEL_US_CTSIC          (1 << 19)               /* Clear to Send Input Change */
 #define                ATMEL_US_RI             (1 << 20)               /* RI */
 #define                ATMEL_US_DSR            (1 << 21)               /* DSR */
 #define ATMEL_US_CSR           0x14                    /* Channel Status Register */
 #define ATMEL_US_RHR           0x18                    /* Receiver Holding Register */
 #define ATMEL_US_THR           0x1c                    /* Transmitter Holding Register */
+#define        ATMEL_US_SYNH           (1 << 15)               /* Transmit/Receive Sync [SAM9 only] */
 
 #define ATMEL_US_BRGR          0x20                    /* Baud Rate Generator Register */
 #define                ATMEL_US_CD             (0xffff << 0)           /* Clock Divider */
index 5980127..2382718 100644 (file)
@@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port)
 }
 
 static void
-clps711xuart_set_termios(struct uart_port *port, struct termios *termios,
-                        struct termios *old)
+clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
+                        struct ktermios *old)
 {
        unsigned int ubrlcr, baud, quot;
        unsigned long flags;
index 7a24e53..42b050c 100644 (file)
@@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = {
 
 #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
 
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
+static struct ktermios *serial_termios[NR_PORTS];
+static struct ktermios *serial_termios_locked[NR_PORTS];
 #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
 static struct fast_timer fast_timers[NR_PORTS];
 #endif
@@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
 }
 
 static void
-rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 
@@ -4877,6 +4877,8 @@ rs_init(void)
        driver->init_termios = tty_std_termios;
        driver->init_termios.c_cflag =
                B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
+       driver->init_termios.c_ispeed = 115200;
+       driver->init_termios.c_ospeed = 115200;
        driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        driver->termios = serial_termios;
        driver->termios_locked = serial_termios_locked;
index f30b93d..4a23340 100644 (file)
@@ -93,8 +93,8 @@ struct e100_serial {
 
        struct work_struct      work;
        struct async_icount     icount;   /* error-statistics etc.*/
-       struct termios          normal_termios;
-       struct termios          callout_termios;
+       struct ktermios         normal_termios;
+       struct ktermios         callout_termios;
 #ifdef DECLARE_WAITQUEUE
        wait_queue_head_t       open_wait;
        wait_queue_head_t       close_wait;
index 53662b3..587d87b 100644 (file)
@@ -1,11 +1,13 @@
 /*
- * dz.c: Serial port driver for DECStations equiped
+ * dz.c: Serial port driver for DECstations equipped
  *       with the DZ chipset.
  *
  * Copyright (C) 1998 Olivier A. D. Lebaillif
  *
  * Email: olivier.lebaillif@ifrsys.com
  *
+ * Copyright (C) 2004, 2006  Maciej W. Rozycki
+ *
  * [31-AUG-98] triemer
  * Changed IRQ to use Harald's dec internals interrupts.h
  * removed base_addr code - moving address assignment to setup.c
 
 #undef DEBUG_DZ
 
+#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#define CONSOLE_LINE (3)       /* for definition of struct console */
-
 #include "dz.h"
 
-#define DZ_INTR_DEBUG 1
-
 static char *dz_name = "DECstation DZ serial driver version ";
-static char *dz_version = "1.02";
+static char *dz_version = "1.03";
 
 struct dz_port {
        struct uart_port        port;
@@ -61,22 +65,6 @@ struct dz_port {
 
 static struct dz_port dz_ports[DZ_NB_PORT];
 
-#ifdef DEBUG_DZ
-/*
- * debugging code to send out chars via prom
- */
-static void debug_console(const char *s, int count)
-{
-       unsigned i;
-
-       for (i = 0; i < count; i++) {
-               if (*s == 10)
-                       prom_printf("%c", 13);
-               prom_printf("%c", *s++);
-       }
-}
-#endif
-
 /*
  * ------------------------------------------------------------
  * dz_in () and dz_out ()
@@ -90,6 +78,7 @@ static inline unsigned short dz_in(struct dz_port *dport, unsigned offset)
 {
        volatile unsigned short *addr =
                (volatile unsigned short *) (dport->port.membase + offset);
+
        return *addr;
 }
 
@@ -98,6 +87,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset,
 {
        volatile unsigned short *addr =
                (volatile unsigned short *) (dport->port.membase + offset);
+
        *addr = value;
 }
 
@@ -144,7 +134,7 @@ static void dz_stop_rx(struct uart_port *uport)
 
        spin_lock_irqsave(&dport->port.lock, flags);
        dport->cflag &= ~DZ_CREAD;
-       dz_out(dport, DZ_LPR, dport->cflag);
+       dz_out(dport, DZ_LPR, dport->cflag | dport->port.line);
        spin_unlock_irqrestore(&dport->port.lock, flags);
 }
 
@@ -155,14 +145,14 @@ static void dz_enable_ms(struct uart_port *port)
 
 /*
  * ------------------------------------------------------------
- * Here starts the interrupt handling routines.  All of the
- * following subroutines are declared as inline and are folded
- * into dz_interrupt.  They were separated out for readability's
- * sake.
  *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * Here start the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * dz_interrupt.  They were separated out for readability's sake.
+ *
+ * Note: dz_interrupt() is a "fast" interrupt, which means that it
  * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
+ * dz_interrupt() should try to keep the interrupt handler as fast as
  * possible.  After you are done making modifications, it is not a bad
  * idea to do:
  *
@@ -180,92 +170,74 @@ static void dz_enable_ms(struct uart_port *port)
  * This routine deals with inputs from any lines.
  * ------------------------------------------------------------
  */
-static inline void dz_receive_chars(struct dz_port *dport)
+static inline void dz_receive_chars(struct dz_port *dport_in,
+                                   struct pt_regs *regs)
 {
+       struct dz_port *dport;
        struct tty_struct *tty = NULL;
        struct uart_icount *icount;
-       int ignore = 0;
-       unsigned short status, tmp;
+       int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };
+       unsigned short status;
        unsigned char ch, flag;
+       int i;
 
-       /* this code is going to be a problem...
-          the call to tty_flip_buffer is going to need
-          to be rethought...
-        */
-       do {
-               status = dz_in(dport, DZ_RBUF);
-
-               /* punt so we don't get duplicate characters */
-               if (!(status & DZ_DVAL))
-                       goto ignore_char;
-
-
-               ch = UCHAR(status);     /* grab the char */
-               flag = TTY_NORMAL;
+       while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) {
+               dport = &dz_ports[LINE(status)];
+               tty = dport->port.info->tty;    /* point to the proper dev */
 
-#if 0
-               if (info->is_console) {
-                       if (ch == 0)
-                               return;         /* it's a break ... */
-               }
-#endif
+               ch = UCHAR(status);             /* grab the char */
 
-               tty = dport->port.info->tty;/* now tty points to the proper dev */
                icount = &dport->port.icount;
-
-               if (!tty)
-                       break;
-
                icount->rx++;
 
-               /* keep track of the statistics */
-               if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
-                       if (status & DZ_PERR)   /* parity error */
-                               icount->parity++;
-                       else if (status & DZ_FERR)      /* frame error */
-                               icount->frame++;
-                       if (status & DZ_OERR)   /* overrun error */
-                               icount->overrun++;
-
-                       /*  check to see if we should ignore the character
-                          and mask off conditions that should be ignored
+               flag = TTY_NORMAL;
+               if (status & DZ_FERR) {         /* frame error */
+                       /*
+                        * There is no separate BREAK status bit, so
+                        * treat framing errors as BREAKs for Magic SysRq
+                        * and SAK; normally, otherwise.
                         */
-
-                       if (status & dport->port.ignore_status_mask) {
-                               if (++ignore > 100)
-                                       break;
-                               goto ignore_char;
-                       }
-                       /* mask off the error conditions we want to ignore */
-                       tmp = status & dport->port.read_status_mask;
-
-                       if (tmp & DZ_PERR) {
-                               flag = TTY_PARITY;
-#ifdef DEBUG_DZ
-                               debug_console("PERR\n", 5);
-#endif
-                       } else if (tmp & DZ_FERR) {
+                       if (uart_handle_break(&dport->port))
+                               continue;
+                       if (dport->port.flags & UPF_SAK)
+                               flag = TTY_BREAK;
+                       else
                                flag = TTY_FRAME;
-#ifdef DEBUG_DZ
-                               debug_console("FERR\n", 5);
-#endif
-                       }
-                       if (tmp & DZ_OERR) {
-#ifdef DEBUG_DZ
-                               debug_console("OERR\n", 5);
-#endif
-                               tty_insert_flip_char(tty, ch, flag);
-                               ch = 0;
-                               flag = TTY_OVERRUN;
-                       }
+               } else if (status & DZ_OERR)    /* overrun error */
+                       flag = TTY_OVERRUN;
+               else if (status & DZ_PERR)      /* parity error */
+                       flag = TTY_PARITY;
+
+               /* keep track of the statistics */
+               switch (flag) {
+               case TTY_FRAME:
+                       icount->frame++;
+                       break;
+               case TTY_PARITY:
+                       icount->parity++;
+                       break;
+               case TTY_OVERRUN:
+                       icount->overrun++;
+                       break;
+               case TTY_BREAK:
+                       icount->brk++;
+                       break;
+               default:
+                       break;
                }
-               tty_insert_flip_char(tty, ch, flag);
-             ignore_char:
-                       ;
-       } while (status & DZ_DVAL);
 
-       if (tty)
-               tty_flip_buffer_push(tty);
+               if (uart_handle_sysrq_char(&dport->port, ch, regs))
+                       continue;
+
+               if ((status & dport->port.ignore_status_mask) == 0) {
+                       uart_insert_char(&dport->port,
+                                        status, DZ_OERR, ch, flag);
+                       lines_rx[LINE(status)] = 1;
+               }
+       }
+       for (i = 0; i < DZ_NB_PORT; i++)
+               if (lines_rx[i])
+                       tty_flip_buffer_push(dz_ports[i].port.info->tty);
 }
 
 /*
@@ -275,26 +247,32 @@ static inline void dz_receive_chars(struct dz_port *dport)
  * This routine deals with outputs to any lines.
  * ------------------------------------------------------------
  */
-static inline void dz_transmit_chars(struct dz_port *dport)
+static inline void dz_transmit_chars(struct dz_port *dport_in)
 {
-       struct circ_buf *xmit = &dport->port.info->xmit;
+       struct dz_port *dport;
+       struct circ_buf *xmit;
+       unsigned short status;
        unsigned char tmp;
 
-       if (dport->port.x_char) {       /* XON/XOFF chars */
+       status = dz_in(dport_in, DZ_CSR);
+       dport = &dz_ports[LINE(status)];
+       xmit = &dport->port.info->xmit;
+
+       if (dport->port.x_char) {               /* XON/XOFF chars */
                dz_out(dport, DZ_TDR, dport->port.x_char);
                dport->port.icount.tx++;
                dport->port.x_char = 0;
                return;
        }
-       /* if nothing to do or stopped or hardware stopped */
+       /* If nothing to do or stopped or hardware stopped. */
        if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
                dz_stop_tx(&dport->port);
                return;
        }
 
        /*
-        * if something to do ... (rember the dz has no output fifo so we go
-        * one char at a time :-<
+        * If something to do... (remember the dz has no output fifo,
+        * so we go one char at a time) :-<
         */
        tmp = xmit->buf[xmit->tail];
        xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
@@ -304,23 +282,29 @@ static inline void dz_transmit_chars(struct dz_port *dport)
        if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
                uart_write_wakeup(&dport->port);
 
-       /* Are we done */
+       /* Are we are done. */
        if (uart_circ_empty(xmit))
                dz_stop_tx(&dport->port);
 }
 
 /*
  * ------------------------------------------------------------
- * check_modem_status ()
+ * check_modem_status()
  *
- * Only valid for the MODEM line duh !
+ * DS 3100 & 5100: Only valid for the MODEM line, duh!
+ * DS 5000/200: Valid for the MODEM and PRINTER line.
  * ------------------------------------------------------------
  */
 static inline void check_modem_status(struct dz_port *dport)
 {
+       /*
+        * FIXME:
+        * 1. No status change interrupt; use a timer.
+        * 2. Handle the 3100/5000 as appropriate. --macro
+        */
        unsigned short status;
 
-       /* if not ne modem line just return */
+       /* If not the modem line just return.  */
        if (dport->port.line != DZ_MODEM)
                return;
 
@@ -341,21 +325,18 @@ static inline void check_modem_status(struct dz_port *dport)
  */
 static irqreturn_t dz_interrupt(int irq, void *dev)
 {
-       struct dz_port *dport;
+       struct dz_port *dport = (struct dz_port *)dev;
        unsigned short status;
 
        /* get the reason why we just got an irq */
-       status = dz_in((struct dz_port *)dev, DZ_CSR);
-       dport = &dz_ports[LINE(status)];
+       status = dz_in(dport, DZ_CSR);
 
-       if (status & DZ_RDONE)
-               dz_receive_chars(dport);
+       if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))
+               dz_receive_chars(dport, regs);
 
-       if (status & DZ_TRDY)
+       if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))
                dz_transmit_chars(dport);
 
-       /* FIXME: what about check modem status??? --rmk */
-
        return IRQ_HANDLED;
 }
 
@@ -367,13 +348,13 @@ static irqreturn_t dz_interrupt(int irq, void *dev)
 
 static unsigned int dz_get_mctrl(struct uart_port *uport)
 {
+       /*
+        * FIXME: Handle the 3100/5000 as appropriate. --macro
+        */
        struct dz_port *dport = (struct dz_port *)uport;
        unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
 
        if (dport->port.line == DZ_MODEM) {
-               /*
-                * CHECKME: This is a guess from the other code... --rmk
-                */
                if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
                        mctrl &= ~TIOCM_DSR;
        }
@@ -383,6 +364,9 @@ static unsigned int dz_get_mctrl(struct uart_port *uport)
 
 static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
 {
+       /*
+        * FIXME: Handle the 3100/5000 as appropriate. --macro
+        */
        struct dz_port *dport = (struct dz_port *)uport;
        unsigned short tmp;
 
@@ -409,13 +393,6 @@ static int dz_startup(struct uart_port *uport)
        unsigned long flags;
        unsigned short tmp;
 
-       /* The dz lines for the mouse/keyboard must be
-        * opened using their respective drivers.
-        */
-       if ((dport->port.line == DZ_KEYBOARD) ||
-           (dport->port.line == DZ_MOUSE))
-               return -ENODEV;
-
        spin_lock_irqsave(&dport->port.lock, flags);
 
        /* enable the interrupt and the scanning */
@@ -442,7 +419,8 @@ static void dz_shutdown(struct uart_port *uport)
 }
 
 /*
- * get_lsr_info - get line status register info
+ * -------------------------------------------------------------------
+ * dz_tx_empty() -- get the transmitter empty status
  *
  * Purpose: Let user call ioctl() to get info when the UART physically
  *          is emptied.  On bus types like RS485, the transmitter must
@@ -450,21 +428,28 @@ static void dz_shutdown(struct uart_port *uport)
  *          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 unsigned int dz_tx_empty(struct uart_port *uport)
 {
        struct dz_port *dport = (struct dz_port *)uport;
-       unsigned short status = dz_in(dport, DZ_LPR);
+       unsigned short tmp, mask = 1 << dport->port.line;
 
-       /* FIXME: this appears to be obviously broken --rmk. */
-       return status ? TIOCSER_TEMT : 0;
+       tmp = dz_in(dport, DZ_TCR);
+       tmp &= mask;
+
+       return tmp ? 0 : TIOCSER_TEMT;
 }
 
 static void dz_break_ctl(struct uart_port *uport, int break_state)
 {
+       /*
+        * FIXME: Can't access BREAK bits in TDR easily;
+        * reuse the code for polled TX. --macro
+        */
        struct dz_port *dport = (struct dz_port *)uport;
        unsigned long flags;
-       unsigned short tmp, mask = 1 << uport->line;
+       unsigned short tmp, mask = 1 << dport->port.line;
 
        spin_lock_irqsave(&uport->lock, flags);
        tmp = dz_in(dport, DZ_TCR);
@@ -476,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state)
        spin_unlock_irqrestore(&uport->lock, flags);
 }
 
-static void dz_set_termios(struct uart_port *uport, struct termios *termios,
-                          struct termios *old_termios)
+static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
+                          struct ktermios *old_termios)
 {
        struct dz_port *dport = (struct dz_port *)uport;
        unsigned long flags;
@@ -561,7 +546,7 @@ static void dz_set_termios(struct uart_port *uport, struct termios *termios,
 
        spin_lock_irqsave(&dport->port.lock, flags);
 
-       dz_out(dport, DZ_LPR, cflag);
+       dz_out(dport, DZ_LPR, cflag | dport->port.line);
        dport->cflag = cflag;
 
        /* setup accept flag */
@@ -650,7 +635,7 @@ static void __init dz_init_ports(void)
        for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
                spin_lock_init(&dport->port.lock);
                dport->port.membase     = (char *) base;
-               dport->port.iotype      = UPIO_PORT;
+               dport->port.iotype      = UPIO_MEM;
                dport->port.irq         = dec_interrupt[DEC_IRQ_DZ11];
                dport->port.line        = i;
                dport->port.fifosize    = 1;
@@ -662,10 +647,7 @@ static void __init dz_init_ports(void)
 static void dz_reset(struct dz_port *dport)
 {
        dz_out(dport, DZ_CSR, DZ_CLR);
-
        while (dz_in(dport, DZ_CSR) & DZ_CLR);
-               /* FIXME: cpu_relax? */
-
        iob();
 
        /* enable scanning */
@@ -673,26 +655,55 @@ static void dz_reset(struct dz_port *dport)
 }
 
 #ifdef CONFIG_SERIAL_DZ_CONSOLE
+/*
+ * -------------------------------------------------------------------
+ * dz_console_putchar() -- transmit a character
+ *
+ * Polled transmission.  This is tricky.  We need to mask transmit
+ * interrupts so that they do not interfere, enable the transmitter
+ * for the line requested and then wait till the transmit scanner
+ * requests data for this line.  But it may request data for another
+ * line first, in which case we have to disable its transmitter and
+ * repeat waiting till our line pops up.  Only then the character may
+ * be transmitted.  Finally, the state of the transmitter mask is
+ * restored.  Welcome to the world of PDP-11!
+ * -------------------------------------------------------------------
+ */
 static void dz_console_putchar(struct uart_port *uport, int ch)
 {
        struct dz_port *dport = (struct dz_port *)uport;
        unsigned long flags;
-       int loops = 2500;
-       unsigned short tmp = (unsigned char)ch;
-       /* this code sends stuff out to serial device - spinning its
-          wheels and waiting. */
+       unsigned short csr, tcr, trdy, mask;
+       int loops = 10000;
 
        spin_lock_irqsave(&dport->port.lock, flags);
+       csr = dz_in(dport, DZ_CSR);
+       dz_out(dport, DZ_CSR, csr & ~DZ_TIE);
+       tcr = dz_in(dport, DZ_TCR);
+       tcr |= 1 << dport->port.line;
+       mask = tcr;
+       dz_out(dport, DZ_TCR, mask);
+       iob();
+       spin_unlock_irqrestore(&dport->port.lock, flags);
 
-       /* spin our wheels */
-       while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
-               /* FIXME: cpu_relax, udelay? --rmk */
-               ;
+       while (loops--) {
+               trdy = dz_in(dport, DZ_CSR);
+               if (!(trdy & DZ_TRDY))
+                       continue;
+               trdy = (trdy & DZ_TLINE) >> 8;
+               if (trdy == dport->port.line)
+                       break;
+               mask &= ~(1 << trdy);
+               dz_out(dport, DZ_TCR, mask);
+               iob();
+               udelay(2);
+       }
 
-       /* Actually transmit the character. */
-       dz_out(dport, DZ_TDR, tmp);
+       if (loops)                              /* Cannot send otherwise. */
+               dz_out(dport, DZ_TDR, ch);
 
-       spin_unlock_irqrestore(&dport->port.lock, flags);
+       dz_out(dport, DZ_TCR, tcr);
+       dz_out(dport, DZ_CSR, csr);
 }
 
 /*
@@ -703,11 +714,11 @@ static void dz_console_putchar(struct uart_port *uport, int ch)
  * The console must be locked when we get here.
  * -------------------------------------------------------------------
  */
-static void dz_console_print(struct console *cons,
+static void dz_console_print(struct console *co,
                             const char *str,
                             unsigned int count)
 {
-       struct dz_port *dport = &dz_ports[CONSOLE_LINE];
+       struct dz_port *dport = &dz_ports[co->index];
 #ifdef DEBUG_DZ
        prom_printf((char *) str);
 #endif
@@ -716,49 +727,43 @@ static void dz_console_print(struct console *cons,
 
 static int __init dz_console_setup(struct console *co, char *options)
 {
-       struct dz_port *dport = &dz_ports[CONSOLE_LINE];
+       struct dz_port *dport = &dz_ports[co->index];
        int baud = 9600;
        int bits = 8;
        int parity = 'n';
        int flow = 'n';
-       int ret;
-       unsigned short mask, tmp;
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
        dz_reset(dport);
 
-       ret = uart_set_options(&dport->port, co, baud, parity, bits, flow);
-       if (ret == 0) {
-               mask = 1 << dport->port.line;
-               tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
-               if (!(tmp & mask)) {
-                       tmp |= mask;            /* set the TX flag */
-                       dz_out(dport, DZ_TCR, tmp);
-               }
-       }
-
-       return ret;
+       return uart_set_options(&dport->port, co, baud, parity, bits, flow);
 }
 
-static struct console dz_sercons =
-{
+static struct uart_driver dz_reg;
+static struct console dz_sercons = {
        .name   = "ttyS",
        .write  = dz_console_print,
        .device = uart_console_device,
        .setup  = dz_console_setup,
-       .flags  = CON_CONSDEV | CON_PRINTBUFFER,
-       .index  = CONSOLE_LINE,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
+       .data   = &dz_reg,
 };
 
-void __init dz_serial_console_init(void)
+static int __init dz_serial_console_init(void)
 {
-       dz_init_ports();
-
-       register_console(&dz_sercons);
+       if (!IOASIC) {
+               dz_init_ports();
+               register_console(&dz_sercons);
+               return 0;
+       } else
+               return -ENXIO;
 }
 
+console_initcall(dz_serial_console_init);
+
 #define SERIAL_DZ_CONSOLE      &dz_sercons
 #else
 #define SERIAL_DZ_CONSOLE      NULL
@@ -767,35 +772,29 @@ void __init dz_serial_console_init(void)
 static struct uart_driver dz_reg = {
        .owner                  = THIS_MODULE,
        .driver_name            = "serial",
-       .dev_name               = "ttyS%d",
+       .dev_name               = "ttyS",
        .major                  = TTY_MAJOR,
        .minor                  = 64,
        .nr                     = DZ_NB_PORT,
        .cons                   = SERIAL_DZ_CONSOLE,
 };
 
-int __init dz_init(void)
+static int __init dz_init(void)
 {
-       unsigned long flags;
        int ret, i;
 
+       if (IOASIC)
+               return -ENXIO;
+
        printk("%s%s\n", dz_name, dz_version);
 
        dz_init_ports();
 
-       save_flags(flags);
-       cli();
-
 #ifndef CONFIG_SERIAL_DZ_CONSOLE
        /* reset the chip */
        dz_reset(&dz_ports[0]);
 #endif
 
-       /* order matters here... the trick is that flags
-          is updated... in request_irq - to immediatedly obliterate
-          it is unwise. */
-       restore_flags(flags);
-
        if (request_irq(dz_ports[0].port.irq, dz_interrupt,
                        IRQF_DISABLED, "DZ", &dz_ports[0]))
                panic("Unable to register DZ interrupt");
@@ -810,5 +809,7 @@ int __init dz_init(void)
        return ret;
 }
 
+module_init(dz_init);
+
 MODULE_DESCRIPTION("DECstation DZ serial driver");
 MODULE_LICENSE("GPL");
index 86ef417..9674d4e 100644 (file)
@@ -1,20 +1,22 @@
 /*
- * dz.h: Serial port driver for DECStations equiped 
+ * dz.h: Serial port driver for DECstations equipped
  *       with the DZ chipset.
  *
  * Copyright (C) 1998 Olivier A. D. Lebaillif 
  *             
  * Email: olivier.lebaillif@ifrsys.com
  *
+ * Copyright (C) 2004, 2006  Maciej W. Rozycki
  */
 #ifndef DZ_SERIAL_H
 #define DZ_SERIAL_H
 
 /*
- * Definitions for the Control and Status Received.
+ * Definitions for the Control and Status Register.
  */
 #define DZ_TRDY        0x8000                 /* Transmitter empty */
-#define DZ_TIE         0x4000                 /* Transmitter Interrupt Enable */
+#define DZ_TIE         0x4000                 /* Transmitter Interrupt Enbl */
+#define DZ_TLINE       0x0300                 /* Transmitter Line Number */
 #define DZ_RDONE       0x0080                 /* Receiver data ready */
 #define DZ_RIE         0x0040                 /* Receive Interrupt Enable */
 #define DZ_MSE         0x0020                 /* Master Scan Enable */
 #define DZ_MAINT       0x0008                 /* Loop Back Mode */
 
 /*
- * Definitions for the Received buffer. 
+ * Definitions for the Receiver Buffer Register.
  */
-#define DZ_RBUF_MASK   0x00FF                 /* Data Mask in the Receive Buffer */
-#define DZ_LINE_MASK   0x0300                 /* Line Mask in the Receive Buffer */
+#define DZ_RBUF_MASK   0x00FF                 /* Data Mask */
+#define DZ_LINE_MASK   0x0300                 /* Line Mask */
 #define DZ_DVAL        0x8000                 /* Valid Data indicator */
 #define DZ_OERR        0x4000                 /* Overrun error indicator */
 #define DZ_FERR        0x2000                 /* Frame error indicator */
 #define DZ_PERR        0x1000                 /* Parity error indicator */
 
-#define LINE(x) (x & DZ_LINE_MASK) >> 8       /* Get the line number from the input buffer */
-#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK)
+#define LINE(x) ((x & DZ_LINE_MASK) >> 8)     /* Get the line number
+                                                 from the input buffer */
+#define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK))
 
 /*
- * Definitions for the Transmit Register.
+ * Definitions for the Transmit Control Register.
  */
 #define DZ_LINE_KEYBOARD 0x0001
 #define DZ_LINE_MOUSE    0x0002
 #define DZ_LINE_MODEM    0x0004
 #define DZ_LINE_PRINTER  0x0008
 
+#define DZ_MODEM_RTS     0x0800               /* RTS for the modem line (2) */
 #define DZ_MODEM_DTR     0x0400               /* DTR for the modem line (2) */
+#define DZ_PRINT_RTS     0x0200               /* RTS for the prntr line (3) */
+#define DZ_PRINT_DTR     0x0100               /* DTR for the prntr line (3) */
+#define DZ_LNENB         0x000f               /* Transmitter Line Enable */
 
 /*
  * Definitions for the Modem Status Register.
  */
+#define DZ_MODEM_RI      0x0800               /* RI for the modem line (2) */
+#define DZ_MODEM_CD      0x0400               /* CD for the modem line (2) */
 #define DZ_MODEM_DSR     0x0200               /* DSR for the modem line (2) */
+#define DZ_MODEM_CTS     0x0100               /* CTS for the modem line (2) */
+#define DZ_PRINT_RI      0x0008               /* RI for the printer line (3) */
+#define DZ_PRINT_CD      0x0004               /* CD for the printer line (3) */
+#define DZ_PRINT_DSR     0x0002               /* DSR for the prntr line (3) */
+#define DZ_PRINT_CTS     0x0001               /* CTS for the prntr line (3) */
 
 /*
  * Definitions for the Transmit Data Register.
index 8aa0f64..7d62300 100644 (file)
@@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port)
 }
 
 static void icom_set_termios(struct uart_port *port,
-                            struct termios *termios,
-                            struct termios *old_termios)
+                            struct ktermios *termios,
+                            struct ktermios *old_termios)
 {
        int baud;
        unsigned cflag, iflag;
index ee5c782..e216dcf 100644 (file)
@@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port)
 }
 
 static void
-imx_set_termios(struct uart_port *port, struct termios *termios,
-                  struct termios *old)
+imx_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long flags;
index 2308d26..9cc0be9 100644 (file)
@@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port)
  */
 static void
 ioc3_change_speed(struct uart_port *the_port,
-                 struct termios *new_termios, struct termios *old_termios)
+                 struct ktermios *new_termios, struct ktermios *old_termios)
 {
        struct ioc3_port *port = get_ioc3_port(the_port);
        unsigned int cflag;
@@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port)
  */
 static void
 ic3_set_termios(struct uart_port *the_port,
-               struct termios *termios, struct termios *old_termios)
+               struct ktermios *termios, struct ktermios *old_termios)
 {
        unsigned long port_flags;
 
index 711bd15..c862f67 100644 (file)
@@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port)
  */
 static void
 ioc4_change_speed(struct uart_port *the_port,
-                 struct termios *new_termios, struct termios *old_termios)
+                 struct ktermios *new_termios, struct ktermios *old_termios)
 {
        struct ioc4_port *port = get_ioc4_port(the_port, 0);
        int baud, bits;
@@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port)
        ioc4_set_proto(port, the_port->mapbase);
 
        /* set the speed of the serial port */
-       ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
+       ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0);
 
        return 0;
 }
@@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port)
  */
 static void
 ic4_set_termios(struct uart_port *the_port,
-               struct termios *termios, struct termios *old_termios)
+               struct ktermios *termios, struct ktermios *old_termios)
 {
        unsigned long port_flags;
 
index dca6c1b..0746c94 100644 (file)
@@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
 
 /* The port lock is not held.  */
 static void
-ip22zilog_set_termios(struct uart_port *port, struct termios *termios,
-                     struct termios *old)
+ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
+                     struct ktermios *old)
 {
        struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
        unsigned long flags;
index f8262e6..7cf1c60 100644 (file)
@@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
 {
        unsigned long lock_flags;
        struct jsm_channel *channel = (struct jsm_channel *)port;
-       struct termios *termios;
+       struct ktermios *termios;
 
        spin_lock_irqsave(&port->lock, lock_flags);
        termios = port->info->tty->termios;
@@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port)
        struct jsm_board *brd;
        int rc = 0;
        struct jsm_channel *channel = (struct jsm_channel *)port;
-       struct termios *termios;
+       struct ktermios *termios;
 
        /* Get board pointer from our array of majors we have allocated */
        brd = channel->ch_bd;
@@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port)
 static void jsm_tty_close(struct uart_port *port)
 {
        struct jsm_board *bd;
-       struct termios *ts;
+       struct ktermios *ts;
        struct jsm_channel *channel = (struct jsm_channel *)port;
 
        jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
@@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port)
 }
 
 static void jsm_tty_set_termios(struct uart_port *port,
-                                struct termios *termios,
-                                struct termios *old_termios)
+                                struct ktermios *termios,
+                                struct ktermios *old_termios)
 {
        unsigned long lock_flags;
        struct jsm_channel *channel = (struct jsm_channel *)port;
index 7656a35..6e09c8b 100644 (file)
@@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port,
 }
 
 static void m32r_sio_set_termios(struct uart_port *port,
-       struct termios *termios, struct termios *old)
+       struct ktermios *termios, struct ktermios *old)
 {
        struct uart_sio_port *up = (struct uart_sio_port *)port;
        unsigned char cval = 0;
index aee1b31..0843096 100644 (file)
@@ -60,7 +60,8 @@ struct timer_list mcfrs_timer_struct;
 #if defined(CONFIG_HW_FEITH)
 #define        CONSOLE_BAUD_RATE       38400
 #define        DEFAULT_CBAUD           B38400
-#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \
+      defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO)
 #define CONSOLE_BAUD_RATE      115200
 #define DEFAULT_CBAUD          B115200
 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
@@ -109,12 +110,30 @@ static struct mcf_serial mcfrs_table[] = {
                .irq = IRQBASE,
                .flags = ASYNC_BOOT_AUTOCONF,
        },
+#ifdef MCFUART_BASE2
        {  /* ttyS1 */
                .magic = 0,
                .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2),
                .irq = IRQBASE+1,
                .flags = ASYNC_BOOT_AUTOCONF,
        },
+#endif
+#ifdef MCFUART_BASE3
+       {  /* ttyS2 */
+               .magic = 0,
+               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3),
+               .irq = IRQBASE+2,
+               .flags = ASYNC_BOOT_AUTOCONF,
+       },
+#endif
+#ifdef MCFUART_BASE4
+       {  /* ttyS3 */
+               .magic = 0,
+               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4),
+               .irq = IRQBASE+3,
+               .flags = ASYNC_BOOT_AUTOCONF,
+       },
+#endif
 };
 
 
@@ -1113,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
        return 0;
 }
 
-static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
 
@@ -1516,6 +1535,22 @@ static void mcfrs_irqinit(struct mcf_serial *info)
        imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
                MCFINTC_IMRL);
        *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
+#if defined(CONFIG_M527x)
+       {
+               /*
+                * External Pin Mask Setting & Enable External Pin for Interface
+                * mrcbis@aliceposta.it
+                */
+               unsigned short *serpin_enable_mask;
+               serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART);
+               if (info->line == 0)
+                       *serpin_enable_mask |= UART0_ENABLE_MASK;
+               else if (info->line == 1)
+                       *serpin_enable_mask |= UART1_ENABLE_MASK;
+               else if (info->line == 2)
+                       *serpin_enable_mask |= UART2_ENABLE_MASK;
+       }
+#endif
 #elif defined(CONFIG_M520x)
        volatile unsigned char *icrp, *uartp;
        volatile unsigned long *imrp;
@@ -1713,7 +1748,7 @@ mcfrs_init(void)
        /* Initialize the tty_driver structure */
        mcfrs_serial_driver->owner = THIS_MODULE;
        mcfrs_serial_driver->name = "ttyS";
-       mcfrs_serial_driver->driver_name = "serial";
+       mcfrs_serial_driver->driver_name = "mcfserial";
        mcfrs_serial_driver->major = TTY_MAJOR;
        mcfrs_serial_driver->minor_start = 64;
        mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
@@ -1797,10 +1832,23 @@ void mcfrs_init_console(void)
        uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
        uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
 
+#ifdef CONFIG_M5272
+{
+       /*
+        * For the MCF5272, also compute the baudrate fraction.
+        */
+       int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud);
+       fraction *= 16;
+       fraction /= (32 * mcfrs_console_baud);
+       uartp[MCFUART_UFPD] = (fraction & 0xf);         /* set fraction */
+       clk = (MCF_BUSCLK / mcfrs_console_baud) / 32;
+}
+#else
        clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */
+#endif
+
        uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8;  /* set msb baud */
        uartp[MCFUART_UBG2] = (clk & 0xff);  /* set lsb baud */
-
        uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
        uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
 
index 6dd579e..9d11a75 100644 (file)
@@ -270,8 +270,8 @@ mpc52xx_uart_shutdown(struct uart_port *port)
 }
 
 static void
-mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
-                         struct termios *old)
+mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
+                         struct ktermios *old)
 {
        struct mpc52xx_psc __iomem *psc = PSC(port);
        unsigned long flags;
index 8eea69f..3d2fcc5 100644 (file)
@@ -555,7 +555,7 @@ mpsc_sdma_start_tx(struct mpsc_port_info *pi)
        if (!mpsc_sdma_tx_active(pi)) {
                txre = (struct mpsc_tx_desc *)(pi->txr +
                        (pi->txr_tail * MPSC_TXRE_SIZE));
-               dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)txre,
@@ -931,7 +931,7 @@ mpsc_init_rings(struct mpsc_port_info *pi)
        }
        txre->link = cpu_to_be32(pi->txr_p);    /* Wrap last back to first */
 
-       dma_cache_sync((void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE,
+       dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE,
                DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
@@ -1005,7 +1005,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi)
 
        rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE));
 
-       dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+       dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                invalidate_dcache_range((ulong)rxre,
@@ -1029,7 +1029,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi)
                }
 
                bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
-               dma_cache_sync((void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)bp,
@@ -1098,7 +1098,7 @@ next_frame:
                                            SDMA_DESC_CMDSTAT_F |
                                            SDMA_DESC_CMDSTAT_L);
                wmb();
-               dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)rxre,
@@ -1109,7 +1109,7 @@ next_frame:
                pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1);
                rxre = (struct mpsc_rx_desc *)(pi->rxr +
                        (pi->rxr_posn * MPSC_RXRE_SIZE));
-               dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)rxre,
@@ -1143,7 +1143,7 @@ mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr)
                                                           SDMA_DESC_CMDSTAT_EI
                                                           : 0));
        wmb();
-       dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL);
+       dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                flush_dcache_range((ulong)txre,
@@ -1192,7 +1192,7 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi)
                else /* All tx data copied into ring bufs */
                        return;
 
-               dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)bp,
@@ -1217,7 +1217,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
                txre = (struct mpsc_tx_desc *)(pi->txr +
                        (pi->txr_tail * MPSC_TXRE_SIZE));
 
-               dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)txre,
@@ -1235,7 +1235,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
 
                        txre = (struct mpsc_tx_desc *)(pi->txr +
                                (pi->txr_tail * MPSC_TXRE_SIZE));
-                       dma_cache_sync((void *) txre, MPSC_TXRE_SIZE,
+                       dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE,
                                DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
@@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port)
 }
 
 static void
-mpsc_set_termios(struct uart_port *port, struct termios *termios,
-                struct termios *old)
+mpsc_set_termios(struct uart_port *port, struct ktermios *termios,
+                struct ktermios *old)
 {
        struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
        u32 baud;
@@ -1652,7 +1652,7 @@ mpsc_console_write(struct console *co, const char *s, uint count)
                        count--;
                }
 
-               dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)bp,
index 8ad1b8c..ccb8fa1 100644 (file)
@@ -273,8 +273,8 @@ static void mux_shutdown(struct uart_port *port)
  * The Serial Mux does not support this function.
  */
 static void
-mux_set_termios(struct uart_port *port, struct termios *termios,
-               struct termios *old)
+mux_set_termios(struct uart_port *port, struct ktermios *termios,
+               struct ktermios *old)
 {
 }
 
index 062bad4..b56f7db 100644 (file)
@@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port)
 }
 
 static void
-netx_set_termios(struct uart_port *port, struct termios *termios,
-                  struct termios *old)
+netx_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
 {
        unsigned int baud, quot;
        unsigned char old_cr;
index bf9809e..752ef07 100644 (file)
@@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
 }
 
 
-static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
-                             struct termios *old)
+static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
+                             struct ktermios *old)
 {
        struct uart_pmac_port *uap = to_pmz(port);
        unsigned long baud;
@@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
        if (ZS_IS_ASLEEP(uap))
                return;
 
-       memcpy(&uap->termios_cache, termios, sizeof(struct termios));
+       memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
 
        /* XXX Check which revs of machines actually allow 1 and 4Mb speeds
         * on the IR dongle. Note that the IRTTY driver currently doesn't know
@@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
 }
 
 /* The port lock is not held.  */
-static void pmz_set_termios(struct uart_port *port, struct termios *termios,
-                           struct termios *old)
+static void pmz_set_termios(struct uart_port *port, struct ktermios *termios,
+                           struct ktermios *old)
 {
        struct uart_pmac_port *uap = to_pmz(port);
        unsigned long flags;
index c03f9bf..570b0d9 100644 (file)
@@ -60,7 +60,7 @@ struct uart_pmac_port {
        volatile struct dbdma_regs      __iomem *tx_dma_regs;
        volatile struct dbdma_regs      __iomem *rx_dma_regs;
 
-       struct termios                  termios_cache;
+       struct ktermios                 termios_cache;
 };
 
 #define to_pmz(p) ((struct uart_pmac_port *)(p))
index 415fe96..d403aaa 100644 (file)
@@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port)
 }
 
 static void
-serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
-                      struct termios *old)
+serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
 {
        struct uart_pxa_port *up = (struct uart_pxa_port *)port;
        unsigned char cval, fcr = 0;
index 8dfc2dd..3ba9208 100644 (file)
@@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
 }
 
 static void s3c24xx_serial_set_termios(struct uart_port *port,
-                                      struct termios *termios,
-                                      struct termios *old)
+                                      struct ktermios *termios,
+                                      struct ktermios *old)
 {
        struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
        struct s3c24xx_uart_port *ourport = to_ourport(port);
index d406526..58a83c2 100644 (file)
@@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port)
 }
 
 static void
-sa1100_set_termios(struct uart_port *port, struct termios *termios,
-                  struct termios *old)
+sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old)
 {
        struct sa1100_port *sport = (struct sa1100_port *)port;
        unsigned long flags;
index c67b05e..f84982e 100644 (file)
@@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key;
 #define uart_console(port)     (0)
 #endif
 
-static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
+static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios);
 static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
 static void uart_change_pm(struct uart_state *state, int pm_state);
 
@@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout);
  *     we're actually going to be using.
  */
 unsigned int
-uart_get_baud_rate(struct uart_port *port, struct termios *termios,
-                  struct termios *old, unsigned int min, unsigned int max)
+uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old, unsigned int min, unsigned int max)
 {
        unsigned int try, baud, altbaud = 38400;
        upf_t flags = port->flags & UPF_SPD_MASK;
@@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
 EXPORT_SYMBOL(uart_get_divisor);
 
 static void
-uart_change_speed(struct uart_state *state, struct termios *old_termios)
+uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
 {
        struct tty_struct *tty = state->info->tty;
        struct uart_port *port = state->port;
-       struct termios *termios;
+       struct ktermios *termios;
 
        /*
         * If we have no tty, termios, or the port does not exist,
@@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
        return ret;
 }
 
-static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct uart_state *state = tty->driver_data;
        unsigned long flags;
@@ -1866,7 +1866,7 @@ int __init
 uart_set_options(struct uart_port *port, struct console *co,
                 int baud, int parity, int bits, int flow)
 {
-       struct termios termios;
+       struct ktermios termios;
        int i;
 
        /*
@@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co,
        spin_lock_init(&port->lock);
        lockdep_set_class(&port->lock, &port_lock_key);
 
-       memset(&termios, 0, sizeof(struct termios));
+       memset(&termios, 0, sizeof(struct ktermios));
 
        termios.c_cflag = CREAD | HUPCL | CLOCAL;
 
@@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
         * Re-enable the console device after suspending.
         */
        if (uart_console(port)) {
-               struct termios termios;
+               struct ktermios termios;
 
                /*
                 * First try to use the console cflag setting.
                 */
-               memset(&termios, 0, sizeof(struct termios));
+               memset(&termios, 0, sizeof(struct ktermios));
                termios.c_cflag = port->cons->cflag;
 
                /*
@@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv)
        normal->subtype         = SERIAL_TYPE_NORMAL;
        normal->init_termios    = tty_std_termios;
        normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
        normal->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        normal->driver_state    = drv;
        tty_set_operations(normal, &uart_ops);
index 5e1ac35..eb18d42 100644 (file)
@@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port)
 }
 
 static void lh7a40xuart_set_termios (struct uart_port* port,
-                                    struct termios* termios,
-                                    struct termios* old)
+                                    struct ktermios* termios,
+                                    struct ktermios* old)
 {
        unsigned int con;
        unsigned int inten;
index 2a48289..7186a82 100644 (file)
@@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port)
 }
 
 static void
-serial_txx9_set_termios(struct uart_port *port, struct termios *termios,
-                      struct termios *old)
+serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
 {
        struct uart_txx9_port *up = (struct uart_txx9_port *)port;
        unsigned int cval, fcr = 0;
index cfcc3ca..9031b57 100644 (file)
@@ -775,7 +775,7 @@ static int sci_notifier(struct notifier_block *self,
                         *
                         * Clean this up later..
                         */
-                       clk = clk_get("module_clk");
+                       clk = clk_get(NULL, "module_clk");
                        port->uartclk = clk_get_rate(clk) * 16;
                        clk_put(clk);
                }
@@ -943,8 +943,8 @@ static void sci_shutdown(struct uart_port *port)
                s->disable(port);
 }
 
-static void sci_set_termios(struct uart_port *port, struct termios *termios,
-                           struct termios *old)
+static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
+                           struct ktermios *old)
 {
        struct sci_port *s = &sci_ports[port->line];
        unsigned int status, baud, smr_val;
@@ -960,7 +960,7 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
                default:
                {
 #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
-                       struct clk *clk = clk_get("module_clk");
+                       struct clk *clk = clk_get(NULL, "module_clk");
                        t = SCBRR_VALUE(baud, clk_get_rate(clk));
                        clk_put(clk);
 #else
@@ -1128,7 +1128,7 @@ static void __init sci_init_ports(void)
                 * XXX: We should use a proper SCI/SCIF clock
                 */
                {
-                       struct clk *clk = clk_get("module_clk");
+                       struct clk *clk = clk_get(NULL, "module_clk");
                        sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
                        clk_put(clk);
                }
index 7ee9921..e4557cc 100644 (file)
 # 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
+#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
+# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
+# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
+# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
+# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
+# define SCSCR_INIT(port)      0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
+# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
+# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001  /* overrun error bit */
+# define SCSCR_INIT(port)      0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
 #else
 # error CPU subtype not defined
 #endif
@@ -365,6 +379,7 @@ SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8)
 SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8)
 SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
 #if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+SCIF_FNS(SCFDR,                             0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
 SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
@@ -544,6 +559,28 @@ static inline int sci_rxd_in(struct uart_port *port)
        if (port->mapbase == 0xffe10000)
                return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xfffe8000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xfffe8800)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xfffe9000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xfffe9800)
+               return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xf8400000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xf8410000)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xf8420000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+}
 #endif
 
 /*
index 956b2cf..253ceb8 100644 (file)
@@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port)
  *
  */
 static void
-snp_set_termios(struct uart_port *port, struct termios *termios,
-               struct termios *old)
+snp_set_termios(struct uart_port *port, struct ktermios *termios,
+               struct ktermios *old)
 {
 }
 
index 03941d2..40d4856 100644 (file)
@@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port)
 }
 
 /* port->lock is not held.  */
-static void sunhv_set_termios(struct uart_port *port, struct termios *termios,
-                             struct termios *old)
+static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios,
+                             struct ktermios *old)
 {
        unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
        unsigned int quot = uart_get_divisor(port, baud);
index 08a7cd6..493d5bb 100644 (file)
@@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
 }
 
 /* port->lock is not held.  */
-static void sunsab_set_termios(struct uart_port *port, struct termios *termios,
-                              struct termios *old)
+static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios,
+                              struct ktermios *old)
 {
        struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
        unsigned long flags;
index c577fae..564592b 100644 (file)
@@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
 }
 
 static void
-sunsu_set_termios(struct uart_port *port, struct termios *termios,
-                 struct termios *old)
+sunsu_set_termios(struct uart_port *port, struct ktermios *termios,
+                 struct ktermios *old)
 {
        unsigned int baud, quot;
 
index b2cc703..75de919 100644 (file)
@@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
 
 /* The port lock is not held.  */
 static void
-sunzilog_set_termios(struct uart_port *port, struct termios *termios,
-                    struct termios *old)
+sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
+                    struct ktermios *old)
 {
        struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
        unsigned long flags;
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
new file mode 100644 (file)
index 0000000..92eba89
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * uartlite.c: Serial driver for Xilinx uartlite serial controller
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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/platform_device.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#define ULITE_MAJOR            204
+#define ULITE_MINOR            187
+#define ULITE_NR_UARTS         4
+
+/* For register details see datasheet:
+   http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
+*/
+#define ULITE_RX               0x00
+#define ULITE_TX               0x04
+#define ULITE_STATUS           0x08
+#define ULITE_CONTROL          0x0c
+
+#define ULITE_REGION           16
+
+#define ULITE_STATUS_RXVALID   0x01
+#define ULITE_STATUS_RXFULL    0x02
+#define ULITE_STATUS_TXEMPTY   0x04
+#define ULITE_STATUS_TXFULL    0x08
+#define ULITE_STATUS_IE                0x10
+#define ULITE_STATUS_OVERRUN   0x20
+#define ULITE_STATUS_FRAME     0x40
+#define ULITE_STATUS_PARITY    0x80
+
+#define ULITE_CONTROL_RST_TX   0x01
+#define ULITE_CONTROL_RST_RX   0x02
+#define ULITE_CONTROL_IE       0x10
+
+
+static struct uart_port ports[ULITE_NR_UARTS];
+
+static int ulite_receive(struct uart_port *port, int stat)
+{
+       struct tty_struct *tty = port->info->tty;
+       unsigned char ch = 0;
+       char flag = TTY_NORMAL;
+
+       if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
+                    | ULITE_STATUS_FRAME)) == 0)
+               return 0;
+
+       /* stats */
+       if (stat & ULITE_STATUS_RXVALID) {
+               port->icount.rx++;
+               ch = readb(port->membase + ULITE_RX);
+
+               if (stat & ULITE_STATUS_PARITY)
+                       port->icount.parity++;
+       }
+
+       if (stat & ULITE_STATUS_OVERRUN)
+               port->icount.overrun++;
+
+       if (stat & ULITE_STATUS_FRAME)
+               port->icount.frame++;
+
+
+       /* drop byte with parity error if IGNPAR specificed */
+       if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
+               stat &= ~ULITE_STATUS_RXVALID;
+
+       stat &= port->read_status_mask;
+
+       if (stat & ULITE_STATUS_PARITY)
+               flag = TTY_PARITY;
+
+
+       stat &= ~port->ignore_status_mask;
+
+       if (stat & ULITE_STATUS_RXVALID)
+               tty_insert_flip_char(tty, ch, flag);
+
+       if (stat & ULITE_STATUS_FRAME)
+               tty_insert_flip_char(tty, 0, TTY_FRAME);
+
+       if (stat & ULITE_STATUS_OVERRUN)
+               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+       return 1;
+}
+
+static int ulite_transmit(struct uart_port *port, int stat)
+{
+       struct circ_buf *xmit  = &port->info->xmit;
+
+       if (stat & ULITE_STATUS_TXFULL)
+               return 0;
+
+       if (port->x_char) {
+               writeb(port->x_char, port->membase + ULITE_TX);
+               port->x_char = 0;
+               port->icount.tx++;
+               return 1;
+       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+               return 0;
+
+       writeb(xmit->buf[xmit->tail], port->membase + ULITE_TX);
+       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
+       port->icount.tx++;
+
+       /* wake up */
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
+       return 1;
+}
+
+static irqreturn_t ulite_isr(int irq, void *dev_id)
+{
+       struct uart_port *port = (struct uart_port *)dev_id;
+       int busy;
+
+       do {
+               int stat = readb(port->membase + ULITE_STATUS);
+               busy  = ulite_receive(port, stat);
+               busy |= ulite_transmit(port, stat);
+       } while (busy);
+
+       tty_flip_buffer_push(port->info->tty);
+
+       return IRQ_HANDLED;
+}
+
+static unsigned int ulite_tx_empty(struct uart_port *port)
+{
+       unsigned long flags;
+       unsigned int ret;
+
+       spin_lock_irqsave(&port->lock, flags);
+       ret = readb(port->membase + ULITE_STATUS);
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int ulite_get_mctrl(struct uart_port *port)
+{
+       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       /* N/A */
+}
+
+static void ulite_stop_tx(struct uart_port *port)
+{
+       /* N/A */
+}
+
+static void ulite_start_tx(struct uart_port *port)
+{
+       ulite_transmit(port, readb(port->membase + ULITE_STATUS));
+}
+
+static void ulite_stop_rx(struct uart_port *port)
+{
+       /* don't forward any more data (like !CREAD) */
+       port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
+               | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+}
+
+static void ulite_enable_ms(struct uart_port *port)
+{
+       /* N/A */
+}
+
+static void ulite_break_ctl(struct uart_port *port, int ctl)
+{
+       /* N/A */
+}
+
+static int ulite_startup(struct uart_port *port)
+{
+       int ret;
+
+       ret = request_irq(port->irq, ulite_isr,
+                         IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "uartlite", port);
+       if (ret)
+               return ret;
+
+       writeb(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
+              port->membase + ULITE_CONTROL);
+       writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
+
+       return 0;
+}
+
+static void ulite_shutdown(struct uart_port *port)
+{
+       writeb(0, port->membase + ULITE_CONTROL);
+       readb(port->membase + ULITE_CONTROL); /* dummy */
+       free_irq(port->irq, port);
+}
+
+static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
+                             struct ktermios *old)
+{
+       unsigned long flags;
+       unsigned int baud;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
+               | ULITE_STATUS_TXFULL;
+
+       if (termios->c_iflag & INPCK)
+               port->read_status_mask |=
+                       ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
+
+       port->ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               port->ignore_status_mask |= ULITE_STATUS_PARITY
+                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+
+       /* ignore all characters if CREAD is not set */
+       if ((termios->c_cflag & CREAD) == 0)
+               port->ignore_status_mask |=
+                       ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
+                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+
+       /* update timeout */
+       baud = uart_get_baud_rate(port, termios, old, 0, 460800);
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *ulite_type(struct uart_port *port)
+{
+       return port->type == PORT_UARTLITE ? "uartlite" : NULL;
+}
+
+static void ulite_release_port(struct uart_port *port)
+{
+       release_mem_region(port->mapbase, ULITE_REGION);
+       iounmap(port->membase);
+       port->membase = 0;
+}
+
+static int ulite_request_port(struct uart_port *port)
+{
+       if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
+               dev_err(port->dev, "Memory region busy\n");
+               return -EBUSY;
+       }
+
+       port->membase = ioremap(port->mapbase, ULITE_REGION);
+       if (!port->membase) {
+               dev_err(port->dev, "Unable to map registers\n");
+               release_mem_region(port->mapbase, ULITE_REGION);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static void ulite_config_port(struct uart_port *port, int flags)
+{
+       ulite_request_port(port);
+       port->type = PORT_UARTLITE;
+}
+
+static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       /* we don't want the core code to modify any port params */
+       return -EINVAL;
+}
+
+static struct uart_ops ulite_ops = {
+       .tx_empty       = ulite_tx_empty,
+       .set_mctrl      = ulite_set_mctrl,
+       .get_mctrl      = ulite_get_mctrl,
+       .stop_tx        = ulite_stop_tx,
+       .start_tx       = ulite_start_tx,
+       .stop_rx        = ulite_stop_rx,
+       .enable_ms      = ulite_enable_ms,
+       .break_ctl      = ulite_break_ctl,
+       .startup        = ulite_startup,
+       .shutdown       = ulite_shutdown,
+       .set_termios    = ulite_set_termios,
+       .type           = ulite_type,
+       .release_port   = ulite_release_port,
+       .request_port   = ulite_request_port,
+       .config_port    = ulite_config_port,
+       .verify_port    = ulite_verify_port
+};
+
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+static void ulite_console_wait_tx(struct uart_port *port)
+{
+       int i;
+
+       /* wait up to 10ms for the character(s) to be sent */
+       for (i = 0; i < 10000; i++) {
+               if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY)
+                       break;
+               udelay(1);
+       }
+}
+
+static void ulite_console_putchar(struct uart_port *port, int ch)
+{
+       ulite_console_wait_tx(port);
+       writeb(ch, port->membase + ULITE_TX);
+}
+
+static void ulite_console_write(struct console *co, const char *s,
+                               unsigned int count)
+{
+       struct uart_port *port = &ports[co->index];
+       unsigned long flags;
+       unsigned int ier;
+       int locked = 1;
+
+       if (oops_in_progress) {
+               locked = spin_trylock_irqsave(&port->lock, flags);
+       } else
+               spin_lock_irqsave(&port->lock, flags);
+
+       /* save and disable interrupt */
+       ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
+       writeb(0, port->membase + ULITE_CONTROL);
+
+       uart_console_write(port, s, count, ulite_console_putchar);
+
+       ulite_console_wait_tx(port);
+
+       /* restore interrupt state */
+       if (ier)
+               writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
+
+       if (locked)
+               spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int __init ulite_console_setup(struct console *co, char *options)
+{
+       struct uart_port *port;
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (co->index < 0 || co->index >= ULITE_NR_UARTS)
+               return -EINVAL;
+
+       port = &ports[co->index];
+
+       /* not initialized yet? */
+       if (!port->membase)
+               return -ENODEV;
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver ulite_uart_driver;
+
+static struct console ulite_console = {
+       .name   = "ttyUL",
+       .write  = ulite_console_write,
+       .device = uart_console_device,
+       .setup  = ulite_console_setup,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
+       .data   = &ulite_uart_driver,
+};
+
+static int __init ulite_console_init(void)
+{
+       register_console(&ulite_console);
+       return 0;
+}
+
+console_initcall(ulite_console_init);
+
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
+
+static struct uart_driver ulite_uart_driver = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "uartlite",
+       .dev_name       = "ttyUL",
+       .major          = ULITE_MAJOR,
+       .minor          = ULITE_MINOR,
+       .nr             = ULITE_NR_UARTS,
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+       .cons           = &ulite_console,
+#endif
+};
+
+static int __devinit ulite_probe(struct platform_device *pdev)
+{
+       struct resource *res, *res2;
+       struct uart_port *port;
+
+       if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS)
+               return -EINVAL;
+
+       if (ports[pdev->id].membase)
+               return -EBUSY;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res2)
+               return -ENODEV;
+
+       port = &ports[pdev->id];
+
+       port->fifosize  = 16;
+       port->regshift  = 2;
+       port->iotype    = UPIO_MEM;
+       port->iobase    = 1; /* mark port in use */
+       port->mapbase   = res->start;
+       port->membase   = 0;
+       port->ops       = &ulite_ops;
+       port->irq       = res2->start;
+       port->flags     = UPF_BOOT_AUTOCONF;
+       port->dev       = &pdev->dev;
+       port->type      = PORT_UNKNOWN;
+       port->line      = pdev->id;
+
+       uart_add_one_port(&ulite_uart_driver, port);
+       platform_set_drvdata(pdev, port);
+
+       return 0;
+}
+
+static int ulite_remove(struct platform_device *pdev)
+{
+       struct uart_port *port = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (port)
+               uart_remove_one_port(&ulite_uart_driver, port);
+
+       /* mark port as free */
+       port->membase = 0;
+
+       return 0;
+}
+
+static struct platform_driver ulite_platform_driver = {
+       .probe  = ulite_probe,
+       .remove = ulite_remove,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name  = "uartlite",
+                  },
+};
+
+int __init ulite_init(void)
+{
+       int ret;
+
+       ret = uart_register_driver(&ulite_uart_driver);
+       if (ret)
+               return ret;
+
+       ret = platform_driver_register(&ulite_platform_driver);
+       if (ret)
+               uart_unregister_driver(&ulite_uart_driver);
+
+       return ret;
+}
+
+void __exit ulite_exit(void)
+{
+       platform_driver_unregister(&ulite_platform_driver);
+       uart_unregister_driver(&ulite_uart_driver);
+}
+
+module_init(ulite_init);
+module_exit(ulite_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Xilinx uartlite serial driver");
+MODULE_LICENSE("GPL");
index 28f3bbf..dd98aca 100644 (file)
@@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port)
 }
 
 static void
-v850e_uart_set_termios (struct uart_port *port, struct termios *termios,
-                       struct termios *old)
+v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios,
+                       struct ktermios *old)
 {
        unsigned cflags = termios->c_cflag;
 
index fd51f81..cf0e663 100644 (file)
@@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port)
        free_irq(port->irq, port);
 }
 
-static void siu_set_termios(struct uart_port *port, struct termios *new,
-                            struct termios *old)
+static void siu_set_termios(struct uart_port *port, struct ktermios *new,
+                            struct ktermios *old)
 {
        tcflag_t c_cflag, c_iflag;
        uint8_t lcr, fcr, ier;
index 72025df..6ed3f1d 100644 (file)
@@ -49,6 +49,14 @@ MODULE_LICENSE("GPL");
 #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
 #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
 
+/* for testing SSCR1 changes that require SSP restart, basically
+ * everything except the service and interrupt enables */
+#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \
+                               | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+                               | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \
+                               | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \
+                               | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
 #define DEFINE_SSP_REG(reg, off) \
 static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
 static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
@@ -123,8 +131,8 @@ struct driver_data {
        u8 n_bytes;
        u32 dma_width;
        int cs_change;
-       void (*write)(struct driver_data *drv_data);
-       void (*read)(struct driver_data *drv_data);
+       int (*write)(struct driver_data *drv_data);
+       int (*read)(struct driver_data *drv_data);
        irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
        void (*cs_control)(u32 command);
 };
@@ -132,7 +140,6 @@ struct driver_data {
 struct chip_data {
        u32 cr0;
        u32 cr1;
-       u32 to;
        u32 psp;
        u32 timeout;
        u8 n_bytes;
@@ -143,12 +150,12 @@ struct chip_data {
        u8 enable_dma;
        u8 bits_per_word;
        u32 speed_hz;
-       void (*write)(struct driver_data *drv_data);
-       void (*read)(struct driver_data *drv_data);
+       int (*write)(struct driver_data *drv_data);
+       int (*read)(struct driver_data *drv_data);
        void (*cs_control)(u32 command);
 };
 
-static void pump_messages(void *data);
+static void pump_messages(struct work_struct *work);
 
 static int flush(struct driver_data *drv_data)
 {
@@ -166,114 +173,118 @@ static int flush(struct driver_data *drv_data)
        return limit;
 }
 
-static void restore_state(struct driver_data *drv_data)
-{
-       void *reg = drv_data->ioaddr;
-
-       /* Clear status and disable clock */
-       write_SSSR(drv_data->clear_sr, reg);
-       write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg);
-
-       /* Load the registers */
-       write_SSCR1(drv_data->cur_chip->cr1, reg);
-       write_SSCR0(drv_data->cur_chip->cr0, reg);
-       if (drv_data->ssp_type != PXA25x_SSP) {
-               write_SSTO(0, reg);
-               write_SSPSP(drv_data->cur_chip->psp, reg);
-       }
-}
-
 static void null_cs_control(u32 command)
 {
 }
 
-static void null_writer(struct driver_data *drv_data)
+static int null_writer(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
        u8 n_bytes = drv_data->n_bytes;
 
-       while ((read_SSSR(reg) & SSSR_TNF)
-                       && (drv_data->tx < drv_data->tx_end)) {
-               write_SSDR(0, reg);
-               drv_data->tx += n_bytes;
-       }
+       if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+               || (drv_data->tx == drv_data->tx_end))
+               return 0;
+
+       write_SSDR(0, reg);
+       drv_data->tx += n_bytes;
+
+       return 1;
 }
 
-static void null_reader(struct driver_data *drv_data)
+static int null_reader(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
        u8 n_bytes = drv_data->n_bytes;
 
        while ((read_SSSR(reg) & SSSR_RNE)
-                       && (drv_data->rx < drv_data->rx_end)) {
+               && (drv_data->rx < drv_data->rx_end)) {
                read_SSDR(reg);
                drv_data->rx += n_bytes;
        }
+
+       return drv_data->rx == drv_data->rx_end;
 }
 
-static void u8_writer(struct driver_data *drv_data)
+static int u8_writer(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
-       while ((read_SSSR(reg) & SSSR_TNF)
-                       && (drv_data->tx < drv_data->tx_end)) {
-               write_SSDR(*(u8 *)(drv_data->tx), reg);
-               ++drv_data->tx;
-       }
+       if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+               || (drv_data->tx == drv_data->tx_end))
+               return 0;
+
+       write_SSDR(*(u8 *)(drv_data->tx), reg);
+       ++drv_data->tx;
+
+       return 1;
 }
 
-static void u8_reader(struct driver_data *drv_data)
+static int u8_reader(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
        while ((read_SSSR(reg) & SSSR_RNE)
-                       && (drv_data->rx < drv_data->rx_end)) {
+               && (drv_data->rx < drv_data->rx_end)) {
                *(u8 *)(drv_data->rx) = read_SSDR(reg);
                ++drv_data->rx;
        }
+
+       return drv_data->rx == drv_data->rx_end;
 }
 
-static void u16_writer(struct driver_data *drv_data)
+static int u16_writer(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
-       while ((read_SSSR(reg) & SSSR_TNF)
-                       && (drv_data->tx < drv_data->tx_end)) {
-               write_SSDR(*(u16 *)(drv_data->tx), reg);
-               drv_data->tx += 2;
-       }
+       if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+               || (drv_data->tx == drv_data->tx_end))
+               return 0;
+
+       write_SSDR(*(u16 *)(drv_data->tx), reg);
+       drv_data->tx += 2;
+
+       return 1;
 }
 
-static void u16_reader(struct driver_data *drv_data)
+static int u16_reader(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
        while ((read_SSSR(reg) & SSSR_RNE)
-                       && (drv_data->rx < drv_data->rx_end)) {
+               && (drv_data->rx < drv_data->rx_end)) {
                *(u16 *)(drv_data->rx) = read_SSDR(reg);
                drv_data->rx += 2;
        }
+
+       return drv_data->rx == drv_data->rx_end;
 }
-static void u32_writer(struct driver_data *drv_data)
+
+static int u32_writer(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
-       while ((read_SSSR(reg) & SSSR_TNF)
-                       && (drv_data->tx < drv_data->tx_end)) {
-               write_SSDR(*(u32 *)(drv_data->tx), reg);
-               drv_data->tx += 4;
-       }
+       if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+               || (drv_data->tx == drv_data->tx_end))
+               return 0;
+
+       write_SSDR(*(u32 *)(drv_data->tx), reg);
+       drv_data->tx += 4;
+
+       return 1;
 }
 
-static void u32_reader(struct driver_data *drv_data)
+static int u32_reader(struct driver_data *drv_data)
 {
        void *reg = drv_data->ioaddr;
 
        while ((read_SSSR(reg) & SSSR_RNE)
-                       && (drv_data->rx < drv_data->rx_end)) {
+               && (drv_data->rx < drv_data->rx_end)) {
                *(u32 *)(drv_data->rx) = read_SSDR(reg);
                drv_data->rx += 4;
        }
+
+       return drv_data->rx == drv_data->rx_end;
 }
 
 static void *next_transfer(struct driver_data *drv_data)
@@ -409,166 +420,134 @@ static int wait_dma_channel_stop(int channel)
        return limit;
 }
 
-static void dma_handler(int channel, void *data)
+void dma_error_stop(struct driver_data *drv_data, const char *msg)
 {
-       struct driver_data *drv_data = data;
-       struct spi_message *msg = drv_data->cur_msg;
        void *reg = drv_data->ioaddr;
-       u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-       u32 trailing_sssr = 0;
 
-       if (irq_status & DCSR_BUSERR) {
+       /* Stop and reset */
+       DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+       DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+       write_SSSR(drv_data->clear_sr, reg);
+       write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+       if (drv_data->ssp_type != PXA25x_SSP)
+               write_SSTO(0, reg);
+       flush(drv_data);
+       write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 
-               /* Disable interrupts, clear status and reset DMA */
-               write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-               write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-               if (drv_data->ssp_type != PXA25x_SSP)
-                       write_SSTO(0, reg);
-               write_SSSR(drv_data->clear_sr, reg);
-               DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-               DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+       unmap_dma_buffers(drv_data);
 
-               if (flush(drv_data) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                                       "dma_handler: flush fail\n");
+       dev_err(&drv_data->pdev->dev, "%s\n", msg);
 
-               unmap_dma_buffers(drv_data);
+       drv_data->cur_msg->state = ERROR_STATE;
+       tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_transfer_complete(struct driver_data *drv_data)
+{
+       void *reg = drv_data->ioaddr;
+       struct spi_message *msg = drv_data->cur_msg;
+
+       /* Clear and disable interrupts on SSP and DMA channels*/
+       write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+       write_SSSR(drv_data->clear_sr, reg);
+       DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+       DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+
+       if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+               dev_err(&drv_data->pdev->dev,
+                       "dma_handler: dma rx channel stop failed\n");
+
+       if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+               dev_err(&drv_data->pdev->dev,
+                       "dma_transfer: ssp rx stall failed\n");
+
+       unmap_dma_buffers(drv_data);
+
+       /* update the buffer pointer for the amount completed in dma */
+       drv_data->rx += drv_data->len -
+                       (DCMD(drv_data->rx_channel) & DCMD_LENGTH);
+
+       /* read trailing data from fifo, it does not matter how many
+        * bytes are in the fifo just read until buffer is full
+        * or fifo is empty, which ever occurs first */
+       drv_data->read(drv_data);
+
+       /* return count of what was actually read */
+       msg->actual_length += drv_data->len -
+                               (drv_data->rx_end - drv_data->rx);
+
+       /* Release chip select if requested, transfer delays are
+        * handled in pump_transfers */
+       if (drv_data->cs_change)
+               drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+       /* Move to next transfer */
+       msg->state = next_transfer(drv_data);
+
+       /* Schedule transfer tasklet */
+       tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_handler(int channel, void *data)
+{
+       struct driver_data *drv_data = data;
+       u32 irq_status = DCSR(channel) & DMA_INT_MASK;
+
+       if (irq_status & DCSR_BUSERR) {
 
                if (channel == drv_data->tx_channel)
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_handler: bad bus address on "
-                               "tx channel %d, source %x target = %x\n",
-                               channel, DSADR(channel), DTADR(channel));
+                       dma_error_stop(drv_data,
+                                       "dma_handler: "
+                                       "bad bus address on tx channel");
                else
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_handler: bad bus address on "
-                               "rx channel %d, source %x target = %x\n",
-                               channel, DSADR(channel), DTADR(channel));
-
-               msg->state = ERROR_STATE;
-               tasklet_schedule(&drv_data->pump_transfers);
+                       dma_error_stop(drv_data,
+                                       "dma_handler: "
+                                       "bad bus address on rx channel");
+               return;
        }
 
        /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
-       if ((drv_data->ssp_type == PXA25x_SSP)
-               && (channel == drv_data->tx_channel)
-               && (irq_status & DCSR_ENDINTR)) {
+       if ((channel == drv_data->tx_channel)
+               && (irq_status & DCSR_ENDINTR)
+               && (drv_data->ssp_type == PXA25x_SSP)) {
 
                /* Wait for rx to stall */
                if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
                        dev_err(&drv_data->pdev->dev,
                                "dma_handler: ssp rx stall failed\n");
 
-               /* Clear and disable interrupts on SSP and DMA channels*/
-               write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-               write_SSSR(drv_data->clear_sr, reg);
-               DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-               DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-               if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_handler: dma rx channel stop failed\n");
-
-               unmap_dma_buffers(drv_data);
-
-               /* Read trailing bytes */
-               /* Calculate number of trailing bytes, read them */
-               trailing_sssr = read_SSSR(reg);
-               if ((trailing_sssr & 0xf008) != 0xf000) {
-                       drv_data->rx = drv_data->rx_end -
-                                       (((trailing_sssr >> 12) & 0x0f) + 1);
-                       drv_data->read(drv_data);
-               }
-               msg->actual_length += drv_data->len;
-
-               /* Release chip select if requested, transfer delays are
-                * handled in pump_transfers */
-               if (drv_data->cs_change)
-                       drv_data->cs_control(PXA2XX_CS_DEASSERT);
-
-               /* Move to next transfer */
-               msg->state = next_transfer(drv_data);
-
-               /* Schedule transfer tasklet */
-               tasklet_schedule(&drv_data->pump_transfers);
+               /* finish this transfer, start the next */
+               dma_transfer_complete(drv_data);
        }
 }
 
 static irqreturn_t dma_transfer(struct driver_data *drv_data)
 {
        u32 irq_status;
-       u32 trailing_sssr = 0;
-       struct spi_message *msg = drv_data->cur_msg;
        void *reg = drv_data->ioaddr;
 
        irq_status = read_SSSR(reg) & drv_data->mask_sr;
        if (irq_status & SSSR_ROR) {
-               /* Clear and disable interrupts on SSP and DMA channels*/
-               write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-               write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-               if (drv_data->ssp_type != PXA25x_SSP)
-                       write_SSTO(0, reg);
-               write_SSSR(drv_data->clear_sr, reg);
-               DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-               DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-               unmap_dma_buffers(drv_data);
-
-               if (flush(drv_data) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                                       "dma_transfer: flush fail\n");
-
-               dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n");
-
-               drv_data->cur_msg->state = ERROR_STATE;
-               tasklet_schedule(&drv_data->pump_transfers);
-
+               dma_error_stop(drv_data, "dma_transfer: fifo overrun");
                return IRQ_HANDLED;
        }
 
        /* Check for false positive timeout */
-       if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) {
+       if ((irq_status & SSSR_TINT)
+               && (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
                write_SSSR(SSSR_TINT, reg);
                return IRQ_HANDLED;
        }
 
        if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
 
-               /* Clear and disable interrupts on SSP and DMA channels*/
-               write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+               /* Clear and disable timeout interrupt, do the rest in
+                * dma_transfer_complete */
                if (drv_data->ssp_type != PXA25x_SSP)
                        write_SSTO(0, reg);
-               write_SSSR(drv_data->clear_sr, reg);
-               DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-               DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 
-               if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_transfer: dma rx channel stop failed\n");
-
-               if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_transfer: ssp rx stall failed\n");
-
-               unmap_dma_buffers(drv_data);
-
-               /* Calculate number of trailing bytes, read them */
-               trailing_sssr = read_SSSR(reg);
-               if ((trailing_sssr & 0xf008) != 0xf000) {
-                       drv_data->rx = drv_data->rx_end -
-                                       (((trailing_sssr >> 12) & 0x0f) + 1);
-                       drv_data->read(drv_data);
-               }
-               msg->actual_length += drv_data->len;
-
-               /* Release chip select if requested, transfer delays are
-                * handled in pump_transfers */
-               if (drv_data->cs_change)
-                       drv_data->cs_control(PXA2XX_CS_DEASSERT);
-
-               /* Move to next transfer */
-               msg->state = next_transfer(drv_data);
-
-               /* Schedule transfer tasklet */
-               tasklet_schedule(&drv_data->pump_transfers);
+               /* finish this transfer, start the next */
+               dma_transfer_complete(drv_data);
 
                return IRQ_HANDLED;
        }
@@ -577,89 +556,103 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
        return IRQ_NONE;
 }
 
-static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+static void int_error_stop(struct driver_data *drv_data, const char* msg)
 {
-       struct spi_message *msg = drv_data->cur_msg;
        void *reg = drv_data->ioaddr;
-       unsigned long limit = loops_per_jiffy << 1;
-       u32 irq_status;
-       u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
-                       drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
-
-       while ((irq_status = read_SSSR(reg) & irq_mask)) {
-
-               if (irq_status & SSSR_ROR) {
 
-                       /* Clear and disable interrupts */
-                       write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-                       write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-                       if (drv_data->ssp_type != PXA25x_SSP)
-                               write_SSTO(0, reg);
-                       write_SSSR(drv_data->clear_sr, reg);
+       /* Stop and reset SSP */
+       write_SSSR(drv_data->clear_sr, reg);
+       write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+       if (drv_data->ssp_type != PXA25x_SSP)
+               write_SSTO(0, reg);
+       flush(drv_data);
+       write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 
-                       if (flush(drv_data) == 0)
-                               dev_err(&drv_data->pdev->dev,
-                                       "interrupt_transfer: flush fail\n");
+       dev_err(&drv_data->pdev->dev, "%s\n", msg);
 
-                       /* Stop the SSP */
+       drv_data->cur_msg->state = ERROR_STATE;
+       tasklet_schedule(&drv_data->pump_transfers);
+}
 
-                       dev_warn(&drv_data->pdev->dev,
-                                       "interrupt_transfer: fifo overun\n");
+static void int_transfer_complete(struct driver_data *drv_data)
+{
+       void *reg = drv_data->ioaddr;
 
-                       msg->state = ERROR_STATE;
-                       tasklet_schedule(&drv_data->pump_transfers);
+       /* Stop SSP */
+       write_SSSR(drv_data->clear_sr, reg);
+       write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+       if (drv_data->ssp_type != PXA25x_SSP)
+               write_SSTO(0, reg);
 
-                       return IRQ_HANDLED;
-               }
+       /* Update total byte transfered return count actual bytes read */
+       drv_data->cur_msg->actual_length += drv_data->len -
+                               (drv_data->rx_end - drv_data->rx);
 
-               /* Look for false positive timeout */
-               if ((irq_status & SSSR_TINT)
-                               && (drv_data->rx < drv_data->rx_end))
-                       write_SSSR(SSSR_TINT, reg);
+       /* Release chip select if requested, transfer delays are
+        * handled in pump_transfers */
+       if (drv_data->cs_change)
+               drv_data->cs_control(PXA2XX_CS_DEASSERT);
 
-               /* Pump data */
-               drv_data->read(drv_data);
-               drv_data->write(drv_data);
+       /* Move to next transfer */
+       drv_data->cur_msg->state = next_transfer(drv_data);
 
-               if (drv_data->tx == drv_data->tx_end) {
-                       /* Disable tx interrupt */
-                       write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
-                       irq_mask = drv_data->mask_sr & ~SSSR_TFS;
+       /* Schedule transfer tasklet */
+       tasklet_schedule(&drv_data->pump_transfers);
+}
 
-                       /* PXA25x_SSP has no timeout, read trailing bytes */
-                       if (drv_data->ssp_type == PXA25x_SSP) {
-                               while ((read_SSSR(reg) & SSSR_BSY) && limit--)
-                                       drv_data->read(drv_data);
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+       void *reg = drv_data->ioaddr;
 
-                               if (limit == 0)
-                                       dev_err(&drv_data->pdev->dev,
-                                               "interrupt_transfer: "
-                                               "trailing byte read failed\n");
-                       }
-               }
+       u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+                       drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
 
-               if ((irq_status & SSSR_TINT)
-                               || (drv_data->rx == drv_data->rx_end)) {
+       u32 irq_status = read_SSSR(reg) & irq_mask;
 
-                       /* Clear timeout */
-                       write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-                       if (drv_data->ssp_type != PXA25x_SSP)
-                               write_SSTO(0, reg);
-                       write_SSSR(drv_data->clear_sr, reg);
+       if (irq_status & SSSR_ROR) {
+               int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+               return IRQ_HANDLED;
+       }
 
-                       /* Update total byte transfered */
-                       msg->actual_length += drv_data->len;
+       if (irq_status & SSSR_TINT) {
+               write_SSSR(SSSR_TINT, reg);
+               if (drv_data->read(drv_data)) {
+                       int_transfer_complete(drv_data);
+                       return IRQ_HANDLED;
+               }
+       }
 
-                       /* Release chip select if requested, transfer delays are
-                        * handled in pump_transfers */
-                       if (drv_data->cs_change)
-                               drv_data->cs_control(PXA2XX_CS_DEASSERT);
+       /* Drain rx fifo, Fill tx fifo and prevent overruns */
+       do {
+               if (drv_data->read(drv_data)) {
+                       int_transfer_complete(drv_data);
+                       return IRQ_HANDLED;
+               }
+       } while (drv_data->write(drv_data));
 
-                       /* Move to next transfer */
-                       msg->state = next_transfer(drv_data);
+       if (drv_data->read(drv_data)) {
+               int_transfer_complete(drv_data);
+               return IRQ_HANDLED;
+       }
 
-                       /* Schedule transfer tasklet */
-                       tasklet_schedule(&drv_data->pump_transfers);
+       if (drv_data->tx == drv_data->tx_end) {
+               write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
+               /* PXA25x_SSP has no timeout, read trailing bytes */
+               if (drv_data->ssp_type == PXA25x_SSP) {
+                       if (!wait_ssp_rx_stall(reg))
+                       {
+                               int_error_stop(drv_data, "interrupt_transfer: "
+                                               "rx stall failed");
+                               return IRQ_HANDLED;
+                       }
+                       if (!drv_data->read(drv_data))
+                       {
+                               int_error_stop(drv_data,
+                                               "interrupt_transfer: "
+                                               "trailing byte read failed");
+                               return IRQ_HANDLED;
+                       }
+                       int_transfer_complete(drv_data);
                }
        }
 
@@ -681,7 +674,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
                write_SSSR(drv_data->clear_sr, reg);
 
                dev_err(&drv_data->pdev->dev, "bad message state "
-                               "in interrupt handler");
+                       "in interrupt handler\n");
 
                /* Never fail */
                return IRQ_HANDLED;
@@ -690,6 +683,102 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
        return drv_data->transfer_handler(drv_data);
 }
 
+int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi,
+                               u8 bits_per_word, u32 *burst_code,
+                               u32 *threshold)
+{
+       struct pxa2xx_spi_chip *chip_info =
+                       (struct pxa2xx_spi_chip *)spi->controller_data;
+       int bytes_per_word;
+       int burst_bytes;
+       int thresh_words;
+       int req_burst_size;
+       int retval = 0;
+
+       /* Set the threshold (in registers) to equal the same amount of data
+        * as represented by burst size (in bytes).  The computation below
+        * is (burst_size rounded up to nearest 8 byte, word or long word)
+        * divided by (bytes/register); the tx threshold is the inverse of
+        * the rx, so that there will always be enough data in the rx fifo
+        * to satisfy a burst, and there will always be enough space in the
+        * tx fifo to accept a burst (a tx burst will overwrite the fifo if
+        * there is not enough space), there must always remain enough empty
+        * space in the rx fifo for any data loaded to the tx fifo.
+        * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
+        * will be 8, or half the fifo;
+        * The threshold can only be set to 2, 4 or 8, but not 16, because
+        * to burst 16 to the tx fifo, the fifo would have to be empty;
+        * however, the minimum fifo trigger level is 1, and the tx will
+        * request service when the fifo is at this level, with only 15 spaces.
+        */
+
+       /* find bytes/word */
+       if (bits_per_word <= 8)
+               bytes_per_word = 1;
+       else if (bits_per_word <= 16)
+               bytes_per_word = 2;
+       else
+               bytes_per_word = 4;
+
+       /* use struct pxa2xx_spi_chip->dma_burst_size if available */
+       if (chip_info)
+               req_burst_size = chip_info->dma_burst_size;
+       else {
+               switch (chip->dma_burst_size) {
+               default:
+                       /* if the default burst size is not set,
+                        * do it now */
+                       chip->dma_burst_size = DCMD_BURST8;
+               case DCMD_BURST8:
+                       req_burst_size = 8;
+                       break;
+               case DCMD_BURST16:
+                       req_burst_size = 16;
+                       break;
+               case DCMD_BURST32:
+                       req_burst_size = 32;
+                       break;
+               }
+       }
+       if (req_burst_size <= 8) {
+               *burst_code = DCMD_BURST8;
+               burst_bytes = 8;
+       } else if (req_burst_size <= 16) {
+               if (bytes_per_word == 1) {
+                       /* don't burst more than 1/2 the fifo */
+                       *burst_code = DCMD_BURST8;
+                       burst_bytes = 8;
+                       retval = 1;
+               } else {
+                       *burst_code = DCMD_BURST16;
+                       burst_bytes = 16;
+               }
+       } else {
+               if (bytes_per_word == 1) {
+                       /* don't burst more than 1/2 the fifo */
+                       *burst_code = DCMD_BURST8;
+                       burst_bytes = 8;
+                       retval = 1;
+               } else if (bytes_per_word == 2) {
+                       /* don't burst more than 1/2 the fifo */
+                       *burst_code = DCMD_BURST16;
+                       burst_bytes = 16;
+                       retval = 1;
+               } else {
+                       *burst_code = DCMD_BURST32;
+                       burst_bytes = 32;
+               }
+       }
+
+       thresh_words = burst_bytes / bytes_per_word;
+
+       /* thresh_words will be between 2 and 8 */
+       *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
+                       | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
+
+       return retval;
+}
+
 static void pump_transfers(unsigned long data)
 {
        struct driver_data *drv_data = (struct driver_data *)data;
@@ -702,6 +791,9 @@ static void pump_transfers(unsigned long data)
        u8 bits = 0;
        u32 speed = 0;
        u32 cr0;
+       u32 cr1;
+       u32 dma_thresh = drv_data->cur_chip->dma_threshold;
+       u32 dma_burst = drv_data->cur_chip->dma_burst_size;
 
        /* Get current state information */
        message = drv_data->cur_msg;
@@ -731,6 +823,16 @@ static void pump_transfers(unsigned long data)
                        udelay(previous->delay_usecs);
        }
 
+       /* Check transfer length */
+       if (transfer->len > 8191)
+       {
+               dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer "
+                               "length greater than 8191\n");
+               message->status = -EINVAL;
+               giveback(drv_data);
+               return;
+       }
+
        /* Setup the transfer state based on the type of transfer */
        if (flush(drv_data) == 0) {
                dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
@@ -747,17 +849,15 @@ static void pump_transfers(unsigned long data)
        drv_data->rx_end = drv_data->rx + transfer->len;
        drv_data->rx_dma = transfer->rx_dma;
        drv_data->tx_dma = transfer->tx_dma;
-       drv_data->len = transfer->len;
+       drv_data->len = transfer->len & DCMD_LENGTH;
        drv_data->write = drv_data->tx ? chip->write : null_writer;
        drv_data->read = drv_data->rx ? chip->read : null_reader;
        drv_data->cs_change = transfer->cs_change;
 
        /* Change speed and bit per word on a per transfer */
+       cr0 = chip->cr0;
        if (transfer->speed_hz || transfer->bits_per_word) {
 
-               /* Disable clock */
-               write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg);
-               cr0 = chip->cr0;
                bits = chip->bits_per_word;
                speed = chip->speed_hz;
 
@@ -796,15 +896,24 @@ static void pump_transfers(unsigned long data)
                        drv_data->write = drv_data->write != null_writer ?
                                                u32_writer : null_writer;
                }
+               /* if bits/word is changed in dma mode, then must check the
+                * thresholds and burst also */
+               if (chip->enable_dma) {
+                       if (set_dma_burst_and_threshold(chip, message->spi,
+                                                       bits, &dma_burst,
+                                                       &dma_thresh))
+                               if (printk_ratelimit())
+                                       dev_warn(&message->spi->dev,
+                                               "pump_transfer: "
+                                               "DMA burst size reduced to "
+                                               "match bits_per_word\n");
+               }
 
                cr0 = clk_div
                        | SSCR0_Motorola
                        | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
                        | SSCR0_SSE
                        | (bits > 16 ? SSCR0_EDSS : 0);
-
-               /* Start it back up */
-               write_SSCR0(cr0, reg);
        }
 
        message->state = RUNNING_STATE;
@@ -823,13 +932,13 @@ static void pump_transfers(unsigned long data)
                        /* No target address increment */
                        DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
                                                        | drv_data->dma_width
-                                                       | chip->dma_burst_size
+                                                       | dma_burst
                                                        | drv_data->len;
                else
                        DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
                                                        | DCMD_FLOWSRC
                                                        | drv_data->dma_width
-                                                       | chip->dma_burst_size
+                                                       | dma_burst
                                                        | drv_data->len;
 
                /* Setup tx DMA Channel */
@@ -840,13 +949,13 @@ static void pump_transfers(unsigned long data)
                        /* No source address increment */
                        DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
                                                        | drv_data->dma_width
-                                                       | chip->dma_burst_size
+                                                       | dma_burst
                                                        | drv_data->len;
                else
                        DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
                                                        | DCMD_FLOWTRG
                                                        | drv_data->dma_width
-                                                       | chip->dma_burst_size
+                                                       | dma_burst
                                                        | drv_data->len;
 
                /* Enable dma end irqs on SSP to detect end of transfer */
@@ -856,16 +965,11 @@ static void pump_transfers(unsigned long data)
                /* Fix me, need to handle cs polarity */
                drv_data->cs_control(PXA2XX_CS_ASSERT);
 
-               /* Go baby, go */
+               /* Clear status and start DMA engine */
+               cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
                write_SSSR(drv_data->clear_sr, reg);
                DCSR(drv_data->rx_channel) |= DCSR_RUN;
                DCSR(drv_data->tx_channel) |= DCSR_RUN;
-               if (drv_data->ssp_type != PXA25x_SSP)
-                       write_SSTO(chip->timeout, reg);
-               write_SSCR1(chip->cr1
-                               | chip->dma_threshold
-                               | drv_data->dma_cr1,
-                               reg);
        } else {
                /* Ensure we have the correct interrupt handler */
                drv_data->transfer_handler = interrupt_transfer;
@@ -873,20 +977,32 @@ static void pump_transfers(unsigned long data)
                /* Fix me, need to handle cs polarity */
                drv_data->cs_control(PXA2XX_CS_ASSERT);
 
-               /* Go baby, go */
+               /* Clear status  */
+               cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
                write_SSSR(drv_data->clear_sr, reg);
+       }
+
+       /* see if we need to reload the config registers */
+       if ((read_SSCR0(reg) != cr0)
+               || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
+                       (cr1 & SSCR1_CHANGE_MASK)) {
+
+               write_SSCR0(cr0 & ~SSCR0_SSE, reg);
                if (drv_data->ssp_type != PXA25x_SSP)
                        write_SSTO(chip->timeout, reg);
-               write_SSCR1(chip->cr1
-                               | chip->threshold
-                               | drv_data->int_cr1,
-                               reg);
+               write_SSCR1(cr1, reg);
+               write_SSCR0(cr0, reg);
+       } else {
+               if (drv_data->ssp_type != PXA25x_SSP)
+                       write_SSTO(chip->timeout, reg);
+               write_SSCR1(cr1, reg);
        }
 }
 
-static void pump_messages(void *data)
+static void pump_messages(struct work_struct *work)
 {
-       struct driver_data *drv_data = data;
+       struct driver_data *drv_data =
+               container_of(work, struct driver_data, pump_messages);
        unsigned long flags;
 
        /* Lock queue and check for queue work */
@@ -914,9 +1030,9 @@ static void pump_messages(void *data)
                                                struct spi_transfer,
                                                transfer_list);
 
-       /* Setup the SSP using the per chip configuration */
+       /* prepare to setup the SSP, in pump_transfers, using the per
+        * chip configuration */
        drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-       restore_state(drv_data);
 
        /* Mark as busy and launch transfers */
        tasklet_schedule(&drv_data->pump_transfers);
@@ -962,63 +1078,77 @@ static int setup(struct spi_device *spi)
                spi->bits_per_word = 8;
 
        if (drv_data->ssp_type != PXA25x_SSP
-                       && (spi->bits_per_word < 4 || spi->bits_per_word > 32))
+               && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
+               dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+                               "b/w not 4-32 for type non-PXA25x_SSP\n",
+                               drv_data->ssp_type, spi->bits_per_word);
                return -EINVAL;
-       else if (spi->bits_per_word < 4 || spi->bits_per_word > 16)
+       }
+       else if (drv_data->ssp_type == PXA25x_SSP
+                       && (spi->bits_per_word < 4
+                               || spi->bits_per_word > 16)) {
+               dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+                               "b/w not 4-16 for type PXA25x_SSP\n",
+                               drv_data->ssp_type, spi->bits_per_word);
                return -EINVAL;
+       }
 
-       /* Only alloc (or use chip_info) on first setup */
+       /* Only alloc on first setup */
        chip = spi_get_ctldata(spi);
-       if (chip == NULL) {
+       if (!chip) {
                chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-               if (!chip)
+               if (!chip) {
+                       dev_err(&spi->dev,
+                               "failed setup: can't allocate chip data\n");
                        return -ENOMEM;
+               }
 
                chip->cs_control = null_cs_control;
                chip->enable_dma = 0;
-               chip->timeout = SSP_TIMEOUT(1000);
+               chip->timeout = 1000;
                chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
                chip->dma_burst_size = drv_data->master_info->enable_dma ?
                                        DCMD_BURST8 : 0;
-
-               chip_info = spi->controller_data;
        }
 
+       /* protocol drivers may change the chip settings, so...
+        * if chip_info exists, use it */
+       chip_info = spi->controller_data;
+
        /* chip_info isn't always needed */
+       chip->cr1 = 0;
        if (chip_info) {
                if (chip_info->cs_control)
                        chip->cs_control = chip_info->cs_control;
 
-               chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs);
+               chip->timeout = chip_info->timeout;
 
-               chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
-                                       | SSCR1_TxTresh(chip_info->tx_threshold);
+               chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
+                                                               SSCR1_RFT) |
+                               (SSCR1_TxTresh(chip_info->tx_threshold) &
+                                                               SSCR1_TFT);
 
                chip->enable_dma = chip_info->dma_burst_size != 0
                                        && drv_data->master_info->enable_dma;
                chip->dma_threshold = 0;
 
-               if (chip->enable_dma) {
-                       if (chip_info->dma_burst_size <= 8) {
-                               chip->dma_threshold = SSCR1_RxTresh(8)
-                                                       | SSCR1_TxTresh(8);
-                               chip->dma_burst_size = DCMD_BURST8;
-                       } else if (chip_info->dma_burst_size <= 16) {
-                               chip->dma_threshold = SSCR1_RxTresh(16)
-                                                       | SSCR1_TxTresh(16);
-                               chip->dma_burst_size = DCMD_BURST16;
-                       } else {
-                               chip->dma_threshold = SSCR1_RxTresh(32)
-                                                       | SSCR1_TxTresh(32);
-                               chip->dma_burst_size = DCMD_BURST32;
-                       }
-               }
-
-
                if (chip_info->enable_loopback)
                        chip->cr1 = SSCR1_LBM;
        }
 
+       /* set dma burst and threshold outside of chip_info path so that if
+        * chip_info goes away after setting chip->enable_dma, the
+        * burst and threshold can still respond to changes in bits_per_word */
+       if (chip->enable_dma) {
+               /* set up legal burst and threshold for dma */
+               if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
+                                               &chip->dma_burst_size,
+                                               &chip->dma_threshold)) {
+                       dev_warn(&spi->dev, "in setup: DMA burst size reduced "
+                                       "to match bits_per_word\n");
+               }
+       }
+
        if (drv_data->ioaddr == SSP1_VIRT)
                clk_div = SSP1_SerClkDiv(spi->max_speed_hz);
        else if (drv_data->ioaddr == SSP2_VIRT)
@@ -1026,7 +1156,11 @@ static int setup(struct spi_device *spi)
        else if (drv_data->ioaddr == SSP3_VIRT)
                clk_div = SSP3_SerClkDiv(spi->max_speed_hz);
        else
+       {
+               dev_err(&spi->dev, "failed setup: unknown IO address=0x%p\n",
+                       drv_data->ioaddr);
                return -ENODEV;
+       }
        chip->speed_hz = spi->max_speed_hz;
 
        chip->cr0 = clk_div
@@ -1070,7 +1204,6 @@ static int setup(struct spi_device *spi)
                chip->write = u32_writer;
        } else {
                dev_err(&spi->dev, "invalid wordsize\n");
-               kfree(chip);
                return -ENODEV;
        }
        chip->bits_per_word = spi->bits_per_word;
@@ -1098,7 +1231,7 @@ static int init_queue(struct driver_data *drv_data)
        tasklet_init(&drv_data->pump_transfers,
                        pump_transfers, (unsigned long)drv_data);
 
-       INIT_WORK(&drv_data->pump_messages, pump_messages, drv_data);
+       INIT_WORK(&drv_data->pump_messages, pump_messages);
        drv_data->workqueue = create_singlethread_workqueue(
                                        drv_data->master->cdev.dev->bus_id);
        if (drv_data->workqueue == NULL)
@@ -1161,6 +1294,12 @@ static int destroy_queue(struct driver_data *drv_data)
        int status;
 
        status = stop_queue(drv_data);
+       /* we are unloading the module or failing to load (only two calls
+        * to this routine), and neither call can handle a return value.
+        * However, destroy_workqueue calls flush_workqueue, and that will
+        * block until all work is done.  If the reason that stop_queue
+        * timed out is that the work will never finish, then it does no
+        * good to call destroy_workqueue, so return anyway. */
        if (status != 0)
                return status;
 
@@ -1359,7 +1498,16 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
        /* Remove the queue */
        status = destroy_queue(drv_data);
        if (status != 0)
-               return status;
+               /* the kernel does not check the return status of this
+                * this routine (mod->exit, within the kernel).  Therefore
+                * nothing is gained by returning from here, the module is
+                * going away regardless, and we should not leave any more
+                * resources allocated than necessary.  We cannot free the
+                * message memory in drv_data->queue, but we can release the
+                * resources below.  I think the kernel should honor -EBUSY
+                * returns but... */
+               dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
+                       "complete, message memory not freed\n");
 
        /* Disable the SSP at the peripheral and SOC level */
        write_SSCR0(0, drv_data->ioaddr);
index c3c0626..270e621 100644 (file)
@@ -360,12 +360,13 @@ spi_alloc_master(struct device *dev, unsigned size)
        if (!dev)
                return NULL;
 
-       master = kzalloc(size + sizeof *master, SLAB_KERNEL);
+       master = kzalloc(size + sizeof *master, GFP_KERNEL);
        if (!master)
                return NULL;
 
        class_device_initialize(&master->cdev);
        master->cdev.class = &spi_master_class;
+       kobj_set_kset_s(&master->cdev, spi_master_class.subsys);
        master->cdev.dev = get_device(dev);
        spi_master_set_devdata(master, &master[1]);
 
@@ -447,7 +448,9 @@ static int __unregister(struct device *dev, void *unused)
  */
 void spi_unregister_master(struct spi_master *master)
 {
-       (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
+       int dummy;
+
+       dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
        class_device_unregister(&master->cdev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
@@ -463,15 +466,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master);
  */
 struct spi_master *spi_busnum_to_master(u16 bus_num)
 {
-       if (bus_num) {
-               char                    name[8];
-               struct kobject          *bus;
-
-               snprintf(name, sizeof name, "spi%u", bus_num);
-               bus = kset_find_obj(&spi_master_class.subsys.kset, name);
-               if (bus)
-                       return container_of(bus, struct spi_master, cdev.kobj);
-       }
+       char                    name[9];
+       struct kobject          *bus;
+
+       snprintf(name, sizeof name, "spi%u", bus_num);
+       bus = kset_find_obj(&spi_master_class.subsys.kset, name);
+       if (bus)
+               return container_of(bus, struct spi_master, cdev.kobj);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(spi_busnum_to_master);
@@ -607,7 +608,7 @@ static int __init spi_init(void)
 {
        int     status;
 
-       buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
+       buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
        if (!buf) {
                status = -ENOMEM;
                goto err0;
index a23862e..57289b6 100644 (file)
@@ -196,7 +196,7 @@ int spi_bitbang_setup(struct spi_device *spi)
                return -EINVAL;
 
        if (!cs) {
-               cs = kzalloc(sizeof *cs, SLAB_KERNEL);
+               cs = kzalloc(sizeof *cs, GFP_KERNEL);
                if (!cs)
                        return -ENOMEM;
                spi->controller_state = cs;
@@ -265,9 +265,10 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
  * Drivers can provide word-at-a-time i/o primitives, or provide
  * transfer-at-a-time ones to leverage dma or fifo hardware.
  */
-static void bitbang_work(void *_bitbang)
+static void bitbang_work(struct work_struct *work)
 {
-       struct spi_bitbang      *bitbang = _bitbang;
+       struct spi_bitbang      *bitbang =
+               container_of(work, struct spi_bitbang, work);
        unsigned long           flags;
 
        spin_lock_irqsave(&bitbang->lock, flags);
@@ -456,7 +457,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
        if (!bitbang->master || !bitbang->chipselect)
                return -EINVAL;
 
-       INIT_WORK(&bitbang->work, bitbang_work, bitbang);
+       INIT_WORK(&bitbang->work, bitbang_work);
        spin_lock_init(&bitbang->lock);
        INIT_LIST_HEAD(&bitbang->queue);
 
index c2f601f..312987a 100644 (file)
@@ -251,6 +251,8 @@ static void butterfly_attach(struct parport *p)
         * setting up a platform device like this is an ugly kluge...
         */
        pdev = platform_device_register_simple("butterfly", -1, NULL, 0);
+       if (IS_ERR(pdev))
+               return;
 
        master = spi_alloc_master(&pdev->dev, sizeof *pp);
        if (!master) {
index 792becd..fc31972 100644 (file)
@@ -1238,7 +1238,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        return 0;
 }
 
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct dec_serial *info = (struct dec_serial *)tty->driver_data;
        int was_stopped;
index 1b601b6..df4cc1f 100644 (file)
@@ -2747,7 +2747,7 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len)
 static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
 {
        unsigned long i = *ppos;
-       IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode));
+       IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
 
        DECLARE_WAITQUEUE(wait, current);
 
@@ -2804,7 +2804,7 @@ static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t
 {
        int pre_retval;
        ssize_t read_retval = 0;
-       IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+       IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
 
        pre_retval = ixj_PreRead(j, 0L);
        switch (pre_retval) {
@@ -2883,7 +2883,7 @@ static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf,
        int pre_retval;
        ssize_t write_retval = 0;
 
-       IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+       IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
 
        pre_retval = ixj_PreWrite(j, 0L);
        switch (pre_retval) {
@@ -4582,7 +4582,7 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
 {
        unsigned int mask = 0;
 
-       IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+       IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
 
        poll_wait(file_p, &(j->poll_q), wait);
        if (j->read_buffer_ready > 0)
@@ -6657,7 +6657,7 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
 
 static int ixj_fasync(int fd, struct file *file_p, int mode)
 {
-       IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+       IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
 
        return fasync_helper(fd, file_p, mode, &j->async_queue);
 }
index f9b1719..9980a4d 100644 (file)
@@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI
        default y if ARCH_S3C2410
        default y if PXA27x
        default y if ARCH_EP93XX
-       default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
+       default y if ARCH_AT91
        default y if ARCH_PNX4008
        # PPC:
        default y if STB03xxx
index e656563..3dfa3e4 100644 (file)
@@ -158,7 +158,7 @@ struct cxacru_data {
        const struct cxacru_modem_type *modem_type;
 
        int line_status;
-       struct work_struct poll_work;
+       struct delayed_work poll_work;
 
        /* contol handles */
        struct mutex cm_serialize;
@@ -347,7 +347,7 @@ static int cxacru_card_status(struct cxacru_data *instance)
        return 0;
 }
 
-static void cxacru_poll_status(struct cxacru_data *instance);
+static void cxacru_poll_status(struct work_struct *work);
 
 static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
                struct atm_dev *atm_dev)
@@ -376,12 +376,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
        }
 
        /* Start status polling */
-       cxacru_poll_status(instance);
+       cxacru_poll_status(&instance->poll_work.work);
        return 0;
 }
 
-static void cxacru_poll_status(struct cxacru_data *instance)
+static void cxacru_poll_status(struct work_struct *work)
 {
+       struct cxacru_data *instance =
+               container_of(work, struct cxacru_data, poll_work.work);
        u32 buf[CXINF_MAX] = {};
        struct usbatm_data *usbatm = instance->usbatm;
        struct atm_dev *atm_dev = usbatm->atm_dev;
@@ -720,7 +722,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
 
        mutex_init(&instance->cm_serialize);
 
-       INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
+       INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status);
 
        usbatm_instance->driver_data = instance;
 
index a823486..8ed6c75 100644 (file)
@@ -142,7 +142,7 @@ struct speedtch_instance_data {
 
        struct speedtch_params params; /* set in probe, constant afterwards */
 
-       struct work_struct status_checker;
+       struct delayed_work status_checker;
 
        unsigned char last_status;
 
@@ -498,8 +498,11 @@ static int speedtch_start_synchro(struct speedtch_instance_data *instance)
        return ret;
 }
 
-static void speedtch_check_status(struct speedtch_instance_data *instance)
+static void speedtch_check_status(struct work_struct *work)
 {
+       struct speedtch_instance_data *instance =
+               container_of(work, struct speedtch_instance_data,
+                            status_checker.work);
        struct usbatm_data *usbatm = instance->usbatm;
        struct atm_dev *atm_dev = usbatm->atm_dev;
        unsigned char *buf = instance->scratch_buffer;
@@ -576,7 +579,7 @@ static void speedtch_status_poll(unsigned long data)
 {
        struct speedtch_instance_data *instance = (void *)data;
 
-       schedule_work(&instance->status_checker);
+       schedule_delayed_work(&instance->status_checker, 0);
 
        /* The following check is racy, but the race is harmless */
        if (instance->poll_delay < MAX_POLL_DELAY)
@@ -596,7 +599,7 @@ static void speedtch_resubmit_int(unsigned long data)
        if (int_urb) {
                ret = usb_submit_urb(int_urb, GFP_ATOMIC);
                if (!ret)
-                       schedule_work(&instance->status_checker);
+                       schedule_delayed_work(&instance->status_checker, 0);
                else {
                        atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
                        mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY));
@@ -640,7 +643,7 @@ static void speedtch_handle_int(struct urb *int_urb)
 
        if ((int_urb = instance->int_urb)) {
                ret = usb_submit_urb(int_urb, GFP_ATOMIC);
-               schedule_work(&instance->status_checker);
+               schedule_delayed_work(&instance->status_checker, 0);
                if (ret < 0) {
                        atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
                        goto fail;
@@ -855,7 +858,7 @@ static int speedtch_bind(struct usbatm_data *usbatm,
 
        usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
 
-       INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
+       INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status);
 
        instance->status_checker.timer.function = speedtch_status_poll;
        instance->status_checker.timer.data = (unsigned long)instance;
index c137c04..dae4ef1 100644 (file)
@@ -64,6 +64,8 @@
 #include <linux/kthread.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
+
 #include <asm/unaligned.h>
 
 #include "usbatm.h"
@@ -655,9 +657,9 @@ static int request_dsp(struct uea_softc *sc)
 /*
  * The uea_load_page() function must be called within a process context
  */
-static void uea_load_page(void *xsc)
+static void uea_load_page(struct work_struct *work)
 {
-       struct uea_softc *sc = xsc;
+       struct uea_softc *sc = container_of(work, struct uea_softc, task);
        u16 pageno = sc->pageno;
        u16 ovl = sc->ovl;
        struct block_info bi;
@@ -1348,7 +1350,7 @@ static int uea_boot(struct uea_softc *sc)
 
        uea_enters(INS_TO_USBDEV(sc));
 
-       INIT_WORK(&sc->task, uea_load_page, sc);
+       INIT_WORK(&sc->task, uea_load_page);
        init_waitqueue_head(&sc->sync_q);
        init_waitqueue_head(&sc->cmv_ack_wait);
 
index ec3438d..9819962 100644 (file)
@@ -421,9 +421,9 @@ static void acm_write_bulk(struct urb *urb)
                schedule_work(&acm->work);
 }
 
-static void acm_softint(void *private)
+static void acm_softint(struct work_struct *work)
 {
-       struct acm *acm = private;
+       struct acm *acm = container_of(work, struct acm, work);
        dbg("Entering acm_softint.");
        
        if (!ACM_READY(acm))
@@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = {
        5, 6, 7, 8
 };
 
-static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
 {
        struct acm *acm = tty->driver_data;
-       struct termios *termios = tty->termios;
+       struct ktermios *termios = tty->termios;
        struct usb_cdc_line_coding newline;
        int newctrl = acm->ctrlout;
 
@@ -927,7 +927,7 @@ skip_normal_probe:
        acm->rx_buflimit = num_rx_buf;
        acm->urb_task.func = acm_rx_tasklet;
        acm->urb_task.data = (unsigned long) acm;
-       INIT_WORK(&acm->work, acm_softint, acm);
+       INIT_WORK(&acm->work, acm_softint);
        spin_lock_init(&acm->throttle_lock);
        spin_lock_init(&acm->write_lock);
        spin_lock_init(&acm->read_lock);
index 840442a..c3915dc 100644 (file)
@@ -93,7 +93,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
 }
 
 
-/* sometimes alloc/free could use kmalloc with SLAB_DMA, for
+/* sometimes alloc/free could use kmalloc with GFP_DMA, for
  * better sharing and to leverage mm/slab.c intelligence.
  */
 
index 0ce393e..2651c2e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -68,7 +69,7 @@ struct usb_hub {
 
        unsigned                has_indicators:1;
        u8                      indicator[USB_MAXCHILDREN];
-       struct work_struct      leds;
+       struct delayed_work     leds;
 };
 
 
@@ -218,9 +219,10 @@ static void set_port_led(
 
 #define        LED_CYCLE_PERIOD        ((2*HZ)/3)
 
-static void led_work (void *__hub)
+static void led_work (struct work_struct *work)
 {
-       struct usb_hub          *hub = __hub;
+       struct usb_hub          *hub =
+               container_of(work, struct usb_hub, leds.work);
        struct usb_device       *hdev = hub->hdev;
        unsigned                i;
        unsigned                changed = 0;
@@ -405,9 +407,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
  * talking to TTs must queue control transfers (not just bulk and iso), so
  * both can talk to the same hub concurrently.
  */
-static void hub_tt_kevent (void *arg)
+static void hub_tt_kevent (struct work_struct *work)
 {
-       struct usb_hub          *hub = arg;
+       struct usb_hub          *hub =
+               container_of(work, struct usb_hub, tt.kevent);
        unsigned long           flags;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
@@ -458,7 +461,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
         * since each TT has "at least two" buffers that can need it (and
         * there can be many TTs per hub).  even if they're uncommon.
         */
-       if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == NULL) {
+       if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
                dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
                /* FIXME recover somehow ... RESET_TT? */
                return;
@@ -694,7 +697,7 @@ static int hub_configure(struct usb_hub *hub,
 
        spin_lock_init (&hub->tt.lock);
        INIT_LIST_HEAD (&hub->tt.clear_list);
-       INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub);
+       INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
        switch (hdev->descriptor.bDeviceProtocol) {
                case 0:
                        break;
@@ -938,7 +941,7 @@ descriptor_error:
        INIT_LIST_HEAD(&hub->event_list);
        hub->intfdev = &intf->dev;
        hub->hdev = hdev;
-       INIT_WORK(&hub->leds, led_work, hub);
+       INIT_DELAYED_WORK(&hub->leds, led_work);
 
        usb_set_intfdata (intf, hub);
        intf->needs_remote_wakeup = 1;
@@ -2369,7 +2372,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
        struct usb_qualifier_descriptor *qual;
        int                             status;
 
-       qual = kmalloc (sizeof *qual, SLAB_KERNEL);
+       qual = kmalloc (sizeof *qual, GFP_KERNEL);
        if (qual == NULL)
                return;
 
@@ -2381,7 +2384,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
                /* hub LEDs are probably harder to miss than syslog */
                if (hub->has_indicators) {
                        hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
-                       schedule_work (&hub->leds);
+                       schedule_delayed_work (&hub->leds, 0);
                }
        }
        kfree(qual);
@@ -2555,7 +2558,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                                if (hub->has_indicators) {
                                        hub->indicator[port1-1] =
                                                INDICATOR_AMBER_BLINK;
-                                       schedule_work (&hub->leds);
+                                       schedule_delayed_work (&hub->leds, 0);
                                }
                                status = -ENOTCONN;     /* Don't retry */
                                goto loop_disable;
@@ -2920,7 +2923,7 @@ static int config_descriptors_changed(struct usb_device *udev)
                if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
                        len = le16_to_cpu(udev->config[index].desc.wTotalLength);
        }
-       buf = kmalloc (len, SLAB_KERNEL);
+       buf = kmalloc (len, GFP_KERNEL);
        if (buf == NULL) {
                dev_err(&udev->dev, "no mem to re-read configs after reset\n");
                /* assume the worst */
index b5d6a79..11dad22 100644 (file)
@@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
 {
        loff_t retval = -EINVAL;
 
-       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+       mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
        switch(orig) {
        case 0:
                if (offset > 0) {
@@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
        default:
                break;
        }
-       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
        return retval;
 }
 
index 29b0fa9..149aa8b 100644 (file)
@@ -488,7 +488,7 @@ void usb_sg_wait (struct usb_sg_request *io)
                int     retval;
 
                io->urbs [i]->dev = io->dev;
-               retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC);
+               retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC);
 
                /* after we submit, let completions or cancelations fire;
                 * we handshake using io->status.
@@ -1501,9 +1501,10 @@ struct set_config_request {
 };
 
 /* Worker routine for usb_driver_set_configuration() */
-static void driver_set_config_work(void *_req)
+static void driver_set_config_work(struct work_struct *work)
 {
-       struct set_config_request *req = _req;
+       struct set_config_request *req =
+               container_of(work, struct set_config_request, work);
 
        usb_lock_device(req->udev);
        usb_set_configuration(req->udev, req->config);
@@ -1541,7 +1542,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
                return -ENOMEM;
        req->udev = udev;
        req->config = config;
-       INIT_WORK(&req->work, driver_set_config_work, req);
+       INIT_WORK(&req->work, driver_set_config_work);
 
        usb_get_dev(udev);
        if (!schedule_work(&req->work)) {
index 81cb525..02426d0 100644 (file)
@@ -203,9 +203,10 @@ static void ksuspend_usb_cleanup(void)
 #ifdef CONFIG_USB_SUSPEND
 
 /* usb_autosuspend_work - callback routine to autosuspend a USB device */
-static void usb_autosuspend_work(void *_udev)
+static void usb_autosuspend_work(struct work_struct *work)
 {
-       struct usb_device       *udev = _udev;
+       struct usb_device *udev =
+               container_of(work, struct usb_device, autosuspend.work);
 
        usb_pm_lock(udev);
        udev->auto_pm = 1;
@@ -215,7 +216,7 @@ static void usb_autosuspend_work(void *_udev)
 
 #else
 
-static void usb_autosuspend_work(void *_udev)
+static void usb_autosuspend_work(struct work_struct *work)
 {}
 
 #endif /* CONFIG_USB_SUSPEND */
@@ -304,7 +305,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 
 #ifdef CONFIG_PM
        mutex_init(&dev->pm_mutex);
-       INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
+       INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
 #endif
        return dev;
 }
index bbbc82a..4097a86 100644 (file)
@@ -189,7 +189,7 @@ config USB_OTG
 
 config USB_GADGET_AT91
        boolean "AT91 USB Device Port"
-       depends on ARCH_AT91RM9200
+       depends on ARCH_AT91
        select USB_GADGET_SELECTED
        help
           Many Atmel AT91 processors (such as the AT91RM2000) have a
index 3bd1dfe..d15bf22 100644 (file)
@@ -1833,9 +1833,9 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
        spin_unlock_irqrestore(&dev->req_lock, flags);
 }
 
-static void eth_work (void *_dev)
+static void eth_work (struct work_struct *work)
 {
-       struct eth_dev          *dev = _dev;
+       struct eth_dev  *dev = container_of(work, struct eth_dev, work);
 
        if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
                if (netif_running (dev->net))
@@ -2398,7 +2398,7 @@ autoconf_fail:
        dev = netdev_priv(net);
        spin_lock_init (&dev->lock);
        spin_lock_init (&dev->req_lock);
-       INIT_WORK (&dev->work, eth_work, dev);
+       INIT_WORK (&dev->work, eth_work);
        INIT_LIST_HEAD (&dev->tx_reqs);
        INIT_LIST_HEAD (&dev->rx_reqs);
 
index 8b975d1..a265e26 100644 (file)
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/utsname.h>
 
 #include <linux/usb_ch9.h>
@@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun)
        if (!filp->f_op->fsync)
                return -EINVAL;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        mutex_lock(&inode->i_mutex);
        rc = filemap_fdatawrite(inode->i_mapping);
-       err = filp->f_op->fsync(filp, filp->f_dentry, 1);
+       err = filp->f_op->fsync(filp, filp->f_path.dentry, 1);
        if (!rc)
                rc = err;
        err = filemap_fdatawait(inode->i_mapping);
@@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg)
 static void invalidate_sub(struct lun *curlun)
 {
        struct file     *filp = curlun->filp;
-       struct inode    *inode = filp->f_dentry->d_inode;
+       struct inode    *inode = filp->f_path.dentry->d_inode;
        unsigned long   rc;
 
        rc = invalidate_inode_pages(inode->i_mapping);
@@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename)
        if (!(filp->f_mode & FMODE_WRITE))
                ro = 1;
 
-       if (filp->f_dentry)
-               inode = filp->f_dentry->d_inode;
+       if (filp->f_path.dentry)
+               inode = filp->f_path.dentry->d_inode;
        if (inode && S_ISBLK(inode->i_mode)) {
                if (bdev_read_only(inode->i_bdev))
                        ro = 1;
@@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
 
        down_read(&fsg->filesem);
        if (backing_file_is_open(curlun)) {     // Get the complete pathname
-               p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt,
+               p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt,
                                buf, PAGE_SIZE - 1);
                if (IS_ERR(p))
                        rc = PTR_ERR(p);
@@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
                if (backing_file_is_open(curlun)) {
                        p = NULL;
                        if (pathbuf) {
-                               p = d_path(curlun->filp->f_dentry,
-                                       curlun->filp->f_vfsmnt,
+                               p = d_path(curlun->filp->f_path.dentry,
+                                       curlun->filp->f_path.mnt,
                                        pathbuf, PATH_MAX);
                                if (IS_ERR(p))
                                        p = NULL;
index 64554ac..3135182 100644 (file)
@@ -1236,7 +1236,7 @@ autoconf_fail:
 
 
        /* ok, we made sense of the hardware ... */
-       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev) {
                return -ENOMEM;
        }
index a3076da..805a982 100644 (file)
@@ -1864,7 +1864,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* alloc, and start init */
-       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+       dev = kmalloc (sizeof *dev, GFP_KERNEL);
        if (dev == NULL){
                pr_debug("enomem %s\n", pci_name(pdev));
                retval = -ENOMEM;
index 86924f9..3fb1044 100644 (file)
@@ -412,7 +412,7 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
        /* FIXME readahead for O_NONBLOCK and poll(); careful with ZLPs */
 
        value = -ENOMEM;
-       kbuf = kmalloc (len, SLAB_KERNEL);
+       kbuf = kmalloc (len, GFP_KERNEL);
        if (unlikely (!kbuf))
                goto free1;
 
@@ -456,7 +456,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        /* FIXME writebehind for O_NONBLOCK and poll(), qlen = 1 */
 
        value = -ENOMEM;
-       kbuf = kmalloc (len, SLAB_KERNEL);
+       kbuf = kmalloc (len, GFP_KERNEL);
        if (!kbuf)
                goto free1;
        if (copy_from_user (kbuf, buf, len)) {
@@ -1898,7 +1898,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        buf += 4;
        length -= 4;
 
-       kbuf = kmalloc (length, SLAB_KERNEL);
+       kbuf = kmalloc (length, GFP_KERNEL);
        if (!kbuf)
                return -ENOMEM;
        if (copy_from_user (kbuf, buf, length)) {
index 0b59083..3024c67 100644 (file)
@@ -2861,7 +2861,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* alloc, and start init */
-       dev = kzalloc (sizeof *dev, SLAB_KERNEL);
+       dev = kzalloc (sizeof *dev, GFP_KERNEL);
        if (dev == NULL){
                retval = -ENOMEM;
                goto done;
index 48a09fd..030d87c 100644 (file)
@@ -2581,7 +2581,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
        /* UDC_PULLUP_EN gates the chip clock */
        // OTG_SYSCON_1_REG |= DEV_IDLE_EN;
 
-       udc = kzalloc(sizeof(*udc), SLAB_KERNEL);
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
        if (!udc)
                return -ENOMEM;
 
index 208e55a..5516c59 100644 (file)
@@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty);
 static void gs_break(struct tty_struct *tty, int break_state);
 static int  gs_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg);
-static void gs_set_termios(struct tty_struct *tty, struct termios *old);
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old);
 
 static int gs_send(struct gs_dev *dev);
 static int gs_send_packet(struct gs_dev *dev, char *packet,
@@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
 /*
  * gs_set_termios
  */
-static void gs_set_termios(struct tty_struct *tty, struct termios *old)
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
 }
 
index 0f809dd..40710ea 100644 (file)
@@ -1190,7 +1190,7 @@ autoconf_fail:
 
 
        /* ok, we made sense of the hardware ... */
-       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
        spin_lock_init (&dev->lock);
index 34b7a31..56349d2 100644 (file)
@@ -492,7 +492,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        unsigned                i;
        __le32                  tag;
 
-       if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
+       if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
                return 0;
        seen_count = 0;
 
index 87eca6a..9325e46 100644 (file)
@@ -188,7 +188,7 @@ static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
 #define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
 {panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
 
-#define SLAB_FLAG     (in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL)
+#define SLAB_FLAG     (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
 #define KMALLOC_FLAG  (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
 
 /* Most helpful debugging aid */
@@ -275,13 +275,13 @@ static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
 static int zout_buffer[4] __attribute__ ((aligned (4)));
 
 /* Cache for allocating new EP and SB descriptors. */
-static kmem_cache_t *usb_desc_cache;
+static struct kmem_cache *usb_desc_cache;
 
 /* Cache for the registers allocated in the top half. */
-static kmem_cache_t *top_half_reg_cache;
+static struct kmem_cache *top_half_reg_cache;
 
 /* Cache for the data allocated in the isoc descr top half. */
-static kmem_cache_t *isoc_compl_cache;
+static struct kmem_cache *isoc_compl_cache;
 
 static struct usb_bus *etrax_usb_bus;
 
@@ -1743,7 +1743,7 @@ static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc)
 
                *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
 
-               comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, SLAB_ATOMIC);
+               comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC);
                assert(comp_data != NULL);
 
                 INIT_WORK(&comp_data->usb_bh, etrax_usb_isoc_descr_interrupt_bottom_half, comp_data);
@@ -3010,7 +3010,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid)
                        if (!urb->iso_frame_desc[i].length)
                                continue;
 
-                       next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC);
+                       next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
                        assert(next_sb_desc != NULL);
 
                        if (urb->iso_frame_desc[i].length > 0) {
@@ -3063,7 +3063,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid)
                if (TxIsocEPList[epid].sub == 0) {
                        dbg_isoc("Isoc traffic not already running, allocating SB");
 
-                       next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC);
+                       next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
                        assert(next_sb_desc != NULL);
 
                        next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) |
@@ -3317,7 +3317,7 @@ static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc)
 
        restore_flags(flags);
 
-       reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, SLAB_ATOMIC);
+       reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, GFP_ATOMIC);
 
        assert(reg != NULL);
 
index 8293c1d..0f47a57 100644 (file)
@@ -505,7 +505,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        char                    *next;
        unsigned                i;
 
-       if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
+       if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
                return 0;
        seen_count = 0;
 
index a95275a..b28a9b6 100644 (file)
@@ -945,7 +945,7 @@ MODULE_LICENSE ("GPL");
 #include "ohci-ppc-soc.c"
 #endif
 
-#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
+#ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
 #endif
 
@@ -962,8 +962,7 @@ MODULE_LICENSE ("GPL");
       || defined (CONFIG_ARCH_EP93XX) \
       || defined (CONFIG_SOC_AU1X00) \
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
-      || defined (CONFIG_ARCH_AT91RM9200) \
-      || defined (CONFIG_ARCH_AT91SAM9261) \
+      || defined (CONFIG_ARCH_AT91) \
       || defined (CONFIG_ARCH_PNX4008) \
        )
 #error "missing bus glue for ohci-hcd"
index 2dbb774..7f26f9b 100644 (file)
@@ -134,7 +134,7 @@ 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);
+       c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL);
 
        if (!c)
                return -ENOMEM;
index ef54e31..a9d7119 100644 (file)
@@ -163,7 +163,7 @@ struct u132_endp {
         u16 queue_next;
         struct urb *urb_list[ENDP_QUEUE_SIZE];
         struct list_head urb_more;
-        struct work_struct scheduler;
+        struct delayed_work scheduler;
 };
 struct u132_ring {
         unsigned in_use:1;
@@ -171,7 +171,7 @@ struct u132_ring {
         u8 number;
         struct u132 *u132;
         struct u132_endp *curr_endp;
-        struct work_struct scheduler;
+        struct delayed_work scheduler;
 };
 #define OHCI_QUIRK_AMD756 0x01
 #define OHCI_QUIRK_SUPERIO 0x02
@@ -198,7 +198,7 @@ struct u132 {
         u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
         int flags;
         unsigned long next_statechange;
-        struct work_struct monitor;
+        struct delayed_work monitor;
         int num_endpoints;
         struct u132_addr addr[MAX_U132_ADDRS];
         struct u132_udev udev[MAX_U132_UDEVS];
@@ -310,7 +310,7 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
         if (delta > 0) {
                 if (queue_delayed_work(workqueue, &ring->scheduler, delta))
                         return;
-        } else if (queue_work(workqueue, &ring->scheduler))
+        } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
                 return;
         kref_put(&u132->kref, u132_hcd_delete);
         return;
@@ -389,12 +389,8 @@ static inline void u132_endp_init_kref(struct u132 *u132,
 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;
+       if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+               kref_get(&endp->kref);
 }
 
 static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
@@ -410,24 +406,14 @@ static inline void u132_monitor_put_kref(struct u132 *u132)
 
 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;
+       if (queue_delayed_work(workqueue, &u132->monitor, delta))
+               kref_get(&u132->kref);
 }
 
 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;
+       if (!queue_delayed_work(workqueue, &u132->monitor, delta))
+               kref_put(&u132->kref, u132_hcd_delete);
 }
 
 static void u132_monitor_cancel_work(struct u132 *u132)
@@ -489,9 +475,9 @@ static int read_roothub_info(struct u132 *u132)
         return 0;
 }
 
-static void u132_hcd_monitor_work(void *data)
+static void u132_hcd_monitor_work(struct work_struct *work)
 {
-        struct u132 *u132 = data;
+        struct u132 *u132 = container_of(work, struct u132, monitor.work);
         if (u132->going > 1) {
                 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
                         , u132->going);
@@ -1315,15 +1301,14 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
         }
 }
 
-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)
+static void u132_hcd_ring_work_scheduler(struct work_struct *work)
 {
-        struct u132_ring *ring = data;
+        struct u132_ring *ring =
+               container_of(work, struct u132_ring, scheduler.work);
         struct u132 *u132 = ring->u132;
         down(&u132->scheduler_lock);
         if (ring->in_use) {
@@ -1382,10 +1367,11 @@ static void u132_hcd_ring_work_scheduler(void *data)
         }
 }
 
-static void u132_hcd_endp_work_scheduler(void *data)
+static void u132_hcd_endp_work_scheduler(struct work_struct *work)
 {
         struct u132_ring *ring;
-        struct u132_endp *endp = data;
+        struct u132_endp *endp =
+               container_of(work, struct u132_endp, scheduler.work);
         struct u132 *u132 = endp->u132;
         down(&u132->scheduler_lock);
         ring = endp->ring;
@@ -1943,7 +1929,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
         if (!endp) {
                 return -ENOMEM;
         }
-        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
         spin_lock_init(&endp->queue_lock.slock);
         INIT_LIST_HEAD(&endp->urb_more);
         ring = endp->ring = &u132->ring[0];
@@ -2032,7 +2018,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
         if (!endp) {
                 return -ENOMEM;
         }
-        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
         spin_lock_init(&endp->queue_lock.slock);
         INIT_LIST_HEAD(&endp->urb_more);
         endp->dequeueing = 0;
@@ -2117,7 +2103,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
         if (!endp) {
                 return -ENOMEM;
         }
-        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
         spin_lock_init(&endp->queue_lock.slock);
         INIT_LIST_HEAD(&endp->urb_more);
         ring = endp->ring = &u132->ring[0];
@@ -3096,10 +3082,10 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
                 ring->number = rings + 1;
                 ring->length = 0;
                 ring->curr_endp = NULL;
-                INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler,
-                        (void *)ring);
+                INIT_DELAYED_WORK(&ring->scheduler,
+                                 u132_hcd_ring_work_scheduler);
         } down(&u132->sw_lock);
-        INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132);
+        INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
         while (ports-- > 0) {
                 struct u132_port *port = &u132->port[ports];
                 port->u132 = u132;
index 226bf3d..e87692c 100644 (file)
@@ -81,7 +81,7 @@ MODULE_PARM_DESC(debug, "Debug level");
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
 
-static kmem_cache_t *uhci_up_cachep;   /* urb_priv */
+static struct kmem_cache *uhci_up_cachep;      /* urb_priv */
 
 static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
 static void wakeup_rh(struct uhci_hcd *uhci);
index 06115f2..30b8845 100644 (file)
@@ -498,7 +498,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
 {
        struct urb_priv *urbp;
 
-       urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+       urbp = kmem_cache_alloc(uhci_up_cachep, GFP_ATOMIC);
        if (!urbp)
                return NULL;
 
index 661af7a..8a62d47 100644 (file)
@@ -6,9 +6,10 @@ comment "USB Input Devices"
 
 config USB_HID
        tristate "USB Human Interface Device (full HID) support"
-       depends on USB
+       default y
+       depends on USB && HID
        ---help---
-         Say Y here if you want full HID support to connect keyboards,
+         Say Y here if you want full HID support to connect USB keyboards,
          mice, joysticks, graphic tablets, or any other HID based devices
          to your computer via USB. You also need to select HID Input layer
          support (below) if you want to use keyboards, mice, joysticks and
@@ -27,20 +28,10 @@ config USB_HID
 comment "Input core support is needed for USB HID input layer or HIDBP support"
        depends on USB_HID && INPUT=n
 
-config USB_HIDINPUT
-       bool "HID input layer support"
-       default y
-       depends on INPUT && USB_HID
-       help
-         Say Y here if you want to use a USB keyboard, mouse or joystick,
-         or any other HID input device.
-
-         If unsure, say Y.
-
-config USB_HIDINPUT_POWERBOOK
+config USB_HID_POWERBOOK
        bool "Enable support for iBook/PowerBook special keys"
        default n
-       depends on USB_HIDINPUT
+       depends on USB_HID
        help
          Say Y here if you want support for the special keys (Fn, Numlock) on
          Apple iBooks and PowerBooks.
@@ -49,7 +40,7 @@ config USB_HIDINPUT_POWERBOOK
 
 config HID_FF
        bool "Force feedback support (EXPERIMENTAL)"
-       depends on USB_HIDINPUT && EXPERIMENTAL
+       depends on USB_HID && EXPERIMENTAL
        help
          Say Y here is you want force feedback support for a few HID devices.
          See below for a list of supported devices.
index d946d52..1a24b5b 100644 (file)
@@ -11,9 +11,6 @@ usbhid-objs   := hid-core.o
 ifeq ($(CONFIG_USB_HIDDEV),y)
        usbhid-objs     += hiddev.o
 endif
-ifeq ($(CONFIG_USB_HIDINPUT),y)
-       usbhid-objs     += hid-input.o
-endif
 ifeq ($(CONFIG_HID_PID),y)
        usbhid-objs     += hid-pidff.o
 endif
index 0096373..909138e 100644 (file)
@@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        if (!acecad || !input_dev)
                goto fail1;
 
-       acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
+       acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
        if (!acecad->data)
                goto fail1;
 
index bf42818..9f52429 100644 (file)
@@ -1988,7 +1988,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto fail1;
 
        aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
-                                       SLAB_ATOMIC, &aiptek->data_dma);
+                                       GFP_ATOMIC, &aiptek->data_dma);
        if (!aiptek->data)
                goto fail1;
 
index 4c21351..c77291d 100644 (file)
 #define APPLE_VENDOR_ID                0x05AC
 
 /* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define GEYSER_ANSI_PRODUCT_ID 0x0214
-#define GEYSER_ISO_PRODUCT_ID  0x0215
-#define GEYSER_JIS_PRODUCT_ID  0x0216
+#define FOUNTAIN_ANSI_PRODUCT_ID       0x020E
+#define FOUNTAIN_ISO_PRODUCT_ID                0x020F
+
+#define FOUNTAIN_TP_ONLY_PRODUCT_ID    0x030A
+
+#define GEYSER1_TP_ONLY_PRODUCT_ID     0x030B
+
+#define GEYSER_ANSI_PRODUCT_ID         0x0214
+#define GEYSER_ISO_PRODUCT_ID          0x0215
+#define GEYSER_JIS_PRODUCT_ID          0x0216
 
 /* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID        0x0217
-#define GEYSER3_ISO_PRODUCT_ID 0x0218
-#define GEYSER3_JIS_PRODUCT_ID 0x0219
+#define GEYSER3_ANSI_PRODUCT_ID                0x0217
+#define GEYSER3_ISO_PRODUCT_ID         0x0218
+#define GEYSER3_JIS_PRODUCT_ID         0x0219
+
+/*
+ * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
+ * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
+ */
+#define GEYSER4_ANSI_PRODUCT_ID        0x021A
+#define GEYSER4_ISO_PRODUCT_ID 0x021B
+#define GEYSER4_JIS_PRODUCT_ID 0x021C
 
 #define ATP_DEVICE(prod)                                       \
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |             \
 
 /* table of devices that work with this driver */
 static struct usb_device_id atp_table [] = {
-       { ATP_DEVICE(0x020E) },
-       { ATP_DEVICE(0x020F) },
-       { ATP_DEVICE(0x030A) },
-       { ATP_DEVICE(0x030B) },
+       { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
+       { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
+       { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
+       { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
 
        /* PowerBooks Oct 2005 */
        { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
        { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
        { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
 
+       /* Core Duo MacBook & MacBook Pro */
        { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
        { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
        { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
 
+       /* Core2 Duo MacBook & MacBook Pro */
+       { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
+       { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
+       { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+
        /* Terminating entry */
        { }
 };
@@ -108,7 +129,7 @@ MODULE_DEVICE_TABLE (usb, atp_table);
  */
 #define ATP_THRESHOLD   5
 
-/* MacBook Pro (Geyser 3) initialization constants */
+/* MacBook Pro (Geyser 3 & 4) initialization constants */
 #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
 #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
 #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
@@ -154,6 +175,13 @@ MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
 MODULE_LICENSE("GPL");
 
+/*
+ * Make the threshold a module parameter
+ */
+static int threshold = ATP_THRESHOLD;
+module_param(threshold, int, 0644);
+MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+
 static int debug = 1;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
@@ -174,7 +202,10 @@ static inline int atp_is_geyser_3(struct atp *dev)
 
        return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
                (productId == GEYSER3_ISO_PRODUCT_ID) ||
-               (productId == GEYSER3_JIS_PRODUCT_ID);
+               (productId == GEYSER3_JIS_PRODUCT_ID) ||
+               (productId == GEYSER4_ANSI_PRODUCT_ID) ||
+               (productId == GEYSER4_ISO_PRODUCT_ID) ||
+               (productId == GEYSER4_JIS_PRODUCT_ID);
 }
 
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -183,16 +214,48 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
        int i;
        /* values to calculate mean */
        int pcum = 0, psum = 0;
+       int is_increasing = 0;
 
        *fingers = 0;
 
        for (i = 0; i < nb_sensors; i++) {
-               if (xy_sensors[i] < ATP_THRESHOLD)
+               if (xy_sensors[i] < threshold) {
+                       if (is_increasing)
+                               is_increasing = 0;
+
                        continue;
-               if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+               }
+
+               /*
+                * Makes the finger detection more versatile.  For example,
+                * two fingers with no gap will be detected.  Also, my
+                * tests show it less likely to have intermittent loss
+                * of multiple finger readings while moving around (scrolling).
+                *
+                * Changes the multiple finger detection to counting humps on
+                * sensors (transitions from nonincreasing to increasing)
+                * instead of counting transitions from low sensors (no
+                * finger reading) to high sensors (finger above
+                * sensor)
+                *
+                * - Jason Parekh <jasonparekh@gmail.com>
+                */
+               if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
                        (*fingers)++;
-               pcum += xy_sensors[i] * i;
-               psum += xy_sensors[i];
+                       is_increasing = 1;
+               } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
+                       is_increasing = 0;
+               }
+
+               /*
+                * Subtracts threshold so a high sensor that just passes the threshold
+                * won't skew the calculated absolute coordinate.  Fixes an issue
+                * where slowly moving the mouse would occassionaly jump a number of
+                * pixels (let me restate--slowly moving the mouse makes this issue
+                * most apparent).
+                */
+               pcum += (xy_sensors[i] - threshold) * i;
+               psum += (xy_sensors[i] - threshold);
        }
 
        if (psum > 0) {
index ff23318..b724e36 100644 (file)
@@ -592,7 +592,7 @@ static void ati_remote_irq_in(struct urb *urb)
                        __FUNCTION__, urb->status);
        }
 
-       retval = usb_submit_urb(urb, SLAB_ATOMIC);
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
                        __FUNCTION__, retval);
@@ -604,12 +604,12 @@ static void ati_remote_irq_in(struct urb *urb)
 static int ati_remote_alloc_buffers(struct usb_device *udev,
                                    struct ati_remote *ati_remote)
 {
-       ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+       ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
                                             &ati_remote->inbuf_dma);
        if (!ati_remote->inbuf)
                return -1;
 
-       ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+       ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
                                              &ati_remote->outbuf_dma);
        if (!ati_remote->outbuf)
                return -1;
index a49644b..89fa688 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006 Jiri Kosina
  */
 
 /*
@@ -32,8 +33,9 @@
 
 #include <linux/usb.h>
 
-#include "hid.h"
+#include <linux/hid.h>
 #include <linux/hiddev.h>
+#include "usbhid.h"
 
 /*
  * Version Information
@@ -54,886 +56,10 @@ static unsigned int hid_mousepoll_interval;
 module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
 MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
 
-/*
- * Register a new report for a device.
- */
-
-static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
-{
-       struct hid_report_enum *report_enum = device->report_enum + type;
-       struct hid_report *report;
-
-       if (report_enum->report_id_hash[id])
-               return report_enum->report_id_hash[id];
-
-       if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
-               return NULL;
-
-       if (id != 0)
-               report_enum->numbered = 1;
-
-       report->id = id;
-       report->type = type;
-       report->size = 0;
-       report->device = device;
-       report_enum->report_id_hash[id] = report;
-
-       list_add_tail(&report->list, &report_enum->report_list);
-
-       return report;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
-{
-       struct hid_field *field;
-
-       if (report->maxfield == HID_MAX_FIELDS) {
-               dbg("too many fields in report");
-               return NULL;
-       }
-
-       if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-               + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
-
-       field->index = report->maxfield++;
-       report->field[field->index] = field;
-       field->usage = (struct hid_usage *)(field + 1);
-       field->value = (unsigned *)(field->usage + usages);
-       field->report = report;
-
-       return field;
-}
-
-/*
- * Open a collection. The type/usage is pushed on the stack.
- */
-
-static int open_collection(struct hid_parser *parser, unsigned type)
-{
-       struct hid_collection *collection;
-       unsigned usage;
-
-       usage = parser->local.usage[0];
-
-       if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
-               dbg("collection stack overflow");
-               return -1;
-       }
-
-       if (parser->device->maxcollection == parser->device->collection_size) {
-               collection = kmalloc(sizeof(struct hid_collection) *
-                               parser->device->collection_size * 2, GFP_KERNEL);
-               if (collection == NULL) {
-                       dbg("failed to reallocate collection array");
-                       return -1;
-               }
-               memcpy(collection, parser->device->collection,
-                       sizeof(struct hid_collection) *
-                       parser->device->collection_size);
-               memset(collection + parser->device->collection_size, 0,
-                       sizeof(struct hid_collection) *
-                       parser->device->collection_size);
-               kfree(parser->device->collection);
-               parser->device->collection = collection;
-               parser->device->collection_size *= 2;
-       }
-
-       parser->collection_stack[parser->collection_stack_ptr++] =
-               parser->device->maxcollection;
-
-       collection = parser->device->collection +
-               parser->device->maxcollection++;
-       collection->type = type;
-       collection->usage = usage;
-       collection->level = parser->collection_stack_ptr - 1;
-
-       if (type == HID_COLLECTION_APPLICATION)
-               parser->device->maxapplication++;
-
-       return 0;
-}
-
-/*
- * Close a collection.
- */
-
-static int close_collection(struct hid_parser *parser)
-{
-       if (!parser->collection_stack_ptr) {
-               dbg("collection stack underflow");
-               return -1;
-       }
-       parser->collection_stack_ptr--;
-       return 0;
-}
-
-/*
- * Climb up the stack, search for the specified collection type
- * and return the usage.
- */
-
-static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
-{
-       int n;
-       for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
-               if (parser->device->collection[parser->collection_stack[n]].type == type)
-                       return parser->device->collection[parser->collection_stack[n]].usage;
-       return 0; /* we know nothing about this usage type */
-}
-
-/*
- * Add a usage to the temporary parser table.
- */
-
-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
-{
-       if (parser->local.usage_index >= HID_MAX_USAGES) {
-               dbg("usage index exceeded");
-               return -1;
-       }
-       parser->local.usage[parser->local.usage_index] = usage;
-       parser->local.collection_index[parser->local.usage_index] =
-               parser->collection_stack_ptr ?
-               parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
-       parser->local.usage_index++;
-       return 0;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
-{
-       struct hid_report *report;
-       struct hid_field *field;
-       int usages;
-       unsigned offset;
-       int i;
-
-       if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
-               dbg("hid_register_report failed");
-               return -1;
-       }
-
-       if (parser->global.logical_maximum < parser->global.logical_minimum) {
-               dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
-               return -1;
-       }
-
-       offset = report->size;
-       report->size += parser->global.report_size * parser->global.report_count;
-
-       if (!parser->local.usage_index) /* Ignore padding fields */
-               return 0;
-
-       usages = max_t(int, parser->local.usage_index, parser->global.report_count);
-
-       if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
-               return 0;
-
-       field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
-       field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-       field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
-
-       for (i = 0; i < usages; i++) {
-               int j = i;
-               /* Duplicate the last usage we parsed if we have excess values */
-               if (i >= parser->local.usage_index)
-                       j = parser->local.usage_index - 1;
-               field->usage[i].hid = parser->local.usage[j];
-               field->usage[i].collection_index =
-                       parser->local.collection_index[j];
-       }
-
-       field->maxusage = usages;
-       field->flags = flags;
-       field->report_offset = offset;
-       field->report_type = report_type;
-       field->report_size = parser->global.report_size;
-       field->report_count = parser->global.report_count;
-       field->logical_minimum = parser->global.logical_minimum;
-       field->logical_maximum = parser->global.logical_maximum;
-       field->physical_minimum = parser->global.physical_minimum;
-       field->physical_maximum = parser->global.physical_maximum;
-       field->unit_exponent = parser->global.unit_exponent;
-       field->unit = parser->global.unit;
-
-       return 0;
-}
-
-/*
- * Read data value from item.
- */
-
-static u32 item_udata(struct hid_item *item)
-{
-       switch (item->size) {
-               case 1: return item->data.u8;
-               case 2: return item->data.u16;
-               case 4: return item->data.u32;
-       }
-       return 0;
-}
-
-static s32 item_sdata(struct hid_item *item)
-{
-       switch (item->size) {
-               case 1: return item->data.s8;
-               case 2: return item->data.s16;
-               case 4: return item->data.s32;
-       }
-       return 0;
-}
-
-/*
- * Process a global item.
- */
-
-static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
-{
-       switch (item->tag) {
-
-               case HID_GLOBAL_ITEM_TAG_PUSH:
-
-                       if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-                               dbg("global enviroment stack overflow");
-                               return -1;
-                       }
-
-                       memcpy(parser->global_stack + parser->global_stack_ptr++,
-                               &parser->global, sizeof(struct hid_global));
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_POP:
-
-                       if (!parser->global_stack_ptr) {
-                               dbg("global enviroment stack underflow");
-                               return -1;
-                       }
-
-                       memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
-                               sizeof(struct hid_global));
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
-                       parser->global.usage_page = item_udata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
-                       parser->global.logical_minimum = item_sdata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
-                       if (parser->global.logical_minimum < 0)
-                               parser->global.logical_maximum = item_sdata(item);
-                       else
-                               parser->global.logical_maximum = item_udata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
-                       parser->global.physical_minimum = item_sdata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
-                       if (parser->global.physical_minimum < 0)
-                               parser->global.physical_maximum = item_sdata(item);
-                       else
-                               parser->global.physical_maximum = item_udata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-                       parser->global.unit_exponent = item_sdata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_UNIT:
-                       parser->global.unit = item_udata(item);
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
-                       if ((parser->global.report_size = item_udata(item)) > 32) {
-                               dbg("invalid report_size %d", parser->global.report_size);
-                               return -1;
-                       }
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
-                       if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
-                               dbg("invalid report_count %d", parser->global.report_count);
-                               return -1;
-                       }
-                       return 0;
-
-               case HID_GLOBAL_ITEM_TAG_REPORT_ID:
-                       if ((parser->global.report_id = item_udata(item)) == 0) {
-                               dbg("report_id 0 is invalid");
-                               return -1;
-                       }
-                       return 0;
-
-               default:
-                       dbg("unknown global tag 0x%x", item->tag);
-                       return -1;
-       }
-}
-
-/*
- * Process a local item.
- */
-
-static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
-{
-       __u32 data;
-       unsigned n;
-
-       if (item->size == 0) {
-               dbg("item data expected for local item");
-               return -1;
-       }
-
-       data = item_udata(item);
-
-       switch (item->tag) {
-
-               case HID_LOCAL_ITEM_TAG_DELIMITER:
-
-                       if (data) {
-                               /*
-                                * We treat items before the first delimiter
-                                * as global to all usage sets (branch 0).
-                                * In the moment we process only these global
-                                * items and the first delimiter set.
-                                */
-                               if (parser->local.delimiter_depth != 0) {
-                                       dbg("nested delimiters");
-                                       return -1;
-                               }
-                               parser->local.delimiter_depth++;
-                               parser->local.delimiter_branch++;
-                       } else {
-                               if (parser->local.delimiter_depth < 1) {
-                                       dbg("bogus close delimiter");
-                                       return -1;
-                               }
-                               parser->local.delimiter_depth--;
-                       }
-                       return 1;
-
-               case HID_LOCAL_ITEM_TAG_USAGE:
-
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg("alternative usage ignored");
-                               return 0;
-                       }
-
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
-
-                       return hid_add_usage(parser, data);
-
-               case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
-
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg("alternative usage ignored");
-                               return 0;
-                       }
-
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
-
-                       parser->local.usage_minimum = data;
-                       return 0;
-
-               case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
-
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg("alternative usage ignored");
-                               return 0;
-                       }
-
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
-
-                       for (n = parser->local.usage_minimum; n <= data; n++)
-                               if (hid_add_usage(parser, n)) {
-                                       dbg("hid_add_usage failed\n");
-                                       return -1;
-                               }
-                       return 0;
-
-               default:
-
-                       dbg("unknown local item tag 0x%x", item->tag);
-                       return 0;
-       }
-       return 0;
-}
-
-/*
- * Process a main item.
- */
-
-static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
-{
-       __u32 data;
-       int ret;
-
-       data = item_udata(item);
-
-       switch (item->tag) {
-               case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
-                       ret = open_collection(parser, data & 0xff);
-                       break;
-               case HID_MAIN_ITEM_TAG_END_COLLECTION:
-                       ret = close_collection(parser);
-                       break;
-               case HID_MAIN_ITEM_TAG_INPUT:
-                       ret = hid_add_field(parser, HID_INPUT_REPORT, data);
-                       break;
-               case HID_MAIN_ITEM_TAG_OUTPUT:
-                       ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
-                       break;
-               case HID_MAIN_ITEM_TAG_FEATURE:
-                       ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
-                       break;
-               default:
-                       dbg("unknown main item tag 0x%x", item->tag);
-                       ret = 0;
-       }
-
-       memset(&parser->local, 0, sizeof(parser->local));       /* Reset the local parser environment */
-
-       return ret;
-}
-
-/*
- * Process a reserved item.
- */
-
-static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
-{
-       dbg("reserved item type, tag 0x%x", item->tag);
-       return 0;
-}
-
-/*
- * Free a report and all registered fields. The field->usage and
- * field->value table's are allocated behind the field, so we need
- * only to free(field) itself.
- */
-
-static void hid_free_report(struct hid_report *report)
-{
-       unsigned n;
-
-       for (n = 0; n < report->maxfield; n++)
-               kfree(report->field[n]);
-       kfree(report);
-}
-
-/*
- * Free a device structure, all reports, and all fields.
- */
-
-static void hid_free_device(struct hid_device *device)
-{
-       unsigned i,j;
-
-       for (i = 0; i < HID_REPORT_TYPES; i++) {
-               struct hid_report_enum *report_enum = device->report_enum + i;
-
-               for (j = 0; j < 256; j++) {
-                       struct hid_report *report = report_enum->report_id_hash[j];
-                       if (report)
-                               hid_free_report(report);
-               }
-       }
-
-       kfree(device->rdesc);
-       kfree(device);
-}
-
-/*
- * Fetch a report description item from the data stream. We support long
- * items, though they are not used yet.
- */
-
-static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
-{
-       u8 b;
-
-       if ((end - start) <= 0)
-               return NULL;
-
-       b = *start++;
-
-       item->type = (b >> 2) & 3;
-       item->tag  = (b >> 4) & 15;
-
-       if (item->tag == HID_ITEM_TAG_LONG) {
-
-               item->format = HID_ITEM_FORMAT_LONG;
-
-               if ((end - start) < 2)
-                       return NULL;
-
-               item->size = *start++;
-               item->tag  = *start++;
-
-               if ((end - start) < item->size)
-                       return NULL;
-
-               item->data.longdata = start;
-               start += item->size;
-               return start;
-       }
-
-       item->format = HID_ITEM_FORMAT_SHORT;
-       item->size = b & 3;
-
-       switch (item->size) {
-
-               case 0:
-                       return start;
-
-               case 1:
-                       if ((end - start) < 1)
-                               return NULL;
-                       item->data.u8 = *start++;
-                       return start;
-
-               case 2:
-                       if ((end - start) < 2)
-                               return NULL;
-                       item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
-                       start = (__u8 *)((__le16 *)start + 1);
-                       return start;
-
-               case 3:
-                       item->size++;
-                       if ((end - start) < 4)
-                               return NULL;
-                       item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
-                       start = (__u8 *)((__le32 *)start + 1);
-                       return start;
-       }
-
-       return NULL;
-}
-
-/*
- * Parse a report description into a hid_device structure. Reports are
- * enumerated, fields are attached to these reports.
- */
-
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
-{
-       struct hid_device *device;
-       struct hid_parser *parser;
-       struct hid_item item;
-       __u8 *end;
-       unsigned i;
-       static int (*dispatch_type[])(struct hid_parser *parser,
-                                     struct hid_item *item) = {
-               hid_parser_main,
-               hid_parser_global,
-               hid_parser_local,
-               hid_parser_reserved
-       };
-
-       if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
-               return NULL;
-
-       if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
-                                  HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
-               kfree(device);
-               return NULL;
-       }
-       device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
-       for (i = 0; i < HID_REPORT_TYPES; i++)
-               INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
-       if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
-               kfree(device->collection);
-               kfree(device);
-               return NULL;
-       }
-       memcpy(device->rdesc, start, size);
-       device->rsize = size;
-
-       if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
-               kfree(device->rdesc);
-               kfree(device->collection);
-               kfree(device);
-               return NULL;
-       }
-       parser->device = device;
-
-       end = start + size;
-       while ((start = fetch_item(start, end, &item)) != NULL) {
-
-               if (item.format != HID_ITEM_FORMAT_SHORT) {
-                       dbg("unexpected long global item");
-                       kfree(device->collection);
-                       hid_free_device(device);
-                       kfree(parser);
-                       return NULL;
-               }
-
-               if (dispatch_type[item.type](parser, &item)) {
-                       dbg("item %u %u %u %u parsing failed\n",
-                               item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-                       kfree(device->collection);
-                       hid_free_device(device);
-                       kfree(parser);
-                       return NULL;
-               }
-
-               if (start == end) {
-                       if (parser->collection_stack_ptr) {
-                               dbg("unbalanced collection at end of report description");
-                               kfree(device->collection);
-                               hid_free_device(device);
-                               kfree(parser);
-                               return NULL;
-                       }
-                       if (parser->local.delimiter_depth) {
-                               dbg("unbalanced delimiter at end of report description");
-                               kfree(device->collection);
-                               hid_free_device(device);
-                               kfree(parser);
-                               return NULL;
-                       }
-                       kfree(parser);
-                       return device;
-               }
-       }
-
-       dbg("item fetching failed at offset %d\n", (int)(end - start));
-       kfree(device->collection);
-       hid_free_device(device);
-       kfree(parser);
-       return NULL;
-}
-
-/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static s32 snto32(__u32 value, unsigned n)
-{
-       switch (n) {
-               case 8:  return ((__s8)value);
-               case 16: return ((__s16)value);
-               case 32: return ((__s32)value);
-       }
-       return value & (1 << (n - 1)) ? value | (-1 << n) : value;
-}
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static u32 s32ton(__s32 value, unsigned n)
-{
-       s32 a = value >> (n - 1);
-       if (a && a != -1)
-               return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
-       return value & ((1 << n) - 1);
-}
-
-/*
- * Extract/implement a data field from/to a little endian report (bit array).
- *
- * Code sort-of follows HID spec:
- *     http://www.usb.org/developers/devclass_docs/HID1_11.pdf
- *
- * While the USB HID spec allows unlimited length bit fields in "report
- * descriptors", most devices never use more than 16 bits.
- * One model of UPS is claimed to report "LINEV" as a 32-bit field.
- * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
- */
-
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
-{
-       u64 x;
-
-       WARN_ON(n > 32);
-
-       report += offset >> 3;  /* adjust byte index */
-       offset &= 7;            /* now only need bit offset into one byte */
-       x = get_unaligned((u64 *) report);
-       x = le64_to_cpu(x);
-       x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
-       return (u32) x;
-}
-
-/*
- * "implement" : set bits in a little endian bit stream.
- * Same concepts as "extract" (see comments above).
- * The data mangled in the bit stream remains in little endian
- * order the whole time. It make more sense to talk about
- * endianness of register values by considering a register
- * a "cached" copy of the little endiad bit stream.
- */
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
-{
-       u64 x;
-       u64 m = (1ULL << n) - 1;
-
-       WARN_ON(n > 32);
-
-       WARN_ON(value > m);
-       value &= m;
-
-       report += offset >> 3;
-       offset &= 7;
-
-       x = get_unaligned((u64 *)report);
-       x &= cpu_to_le64(~(m << offset));
-       x |= cpu_to_le64(((u64) value) << offset);
-       put_unaligned(x, (u64 *) report);
-}
-
-/*
- * Search an array for a value.
- */
-
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
-{
-       while (n--) {
-               if (*array++ == value)
-                       return 0;
-       }
-       return -1;
-}
-
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
-{
-       hid_dump_input(usage, value);
-       if (hid->claimed & HID_CLAIMED_INPUT)
-               hidinput_hid_event(hid, field, usage, value);
-       if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
-               hiddev_hid_event(hid, field, usage, value);
-}
-
-/*
- * Analyse a received field, and fetch the data from it. The field
- * content is stored for next report processing (we do differential
- * reporting to the layer).
- */
-
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
-{
-       unsigned n;
-       unsigned count = field->report_count;
-       unsigned offset = field->report_offset;
-       unsigned size = field->report_size;
-       __s32 min = field->logical_minimum;
-       __s32 max = field->logical_maximum;
-       __s32 *value;
-
-       if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
-               return;
-
-       for (n = 0; n < count; n++) {
-
-                       value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
-                                                   extract(data, offset + n * size, size);
-
-                       if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
-                           && value[n] >= min && value[n] <= max
-                           && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
-                               goto exit;
-       }
-
-       for (n = 0; n < count; n++) {
-
-               if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-                       hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
-                       continue;
-               }
-
-               if (field->value[n] >= min && field->value[n] <= max
-                       && field->usage[field->value[n] - min].hid
-                       && search(value, field->value[n], count))
-                               hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
-
-               if (value[n] >= min && value[n] <= max
-                       && field->usage[value[n] - min].hid
-                       && search(field->value, value[n], count))
-                               hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
-       }
-
-       memcpy(field->value, value, count * sizeof(__s32));
-exit:
-       kfree(value);
-}
-
-static int hid_input_report(int type, struct urb *urb, int interrupt)
-{
-       struct hid_device *hid = urb->context;
-       struct hid_report_enum *report_enum = hid->report_enum + type;
-       u8 *data = urb->transfer_buffer;
-       int len = urb->actual_length;
-       struct hid_report *report;
-       int n, size;
-
-       if (!len) {
-               dbg("empty report");
-               return -1;
-       }
-
-#ifdef DEBUG_DATA
-       printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
-#endif
-
-       n = 0;                          /* Normally report number is 0 */
-       if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
-               n = *data++;
-               len--;
-       }
-
-#ifdef DEBUG_DATA
-       {
-               int i;
-               printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
-               for (i = 0; i < len; i++)
-                       printk(" %02x", data[i]);
-               printk("\n");
-       }
-#endif
-
-       if (!(report = report_enum->report_id_hash[n])) {
-               dbg("undefined report_id %d received", n);
-               return -1;
-       }
-
-       size = ((report->size - 1) >> 3) + 1;
-
-       if (len < size) {
-               dbg("report %d is too short, (%d < %d)", report->id, len, size);
-               memset(data + len, 0, size - len);
-       }
-
-       if (hid->claimed & HID_CLAIMED_HIDDEV)
-               hiddev_report_event(hid, report);
-
-       for (n = 0; n < report->maxfield; n++)
-               hid_input_field(hid, report->field[n], data, interrupt);
-
-       if (hid->claimed & HID_CLAIMED_INPUT)
-               hidinput_report_event(hid, report);
-
-       return 0;
-}
+static int usbhid_pb_fnmode = 1;
+module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+               "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
 
 /*
  * Input submission and I/O error handler.
@@ -946,15 +72,16 @@ static int hid_start_in(struct hid_device *hid)
 {
        unsigned long flags;
        int rc = 0;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       spin_lock_irqsave(&hid->inlock, flags);
-       if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
-                       !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
-               rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
+       spin_lock_irqsave(&usbhid->inlock, flags);
+       if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+                       !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+               rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
                if (rc != 0)
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
        }
-       spin_unlock_irqrestore(&hid->inlock, flags);
+       spin_unlock_irqrestore(&usbhid->inlock, flags);
        return rc;
 }
 
@@ -962,46 +89,49 @@ static int hid_start_in(struct hid_device *hid)
 static void hid_retry_timeout(unsigned long _hid)
 {
        struct hid_device *hid = (struct hid_device *) _hid;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       dev_dbg(&hid->intf->dev, "retrying intr urb\n");
+       dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
        if (hid_start_in(hid))
                hid_io_error(hid);
 }
 
 /* Workqueue routine to reset the device or clear a halt */
-static void hid_reset(void *_hid)
+static void hid_reset(struct work_struct *work)
 {
-       struct hid_device *hid = (struct hid_device *) _hid;
+       struct usbhid_device *usbhid =
+               container_of(work, struct usbhid_device, reset_work);
+       struct hid_device *hid = usbhid->hid;
        int rc_lock, rc = 0;
 
-       if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
-               dev_dbg(&hid->intf->dev, "clear halt\n");
-               rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
-               clear_bit(HID_CLEAR_HALT, &hid->iofl);
+       if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+               dev_dbg(&usbhid->intf->dev, "clear halt\n");
+               rc = usb_clear_halt(to_usb_device(hid->dev), usbhid->urbin->pipe);
+               clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
                hid_start_in(hid);
        }
 
-       else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
-               dev_dbg(&hid->intf->dev, "resetting device\n");
-               rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+       else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+               dev_dbg(&usbhid->intf->dev, "resetting device\n");
+               rc = rc_lock = usb_lock_device_for_reset(to_usb_device(hid->dev), usbhid->intf);
                if (rc_lock >= 0) {
-                       rc = usb_reset_composite_device(hid->dev, hid->intf);
+                       rc = usb_reset_composite_device(to_usb_device(hid->dev), usbhid->intf);
                        if (rc_lock)
-                               usb_unlock_device(hid->dev);
+                               usb_unlock_device(to_usb_device(hid->dev));
                }
-               clear_bit(HID_RESET_PENDING, &hid->iofl);
+               clear_bit(HID_RESET_PENDING, &usbhid->iofl);
        }
 
        switch (rc) {
        case 0:
-               if (!test_bit(HID_IN_RUNNING, &hid->iofl))
+               if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
                        hid_io_error(hid);
                break;
        default:
                err("can't reset device, %s-%s/input%d, status %d",
-                               hid->dev->bus->bus_name,
-                               hid->dev->devpath,
-                               hid->ifnum, rc);
+                               to_usb_device(hid->dev)->bus->bus_name,
+                               to_usb_device(hid->dev)->devpath,
+                               usbhid->ifnum, rc);
                /* FALLTHROUGH */
        case -EHOSTUNREACH:
        case -ENODEV:
@@ -1014,33 +144,34 @@ static void hid_reset(void *_hid)
 static void hid_io_error(struct hid_device *hid)
 {
        unsigned long flags;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       spin_lock_irqsave(&hid->inlock, flags);
+       spin_lock_irqsave(&usbhid->inlock, flags);
 
        /* Stop when disconnected */
-       if (usb_get_intfdata(hid->intf) == NULL)
+       if (usb_get_intfdata(usbhid->intf) == NULL)
                goto done;
 
        /* When an error occurs, retry at increasing intervals */
-       if (hid->retry_delay == 0) {
-               hid->retry_delay = 13;  /* Then 26, 52, 104, 104, ... */
-               hid->stop_retry = jiffies + msecs_to_jiffies(1000);
-       } else if (hid->retry_delay < 100)
-               hid->retry_delay *= 2;
+       if (usbhid->retry_delay == 0) {
+               usbhid->retry_delay = 13;       /* Then 26, 52, 104, 104, ... */
+               usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
+       } else if (usbhid->retry_delay < 100)
+               usbhid->retry_delay *= 2;
 
-       if (time_after(jiffies, hid->stop_retry)) {
+       if (time_after(jiffies, usbhid->stop_retry)) {
 
                /* Retries failed, so do a port reset */
-               if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
-                       schedule_work(&hid->reset_work);
+               if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+                       schedule_work(&usbhid->reset_work);
                        goto done;
                }
        }
 
-       mod_timer(&hid->io_retry,
-                       jiffies + msecs_to_jiffies(hid->retry_delay));
+       mod_timer(&usbhid->io_retry,
+                       jiffies + msecs_to_jiffies(usbhid->retry_delay));
 done:
-       spin_unlock_irqrestore(&hid->inlock, flags);
+       spin_unlock_irqrestore(&usbhid->inlock, flags);
 }
 
 /*
@@ -1050,108 +181,50 @@ done:
 static void hid_irq_in(struct urb *urb)
 {
        struct hid_device       *hid = urb->context;
+       struct usbhid_device    *usbhid = hid->driver_data;
        int                     status;
 
        switch (urb->status) {
                case 0:                 /* success */
-                       hid->retry_delay = 0;
-                       hid_input_report(HID_INPUT_REPORT, urb, 1);
+                       usbhid->retry_delay = 0;
+                       hid_input_report(urb->context, HID_INPUT_REPORT,
+                                        urb->transfer_buffer,
+                                        urb->actual_length, 1);
                        break;
                case -EPIPE:            /* stall */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
-                       set_bit(HID_CLEAR_HALT, &hid->iofl);
-                       schedule_work(&hid->reset_work);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+                       set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+                       schedule_work(&usbhid->reset_work);
                        return;
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
                case -ESHUTDOWN:        /* unplug */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
                        return;
                case -EILSEQ:           /* protocol error or unplug */
                case -EPROTO:           /* protocol error or unplug */
                case -ETIME:            /* protocol error or unplug */
                case -ETIMEDOUT:        /* Should never happen, but... */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
                        hid_io_error(hid);
                        return;
                default:                /* error */
                        warn("input irq status %d received", urb->status);
        }
 
-       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
-               clear_bit(HID_IN_RUNNING, &hid->iofl);
+               clear_bit(HID_IN_RUNNING, &usbhid->iofl);
                if (status != -EPERM) {
                        err("can't resubmit intr, %s-%s/input%d, status %d",
-                                       hid->dev->bus->bus_name,
-                                       hid->dev->devpath,
-                                       hid->ifnum, status);
+                                       to_usb_device(hid->dev)->bus->bus_name,
+                                       to_usb_device(hid->dev)->devpath,
+                                       usbhid->ifnum, status);
                        hid_io_error(hid);
                }
        }
 }
 
-/*
- * Output the field into the report.
- */
-
-static void hid_output_field(struct hid_field *field, __u8 *data)
-{
-       unsigned count = field->report_count;
-       unsigned offset = field->report_offset;
-       unsigned size = field->report_size;
-       unsigned n;
-
-       for (n = 0; n < count; n++) {
-               if (field->logical_minimum < 0) /* signed values */
-                       implement(data, offset + n * size, size, s32ton(field->value[n], size));
-               else                            /* unsigned values */
-                       implement(data, offset + n * size, size, field->value[n]);
-       }
-}
-
-/*
- * Create a report.
- */
-
-static void hid_output_report(struct hid_report *report, __u8 *data)
-{
-       unsigned n;
-
-       if (report->id > 0)
-               *data++ = report->id;
-
-       for (n = 0; n < report->maxfield; n++)
-               hid_output_field(report->field[n], data);
-}
-
-/*
- * Set a field value. The report this field belongs to has to be
- * created and transferred to the device, to set this value in the
- * device.
- */
-
-int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
-{
-       unsigned size = field->report_size;
-
-       hid_dump_input(field->usage + offset, value);
-
-       if (offset >= field->report_count) {
-               dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
-               hid_dump_field(field, 8);
-               return -1;
-       }
-       if (field->logical_minimum < 0) {
-               if (value != snto32(s32ton(value, size), size)) {
-                       dbg("value %d is out of range", value);
-                       return -1;
-               }
-       }
-       field->value[offset] = value;
-       return 0;
-}
-
 /*
  * Find a report field with a specified HID usage.
  */
@@ -1172,16 +245,17 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u
 static int hid_submit_out(struct hid_device *hid)
 {
        struct hid_report *report;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       report = hid->out[hid->outtail];
+       report = usbhid->out[usbhid->outtail];
 
-       hid_output_report(report, hid->outbuf);
-       hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       hid->urbout->dev = hid->dev;
+       hid_output_report(report, usbhid->outbuf);
+       usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       usbhid->urbout->dev = to_usb_device(hid->dev);
 
        dbg("submitting out urb");
 
-       if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
+       if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
                err("usb_submit_urb(out) failed");
                return -1;
        }
@@ -1194,42 +268,43 @@ static int hid_submit_ctrl(struct hid_device *hid)
        struct hid_report *report;
        unsigned char dir;
        int len;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       report = hid->ctrl[hid->ctrltail].report;
-       dir = hid->ctrl[hid->ctrltail].dir;
+       report = usbhid->ctrl[usbhid->ctrltail].report;
+       dir = usbhid->ctrl[usbhid->ctrltail].dir;
 
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
        if (dir == USB_DIR_OUT) {
-               hid_output_report(report, hid->ctrlbuf);
-               hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0);
-               hid->urbctrl->transfer_buffer_length = len;
+               hid_output_report(report, usbhid->ctrlbuf);
+               usbhid->urbctrl->pipe = usb_sndctrlpipe(to_usb_device(hid->dev), 0);
+               usbhid->urbctrl->transfer_buffer_length = len;
        } else {
                int maxpacket, padlen;
 
-               hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0);
-               maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0);
+               usbhid->urbctrl->pipe = usb_rcvctrlpipe(to_usb_device(hid->dev), 0);
+               maxpacket = usb_maxpacket(to_usb_device(hid->dev), usbhid->urbctrl->pipe, 0);
                if (maxpacket > 0) {
                        padlen = (len + maxpacket - 1) / maxpacket;
                        padlen *= maxpacket;
-                       if (padlen > hid->bufsize)
-                               padlen = hid->bufsize;
+                       if (padlen > usbhid->bufsize)
+                               padlen = usbhid->bufsize;
                } else
                        padlen = 0;
-               hid->urbctrl->transfer_buffer_length = padlen;
+               usbhid->urbctrl->transfer_buffer_length = padlen;
        }
-       hid->urbctrl->dev = hid->dev;
+       usbhid->urbctrl->dev = to_usb_device(hid->dev);
 
-       hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
-       hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
-       hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
-       hid->cr->wIndex = cpu_to_le16(hid->ifnum);
-       hid->cr->wLength = cpu_to_le16(len);
+       usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+       usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
+       usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
+       usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
+       usbhid->cr->wLength = cpu_to_le16(len);
 
        dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
-               hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
-               hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+               usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+               usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
 
-       if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
+       if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
                err("usb_submit_urb(ctrl) failed");
                return -1;
        }
@@ -1244,6 +319,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
 static void hid_irq_out(struct urb *urb)
 {
        struct hid_device *hid = urb->context;
+       struct usbhid_device *usbhid = hid->driver_data;
        unsigned long flags;
        int unplug = 0;
 
@@ -1261,24 +337,24 @@ static void hid_irq_out(struct urb *urb)
                        warn("output irq status %d received", urb->status);
        }
 
-       spin_lock_irqsave(&hid->outlock, flags);
+       spin_lock_irqsave(&usbhid->outlock, flags);
 
        if (unplug)
-               hid->outtail = hid->outhead;
+               usbhid->outtail = usbhid->outhead;
        else
-               hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+               usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
 
-       if (hid->outhead != hid->outtail) {
+       if (usbhid->outhead != usbhid->outtail) {
                if (hid_submit_out(hid)) {
-                       clear_bit(HID_OUT_RUNNING, &hid->iofl);
+                       clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
                        wake_up(&hid->wait);
                }
-               spin_unlock_irqrestore(&hid->outlock, flags);
+               spin_unlock_irqrestore(&usbhid->outlock, flags);
                return;
        }
 
-       clear_bit(HID_OUT_RUNNING, &hid->iofl);
-       spin_unlock_irqrestore(&hid->outlock, flags);
+       clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+       spin_unlock_irqrestore(&usbhid->outlock, flags);
        wake_up(&hid->wait);
 }
 
@@ -1289,15 +365,17 @@ static void hid_irq_out(struct urb *urb)
 static void hid_ctrl(struct urb *urb)
 {
        struct hid_device *hid = urb->context;
+       struct usbhid_device *usbhid = hid->driver_data;
        unsigned long flags;
        int unplug = 0;
 
-       spin_lock_irqsave(&hid->ctrllock, flags);
+       spin_lock_irqsave(&usbhid->ctrllock, flags);
 
        switch (urb->status) {
                case 0:                 /* success */
-                       if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
-                               hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0);
+                       if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+                               hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
+                                               urb->transfer_buffer, urb->actual_length, 0);
                        break;
                case -ESHUTDOWN:        /* unplug */
                        unplug = 1;
@@ -1312,76 +390,102 @@ static void hid_ctrl(struct urb *urb)
        }
 
        if (unplug)
-               hid->ctrltail = hid->ctrlhead;
+               usbhid->ctrltail = usbhid->ctrlhead;
        else
-               hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+               usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
-       if (hid->ctrlhead != hid->ctrltail) {
+       if (usbhid->ctrlhead != usbhid->ctrltail) {
                if (hid_submit_ctrl(hid)) {
-                       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+                       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
                        wake_up(&hid->wait);
                }
-               spin_unlock_irqrestore(&hid->ctrllock, flags);
+               spin_unlock_irqrestore(&usbhid->ctrllock, flags);
                return;
        }
 
-       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-       spin_unlock_irqrestore(&hid->ctrllock, flags);
+       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+       spin_unlock_irqrestore(&usbhid->ctrllock, flags);
        wake_up(&hid->wait);
 }
 
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
 {
        int head;
        unsigned long flags;
+       struct usbhid_device *usbhid = hid->driver_data;
 
        if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
                return;
 
-       if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
+       if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
 
-               spin_lock_irqsave(&hid->outlock, flags);
+               spin_lock_irqsave(&usbhid->outlock, flags);
 
-               if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
-                       spin_unlock_irqrestore(&hid->outlock, flags);
+               if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
+                       spin_unlock_irqrestore(&usbhid->outlock, flags);
                        warn("output queue full");
                        return;
                }
 
-               hid->out[hid->outhead] = report;
-               hid->outhead = head;
+               usbhid->out[usbhid->outhead] = report;
+               usbhid->outhead = head;
 
-               if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
+               if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
                        if (hid_submit_out(hid))
-                               clear_bit(HID_OUT_RUNNING, &hid->iofl);
+                               clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
 
-               spin_unlock_irqrestore(&hid->outlock, flags);
+               spin_unlock_irqrestore(&usbhid->outlock, flags);
                return;
        }
 
-       spin_lock_irqsave(&hid->ctrllock, flags);
+       spin_lock_irqsave(&usbhid->ctrllock, flags);
 
-       if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
-               spin_unlock_irqrestore(&hid->ctrllock, flags);
+       if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
+               spin_unlock_irqrestore(&usbhid->ctrllock, flags);
                warn("control queue full");
                return;
        }
 
-       hid->ctrl[hid->ctrlhead].report = report;
-       hid->ctrl[hid->ctrlhead].dir = dir;
-       hid->ctrlhead = head;
+       usbhid->ctrl[usbhid->ctrlhead].report = report;
+       usbhid->ctrl[usbhid->ctrlhead].dir = dir;
+       usbhid->ctrlhead = head;
 
-       if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
+       if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
                if (hid_submit_ctrl(hid))
-                       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+                       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+
+       spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+}
+
+static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+       struct hid_device *hid = dev->private;
+       struct hid_field *field;
+       int offset;
+
+       if (type == EV_FF)
+               return input_ff_event(dev, type, code, value);
+
+       if (type != EV_LED)
+               return -1;
+
+       if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
+               warn("event field not found");
+               return -1;
+       }
+
+       hid_set_field(field, offset, value);
+       usbhid_submit_report(hid, field->report, USB_DIR_OUT);
 
-       spin_unlock_irqrestore(&hid->ctrllock, flags);
+       return 0;
 }
 
-int hid_wait_io(struct hid_device *hid)
+int usbhid_wait_io(struct hid_device *hid)
 {
-       if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
-                                       !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+                                       !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
                                        10*HZ)) {
                dbg("timeout waiting for ctrl or out queue to clear");
                return -1;
@@ -1413,7 +517,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
        return result;
 }
 
-int hid_open(struct hid_device *hid)
+int usbhid_open(struct hid_device *hid)
 {
        ++hid->open;
        if (hid_start_in(hid))
@@ -1421,10 +525,24 @@ int hid_open(struct hid_device *hid)
        return 0;
 }
 
-void hid_close(struct hid_device *hid)
+void usbhid_close(struct hid_device *hid)
 {
+       struct usbhid_device *usbhid = hid->driver_data;
+
        if (!--hid->open)
-               usb_kill_urb(hid->urbin);
+               usb_kill_urb(usbhid->urbin);
+}
+
+static int hidinput_open(struct input_dev *dev)
+{
+       struct hid_device *hid = dev->private;
+       return usbhid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+       struct hid_device *hid = dev->private;
+       usbhid_close(hid);
 }
 
 #define USB_VENDOR_ID_PANJIT           0x134c
@@ -1436,26 +554,27 @@ void hid_close(struct hid_device *hid)
  * Initialize all reports
  */
 
-void hid_init_reports(struct hid_device *hid)
+void usbhid_init_reports(struct hid_device *hid)
 {
        struct hid_report *report;
+       struct usbhid_device *usbhid = hid->driver_data;
        int err, ret;
 
        list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
-               hid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
 
        list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
-               hid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
 
        err = 0;
-       ret = hid_wait_io(hid);
+       ret = usbhid_wait_io(hid);
        while (ret) {
                err |= ret;
-               if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
-                       usb_kill_urb(hid->urbctrl);
-               if (test_bit(HID_OUT_RUNNING, &hid->iofl))
-                       usb_kill_urb(hid->urbout);
-               ret = hid_wait_io(hid);
+               if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+                       usb_kill_urb(usbhid->urbctrl);
+               if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+                       usb_kill_urb(usbhid->urbout);
+               ret = usbhid_wait_io(hid);
        }
 
        if (err)
@@ -1669,6 +788,9 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_AIRCABLE         0x16CA
 #define USB_DEVICE_ID_AIRCABLE1                0x1502
 
+#define USB_VENDOR_ID_LOGITECH         0x046d
+#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER    0xc101
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1840,7 +962,9 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
 
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-       
+
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+
        { 0, 0 }
 };
 
@@ -1863,13 +987,15 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *
 
 static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
                return -1;
-       if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
+       if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
                return -1;
-       if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
+       if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
                return -1;
-       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+       if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
                return -1;
 
        return 0;
@@ -1877,14 +1003,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (hid->inbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
-       if (hid->outbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
-       if (hid->cr)
-               usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
-       if (hid->ctrlbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (usbhid->inbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+       if (usbhid->outbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+       if (usbhid->cr)
+               usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+       if (usbhid->ctrlbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
 }
 
 /*
@@ -1910,6 +1038,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        unsigned quirks = 0, rsize = 0;
        char *rdesc;
        int n, len, insize = 0;
+       struct usbhid_device *usbhid;
 
         /* Ignore all Wacom devices */
         if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
@@ -1979,13 +1108,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        kfree(rdesc);
        hid->quirks = quirks;
 
-       hid->bufsize = HID_MIN_BUFFER_SIZE;
-       hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
-       hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
-       hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+       if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
+               goto fail;
+
+       hid->driver_data = usbhid;
+       usbhid->hid = hid;
 
-       if (hid->bufsize > HID_MAX_BUFFER_SIZE)
-               hid->bufsize = HID_MAX_BUFFER_SIZE;
+       usbhid->bufsize = HID_MIN_BUFFER_SIZE;
+       hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
+       hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
+       hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);
+
+       if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
+               usbhid->bufsize = HID_MAX_BUFFER_SIZE;
 
        hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
 
@@ -2014,47 +1149,47 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                        interval = hid_mousepoll_interval;
 
                if (usb_endpoint_dir_in(endpoint)) {
-                       if (hid->urbin)
+                       if (usbhid->urbin)
                                continue;
-                       if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
+                       if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
+                       usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
                                         hid_irq_in, hid, interval);
-                       hid->urbin->transfer_dma = hid->inbuf_dma;
-                       hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+                       usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
+                       usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                } else {
-                       if (hid->urbout)
+                       if (usbhid->urbout)
                                continue;
-                       if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
+                       if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
-                       usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
+                       usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
                                         hid_irq_out, hid, interval);
-                       hid->urbout->transfer_dma = hid->outbuf_dma;
-                       hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+                       usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
+                       usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                }
        }
 
-       if (!hid->urbin) {
+       if (!usbhid->urbin) {
                err("couldn't find an input interrupt endpoint");
                goto fail;
        }
 
        init_waitqueue_head(&hid->wait);
 
-       INIT_WORK(&hid->reset_work, hid_reset, hid);
-       setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
+       INIT_WORK(&usbhid->reset_work, hid_reset);
+       setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
 
-       spin_lock_init(&hid->inlock);
-       spin_lock_init(&hid->outlock);
-       spin_lock_init(&hid->ctrllock);
+       spin_lock_init(&usbhid->inlock);
+       spin_lock_init(&usbhid->outlock);
+       spin_lock_init(&usbhid->ctrllock);
 
        hid->version = le16_to_cpu(hdesc->bcdHID);
        hid->country = hdesc->bCountryCode;
-       hid->dev = dev;
-       hid->intf = intf;
-       hid->ifnum = interface->desc.bInterfaceNumber;
+       hid->dev = &dev->dev;
+       usbhid->intf = intf;
+       usbhid->ifnum = interface->desc.bInterfaceNumber;
 
        hid->name[0] = 0;
 
@@ -2072,6 +1207,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                         le16_to_cpu(dev->descriptor.idVendor),
                         le16_to_cpu(dev->descriptor.idProduct));
 
+       hid->bus = BUS_USB;
+       hid->vendor = dev->descriptor.idVendor;
+       hid->product = dev->descriptor.idProduct;
+
        usb_make_path(dev, hid->phys, sizeof(hid->phys));
        strlcat(hid->phys, "/input", sizeof(hid->phys));
        len = strlen(hid->phys);
@@ -2082,22 +1221,32 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
                hid->uniq[0] = 0;
 
-       hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-       if (!hid->urbctrl)
+       usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+       if (!usbhid->urbctrl)
                goto fail;
 
-       usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
-                            hid->ctrlbuf, 1, hid_ctrl, hid);
-       hid->urbctrl->setup_dma = hid->cr_dma;
-       hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+       usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
+                            usbhid->ctrlbuf, 1, hid_ctrl, hid);
+       usbhid->urbctrl->setup_dma = usbhid->cr_dma;
+       usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
+       usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+       hid->hidinput_input_event = usb_hidinput_input_event;
+       hid->hidinput_open = hidinput_open;
+       hid->hidinput_close = hidinput_close;
+#ifdef CONFIG_USB_HIDDEV
+       hid->hiddev_hid_event = hiddev_hid_event;
+       hid->hiddev_report_event = hiddev_report_event;
+#endif
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+       hid->pb_fnmode = usbhid_pb_fnmode;
+#endif
 
        return hid;
 
 fail:
-       usb_free_urb(hid->urbin);
-       usb_free_urb(hid->urbout);
-       usb_free_urb(hid->urbctrl);
+       usb_free_urb(usbhid->urbin);
+       usb_free_urb(usbhid->urbout);
+       usb_free_urb(usbhid->urbctrl);
        hid_free_buffers(dev, hid);
        hid_free_device(hid);
 
@@ -2107,18 +1256,21 @@ fail:
 static void hid_disconnect(struct usb_interface *intf)
 {
        struct hid_device *hid = usb_get_intfdata (intf);
+       struct usbhid_device *usbhid;
 
        if (!hid)
                return;
 
-       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
+       usbhid = hid->driver_data;
+
+       spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
        usb_set_intfdata(intf, NULL);
-       spin_unlock_irq(&hid->inlock);
-       usb_kill_urb(hid->urbin);
-       usb_kill_urb(hid->urbout);
-       usb_kill_urb(hid->urbctrl);
+       spin_unlock_irq(&usbhid->inlock);
+       usb_kill_urb(usbhid->urbin);
+       usb_kill_urb(usbhid->urbout);
+       usb_kill_urb(usbhid->urbctrl);
 
-       del_timer_sync(&hid->io_retry);
+       del_timer_sync(&usbhid->io_retry);
        flush_scheduled_work();
 
        if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2126,11 +1278,11 @@ static void hid_disconnect(struct usb_interface *intf)
        if (hid->claimed & HID_CLAIMED_HIDDEV)
                hiddev_disconnect(hid);
 
-       usb_free_urb(hid->urbin);
-       usb_free_urb(hid->urbctrl);
-       usb_free_urb(hid->urbout);
+       usb_free_urb(usbhid->urbin);
+       usb_free_urb(usbhid->urbctrl);
+       usb_free_urb(usbhid->urbout);
 
-       hid_free_buffers(hid->dev, hid);
+       hid_free_buffers(to_usb_device(hid->dev), hid);
        hid_free_device(hid);
 }
 
@@ -2147,7 +1299,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (!(hid = usb_hid_configure(intf)))
                return -ENODEV;
 
-       hid_init_reports(hid);
+       usbhid_init_reports(hid);
        hid_dump_device(hid);
 
        if (!hidinput_connect(hid))
@@ -2163,6 +1315,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
                return -ENODEV;
        }
 
+       /* This only gets called when we are a single-input (most of the
+        * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
+        * only useful in this case, and not for multi-input quirks. */
+       if ((hid->claimed & HID_CLAIMED_INPUT) &&
+                       !(hid->quirks & HID_QUIRK_MULTI_INPUT))
+               hid_ff_init(hid);
+
        printk(KERN_INFO);
 
        if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2193,12 +1352,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct hid_device *hid = usb_get_intfdata (intf);
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
-       set_bit(HID_SUSPENDED, &hid->iofl);
-       spin_unlock_irq(&hid->inlock);
-       del_timer(&hid->io_retry);
-       usb_kill_urb(hid->urbin);
+       spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+       set_bit(HID_SUSPENDED, &usbhid->iofl);
+       spin_unlock_irq(&usbhid->inlock);
+       del_timer(&usbhid->io_retry);
+       usb_kill_urb(usbhid->urbin);
        dev_dbg(&intf->dev, "suspend\n");
        return 0;
 }
@@ -2206,10 +1366,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 static int hid_resume(struct usb_interface *intf)
 {
        struct hid_device *hid = usb_get_intfdata (intf);
+       struct usbhid_device *usbhid = hid->driver_data;
        int status;
 
-       clear_bit(HID_SUSPENDED, &hid->iofl);
-       hid->retry_delay = 0;
+       clear_bit(HID_SUSPENDED, &usbhid->iofl);
+       usbhid->retry_delay = 0;
        status = hid_start_in(hid);
        dev_dbg(&intf->dev, "resume status %d\n", status);
        return status;
index a8fc46c..f8f660e 100644 (file)
@@ -32,7 +32,7 @@
 #undef DEBUG
 #include <linux/usb.h>
 
-#include "hid.h"
+#include <linux/hid.h>
 
 /*
  * This table contains pointers to initializers. To add support for new
@@ -70,8 +70,8 @@ static struct hid_ff_initializer inits[] = {
 int hid_ff_init(struct hid_device* hid)
 {
        struct hid_ff_initializer *init;
-       int vendor = le16_to_cpu(hid->dev->descriptor.idVendor);
-       int product = le16_to_cpu(hid->dev->descriptor.idProduct);
+       int vendor = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idVendor);
+       int product = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idProduct);
 
        for (init = inits; init->idVendor; init++)
                if (init->idVendor == vendor && init->idProduct == product)
@@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid)
 
        return init->init(hid);
 }
+EXPORT_SYMBOL_GPL(hid_ff_init);
+
index 93da222..e474662 100644 (file)
@@ -29,7 +29,8 @@
 
 #include <linux/input.h>
 #include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
 
 struct device_type {
        u16 idVendor;
@@ -75,7 +76,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = x;
                report->field[0]->value[3] = y;
                dbg("(x, y)=(%04x, %04x)", x, y);
-               hid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
                break;
 
        case FF_RUMBLE:
@@ -90,7 +91,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = left;
                report->field[0]->value[3] = right;
                dbg("(left, right)=(%04x, %04x)", left, right);
-               hid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
                break;
        }
        return 0;
index 5420c13..cbd2d53 100644 (file)
@@ -28,7 +28,9 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 
-#include "hid.h"
+#include <linux/hid.h>
+
+#include "usbhid.h"
 
 #define        PID_EFFECTS_MAX         64
 
@@ -260,7 +262,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
        debug("attack %u => %d", envelope->attack_level,
              pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
                          USB_DIR_OUT);
 }
 
@@ -287,7 +289,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
        pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
                         effect->u.constant.level);
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
                          USB_DIR_OUT);
 }
 
@@ -322,7 +324,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
                                pidff->effect_direction);
        pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
                          USB_DIR_OUT);
 }
 
@@ -354,7 +356,7 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
        pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
        pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
                          USB_DIR_OUT);
 
 }
@@ -396,8 +398,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
                          effect->u.condition[i].left_saturation);
                pidff_set(&pidff->set_condition[PID_DEAD_BAND],
                          effect->u.condition[i].deadband);
-               hid_wait_io(pidff->hid);
-               hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
+               usbhid_wait_io(pidff->hid);
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
                                  USB_DIR_OUT);
        }
 }
@@ -438,7 +440,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
                         effect->u.ramp.start_level);
        pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
                         effect->u.ramp.end_level);
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
                          USB_DIR_OUT);
 }
 
@@ -463,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
        int j;
 
        pidff->create_new_effect_type->value[0] = efnum;
-       hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
                          USB_DIR_OUT);
        debug("create_new_effect sent, type: %d", efnum);
 
        pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
        pidff->block_load_status->value[0] = 0;
-       hid_wait_io(pidff->hid);
+       usbhid_wait_io(pidff->hid);
 
        for (j = 0; j < 60; j++) {
                debug("pid_block_load requested");
-               hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
                                  USB_DIR_IN);
-               hid_wait_io(pidff->hid);
+               usbhid_wait_io(pidff->hid);
                if (pidff->block_load_status->value[0] ==
                    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
                        debug("device reported free memory: %d bytes",
@@ -511,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
                pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
        }
 
-       hid_wait_io(pidff->hid);
-       hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+       usbhid_wait_io(pidff->hid);
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
                          USB_DIR_OUT);
 }
 
@@ -534,7 +536,7 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 {
        pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-       hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
                          USB_DIR_OUT);
 }
 
@@ -714,7 +716,7 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
        struct pidff_device *pidff = dev->ff->private;
 
        pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
-       hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
                          USB_DIR_OUT);
 }
 
@@ -739,7 +741,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
        pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
        pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
                          USB_DIR_OUT);
 }
 
@@ -1163,19 +1165,19 @@ static void pidff_reset(struct pidff_device *pidff)
 
        pidff->device_control->value[0] = pidff->control_id[PID_RESET];
        /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
 
        pidff->device_control->value[0] =
                pidff->control_id[PID_ENABLE_ACTUATORS];
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
 
        /* pool report is sometimes messed up, refetch it */
-       hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
+       usbhid_wait_io(hid);
 
        if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
                int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0];
@@ -1187,9 +1189,9 @@ static void pidff_reset(struct pidff_device *pidff)
                                break;
                        }
                        debug("pid_pool requested again");
-                       hid_submit_report(hid, pidff->reports[PID_POOL],
+                       usbhid_submit_report(hid, pidff->reports[PID_POOL],
                                          USB_DIR_IN);
-                       hid_wait_io(hid);
+                       usbhid_wait_io(hid);
                }
        }
 }
@@ -1275,7 +1277,7 @@ int hid_pidff_init(struct hid_device *hid)
 
        if (test_bit(FF_GAIN, dev->ffbit)) {
                pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-               hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
                                  USB_DIR_OUT);
        }
 
index 2d5be4c..ab67331 100644 (file)
@@ -32,7 +32,8 @@
 #undef DEBUG
 #include <linux/usb.h>
 
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
 
 /* Usages for thrustmaster devices I know about */
 #define THRUSTMASTER_USAGE_RUMBLE_LR   (HID_UP_GENDESK | 0xbb)
@@ -70,7 +71,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
        tmff->rumble->value[0] = left;
        tmff->rumble->value[1] = right;
        dbg("(left,right)=(%08x, %08x)", left, right);
-       hid_submit_report(hid, tmff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
 
        return 0;
 }
index d2ce321..7bd8238 100644 (file)
@@ -27,7 +27,8 @@
 
 #include <linux/input.h>
 #include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
 
 struct zpff_device {
        struct hid_report *report;
@@ -56,7 +57,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
        zpff->report->field[2]->value[0] = left;
        zpff->report->field[3]->value[0] = right;
        debug("running with 0x%02x 0x%02x", left, right);
-       hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
        return 0;
 }
@@ -101,7 +102,7 @@ int hid_zpff_init(struct hid_device *hid)
        zpff->report->field[1]->value[0] = 0x02;
        zpff->report->field[2]->value[0] = 0x00;
        zpff->report->field[3]->value[0] = 0x00;
-       hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
        printk(KERN_INFO "Force feedback for Zeroplus based devices by "
               "Anssi Hannula <anssi.hannula@gmail.com>\n");
index 7dc14d0..114d6c9 100644 (file)
@@ -32,8 +32,9 @@
 #include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
 #include <linux/hiddev.h>
+#include "usbhid.h"
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 #define HIDDEV_MINOR_BASE      0
@@ -196,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 
        hiddev_send_event(hid, &uref);
 }
-
+EXPORT_SYMBOL_GPL(hiddev_hid_event);
 
 void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
 {
@@ -213,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
 
        hiddev_send_event(hid, &uref);
 }
+
 /*
  * fasync file op
  */
@@ -239,7 +241,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
 
        if (!--list->hiddev->open) {
                if (list->hiddev->exist)
-                       hid_close(list->hiddev->hid);
+                       usbhid_close(list->hiddev->hid);
                else
                        kfree(list->hiddev);
        }
@@ -270,7 +272,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
 
        if (!list->hiddev->open++)
                if (list->hiddev->exist)
-                       hid_open(hiddev_table[i]->hid);
+                       usbhid_open(hiddev_table[i]->hid);
 
        return 0;
 }
@@ -382,7 +384,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct hiddev_list *list = file->private_data;
        struct hiddev *hiddev = list->hiddev;
        struct hid_device *hid = hiddev->hid;
-       struct usb_device *dev = hid->dev;
+       struct usb_device *dev = to_usb_device(hid->dev);
        struct hiddev_collection_info cinfo;
        struct hiddev_report_info rinfo;
        struct hiddev_field_info finfo;
@@ -391,6 +393,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct hiddev_devinfo dinfo;
        struct hid_report *report;
        struct hid_field *field;
+       struct usbhid_device *usbhid = hid->driver_data;
        void __user *user_arg = (void __user *)arg;
        int i;
 
@@ -420,7 +423,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                dinfo.bustype = BUS_USB;
                dinfo.busnum = dev->bus->busnum;
                dinfo.devnum = dev->devnum;
-               dinfo.ifnum = hid->ifnum;
+               dinfo.ifnum = usbhid->ifnum;
                dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
                dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
                dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
@@ -479,7 +482,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                }
 
        case HIDIOCINITREPORT:
-               hid_init_reports(hid);
+               usbhid_init_reports(hid);
 
                return 0;
 
@@ -493,8 +496,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               hid_submit_report(hid, report, USB_DIR_IN);
-               hid_wait_io(hid);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_wait_io(hid);
 
                return 0;
 
@@ -508,8 +511,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               hid_submit_report(hid, report, USB_DIR_OUT);
-               hid_wait_io(hid);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_wait_io(hid);
 
                return 0;
 
@@ -745,6 +748,7 @@ static struct usb_class_driver hiddev_class = {
 int hiddev_connect(struct hid_device *hid)
 {
        struct hiddev *hiddev;
+       struct usbhid_device *usbhid = hid->driver_data;
        int i;
        int retval;
 
@@ -760,7 +764,7 @@ int hiddev_connect(struct hid_device *hid)
        if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
                return -1;
 
-       retval = usb_register_dev(hid->intf, &hiddev_class);
+       retval = usb_register_dev(usbhid->intf, &hiddev_class);
        if (retval) {
                err("Not able to get a minor for this device.");
                kfree(hiddev);
@@ -772,10 +776,10 @@ int hiddev_connect(struct hid_device *hid)
        hiddev->hid = hid;
        hiddev->exist = 1;
 
-       hid->minor = hid->intf->minor;
+       hid->minor = usbhid->intf->minor;
        hid->hiddev = hiddev;
 
-       hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+       hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
 
        return 0;
 }
@@ -788,14 +792,15 @@ static struct usb_class_driver hiddev_class;
 void hiddev_disconnect(struct hid_device *hid)
 {
        struct hiddev *hiddev = hid->hiddev;
+       struct usbhid_device *usbhid = hid->driver_data;
 
        hiddev->exist = 0;
 
        hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-       usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+       usb_deregister_dev(usbhid->intf, &hiddev_class);
 
        if (hiddev->open) {
-               hid_close(hiddev->hid);
+               usbhid_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
        } else {
                kfree(hiddev);
index 50aa810..98bd323 100644 (file)
@@ -456,7 +456,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        remote->in_endpoint = endpoint;
        remote->toggle = -1;    /* Set to -1 so we will always not match the toggle from the first remote message. */
 
-       remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+       remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
        if (!remote->in_buffer) {
                retval = -ENOMEM;
                goto fail1;
index 79a85d4..92c4e07 100644 (file)
@@ -164,7 +164,7 @@ static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *m
        dbg("%s - called", __FUNCTION__);
 
        mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-                                       SLAB_ATOMIC, &mtouch->data_dma);
+                                       GFP_ATOMIC, &mtouch->data_dma);
 
        if (!mtouch->data)
                return -1;
index 0bf9177..fea97e5 100644 (file)
@@ -277,12 +277,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig
 static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
 {
        pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX,
-                                   SLAB_ATOMIC, &pm->data_dma);
+                                   GFP_ATOMIC, &pm->data_dma);
        if (!pm->data)
                return -1;
 
        pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
-                                       SLAB_ATOMIC, &pm->configcr_dma);
+                                       GFP_ATOMIC, &pm->configcr_dma);
        if (!pm->configcr)
                return -1;
 
index 05c0d1c..2a314b0 100644 (file)
@@ -248,7 +248,7 @@ static int touchkit_alloc_buffers(struct usb_device *udev,
                                  struct touchkit_usb *touchkit)
 {
        touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE,
-                                         SLAB_ATOMIC, &touchkit->data_dma);
+                                         GFP_ATOMIC, &touchkit->data_dma);
 
        if (!touchkit->data)
                return -1;
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
new file mode 100644 (file)
index 0000000..830107e
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __USBHID_H
+#define __USBHID_H
+
+/*
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+
+/*  API provided by hid-core.c for USB HID drivers */
+int usbhid_wait_io(struct hid_device* hid);
+void usbhid_close(struct hid_device *hid);
+int usbhid_open(struct hid_device *hid);
+void usbhid_init_reports(struct hid_device *hid);
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+
+/*
+ * USB-specific HID struct, to be pointed to
+ * from struct hid_device->driver_data
+ */
+
+struct usbhid_device {
+       struct hid_device *hid;                                         /* pointer to corresponding HID dev */
+
+       struct usb_interface *intf;                                     /* USB interface */
+       int ifnum;                                                      /* USB interface number */
+
+       unsigned int bufsize;                                           /* URB buffer size */
+
+       struct urb *urbin;                                              /* Input URB */
+       char *inbuf;                                                    /* Input buffer */
+       dma_addr_t inbuf_dma;                                           /* Input buffer dma */
+       spinlock_t inlock;                                              /* Input fifo spinlock */
+
+       struct urb *urbctrl;                                            /* Control URB */
+       struct usb_ctrlrequest *cr;                                     /* Control request struct */
+       dma_addr_t cr_dma;                                              /* Control request struct dma */
+       struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];            /* Control fifo */
+       unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
+       char *ctrlbuf;                                                  /* Control buffer */
+       dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
+       spinlock_t ctrllock;                                            /* Control fifo spinlock */
+
+       struct urb *urbout;                                             /* Output URB */
+       struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
+       unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
+       char *outbuf;                                                   /* Output buffer */
+       dma_addr_t outbuf_dma;                                          /* Output buffer dma */
+       spinlock_t outlock;                                             /* Output fifo spinlock */
+
+       unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+       struct timer_list io_retry;                                     /* Retry timer */
+       unsigned long stop_retry;                                       /* Time to give up, in jiffies */
+       unsigned int retry_delay;                                       /* Delay length in ms */
+       struct work_struct reset_work;                                  /* Task context for resets */
+
+};
+
+#endif
+
index dac8864..8505824 100644 (file)
@@ -122,7 +122,7 @@ static void usb_kbd_irq(struct urb *urb)
        memcpy(kbd->old, kbd->new, 8);
 
 resubmit:
-       i = usb_submit_urb (urb, SLAB_ATOMIC);
+       i = usb_submit_urb (urb, GFP_ATOMIC);
        if (i)
                err ("can't resubmit intr, %s-%s/input0, status %d",
                                kbd->usbdev->bus->bus_name,
@@ -196,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
                return -1;
        if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
                return -1;
-       if (!(kbd->new = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbd->new_dma)))
+       if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
                return -1;
-       if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), SLAB_ATOMIC, &kbd->cr_dma)))
+       if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
                return -1;
-       if (!(kbd->leds = usb_buffer_alloc(dev, 1, SLAB_ATOMIC, &kbd->leds_dma)))
+       if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
                return -1;
 
        return 0;
index 68a5564..64a33e4 100644 (file)
@@ -86,7 +86,7 @@ static void usb_mouse_irq(struct urb *urb)
 
        input_sync(dev);
 resubmit:
-       status = usb_submit_urb (urb, SLAB_ATOMIC);
+       status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("can't resubmit intr, %s-%s/input0, status %d",
                                mouse->usbdev->bus->bus_name,
@@ -137,7 +137,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
        if (!mouse || !input_dev)
                goto fail1;
 
-       mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
+       mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
        if (!mouse->data)
                goto fail1;
 
index 49704d4..7f3c57d 100644 (file)
@@ -680,7 +680,7 @@ static int usbtouch_probe(struct usb_interface *intf,
                type->process_pkt = usbtouch_process_pkt;
 
        usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
-                                         SLAB_KERNEL, &usbtouch->data_dma);
+                                         GFP_KERNEL, &usbtouch->data_dma);
        if (!usbtouch->data)
                goto out_free;
 
index df97e5c..e4bc76e 100644 (file)
@@ -325,7 +325,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
                goto fail1;
 
        xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
-                                      SLAB_ATOMIC, &xpad->idata_dma);
+                                      GFP_ATOMIC, &xpad->idata_dma);
        if (!xpad->idata)
                goto fail1;
 
index 2268ca3..caff8e6 100644 (file)
@@ -874,17 +874,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
        /* allocate usb buffers */
        yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
-                                       SLAB_ATOMIC, &yld->irq_dma);
+                                       GFP_ATOMIC, &yld->irq_dma);
        if (yld->irq_data == NULL)
                return usb_cleanup(yld, -ENOMEM);
 
        yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
-                                       SLAB_ATOMIC, &yld->ctl_dma);
+                                       GFP_ATOMIC, &yld->ctl_dma);
        if (!yld->ctl_data)
                return usb_cleanup(yld, -ENOMEM);
 
        yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
-                                       SLAB_ATOMIC, &yld->ctl_req_dma);
+                                       GFP_ATOMIC, &yld->ctl_req_dma);
        if (yld->ctl_req == NULL)
                return usb_cleanup(yld, -ENOMEM);
 
index ba30ca6..02cbb7f 100644 (file)
@@ -76,7 +76,7 @@ struct appledisplay {
        char *urbdata;                  /* interrupt URB data buffer */
        char *msgdata;                  /* control message data buffer */
 
-       struct work_struct work;
+       struct delayed_work work;
        int button_pressed;
        spinlock_t lock;
 };
@@ -117,7 +117,7 @@ static void appledisplay_complete(struct urb *urb)
        case ACD_BTN_BRIGHT_UP:
        case ACD_BTN_BRIGHT_DOWN:
                pdata->button_pressed = 1;
-               queue_work(wq, &pdata->work);
+               queue_delayed_work(wq, &pdata->work, 0);
                break;
        case ACD_BTN_NONE:
        default:
@@ -184,9 +184,10 @@ static struct backlight_properties appledisplay_bl_data = {
        .max_brightness = 0xFF
 };
 
-static void appledisplay_work(void *private)
+static void appledisplay_work(struct work_struct *work)
 {
-       struct appledisplay *pdata = private;
+       struct appledisplay *pdata =
+               container_of(work, struct appledisplay, work.work);
        int retval;
 
        up(&pdata->bd->sem);
@@ -238,7 +239,7 @@ static int appledisplay_probe(struct usb_interface *iface,
        pdata->udev = udev;
 
        spin_lock_init(&pdata->lock);
-       INIT_WORK(&pdata->work, appledisplay_work, pdata);
+       INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
 
        /* Allocate buffer for control messages */
        pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
index cb0ba31..18b1925 100644 (file)
@@ -156,9 +156,9 @@ struct usb_ftdi {
         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 delayed_work status_work;
+        struct delayed_work command_work;
+        struct delayed_work respond_work;
         struct u132_platform_data platform_data;
         struct resource resources[0];
         struct platform_device platform_dev;
@@ -210,23 +210,14 @@ static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
 
 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;
+       if (!queue_delayed_work(status_queue, &ftdi->status_work, delta))
+               kref_put(&ftdi->kref, ftdi_elan_delete);
 }
 
 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;
+       if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+               kref_get(&ftdi->kref);
 }
 
 static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
@@ -237,25 +228,14 @@ static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
 
 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;
+       if (!queue_delayed_work(command_queue, &ftdi->command_work, delta))
+               kref_put(&ftdi->kref, ftdi_elan_delete);
 }
 
 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;
+       if (queue_delayed_work(command_queue, &ftdi->command_work, delta))
+               kref_get(&ftdi->kref);
 }
 
 static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
@@ -267,25 +247,14 @@ static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
 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;
+       if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta))
+               kref_put(&ftdi->kref, ftdi_elan_delete);
 }
 
 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;
+       if (queue_delayed_work(respond_queue, &ftdi->respond_work, delta))
+               kref_get(&ftdi->kref);
 }
 
 static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
@@ -475,9 +444,11 @@ static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
         return;
 }
 
-static void ftdi_elan_command_work(void *data)
+static void ftdi_elan_command_work(struct work_struct *work)
 {
-        struct usb_ftdi *ftdi = data;
+        struct usb_ftdi *ftdi =
+               container_of(work, struct usb_ftdi, command_work.work);
+
         if (ftdi->disconnected > 0) {
                 ftdi_elan_put_kref(ftdi);
                 return;
@@ -500,9 +471,10 @@ static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
         return;
 }
 
-static void ftdi_elan_respond_work(void *data)
+static void ftdi_elan_respond_work(struct work_struct *work)
 {
-        struct usb_ftdi *ftdi = data;
+        struct usb_ftdi *ftdi =
+               container_of(work, struct usb_ftdi, respond_work.work);
         if (ftdi->disconnected > 0) {
                 ftdi_elan_put_kref(ftdi);
                 return;
@@ -534,9 +506,10 @@ static void ftdi_elan_respond_work(void *data)
 * after the FTDI has been synchronized
 *
 */
-static void ftdi_elan_status_work(void *data)
+static void ftdi_elan_status_work(struct work_struct *work)
 {
-        struct usb_ftdi *ftdi = data;
+        struct usb_ftdi *ftdi =
+               container_of(work, struct usb_ftdi, status_work.work);
         int work_delay_in_msec = 0;
         if (ftdi->disconnected > 0) {
                 ftdi_elan_put_kref(ftdi);
@@ -2677,12 +2650,9 @@ static int ftdi_elan_probe(struct usb_interface *interface,
                 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);
+                INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work);
+                INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work);
+                INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work);
                 ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
                 return 0;
         } else {
index 9110793..371bf2b 100644 (file)
@@ -81,8 +81,8 @@ struct interfacekit {
        unsigned char *data;
        dma_addr_t data_dma;
 
-       struct work_struct do_notify;
-       struct work_struct do_resubmit;
+       struct delayed_work do_notify;
+       struct delayed_work do_resubmit;
        unsigned long input_events;
        unsigned long sensor_events;
 };
@@ -374,19 +374,20 @@ static void interfacekit_irq(struct urb *urb)
        }
 
        if (kit->input_events || kit->sensor_events)
-               schedule_work(&kit->do_notify);
+               schedule_delayed_work(&kit->do_notify, 0);
 
 resubmit:
-       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status)
                err("can't resubmit intr, %s-%s/interfacekit0, status %d",
                        kit->udev->bus->bus_name,
                        kit->udev->devpath, status);
 }
 
-static void do_notify(void *data)
+static void do_notify(struct work_struct *work)
 {
-       struct interfacekit *kit = data;
+       struct interfacekit *kit =
+               container_of(work, struct interfacekit, do_notify.work);
        int i;
        char sysfs_file[8];
 
@@ -405,9 +406,11 @@ static void do_notify(void *data)
        }
 }
 
-static void do_resubmit(void *data)
+static void do_resubmit(struct work_struct *work)
 {
-       set_outputs(data);
+       struct interfacekit *kit =
+               container_of(work, struct interfacekit, do_resubmit.work);
+       set_outputs(kit);
 }
 
 #define show_set_output(value)         \
@@ -565,7 +568,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
 
        kit->dev_no = -1;
        kit->ifkit = ifkit;
-       kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
+       kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma);
        if (!kit->data)
                goto out;
 
@@ -575,8 +578,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
 
        kit->udev = usb_get_dev(dev);
        kit->intf = intf;
-       INIT_WORK(&kit->do_notify, do_notify, kit);
-       INIT_WORK(&kit->do_resubmit, do_resubmit, kit);
+       INIT_DELAYED_WORK(&kit->do_notify, do_notify);
+       INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit);
        usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
                        maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
                        interfacekit_irq, kit, endpoint->bInterval);
index c3469b0..5727e1e 100644 (file)
@@ -41,7 +41,7 @@ struct motorcontrol {
        unsigned char *data;
        dma_addr_t data_dma;
 
-       struct work_struct do_notify;
+       struct delayed_work do_notify;
        unsigned long input_events;
        unsigned long speed_events;
        unsigned long exceed_events;
@@ -148,10 +148,10 @@ static void motorcontrol_irq(struct urb *urb)
                set_bit(1, &mc->exceed_events);
 
        if (mc->input_events || mc->exceed_events || mc->speed_events)
-               schedule_work(&mc->do_notify);
+               schedule_delayed_work(&mc->do_notify, 0);
 
 resubmit:
-       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status)
                dev_err(&mc->intf->dev,
                        "can't resubmit intr, %s-%s/motorcontrol0, status %d",
@@ -159,9 +159,10 @@ resubmit:
                        mc->udev->devpath, status);
 }
 
-static void do_notify(void *data)
+static void do_notify(struct work_struct *work)
 {
-       struct motorcontrol *mc = data;
+       struct motorcontrol *mc =
+               container_of(work, struct motorcontrol, do_notify.work);
        int i;
        char sysfs_file[8];
 
@@ -337,7 +338,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
                goto out;
 
        mc->dev_no = -1;
-       mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
+       mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma);
        if (!mc->data)
                goto out;
 
@@ -348,7 +349,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
        mc->udev = usb_get_dev(dev);
        mc->intf = intf;
        mc->acceleration[0] = mc->acceleration[1] = 10;
-       INIT_WORK(&mc->do_notify, do_notify, mc);
+       INIT_DELAYED_WORK(&mc->do_notify, do_notify);
        usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
                        maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
                        motorcontrol_irq, mc, endpoint->bInterval);
index b99ca9c..0398908 100644 (file)
@@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                case SISUSB_GET_CONFIG:
                case SISUSB_COMMAND:
                        lock_kernel();
-                       retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+                       retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
                        unlock_kernel();
                        return retval;
 
index 194065d..fb32186 100644 (file)
@@ -213,7 +213,7 @@ static struct urb *simple_alloc_urb (
 
        if (bytes < 0)
                return NULL;
-       urb = usb_alloc_urb (0, SLAB_KERNEL);
+       urb = usb_alloc_urb (0, GFP_KERNEL);
        if (!urb)
                return urb;
        usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL);
@@ -223,7 +223,7 @@ static struct urb *simple_alloc_urb (
        urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
        if (usb_pipein (pipe))
                urb->transfer_flags |= URB_SHORT_NOT_OK;
-       urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL,
+       urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL,
                        &urb->transfer_dma);
        if (!urb->transfer_buffer) {
                usb_free_urb (urb);
@@ -315,7 +315,7 @@ static int simple_io (
                init_completion (&completion);
                if (usb_pipeout (urb->pipe))
                        simple_fill_buf (urb);
-               if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0)
+               if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0)
                        break;
 
                /* NOTE:  no timeouts; can't be broken out of by interrupt */
@@ -374,7 +374,7 @@ alloc_sglist (int nents, int max, int vary)
        unsigned                i;
        unsigned                size = max;
 
-       sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL);
+       sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
        if (!sg)
                return NULL;
 
@@ -382,7 +382,7 @@ alloc_sglist (int nents, int max, int vary)
                char            *buf;
                unsigned        j;
 
-               buf = kzalloc (size, SLAB_KERNEL);
+               buf = kzalloc (size, GFP_KERNEL);
                if (!buf) {
                        free_sglist (sg, i);
                        return NULL;
@@ -428,7 +428,7 @@ static int perform_sglist (
                                (udev->speed == USB_SPEED_HIGH)
                                        ? (INTERRUPT_RATE << 3)
                                        : INTERRUPT_RATE,
-                               sg, nents, 0, SLAB_KERNEL);
+                               sg, nents, 0, GFP_KERNEL);
                
                if (retval)
                        break;
@@ -819,7 +819,7 @@ error:
 
        /* resubmit if we need to, else mark this as done */
        if ((status == 0) && (ctx->pending < ctx->count)) {
-               if ((status = usb_submit_urb (urb, SLAB_ATOMIC)) != 0) {
+               if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
                        dbg ("can't resubmit ctrl %02x.%02x, err %d",
                                reqp->bRequestType, reqp->bRequest, status);
                        urb->dev = NULL;
@@ -855,7 +855,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
         * as with bulk/intr sglists, sglen is the queue depth; it also
         * controls which subtests run (more tests than sglen) or rerun.
         */
-       urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL);
+       urb = kcalloc(param->sglen, sizeof(struct urb *), GFP_KERNEL);
        if (!urb)
                return -ENOMEM;
        for (i = 0; i < param->sglen; i++) {
@@ -981,7 +981,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
                if (!u)
                        goto cleanup;
 
-               reqp = usb_buffer_alloc (udev, sizeof *reqp, SLAB_KERNEL,
+               reqp = usb_buffer_alloc (udev, sizeof *reqp, GFP_KERNEL,
                                &u->setup_dma);
                if (!reqp)
                        goto cleanup;
@@ -999,7 +999,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
        context.urb = urb;
        spin_lock_irq (&context.lock);
        for (i = 0; i < param->sglen; i++) {
-               context.status = usb_submit_urb (urb [i], SLAB_ATOMIC);
+               context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
                if (context.status != 0) {
                        dbg ("can't submit urb[%d], status %d",
                                        i, context.status);
@@ -1041,7 +1041,7 @@ static void unlink1_callback (struct urb *urb)
 
        // we "know" -EPIPE (stall) never happens
        if (!status)
-               status = usb_submit_urb (urb, SLAB_ATOMIC);
+               status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status) {
                urb->status = status;
                complete ((struct completion *) urb->context);
@@ -1067,7 +1067,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
         * FIXME want additional tests for when endpoint is STALLing
         * due to errors, or is just NAKing requests.
         */
-       if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) {
+       if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
                dev_dbg (&dev->intf->dev, "submit fail %d\n", retval);
                return retval;
        }
@@ -1251,7 +1251,7 @@ static int ctrl_out (struct usbtest_dev *dev,
        if (length < 1 || length > 0xffff || vary >= length)
                return -EINVAL;
 
-       buf = kmalloc(length, SLAB_KERNEL);
+       buf = kmalloc(length, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
@@ -1403,7 +1403,7 @@ static struct urb *iso_alloc_urb (
        maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
        packets = (bytes + maxp - 1) / maxp;
 
-       urb = usb_alloc_urb (packets, SLAB_KERNEL);
+       urb = usb_alloc_urb (packets, GFP_KERNEL);
        if (!urb)
                return urb;
        urb->dev = udev;
@@ -1411,7 +1411,7 @@ static struct urb *iso_alloc_urb (
 
        urb->number_of_packets = packets;
        urb->transfer_buffer_length = bytes;
-       urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL,
+       urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL,
                        &urb->transfer_dma);
        if (!urb->transfer_buffer) {
                usb_free_urb (urb);
@@ -1481,7 +1481,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
        spin_lock_irq (&context.lock);
        for (i = 0; i < param->sglen; i++) {
                ++context.pending;
-               status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
+               status = usb_submit_urb (urbs [i], GFP_ATOMIC);
                if (status < 0) {
                        ERROR (dev, "submit iso[%d], error %d\n", i, status);
                        if (i == 0) {
@@ -1900,7 +1900,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
        }
 #endif
 
-       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
        info = (struct usbtest_info *) id->driver_info;
@@ -1910,7 +1910,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
        dev->intf = intf;
 
        /* cacheline-aligned scratch for i/o */
-       if ((dev->buf = kmalloc (TBUF_SIZE, SLAB_KERNEL)) == NULL) {
+       if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) {
                kfree (dev);
                return -ENOMEM;
        }
index 7a2346c..05cf2c9 100644 (file)
@@ -50,7 +50,7 @@ struct mon_event_text {
 
 #define SLAB_NAME_SZ  30
 struct mon_reader_text {
-       kmem_cache_t *e_slab;
+       struct kmem_cache *e_slab;
        int nevents;
        struct list_head e_list;
        struct mon_reader r;    /* In C, parent class can be placed anywhere */
@@ -63,7 +63,7 @@ struct mon_reader_text {
        char slab_name[SLAB_NAME_SZ];
 };
 
-static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
+static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
 
 /*
  * mon_text_submit
@@ -147,7 +147,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
        stamp = mon_get_timestamp();
 
        if (rp->nevents >= EVENT_MAX ||
-           (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+           (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
                rp->r.m_bus->cnt_text_lost++;
                return;
        }
@@ -188,7 +188,7 @@ static void mon_text_error(void *data, struct urb *urb, int error)
        struct mon_event_text *ep;
 
        if (rp->nevents >= EVENT_MAX ||
-           (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+           (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
                rp->r.m_bus->cnt_text_lost++;
                return;
        }
@@ -450,7 +450,7 @@ const struct file_operations mon_fops_text = {
 /*
  * Slab interface: constructor.
  */
-static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sflags)
 {
        /*
         * Nothing to initialize. No, really!
index 907b820..4852012 100644 (file)
@@ -345,7 +345,7 @@ static void catc_irq_done(struct urb *urb)
                } 
        }
 resubmit:
-       status = usb_submit_urb (urb, SLAB_ATOMIC);
+       status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("can't resubmit intr, %s-%s, status %d",
                                catc->usbdev->bus->bus_name,
index 7c906a4..fa78326 100644 (file)
@@ -222,7 +222,7 @@ struct kaweth_device
        int suspend_lowmem_ctrl;
        int linkstate;
        int opened;
-       struct work_struct lowmem_work;
+       struct delayed_work lowmem_work;
 
        struct usb_device *dev;
        struct net_device *net;
@@ -530,9 +530,10 @@ resubmit:
        kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC);
 }
 
-static void kaweth_resubmit_tl(void *d)
+static void kaweth_resubmit_tl(struct work_struct *work)
 {
-       struct kaweth_device *kaweth = (struct kaweth_device *)d;
+       struct kaweth_device *kaweth =
+               container_of(work, struct kaweth_device, lowmem_work.work);
 
        if (IS_BLOCKED(kaweth->status))
                return;
@@ -1126,7 +1127,7 @@ err_fw:
 
        /* kaweth is zeroed as part of alloc_netdev */
 
-       INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth);
+       INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
 
        SET_MODULE_OWNER(netdev);
 
index a774105..4936359 100644 (file)
@@ -383,7 +383,7 @@ static void nc_ensure_sync(struct usbnet *dev)
                int                     status;
 
                /* Send a flush */
-               urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               urb = usb_alloc_urb(0, GFP_ATOMIC);
                if (!urb)
                        return;
 
index 69eb0db..d48c024 100644 (file)
@@ -856,7 +856,7 @@ static void intr_callback(struct urb *urb)
                pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
        }
 
-       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status == -ENODEV)
                netif_device_detach(pegasus->net);
        if (status && netif_msg_timer(pegasus))
@@ -1281,9 +1281,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
 static struct workqueue_struct *pegasus_workqueue = NULL;
 #define CARRIER_CHECK_DELAY (2 * HZ)
 
-static void check_carrier(void *data)
+static void check_carrier(struct work_struct *work)
 {
-       pegasus_t *pegasus = data;
+       pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work);
        set_carrier(pegasus->net);
        if (!(pegasus->flags & PEGASUS_UNPLUG)) {
                queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
@@ -1319,7 +1319,7 @@ static int pegasus_probe(struct usb_interface *intf,
 
        tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
 
-       INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
+       INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
 
        pegasus->intf = intf;
        pegasus->usb = dev;
index 0064380..98f6898 100644 (file)
@@ -95,7 +95,7 @@ typedef struct pegasus {
        int                     dev_index;
        int                     intr_interval;
        struct tasklet_struct   rx_tl;
-       struct work_struct      carrier_check;
+       struct delayed_work     carrier_check;
        struct urb              *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
        struct sk_buff          *rx_pool[RX_SKBS];
        struct sk_buff          *rx_skb;
index c2a28d8..99f26b3 100644 (file)
@@ -469,7 +469,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
        struct rndis_halt       *halt;
 
        /* try to clear any rndis state/activity (no i/o from stack!) */
-       halt = kcalloc(1, sizeof *halt, SLAB_KERNEL);
+       halt = kcalloc(1, sizeof *halt, GFP_KERNEL);
        if (halt) {
                halt->msg_type = RNDIS_MSG_HALT;
                halt->msg_len = ccpu2(sizeof *halt);
index 72171f9..c54235f 100644 (file)
@@ -587,7 +587,7 @@ static void intr_callback(struct urb *urb)
        }
 
 resubmit:
-       status = usb_submit_urb (urb, SLAB_ATOMIC);
+       status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status == -ENODEV)
                netif_device_detach(dev->netdev);
        else if (status)
index 7672e11..6e39e99 100644 (file)
@@ -179,9 +179,9 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
        period = max ((int) dev->status->desc.bInterval,
                (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
 
-       buf = kmalloc (maxp, SLAB_KERNEL);
+       buf = kmalloc (maxp, GFP_KERNEL);
        if (buf) {
-               dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL);
+               dev->interrupt = usb_alloc_urb (0, GFP_KERNEL);
                if (!dev->interrupt) {
                        kfree (buf);
                        return -ENOMEM;
@@ -782,9 +782,10 @@ static struct ethtool_ops usbnet_ethtool_ops = {
  * especially now that control transfers can be queued.
  */
 static void
-kevent (void *data)
+kevent (struct work_struct *work)
 {
-       struct usbnet           *dev = data;
+       struct usbnet           *dev =
+               container_of(work, struct usbnet, kevent);
        int                     status;
 
        /* usb_clear_halt() needs a thread context */
@@ -1146,7 +1147,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        skb_queue_head_init (&dev->done);
        dev->bh.func = usbnet_bh;
        dev->bh.data = (unsigned long) dev;
-       INIT_WORK (&dev->kevent, kevent, dev);
+       INIT_WORK (&dev->kevent, kevent);
        dev->delay.function = usbnet_bh;
        dev->delay.data = (unsigned long) dev;
        init_timer (&dev->delay);
index b1b5707..86bcf63 100644 (file)
@@ -92,6 +92,7 @@ struct aircable_private {
        struct circ_buf *rx_buf;        /* read buffer */
        int rx_flags;                   /* for throttilng */
        struct work_struct rx_work;     /* work cue for the receiving line */
+       struct usb_serial_port *port;   /* USB port with which associated */
 };
 
 /* Private methods */
@@ -251,10 +252,11 @@ static void aircable_send(struct usb_serial_port *port)
        schedule_work(&port->work);
 }
 
-static void aircable_read(void *params)
+static void aircable_read(struct work_struct *work)
 {
-       struct usb_serial_port *port = params;
-       struct aircable_private *priv = usb_get_serial_port_data(port);
+       struct aircable_private *priv =
+               container_of(work, struct aircable_private, rx_work);
+       struct usb_serial_port *port = priv->port;
        struct tty_struct *tty;
        unsigned char *data;
        int count;
@@ -349,7 +351,8 @@ static int aircable_attach (struct usb_serial *serial)
        }
 
        priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-       INIT_WORK(&priv->rx_work, aircable_read, port);
+       priv->port = port;
+       INIT_WORK(&priv->rx_work, aircable_read);
 
        usb_set_serial_port_data(serial->port[0], priv);
 
@@ -516,7 +519,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
                                        package_length - shift);
                        }
                }
-               aircable_read(port);
+               aircable_read(&priv->rx_work);
        }
 
        /* Schedule the next read _if_ we are still open */
index 863966c..5261cd2 100644 (file)
@@ -156,7 +156,7 @@ cleanup:
 }
 
 static void ark3116_set_termios(struct usb_serial_port *port,
-                               struct termios *old_termios)
+                               struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct ark3116_private *priv = usb_get_serial_port_data(port);
@@ -326,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
 
 static int ark3116_open(struct usb_serial_port *port, struct file *filp)
 {
-       struct termios tmp_termios;
+       struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
        char *buf;
        int result = 0;
index 8835bb5..38b4dae 100644 (file)
@@ -92,7 +92,7 @@ static void belkin_sa_shutdown                (struct usb_serial *serial);
 static int  belkin_sa_open             (struct usb_serial_port *port, struct file *filp);
 static void belkin_sa_close            (struct usb_serial_port *port, struct file *filp);
 static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios      (struct usb_serial_port *port, struct termios * old);
+static void belkin_sa_set_termios      (struct usb_serial_port *port, struct ktermios * old);
 static int  belkin_sa_ioctl            (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void belkin_sa_break_ctl                (struct usb_serial_port *port, int break_state );
 static int  belkin_sa_tiocmget         (struct usb_serial_port *port, struct file *file);
@@ -333,7 +333,7 @@ exit:
                     __FUNCTION__, retval);
 }
 
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct belkin_sa_private *priv = usb_get_serial_port_data(port);
index 7167728..9386e21 100644 (file)
@@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options)
        struct usb_serial_port *port;
        int retval = 0;
        struct tty_struct *tty;
-       struct termios *termios;
+       struct ktermios *termios;
 
        dbg ("%s", __FUNCTION__);
 
index f95d42c..2f9b7ac 100644 (file)
@@ -41,7 +41,7 @@ static int cp2101_open(struct usb_serial_port*, struct file*);
 static void cp2101_cleanup(struct usb_serial_port*);
 static void cp2101_close(struct usb_serial_port*, struct file*);
 static void cp2101_get_termios(struct usb_serial_port*);
-static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*);
 static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
 static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
                unsigned int, unsigned int);
@@ -506,7 +506,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
 }
 
 static void cp2101_set_termios (struct usb_serial_port *port,
-               struct termios *old_termios)
+               struct ktermios *old_termios)
 {
        unsigned int cflag, old_cflag=0;
        int baud=0, bits;
index 093f303..a1fdb85 100644 (file)
@@ -143,7 +143,7 @@ struct cypress_private {
        wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
        char prev_status, diff_status;     /* used for TIOCMIWAIT */
        /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
-       struct termios tmp_termios;        /* stores the old termios settings */
+       struct ktermios tmp_termios;       /* stores the old termios settings */
 };
 
 /* write buffer structure */
@@ -165,7 +165,7 @@ static int  cypress_write           (struct usb_serial_port *port, const unsigned char *b
 static void cypress_send               (struct usb_serial_port *port);
 static int  cypress_write_room         (struct usb_serial_port *port);
 static int  cypress_ioctl              (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios                (struct usb_serial_port *port, struct termios * old);
+static void cypress_set_termios                (struct usb_serial_port *port, struct ktermios * old);
 static int  cypress_tiocmget           (struct usb_serial_port *port, struct file *file);
 static int  cypress_tiocmset           (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
 static int  cypress_chars_in_buffer    (struct usb_serial_port *port);
@@ -949,13 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
 
        switch (cmd) {
                case TIOCGSERIAL:
-                       if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
+                       if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
                                return -EFAULT;
                        }
                        return (0);
                        break;
                case TIOCSSERIAL:
-                       if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
+                       if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
                                return -EFAULT;
                        }
                        /* here we need to call cypress_set_termios to invoke the new settings */
@@ -1019,7 +1019,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
 
 
 static void cypress_set_termios (struct usb_serial_port *port,
-               struct termios *old_termios)
+               struct ktermios *old_termios)
 {
        struct cypress_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
index 5e3ac28..9d9ea87 100644 (file)
@@ -430,13 +430,14 @@ struct digi_port {
        int dp_in_close;                        /* close in progress */
        wait_queue_head_t dp_close_wait;        /* wait queue for close */
        struct work_struct dp_wakeup_work;
+       struct usb_serial_port *dp_port;
 };
 
 
 /* Local Function Declarations */
 
 static void digi_wakeup_write( struct usb_serial_port *port );
-static void digi_wakeup_write_lock(void *);
+static void digi_wakeup_write_lock(struct work_struct *work);
 static int digi_write_oob_command( struct usb_serial_port *port,
        unsigned char *buf, int count, int interruptible );
 static int digi_write_inb_command( struct usb_serial_port *port,
@@ -448,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port,
 static void digi_rx_throttle (struct usb_serial_port *port);
 static void digi_rx_unthrottle (struct usb_serial_port *port);
 static void digi_set_termios( struct usb_serial_port *port, 
-       struct termios *old_termios );
+       struct ktermios *old_termios );
 static void digi_break_ctl( struct usb_serial_port *port, int break_state );
 static int digi_ioctl( struct usb_serial_port *port, struct file *file,
        unsigned int cmd, unsigned long arg );
@@ -598,11 +599,12 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
 *  on writes.
 */
 
-static void digi_wakeup_write_lock(void *arg)
+static void digi_wakeup_write_lock(struct work_struct *work)
 {
-       struct usb_serial_port *port = arg;
+       struct digi_port *priv =
+               container_of(work, struct digi_port, dp_wakeup_work);
+       struct usb_serial_port *port = priv->dp_port;
        unsigned long flags;
-       struct digi_port *priv = usb_get_serial_port_data(port);
 
 
        spin_lock_irqsave( &priv->dp_port_lock, flags );
@@ -974,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
 
 
 static void digi_set_termios( struct usb_serial_port *port, 
-       struct termios *old_termios )
+       struct ktermios *old_termios )
 {
 
        struct digi_port *priv = usb_get_serial_port_data(port);
@@ -1461,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp )
        int ret;
        unsigned char buf[32];
        struct digi_port *priv = usb_get_serial_port_data(port);
-       struct termios not_termios;
+       struct ktermios not_termios;
        unsigned long flags = 0;
 
 
@@ -1702,8 +1704,8 @@ dbg( "digi_startup: TOP" );
                init_waitqueue_head( &priv->dp_flush_wait );
                priv->dp_in_close = 0;
                init_waitqueue_head( &priv->dp_close_wait );
-               INIT_WORK(&priv->dp_wakeup_work,
-                               digi_wakeup_write_lock, serial->port[i]);
+               INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+               priv->dp_port = serial->port[i];
 
                /* initialize write wait queue for this port */
                init_waitqueue_head( &serial->port[i]->write_wait );
index 4ce10a8..92beeb1 100644 (file)
@@ -92,7 +92,7 @@ static int  empeg_ioctl                       (struct usb_serial_port *port,
                                        struct file * file,
                                        unsigned int cmd,
                                        unsigned long arg);
-static void empeg_set_termios          (struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_set_termios          (struct usb_serial_port *port, struct ktermios *old_termios);
 static void empeg_write_bulk_callback  (struct urb *urb);
 static void empeg_read_bulk_callback   (struct urb *urb);
 
@@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
 }
 
 
-static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
 
        dbg("%s - port %d", __FUNCTION__, port->number);
index 89ce277..41b0ad2 100644 (file)
@@ -559,7 +559,8 @@ struct ftdi_private {
        char prev_status, diff_status;        /* Used for TIOCMIWAIT */
        __u8 rx_flags;          /* receive state flags (throttling) */
        spinlock_t rx_lock;     /* spinlock for receive state */
-       struct work_struct rx_work;
+       struct delayed_work rx_work;
+       struct usb_serial_port *port;
        int rx_processed;
        unsigned long rx_bytes;
 
@@ -593,8 +594,8 @@ static int  ftdi_write_room         (struct usb_serial_port *port);
 static int  ftdi_chars_in_buffer       (struct usb_serial_port *port);
 static void ftdi_write_bulk_callback   (struct urb *urb);
 static void ftdi_read_bulk_callback    (struct urb *urb);
-static void ftdi_process_read          (void *param);
-static void ftdi_set_termios           (struct usb_serial_port *port, struct termios * old);
+static void ftdi_process_read          (struct work_struct *work);
+static void ftdi_set_termios           (struct usb_serial_port *port, struct ktermios * old);
 static int  ftdi_tiocmget               (struct usb_serial_port *port, struct file *file);
 static int  ftdi_tiocmset              (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
 static int  ftdi_ioctl                 (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
@@ -1201,7 +1202,8 @@ static int ftdi_sio_attach (struct usb_serial *serial)
                port->read_urb->transfer_buffer_length = BUFSZ;
        }
 
-       INIT_WORK(&priv->rx_work, ftdi_process_read, port);
+       INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
+       priv->port = port;
 
        /* Free port's existing write urb and transfer buffer. */
        if (port->write_urb) {
@@ -1640,17 +1642,18 @@ static void ftdi_read_bulk_callback (struct urb *urb)
        priv->rx_bytes += countread;
        spin_unlock_irqrestore(&priv->rx_lock, flags);
 
-       ftdi_process_read(port);
+       ftdi_process_read(&priv->rx_work.work);
 
 } /* ftdi_read_bulk_callback */
 
 
-static void ftdi_process_read (void *param)
+static void ftdi_process_read (struct work_struct *work)
 { /* ftdi_process_read */
-       struct usb_serial_port *port = (struct usb_serial_port*)param;
+       struct ftdi_private *priv =
+               container_of(work, struct ftdi_private, rx_work.work);
+       struct usb_serial_port *port = priv->port;
        struct urb *urb;
        struct tty_struct *tty;
-       struct ftdi_private *priv;
        char error_flag;
        unsigned char *data;
 
@@ -1877,7 +1880,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
  * WARNING: set_termios calls this with old_termios in kernel space
  */
 
-static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 { /* ftdi_termios */
        struct usb_device *dev = port->serial->dev;
        unsigned int cflag = port->tty->termios->c_cflag;
@@ -2179,7 +2182,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
        spin_unlock_irqrestore(&priv->rx_lock, flags);
 
        if (actually_throttled)
-               schedule_work(&priv->rx_work);
+               schedule_delayed_work(&priv->rx_work, 0);
 }
 
 static int __init ftdi_init (void)
index d06547a..f623d58 100644 (file)
@@ -229,7 +229,7 @@ static int  edge_write_room         (struct usb_serial_port *port);
 static int  edge_chars_in_buffer       (struct usb_serial_port *port);
 static void edge_throttle              (struct usb_serial_port *port);
 static void edge_unthrottle            (struct usb_serial_port *port);
-static void edge_set_termios           (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios           (struct usb_serial_port *port, struct ktermios *old_termios);
 static int  edge_ioctl                 (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
 static void edge_break                 (struct usb_serial_port *port, int break_state);
 static int  edge_tiocmget              (struct usb_serial_port *port, struct file *file);
@@ -257,7 +257,7 @@ static void handle_new_lsr          (struct edgeport_port *edge_port, __u8 lsrData, __u8
 static int  send_iosp_ext_cmd          (struct edgeport_port *edge_port, __u8 command, __u8 param);
 static int  calc_baud_rate_divisor     (int baud_rate, int *divisor);
 static int  send_cmd_write_baud_rate   (struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings       (struct edgeport_port *edge_port, struct termios *old_termios);
+static void change_port_settings       (struct edgeport_port *edge_port, struct ktermios *old_termios);
 static int  send_cmd_write_uart_register       (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
 static int  write_cmd_usb              (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
 static void send_more_port_data                (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
@@ -1431,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
  * SerialSetTermios
  *     this function is called by the tty driver when it wants to change the termios structure
  *****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        struct tty_struct *tty = port->tty;
@@ -2412,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
 #ifndef CMSPAR
 #define CMSPAR 0
 #endif
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
 {
        struct tty_struct *tty;
        int baud;
index ee0c921..2da2684 100644 (file)
@@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
 static void stop_read(struct edgeport_port *edge_port);
 static int restart_read(struct edgeport_port *edge_port);
 
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 static void edge_send(struct usb_serial_port *port);
 
 /* circular buffer */
@@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port)
        return status;
 }
 
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
 {
        struct ump_uart_config *config;
        struct tty_struct *tty;
@@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
        return;
 }
 
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        struct tty_struct *tty = port->tty;
index 331bf81..8fdf486 100644 (file)
@@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep);
 static int  ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
 static void ir_write_bulk_callback (struct urb *urb);
 static void ir_read_bulk_callback (struct urb *urb);
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 
 static u8 ir_baud = 0;
 static u8 ir_xbof = 0;
@@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb)
        return;
 }
 
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        unsigned char *transfer_buffer;
        unsigned int cflag;
index 7639652..9d2fdfd 100644 (file)
@@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
 
 
 static void keyspan_set_termios (struct usb_serial_port *port, 
-                                    struct termios *old_termios)
+                                    struct ktermios *old_termios)
 {
        int                             baud_rate, device_port;
        struct keyspan_port_private     *p_priv;
index 7472ed6..6413d73 100644 (file)
@@ -59,7 +59,7 @@ static int  keyspan_ioctl             (struct usb_serial_port *port,
                                         unsigned int cmd,
                                         unsigned long arg);
 static void keyspan_set_termios                (struct usb_serial_port *port,
-                                        struct termios *old);
+                                        struct ktermios *old);
 static void keyspan_break_ctl          (struct usb_serial_port *port,
                                         int break_state);
 static int  keyspan_tiocmget           (struct usb_serial_port *port,
index 9090051..126b970 100644 (file)
@@ -120,6 +120,8 @@ struct keyspan_pda_private {
        int                     tx_throttled;
        struct work_struct                      wakeup_work;
        struct work_struct                      unthrottle_work;
+       struct usb_serial       *serial;
+       struct usb_serial_port  *port;
 };
 
 
@@ -175,9 +177,11 @@ static struct usb_device_id id_table_fake_xircom [] = {
 };
 #endif
 
-static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
+static void keyspan_pda_wakeup_write(struct work_struct *work)
 {
-
+       struct keyspan_pda_private *priv =
+               container_of(work, struct keyspan_pda_private, wakeup_work);
+       struct usb_serial_port *port = priv->port;
        struct tty_struct *tty = port->tty;
 
        /* wake up port processes */
@@ -187,8 +191,11 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
        tty_wakeup(tty);
 }
 
-static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
+static void keyspan_pda_request_unthrottle(struct work_struct *work)
 {
+       struct keyspan_pda_private *priv =
+               container_of(work, struct keyspan_pda_private, unthrottle_work);
+       struct usb_serial *serial = priv->serial;
        int result;
 
        dbg(" request_unthrottle");
@@ -358,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
 
 
 static void keyspan_pda_set_termios (struct usb_serial_port *port, 
-                                    struct termios *old_termios)
+                                    struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        unsigned int cflag = port->tty->termios->c_cflag;
@@ -765,11 +772,10 @@ static int keyspan_pda_startup (struct usb_serial *serial)
                return (1); /* error */
        usb_set_serial_port_data(serial->port[0], priv);
        init_waitqueue_head(&serial->port[0]->write_wait);
-       INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write,
-                       (void *)(serial->port[0]));
-       INIT_WORK(&priv->unthrottle_work,
-                       (void *)keyspan_pda_request_unthrottle,
-                       (void *)(serial));
+       INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
+       INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
+       priv->serial = serial;
+       priv->port = serial->port[0];
        return (0);
 }
 
index 17e2056..73d755d 100644 (file)
@@ -86,7 +86,7 @@ static int  klsi_105_write_room          (struct usb_serial_port *port);
 
 static void klsi_105_read_bulk_callback  (struct urb *urb);
 static void klsi_105_set_termios         (struct usb_serial_port *port,
-                                         struct termios * old);
+                                         struct ktermios *old);
 static int  klsi_105_ioctl              (struct usb_serial_port *port,
                                          struct file * file,
                                          unsigned int cmd,
@@ -164,7 +164,7 @@ struct klsi_105_port_settings {
 #define URB_TRANSFER_BUFFER_SIZE       64
 struct klsi_105_private {
        struct klsi_105_port_settings   cfg;
-       struct termios                  termios;
+       struct ktermios                 termios;
        unsigned long                   line_state; /* modem line settings */
        /* write pool */
        struct urb *                    write_urb_pool[NUM_URBS];
@@ -688,7 +688,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
 
 
 static void klsi_105_set_termios (struct usb_serial_port *port,
-                                 struct termios *old_termios)
+                                 struct ktermios *old_termios)
 {
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
        unsigned int iflag = port->tty->termios->c_iflag;
index 2372899..e284d6c 100644 (file)
@@ -136,7 +136,7 @@ struct kobil_private {
        int cur_pos; // index of the next char to send in buf
        __u16 device_type;
        int line_state;
-       struct termios internal_termios;
+       struct ktermios internal_termios;
 };
 
 
@@ -624,11 +624,11 @@ static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
 
        switch (cmd) {
        case TCGETS:   // 0x5401
-               if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) {
+               if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) {
                        dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
                        return -EFAULT;
                }
-               if (kernel_termios_to_user_termios((struct termios __user *)arg,
+               if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
                                                   &priv->internal_termios))
                        return -EFAULT;
                return 0;
@@ -638,12 +638,12 @@ static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
                        dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
                        return -ENOTTY;
                }
-               if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) {
+               if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) {
                        dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
                        return -EFAULT;
                }
                if (user_termios_to_kernel_termios(&priv->internal_termios,
-                                                  (struct termios __user *)arg))
+                                                  (struct ktermios __user *)arg))
                        return -EFAULT;
                
                settings = kzalloc(50, GFP_KERNEL);
index a906e50..38b1d17 100644 (file)
@@ -98,7 +98,7 @@ static void mct_u232_close             (struct usb_serial_port *port,
                                          struct file *filp);
 static void mct_u232_read_int_callback   (struct urb *urb);
 static void mct_u232_set_termios         (struct usb_serial_port *port,
-                                         struct termios * old);
+                                         struct ktermios * old);
 static int  mct_u232_ioctl              (struct usb_serial_port *port,
                                          struct file * file,
                                          unsigned int cmd,
@@ -556,7 +556,7 @@ exit:
 } /* mct_u232_read_int_callback */
 
 static void mct_u232_set_termios (struct usb_serial_port *port,
-                                 struct termios *old_termios)
+                                 struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
index 82cd15b..e55f4ed 100644 (file)
@@ -363,7 +363,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
 
        /* Initialising the write urb pool */
        for (j = 0; j < NUM_URBS; ++j) {
-               urb = usb_alloc_urb(0,SLAB_ATOMIC);
+               urb = usb_alloc_urb(0,GFP_ATOMIC);
                mos7720_port->write_urb_pool[j] = urb;
 
                if (urb == NULL) {
@@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
  *      the specified new settings.
  */
 static void change_port_settings(struct moschip_port *mos7720_port,
-                                struct termios *old_termios)
+                                struct ktermios *old_termios)
 {
        struct usb_serial_port *port;
        struct usb_serial *serial;
@@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
  *     termios structure.
  */
 static void mos7720_set_termios(struct usb_serial_port *port,
-                               struct termios *old_termios)
+                               struct ktermios *old_termios)
 {
        int status;
        unsigned int cflag;
index 02c89e1..8cc728a 100644 (file)
@@ -826,7 +826,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
 
        /* Initialising the write urb pool */
        for (j = 0; j < NUM_URBS; ++j) {
-               urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               urb = usb_alloc_urb(0, GFP_ATOMIC);
                mos7840_port->write_urb_pool[j] = urb;
 
                if (urb == NULL) {
@@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
  *****************************************************************************/
 
 static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
-                                        struct termios *old_termios)
+                                        struct ktermios *old_termios)
 {
        struct tty_struct *tty;
        int baud;
@@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
  *****************************************************************************/
 
 static void mos7840_set_termios(struct usb_serial_port *port,
-                               struct termios *old_termios)
+                               struct ktermios *old_termios)
 {
        int status;
        unsigned int cflag;
@@ -2786,7 +2786,7 @@ static int mos7840_startup(struct usb_serial *serial)
                                    i + 1, status);
 
                }
-               mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               mos7840_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC);
                mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
 
        }
index 130afbb..0ae4098 100644 (file)
@@ -59,7 +59,7 @@ static int  option_chars_in_buffer(struct usb_serial_port *port);
 static int  option_ioctl(struct usb_serial_port *port, struct file *file,
                        unsigned int cmd, unsigned long arg);
 static void option_set_termios(struct usb_serial_port *port,
-                               struct termios *old);
+                               struct ktermios *old);
 static void option_break_ctl(struct usb_serial_port *port, int break_state);
 static int  option_tiocmget(struct usb_serial_port *port, struct file *file);
 static int  option_tiocmset(struct usb_serial_port *port, struct file *file,
@@ -230,7 +230,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state)
 }
 
 static void option_set_termios(struct usb_serial_port *port,
-                       struct termios *old_termios)
+                       struct ktermios *old_termios)
 {
        dbg("%s", __FUNCTION__);
 
index bc800c8..d124d78 100644 (file)
@@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
 }
 
 static void pl2303_set_termios(struct usb_serial_port *port,
-                              struct termios *old_termios)
+                              struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
 
 static int pl2303_open(struct usb_serial_port *port, struct file *filp)
 {
-       struct termios tmp_termios;
+       struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned char *buf;
index 4b5097f..6d8e91e 100644 (file)
@@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
 }
 
 static void sierra_set_termios(struct usb_serial_port *port,
-                       struct termios *old_termios)
+                       struct ktermios *old_termios)
 {
        dbg("%s", __FUNCTION__);
 
index ae98d8c..f42eb9e 100644 (file)
@@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port);
 static void ti_unthrottle(struct usb_serial_port *port);
 static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
 static void ti_set_termios(struct usb_serial_port *port,
-       struct termios *old_termios);
+       struct ktermios *old_termios);
 static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
 static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
        unsigned int set, unsigned int clear);
@@ -881,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
 
 
 static void ti_set_termios(struct usb_serial_port *port,
-       struct termios *old_termios)
+       struct ktermios *old_termios)
 {
        struct ti_port *tport = usb_get_serial_port_data(port);
        struct tty_struct *tty = port->tty;
index c1257d5..716f680 100644 (file)
@@ -397,7 +397,7 @@ exit:
        return retval;
 }
 
-static void serial_set_termios (struct tty_struct *tty, struct termios * old)
+static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
 {
        struct usb_serial_port *port = tty->driver_data;
 
@@ -533,9 +533,10 @@ void usb_serial_port_softint(struct usb_serial_port *port)
        schedule_work(&port->work);
 }
 
-static void usb_serial_port_work(void *private)
+static void usb_serial_port_work(struct work_struct *work)
 {
-       struct usb_serial_port *port = private;
+       struct usb_serial_port *port =
+               container_of(work, struct usb_serial_port, work);
        struct tty_struct *tty;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
@@ -799,7 +800,7 @@ int usb_serial_probe(struct usb_interface *interface,
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
-               INIT_WORK(&port->work, usb_serial_port_work, port);
+               INIT_WORK(&port->work, usb_serial_port_work);
                serial->port[i] = port;
        }
 
index eef5eaa..b09f060 100644 (file)
@@ -46,7 +46,7 @@ static int  visor_probe               (struct usb_serial *serial, const struct usb_device_id
 static int  visor_calc_num_ports(struct usb_serial *serial);
 static void visor_shutdown     (struct usb_serial *serial);
 static int  visor_ioctl                (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_set_termios  (struct usb_serial_port *port, struct termios *old_termios);
+static void visor_set_termios  (struct usb_serial_port *port, struct ktermios *old_termios);
 static void visor_write_bulk_callback  (struct urb *urb);
 static void visor_read_bulk_callback   (struct urb *urb);
 static void visor_read_int_callback    (struct urb *urb);
@@ -916,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign
 
 
 /* This function is all nice and good, but we don't change anything based on it :) */
-static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        unsigned int cflag;
 
index 4d1cd7a..dc45e58 100644 (file)
@@ -145,7 +145,7 @@ static void whiteheat_close         (struct usb_serial_port *port, struct file *filp);
 static int  whiteheat_write            (struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  whiteheat_write_room       (struct usb_serial_port *port);
 static int  whiteheat_ioctl            (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios      (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_set_termios      (struct usb_serial_port *port, struct ktermios * old);
 static int  whiteheat_tiocmget         (struct usb_serial_port *port, struct file *file);
 static int  whiteheat_tiocmset         (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
 static void whiteheat_break_ctl                (struct usb_serial_port *port, int break_state);
@@ -227,6 +227,7 @@ struct whiteheat_private {
        struct list_head        rx_urbs_submitted;
        struct list_head        rx_urb_q;
        struct work_struct      rx_work;
+       struct usb_serial_port  *port;
        struct list_head        tx_urbs_free;
        struct list_head        tx_urbs_submitted;
 };
@@ -241,7 +242,7 @@ static void command_port_read_callback(struct urb *urb);
 static int start_port_read(struct usb_serial_port *port);
 static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
 static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(void *private);
+static void rx_data_softint(struct work_struct *work);
 
 static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
 static int firm_open(struct usb_serial_port *port);
@@ -424,7 +425,8 @@ static int whiteheat_attach (struct usb_serial *serial)
                spin_lock_init(&info->lock);
                info->flags = 0;
                info->mcr = 0;
-               INIT_WORK(&info->rx_work, rx_data_softint, port);
+               INIT_WORK(&info->rx_work, rx_data_softint);
+               info->port = port;
 
                INIT_LIST_HEAD(&info->rx_urbs_free);
                INIT_LIST_HEAD(&info->rx_urbs_submitted);
@@ -595,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
 static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
 {
        int             retval = 0;
-       struct termios  old_term;
+       struct ktermios old_term;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -868,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
 }
 
 
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        dbg("%s -port %d", __FUNCTION__, port->number);
 
@@ -949,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
        spin_unlock_irqrestore(&info->lock, flags);
 
        if (actually_throttled)
-               rx_data_softint(port);
+               rx_data_softint(&info->rx_work);
 
        return;
 }
@@ -1400,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head)
 }
 
 
-static void rx_data_softint(void *private)
+static void rx_data_softint(struct work_struct *work)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)private;
-       struct whiteheat_private *info = usb_get_serial_port_data(port);
+       struct whiteheat_private *info =
+               container_of(work, struct whiteheat_private, rx_work);
+       struct usb_serial_port *port = info->port;
        struct tty_struct *tty = port->tty;
        struct whiteheat_urb_wrap *wrap;
        struct urb *urb;
index 3a158d5..e565d3d 100644 (file)
@@ -76,7 +76,7 @@ static void usb_onetouch_irq(struct urb *urb)
        input_sync(dev);
 
 resubmit:
-       status = usb_submit_urb (urb, SLAB_ATOMIC);
+       status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("can't resubmit intr, %s-%s/input0, status %d",
                        onetouch->udev->bus->bus_name,
@@ -154,7 +154,7 @@ int onetouch_connect_input(struct us_data *ss)
                goto fail1;
 
        onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
-                                         SLAB_ATOMIC, &onetouch->data_dma);
+                                         GFP_ATOMIC, &onetouch->data_dma);
        if (!onetouch->data)
                goto fail1;
 
index 47644b5..323293a 100644 (file)
@@ -427,7 +427,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
        US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
                        length, num_sg);
        result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
-                       sg, num_sg, length, SLAB_NOIO);
+                       sg, num_sg, length, GFP_NOIO);
        if (result) {
                US_DEBUGP("usb_sg_init returned %d\n", result);
                return USB_STOR_XFER_ERROR;
index b401084..7064450 100644 (file)
@@ -49,7 +49,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 7a43020..4e83f01 100644 (file)
@@ -541,6 +541,7 @@ config FB_TGA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select BITREVERSE
        help
          This is the frame buffer device driver for generic TGA graphic
          cards. Say Y if you have one of those.
@@ -551,6 +552,7 @@ config FB_VESA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select VIDEO_SELECT
        help
          This is the frame buffer device driver for generic VESA 2.0
          compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -705,6 +707,7 @@ config FB_NVIDIA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select BITREVERSE
        help
          This driver supports graphics boards with the nVidia chips, TNT
          and newer. For very old chipsets, such as the RIVA128, then use
@@ -744,6 +747,7 @@ config FB_RIVA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select BITREVERSE
        help
          This driver supports graphics boards with the nVidia Riva/Geforce
          chips.
@@ -1611,6 +1615,16 @@ config FB_PNX4008_DUM_RGB
        ---help---
          Say Y here to enable support for PNX4008 RGB Framebuffer
 
+config FB_IBM_GXT4500
+       tristate "Framebuffer support for IBM GXT4500P adaptor"
+       depends on PPC
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         Say Y here to enable support for the IBM GXT4500P display
+         adaptor, found on some IBM System P (pSeries) machines.
+
 config FB_VIRTUAL
        tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
        depends on FB
index a6980e9..309a26d 100644 (file)
@@ -99,6 +99,7 @@ obj-$(CONFIG_FB_IMX)              += imxfb.o
 obj-$(CONFIG_FB_S3C2410)         += s3c2410fb.o
 obj-$(CONFIG_FB_PNX4008_DUM)     += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
+obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
index 397005e..b3717c8 100644 (file)
@@ -535,8 +535,11 @@ static void __init s3triofb_of_init(struct device_node *dp)
 #endif
 
     fb_info.flags = FBINFO_FLAG_DEFAULT;
-    if (register_framebuffer(&fb_info) < 0)
-       return;
+    if (register_framebuffer(&fb_info) < 0) {
+               iounmap(fb_info.screen_base);
+               fb_info.screen_base = NULL;
+               return;
+    }
 
     printk("fb%d: S3 Trio frame buffer device on %s\n",
           fb_info.node, dp->full_name);
index a4e3fca..88a4784 100644 (file)
@@ -2407,10 +2407,10 @@ default_chipset:
                                                   fb_info.fix.smem_len);
        if (!videomemory) {
                printk("amifb: WARNING! unable to map videomem cached writethrough\n");
-               videomemory = ZTWO_VADDR(fb_info.fix.smem_start);
-       }
+               fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
+       } else
+               fb_info.screen_base = (char *)videomemory;
 
-       fb_info.screen_base = (char *)videomemory;
        memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
 
        /*
@@ -2453,6 +2453,8 @@ static void amifb_deinit(void)
 {
        fb_dealloc_cmap(&fb_info.cmap);
        chipfree();
+       if (videomemory)
+               iounmap((void*)videomemory);
        release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
        custom.dmacon = DMAF_ALL | DMAF_MASTER;
 }
index ab34b96..30a8369 100644 (file)
@@ -454,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
        unsigned int xres;
 
        p = *ppos;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        fbidx = iminor(inode);
        info = registered_fb[fbidx];
 
index 02c41a6..602db66 100644 (file)
@@ -2804,8 +2804,19 @@ int __init atafb_init(void)
        atafb_set_disp(-1, &fb_info);
        do_install_cmap(0, &fb_info);
 
-       if (register_framebuffer(&fb_info) < 0)
+       if (register_framebuffer(&fb_info) < 0) {
+#ifdef ATAFB_EXT
+               if (external_addr) {
+                       iounmap(external_addr);
+                       external_addr = NULL;
+               }
+               if (external_vgaiobase) {
+                       iounmap((void*)external_vgaiobase);
+                       external_vgaiobase = 0;
+               }
+#endif
                return -EINVAL;
+       }
 
        printk("Determined %dx%d, depth %d\n",
               disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
index 276a215..3feddf8 100644 (file)
@@ -1333,6 +1333,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
        if (vclk * 12 < c.ppll_min)
                vclk = c.ppll_min/12;
 
+       pll->post_divider = -1;
+
        /* now, find an acceptable divider */
        for (i = 0; i < sizeof(post_dividers); i++) {
                output_freq = post_dividers[i] * vclk;
@@ -1342,6 +1344,9 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
                }
        }
 
+       if (pll->post_divider < 0)
+               return -EINVAL;
+
        /* calculate feedback divider */
        n = c.ref_divider * output_freq;
        d = c.ref_clk;
index b04f49f..f72faff 100644 (file)
@@ -126,7 +126,6 @@ union aty_pll {
      */
 
 struct atyfb_par {
-       struct aty_cmap_regs __iomem *aty_cmap_regs;
        struct { u8 red, green, blue; } palette[256];
        const struct aty_dac_ops *dac_ops;
        const struct aty_pll_ops *pll_ops;
@@ -186,6 +185,7 @@ struct atyfb_par {
        int mtrr_aper;
        int mtrr_reg;
 #endif
+       u32 mem_cntl;
 };
 
     /*
@@ -227,7 +227,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
                regindex -= 0x800;
 
 #ifdef CONFIG_ATARI
-       return in_le32((volatile u32 *)(par->ati_regbase + regindex));
+       return in_le32(par->ati_regbase + regindex);
 #else
        return readl(par->ati_regbase + regindex);
 #endif
@@ -240,7 +240,7 @@ static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *pa
                regindex -= 0x800;
 
 #ifdef CONFIG_ATARI
-       out_le32((volatile u32 *)(par->ati_regbase + regindex), val);
+       out_le32(par->ati_regbase + regindex, val);
 #else
        writel(val, par->ati_regbase + regindex);
 #endif
@@ -253,7 +253,7 @@ static inline void aty_st_le16(int regindex, u16 val,
        if (regindex >= 0x400)
                regindex -= 0x800;
 #ifdef CONFIG_ATARI
-       out_le16((volatile u16 *)(par->ati_regbase + regindex), val);
+       out_le16(par->ati_regbase + regindex, val);
 #else
        writel(val, par->ati_regbase + regindex);
 #endif
@@ -315,6 +315,7 @@ struct aty_pll_ops {
        void (*set_pll)   (const struct fb_info * info, const union aty_pll * pll);
        void (*get_pll)   (const struct fb_info *info, union aty_pll * pll);
        int (*init_pll)   (const struct fb_info * info, union aty_pll * pll);
+       void (*resume_pll)(const struct fb_info *info, union aty_pll *pll);
 };
 
 extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
index e815b35..176f9b8 100644 (file)
@@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator)
      *  The Hardware parameters for each card
      */
 
-struct aty_cmap_regs {
-       u8 windex;
-       u8 lut;
-       u8 mask;
-       u8 rindex;
-       u8 cntl;
-};
-
 struct pci_mmap_map {
        unsigned long voff;
        unsigned long poff;
@@ -249,7 +241,8 @@ static int atyfb_sync(struct fb_info *info);
      *  Internal routines
      */
 
-static int aty_init(struct fb_info *info, const char *name);
+static int aty_init(struct fb_info *info);
+static void aty_resume_chip(struct fb_info *info);
 #ifdef CONFIG_ATARI
 static int store_video_par(char *videopar, unsigned char m64_num);
 #endif
@@ -1937,17 +1930,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter)
                aty_st_8(DAC_CNTL, tmp, par);
                aty_st_8(DAC_MASK, 0xff, par);
 
-               writeb(i, &par->aty_cmap_regs->rindex);
-               atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut);
-               atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut);
-               atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut);
-               writeb(i, &par->aty_cmap_regs->windex);
-               writeb(atyfb_save.r[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
-               writeb(atyfb_save.g[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
-               writeb(atyfb_save.b[1 - enter][i],
-                      &par->aty_cmap_regs->lut);
+               aty_st_8(DAC_R_INDEX, i, par);
+               atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par);
+               atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par);
+               atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par);
+               aty_st_8(DAC_W_INDEX, i, par);
+               aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par);
+               aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par);
+               aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par);
        }
 }
 
@@ -1982,6 +1972,7 @@ static void atyfb_palette(int enter)
 
 #if defined(CONFIG_PM) && defined(CONFIG_PCI)
 
+#ifdef CONFIG_PPC_PMAC
 /* Power management routines. Those are used for PowerBook sleep.
  */
 static int aty_power_mgmt(int sleep, struct atyfb_par *par)
@@ -2038,21 +2029,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
 
        return timeout ? 0 : -EIO;
 }
+#endif
 
 static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct atyfb_par *par = (struct atyfb_par *) info->par;
 
-#ifndef CONFIG_PPC_PMAC
-       /* HACK ALERT ! Once I find a proper way to say to each driver
-        * individually what will happen with it's PCI slot, I'll change
-        * that. On laptops, the AGP slot is just unclocked, so D2 is
-        * expected, while on desktops, the card is powered off
-        */
-       return 0;
-#endif /* CONFIG_PPC_PMAC */
-
        if (state.event == pdev->dev.power.power_state.event)
                return 0;
 
@@ -2070,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        par->asleep = 1;
        par->lock_blank = 1;
 
+#ifdef CONFIG_PPC_PMAC
        /* Set chip to "suspend" mode */
        if (aty_power_mgmt(1, par)) {
                par->asleep = 0;
@@ -2079,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                release_console_sem();
                return -EIO;
        }
+#else
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+#endif
 
        release_console_sem();
 
@@ -2097,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
 
        acquire_console_sem();
 
+#ifdef CONFIG_PPC_PMAC
        if (pdev->dev.power.power_state.event == 2)
                aty_power_mgmt(0, par);
+#else
+       pci_set_power_state(pdev, PCI_D0);
+#endif
+
+       aty_resume_chip(info);
+
        par->asleep = 0;
 
        /* Restore display */
@@ -2344,24 +2338,16 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
 }
 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
 
-static int __devinit aty_init(struct fb_info *info, const char *name)
+static int __devinit aty_init(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        const char *ramname = NULL, *xtal;
        int gtb_memsize, has_var = 0;
        struct fb_var_screeninfo var;
-       u8 pll_ref_div;
-       u32 i;
-#if defined(CONFIG_PPC)
-       int sense;
-#endif
 
        init_waitqueue_head(&par->vblank.wait);
        spin_lock_init(&par->int_lock);
 
-       par->aty_cmap_regs =
-           (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0);
-
 #ifdef CONFIG_PPC_PMAC
        /* The Apple iBook1 uses non-standard memory frequencies. We detect it
         * and set the frequency manually. */
@@ -2464,18 +2450,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                        par->pll_limits.mclk = 63;
        }
 
-       if (M64_HAS(GTB_DSP)
-           && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) {
-               int diff1, diff2;
-               diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
-               diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
-               if (diff1 < 0)
-                       diff1 = -diff1;
-               if (diff2 < 0)
-                       diff2 = -diff2;
-               if (diff2 < diff1) {
-                       par->ref_clk_per = 1000000000000ULL / 29498928;
-                       xtal = "29.498928";
+       if (M64_HAS(GTB_DSP)) {
+               u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+
+               if (pll_ref_div) {
+                       int diff1, diff2;
+                       diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
+                       diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
+                       if (diff1 < 0)
+                               diff1 = -diff1;
+                       if (diff2 < 0)
+                               diff2 = -diff2;
+                       if (diff2 < diff1) {
+                               par->ref_clk_per = 1000000000000ULL / 29498928;
+                               xtal = "29.498928";
+                       }
                }
        }
 #endif /* CONFIG_FB_ATY_CT */
@@ -2485,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
        if(par->pll_ops->get_pll)
                par->pll_ops->get_pll(info, &saved_pll);
 
-       i = aty_ld_le32(MEM_CNTL, par);
+       par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
        gtb_memsize = M64_HAS(GTB_DSP);
        if (gtb_memsize)
-               switch (i & 0xF) {      /* 0xF used instead of MEM_SIZE_ALIAS */
+               switch (par->mem_cntl & 0xF) {  /* 0xF used instead of MEM_SIZE_ALIAS */
                case MEM_SIZE_512K:
                        info->fix.smem_len = 0x80000;
                        break;
@@ -2510,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                default:
                        info->fix.smem_len = 0x80000;
        } else
-               switch (i & MEM_SIZE_ALIAS) {
+               switch (par->mem_cntl & MEM_SIZE_ALIAS) {
                case MEM_SIZE_512K:
                        info->fix.smem_len = 0x80000;
                        break;
@@ -2540,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
 
        if (vram) {
                info->fix.smem_len = vram * 1024;
-               i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+               par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
                if (info->fix.smem_len <= 0x80000)
-                       i |= MEM_SIZE_512K;
+                       par->mem_cntl |= MEM_SIZE_512K;
                else if (info->fix.smem_len <= 0x100000)
-                       i |= MEM_SIZE_1M;
+                       par->mem_cntl |= MEM_SIZE_1M;
                else if (info->fix.smem_len <= 0x200000)
-                       i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+                       par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
                else if (info->fix.smem_len <= 0x400000)
-                       i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+                       par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
                else if (info->fix.smem_len <= 0x600000)
-                       i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+                       par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
                else
-                       i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
-               aty_st_le32(MEM_CNTL, i, par);
+                       par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+               aty_st_le32(MEM_CNTL, par->mem_cntl, par);
        }
 
        /*
@@ -2599,11 +2588,12 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
 #endif
        if(par->pll_ops->init_pll)
                par->pll_ops->init_pll(info, &par->pll);
+       if (par->pll_ops->resume_pll)
+               par->pll_ops->resume_pll(info, &par->pll);
 
        /*
-        *  Last page of 8 MB (4 MB on ISA) aperture is MMIO
-        *  FIXME: we should use the auxiliary aperture instead so we can access
-        *  the full 8 MB of video RAM on 8 MB boards
+        *  Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+        *  unless the auxiliary register aperture is used.
         */
 
        if (!par->aux_start &&
@@ -2669,6 +2659,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
                                has_var = 1;
                } else {
                        if (default_vmode == VMODE_CHOOSE) {
+                               int sense;
                                if (M64_HAS(G3_PB_1024x768))
                                        /* G3 PowerBook with 1024x768 LCD */
                                        default_vmode = VMODE_1024_768_60;
@@ -2749,7 +2740,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
        fb_list = info;
 
        PRINTKI("fb%d: %s frame buffer device on %s\n",
-              info->node, info->fix.id, name);
+               info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
        return 0;
 
 aty_init_exit:
@@ -2770,6 +2761,19 @@ aty_init_exit:
        return -1;
 }
 
+static void aty_resume_chip(struct fb_info *info)
+{
+       struct atyfb_par *par = info->par;
+
+       aty_st_le32(MEM_CNTL, par->mem_cntl, par);
+
+       if (par->pll_ops->resume_pll)
+               par->pll_ops->resume_pll(info, &par->pll);
+
+       if (par->aux_start)
+               aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
+}
+
 #ifdef CONFIG_ATARI
 static int __devinit store_video_par(char *video_str, unsigned char m64_num)
 {
@@ -2826,9 +2830,9 @@ static int atyfb_blank(int blank, struct fb_info *info)
 #endif
 
        gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+       gen_cntl &= ~0x400004c;
        switch (blank) {
-               case FB_BLANK_UNBLANK:
-                       gen_cntl &= ~0x400004c;
+               case FB_BLANK_UNBLANK:
                        break;
                case FB_BLANK_NORMAL:
                        gen_cntl |= 0x4000040;
@@ -2863,17 +2867,10 @@ static int atyfb_blank(int blank, struct fb_info *info)
 static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
                       const struct atyfb_par *par)
 {
-#ifdef CONFIG_ATARI
-       out_8(&par->aty_cmap_regs->windex, regno);
-       out_8(&par->aty_cmap_regs->lut, red);
-       out_8(&par->aty_cmap_regs->lut, green);
-       out_8(&par->aty_cmap_regs->lut, blue);
-#else
-       writeb(regno, &par->aty_cmap_regs->windex);
-       writeb(red, &par->aty_cmap_regs->lut);
-       writeb(green, &par->aty_cmap_regs->lut);
-       writeb(blue, &par->aty_cmap_regs->lut);
-#endif
+       aty_st_8(DAC_W_INDEX, regno, par);
+       aty_st_8(DAC_DATA, red, par);
+       aty_st_8(DAC_DATA, green, par);
+       aty_st_8(DAC_DATA, blue, par);
 }
 
     /*
@@ -3182,7 +3179,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 
 #ifdef __i386__
 #ifdef CONFIG_FB_ATY_GENERIC_LCD
-static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
 {
        u32 driv_inf_tab, sig;
        u16 lcd_ofs;
@@ -3527,6 +3524,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i
 atyfb_setup_generic_fail:
        iounmap(par->ati_regbase);
        par->ati_regbase = NULL;
+       if (info->screen_base) {
+               iounmap(info->screen_base);
+               info->screen_base = NULL;
+       }
        return ret;
 }
 
@@ -3594,7 +3595,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        pci_set_drvdata(pdev, info);
 
        /* Init chip & register framebuffer */
-       if (aty_init(info, "PCI"))
+       if (aty_init(info))
                goto err_release_io;
 
 #ifdef __sparc__
@@ -3641,12 +3642,13 @@ err_release_mem:
 
 #ifdef CONFIG_ATARI
 
-static int __devinit atyfb_atari_probe(void)
+static int __init atyfb_atari_probe(void)
 {
        struct atyfb_par *par;
        struct fb_info *info;
        int m64_num;
        u32 clock_r;
+       int num_found = 0;
 
        for (m64_num = 0; m64_num < mach64_count; m64_num++) {
                if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
@@ -3694,16 +3696,34 @@ static int __devinit atyfb_atari_probe(void)
                        break;
                }
 
-               if (aty_init(info, "ISA bus")) {
+               /* Fake pci_id for correct_chipset() */
+               switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+               case 0x00d7:
+                       par->pci_id = PCI_CHIP_MACH64GX;
+                       break;
+               case 0x0057:
+                       par->pci_id = PCI_CHIP_MACH64CX;
+                       break;
+               default:
+                       break;
+               }
+
+               if (correct_chipset(par) || aty_init(info)) {
+                       iounmap(info->screen_base);
+                       iounmap(par->ati_regbase);
                        framebuffer_release(info);
-                       /* This is insufficient! kernel_map has added two large chunks!! */
-                       return -ENXIO;
+               } else {
+                       num_found++;
                }
        }
+
+       return num_found ? 0 : -ENXIO;
 }
 
 #endif /* CONFIG_ATARI */
 
+#ifdef CONFIG_PCI
+
 static void __devexit atyfb_remove(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -3751,7 +3771,6 @@ static void __devexit atyfb_remove(struct fb_info *info)
        framebuffer_release(info);
 }
 
-#ifdef CONFIG_PCI
 
 static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
 {
@@ -3786,7 +3805,7 @@ static struct pci_driver atyfb_driver = {
 #endif /* CONFIG_PCI */
 
 #ifndef MODULE
-static int __devinit atyfb_setup(char *options)
+static int __init atyfb_setup(char *options)
 {
        char *this_opt;
 
@@ -3858,7 +3877,7 @@ static int __devinit atyfb_setup(char *options)
 }
 #endif  /*  MODULE  */
 
-static int __devinit atyfb_init(void)
+static int __init atyfb_init(void)
 {
     int err1 = 1, err2 = 1;
 #ifndef MODULE
index 5080816..f3b487b 100644 (file)
@@ -370,8 +370,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
 #endif
 }
 
-static void __init aty_get_pll_ct(const struct fb_info *info,
-                                 union aty_pll *pll)
+static void __devinit aty_get_pll_ct(const struct fb_info *info,
+                                    union aty_pll *pll)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        u8 tmp, clock;
@@ -394,12 +394,12 @@ static void __init aty_get_pll_ct(const struct fb_info *info,
        }
 }
 
-static int __init aty_init_pll_ct(const struct fb_info *info,
-                                union aty_pll *pll)
+static int __devinit aty_init_pll_ct(const struct fb_info *info,
+                                    union aty_pll *pll)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
-       u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;
-       u32 q, i, memcntl, trp;
+       u8 mpost_div, xpost_div, sclk_post_div_real;
+       u32 q, memcntl, trp;
        u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
 #ifdef DEBUG
        int pllmclk, pllsclk;
@@ -575,14 +575,30 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
                        mpost_div += (q <  32*8);
                }
                sclk_post_div_real = postdividers[mpost_div];
-               sclk_fb_div = q * sclk_post_div_real / 8;
-               spll_cntl2 = mpost_div << 4;
+               pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
+               pll->ct.spll_cntl2 = mpost_div << 4;
 #ifdef DEBUG
-               pllsclk = (1000000 * 2 * sclk_fb_div) /
+               pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
                        (par->ref_clk_per * pll->ct.pll_ref_div);
                printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
                        __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
 #endif
+       }
+
+       /* Disable the extra precision pixel clock controls since we do not use them. */
+       pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par);
+       pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC);
+
+       return 0;
+}
+
+static void aty_resume_pll_ct(const struct fb_info *info,
+                             union aty_pll *pll)
+{
+       struct atyfb_par *par = info->par;
+
+       if (par->mclk_per != par->xclk_per) {
+               int i;
                /*
                * This disables the sclk, crashes the computer as reported:
                * aty_st_pll_ct(SPLL_CNTL2, 3, info);
@@ -590,8 +606,8 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
                * So it seems the sclk must be enabled before it is used;
                * so PLL_GEN_CNTL must be programmed *after* the sclk.
                */
-               aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par);
-               aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par);
+               aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
+               aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
                /*
                 * The sclk has been started. However, I believe the first clock
                 * ticks it generates are not very stable. Hope this primitive loop
@@ -605,11 +621,7 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
        aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
        aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
        aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
-       /* Disable the extra precision pixel clock controls since we do not use them. */
-       aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &
-               ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);
-
-       return 0;
+       aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par);
 }
 
 static int dummy(void)
@@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = {
        .pll_to_var     = aty_pll_to_var_ct,
        .set_pll        = aty_set_pll_ct,
        .get_pll        = aty_get_pll_ct,
-       .init_pll       = aty_init_pll_ct
+       .init_pll       = aty_init_pll_ct,
+       .resume_pll     = aty_resume_pll_ct,
 };
index ea531a6..38c7dbf 100644 (file)
@@ -104,10 +104,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
        if (pedid == NULL)
                return mt;
 
-       tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL);
+       tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
        if (!tmp)
                return mt;
-       memcpy(tmp, pedid, EDID_LENGTH);
        *out_EDID = tmp;
        return mt;
 }
index 2855534..164fe2f 100644 (file)
@@ -274,7 +274,7 @@ static struct au1100fb_panel known_lcd_panels[] =
                .bpp = 16,
                .control_base = 0x0004886A |
                        LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
-                       LCD_CONTROL_BPP_16,
+                       LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4,
                .clkcontrol_base = 0x00020000,
                .horztiming = 0x005aff1f,
                .verttiming = 0x16000e57,
index 27597c5..db8c191 100644 (file)
 #include <linux/err.h>
 #include <linux/fb.h>
 
+
+#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
+                          defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
+/* This callback gets called when something important happens inside a
+ * framebuffer driver. We're looking if that important event is blanking,
+ * and if it is, we're switching backlight power as well ...
+ */
+static int fb_notifier_callback(struct notifier_block *self,
+                               unsigned long event, void *data)
+{
+       struct backlight_device *bd;
+       struct fb_event *evdata = data;
+
+       /* If we aren't interested in this event, skip it immediately ... */
+       if (event != FB_EVENT_BLANK)
+               return 0;
+
+       bd = container_of(self, struct backlight_device, fb_notif);
+       down(&bd->sem);
+       if (bd->props)
+               if (!bd->props->check_fb ||
+                   bd->props->check_fb(evdata->info)) {
+                       bd->props->fb_blank = *(int *)evdata->data;
+                       if (likely(bd->props && bd->props->update_status))
+                               bd->props->update_status(bd);
+               }
+       up(&bd->sem);
+       return 0;
+}
+
+static int backlight_register_fb(struct backlight_device *bd)
+{
+       memset(&bd->fb_notif, 0, sizeof(bd->fb_notif));
+       bd->fb_notif.notifier_call = fb_notifier_callback;
+
+       return fb_register_client(&bd->fb_notif);
+}
+
+static void backlight_unregister_fb(struct backlight_device *bd)
+{
+       fb_unregister_client(&bd->fb_notif);
+}
+#else
+static inline int backlight_register_fb(struct backlight_device *bd)
+{
+       return 0;
+}
+
+static inline void backlight_unregister_fb(struct backlight_device *bd)
+{
+}
+#endif /* CONFIG_FB */
+
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
        int rc = -ENXIO;
@@ -142,7 +195,7 @@ static struct class backlight_class = {
        .store  = _store,                                       \
 }
 
-static struct class_device_attribute bl_class_device_attributes[] = {
+static const struct class_device_attribute bl_class_device_attributes[] = {
        DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power),
        DECLARE_ATTR(brightness, 0644, backlight_show_brightness,
                     backlight_store_brightness),
@@ -151,33 +204,6 @@ static struct class_device_attribute bl_class_device_attributes[] = {
        DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
 };
 
-/* This callback gets called when something important happens inside a
- * framebuffer driver. We're looking if that important event is blanking,
- * and if it is, we're switching backlight power as well ...
- */
-static int fb_notifier_callback(struct notifier_block *self,
-                               unsigned long event, void *data)
-{
-       struct backlight_device *bd;
-       struct fb_event *evdata =(struct fb_event *)data;
-
-       /* If we aren't interested in this event, skip it immediately ... */
-       if (event != FB_EVENT_BLANK)
-               return 0;
-
-       bd = container_of(self, struct backlight_device, fb_notif);
-       down(&bd->sem);
-       if (bd->props)
-               if (!bd->props->check_fb ||
-                   bd->props->check_fb(evdata->info)) {
-                       bd->props->fb_blank = *(int *)evdata->data;
-                       if (likely(bd->props && bd->props->update_status))
-                               bd->props->update_status(bd);
-               }
-       up(&bd->sem);
-       return 0;
-}
-
 /**
  * backlight_device_register - create and register a new object of
  *   backlight_device class.
@@ -215,10 +241,7 @@ error:             kfree(new_bd);
                return ERR_PTR(rc);
        }
 
-       memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif));
-       new_bd->fb_notif.notifier_call = fb_notifier_callback;
-
-       rc = fb_register_client(&new_bd->fb_notif);
+       rc = backlight_register_fb(new_bd);
        if (unlikely(rc))
                goto error;
 
@@ -259,16 +282,10 @@ void backlight_device_unregister(struct backlight_device *bd)
                                         &bl_class_device_attributes[i]);
 
        down(&bd->sem);
-       if (likely(bd->props && bd->props->update_status)) {
-               bd->props->brightness = 0;
-               bd->props->power = 0;
-               bd->props->update_status(bd);
-       }
-
        bd->props = NULL;
        up(&bd->sem);
 
-       fb_unregister_client(&bd->fb_notif);
+       backlight_unregister_fb(bd);
 
        class_device_unregister(&bd->class_dev);
 }
index d07ecb5..61587ca 100644 (file)
@@ -135,6 +135,10 @@ static int corgibl_probe(struct platform_device *pdev)
 
 static int corgibl_remove(struct platform_device *dev)
 {
+       corgibl_data.power = 0;
+       corgibl_data.brightness = 0;
+       corgibl_send_intensity(corgi_backlight_device);
+
        backlight_device_unregister(corgi_backlight_device);
 
        printk("Corgi Backlight Driver Unloaded\n");
index e399321..1c569fb 100644 (file)
@@ -117,6 +117,10 @@ static int __init hp680bl_probe(struct platform_device *dev)
 
 static int hp680bl_remove(struct platform_device *dev)
 {
+       hp680bl_data.brightness = 0;
+       hp680bl_data.power = 0;
+       hp680bl_send_intensity(hp680_backlight_device);
+
        backlight_device_unregister(hp680_backlight_device);
 
        return 0;
index bc8ab00..f6e0416 100644 (file)
 #include <linux/err.h>
 #include <linux/fb.h>
 
+#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
+                          defined(CONFIG_LCD_CLASS_DEVICE_MODULE))
+/* This callback gets called when something important happens inside a
+ * framebuffer driver. We're looking if that important event is blanking,
+ * and if it is, we're switching lcd power as well ...
+ */
+static int fb_notifier_callback(struct notifier_block *self,
+                                unsigned long event, void *data)
+{
+       struct lcd_device *ld;
+       struct fb_event *evdata = data;
+
+       /* If we aren't interested in this event, skip it immediately ... */
+       if (event != FB_EVENT_BLANK)
+               return 0;
+
+       ld = container_of(self, struct lcd_device, fb_notif);
+       down(&ld->sem);
+       if (ld->props)
+               if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
+                       ld->props->set_power(ld, *(int *)evdata->data);
+       up(&ld->sem);
+       return 0;
+}
+
+static int lcd_register_fb(struct lcd_device *ld)
+{
+       memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif));
+       ld->fb_notif.notifier_call = fb_notifier_callback;
+       return fb_register_client(&ld->fb_notif);
+}
+
+static void lcd_unregister_fb(struct lcd_device *ld)
+{
+       fb_unregister_client(&ld->fb_notif);
+}
+#else
+static int lcd_register_fb(struct lcd_device *ld)
+{
+       return 0;
+}
+
+static inline void lcd_unregister_fb(struct lcd_device *ld)
+{
+}
+#endif /* CONFIG_FB */
+
 static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
 {
        int rc;
@@ -121,35 +168,12 @@ static struct class lcd_class = {
        .store  = _store,                                       \
 }
 
-static struct class_device_attribute lcd_class_device_attributes[] = {
+static const struct class_device_attribute lcd_class_device_attributes[] = {
        DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power),
        DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
        DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
 };
 
-/* This callback gets called when something important happens inside a
- * framebuffer driver. We're looking if that important event is blanking,
- * and if it is, we're switching lcd power as well ...
- */
-static int fb_notifier_callback(struct notifier_block *self,
-                                unsigned long event, void *data)
-{
-       struct lcd_device *ld;
-       struct fb_event *evdata =(struct fb_event *)data;
-
-       /* If we aren't interested in this event, skip it immediately ... */
-       if (event != FB_EVENT_BLANK)
-               return 0;
-
-       ld = container_of(self, struct lcd_device, fb_notif);
-       down(&ld->sem);
-       if (ld->props)
-               if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
-                       ld->props->set_power(ld, *(int *)evdata->data);
-       up(&ld->sem);
-       return 0;
-}
-
 /**
  * lcd_device_register - register a new object of lcd_device class.
  * @name: the name of the new object(must be the same as the name of the
@@ -186,10 +210,8 @@ error:             kfree(new_ld);
                return ERR_PTR(rc);
        }
 
-       memset(&new_ld->fb_notif, 0, sizeof(new_ld->fb_notif));
-       new_ld->fb_notif.notifier_call = fb_notifier_callback;
+       rc = lcd_register_fb(new_ld);
 
-       rc = fb_register_client(&new_ld->fb_notif);
        if (unlikely(rc))
                goto error;
 
@@ -232,9 +254,7 @@ void lcd_device_unregister(struct lcd_device *ld)
        down(&ld->sem);
        ld->props = NULL;
        up(&ld->sem);
-
-       fb_unregister_client(&ld->fb_notif);
-
+       lcd_unregister_fb(ld);
        class_device_unregister(&ld->class_dev);
 }
 EXPORT_SYMBOL(lcd_device_unregister);
index 628571c..2d79054 100644 (file)
@@ -200,6 +200,10 @@ static int locomolcd_remove(struct locomo_dev *dev)
 {
        unsigned long flags;
 
+       locomobl_data.brightness = 0;
+       locomobl_data.power = 0;
+       locomolcd_set_intensity(locomolcd_bl_device);
+
        backlight_device_unregister(locomolcd_bl_device);
        local_irq_save(flags);
        locomolcd_dev = NULL;
index 51d3538..2610044 100644 (file)
@@ -42,7 +42,7 @@
 #define DPRINTK(fmt, args...)
 #endif
 
-static u32 cfb_tab8[] = {
+static const u32 cfb_tab8[] = {
 #if defined(__BIG_ENDIAN)
     0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
     0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
@@ -58,7 +58,7 @@ static u32 cfb_tab8[] = {
 #endif
 };
 
-static u32 cfb_tab16[] = {
+static const u32 cfb_tab16[] = {
 #if defined(__BIG_ENDIAN)
     0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
 #elif defined(__LITTLE_ENDIAN)
@@ -68,7 +68,7 @@ static u32 cfb_tab16[] = {
 #endif
 };
 
-static u32 cfb_tab32[] = {
+static const u32 cfb_tab32[] = {
        0x00000000, 0xffffffff
 };
 
@@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
        u32 bit_mask, end_mask, eorx, shift;
        const char *s = image->data, *src;
        u32 __iomem *dst;
-       u32 *tab = NULL;
+       const u32 *tab = NULL;
        int i, j, k;
                
        switch (bpp) {
index daf43f5..2c4bc62 100644 (file)
@@ -2442,7 +2442,10 @@ static int cirrusfb_pci_register (struct pci_dev *pdev,
        printk ("Cirrus Logic chipset on PCI bus\n");
        pci_set_drvdata(pdev, info);
 
-       return cirrusfb_register(cinfo);
+       ret = cirrusfb_register(cinfo);
+       if (ret)
+               iounmap(cinfo->fbmem);
+       return ret;
 
 err_release_legacy:
        if (release_io_ports)
@@ -2574,7 +2577,15 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
        zorro_set_drvdata(z, info);
 
-       return cirrusfb_register(cinfo);
+       ret = cirrusfb_register(cinfo);
+       if (ret) {
+               if (btype == BT_PICASSO4) {
+                       iounmap(cinfo->fbmem);
+                       iounmap(cinfo->regbase - 0x600000);
+               } else if (board_addr > 0x01000000)
+                       iounmap(cinfo->fbmem);
+       }
+       return ret;
 
 err_unmap_regbase:
        /* Parental advisory: explicit hack */
index 302174b..31f476a 100644 (file)
@@ -383,9 +383,9 @@ static void fbcon_update_softback(struct vc_data *vc)
                softback_top = 0;
 }
 
-static void fb_flashcursor(void *private)
+static void fb_flashcursor(struct work_struct *work)
 {
-       struct fb_info *info = private;
+       struct fb_info *info = container_of(work, struct fb_info, queue);
        struct fbcon_ops *ops = info->fbcon_par;
        struct display *p;
        struct vc_data *vc = NULL;
@@ -442,7 +442,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info)
        if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
            !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
                if (!info->queue.func)
-                       INIT_WORK(&info->queue, fb_flashcursor, info);
+                       INIT_WORK(&info->queue, fb_flashcursor);
 
                init_timer(&ops->cursor_timer);
                ops->cursor_timer.function = cursor_timer_handler;
index 7d07d83..f577bd8 100644 (file)
@@ -1,11 +1,13 @@
 /*
- * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices
+ * linux/drivers/video/softcursor.c
+ *
+ * Generic software cursor for frame buffer devices
  *
  *  Created 14 Nov 2002 by James Simmons
  *
- * 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 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>
@@ -25,7 +27,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
        unsigned int buf_align = info->pixmap.buf_align - 1;
        unsigned int i, size, dsize, s_pitch, d_pitch;
        struct fb_image *image;
-       u8 *dst;
+       u8 *src, *dst;
 
        if (info->state != FBINFO_STATE_RUNNING)
                return 0;
@@ -45,7 +47,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
                }
        }
 
-       image = (struct fb_image *) (ops->cursor_src + dsize);
+       src = ops->cursor_src + sizeof(struct fb_image);
+       image = (struct fb_image *)ops->cursor_src;
        *image = cursor->image;
        d_pitch = (s_pitch + scan_align) & ~scan_align;
 
@@ -57,21 +60,18 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
                switch (cursor->rop) {
                case ROP_XOR:
                        for (i = 0; i < dsize; i++)
-                               ops->cursor_src[i] = image->data[i] ^
-                                       cursor->mask[i];
+                               src[i] = image->data[i] ^ cursor->mask[i];
                        break;
                case ROP_COPY:
                default:
                        for (i = 0; i < dsize; i++)
-                               ops->cursor_src[i] = image->data[i] &
-                                       cursor->mask[i];
+                               src[i] = image->data[i] & cursor->mask[i];
                        break;
                }
        } else
-               memcpy(ops->cursor_src, image->data, dsize);
+               memcpy(src, image->data, dsize);
 
-       fb_pad_aligned_buffer(dst, d_pitch, ops->cursor_src, s_pitch,
-                             image->height);
+       fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
        image->data = dst;
        info->fbops->fb_imageblit(info, image);
        return 0;
index 45586aa..57b21e5 100644 (file)
@@ -345,7 +345,7 @@ static void sticon_save_screen(struct vc_data *conp)
 {
 }
 
-static struct consw sti_con = {
+static const struct consw sti_con = {
        .owner                  = THIS_MODULE,
        .con_startup            = sticon_startup,
        .con_init               = sticon_init,
index 0a2c10a..4a9bde2 100644 (file)
@@ -93,27 +93,27 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
 static unsigned long vgacon_uni_pagedir[2];
 
 /* Description of the hardware situation */
-static unsigned long   vga_vram_base;          /* Base of video memory */
-static unsigned long   vga_vram_end;           /* End of video memory */
-static int             vga_vram_size;          /* Size of video memory */
-static u16             vga_video_port_reg;     /* Video register select port */
-static u16             vga_video_port_val;     /* Video register value port */
-static unsigned int    vga_video_num_columns;  /* Number of text columns */
-static unsigned int    vga_video_num_lines;    /* Number of text lines */
-static int             vga_can_do_color = 0;   /* Do we support colors? */
-static unsigned int    vga_default_font_height;/* Height of default screen font */
-static unsigned char   vga_video_type;         /* Card type */
-static unsigned char   vga_hardscroll_enabled;
-static unsigned char   vga_hardscroll_user_enable = 1;
+static int             vga_init_done           __read_mostly;
+static unsigned long   vga_vram_base           __read_mostly;  /* Base of video memory */
+static unsigned long   vga_vram_end            __read_mostly;  /* End of video memory */
+static unsigned int    vga_vram_size           __read_mostly;  /* Size of video memory */
+static u16             vga_video_port_reg      __read_mostly;  /* Video register select port */
+static u16             vga_video_port_val      __read_mostly;  /* Video register value port */
+static unsigned int    vga_video_num_columns;                  /* Number of text columns */
+static unsigned int    vga_video_num_lines;                    /* Number of text lines */
+static int             vga_can_do_color        __read_mostly;  /* Do we support colors? */
+static unsigned int    vga_default_font_height __read_mostly;  /* Height of default screen font */
+static unsigned char   vga_video_type          __read_mostly;  /* Card type */
+static unsigned char   vga_hardscroll_enabled  __read_mostly;
+static unsigned char   vga_hardscroll_user_enable __read_mostly = 1;
 static unsigned char   vga_font_is_default = 1;
 static int             vga_vesa_blanked;
 static int             vga_palette_blanked;
 static int             vga_is_gfx;
 static int             vga_512_chars;
 static int             vga_video_font_height;
-static int             vga_scan_lines;
-static unsigned int    vga_rolled_over = 0;
-static int              vga_init_done;
+static int             vga_scan_lines          __read_mostly;
+static unsigned int    vga_rolled_over;
 
 static int __init no_scroll(char *str)
 {
index c40e72d..0b8d5b1 100644 (file)
@@ -109,8 +109,6 @@ static void cv64_dump(void);
 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
 
-#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
-
 struct cyberfb_par {
        struct fb_var_screeninfo var;
        __u32 type;
@@ -1055,6 +1053,8 @@ int __init cyberfb_init(void)
 
            if (register_framebuffer(&fb_info) < 0) {
                    DPRINTK("EXIT - register_framebuffer failed\n");
+                       if (CyberBase)
+                               iounmap(CyberBase);
                    release_mem_region(CyberMem_phys, 0x400000);
                    release_mem_region(CyberRegs_phys, 0x10000);
                    return -EINVAL;
index 737257d..29e07c1 100644 (file)
@@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from,
 static ssize_t
 epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
        unsigned long p = *ppos;
@@ -437,7 +437,7 @@ static ssize_t
 epson1355fb_write(struct file *file, const char *buf,
                  size_t count, loff_t * ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
        unsigned long p = *ppos;
index e8b135f..148108a 100644 (file)
 
 #include <asm/uaccess.h>
 
-static u16 red2[] = {
+static u16 red2[] __read_mostly = {
     0x0000, 0xaaaa
 };
-static u16 green2[] = {
+static u16 green2[] __read_mostly = {
     0x0000, 0xaaaa
 };
-static u16 blue2[] = {
+static u16 blue2[] __read_mostly = {
     0x0000, 0xaaaa
 };
 
-static u16 red4[] = {
+static u16 red4[] __read_mostly = {
     0x0000, 0xaaaa, 0x5555, 0xffff
 };
-static u16 green4[] = {
+static u16 green4[] __read_mostly = {
     0x0000, 0xaaaa, 0x5555, 0xffff
 };
-static u16 blue4[] = {
+static u16 blue4[] __read_mostly = {
     0x0000, 0xaaaa, 0x5555, 0xffff
 };
 
-static u16 red8[] = {
+static u16 red8[] __read_mostly = {
     0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
 };
-static u16 green8[] = {
+static u16 green8[] __read_mostly = {
     0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
 };
-static u16 blue8[] = {
+static u16 blue8[] __read_mostly = {
     0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
 };
 
-static u16 red16[] = {
+static u16 red16[] __read_mostly = {
     0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
     0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
 };
-static u16 green16[] = {
+static u16 green16[] __read_mostly = {
     0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
     0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
 };
-static u16 blue16[] = {
+static u16 blue16[] __read_mostly = {
     0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
     0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
 };
 
-static struct fb_cmap default_2_colors = {
-    0, 2, red2, green2, blue2, NULL
+static const struct fb_cmap default_2_colors = {
+    .len=2, .red=red2, .green=green2, .blue=blue2
 };
-static struct fb_cmap default_8_colors = {
-    0, 8, red8, green8, blue8, NULL
+static const struct fb_cmap default_8_colors = {
+    .len=8, .red=red8, .green=green8, .blue=blue8
 };
-static struct fb_cmap default_4_colors = {
-    0, 4, red4, green4, blue4, NULL
+static const struct fb_cmap default_4_colors = {
+    .len=4, .red=red4, .green=green4, .blue=blue4
 };
-static struct fb_cmap default_16_colors = {
-    0, 16, red16, green16, blue16, NULL
+static const struct fb_cmap default_16_colors = {
+    .len=16, .red=red16, .green=green16, .blue=blue16
 };
 
 
+
 /**
  *     fb_alloc_cmap - allocate a colormap
  *     @cmap: frame buffer colormap structure
@@ -146,7 +147,7 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)
  *     Copy contents of colormap from @from to @to.
  */
 
-int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
+int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
 {
        int tooff = 0, fromoff = 0;
        int size;
@@ -170,7 +171,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
        return 0;
 }
 
-int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to)
+int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
 {
        int tooff = 0, fromoff = 0;
        int size;
@@ -282,7 +283,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
  *
  */
 
-struct fb_cmap *fb_default_cmap(int len)
+const struct fb_cmap *fb_default_cmap(int len)
 {
     if (len <= 2)
        return &default_2_colors;
@@ -305,22 +306,22 @@ void fb_invert_cmaps(void)
 {
     u_int i;
 
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < ARRAY_SIZE(red2); i++) {
        red2[i] = ~red2[i];
        green2[i] = ~green2[i];
        blue2[i] = ~blue2[i];
     }
-    for (i = 0; i < 4; i++) {
+    for (i = 0; i < ARRAY_SIZE(red4); i++) {
        red4[i] = ~red4[i];
        green4[i] = ~green4[i];
        blue4[i] = ~blue4[i];
     }
-    for (i = 0; i < 8; i++) {
+    for (i = 0; i < ARRAY_SIZE(red8); i++) {
        red8[i] = ~red8[i];
        green8[i] = ~green8[i];
        blue8[i] = ~blue8[i];
     }
-    for (i = 0; i < 16; i++) {
+    for (i = 0; i < ARRAY_SIZE(red16); i++) {
        red16[i] = ~red16[i];
        green16[i] = ~green16[i];
        blue16[i] = ~blue16[i];
index b549899..0847c5e 100644 (file)
@@ -57,7 +57,7 @@ struct fb_cvt_data {
        u32 status;
 };
 
-static int fb_cvt_vbi_tab[] = {
+static const unsigned char fb_cvt_vbi_tab[] = {
        4,        /* 4:3      */
        5,        /* 16:9     */
        6,        /* 16:10    */
index e973a87..3cfea31 100644 (file)
@@ -52,8 +52,8 @@
 
 #define FBPIXMAPSIZE   (1024 * 8)
 
-struct fb_info *registered_fb[FB_MAX];
-int num_registered_fb;
+struct fb_info *registered_fb[FB_MAX] __read_mostly;
+int num_registered_fb __read_mostly;
 
 /*
  * Helpers
@@ -202,7 +202,7 @@ static void  fb_set_logo_truepalette(struct fb_info *info,
                                            const struct linux_logo *logo,
                                            u32 *palette)
 {
-       unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
+       static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
        unsigned char redmask, greenmask, bluemask;
        int redshift, greenshift, blueshift;
        int i;
@@ -317,7 +317,7 @@ static struct logo_data {
        int needs_truepalette;
        int needs_cmapreset;
        const struct linux_logo *logo;
-} fb_logo;
+} fb_logo __read_mostly;
 
 static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
 {
@@ -572,7 +572,7 @@ static ssize_t
 fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
        u32 *buffer, *dst;
@@ -647,7 +647,7 @@ static ssize_t
 fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
        u32 *buffer, *src;
@@ -1081,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
 static long
 fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
        struct fb_info *info = registered_fb[fbidx];
        struct fb_ops *fb = info->fbops;
@@ -1121,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static int 
 fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
-       int fbidx = iminor(file->f_dentry->d_inode);
+       int fbidx = iminor(file->f_path.dentry->d_inode);
        struct fb_info *info = registered_fb[fbidx];
        struct fb_ops *fb = info->fbops;
        unsigned long off;
@@ -1253,7 +1253,7 @@ fb_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations fb_fops = {
+static const struct file_operations fb_fops = {
        .owner =        THIS_MODULE,
        .read =         fb_read,
        .write =        fb_write,
@@ -1459,8 +1459,8 @@ int fb_new_modelist(struct fb_info *info)
        return err;
 }
 
-static char *video_options[FB_MAX];
-static int ofonly;
+static char *video_options[FB_MAX] __read_mostly;
+static int ofonly __read_mostly;
 
 extern const char *global_mode_option;
 
index de93139..6b385c3 100644 (file)
@@ -58,7 +58,7 @@ struct broken_edid {
        u32 fix;
 };
 
-static struct broken_edid brokendb[] = {
+static const struct broken_edid brokendb[] = {
        /* DEC FR-PCXAV-YZ */
        {
                .manufacturer = "DEC",
index 2a0e821..949141b 100644 (file)
@@ -968,6 +968,8 @@ static int ffb_init_one(struct of_device *op)
 
        if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
                printk(KERN_ERR "ffb: Could not allocate color map.\n");
+               of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
+               of_iounmap(all->par.dac, sizeof(struct ffb_dac));
                kfree(all);
                return -ENOMEM;
        }
@@ -978,6 +980,8 @@ static int ffb_init_one(struct of_device *op)
        if (err < 0) {
                printk(KERN_ERR "ffb: Could not register framebuffer.\n");
                fb_dealloc_cmap(&all->info.cmap);
+               of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
+               of_iounmap(all->par.dac, sizeof(struct ffb_dac));
                kfree(all);
                return err;
        }
index 998374c..70ff55b 100644 (file)
@@ -283,6 +283,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
 
        if (register_framebuffer(info) < 0) {
                fb_dealloc_cmap(&info->cmap);
+               iounmap(info->screen_base);
                framebuffer_release(info);
                zorro_release_device(z);
                return -EINVAL;
index 4e173ef..a814b6c 100644 (file)
@@ -23,6 +23,26 @@ config FB_GEODE_GX
 
          If unsure, say N.
 
+config FB_GEODE_GX_SET_FBSIZE
+       bool "Manually specify the Geode GX framebuffer size"
+       depends on FB_GEODE_GX
+       default n
+       ---help---
+         If you want to manually specify the size of your GX framebuffer,
+         say Y here, otherwise say N to dynamically probe it.
+
+         Say N unless you know what you are doing.
+
+config FB_GEODE_GX_FBSIZE
+       hex "Size of the GX framebuffer, in bytes"
+       depends on FB_GEODE_GX_SET_FBSIZE
+       default "0x1600000"
+       ---help---
+         Specify the size of the GX framebuffer.  Normally, you will
+         want this to be MB aligned.  Common values are 0x80000 (8MB)
+         and 0x1600000 (16MB).  Don't change this unless you know what
+         you are doing
+
 config FB_GEODE_GX1
        tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
        depends on FB && FB_GEODE && EXPERIMENTAL
index 825c340..0f16e4b 100644 (file)
 #include "geodefb.h"
 #include "display_gx.h"
 
-int gx_frame_buffer_size(void)
+#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
+unsigned int gx_frame_buffer_size(void)
 {
-       /* Assuming 16 MiB. */
-       return 16*1024*1024;
+       return CONFIG_FB_GEODE_GX_FBSIZE;
 }
+#else
+unsigned int gx_frame_buffer_size(void)
+{
+       unsigned int val;
+
+       /* FB size is reported by a virtual register */
+       /* Virtual register class = 0x02 */
+       /* VG_MEM_SIZE(512Kb units) = 0x00 */
+
+       outw(0xFC53, 0xAC1C);
+       outw(0x0200, 0xAC1C);
+
+       val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
+       return (val << 19);
+}
+#endif
 
 int gx_line_delta(int xres, int bpp)
 {
@@ -81,6 +97,7 @@ static void gx_set_mode(struct fb_info *info)
        writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
               par->dc_regs + DC_LINE_SIZE);
 
+
        /* Enable graphics and video data and unmask address lines. */
        dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
 
index 86c6233..0af33f3 100644 (file)
 #ifndef __DISPLAY_GX_H__
 #define __DISPLAY_GX_H__
 
-int gx_frame_buffer_size(void);
+unsigned int gx_frame_buffer_size(void);
 int gx_line_delta(int xres, int bpp);
 
 extern struct geode_dc_ops gx_dc_ops;
 
+/* MSR that tells us if a TFT or CRT is attached */
+#define GLD_MSR_CONFIG   0xC0002001
+#define GLD_MSR_CONFIG_DM_FP 0x40
+
 /* Display controller registers */
 
 #define DC_UNLOCK 0x00
@@ -93,4 +97,5 @@ extern struct geode_dc_ops gx_dc_ops;
 #define DC_PAL_ADDRESS 0x70
 #define DC_PAL_DATA    0x74
 
+#define DC_GLIU0_MEM_OFFSET 0x84
 #endif /* !__DISPLAY_GX1_H__ */
index 0d3643f..cf841ef 100644 (file)
 #include "display_gx.h"
 #include "video_gx.h"
 
-static char mode_option[32] = "640x480-16@60";
+static char *mode_option;
 
 /* Modes relevant to the GX (taken from modedb.c) */
-static const struct fb_videomode __initdata gx_modedb[] = {
+static const struct fb_videomode gx_modedb[] __initdata = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -240,6 +240,12 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de
        if (!info->screen_base)
                return -ENOMEM;
 
+       /* Set the 16MB aligned base address of the graphics memory region
+        * in the display controller */
+
+       writel(info->fix.smem_start & 0xFF000000,
+                       par->dc_regs + DC_GLIU0_MEM_OFFSET);
+
        dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
                 info->fix.smem_len / 1024, info->fix.smem_start);
 
@@ -302,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
        struct geodefb_par *par;
        struct fb_info *info;
        int ret;
+       unsigned long val;
 
        info = gxfb_init_fbinfo(&pdev->dev);
        if (!info)
@@ -317,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
                goto err;
        }
 
+       /* Figure out if this is a TFT or CRT part */
+
+       rdmsrl(GLD_MSR_CONFIG, val);
+
+       if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP)
+               par->enable_crt = 0;
+       else
+               par->enable_crt = 1;
+
        ret = fb_find_mode(&info->var, info, mode_option,
                           gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
        if (ret == 0 || ret == 4) {
@@ -325,7 +341,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
                goto err;
        }
 
-        /* Clear the frame buffer of garbage. */
+
+       /* Clear the frame buffer of garbage. */
         memset_io(info->screen_base, 0, info->fix.smem_len);
 
        gxfb_check_var(&info->var, info);
@@ -380,7 +397,7 @@ static void gxfb_remove(struct pci_dev *pdev)
 }
 
 static struct pci_device_id gxfb_id_table[] = {
-       { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO,
+       { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
          PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
          0xff0000, 0 },
        { 0, }
@@ -395,11 +412,35 @@ static struct pci_driver gxfb_driver = {
        .remove         = gxfb_remove,
 };
 
+#ifndef MODULE
+static int __init gxfb_setup(char *options)
+{
+
+       char *opt;
+
+       if (!options || !*options)
+               return 0;
+
+       while ((opt = strsep(&options, ",")) != NULL) {
+               if (!*opt)
+                       continue;
+
+               mode_option = opt;
+       }
+
+       return 0;
+}
+#endif
+
 static int __init gxfb_init(void)
 {
 #ifndef MODULE
-       if (fb_get_options("gxfb", NULL))
+       char *option = NULL;
+
+       if (fb_get_options("gxfb", &option))
                return -ENODEV;
+
+       gxfb_setup(option);
 #endif
        return pci_register_driver(&gxfb_driver);
 }
@@ -412,8 +453,8 @@ static void __exit gxfb_cleanup(void)
 module_init(gxfb_init);
 module_exit(gxfb_cleanup);
 
-module_param_string(mode, mode_option, sizeof(mode_option), 0444);
-MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
 
 MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
 MODULE_LICENSE("GPL");
index 2b2a788..7f3f18d 100644 (file)
@@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct fb_info *info)
        } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
 }
 
+static void
+gx_configure_tft(struct fb_info *info)
+{
+       struct geodefb_par *par = info->par;
+       unsigned long val;
+       unsigned long fp;
+
+       /* Set up the DF pad select MSR */
+
+       rdmsrl(GX_VP_MSR_PAD_SELECT, val);
+       val &= ~GX_VP_PAD_SELECT_MASK;
+       val |= GX_VP_PAD_SELECT_TFT;
+       wrmsrl(GX_VP_MSR_PAD_SELECT, val);
+
+       /* Turn off the panel */
+
+       fp = readl(par->vid_regs + GX_FP_PM);
+       fp &= ~GX_FP_PM_P;
+       writel(fp, par->vid_regs + GX_FP_PM);
+
+       /* Set timing 1 */
+
+       fp = readl(par->vid_regs + GX_FP_PT1);
+       fp &= GX_FP_PT1_VSIZE_MASK;
+       fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
+       writel(fp, par->vid_regs + GX_FP_PT1);
+
+       /* Timing 2 */
+       /* Set bits that are always on for TFT */
+
+       fp = 0x0F100000;
+
+       /* Add sync polarity */
+
+       if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+               fp |= GX_FP_PT2_VSP;
+
+       if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+               fp |= GX_FP_PT2_HSP;
+
+       writel(fp, par->vid_regs + GX_FP_PT2);
+
+       /*  Set the dither control */
+       writel(0x70, par->vid_regs + GX_FP_DFC);
+
+       /* Enable the FP data and power (in case the BIOS didn't) */
+
+       fp = readl(par->vid_regs + GX_DCFG);
+       fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
+       writel(fp, par->vid_regs + GX_DCFG);
+
+       /* Unblank the panel */
+
+       fp = readl(par->vid_regs + GX_FP_PM);
+       fp |= GX_FP_PM_P;
+       writel(fp, par->vid_regs + GX_FP_PM);
+}
+
 static void gx_configure_display(struct fb_info *info)
 {
        struct geodefb_par *par = info->par;
-       u32 dcfg, fp_pm;
+       u32 dcfg, misc;
+
+       /* Set up the MISC register */
+
+       misc = readl(par->vid_regs + GX_MISC);
+
+       /* Power up the DAC */
+       misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
+
+       /* Disable gamma correction */
+       misc |= GX_MISC_GAM_EN;
+
+       writel(misc, par->vid_regs + GX_MISC);
 
+       /* Write the display configuration */
        dcfg = readl(par->vid_regs + GX_DCFG);
 
+       /* Disable hsync and vsync */
+       dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
+       writel(dcfg, par->vid_regs + GX_DCFG);
+
        /* Clear bits from existing mode. */
        dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
                  | GX_DCFG_CRT_HSYNC_POL   | GX_DCFG_CRT_VSYNC_POL
@@ -199,12 +274,19 @@ static void gx_configure_display(struct fb_info *info)
        if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
                dcfg |= GX_DCFG_CRT_VSYNC_POL;
 
+       /* Enable the display logic */
+       /* Set up the DACS to blank normally */
+
+       dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
+
+       /* Enable the external DAC VREF? */
+
        writel(dcfg, par->vid_regs + GX_DCFG);
 
-       /* Power on flat panel. */
-       fp_pm = readl(par->vid_regs + GX_FP_PM);
-       fp_pm |= GX_FP_PM_P;
-       writel(fp_pm, par->vid_regs + GX_FP_PM);
+       /* Set up the flat panel (if it is enabled) */
+
+       if (par->enable_crt == 0)
+               gx_configure_tft(info);
 }
 
 static int gx_blank_display(struct fb_info *info, int blank_mode)
@@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
        writel(dcfg, par->vid_regs + GX_DCFG);
 
        /* Power on/off flat panel. */
-       fp_pm = readl(par->vid_regs + GX_FP_PM);
-       if (blank_mode == FB_BLANK_POWERDOWN)
-               fp_pm &= ~GX_FP_PM_P;
-       else
-               fp_pm |= GX_FP_PM_P;
-       writel(fp_pm, par->vid_regs + GX_FP_PM);
+
+       if (par->enable_crt == 0) {
+               fp_pm = readl(par->vid_regs + GX_FP_PM);
+               if (blank_mode == FB_BLANK_POWERDOWN)
+                       fp_pm &= ~GX_FP_PM_P;
+               else
+                       fp_pm |= GX_FP_PM_P;
+               writel(fp_pm, par->vid_regs + GX_FP_PM);
+       }
 
        return 0;
 }
index 2d9211f..ce28d8f 100644 (file)
 
 extern struct geode_vid_ops gx_vid_ops;
 
+/* GX Flatpanel control MSR */
+#define GX_VP_MSR_PAD_SELECT           0xC0002011
+#define GX_VP_PAD_SELECT_MASK          0x3FFFFFFF
+#define GX_VP_PAD_SELECT_TFT           0x1FFFFFFF
+
 /* Geode GX video processor registers */
 
 #define GX_DCFG                0x0008
@@ -20,6 +25,8 @@ extern struct geode_vid_ops gx_vid_ops;
 #  define GX_DCFG_HSYNC_EN             0x00000002
 #  define GX_DCFG_VSYNC_EN             0x00000004
 #  define GX_DCFG_DAC_BL_EN            0x00000008
+#  define GX_DCFG_FP_PWR_EN            0x00000040
+#  define GX_DCFG_FP_DATA_EN           0x00000080
 #  define GX_DCFG_CRT_HSYNC_POL                0x00000100
 #  define GX_DCFG_CRT_VSYNC_POL                0x00000200
 #  define GX_DCFG_CRT_SYNC_SKW_MASK    0x0001C000
@@ -28,10 +35,28 @@ extern struct geode_vid_ops gx_vid_ops;
 #  define GX_DCFG_GV_GAM               0x00200000
 #  define GX_DCFG_DAC_VREF             0x04000000
 
+/* Geode GX MISC video configuration */
+
+#define GX_MISC 0x50
+#define GX_MISC_GAM_EN     0x00000001
+#define GX_MISC_DAC_PWRDN  0x00000400
+#define GX_MISC_A_PWRDN    0x00000800
+
 /* Geode GX flat panel display control registers */
+
+#define GX_FP_PT1 0x0400
+#define GX_FP_PT1_VSIZE_MASK 0x7FF0000
+#define GX_FP_PT1_VSIZE_SHIFT 16
+
+#define GX_FP_PT2 0x408
+#define GX_FP_PT2_VSP (1 << 23)
+#define GX_FP_PT2_HSP (1 << 22)
+
 #define GX_FP_PM 0x410
 #  define GX_FP_PM_P 0x01000000
 
+#define GX_FP_DFC 0x418
+
 /* Geode GX clock control MSRs */
 
 #define MSR_GLCP_SYS_RSTPLL    0x4c000014
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
new file mode 100644 (file)
index 0000000..3adf6ab
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ * Frame buffer device for IBM GXT4500P display adaptor
+ *
+ * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/delay.h>
+
+#define PCI_DEVICE_ID_IBM_GXT4500P     0x21c
+
+/* GXT4500P registers */
+
+/* Registers in PCI config space */
+#define CFG_ENDIAN0            0x40
+
+/* Misc control/status registers */
+#define STATUS                 0x1000
+#define CTRL_REG0              0x1004
+#define   CR0_HALT_DMA                 0x4
+#define   CR0_RASTER_RESET             0x8
+#define   CR0_GEOM_RESET               0x10
+#define   CR0_MEM_CTRLER_RESET         0x20
+
+/* Framebuffer control registers */
+#define FB_AB_CTRL             0x1100
+#define FB_CD_CTRL             0x1104
+#define FB_WID_CTRL            0x1108
+#define FB_Z_CTRL              0x110c
+#define FB_VGA_CTRL            0x1110
+#define REFRESH_AB_CTRL                0x1114
+#define REFRESH_CD_CTRL                0x1118
+#define FB_OVL_CTRL            0x111c
+#define   FB_CTRL_TYPE                 0x80000000
+#define   FB_CTRL_WIDTH_MASK           0x007f0000
+#define   FB_CTRL_WIDTH_SHIFT          16
+#define   FB_CTRL_START_SEG_MASK       0x00003fff
+
+#define REFRESH_START          0x1098
+#define REFRESH_SIZE           0x109c
+
+/* "Direct" framebuffer access registers */
+#define DFA_FB_A               0x11e0
+#define DFA_FB_B               0x11e4
+#define DFA_FB_C               0x11e8
+#define DFA_FB_D               0x11ec
+#define   DFA_FB_ENABLE                        0x80000000
+#define   DFA_FB_BASE_MASK             0x03f00000
+#define   DFA_FB_STRIDE_1k             0x00000000
+#define   DFA_FB_STRIDE_2k             0x00000010
+#define   DFA_FB_STRIDE_4k             0x00000020
+#define   DFA_PIX_8BIT                 0x00000000
+#define   DFA_PIX_16BIT_565            0x00000001
+#define   DFA_PIX_16BIT_1555           0x00000002
+#define   DFA_PIX_24BIT                        0x00000004
+#define   DFA_PIX_32BIT                        0x00000005
+
+/* maps DFA_PIX_* to pixel size in bytes */
+static const unsigned char pixsize[] = {
+       1, 2, 2, 2, 4, 4
+};
+
+/* Display timing generator registers */
+#define DTG_CONTROL            0x1900
+#define   DTG_CTL_SCREEN_REFRESH       2
+#define   DTG_CTL_ENABLE               1
+#define DTG_HORIZ_EXTENT       0x1904
+#define DTG_HORIZ_DISPLAY      0x1908
+#define DTG_HSYNC_START                0x190c
+#define DTG_HSYNC_END          0x1910
+#define DTG_HSYNC_END_COMP     0x1914
+#define DTG_VERT_EXTENT                0x1918
+#define DTG_VERT_DISPLAY       0x191c
+#define DTG_VSYNC_START                0x1920
+#define DTG_VSYNC_END          0x1924
+#define DTG_VERT_SHORT         0x1928
+
+/* PLL/RAMDAC registers */
+#define DISP_CTL               0x402c
+#define   DISP_CTL_OFF                 2
+#define SYNC_CTL               0x4034
+#define   SYNC_CTL_SYNC_ON_RGB         1
+#define   SYNC_CTL_SYNC_OFF            2
+#define   SYNC_CTL_HSYNC_INV           8
+#define   SYNC_CTL_VSYNC_INV           0x10
+#define   SYNC_CTL_HSYNC_OFF           0x20
+#define   SYNC_CTL_VSYNC_OFF           0x40
+
+#define PLL_M                  0x4040
+#define PLL_N                  0x4044
+#define PLL_POSTDIV            0x4048
+
+/* Hardware cursor */
+#define CURSOR_X               0x4078
+#define CURSOR_Y               0x407c
+#define CURSOR_HOTSPOT         0x4080
+#define CURSOR_MODE            0x4084
+#define   CURSOR_MODE_OFF              0
+#define   CURSOR_MODE_4BPP             1
+#define CURSOR_PIXMAP          0x5000
+#define CURSOR_CMAP            0x7400
+
+/* Window attribute table */
+#define WAT_FMT                        0x4100
+#define   WAT_FMT_24BIT                        0
+#define   WAT_FMT_16BIT_565            1
+#define   WAT_FMT_16BIT_1555           2
+#define   WAT_FMT_32BIT                        3       /* 0 vs. 3 is a guess */
+#define   WAT_FMT_8BIT_332             9
+#define   WAT_FMT_8BIT                 0xa
+#define   WAT_FMT_NO_CMAP              4       /* ORd in to other values */
+#define WAT_CMAP_OFFSET                0x4104          /* 4-bit value gets << 6 */
+#define WAT_CTRL               0x4108
+#define   WAT_CTRL_SEL_B               1       /* select B buffer if 1 */
+#define   WAT_CTRL_NO_INC              2
+#define WAT_GAMMA_CTRL         0x410c
+#define   WAT_GAMMA_DISABLE            1       /* disables gamma cmap */
+#define WAT_OVL_CTRL           0x430c          /* controls overlay */
+
+/* Indexed by DFA_PIX_* values */
+static const unsigned char watfmt[] = {
+       WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0,
+       WAT_FMT_24BIT, WAT_FMT_32BIT
+};
+
+/* Colormap array; 1k entries of 4 bytes each */
+#define CMAP                   0x6000
+
+#define readreg(par, reg)      readl((par)->regs + (reg))
+#define writereg(par, reg, val)        writel((val), (par)->regs + (reg))
+
+struct gxt4500_par {
+       void __iomem *regs;
+
+       int pixfmt;             /* pixel format, see DFA_PIX_* values */
+
+       /* PLL parameters */
+       int pll_m;              /* ref clock divisor */
+       int pll_n;              /* VCO divisor */
+       int pll_pd1;            /* first post-divisor */
+       int pll_pd2;            /* second post-divisor */
+
+       u32 pseudo_palette[16]; /* used in color blits */
+};
+
+/* mode requested by user */
+static char *mode_option;
+
+/* default mode: 1280x1024 @ 60 Hz, 8 bpp */
+static const struct fb_videomode defaultmode __devinitdata = {
+       .refresh = 60,
+       .xres = 1280,
+       .yres = 1024,
+       .pixclock = 9295,
+       .left_margin = 248,
+       .right_margin = 48,
+       .upper_margin = 38,
+       .lower_margin = 1,
+       .hsync_len = 112,
+       .vsync_len = 3,
+       .vmode = FB_VMODE_NONINTERLACED
+};
+
+/*
+ * The refclk and VCO dividers appear to use a linear feedback shift
+ * register, which gets reloaded when it reaches a terminal value, at
+ * which point the divider output is toggled.  Thus one can obtain
+ * whatever divisor is required by putting the appropriate value into
+ * the reload register.  For a divisor of N, one puts the value from
+ * the LFSR sequence that comes N-1 places before the terminal value
+ * into the reload register.
+ */
+
+static const unsigned char mdivtab[] = {
+/* 1 */                      0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a,
+/* 10 */       0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11,
+/* 20 */       0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d,
+/* 30 */       0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02,
+/* 40 */       0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e,
+/* 50 */       0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e,
+/* 60 */       0x1f, 0x0f, 0x07, 0x03, 0x01,
+};
+
+static const unsigned char ndivtab[] = {
+/* 2 */                            0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e,
+/* 10 */       0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e,
+/* 20 */       0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf,
+/* 30 */       0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc,
+/* 40 */       0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8,
+/* 50 */       0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6,
+/* 60 */       0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62,
+/* 70 */       0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57,
+/* 80 */       0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94,
+/* 90 */       0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79,
+/* 100 */      0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24,
+/* 110 */      0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45,
+/* 120 */      0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d,
+/* 130 */      0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e,
+/* 140 */      0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98,
+/* 150 */      0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2,
+/* 160 */      0x69, 0xb4, 0xda, 0xed, 0x76, 0xbb, 0x5d, 0xae, 0xd7, 0x6b,
+/* 170 */      0xb5, 0x5a, 0xad, 0x56, 0xab, 0xd5, 0x6a, 0x35, 0x1a, 0x8d,
+/* 180 */      0x46, 0x23, 0x11, 0x88, 0x44, 0x22, 0x91, 0xc8, 0x64, 0x32,
+/* 190 */      0x19, 0x0c, 0x86, 0x43, 0x21, 0x10, 0x08, 0x04, 0x02, 0x81,
+/* 200 */      0x40, 0xa0, 0xd0, 0x68, 0x34, 0x9a, 0xcd, 0x66, 0x33, 0x99,
+/* 210 */      0x4c, 0xa6, 0x53, 0xa9, 0xd4, 0xea, 0x75, 0x3a, 0x9d, 0xce,
+/* 220 */      0xe7, 0xf3, 0xf9, 0x7c, 0x3e, 0x1f, 0x8f, 0x47, 0xa3, 0x51,
+/* 230 */      0xa8, 0x54, 0xaa, 0x55, 0x2a, 0x15, 0x0a, 0x05, 0x82, 0xc1,
+/* 240 */      0x60, 0xb0, 0x58, 0xac, 0xd6, 0xeb, 0xf5, 0x7a, 0xbd, 0xde,
+/* 250 */      0x6f, 0x37, 0x1b, 0x0d, 0x06, 0x03, 0x01,
+};
+
+#define REF_PERIOD_PS  9259    /* period of reference clock in ps */
+
+static int calc_pll(int period_ps, struct gxt4500_par *par)
+{
+       int m, n, pdiv1, pdiv2, postdiv;
+       int pll_period, best_error, t;
+
+       /* only deal with range 1MHz - 400MHz */
+       if (period_ps < 2500 || period_ps > 1000000)
+               return -1;
+
+       best_error = 1000000;
+       for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
+               for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
+                       postdiv = pdiv1 * pdiv2;
+                       pll_period = (period_ps + postdiv - 1) / postdiv;
+                       /* keep pll in range 500..1250 MHz */
+                       if (pll_period < 800 || pll_period > 2000)
+                               continue;
+                       for (m = 3; m <= 40; ++m) {
+                               n = REF_PERIOD_PS * m * postdiv / period_ps;
+                               if (n < 5 || n > 256)
+                                       continue;
+                               t = REF_PERIOD_PS * m * postdiv / n;
+                               t -= period_ps;
+                               if (t >= 0 && t < best_error) {
+                                       par->pll_m = m;
+                                       par->pll_n = n;
+                                       par->pll_pd1 = pdiv1;
+                                       par->pll_pd2 = pdiv2;
+                                       best_error = t;
+                               }
+                       }
+               }
+       }
+       if (best_error == 1000000)
+               return -1;
+       return 0;
+}
+
+static int calc_pixclock(struct gxt4500_par *par)
+{
+       return REF_PERIOD_PS * par->pll_m * par->pll_pd1 * par->pll_pd2
+               / par->pll_n;
+}
+
+static int gxt4500_var_to_par(struct fb_var_screeninfo *var,
+                             struct gxt4500_par *par)
+{
+       if (var->xres + var->xoffset > var->xres_virtual ||
+           var->yres + var->yoffset > var->yres_virtual ||
+           var->xres_virtual > 4096)
+               return -EINVAL;
+       if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+       if (calc_pll(var->pixclock, par) < 0)
+               return -EINVAL;
+
+       switch (var->bits_per_pixel) {
+       case 32:
+               if (var->transp.length)
+                       par->pixfmt = DFA_PIX_32BIT;
+               else
+                       par->pixfmt = DFA_PIX_24BIT;
+               break;
+       case 24:
+               par->pixfmt = DFA_PIX_24BIT;
+               break;
+       case 16:
+               if (var->green.length == 5)
+                       par->pixfmt = DFA_PIX_16BIT_1555;
+               else
+                       par->pixfmt = DFA_PIX_16BIT_565;
+               break;
+       case 8:
+               par->pixfmt = DFA_PIX_8BIT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct fb_bitfield eightbits = {0, 8};
+static const struct fb_bitfield nobits = {0, 0};
+
+static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var,
+                                 int pixfmt)
+{
+       var->bits_per_pixel = pixsize[pixfmt] * 8;
+       var->red = eightbits;
+       var->green = eightbits;
+       var->blue = eightbits;
+       var->transp = nobits;
+
+       switch (pixfmt) {
+       case DFA_PIX_16BIT_565:
+               var->red.length = 5;
+               var->green.length = 6;
+               var->blue.length = 5;
+               break;
+       case DFA_PIX_16BIT_1555:
+               var->red.length = 5;
+               var->green.length = 5;
+               var->blue.length = 5;
+               var->transp.length = 1;
+               break;
+       case DFA_PIX_32BIT:
+               var->transp.length = 8;
+               break;
+       }
+       if (pixfmt != DFA_PIX_8BIT) {
+               var->green.offset = var->red.length;
+               var->blue.offset = var->green.offset + var->green.length;
+               if (var->transp.length)
+                       var->transp.offset =
+                               var->blue.offset + var->blue.length;
+       }
+}
+
+static int gxt4500_check_var(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+       struct gxt4500_par par;
+       int err;
+
+       par = *(struct gxt4500_par *)info->par;
+       err = gxt4500_var_to_par(var, &par);
+       if (!err) {
+               var->pixclock = calc_pixclock(&par);
+               gxt4500_unpack_pixfmt(var, par.pixfmt);
+       }
+       return err;
+}
+
+static int gxt4500_set_par(struct fb_info *info)
+{
+       struct gxt4500_par *par = info->par;
+       struct fb_var_screeninfo *var = &info->var;
+       int err;
+       u32 ctrlreg;
+       unsigned int dfa_ctl, pixfmt, stride;
+       unsigned int wid_tiles, i;
+       unsigned int prefetch_pix, htot;
+       struct gxt4500_par save_par;
+
+       save_par = *par;
+       err = gxt4500_var_to_par(var, par);
+       if (err) {
+               *par = save_par;
+               return err;
+       }
+
+       /* turn off DTG for now */
+       ctrlreg = readreg(par, DTG_CONTROL);
+       ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH);
+       writereg(par, DTG_CONTROL, ctrlreg);
+
+       /* set PLL registers */
+       writereg(par, PLL_M, mdivtab[par->pll_m - 1]);
+       writereg(par, PLL_N, ndivtab[par->pll_n - 2]);
+       writereg(par, PLL_POSTDIV,
+                ((8 - par->pll_pd1) << 3) | (8 - par->pll_pd2));
+       msleep(20);
+
+       /* turn off hardware cursor */
+       writereg(par, CURSOR_MODE, CURSOR_MODE_OFF);
+
+       /* reset raster engine */
+       writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16));
+       udelay(10);
+       writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16);
+
+       /* set display timing generator registers */
+       htot = var->xres + var->left_margin + var->right_margin +
+               var->hsync_len;
+       writereg(par, DTG_HORIZ_EXTENT, htot - 1);
+       writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1);
+       writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1);
+       writereg(par, DTG_HSYNC_END,
+                var->xres + var->right_margin + var->hsync_len - 1);
+       writereg(par, DTG_HSYNC_END_COMP,
+                var->xres + var->right_margin + var->hsync_len - 1);
+       writereg(par, DTG_VERT_EXTENT,
+                var->yres + var->upper_margin + var->lower_margin +
+                var->vsync_len - 1);
+       writereg(par, DTG_VERT_DISPLAY, var->yres - 1);
+       writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1);
+       writereg(par, DTG_VSYNC_END,
+                var->yres + var->lower_margin + var->vsync_len - 1);
+       prefetch_pix = 3300000 / var->pixclock;
+       if (prefetch_pix >= htot)
+               prefetch_pix = htot - 1;
+       writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1);
+       ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH;
+       writereg(par, DTG_CONTROL, ctrlreg);
+
+       /* calculate stride in DFA aperture */
+       if (var->xres_virtual > 2048) {
+               stride = 4096;
+               dfa_ctl = DFA_FB_STRIDE_4k;
+       } else if (var->xres_virtual > 1024) {
+               stride = 2048;
+               dfa_ctl = DFA_FB_STRIDE_2k;
+       } else {
+               stride = 1024;
+               dfa_ctl = DFA_FB_STRIDE_1k;
+       }
+
+       /* Set up framebuffer definition */
+       wid_tiles = (var->xres_virtual + 63) >> 6;
+
+       /* XXX add proper FB allocation here someday */
+       writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+       writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+       writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+       writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+       writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+       writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres);
+
+       /* Set up framebuffer access by CPU */
+
+       pixfmt = par->pixfmt;
+       dfa_ctl |= DFA_FB_ENABLE | pixfmt;
+       writereg(par, DFA_FB_A, dfa_ctl);
+
+       /*
+        * Set up window attribute table.
+        * We set all WAT entries the same so it doesn't matter what the
+        * window ID (WID) plane contains.
+        */
+       for (i = 0; i < 32; ++i) {
+               writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]);
+               writereg(par, WAT_CMAP_OFFSET + (i << 4), 0);
+               writereg(par, WAT_CTRL + (i << 4), 0);
+               writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE);
+       }
+
+       /* Set sync polarity etc. */
+       ctrlreg = readreg(par, SYNC_CTL) &
+               ~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV |
+                 SYNC_CTL_VSYNC_INV);
+       if (var->sync & FB_SYNC_ON_GREEN)
+               ctrlreg |= SYNC_CTL_SYNC_ON_RGB;
+       if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+               ctrlreg |= SYNC_CTL_HSYNC_INV;
+       if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+               ctrlreg |= SYNC_CTL_VSYNC_INV;
+       writereg(par, SYNC_CTL, ctrlreg);
+
+       info->fix.line_length = stride * pixsize[pixfmt];
+       info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR:
+               FB_VISUAL_DIRECTCOLOR;
+
+       return 0;
+}
+
+static int gxt4500_setcolreg(unsigned int reg, unsigned int red,
+                            unsigned int green, unsigned int blue,
+                            unsigned int transp, struct fb_info *info)
+{
+       u32 cmap_entry;
+       struct gxt4500_par *par = info->par;
+
+       if (reg > 1023)
+               return 1;
+       cmap_entry = ((transp & 0xff00) << 16) | ((blue & 0xff00) << 8) |
+               (green & 0xff00) | (red >> 8);
+       writereg(par, CMAP + reg * 4, cmap_entry);
+
+       if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) {
+               u32 *pal = info->pseudo_palette;
+               u32 val = reg;
+               switch (par->pixfmt) {
+               case DFA_PIX_16BIT_565:
+                       val |= (reg << 11) | (reg << 6);
+                       break;
+               case DFA_PIX_16BIT_1555:
+                       val |= (reg << 10) | (reg << 5);
+                       break;
+               case DFA_PIX_32BIT:
+                       val |= (reg << 24);
+                       /* fall through */
+               case DFA_PIX_24BIT:
+                       val |= (reg << 16) | (reg << 8);
+                       break;
+               }
+               pal[reg] = val;
+       }
+
+       return 0;
+}
+
+static int gxt4500_pan_display(struct fb_var_screeninfo *var,
+                              struct fb_info *info)
+{
+       struct gxt4500_par *par = info->par;
+
+       if (var->xoffset & 7)
+               return -EINVAL;
+       if (var->xoffset + var->xres > var->xres_virtual ||
+           var->yoffset + var->yres > var->yres_virtual)
+               return -EINVAL;
+
+       writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+       return 0;
+}
+
+static int gxt4500_blank(int blank, struct fb_info *info)
+{
+       struct gxt4500_par *par = info->par;
+       int ctrl, dctl;
+
+       ctrl = readreg(par, SYNC_CTL);
+       ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF);
+       dctl = readreg(par, DISP_CTL);
+       dctl |= DISP_CTL_OFF;
+       switch (blank) {
+       case FB_BLANK_UNBLANK:
+               dctl &= ~DISP_CTL_OFF;
+               break;
+       case FB_BLANK_POWERDOWN:
+               ctrl |= SYNC_CTL_SYNC_OFF;
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               ctrl |= SYNC_CTL_HSYNC_OFF;
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               ctrl |= SYNC_CTL_VSYNC_OFF;
+               break;
+       default: ;
+       }
+       writereg(par, SYNC_CTL, ctrl);
+       writereg(par, DISP_CTL, dctl);
+
+       return 0;
+}
+
+static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = {
+       .id = "IBM GXT4500P",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_PSEUDOCOLOR,
+       .xpanstep = 8,
+       .ypanstep = 1,
+       .mmio_len = 0x20000,
+};
+
+static struct fb_ops gxt4500_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = gxt4500_check_var,
+       .fb_set_par = gxt4500_set_par,
+       .fb_setcolreg = gxt4500_setcolreg,
+       .fb_pan_display = gxt4500_pan_display,
+       .fb_blank = gxt4500_blank,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+};
+
+/* PCI functions */
+static int __devinit gxt4500_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+{
+       int err;
+       unsigned long reg_phys, fb_phys;
+       struct gxt4500_par *par;
+       struct fb_info *info;
+       struct fb_var_screeninfo var;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n",
+                       err);
+               return err;
+       }
+
+       reg_phys = pci_resource_start(pdev, 0);
+       if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0),
+                               "gxt4500 regs")) {
+               dev_err(&pdev->dev, "gxt4500: cannot get registers\n");
+               goto err_nodev;
+       }
+
+       fb_phys = pci_resource_start(pdev, 1);
+       if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1),
+                               "gxt4500 FB")) {
+               dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n");
+               goto err_free_regs;
+       }
+
+       info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev);
+       if (!info) {
+               dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record");
+               goto err_free_fb;
+       }
+       par = info->par;
+       info->fix = gxt4500_fix;
+       info->pseudo_palette = par->pseudo_palette;
+
+       info->fix.mmio_start = reg_phys;
+       par->regs = ioremap(reg_phys, pci_resource_len(pdev, 0));
+       if (!par->regs) {
+               dev_err(&pdev->dev, "gxt4500: cannot map registers\n");
+               goto err_free_all;
+       }
+
+       info->fix.smem_start = fb_phys;
+       info->fix.smem_len = pci_resource_len(pdev, 1);
+       info->screen_base = ioremap(fb_phys, pci_resource_len(pdev, 1));
+       if (!info->screen_base) {
+               dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n");
+               goto err_unmap_regs;
+       }
+
+       pci_set_drvdata(pdev, info);
+
+       /* Set byte-swapping for DFA aperture for all pixel sizes */
+       pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300);
+
+       info->fbops = &gxt4500_ops;
+       info->flags = FBINFO_FLAG_DEFAULT;
+
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err) {
+               dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n");
+               goto err_unmap_all;
+       }
+
+       gxt4500_blank(FB_BLANK_UNBLANK, info);
+
+       if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) {
+               dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n");
+               goto err_free_cmap;
+       }
+       info->var = var;
+       if (gxt4500_set_par(info)) {
+               printk(KERN_ERR "gxt4500: cannot set video mode\n");
+               goto err_free_cmap;
+       }
+
+       if (register_framebuffer(info) < 0) {
+               dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n");
+               goto err_free_cmap;
+       }
+       printk(KERN_INFO "fb%d: %s frame buffer device\n",
+              info->node, info->fix.id);
+
+       return 0;
+
+ err_free_cmap:
+       fb_dealloc_cmap(&info->cmap);
+ err_unmap_all:
+       iounmap(info->screen_base);
+ err_unmap_regs:
+       iounmap(par->regs);
+ err_free_all:
+       framebuffer_release(info);
+ err_free_fb:
+       release_mem_region(fb_phys, pci_resource_len(pdev, 1));
+ err_free_regs:
+       release_mem_region(reg_phys, pci_resource_len(pdev, 0));
+ err_nodev:
+       return -ENODEV;
+}
+
+static void __devexit gxt4500_remove(struct pci_dev *pdev)
+{
+       struct fb_info *info = pci_get_drvdata(pdev);
+       struct gxt4500_par *par;
+
+       if (!info)
+               return;
+       par = info->par;
+       unregister_framebuffer(info);
+       fb_dealloc_cmap(&info->cmap);
+       iounmap(par->regs);
+       iounmap(info->screen_base);
+       release_mem_region(pci_resource_start(pdev, 0),
+                          pci_resource_len(pdev, 0));
+       release_mem_region(pci_resource_start(pdev, 1),
+                          pci_resource_len(pdev, 1));
+       framebuffer_release(info);
+}
+
+/* supported chipsets */
+static const struct pci_device_id gxt4500_pci_tbl[] = {
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl);
+
+static struct pci_driver gxt4500_driver = {
+       .name = "gxt4500",
+       .id_table = gxt4500_pci_tbl,
+       .probe = gxt4500_probe,
+       .remove = __devexit_p(gxt4500_remove),
+};
+
+static int __devinit gxt4500_init(void)
+{
+#ifndef MODULE
+       if (fb_get_options("gxt4500", &mode_option))
+               return -ENODEV;
+#endif
+
+       return pci_register_driver(&gxt4500_driver);
+}
+module_init(gxt4500_init);
+
+static void __exit gxt4500_exit(void)
+{
+       pci_unregister_driver(&gxt4500_driver);
+}
+module_exit(gxt4500_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P");
+MODULE_LICENSE("GPL");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
index 91cf3b5..9ab9b83 100644 (file)
@@ -295,6 +295,8 @@ static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base
 
        if (register_framebuffer(&fb_info) < 0) {
                fb_dealloc_cmap(&fb_info.cmap);
+               iounmap(fb_info.screen_base);
+               fb_info.screen_base = NULL;
                return 1;
        }
 
index b38d805..b952e45 100644 (file)
@@ -162,9 +162,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
 
                if (e != NULL) {
                        DPRINTK("i810-i2c: Getting EDID from BIOS\n");
-                       edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-                       if (edid)
-                               memcpy(edid, e, EDID_LENGTH);
+                       edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
                }
        }
 
index e6df492..655ae0f 100644 (file)
@@ -384,19 +384,21 @@ int __init igafb_init(void)
         if (!con_is_present())
                 return -ENXIO;
 
-        pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
+        pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
                                PCI_DEVICE_ID_INTERG_1682, 0);
        if (pdev == NULL) {
                /*
                 * XXX We tried to use cyber2000fb.c for IGS 2000.
                 * But it does not initialize the chip in JavaStation-E, alas.
                 */
-               pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
+               pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
                if(pdev == NULL) {
                        return -ENXIO;
                }
                iga2000 = 1;
        }
+       /* We leak a reference here but as it cannot be unloaded this is
+          fine. If you write unload code remember to free it in unload */
        
        size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16;
 
index 6f9de04..664fc5c 100644 (file)
@@ -1058,10 +1058,9 @@ intelfb_init_var(struct intelfb_info *dinfo)
                u8 *edid_d = NULL;
 
                if (edid_s) {
-                       edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL);
+                       edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
 
                        if (edid_d) {
-                               memcpy(edid_d, edid_s, EDID_LENGTH);
                                fb_edid_to_monspecs(edid_d,
                                                    &dinfo->info->monspecs);
                                kfree(edid_d);
index 80a0438..180d94c 100644 (file)
@@ -608,6 +608,22 @@ void __init macfb_setup(char *options)
        }
 }
 
+static void __init iounmap_macfb(void)
+{
+       if (valkyrie_cmap_regs)
+               iounmap(valkyrie_cmap_regs);
+       if (dafb_cmap_regs)
+               iounmap(dafb_cmap_regs);
+       if (v8_brazil_cmap_regs)
+               iounmap(v8_brazil_cmap_regs);
+       if (rbv_cmap_regs)
+               iounmap(rbv_cmap_regs);
+       if (civic_cmap_regs)
+               iounmap(civic_cmap_regs);
+       if (csc_cmap_regs)
+               iounmap(csc_cmap_regs);
+}
+
 static int __init macfb_init(void)
 {
        int video_cmap_len, video_is_nubus = 0;
@@ -962,6 +978,10 @@ static int __init macfb_init(void)
        if (!err)
                printk("fb%d: %s frame buffer device\n",
                       fb_info.node, fb_info.fix.id);
+       else {
+               iounmap(fb_info.screen_base);
+               iounmap_macfb();
+       }
        return err;
 }
 
index 84aab3a..472a3ca 100644 (file)
@@ -10,6 +10,8 @@ struct mbxfb_debugfs_data {
        struct dentry *clock;
        struct dentry *display;
        struct dentry *gsctl;
+       struct dentry *sdram;
+       struct dentry *misc;
 };
 
 static int open_file_generic(struct inode *inode, struct file *file)
@@ -29,11 +31,11 @@ static ssize_t sysconf_read_file(struct file *file, char __user *userbuf,
 {
        char * s = big_buffer;
 
-       s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG);
-       s += sprintf(s, "PFBASE = %08lx\n", PFBASE);
-       s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL);
-       s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG);
-       s += sprintf(s, "SYSRST = %08lx\n", SYSRST);
+       s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG));
+       s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE));
+       s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL));
+       s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG));
+       s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST));
 
        return  simple_read_from_buffer(userbuf, count, ppos,
                                        big_buffer, s-big_buffer);
@@ -45,24 +47,24 @@ static ssize_t gsctl_read_file(struct file *file, char __user *userbuf,
 {
        char * s = big_buffer;
 
-       s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL);
-       s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL);
-       s += sprintf(s, "GBBASE = %08lx\n", GBBASE);
-       s += sprintf(s, "VBBASE = %08lx\n", VBBASE);
-       s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL);
-       s += sprintf(s, "VCMSK = %08lx\n", VCMSK);
-       s += sprintf(s, "GSCADR = %08lx\n", GSCADR);
-       s += sprintf(s, "VSCADR = %08lx\n", VSCADR);
-       s += sprintf(s, "VUBASE = %08lx\n", VUBASE);
-       s += sprintf(s, "VVBASE = %08lx\n", VVBASE);
-       s += sprintf(s, "GSADR = %08lx\n", GSADR);
-       s += sprintf(s, "VSADR = %08lx\n", VSADR);
-       s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL);
-       s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE);
-       s += sprintf(s, "HCPOS = %08lx\n", HCPOS);
-       s += sprintf(s, "HCBADR = %08lx\n", HCBADR);
-       s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK);
-       s += sprintf(s, "GPLUT = %08lx\n", GPLUT);
+       s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL));
+       s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL));
+       s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE));
+       s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE));
+       s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL));
+       s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK));
+       s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR));
+       s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR));
+       s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE));
+       s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE));
+       s += sprintf(s, "GSADR = %08x\n", readl(GSADR));
+       s += sprintf(s, "VSADR = %08x\n", readl(VSADR));
+       s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL));
+       s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE));
+       s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS));
+       s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR));
+       s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK));
+       s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT));
 
        return  simple_read_from_buffer(userbuf, count, ppos,
                                        big_buffer, s-big_buffer);
@@ -73,36 +75,36 @@ static ssize_t display_read_file(struct file *file, char __user *userbuf,
 {
        char * s = big_buffer;
 
-       s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL);
-       s += sprintf(s, "DHT01 = %08lx\n", DHT01);
-       s += sprintf(s, "DHT02 = %08lx\n", DHT02);
-       s += sprintf(s, "DHT03 = %08lx\n", DHT03);
-       s += sprintf(s, "DVT01 = %08lx\n", DVT01);
-       s += sprintf(s, "DVT02 = %08lx\n", DVT02);
-       s += sprintf(s, "DVT03 = %08lx\n", DVT03);
-       s += sprintf(s, "DBCOL = %08lx\n", DBCOL);
-       s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR);
-       s += sprintf(s, "DINTRS = %08lx\n", DINTRS);
-       s += sprintf(s, "DINTRE = %08lx\n", DINTRE);
-       s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT);
-       s += sprintf(s, "DSIG = %08lx\n", DSIG);
-       s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL);
-       s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL);
-       s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL);
-       s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL);
-       s += sprintf(s, "DLSTS = %08lx\n", DLSTS);
-       s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL);
-       s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM);
-       s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL);
-       s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL);
-       s += sprintf(s, "DHDET = %08lx\n", DHDET);
-       s += sprintf(s, "DVDET = %08lx\n", DVDET);
-       s += sprintf(s, "DODMSK = %08lx\n", DODMSK);
-       s += sprintf(s, "CSC01 = %08lx\n", CSC01);
-       s += sprintf(s, "CSC02 = %08lx\n", CSC02);
-       s += sprintf(s, "CSC03 = %08lx\n", CSC03);
-       s += sprintf(s, "CSC04 = %08lx\n", CSC04);
-       s += sprintf(s, "CSC05 = %08lx\n", CSC05);
+       s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL));
+       s += sprintf(s, "DHT01 = %08x\n", readl(DHT01));
+       s += sprintf(s, "DHT02 = %08x\n", readl(DHT02));
+       s += sprintf(s, "DHT03 = %08x\n", readl(DHT03));
+       s += sprintf(s, "DVT01 = %08x\n", readl(DVT01));
+       s += sprintf(s, "DVT02 = %08x\n", readl(DVT02));
+       s += sprintf(s, "DVT03 = %08x\n", readl(DVT03));
+       s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL));
+       s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR));
+       s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS));
+       s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE));
+       s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT));
+       s += sprintf(s, "DSIG = %08x\n", readl(DSIG));
+       s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL));
+       s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL));
+       s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL));
+       s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL));
+       s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS));
+       s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL));
+       s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM));
+       s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL));
+       s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL));
+       s += sprintf(s, "DHDET = %08x\n", readl(DHDET));
+       s += sprintf(s, "DVDET = %08x\n", readl(DVDET));
+       s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK));
+       s += sprintf(s, "CSC01 = %08x\n", readl(CSC01));
+       s += sprintf(s, "CSC02 = %08x\n", readl(CSC02));
+       s += sprintf(s, "CSC03 = %08x\n", readl(CSC03));
+       s += sprintf(s, "CSC04 = %08x\n", readl(CSC04));
+       s += sprintf(s, "CSC05 = %08x\n", readl(CSC05));
 
        return  simple_read_from_buffer(userbuf, count, ppos,
                                        big_buffer, s-big_buffer);
@@ -113,24 +115,61 @@ static ssize_t clock_read_file(struct file *file, char __user *userbuf,
 {
        char * s = big_buffer;
 
-       s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC);
-       s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC);
-       s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP);
-       s += sprintf(s, "COREPLL = %08lx\n", COREPLL);
-       s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL);
-       s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT);
-       s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK);
-       s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK);
-       s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK);
-       s += sprintf(s, "M24CLK = %08lx\n", M24CLK);
-       s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK);
-       s += sprintf(s, "SDCLK = %08lx\n", SDCLK);
-       s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV);
+       s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC));
+       s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC));
+       s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP));
+       s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL));
+       s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL));
+       s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT));
+       s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK));
+       s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK));
+       s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK));
+       s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK));
+       s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK));
+       s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK));
+       s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV));
 
        return  simple_read_from_buffer(userbuf, count, ppos,
                                        big_buffer, s-big_buffer);
 }
 
+static ssize_t sdram_read_file(struct file *file, char __user *userbuf,
+                              size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "LMRST = %08x\n", readl(LMRST));
+       s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG));
+       s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR));
+       s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT));
+       s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR));
+       s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE));
+       s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM));
+       s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH));
+       s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN));
+       s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX));
+       s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG));
+       s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR));
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+static ssize_t misc_read_file(struct file *file, char __user *userbuf,
+                              size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG));
+       s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR));
+       s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT));
+       s += sprintf(s, "ID = %08x\n", readl(ID));
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+
 static struct file_operations sysconf_fops = {
        .read = sysconf_read_file,
        .write = write_file_dummy,
@@ -155,6 +194,17 @@ static struct file_operations gsctl_fops = {
        .open = open_file_generic,
 };
 
+static struct file_operations sdram_fops = {
+       .read = sdram_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
+
+static struct file_operations misc_fops = {
+       .read = misc_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
 
 static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
 {
@@ -173,6 +223,10 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
                                      fbi, &display_fops);
        dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir,
                                    fbi, &gsctl_fops);
+       dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir,
+                                       fbi, &sdram_fops);
+       dbg->misc = debugfs_create_file("misc", 0444, dbg->dir,
+                                       fbi, &misc_fops);
 }
 
 static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
@@ -180,6 +234,8 @@ static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
        struct mbxfb_info *mfbi = fbi->par;
        struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
 
+       debugfs_remove(dbg->misc);
+       debugfs_remove(dbg->sdram);
        debugfs_remove(dbg->gsctl);
        debugfs_remove(dbg->display);
        debugfs_remove(dbg->clock);
index a32d1af..980d5f6 100644 (file)
@@ -1,8 +1,14 @@
 /*
  *  linux/drivers/video/mbx/mbxfb.c
  *
+ *  Copyright (C) 2006 8D Technologies inc
+ *  Raphael Assenat <raph@8d.com>
+ *     - Added video overlay support
+ *     - Various improvements
+ *
  *  Copyright (C) 2006 Compulab, Ltd.
  *  Mike Rapoport <mike@compulab.co.il>
+ *     - Creation of driver
  *
  *   Based on pxafb.c
  *
@@ -19,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/uaccess.h>
 
 #include <asm/io.h>
 
 
 static unsigned long virt_base_2700;
 
+#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
+
+/* Without this delay, the graphics appears somehow scaled and
+ * there is a lot of jitter in scanlines. This delay is probably
+ * needed only after setting some specific register(s) somewhere,
+ * not all over the place... */
+#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
+
 #define MIN_XRES       16
 #define MIN_YRES       16
 #define MAX_XRES       2048
@@ -257,19 +272,17 @@ static int mbxfb_set_par(struct fb_info *info)
        gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
        gsctrl |= Gsctrl_Width(info->var.xres) |
                Gsctrl_Height(info->var.yres);
-       writel(gsctrl, GSCTRL);
-       udelay(1000);
+       write_reg_dly(gsctrl, GSCTRL);
 
        gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
        gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
                                 (8 * 16) - 1);
-       writel(gsadr, GSADR);
-       udelay(1000);
+       write_reg_dly(gsadr, GSADR);
 
        /* setup timings */
        var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
 
-       writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
+       write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
                Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
 
        hbps = var->hsync_len;
@@ -282,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info)
        vfps = vas + var->yres;
        vt = vfps + var->lower_margin;
 
-       writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
-       writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
-       writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
-       writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
+       write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
+       write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
+       write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
+       write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
 
-       writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
-       writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
-       writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
-       writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
-       writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
+       write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
+       write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
+       write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
+       write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
+       write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
 
-       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+       write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+
+       write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
 
        return 0;
 }
@@ -305,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info)
        case FB_BLANK_VSYNC_SUSPEND:
        case FB_BLANK_HSYNC_SUSPEND:
        case FB_BLANK_NORMAL:
-               writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
-               udelay(1000);
-               writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
-               udelay(1000);
-               writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
-               udelay(1000);
+               write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
+               write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
+               write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
                break;
        case FB_BLANK_UNBLANK:
-               writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
-               udelay(1000);
-               writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
-               udelay(1000);
+               write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+               write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
                break;
        }
        return 0;
 }
 
+static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
+{
+       u32 vsctrl, vbbase, vscadr, vsadr;
+       u32 sssize, spoctrl, svctrl, shctrl;
+       u32 vubase, vvbase;
+       u32 vovrclk;
+
+       if (set->scaled_width==0 || set->scaled_height==0)
+               return -EINVAL;
+
+       /* read registers which have reserved bits
+        * so we can write them back as-is. */
+       vovrclk = readl(VOVRCLK);
+       vsctrl = readl(VSCTRL);
+       vscadr = readl(VSCADR);
+       vubase = readl(VUBASE);
+       vvbase = readl(VVBASE);
+
+       spoctrl = readl(SPOCTRL);
+       sssize = readl(SSSIZE);
+
+
+       vbbase = Vbbase_Glalpha(set->alpha);
+
+       vsctrl &= ~(    FMsk(VSCTRL_VSWIDTH) |
+                                       FMsk(VSCTRL_VSHEIGHT) |
+                                       FMsk(VSCTRL_VPIXFMT) |
+                                       VSCTRL_GAMMA_EN | VSCTRL_CSC_EN |
+                                       VSCTRL_COSITED );
+       vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
+                               VSCTRL_CSC_EN;
+
+       vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC |
+                               FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) |
+                               FMsk(VSCADR_VBASE_ADR) );
+       vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
+       vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
+
+       switch (set->fmt)
+       {
+               case MBXFB_FMT_YUV12:
+                       vsctrl |= VSCTRL_VPIXFMT_YUV12;
+
+                       set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+
+                       break;
+               case MBXFB_FMT_UY0VY1:
+                       vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
+                       set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+                       break;
+               case MBXFB_FMT_VY0UY1:
+                       vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
+                       set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+                       break;
+               case MBXFB_FMT_Y0UY1V:
+                       vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
+                       set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+                       break;
+               case MBXFB_FMT_Y0VY1U:
+                       vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
+                       set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       /* VSCTRL has the bits which sets the Video Pixel Format.
+        * When passing from a packed to planar format,
+        * if we write VSCTRL first, VVBASE and VUBASE would
+        * be zero if we would not set them here. (And then,
+        * the chips hangs and only a reset seems to fix it).
+        *
+        * If course, the values calculated here have no meaning
+        * for packed formats.
+        */
+       set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7;
+               set->U_offset = set->height * set->Y_stride;
+               set->V_offset = set->U_offset +
+                                               set->height * set->UV_stride;
+       vubase |= Vubase_Ubase_Adr(
+                       (0x60000 + set->mem_offset + set->U_offset)>>3);
+       vvbase |= Vvbase_Vbase_Adr(
+                       (0x60000 + set->mem_offset + set->V_offset)>>3);
+
+
+       vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB |
+               Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
+
+       if (set->enable)
+               vscadr |= VSCADR_STR_EN;
+
+
+       vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) |
+               Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y);
+
+       sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT));
+       sssize = Sssize_Sc_Width(set->scaled_width-1) |
+                       Sssize_Sc_Height(set->scaled_height-1);
+
+       spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
+                       SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
+                       FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH));
+       spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height)
+                                                       | SPOCTRL_VORDER_2TAP;
+
+       /* Bypass horiz/vert scaler when same size */
+       if (set->scaled_width == set->width)
+               spoctrl |= SPOCTRL_H_SC_BP;
+       if (set->scaled_height == set->height)
+               spoctrl |= SPOCTRL_V_SC_BP;
+
+       svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
+
+       shctrl = Shctrl_Hinitial(4<<11)
+                       | Shctrl_Hpitch((set->width<<11)/set->scaled_width);
+
+       /* Video plane registers */
+       write_reg(vsctrl, VSCTRL);
+       write_reg(vbbase, VBBASE);
+       write_reg(vscadr, VSCADR);
+       write_reg(vubase, VUBASE);
+       write_reg(vvbase, VVBASE);
+       write_reg(vsadr, VSADR);
+
+       /* Video scaler registers */
+       write_reg(sssize, SSSIZE);
+       write_reg(spoctrl, SPOCTRL);
+       write_reg(svctrl, SVCTRL);
+       write_reg(shctrl, SHCTRL);
+
+       /* RAPH: Using those coefficients, the scaled
+        * image is quite blurry. I dont know how
+        * to improve them ; The chip documentation
+        * was not helpful.. */
+       write_reg(0x21212121, VSCOEFF0);
+       write_reg(0x21212121, VSCOEFF1);
+       write_reg(0x21212121, VSCOEFF2);
+       write_reg(0x21212121, VSCOEFF3);
+       write_reg(0x21212121, VSCOEFF4);
+       write_reg(0x00000000, HSCOEFF0);
+       write_reg(0x00000000, HSCOEFF1);
+       write_reg(0x00000000, HSCOEFF2);
+       write_reg(0x03020201, HSCOEFF3);
+       write_reg(0x09070604, HSCOEFF4);
+       write_reg(0x0f0e0c0a, HSCOEFF5);
+       write_reg(0x15141211, HSCOEFF6);
+       write_reg(0x19181716, HSCOEFF7);
+       write_reg(0x00000019, HSCOEFF8);
+
+       /* Clock */
+       if (set->enable)
+               vovrclk |= 1;
+       else
+               vovrclk &= ~1;
+
+       write_reg(vovrclk, VOVRCLK);
+
+       return 0;
+}
+
+static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct mbxfb_overlaySetup setup;
+       int res;
+
+       if (cmd == MBXFB_IOCX_OVERLAY)
+       {
+               if (copy_from_user(&setup, (void __user*)arg,
+                                       sizeof(struct mbxfb_overlaySetup)))
+                       return -EFAULT;
+
+               res = mbxfb_setupOverlay(&setup);
+               if (res)
+                       return res;
+
+               if (copy_to_user((void __user*)arg, &setup,
+                                       sizeof(struct mbxfb_overlaySetup)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       return -EINVAL;
+}
+
 static struct fb_ops mbxfb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = mbxfb_check_var,
@@ -331,6 +526,7 @@ static struct fb_ops mbxfb_ops = {
        .fb_copyarea = cfb_copyarea,
        .fb_imageblit = cfb_imageblit,
        .fb_blank = mbxfb_blank,
+       .fb_ioctl = mbxfb_ioctl,
 };
 
 /*
@@ -339,36 +535,29 @@ static struct fb_ops mbxfb_ops = {
 */
 static void __devinit setup_memc(struct fb_info *fbi)
 {
-       struct mbxfb_info *mfbi = fbi->par;
        unsigned long tmp;
        int i;
 
        /* FIXME: use platfrom specific parameters */
        /* setup SDRAM controller */
-       writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
+       write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
                LMCFG_LMA_TS),
               LMCFG);
-       udelay(1000);
 
-       writel(LMPWR_MC_PWR_ACT, LMPWR);
-       udelay(1000);
+       write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
 
        /* setup SDRAM timings */
-       writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
+       write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
                Lmtim_Trc(9) | Lmtim_Tdpl(2)),
               LMTIM);
-       udelay(1000);
        /* setup SDRAM refresh rate */
-       writel(0xc2b, LMREFRESH);
-       udelay(1000);
+       write_reg_dly(0xc2b, LMREFRESH);
        /* setup SDRAM type parameters */
-       writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
+       write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
                LMTYPE_COLSZ_8),
               LMTYPE);
-       udelay(1000);
        /* enable memory controller */
-       writel(LMPWR_MC_PWR_ACT, LMPWR);
-       udelay(1000);
+       write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
 
        /* perform dummy reads */
        for ( i = 0; i < 16; i++ ) {
@@ -379,34 +568,30 @@ static void __devinit setup_memc(struct fb_info *fbi)
 static void enable_clocks(struct fb_info *fbi)
 {
        /* enable clocks */
-       writel(SYSCLKSRC_PLL_2, SYSCLKSRC);
-       udelay(1000);
-       writel(PIXCLKSRC_PLL_1, PIXCLKSRC);
-       udelay(1000);
-       writel(0x00000000, CLKSLEEP);
-       udelay(1000);
-       writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) |
+       write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
+       write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
+       write_reg_dly(0x00000000, CLKSLEEP);
+
+       /* PLL output = (Frefclk * M) / (N * 2^P )
+        *
+        * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
+        * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
+        * */
+       write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
                CORE_PLL_EN),
               COREPLL);
-       udelay(1000);
-       writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
+
+       write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
                DISP_PLL_EN),
               DISPPLL);
 
-       writel(0x00000000, VOVRCLK);
-       udelay(1000);
-       writel(PIXCLK_EN, PIXCLK);
-       udelay(1000);
-       writel(MEMCLK_EN, MEMCLK);
-       udelay(1000);
-       writel(0x00000006, M24CLK);
-       udelay(1000);
-       writel(0x00000006, MBXCLK);
-       udelay(1000);
-       writel(SDCLK_EN, SDCLK);
-       udelay(1000);
-       writel(0x00000001, PIXCLKDIV);
-       udelay(1000);
+       write_reg_dly(0x00000000, VOVRCLK);
+       write_reg_dly(PIXCLK_EN, PIXCLK);
+       write_reg_dly(MEMCLK_EN, MEMCLK);
+       write_reg_dly(0x00000006, M24CLK);
+       write_reg_dly(0x00000006, MBXCLK);
+       write_reg_dly(SDCLK_EN, SDCLK);
+       write_reg_dly(0x00000001, PIXCLKDIV);
 }
 
 static void __devinit setup_graphics(struct fb_info *fbi)
@@ -430,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi)
                break;
        }
 
-       writel(gsctrl, GSCTRL);
-       udelay(1000);
-       writel(0x00000000, GBBASE);
-       udelay(1000);
-       writel(0x00ffffff, GDRCTRL);
-       udelay(1000);
-       writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
-       udelay(1000);
-       writel(0x00000000, GPLUT);
-       udelay(1000);
+       write_reg_dly(gsctrl, GSCTRL);
+       write_reg_dly(0x00000000, GBBASE);
+       write_reg_dly(0x00ffffff, GDRCTRL);
+       write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
+       write_reg_dly(0x00000000, GPLUT);
 }
 
 static void __devinit setup_display(struct fb_info *fbi)
@@ -451,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi)
                dsctrl |= DSCTRL_HS_POL;
        if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
                dsctrl |= DSCTRL_VS_POL;
-       writel(dsctrl, DSCTRL);
-       udelay(1000);
-       writel(0xd0303010, DMCTRL);
-       udelay(1000);
-       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+       write_reg_dly(dsctrl, DSCTRL);
+       write_reg_dly(0xd0303010, DMCTRL);
+       write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
 }
 
 static void __devinit enable_controller(struct fb_info *fbi)
 {
-       writel(SYSRST_RST, SYSRST);
-       udelay(1000);
+       write_reg_dly(SYSRST_RST, SYSRST);
 
 
        enable_clocks(fbi);
@@ -478,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi)
 static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
 {
        /* make frame buffer memory enter self-refresh mode */
-       writel(LMPWR_MC_PWR_SRM, LMPWR);
+       write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
        while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
                ; /* empty statement */
 
        /* reset the device, since it's initial state is 'mostly sleeping' */
-       writel(SYSRST_RST, SYSRST);
+       write_reg_dly(SYSRST_RST, SYSRST);
        return 0;
 }
 
@@ -495,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev)
 /*     setup_graphics(fbi); */
 /*     setup_display(fbi); */
 
-       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+       write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
        return 0;
 }
 #else
@@ -520,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
 
        dev_dbg(dev, "mbxfb_probe\n");
 
+       pdata = dev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&dev->dev, "platform data is required\n");
+               return -EINVAL;
+       }
+
        fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
        if (fbi == NULL) {
                dev_err(&dev->dev, "framebuffer_alloc failed\n");
@@ -528,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
 
        mfbi = fbi->par;
        fbi->pseudo_palette = mfbi->pseudo_palette;
-       pdata = dev->dev.platform_data;
+
+
        if (pdata->probe)
                mfbi->platform_probe = pdata->probe;
        if (pdata->remove)
@@ -578,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
                goto err4;
        }
 
-       /* FIXME: get from platform */
        fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
-       fbi->screen_size = 8 * 1024 * 1024;     /* 8 Megs */
+       fbi->screen_size = pdata->memsize;
        fbi->fbops = &mbxfb_ops;
 
        fbi->var = mbxfb_default;
        fbi->fix = mbxfb_fix;
        fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
-       fbi->fix.smem_len = 8 * 1024 * 1024;
-       fbi->fix.line_length = 640 * 2;
+       fbi->fix.smem_len = pdata->memsize;
+       fbi->fix.line_length = mbxfb_default.xres_virtual *
+                                       mbxfb_default.bits_per_pixel / 8;
 
        ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
        if (ret < 0) {
@@ -636,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
 {
        struct fb_info *fbi = platform_get_drvdata(dev);
 
-       writel(SYSRST_RST, SYSRST);
-       udelay(1000);
+       write_reg_dly(SYSRST_RST, SYSRST);
 
        mbxfb_debugfs_remove(fbi);
 
index c226a8e..9a24fb0 100644 (file)
 #define GPLUT_LUTDATA  Fld(24,0)
 #define Gplut_Lutdata(x)       ((x) << FShft(GPLUT_LUTDATA))
 
+/* VSCTRL - Video Surface Control Register */
+#define VSCTRL_VPIXFMT         Fld(4,27)
+#define VSCTRL_VPIXFMT_YUV12   ((0x9) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_UY0VY1  ((0xc) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_VY0UY1  ((0xd) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0UY1V  ((0xe) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0VY1U  ((0xf) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_GAMMA_EN                (1 << 26)
+#define VSCTRL_CSC_EN          (1 << 25)
+#define VSCTRL_COSITED         (1 << 22)
+#define VSCTRL_VSWIDTH         Fld(11,11)
+#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
+                       (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
+#define VSCTRL_VSHEIGHT                Fld(11,0)
+#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
+                       (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
+
+/* VBBASE - Video Blending Base Register */
+#define VBBASE_GLALPHA         Fld(8,24)
+#define Vbbase_Glalpha(x)      ((x) << FShft(VBBASE_GLALPHA))
+
+#define VBBASE_COLKEY          Fld(24,0)
+#define Vbbase_Colkey(x)       ((x) << FShft(VBBASE_COLKEY))
+
+/* VCMSK - Video Color Key Mask Register */
+#define VCMSK_COLKEY_M         Fld(24,0)
+#define Vcmsk_colkey_m(x)      ((x) << FShft(VCMSK_COLKEY_M))
+
+/* VSCADR - Video Stream Control Rddress Register */
+#define VSCADR_STR_EN          (1 << 31)
+#define VSCADR_COLKEY_EN       (1 << 30)
+#define VSCADR_COLKEYSRC       (1 << 29)
+#define VSCADR_BLEND_M         Fld(2,27)
+#define VSCADR_BLEND_NONE      ((0x0) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_INV       ((0x1) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_GLOB      ((0x2) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_PIX       ((0x3) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_POS       Fld(2,24)
+#define VSCADR_BLEND_GFX       ((0x0) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_VID       ((0x1) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_CUR       ((0x2) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_VBASE_ADR       Fld(23,0)
+#define Vscadr_Vbase_Adr(x)    ((x) << FShft(VSCADR_VBASE_ADR))
+
+/* VUBASE - Video U Base Register */
+#define VUBASE_UVHALFSTR       (1 << 31)
+#define VUBASE_UBASE_ADR       Fld(24,0)
+#define Vubase_Ubase_Adr(x)    ((x) << FShft(VUBASE_UBASE_ADR))
+
+/* VVBASE - Video V Base Register */
+#define VVBASE_VBASE_ADR       Fld(24,0)
+#define Vvbase_Vbase_Adr(x)    ((x) << FShft(VVBASE_VBASE_ADR))
+
+/* VSADR - Video Stride Address Register */
+#define VSADR_SRCSTRIDE                Fld(10,22)
+#define Vsadr_Srcstride(x)     ((x) << FShft(VSADR_SRCSTRIDE))
+#define VSADR_XSTART           Fld(11,11)
+#define Vsadr_Xstart(x)                ((x) << FShft(VSADR_XSTART))
+#define VSADR_YSTART           Fld(11,0)
+#define Vsadr_Ystart(x)                ((x) << FShft(VSADR_YSTART))
+
 /* HCCTRL - Hardware Cursor Register fields */
 #define HCCTRL_CUR_EN  (1 << 31)
 #define HCCTRL_COLKEY_EN       (1 << 29)
 #define DMCTRL_BURSTLEN        Fld(6,0)
 #define Dmctrl_Burstlen(x)     ((x) << FShft(DMCTRL_BURSTLEN))
 
+/* DINTRS - Display Interrupt Status Register */
+#define DINTRS_CUR_OR_S                (1 << 18)
+#define DINTRS_STR2_OR_S       (1 << 17)
+#define DINTRS_STR1_OR_S       (1 << 16)
+#define DINTRS_CUR_UR_S                (1 << 6)
+#define DINTRS_STR2_UR_S       (1 << 5)
+#define DINTRS_STR1_UR_S       (1 << 4)
+#define DINTRS_VEVENT1_S       (1 << 3)
+#define DINTRS_VEVENT0_S       (1 << 2)
+#define DINTRS_HBLNK1_S                (1 << 1)
+#define DINTRS_HBLNK0_S                (1 << 0)
+
+/* DINTRE - Display Interrupt Enable Register */
+#define DINTRE_CUR_OR_EN       (1 << 18)
+#define DINTRE_STR2_OR_EN      (1 << 17)
+#define DINTRE_STR1_OR_EN      (1 << 16)
+#define DINTRE_CUR_UR_EN       (1 << 6)
+#define DINTRE_STR2_UR_EN      (1 << 5)
+#define DINTRE_STR1_UR_EN      (1 << 4)
+#define DINTRE_VEVENT1_EN      (1 << 3)
+#define DINTRE_VEVENT0_EN      (1 << 2)
+#define DINTRE_HBLNK1_EN       (1 << 1)
+#define DINTRE_HBLNK0_EN       (1 << 0)
+
 
 /* DLSTS - display load status register */
 #define DLSTS_RLD_ADONE        (1 << 23)
 #define DLLCTRL_RLD_ADRLN      Fld(8,24)
 #define Dllctrl_Rld_Adrln(x)   ((x) << FShft(DLLCTRL_RLD_ADRLN))
 
+/* CLIPCTRL - Clipping Control Register */
+#define CLIPCTRL_HSKIP         Fld(11,16)
+#define Clipctrl_Hskip         ((x) << FShft(CLIPCTRL_HSKIP))
+#define CLIPCTRL_VSKIP         Fld(11,0)
+#define Clipctrl_Vskip         ((x) << FShft(CLIPCTRL_VSKIP))
+
 /* SPOCTRL - Scale Pitch/Order Control Register */
 #define SPOCTRL_H_SC_BP                (1 << 31)
 #define SPOCTRL_V_SC_BP                (1 << 30)
 #define SPOCTRL_HV_SC_OR       (1 << 29)
 #define SPOCTRL_VS_UR_C                (1 << 27)
-#define SPOCTRL_VORDER Fld(2,16)
+#define SPOCTRL_VORDER         Fld(2,16)
 #define SPOCTRL_VORDER_1TAP    ((0x0) << FShft(SPOCTRL_VORDER))
 #define SPOCTRL_VORDER_2TAP    ((0x1) << FShft(SPOCTRL_VORDER))
 #define SPOCTRL_VORDER_4TAP    ((0x3) << FShft(SPOCTRL_VORDER))
-#define SPOCTRL_VPITCH Fld(16,0)
+#define SPOCTRL_VPITCH         Fld(16,0)
 #define Spoctrl_Vpitch(x)      ((x) << FShft(SPOCTRL_VPITCH))
 
+/* SVCTRL - Scale Vertical Control Register */
+#define SVCTRL_INITIAL1                Fld(16,16)
+#define Svctrl_Initial1(x)     ((x) << FShft(SVCTRL_INITIAL1))
+#define SVCTRL_INITIAL2                Fld(16,0)
+#define Svctrl_Initial2(x)     ((x) << FShft(SVCTRL_INITIAL2))
+
+/* SHCTRL - Scale Horizontal Control Register */
+#define SHCTRL_HINITIAL                Fld(16,16)
+#define Shctrl_Hinitial(x)     ((x) << FShft(SHCTRL_HINITIAL))
+#define SHCTRL_HDECIM          (1 << 15)
+#define SHCTRL_HPITCH          Fld(15,0)
+#define Shctrl_Hpitch(x)       ((x) << FShft(SHCTRL_HPITCH))
+
+/* SSSIZE - Scale Surface Size Register */
+#define SSSIZE_SC_WIDTH                Fld(11,16)
+#define Sssize_Sc_Width(x)     ((x) << FShft(SSSIZE_SC_WIDTH))
+#define SSSIZE_SC_HEIGHT       Fld(11,0)
+#define Sssize_Sc_Height(x)    ((x) << FShft(SSSIZE_SC_HEIGHT))
+
 #endif /* __REG_BITS_2700G_ */
index ad20be0..a7c63d8 100644 (file)
 #define HSCOEFF0       __REG_2700G(0x000021b4)
 #define HSCOEFF1       __REG_2700G(0x000021b8)
 #define HSCOEFF2       __REG_2700G(0x000021bc)
-#define HSCOEFF3       __REG_2700G(0x000021b0)
+#define HSCOEFF3       __REG_2700G(0x000021c0)
 #define HSCOEFF4       __REG_2700G(0x000021c4)
 #define HSCOEFF5       __REG_2700G(0x000021c8)
 #define HSCOEFF6       __REG_2700G(0x000021cc)
index d126790..5df41f6 100644 (file)
@@ -34,8 +34,6 @@ const char *global_mode_option;
      *  Standard video mode definitions (taken from XFree86)
      */
 
-#define DEFAULT_MODEDB_INDEX   0
-
 static const struct fb_videomode modedb[] = {
     {
        /* 640x400 @ 70 Hz, 31.5 kHz hsync */
@@ -505,8 +503,10 @@ int fb_find_mode(struct fb_var_screeninfo *var,
        db = modedb;
        dbsize = ARRAY_SIZE(modedb);
     }
+
     if (!default_mode)
-       default_mode = &modedb[DEFAULT_MODEDB_INDEX];
+       default_mode = &db[0];
+
     if (!default_bpp)
        default_bpp = 8;
 
index 59a6f5f..deaf820 100644 (file)
@@ -1932,7 +1932,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
        printk(KERN_DEBUG "--- Neo extended register dump ---\n");
        for (int w = 0; w < 0x85; w++)
                printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
-                      (void *) vga_rcrt(NULL, w);
+                      (void *) vga_rcrt(NULL, w));
        for (int w = 0; w < 0xC7; w++)
                printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
                       (void *) vga_rgfx(NULL, w));
index 4aefb8f..9efb8a3 100644 (file)
@@ -261,41 +261,6 @@ void NVResetGraphics(struct fb_info *info)
        NVDmaKickoff(par);
 }
 
-u8 byte_rev[256] = {
-       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-
 int nvidiafb_sync(struct fb_info *info)
 {
        struct nvidia_par *par = info->par;
index 19eef3a..442e853 100644 (file)
@@ -210,11 +210,8 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
                /* try to get from firmware */
                const u8 *e = fb_firmware_edid(info->device);
 
-               if (e != NULL) {
-                       edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-                       if (edid)
-                               memcpy(edid, e, EDID_LENGTH);
-               }
+               if (e != NULL)
+                       edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
        }
 
        *out_edid = edid;
index 4243d7f..e009d24 100644 (file)
 #define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
 
 #ifdef __LITTLE_ENDIAN
+
+#include <linux/bitrev.h>
+
 #define reverse_order(l)        \
 do {                            \
        u8 *a = (u8 *)(l);      \
-       *a = byte_rev[*a], a++; \
-       *a = byte_rev[*a], a++; \
-       *a = byte_rev[*a], a++; \
-       *a = byte_rev[*a];      \
+       a[0] = bitrev8(a[0]);   \
+       a[1] = bitrev8(a[1]);   \
+       a[2] = bitrev8(a[2]);   \
+       a[3] = bitrev8(a[3]);   \
 } while(0)
 #else
 #define reverse_order(l) do { } while(0)
index d9af88c..181875f 100644 (file)
@@ -72,10 +72,9 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
                }
        }
        if (pedid) {
-               *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+               *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
                if (*out_edid == NULL)
                        return -1;
-               memcpy(*out_edid, pedid, EDID_LENGTH);
                printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
                return 0;
        }
index 8612710..43058d0 100644 (file)
@@ -62,7 +62,6 @@ extern void nvidiafb_fillrect(struct fb_info *info,
 extern void nvidiafb_imageblit(struct fb_info *info,
                               const struct fb_image *image);
 extern int nvidiafb_sync(struct fb_info *info);
-extern u8 byte_rev[256];
 
 /* in nv_backlight.h */
 #ifdef CONFIG_FB_NVIDIA_BACKLIGHT
index 9a40bbe..9576a55 100644 (file)
@@ -402,6 +402,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
        fb_alloc_cmap(&info->cmap, 256, 0);
 
        if (register_framebuffer(info) < 0) {
+               iounmap(par->cmap_adr);
+               par->cmap_adr = NULL;
+               iounmap(info->screen_base);
                kfree(info);
                release_mem_region(res_start, res_size);
                return;
index cb26c6d..2338716 100644 (file)
@@ -627,6 +627,9 @@ static int __devinit platinumfb_probe(struct of_device* odev,
        
        rc = platinum_init_fb(info);
        if (rc != 0) {
+               iounmap(pinfo->frame_buffer);
+               iounmap(pinfo->platinum_regs);
+               iounmap(pinfo->cmap_regs);
                dev_set_drvdata(&odev->dev, NULL);
                framebuffer_release(info);
        }
index 73e2d7d..a06a064 100644 (file)
@@ -186,7 +186,7 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info)
 static void __init pmagbbfb_osc_setup(struct fb_info *info)
 {
        static unsigned int pmagbbfb_freqs[] __initdata = {
-               130808, 119843, 104000, 92980, 74367, 72800,
+               130808, 119843, 104000, 92980, 74370, 72800,
                69197, 66000, 65000, 50350, 36000, 32000, 25175
        };
        struct pmagbbfb_par *par = info->par;
index c7bc809..a93618b 100644 (file)
@@ -905,6 +905,15 @@ static int __init pvr2fb_dc_init(void)
 
 static void pvr2fb_dc_exit(void)
 {
+       if (fb_info->screen_base) {
+               iounmap(fb_info->screen_base);
+               fb_info->screen_base = NULL;
+       }
+       if (currentpar->mmio_base) {
+               iounmap((void *)currentpar->mmio_base);
+               currentpar->mmio_base = 0;
+       }
+
        free_irq(HW_EVENT_VSYNC, 0);
 #ifdef CONFIG_SH_DMA
        free_dma(pvr2dma);
@@ -946,6 +955,15 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev,
 
 static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev)
 {
+       if (fb_info->screen_base) {
+               iounmap(fb_info->screen_base);
+               fb_info->screen_base = NULL;
+       }
+       if (currentpar->mmio_base) {
+               iounmap((void *)currentpar->mmio_base);
+               currentpar->mmio_base = 0;
+       }
+
        pci_release_regions(pdev);
 }
 
index 8a8ae55..38eb0b6 100644 (file)
@@ -964,9 +964,10 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
  * Our LCD controller task (which is called when we blank or unblank)
  * via keventd.
  */
-static void pxafb_task(void *dummy)
+static void pxafb_task(struct work_struct *work)
 {
-       struct pxafb_info *fbi = dummy;
+       struct pxafb_info *fbi =
+               container_of(work, struct pxafb_info, task);
        u_int state = xchg(&fbi->task_state, -1);
 
        set_ctrlr_state(fbi, state);
@@ -1159,7 +1160,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
        }
 
        init_waitqueue_head(&fbi->ctrlr_wait);
-       INIT_WORK(&fbi->task, pxafb_task, fbi);
+       INIT_WORK(&fbi->task, pxafb_task);
        init_MUTEX(&fbi->ctrlr_sem);
 
        return fbi;
index cf41ff1..bc7ffc8 100644 (file)
@@ -1423,8 +1423,10 @@ int __init retz3fb_init(void)
 
                do_install_cmap(0, fb_info);
 
-               if (register_framebuffer(fb_info) < 0)
+               if (register_framebuffer(fb_info) < 0) {
+                       iounmap(zinfo->base);
                        return -EINVAL;
+               }
 
                printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
                       "video memory\n", fb_info->node,
index a433cc7..345e8b1 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/backlight.h>
+#include <linux/bitrev.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
@@ -521,48 +522,13 @@ static inline unsigned char MISCin(struct riva_par *par)
        return (VGA_RD08(par->riva.PVIO, 0x3cc));
 }
 
-static u8 byte_rev[256] = {
-       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-
 static inline void reverse_order(u32 *l)
 {
        u8 *a = (u8 *)l;
-       *a = byte_rev[*a], a++;
-       *a = byte_rev[*a], a++;
-       *a = byte_rev[*a], a++;
-       *a = byte_rev[*a];
+       a[0] = bitrev8(a[0]);
+       a[1] = bitrev8(a[1]);
+       a[2] = bitrev8(a[2]);
+       a[3] = bitrev8(a[3]);
 }
 
 /* ------------------------------------------------------------------------- *
@@ -774,11 +740,12 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
  * CALLED FROM:
  * rivafb_set_par()
  */
-static void riva_load_video_mode(struct fb_info *info)
+static int riva_load_video_mode(struct fb_info *info)
 {
        int bpp, width, hDisplaySize, hDisplay, hStart,
            hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
        int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
+       int rc;
        struct riva_par *par = info->par;
        struct riva_regs newmode;
        
@@ -884,8 +851,10 @@ static void riva_load_video_mode(struct fb_info *info)
        else
                newmode.misc_output |= 0x80;    
 
-       par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
-                                 hDisplaySize, height, dotClock);
+       rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width,
+                         hDisplaySize, height, dotClock);
+       if (rc)
+               goto out;
 
        newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
                0xfff000ff;
@@ -917,8 +886,12 @@ static void riva_load_video_mode(struct fb_info *info)
        par->current_state = newmode;
        riva_load_state(par, &par->current_state);
        par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
+
+out:
        rivafb_blank(FB_BLANK_UNBLANK, info);
        NVTRACE_LEAVE();
+
+       return rc;
 }
 
 static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
@@ -1286,12 +1259,15 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 static int rivafb_set_par(struct fb_info *info)
 {
        struct riva_par *par = info->par;
+       int rc = 0;
 
        NVTRACE_ENTER();
        /* vgaHWunlock() + riva unlock (0x7F) */
        CRTCout(par, 0x11, 0xFF);
        par->riva.LockUnlock(&par->riva, 0);
-       riva_load_video_mode(info);
+       rc = riva_load_video_mode(info);
+       if (rc)
+               goto out;
        if(!(info->flags & FBINFO_HWACCEL_DISABLED))
                riva_setup_accel(info);
        
@@ -1304,8 +1280,10 @@ static int rivafb_set_par(struct fb_info *info)
                info->pixmap.scan_align = 1;
        else
                info->pixmap.scan_align = 4;
+
+out:
        NVTRACE_LEAVE();
-       return 0;
+       return rc;
 }
 
 /**
index b6f8690..e0b8c52 100644 (file)
@@ -1227,7 +1227,7 @@ static int CalcVClock
  * Calculate extended mode parameters (SVGA) and save in a 
  * mode state structure.
  */
-static void CalcStateExt
+int CalcStateExt
 (
     RIVA_HW_INST  *chip,
     RIVA_HW_STATE *state,
@@ -1249,7 +1249,8 @@ static void CalcStateExt
      * Extended RIVA registers.
      */
     pixelDepth = (bpp + 1)/8;
-    CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
+    if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip))
+       return -EINVAL;
 
     switch (chip->Architecture)
     {
@@ -1327,6 +1328,8 @@ static void CalcStateExt
     state->pitch1   =
     state->pitch2   =
     state->pitch3   = pixelDepth * width;
+
+    return 0;
 }
 /*
  * Load fixed function state and pre-calculated/stored state.
@@ -2026,7 +2029,6 @@ static void nv3GetConfig
      */
     chip->Busy            = nv3Busy;
     chip->ShowHideCursor  = ShowHideCursor;
-    chip->CalcStateExt    = CalcStateExt;
     chip->LoadStateExt    = LoadStateExt;
     chip->UnloadStateExt  = UnloadStateExt;
     chip->SetStartAddress = SetStartAddress3;
@@ -2084,7 +2086,6 @@ static void nv4GetConfig
      */
     chip->Busy            = nv4Busy;
     chip->ShowHideCursor  = ShowHideCursor;
-    chip->CalcStateExt    = CalcStateExt;
     chip->LoadStateExt    = LoadStateExt;
     chip->UnloadStateExt  = UnloadStateExt;
     chip->SetStartAddress = SetStartAddress;
@@ -2186,7 +2187,6 @@ static void nv10GetConfig
      */
     chip->Busy            = nv10Busy;
     chip->ShowHideCursor  = ShowHideCursor;
-    chip->CalcStateExt    = CalcStateExt;
     chip->LoadStateExt    = LoadStateExt;
     chip->UnloadStateExt  = UnloadStateExt;
     chip->SetStartAddress = SetStartAddress;
index a1e71a6..c2769f7 100644 (file)
@@ -463,7 +463,6 @@ typedef struct _riva_hw_inst
      * Common chip functions.
      */
     int  (*Busy)(struct _riva_hw_inst *);
-    void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int);
     void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
     void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
     void (*SetStartAddress)(struct _riva_hw_inst *,U032);
@@ -528,6 +527,22 @@ typedef struct _riva_hw_state
     U032 pitch2;
     U032 pitch3;
 } RIVA_HW_STATE;
+
+/*
+ * function prototypes
+ */
+
+extern int CalcStateExt
+(
+    RIVA_HW_INST  *chip,
+    RIVA_HW_STATE *state,
+    int            bpp,
+    int            width,
+    int            hDisplaySize,
+    int            height,
+    int            dotClock
+);
+
 /*
  * External routines.
  */
index 5940734..ccef56d 100644 (file)
@@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
        saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
        saddr2>>= 1;
 
-       saddr3 =  S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+       saddr3 =  S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff);
 
        dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
        dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
@@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
                var->bits_per_pixel = fbi->mach_info->bpp.min;
 
        /* set r/g/b positions */
+       switch (var->bits_per_pixel) {
+               case 1:
+               case 2:
+               case 4:
+                       var->red.offset         = 0;
+                       var->red.length         = var->bits_per_pixel;
+                       var->green              = var->red;
+                       var->blue               = var->red;
+                       var->transp.offset      = 0;
+                       var->transp.length      = 0;
+                       break;
+               case 8:
+                       if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) {
+                               /* 8 bpp 332 */
+                               var->red.length         = 3;
+                               var->red.offset         = 5;
+                               var->green.length       = 3;
+                               var->green.offset       = 2;
+                               var->blue.length        = 2;
+                               var->blue.offset        = 0;
+                               var->transp.length      = 0;
+                       } else {
+                               var->red.offset         = 0;
+                               var->red.length         = var->bits_per_pixel;
+                               var->green              = var->red;
+                               var->blue               = var->red;
+                               var->transp.offset      = 0;
+                               var->transp.length      = 0;
+                       }
+                       break;
+               case 12:
+                       /* 12 bpp 444 */
+                       var->red.length         = 4;
+                       var->red.offset         = 8;
+                       var->green.length       = 4;
+                       var->green.offset       = 4;
+                       var->blue.length        = 4;
+                       var->blue.offset        = 0;
+                       var->transp.length      = 0;
+                       break;
+
+               default:
+               case 16:
+                       if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) {
+                               /* 16 bpp, 565 format */
+                               var->red.offset         = 11;
+                               var->green.offset       = 5;
+                               var->blue.offset        = 0;
+                               var->red.length         = 5;
+                               var->green.length       = 6;
+                               var->blue.length        = 5;
+                               var->transp.length      = 0;
+                       } else {
+                               /* 16 bpp, 5551 format */
+                               var->red.offset         = 11;
+                               var->green.offset       = 6;
+                               var->blue.offset        = 1;
+                               var->red.length         = 5;
+                               var->green.length       = 5;
+                               var->blue.length        = 5;
+                               var->transp.length      = 0;
+                       }
+                       break;
+               case 24:
+                       /* 24 bpp 888 */
+                       var->red.length         = 8;
+                       var->red.offset         = 16;
+                       var->green.length       = 8;
+                       var->green.offset       = 8;
+                       var->blue.length        = 8;
+                       var->blue.offset        = 0;
+                       var->transp.length      = 0;
+                       break;
 
-       if (var->bits_per_pixel == 16) {
-               var->red.offset         = 11;
-               var->green.offset       = 5;
-               var->blue.offset        = 0;
-               var->red.length         = 5;
-               var->green.length       = 6;
-               var->blue.length        = 5;
-               var->transp.length      = 0;
-       } else {
-               var->red.length         = var->bits_per_pixel;
-               var->red.offset         = 0;
-               var->green.length       = var->bits_per_pixel;
-               var->green.offset       = 0;
-               var->blue.length        = var->bits_per_pixel;
-               var->blue.offset        = 0;
-               var->transp.length      = 0;
-       }
 
+       }
        return 0;
 }
 
+
 /* s3c2410fb_activate_var
  *
  * activate (set) the controller from the given framebuffer
@@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
 static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
                                   struct fb_var_screeninfo *var)
 {
+       int hs;
+
        fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+       fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
 
        dprintk("%s: var->xres  = %d\n", __FUNCTION__, var->xres);
        dprintk("%s: var->yres  = %d\n", __FUNCTION__, var->yres);
        dprintk("%s: var->bpp   = %d\n", __FUNCTION__, var->bits_per_pixel);
 
-       switch (var->bits_per_pixel) {
-       case 1:
-               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
-               break;
-       case 2:
-               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
-               break;
-       case 4:
-               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
-               break;
-       case 8:
-               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
-               break;
-       case 16:
-               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
-               break;
-       }
+       fbi->regs.lcdcon1 |= fbi->mach_info->type;
+
+       if (fbi->mach_info->type == S3C2410_LCDCON1_TFT)
+               switch (var->bits_per_pixel) {
+               case 1:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+                       break;
+               case 2:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+                       break;
+               case 4:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+                       break;
+               case 8:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+                       break;
+               case 16:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+                       break;
+
+               default:
+                       /* invalid pixel depth */
+                       dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
+               }
+       else
+               switch (var->bits_per_pixel) {
+               case 1:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
+                       break;
+               case 2:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
+                       break;
+               case 4:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
+                       break;
+               case 8:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
+                       break;
+               case 12:
+                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
+                       break;
+
+               default:
+                       /* invalid pixel depth */
+                       dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
+               }
 
        /* check to see if we need to update sync/borders */
 
@@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
        fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
        fbi->regs.lcdcon2 |=  S3C2410_LCDCON2_LINEVAL(var->yres - 1);
 
+       switch(fbi->mach_info->type) {
+               case S3C2410_LCDCON1_DSCAN4:
+               case S3C2410_LCDCON1_STN8:
+                       hs = var->xres / 8;
+                       break;
+               case S3C2410_LCDCON1_STN4:
+                       hs = var->xres / 4;
+                       break;
+               default:
+               case S3C2410_LCDCON1_TFT:
+                       hs = var->xres;
+                       break;
+
+       }
+
+       /* Special cases : STN color displays */
+       if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \
+         || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) {
+               hs = hs * 3;
+       }
+
+
        fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
-       fbi->regs.lcdcon3 |=  S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+       fbi->regs.lcdcon3 |=  S3C2410_LCDCON3_HOZVAL(hs - 1);
 
        if (var->pixclock > 0) {
                int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
 
-               clkdiv = (clkdiv / 2) -1;
-               if (clkdiv < 0)
-                       clkdiv = 0;
+               if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) {
+                       clkdiv = (clkdiv / 2) -1;
+                       if (clkdiv < 0)
+                               clkdiv = 0;
+               }
+               else {
+                       clkdiv = (clkdiv / 2);
+                       if (clkdiv < 2)
+                               clkdiv = 2;
+               }
 
                fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
                fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);
@@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info)
        struct s3c2410fb_info *fbi = info->par;
        struct fb_var_screeninfo *var = &info->var;
 
-       if (var->bits_per_pixel == 16)
-               fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
-       else
-               fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+       switch (var->bits_per_pixel)
+       {
+               case 16:
+                       fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
+                       break;
+               case 1:
+                        fbi->fb->fix.visual = FB_VISUAL_MONO01;
+                        break;
+               default:
+                        fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+                        break;
+       }
 
        fbi->fb->fix.line_length     = (var->width*var->bits_per_pixel)/8;
 
index 3f94223..cef5bf5 100644 (file)
@@ -227,11 +227,8 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
                /* try to get from firmware */
                const u8 *e = fb_firmware_edid(info->device);
 
-               if (e) {
-                       edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-                       if (edid)
-                               memcpy(edid, e, EDID_LENGTH);
-               }
+               if (e)
+                       edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
        }
 
        *out_edid = edid;
index f13fadd..47e1896 100644 (file)
@@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 void
 SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
 {
-   unsigned int i, j;
-
-   for(i = 0; i < delaytime; i++) {
-      j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
-   }
+   while (delaytime-- > 0)
+      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
 }
 
 #if defined(SIS300) || defined(SIS315H)
index 3e16e2d..69f3b26 100644 (file)
@@ -1291,6 +1291,7 @@ out_err3:
 out_err2:
        release_mem_region(fix->smem_start, fix->smem_len);
 out_err1:
+       iounmap(info->screen_base);
        fb_dealloc_cmap(&info->cmap);
 out_err0:
        kfree(fb);
@@ -1364,6 +1365,8 @@ stifb_cleanup(void)
                        unregister_framebuffer(sti->info);
                        release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
                        release_mem_region(info->fix.smem_start, info->fix.smem_len);
+                               if (info->screen_base)
+                                       iounmap(info->screen_base);
                        fb_dealloc_cmap(&info->cmap);
                        kfree(info); 
                }
index 94fde62..4b88fab 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/selection.h>
+#include <linux/bitrev.h>
 #include <asm/io.h>
 #include <video/tgafb.h>
 
@@ -517,41 +518,6 @@ tgafb_blank(int blank, struct fb_info *info)
 static void
 tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-       static unsigned char const bitrev[256] = {
-               0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-               0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-               0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-               0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-               0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-               0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-               0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-               0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-               0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-               0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-               0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-               0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-               0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-               0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-               0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-               0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-               0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-               0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-               0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-               0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-               0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-               0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-               0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-               0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-               0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-               0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-               0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-               0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-               0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-               0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-               0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-               0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-       };
-
        struct tga_par *par = (struct tga_par *) info->par;
        u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
        unsigned long rincr, line_length, shift, pos, is8bpp;
@@ -649,7 +615,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                        /* The image data is bit big endian; we need
                           little endian.  */
                        for (j = 0; j < bwidth; ++j)
-                               mask |= bitrev[data[j]] << (j * 8);
+                               mask |= bitrev8(data[j]) << (j * 8);
 
                        __raw_writel(mask << shift, fb_base + pos);
 
@@ -676,10 +642,10 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                for (i = 0; i < height; ++i) {
                        for (j = 0; j < bwidth; j += 4) {
                                u32 mask = 0;
-                               mask |= bitrev[data[j+0]] << (0 * 8);
-                               mask |= bitrev[data[j+1]] << (1 * 8);
-                               mask |= bitrev[data[j+2]] << (2 * 8);
-                               mask |= bitrev[data[j+3]] << (3 * 8);
+                               mask |= bitrev8(data[j+0]) << (0 * 8);
+                               mask |= bitrev8(data[j+1]) << (1 * 8);
+                               mask |= bitrev8(data[j+2]) << (2 * 8);
+                               mask |= bitrev8(data[j+3]) << (3 * 8);
                                __raw_writel(mask, fb_base + pos + j*bincr);
                        }
                        pos += line_length;
@@ -699,7 +665,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                        for (i = 0; i < height; ++i) {
                                u32 mask = 0;
                                for (j = 0; j < bwidth; ++j)
-                                       mask |= bitrev[data[j]] << (j * 8);
+                                       mask |= bitrev8(data[j]) << (j * 8);
                                __raw_writel(mask, fb_base + pos);
                                pos += line_length;
                                data += rincr;
@@ -726,8 +692,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                for (i = 0; i < height; ++i) {
                        for (j = 0; j < bwidth; j += 2) {
                                u32 mask = 0;
-                               mask |= bitrev[data[j+0]] << (0 * 8);
-                               mask |= bitrev[data[j+1]] << (1 * 8);
+                               mask |= bitrev8(data[j+0]) << (0 * 8);
+                               mask |= bitrev8(data[j+1]) << (1 * 8);
                                mask <<= shift;
                                __raw_writel(mask, fb_base + pos + j*bincr);
                        }
@@ -746,9 +712,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                        bwidth = (width & 15) > 8;
 
                        for (i = 0; i < height; ++i) {
-                               u32 mask = bitrev[data[0]];
+                               u32 mask = bitrev8(data[0]);
                                if (bwidth)
-                                       mask |= bitrev[data[1]] << 8;
+                                       mask |= bitrev8(data[1]) << 8;
                                mask <<= shift;
                                __raw_writel(mask, fb_base + pos);
                                pos += line_length;
@@ -1473,6 +1439,8 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
  err1:
+       if (mem_base)
+               iounmap(mem_base);
        release_mem_region(bar0_start, bar0_len);
  err0:
        kfree(all);
index 14175cd..55e8aa4 100644 (file)
@@ -1130,7 +1130,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
        
        if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
                debug("request_mem_region failed!\n");
-               return -1;
+               err = -1;
+               goto out_unmap;
        }
 
        fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
@@ -1139,7 +1140,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
        if (!fb_info.screen_base) {
                release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
                debug("ioremap failed\n");
-               return -1;
+               err = -1;
+               goto out_unmap;
        }
 
        output("%s board found\n", pci_name(dev));
@@ -1162,8 +1164,10 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
 #endif
        fb_info.pseudo_palette = pseudo_pal;
 
-       if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp))
-               return -EINVAL;
+       if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) {
+               err = -EINVAL;
+               goto out_unmap;
+       }
        fb_alloc_cmap(&fb_info.cmap,256,0);
        if (defaultaccel && acc)
                default_var.accel_flags |= FB_ACCELF_TEXT;
@@ -1174,12 +1178,20 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
        fb_info.device = &dev->dev;
        if (register_framebuffer(&fb_info) < 0) {
                printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_unmap;
        }
        output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
           fb_info.node, fb_info.fix.id,default_var.xres,
           default_var.yres,default_var.bits_per_pixel);
        return 0;
+
+out_unmap:
+       if (default_par.io_virt)
+               iounmap(default_par.io_virt);
+       if (fb_info.screen_base)
+               iounmap(fb_info.screen_base);
+       return err;
 }
 
 static void __devexit trident_pci_remove(struct pci_dev * dev)
index 2196448..e16322d 100644 (file)
@@ -47,17 +47,16 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = {
        .accel  = FB_ACCEL_NONE,
 };
 
-static int             inverse   = 0;
-static int             mtrr      = 0; /* disable mtrr */
-static int            vram_remap __initdata = 0; /* Set amount of memory to be used */
-static int            vram_total __initdata = 0; /* Set total amount of memory */
-static int             pmi_setpal = 1; /* pmi for palette changes ??? */
-static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
-static unsigned short  *pmi_base  = NULL;
-static void            (*pmi_start)(void);
-static void            (*pmi_pal)(void);
-static int             depth;
-static int             vga_compat;
+static int   inverse    __read_mostly;
+static int   mtrr       __read_mostly;         /* disable mtrr */
+static int   vram_remap __initdata;            /* Set amount of memory to be used */
+static int   vram_total __initdata;            /* Set total amount of memory */
+static int   pmi_setpal __read_mostly = 1;     /* pmi for palette changes ??? */
+static int   ypan       __read_mostly;         /* 0..nothing, 1..ypan, 2..ywrap */
+static void  (*pmi_start)(void) __read_mostly;
+static void  (*pmi_pal)  (void) __read_mostly;
+static int   depth      __read_mostly;
+static int   vga_compat __read_mostly;
 /* --------------------------------------------------------------------- */
 
 static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -312,6 +311,7 @@ static int __init vesafb_probe(struct platform_device *dev)
                ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
 
        if (ypan || pmi_setpal) {
+               unsigned short *pmi_base;
                pmi_base  = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
                pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
                pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
@@ -456,6 +456,8 @@ static int __init vesafb_probe(struct platform_device *dev)
               info->node, info->fix.id);
        return 0;
 err:
+       if (info->screen_base)
+               iounmap(info->screen_base);
        framebuffer_release(info);
        release_mem_region(vesafb_fix.smem_start, size_total);
        return err;
index 43d5a6d..6aff63d 100644 (file)
@@ -264,7 +264,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
                               const struct fb_info *info,
                               int mul, int div)
 {
-       static struct {
+       static const struct {
                u32 pixclock;
                u8  misc;
                u8  seq_clock_mode;
@@ -652,7 +652,7 @@ static int vga16fb_set_par(struct fb_info *info)
 
 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
-       static unsigned char map[] = { 000, 001, 010, 011 };
+       static const unsigned char map[] = { 000, 001, 010, 011 };
        int val;
        
        if (regno >= 16)
@@ -1139,23 +1139,19 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
        }
 }
 
-#ifdef __LITTLE_ENDIAN
-static unsigned int transl_l[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_h[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
-#else
-#ifdef __BIG_ENDIAN
-static unsigned int transl_h[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_l[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
+#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
+#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
+                        0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
+
+#if defined(__LITTLE_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_LOW;
+static const u16 transl_h[] = TRANS_MASK_HIGH;
+#elif defined(__BIG_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_HIGH;
+static const u16 transl_h[] = TRANS_MASK_LOW;
 #else
 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
 #endif
-#endif
 
 static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
 {
index 6437895..b9fb6fb 100644 (file)
@@ -1799,7 +1799,7 @@ int __init virgefb_init(void)
                #warning release resources
                printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
                DPRINTK("EXIT\n");
-               return -EINVAL;
+               goto out_unmap;
        }
 
        printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
@@ -1809,6 +1809,21 @@ int __init virgefb_init(void)
 
        DPRINTK("EXIT\n");
        return 0;
+
+out_unmap:
+       if (board_addr >= 0x01000000) {
+               if (v_ram)
+                       iounmap((void*)v_ram);
+               if (vgaio_regs)
+                       iounmap(vgaio_regs);
+               if (mmio_regs)
+                       iounmap(mmio_regs);
+               if (vcode_switch_base)
+                       iounmap((void*)vcode_switch_base);
+               v_ram = vcode_switch_base = 0;
+               vgaio_regs = mmio_regs = NULL;
+       }
+       return -EINVAL;
 }
 
 
index 93845a2..6bb0b54 100644 (file)
@@ -2,10 +2,6 @@
 # Makefile for the Dallas's 1-wire bus.
 #
 
-ifeq ($(CONFIG_W1_DS2433_CRC), y)
-EXTRA_CFLAGS   += -DCONFIG_W1_F23_CRC
-endif
-
 obj-$(CONFIG_W1)       += wire.o
 wire-objs              := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
 
index 70e21e2..725dcfd 100644 (file)
@@ -2,10 +2,6 @@
 # Makefile for the Dallas's 1-wire slaves.
 #
 
-ifeq ($(CONFIG_W1_SLAVE_DS2433_CRC), y)
-EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC
-endif
-
 obj-$(CONFIG_W1_SLAVE_THERM)   += w1_therm.o
 obj-$(CONFIG_W1_SLAVE_SMEM)    += w1_smem.o
 obj-$(CONFIG_W1_SLAVE_DS2433)  += w1_ds2433.o
index 2ac238f..8ea17a5 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/device.h>
 #include <linux/types.h>
 #include <linux/delay.h>
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
 #include <linux/crc16.h>
 
 #define CRC16_INIT             0
@@ -62,7 +62,7 @@ static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size)
        return count;
 }
 
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
 static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
                                int block)
 {
@@ -89,13 +89,13 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
 
        return 0;
 }
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
 static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
                               size_t count)
 {
        struct w1_slave *sl = kobj_to_w1_slave(kobj);
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
        struct w1_f23_data *data = sl->family_data;
        int i, min_page, max_page;
 #else
@@ -107,7 +107,7 @@ static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
 
        mutex_lock(&sl->master->mutex);
 
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
 
        min_page = (off >> W1_PAGE_BITS);
        max_page = (off + count - 1) >> W1_PAGE_BITS;
@@ -119,7 +119,7 @@ static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
        }
        memcpy(buf, &data->memory[off], count);
 
-#else  /* CONFIG_W1_F23_CRC */
+#else  /* CONFIG_W1_SLAVE_DS2433_CRC */
 
        /* read directly from the EEPROM */
        if (w1_reset_select_slave(sl)) {
@@ -133,7 +133,7 @@ static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
        w1_write_block(sl->master, wrbuf, 3);
        w1_read_block(sl->master, buf, count);
 
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
 out_up:
        mutex_unlock(&sl->master->mutex);
@@ -208,7 +208,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
        if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
                return 0;
 
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
        /* can only write full blocks in cached mode */
        if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
                dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
@@ -223,7 +223,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
                        return -EINVAL;
                }
        }
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
        mutex_lock(&sl->master->mutex);
 
@@ -262,7 +262,7 @@ static struct bin_attribute w1_f23_bin_attr = {
 static int w1_f23_add_slave(struct w1_slave *sl)
 {
        int err;
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
        struct w1_f23_data *data;
 
        data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
@@ -271,24 +271,24 @@ static int w1_f23_add_slave(struct w1_slave *sl)
        memset(data, 0, sizeof(struct w1_f23_data));
        sl->family_data = data;
 
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
        err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
 
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
        if (err)
                kfree(data);
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
        return err;
 }
 
 static void w1_f23_remove_slave(struct w1_slave *sl)
 {
-#ifdef CONFIG_W1_F23_CRC
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
        kfree(sl->family_data);
        sl->family_data = NULL;
-#endif /* CONFIG_W1_F23_CRC */
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
        sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
 }
 
index de3e979..63c0724 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/atomic.h>
 
index 7aa2d3d..60b05bc 100644 (file)
@@ -47,7 +47,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
 static ssize_t
 proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       struct inode *ino = file->f_dentry->d_inode;
+       struct inode *ino = file->f_path.dentry->d_inode;
        struct proc_dir_entry *dp = PDE(ino);
        struct zorro_dev *z = dp->data;
        struct ConfigDev cd;
index 90a79c7..944273c 100644 (file)
@@ -110,8 +110,8 @@ struct v9fs_mux_rpc {
 };
 
 static int v9fs_poll_proc(void *);
-static void v9fs_read_work(void *);
-static void v9fs_write_work(void *);
+static void v9fs_read_work(struct work_struct *work);
+static void v9fs_write_work(struct work_struct *work);
 static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
                          poll_table * p);
 static u16 v9fs_mux_get_tag(struct v9fs_mux_data *);
@@ -297,8 +297,8 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
        m->rbuf = NULL;
        m->wpos = m->wsize = 0;
        m->wbuf = NULL;
-       INIT_WORK(&m->rq, v9fs_read_work, m);
-       INIT_WORK(&m->wq, v9fs_write_work, m);
+       INIT_WORK(&m->rq, v9fs_read_work);
+       INIT_WORK(&m->wq, v9fs_write_work);
        m->wsched = 0;
        memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
        m->poll_task = NULL;
@@ -458,13 +458,13 @@ static int v9fs_poll_proc(void *a)
 /**
  * v9fs_write_work - called when a transport can send some data
  */
-static void v9fs_write_work(void *a)
+static void v9fs_write_work(struct work_struct *work)
 {
        int n, err;
        struct v9fs_mux_data *m;
        struct v9fs_req *req;
 
-       m = a;
+       m = container_of(work, struct v9fs_mux_data, wq);
 
        if (m->err < 0) {
                clear_bit(Wworksched, &m->wsched);
@@ -564,7 +564,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
 /**
  * v9fs_read_work - called when there is some data to be read from a transport
  */
-static void v9fs_read_work(void *a)
+static void v9fs_read_work(struct work_struct *work)
 {
        int n, err;
        struct v9fs_mux_data *m;
@@ -572,7 +572,7 @@ static void v9fs_read_work(void *a)
        struct v9fs_fcall *rcall;
        char *rbuf;
 
-       m = a;
+       m = container_of(work, struct v9fs_mux_data, rq);
 
        if (m->err < 0)
                return;
index 9dfd259..cc24abf 100644 (file)
@@ -54,7 +54,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
        int retval = -EIO;
        loff_t offset = page_offset(page);
        int count = PAGE_CACHE_SIZE;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
        int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
        struct v9fs_fid *v9f = filp->private_data;
index 905c882..3129688 100644 (file)
@@ -71,7 +71,7 @@ static inline int dt_type(struct v9fs_stat *mistat)
 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        struct v9fs_fcall *fcall = NULL;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
        struct v9fs_fid *file = filp->private_data;
        unsigned int i, n, s;
@@ -80,7 +80,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct v9fs_stat stat;
        int over = 0;
 
-       dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
+       dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
 
        fid = file->fid;
 
index 79e6f9c..e86a071 100644 (file)
@@ -60,7 +60,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
        dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
 
-       vfid = v9fs_fid_lookup(file->f_dentry);
+       vfid = v9fs_fid_lookup(file->f_path.dentry);
        if (!vfid) {
                dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
                return -EBADF;
@@ -133,7 +133,7 @@ free_fcall:
 static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
        int res = 0;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
 
@@ -161,7 +161,7 @@ static ssize_t
 v9fs_file_read(struct file *filp, char __user * data, size_t count,
               loff_t * offset)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
        struct v9fs_fid *v9f = filp->private_data;
        struct v9fs_fcall *fcall = NULL;
@@ -225,7 +225,7 @@ static ssize_t
 v9fs_file_write(struct file *filp, const char __user * data,
                size_t count, loff_t * offset)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
        struct v9fs_fid *v9fid = filp->private_data;
        struct v9fs_fcall *fcall;
index 5241c60..18f26cd 100644 (file)
@@ -256,7 +256,7 @@ static int
 v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
        u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
 {
-       u32 fid;
+       int fid;
        int err;
        struct v9fs_fcall *fcall;
 
@@ -310,7 +310,7 @@ static struct v9fs_fid*
 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
 {
        int err;
-       u32 nfid;
+       int nfid;
        struct v9fs_fid *ret;
        struct v9fs_fcall *fcall;
 
index 9a5ce93..b9ffa63 100644 (file)
@@ -10,7 +10,8 @@ obj-y :=      open.o read_write.o file_table.o super.o \
                ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
                seq_file.o xattr.o libfs.o fs-writeback.o \
-               pnode.o drop_caches.o splice.o sync.o utimes.o
+               pnode.o drop_caches.o splice.o sync.o utimes.o \
+               stack.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=       buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
index d3c7905..2b89038 100644 (file)
@@ -28,7 +28,7 @@ static DEFINE_RWLOCK(adfs_dir_lock);
 static int
 adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
        struct object_info obj;
index 9ade139..5023351 100644 (file)
@@ -36,7 +36,7 @@ void __adfs_error(struct super_block *sb, const char *function, const char *fmt,
        va_list args;
 
        va_start(args, fmt);
-       vsprintf(error_buf, fmt, args);
+       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
        va_end(args);
 
        printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n",
@@ -212,12 +212,12 @@ static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
-static kmem_cache_t *adfs_inode_cachep;
+static struct kmem_cache *adfs_inode_cachep;
 
 static struct inode *adfs_alloc_inode(struct super_block *sb)
 {
        struct adfs_inode_info *ei;
-       ei = (struct adfs_inode_info *)kmem_cache_alloc(adfs_inode_cachep, SLAB_KERNEL);
+       ei = (struct adfs_inode_info *)kmem_cache_alloc(adfs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -228,7 +228,7 @@ static void adfs_destroy_inode(struct inode *inode)
        kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
 
index ccd624e..f4de4b9 100644 (file)
@@ -445,7 +445,7 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
        va_list  args;
 
        va_start(args,fmt);
-       vsprintf(ErrorBuffer,fmt,args);
+       vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
        va_end(args);
 
        printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n", sb->s_id,
@@ -461,7 +461,7 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
        va_list  args;
 
        va_start(args,fmt);
-       vsprintf(ErrorBuffer,fmt,args);
+       vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
        va_end(args);
 
        printk(KERN_WARNING "AFFS warning (device %s): %s(): %s\n", sb->s_id,
index b0b9536..b330009 100644 (file)
@@ -289,12 +289,11 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
        sbi->s_bmap_count = (sbi->s_partition_size - sbi->s_reserved +
                                 sbi->s_bmap_bits - 1) / sbi->s_bmap_bits;
        size = sbi->s_bmap_count * sizeof(*bm);
-       bm = sbi->s_bitmap = kmalloc(size, GFP_KERNEL);
+       bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL);
        if (!sbi->s_bitmap) {
                printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
                return -ENOMEM;
        }
-       memset(sbi->s_bitmap, 0, size);
 
        bmap_blk = (__be32 *)sbi->s_root_bh->b_data;
        blk = sb->s_blocksize / 4 - 49;
index 5d9649f..cad3ee3 100644 (file)
@@ -41,7 +41,7 @@ struct inode_operations affs_dir_inode_operations = {
 static int
 affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode            *inode = filp->f_dentry->d_inode;
+       struct inode            *inode = filp->f_path.dentry->d_inode;
        struct super_block      *sb = inode->i_sb;
        struct buffer_head      *dir_bh;
        struct buffer_head      *fh_bh;
@@ -71,7 +71,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                stored++;
        }
        if (f_pos == 1) {
-               if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0)
+               if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
                        return stored;
                filp->f_pos = f_pos = 2;
                stored++;
index 5ea72c3..3de93e7 100644 (file)
@@ -66,12 +66,12 @@ affs_write_super(struct super_block *sb)
        pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean);
 }
 
-static kmem_cache_t * affs_inode_cachep;
+static struct kmem_cache * affs_inode_cachep;
 
 static struct inode *affs_alloc_inode(struct super_block *sb)
 {
        struct affs_inode_info *ei;
-       ei = (struct affs_inode_info *)kmem_cache_alloc(affs_inode_cachep, SLAB_KERNEL);
+       ei = (struct affs_inode_info *)kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        ei->vfs_inode.i_version = 1;
@@ -83,7 +83,7 @@ static void affs_destroy_inode(struct inode *inode)
        kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 
index a6ec75c..4acd041 100644 (file)
@@ -392,10 +392,10 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
        unsigned fpos;
        int ret;
 
-       _enter("{%Ld,{%lu}}", file->f_pos, file->f_dentry->d_inode->i_ino);
+       _enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino);
 
        fpos = file->f_pos;
-       ret = afs_dir_iterate(file->f_dentry->d_inode, &fpos, cookie, filldir);
+       ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir);
        file->f_pos = fpos;
 
        _leave(" = %d", ret);
index f09a794..615df24 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
+#include <linux/freezer.h>
 #include "cell.h"
 #include "server.h"
 #include "volume.h"
index 65bc05a..694344e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
+#include <linux/freezer.h>
 #include "cell.h"
 #include "volume.h"
 #include "kafstimod.h"
index 99785a7..8f74e84 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/pagemap.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include "super.h"
 #include "cell.h"
 #include "volume.h"
@@ -136,11 +136,11 @@ static int afs_mntpt_open(struct inode *inode, struct file *file)
 {
        kenter("%p,%p{%p{%s},%s}",
               inode, file,
-              file->f_dentry->d_parent,
-              file->f_dentry->d_parent ?
-              file->f_dentry->d_parent->d_name.name :
+              file->f_path.dentry->d_parent,
+              file->f_path.dentry->d_parent ?
+              file->f_path.dentry->d_parent->d_name.name :
               (const unsigned char *) "",
-              file->f_dentry->d_name.name);
+              file->f_path.dentry->d_name.name);
 
        return -EREMOTE;
 } /* end afs_mntpt_open() */
index 22afaae..44aff81 100644 (file)
@@ -55,13 +55,12 @@ int afs_server_lookup(struct afs_cell *cell, const struct in_addr *addr,
        _enter("%p,%08x,", cell, ntohl(addr->s_addr));
 
        /* allocate and initialise a server record */
-       server = kmalloc(sizeof(struct afs_server), GFP_KERNEL);
+       server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
        if (!server) {
                _leave(" = -ENOMEM");
                return -ENOMEM;
        }
 
-       memset(server, 0, sizeof(struct afs_server));
        atomic_set(&server->usage, 1);
 
        INIT_LIST_HEAD(&server->link);
index 67d1f5c..18d9b77 100644 (file)
@@ -35,7 +35,7 @@ struct afs_mount_params {
        struct afs_volume       *volume;
 };
 
-static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
+static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
                            unsigned long flags);
 
 static int afs_get_sb(struct file_system_type *fs_type,
@@ -65,7 +65,7 @@ static struct super_operations afs_super_ops = {
        .put_super      = afs_put_super,
 };
 
-static kmem_cache_t *afs_inode_cachep;
+static struct kmem_cache *afs_inode_cachep;
 static atomic_t afs_count_active_inodes;
 
 /*****************************************************************************/
@@ -242,14 +242,12 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent)
        kenter("");
 
        /* allocate a superblock info record */
-       as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL);
+       as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
        if (!as) {
                _leave(" = -ENOMEM");
                return -ENOMEM;
        }
 
-       memset(as, 0, sizeof(struct afs_super_info));
-
        afs_get_volume(params->volume);
        as->volume = params->volume;
 
@@ -384,7 +382,7 @@ static void afs_put_super(struct super_block *sb)
 /*
  * initialise an inode cache slab element prior to any use
  */
-static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep,
+static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
                            unsigned long flags)
 {
        struct afs_vnode *vnode = (struct afs_vnode *) _vnode;
@@ -412,7 +410,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
        struct afs_vnode *vnode;
 
        vnode = (struct afs_vnode *)
-               kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
+               kmem_cache_alloc(afs_inode_cachep, GFP_KERNEL);
        if (!vnode)
                return NULL;
 
index 277a5f2..d3a6ec2 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -47,19 +47,19 @@ unsigned long aio_nr;               /* current system wide number of aio requests */
 unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
 /*----end sysctl variables---*/
 
-static kmem_cache_t    *kiocb_cachep;
-static kmem_cache_t    *kioctx_cachep;
+static struct kmem_cache       *kiocb_cachep;
+static struct kmem_cache       *kioctx_cachep;
 
 static struct workqueue_struct *aio_wq;
 
 /* Used for rare fput completion. */
-static void aio_fput_routine(void *);
-static DECLARE_WORK(fput_work, aio_fput_routine, NULL);
+static void aio_fput_routine(struct work_struct *);
+static DECLARE_WORK(fput_work, aio_fput_routine);
 
 static DEFINE_SPINLOCK(fput_lock);
 static LIST_HEAD(fput_head);
 
-static void aio_kick_handler(void *);
+static void aio_kick_handler(struct work_struct *);
 static void aio_queue_work(struct kioctx *);
 
 /* aio_setup
@@ -227,7 +227,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
        INIT_LIST_HEAD(&ctx->active_reqs);
        INIT_LIST_HEAD(&ctx->run_list);
-       INIT_WORK(&ctx->wq, aio_kick_handler, ctx);
+       INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler);
 
        if (aio_setup_ring(ctx) < 0)
                goto out_freectx;
@@ -469,7 +469,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
                wake_up(&ctx->wait);
 }
 
-static void aio_fput_routine(void *data)
+static void aio_fput_routine(struct work_struct *data)
 {
        spin_lock_irq(&fput_lock);
        while (likely(!list_empty(&fput_head))) {
@@ -666,17 +666,6 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
        ssize_t (*retry)(struct kiocb *);
        ssize_t ret;
 
-       if (iocb->ki_retried++ > 1024*1024) {
-               printk("Maximal retry count.  Bytes done %Zd\n",
-                       iocb->ki_nbytes - iocb->ki_left);
-               return -EAGAIN;
-       }
-
-       if (!(iocb->ki_retried & 0xff)) {
-               pr_debug("%ld retry: %zd of %zd\n", iocb->ki_retried,
-                       iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
-       }
-
        if (!(retry = iocb->ki_retry)) {
                printk("aio_run_iocb: iocb->ki_retry = NULL\n");
                return 0;
@@ -857,9 +846,9 @@ static inline void aio_run_all_iocbs(struct kioctx *ctx)
  *      space.
  * Run on aiod's context.
  */
-static void aio_kick_handler(void *data)
+static void aio_kick_handler(struct work_struct *work)
 {
-       struct kioctx *ctx = data;
+       struct kioctx *ctx = container_of(work, struct kioctx, wq.work);
        mm_segment_t oldfs = get_fs();
        int requeue;
 
@@ -874,7 +863,7 @@ static void aio_kick_handler(void *data)
         * we're in a worker thread already, don't use queue_delayed_work,
         */
        if (requeue)
-               queue_work(aio_wq, &ctx->wq);
+               queue_delayed_work(aio_wq, &ctx->wq, 0);
 }
 
 
@@ -1005,9 +994,6 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
        kunmap_atomic(ring, KM_IRQ1);
 
        pr_debug("added to ring %p at [%lu]\n", iocb, tail);
-
-       pr_debug("%ld retries: %zd of %zd\n", iocb->ki_retried,
-               iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
 put_rq:
        /* everything turned out well, dispose of the aiocb. */
        ret = __aio_put_req(ctx, iocb);
@@ -1413,7 +1399,6 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
        kiocb->ki_iovec->iov_len = kiocb->ki_left;
        kiocb->ki_nr_segs = 1;
        kiocb->ki_cur_seg = 0;
-       kiocb->ki_nbytes = kiocb->ki_left;
        return 0;
 }
 
@@ -1591,7 +1576,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        req->ki_opcode = iocb->aio_lio_opcode;
        init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
        INIT_LIST_HEAD(&req->ki_wait.task_list);
-       req->ki_retried = 0;
 
        ret = aio_setup_iocb(req);
 
index 38ede5c..f968d13 100644 (file)
@@ -28,10 +28,11 @@ void autofs_kill_sb(struct super_block *sb)
        /*
         * In the event of a failure in get_sb_nodev the superblock
         * info is not present so nothing else has been setup, so
-        * just exit when we are called from deactivate_super.
+        * just call kill_anon_super when we are called from
+        * deactivate_super.
         */
        if (!sbi)
-               return;
+               goto out_kill_sb;
 
        if ( !sbi->catatonic )
                autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
@@ -44,6 +45,7 @@ void autofs_kill_sb(struct super_block *sb)
 
        kfree(sb->s_fs_info);
 
+out_kill_sb:
        DPRINTK(("autofs: shutting down\n"));
        kill_anon_super(sb);
 }
@@ -209,7 +211,6 @@ fail_iput:
 fail_free:
        kfree(sbi);
        s->s_fs_info = NULL;
-       kill_anon_super(s);
 fail_unlock:
        return -EINVAL;
 }
index 368a1c3..e698c51 100644 (file)
@@ -45,7 +45,7 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi
        struct autofs_dir_ent *ent = NULL;
        struct autofs_dirhash *dirhash;
        struct autofs_sb_info *sbi;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        off_t onr, nr;
 
        lock_kernel();
@@ -557,7 +557,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
        case AUTOFS_IOC_SETTIMEOUT:
                return autofs_get_set_timeout(sbi, argp);
        case AUTOFS_IOC_EXPIRE:
-               return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
+               return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt,
                                         argp);
        default:
                return -ENOSYS;
index b13f32c..216b1a3 100644 (file)
@@ -150,7 +150,8 @@ static inline int autofs4_ispending(struct dentry *dentry)
 
 static inline void autofs4_copy_atime(struct file *src, struct file *dst)
 {
-       dst->f_dentry->d_inode->i_atime = src->f_dentry->d_inode->i_atime;
+       dst->f_path.dentry->d_inode->i_atime =
+               src->f_path.dentry->d_inode->i_atime;
        return;
 }
 
index ce7c0f1..9c48250 100644 (file)
@@ -152,10 +152,11 @@ void autofs4_kill_sb(struct super_block *sb)
        /*
         * In the event of a failure in get_sb_nodev the superblock
         * info is not present so nothing else has been setup, so
-        * just exit when we are called from deactivate_super.
+        * just call kill_anon_super when we are called from
+        * deactivate_super.
         */
        if (!sbi)
-               return;
+               goto out_kill_sb;
 
        sb->s_fs_info = NULL;
 
@@ -167,6 +168,7 @@ void autofs4_kill_sb(struct super_block *sb)
 
        kfree(sbi);
 
+out_kill_sb:
        DPRINTK("shutting down");
        kill_anon_super(sb);
 }
@@ -426,7 +428,6 @@ fail_ino:
 fail_free:
        kfree(sbi);
        s->s_fs_info = NULL;
-       kill_anon_super(s);
 fail_unlock:
        return -EINVAL;
 }
index c149352..8d05b9f 100644 (file)
@@ -74,7 +74,7 @@ struct inode_operations autofs4_dir_inode_operations = {
 static int autofs4_root_readdir(struct file *file, void *dirent,
                                filldir_t filldir)
 {
-       struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
+       struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb);
        int oz_mode = autofs4_oz_mode(sbi);
 
        DPRINTK("called, filp->f_pos = %lld", file->f_pos);
@@ -95,8 +95,8 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
 
 static int autofs4_dir_open(struct inode *inode, struct file *file)
 {
-       struct dentry *dentry = file->f_dentry;
-       struct vfsmount *mnt = file->f_vfsmnt;
+       struct dentry *dentry = file->f_path.dentry;
+       struct vfsmount *mnt = file->f_path.mnt;
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct dentry *cursor;
        int status;
@@ -172,7 +172,7 @@ out:
 
 static int autofs4_dir_close(struct inode *inode, struct file *file)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct dentry *cursor = file->private_data;
        int status = 0;
@@ -204,7 +204,7 @@ out:
 
 static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct dentry *cursor = file->private_data;
        int status;
@@ -858,14 +858,14 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
                return autofs4_ask_reghost(sbi, p);
 
        case AUTOFS_IOC_ASKUMOUNT:
-               return autofs4_ask_umount(filp->f_vfsmnt, p);
+               return autofs4_ask_umount(filp->f_path.mnt, p);
 
        /* return a single thing to expire */
        case AUTOFS_IOC_EXPIRE:
-               return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p);
+               return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p);
        /* same as above, but can send multiple expires through pipe */
        case AUTOFS_IOC_EXPIRE_MULTI:
-               return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p);
+               return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p);
 
        default:
                return -ENOSYS;
index 07f7144..481e59b 100644 (file)
@@ -61,7 +61,7 @@ static const struct super_operations befs_sops = {
 };
 
 /* slab cache for befs_inode_info objects */
-static kmem_cache_t *befs_inode_cachep;
+static struct kmem_cache *befs_inode_cachep;
 
 static const struct file_operations befs_dir_operations = {
        .read           = generic_read_dir,
@@ -212,7 +212,7 @@ befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 static int
 befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
        befs_off_t value;
@@ -222,7 +222,7 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        char keybuf[BEFS_NAME_LEN + 1];
        char *nlsname;
        int nlsnamelen;
-       const char *dirname = filp->f_dentry->d_name.name;
+       const char *dirname = filp->f_path.dentry->d_name.name;
 
        befs_debug(sb, "---> befs_readdir() "
                   "name %s, inode %ld, filp->f_pos %Ld",
@@ -277,7 +277,7 @@ befs_alloc_inode(struct super_block *sb)
 {
         struct befs_inode_info *bi;
         bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep,
-                                                       SLAB_KERNEL);
+                                                       GFP_KERNEL);
         if (!bi)
                 return NULL;
         return &bi->vfs_inode;
@@ -289,7 +289,7 @@ befs_destroy_inode(struct inode *inode)
         kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
         struct befs_inode_info *bi = (struct befs_inode_info *) foo;
        
index a650f1d..2a746e6 100644 (file)
@@ -27,7 +27,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
 
 static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
 {
-       struct inode * dir = f->f_dentry->d_inode;
+       struct inode * dir = f->f_path.dentry->d_inode;
        struct buffer_head * bh;
        struct bfs_dirent * de;
        unsigned int offset;
index ed27ffb..eac175e 100644 (file)
@@ -228,12 +228,12 @@ static void bfs_write_super(struct super_block *s)
        unlock_kernel();
 }
 
-static kmem_cache_t * bfs_inode_cachep;
+static struct kmem_cache * bfs_inode_cachep;
 
 static struct inode *bfs_alloc_inode(struct super_block *sb)
 {
        struct bfs_inode_info *bi;
-       bi = kmem_cache_alloc(bfs_inode_cachep, SLAB_KERNEL);
+       bi = kmem_cache_alloc(bfs_inode_cachep, GFP_KERNEL);
        if (!bi)
                return NULL;
        return &bi->vfs_inode;
@@ -244,7 +244,7 @@ static void bfs_destroy_inode(struct inode *inode)
        kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct bfs_inode_info *bi = foo;
 
index 517e111..813a887 100644 (file)
@@ -274,7 +274,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
             N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
            N_TRSIZE(ex) || N_DRSIZE(ex) ||
-           i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+           i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
                return -ENOEXEC;
        }
 
@@ -389,7 +389,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                {
                        printk(KERN_WARNING 
                               "fd_offset is not page aligned. Please convert program: %s\n",
-                              bprm->file->f_dentry->d_name.name);
+                              bprm->file->f_path.dentry->d_name.name);
                        error_time = jiffies;
                }
 
@@ -469,7 +469,7 @@ static int load_aout_library(struct file *file)
        int retval;
        struct exec ex;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        retval = -ENOEXEC;
        error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
@@ -506,7 +506,7 @@ static int load_aout_library(struct file *file)
                {
                        printk(KERN_WARNING 
                               "N_TXTOFF is not page aligned. Please convert library: %s\n",
-                              file->f_dentry->d_name.name);
+                              file->f_path.dentry->d_name.name);
                        error_time = jiffies;
                }
                down_write(&current->mm->mmap_sem);
index cc72bb4..d3adfd3 100644 (file)
@@ -47,10 +47,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
 static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
 
-#ifndef elf_addr_t
-#define elf_addr_t unsigned long
-#endif
-
 /*
  * If we don't support core dumping, then supply a NULL so we
  * don't even try.
@@ -243,8 +239,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
        if (interp_aout) {
                argv = sp + 2;
                envp = argv + argc + 1;
-               __put_user((elf_addr_t)(unsigned long)argv, sp++);
-               __put_user((elf_addr_t)(unsigned long)envp, sp++);
+               if (__put_user((elf_addr_t)(unsigned long)argv, sp++) ||
+                   __put_user((elf_addr_t)(unsigned long)envp, sp++))
+                       return -EFAULT;
        } else {
                argv = sp;
                envp = argv + argc + 1;
@@ -254,7 +251,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
        p = current->mm->arg_end = current->mm->arg_start;
        while (argc-- > 0) {
                size_t len;
-               __put_user((elf_addr_t)p, argv++);
+               if (__put_user((elf_addr_t)p, argv++))
+                       return -EFAULT;
                len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
                        return 0;
@@ -265,7 +263,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
        current->mm->arg_end = current->mm->env_start = p;
        while (envc-- > 0) {
                size_t len;
-               __put_user((elf_addr_t)p, envp++);
+               if (__put_user((elf_addr_t)p, envp++))
+                       return -EFAULT;
                len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
                        return 0;
@@ -545,7 +544,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        unsigned long reloc_func_desc = 0;
        char passed_fileno[6];
        struct files_struct *files;
-       int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
+       int executable_stack = EXSTACK_DEFAULT;
        unsigned long def_flags = 0;
        struct {
                struct elfhdr elf_ex;
@@ -708,7 +707,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                                executable_stack = EXSTACK_DISABLE_X;
                        break;
                }
-       have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
 
        /* Some simple consistency checks for the interpreter */
        if (elf_interpreter) {
@@ -856,7 +854,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         * default mmap base, as well as whatever program they
                         * might try to exec.  This is because the brk will
                         * follow the loader, and is not movable.  */
-                       load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+                       if (current->flags & PF_RANDOMIZE)
+                               load_bias = randomize_range(0x10000,
+                                                           ELF_ET_DYN_BASE,
+                                                           0);
+                       else
+                               load_bias = ELF_ET_DYN_BASE;
+                       load_bias = ELF_PAGESTART(load_bias - vaddr);
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
@@ -1186,7 +1190,7 @@ static int maydump(struct vm_area_struct *vma)
 
        /* Dump shared memory only if mapped from an anonymous file. */
        if (vma->vm_flags & VM_SHARED)
-               return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
+               return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0;
 
        /* If it hasn't been written to, don't write it out */
        if (!vma->anon_vma)
@@ -1313,7 +1317,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
        prstatus->pr_pid = p->pid;
        prstatus->pr_ppid = p->parent->pid;
        prstatus->pr_pgrp = process_group(p);
-       prstatus->pr_sid = p->signal->session;
+       prstatus->pr_sid = process_session(p);
        if (thread_group_leader(p)) {
                /*
                 * This is the record for the group leader.  Add in the
@@ -1359,7 +1363,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
        psinfo->pr_pid = p->pid;
        psinfo->pr_ppid = p->parent->pid;
        psinfo->pr_pgrp = process_group(p);
-       psinfo->pr_sid = p->signal->session;
+       psinfo->pr_sid = process_session(p);
 
        i = p->state ? ffz(~p->state) + 1 : 0;
        psinfo->pr_state = i;
index f86d5c9..76f06f6 100644 (file)
@@ -40,9 +40,6 @@
 #include <asm/pgalloc.h>
 
 typedef char *elf_caddr_t;
-#ifndef elf_addr_t
-#define elf_addr_t unsigned long
-#endif
 
 #if 0
 #define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
@@ -858,7 +855,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
 
 dynamic_error:
        printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
-              what, file->f_dentry->d_inode->i_ino);
+              what, file->f_path.dentry->d_inode->i_ino);
        return -ELIBBAD;
 }
 
@@ -1189,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma)
 
        /* Dump shared memory only if mapped from an anonymous file. */
        if (vma->vm_flags & VM_SHARED) {
-               if (vma->vm_file->f_dentry->d_inode->i_nlink == 0) {
+               if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) {
                        kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
                        return 1;
                }
@@ -1325,7 +1322,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
        prstatus->pr_pid = p->pid;
        prstatus->pr_ppid = p->parent->pid;
        prstatus->pr_pgrp = process_group(p);
-       prstatus->pr_sid = p->signal->session;
+       prstatus->pr_sid = process_session(p);
        if (thread_group_leader(p)) {
                /*
                 * This is the record for the group leader.  Add in the
@@ -1374,7 +1371,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
        psinfo->pr_pid = p->pid;
        psinfo->pr_ppid = p->parent->pid;
        psinfo->pr_pgrp = process_group(p);
-       psinfo->pr_sid = p->signal->session;
+       psinfo->pr_sid = process_session(p);
 
        i = p->state ? ffz(~p->state) + 1 : 0;
        psinfo->pr_state = i;
index a62fd40..ae8595d 100644 (file)
@@ -429,7 +429,7 @@ static int load_flat_file(struct linux_binprm * bprm,
        int ret;
 
        hdr = ((struct flat_hdr *) bprm->buf);          /* exec-header */
-       inode = bprm->file->f_dentry->d_inode;
+       inode = bprm->file->f_path.dentry->d_inode;
 
        text_len  = ntohl(hdr->data_start);
        data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start);
index 1713c48..00687ea 100644 (file)
@@ -542,7 +542,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->i_private;
+       Node *e = file->f_path.dentry->d_inode->i_private;
        loff_t pos = *ppos;
        ssize_t res;
        char *page;
@@ -576,7 +576,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->i_private;
+       Node *e = file->f_path.dentry->d_inode->i_private;
        int res = parse_command(buffer, count);
 
        switch (res) {
@@ -584,7 +584,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
                        break;
                case 2: set_bit(Enabled, &e->flags);
                        break;
-               case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
+               case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
                        mutex_lock(&root->d_inode->i_mutex);
 
                        kill_node(e);
@@ -610,7 +610,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
        Node *e;
        struct inode *inode;
        struct dentry *root, *dentry;
-       struct super_block *sb = file->f_vfsmnt->mnt_sb;
+       struct super_block *sb = file->f_path.mnt->mnt_sb;
        int err = 0;
 
        e = create_entry(buffer, count);
@@ -699,7 +699,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
        switch (res) {
                case 1: enabled = 0; break;
                case 2: enabled = 1; break;
-               case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
+               case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
                        mutex_lock(&root->d_inode->i_mutex);
 
                        while (!list_empty(&entries))
index aa4d09b..7ec737e 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -30,7 +30,7 @@
 
 #define BIO_POOL_SIZE 256
 
-static kmem_cache_t *bio_slab __read_mostly;
+static struct kmem_cache *bio_slab __read_mostly;
 
 #define BIOVEC_NR_POOLS 6
 
@@ -44,7 +44,7 @@ mempool_t *bio_split_pool __read_mostly;
 struct biovec_slab {
        int nr_vecs;
        char *name; 
-       kmem_cache_t *slab;
+       struct kmem_cache *slab;
 };
 
 /*
@@ -940,16 +940,16 @@ static void bio_release_pages(struct bio *bio)
  * run one bio_put() against the BIO.
  */
 
-static void bio_dirty_fn(void *data);
+static void bio_dirty_fn(struct work_struct *work);
 
-static DECLARE_WORK(bio_dirty_work, bio_dirty_fn, NULL);
+static DECLARE_WORK(bio_dirty_work, bio_dirty_fn);
 static DEFINE_SPINLOCK(bio_dirty_lock);
 static struct bio *bio_dirty_list;
 
 /*
  * This runs in process context
  */
-static void bio_dirty_fn(void *data)
+static void bio_dirty_fn(struct work_struct *work)
 {
        unsigned long flags;
        struct bio *bio;
index 36c0e7a..197f939 100644 (file)
@@ -190,7 +190,7 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr
 
 /*
  * private llseek:
- * for a block special file file->f_dentry->d_inode->i_size is zero
+ * for a block special file file->f_path.dentry->d_inode->i_size is zero
  * so we compute the size by hand (just as in block_read/write above)
  */
 static loff_t block_llseek(struct file *file, loff_t offset, int origin)
@@ -235,11 +235,11 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
  */
 
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock);
-static kmem_cache_t * bdev_cachep __read_mostly;
+static struct kmem_cache * bdev_cachep __read_mostly;
 
 static struct inode *bdev_alloc_inode(struct super_block *sb)
 {
-       struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, SLAB_KERNEL);
+       struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -253,7 +253,7 @@ static void bdev_destroy_inode(struct inode *inode)
        kmem_cache_free(bdev_cachep, bdi);
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct bdev_inode *ei = (struct bdev_inode *) foo;
        struct block_device *bdev = &ei->bdev;
@@ -762,7 +762,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
        if (!bo)
                return -ENOMEM;
 
-       mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
+       mutex_lock(&bdev->bd_mutex);
        res = bd_claim(bdev, holder);
        if (res == 0) {
                found = find_bd_holder(bdev, bo);
@@ -796,7 +796,7 @@ static void bd_release_from_kobject(struct block_device *bdev,
        if (!kobj)
                return;
 
-       mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
+       mutex_lock(&bdev->bd_mutex);
        bd_release(bdev);
        if ((bo = del_bd_holder(bdev, kobj)))
                free_bd_holder(bo);
@@ -854,22 +854,6 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode)
 
 EXPORT_SYMBOL(open_by_devnum);
 
-static int
-blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags);
-
-struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode)
-{
-       struct block_device *bdev = bdget(dev);
-       int err = -ENOMEM;
-       int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY;
-       if (bdev)
-               err = blkdev_get_partition(bdev, mode, flags);
-       return err ? ERR_PTR(err) : bdev;
-}
-
-EXPORT_SYMBOL(open_partition_by_devnum);
-
-
 /*
  * This routine checks whether a removable media has been changed,
  * and invalidates all buffer-cache-entries in that case. This
@@ -916,66 +900,11 @@ void bd_set_size(struct block_device *bdev, loff_t size)
 }
 EXPORT_SYMBOL(bd_set_size);
 
-static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
-{
-       int ret = 0;
-       struct inode *bd_inode = bdev->bd_inode;
-       struct gendisk *disk = bdev->bd_disk;
-
-       mutex_lock_nested(&bdev->bd_mutex, subclass);
-       lock_kernel();
-       if (!--bdev->bd_openers) {
-               sync_blockdev(bdev);
-               kill_bdev(bdev);
-       }
-       if (bdev->bd_contains == bdev) {
-               if (disk->fops->release)
-                       ret = disk->fops->release(bd_inode, NULL);
-       } else {
-               mutex_lock_nested(&bdev->bd_contains->bd_mutex,
-                                 subclass + 1);
-               bdev->bd_contains->bd_part_count--;
-               mutex_unlock(&bdev->bd_contains->bd_mutex);
-       }
-       if (!bdev->bd_openers) {
-               struct module *owner = disk->fops->owner;
-
-               put_disk(disk);
-               module_put(owner);
-
-               if (bdev->bd_contains != bdev) {
-                       kobject_put(&bdev->bd_part->kobj);
-                       bdev->bd_part = NULL;
-               }
-               bdev->bd_disk = NULL;
-               bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
-               if (bdev != bdev->bd_contains)
-                       __blkdev_put(bdev->bd_contains, subclass + 1);
-               bdev->bd_contains = NULL;
-       }
-       unlock_kernel();
-       mutex_unlock(&bdev->bd_mutex);
-       bdput(bdev);
-       return ret;
-}
-
-int blkdev_put(struct block_device *bdev)
-{
-       return __blkdev_put(bdev, BD_MUTEX_NORMAL);
-}
-EXPORT_SYMBOL(blkdev_put);
-
-int blkdev_put_partition(struct block_device *bdev)
-{
-       return __blkdev_put(bdev, BD_MUTEX_PARTITION);
-}
-EXPORT_SYMBOL(blkdev_put_partition);
+static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+                       int for_part);
+static int __blkdev_put(struct block_device *bdev, int for_part);
 
-static int
-blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags);
-
-static int
-do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
+static int do_open(struct block_device *bdev, struct file *file, int for_part)
 {
        struct module *owner = NULL;
        struct gendisk *disk;
@@ -992,8 +921,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
        }
        owner = disk->fops->owner;
 
-       mutex_lock_nested(&bdev->bd_mutex, subclass);
-
+       mutex_lock_nested(&bdev->bd_mutex, for_part);
        if (!bdev->bd_openers) {
                bdev->bd_disk = disk;
                bdev->bd_contains = bdev;
@@ -1020,25 +948,21 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
                        ret = -ENOMEM;
                        if (!whole)
                                goto out_first;
-                       ret = blkdev_get_whole(whole, file->f_mode, file->f_flags);
+                       BUG_ON(for_part);
+                       ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1);
                        if (ret)
                                goto out_first;
                        bdev->bd_contains = whole;
-                       mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE);
-                       whole->bd_part_count++;
                        p = disk->part[part - 1];
                        bdev->bd_inode->i_data.backing_dev_info =
                           whole->bd_inode->i_data.backing_dev_info;
                        if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) {
-                               whole->bd_part_count--;
-                               mutex_unlock(&whole->bd_mutex);
                                ret = -ENXIO;
                                goto out_first;
                        }
                        kobject_get(&p->kobj);
                        bdev->bd_part = p;
                        bd_set_size(bdev, (loff_t) p->nr_sects << 9);
-                       mutex_unlock(&whole->bd_mutex);
                }
        } else {
                put_disk(disk);
@@ -1051,14 +975,11 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
                        }
                        if (bdev->bd_invalidated)
                                rescan_partitions(bdev->bd_disk, bdev);
-               } else {
-                       mutex_lock_nested(&bdev->bd_contains->bd_mutex,
-                                         BD_MUTEX_WHOLE);
-                       bdev->bd_contains->bd_part_count++;
-                       mutex_unlock(&bdev->bd_contains->bd_mutex);
                }
        }
        bdev->bd_openers++;
+       if (for_part)
+               bdev->bd_part_count++;
        mutex_unlock(&bdev->bd_mutex);
        unlock_kernel();
        return 0;
@@ -1067,7 +988,7 @@ out_first:
        bdev->bd_disk = NULL;
        bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
        if (bdev != bdev->bd_contains)
-               __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE);
+               __blkdev_put(bdev->bd_contains, 1);
        bdev->bd_contains = NULL;
        put_disk(disk);
        module_put(owner);
@@ -1079,7 +1000,8 @@ out:
        return ret;
 }
 
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
+static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+                       int for_part)
 {
        /*
         * This crockload is due to bad choice of ->open() type.
@@ -1091,51 +1013,17 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
        struct dentry fake_dentry = {};
        fake_file.f_mode = mode;
        fake_file.f_flags = flags;
-       fake_file.f_dentry = &fake_dentry;
+       fake_file.f_path.dentry = &fake_dentry;
        fake_dentry.d_inode = bdev->bd_inode;
 
-       return do_open(bdev, &fake_file, BD_MUTEX_NORMAL);
+       return do_open(bdev, &fake_file, for_part);
 }
 
-EXPORT_SYMBOL(blkdev_get);
-
-static int
-blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags)
-{
-       /*
-        * This crockload is due to bad choice of ->open() type.
-        * It will go away.
-        * For now, block device ->open() routine must _not_
-        * examine anything in 'inode' argument except ->i_rdev.
-        */
-       struct file fake_file = {};
-       struct dentry fake_dentry = {};
-       fake_file.f_mode = mode;
-       fake_file.f_flags = flags;
-       fake_file.f_dentry = &fake_dentry;
-       fake_dentry.d_inode = bdev->bd_inode;
-
-       return do_open(bdev, &fake_file, BD_MUTEX_WHOLE);
-}
-
-static int
-blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags)
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
 {
-       /*
-        * This crockload is due to bad choice of ->open() type.
-        * It will go away.
-        * For now, block device ->open() routine must _not_
-        * examine anything in 'inode' argument except ->i_rdev.
-        */
-       struct file fake_file = {};
-       struct dentry fake_dentry = {};
-       fake_file.f_mode = mode;
-       fake_file.f_flags = flags;
-       fake_file.f_dentry = &fake_dentry;
-       fake_dentry.d_inode = bdev->bd_inode;
-
-       return do_open(bdev, &fake_file, BD_MUTEX_PARTITION);
+       return __blkdev_get(bdev, mode, flags, 0);
 }
+EXPORT_SYMBOL(blkdev_get);
 
 static int blkdev_open(struct inode * inode, struct file * filp)
 {
@@ -1154,7 +1042,7 @@ static int blkdev_open(struct inode * inode, struct file * filp)
        if (bdev == NULL)
                return -ENOMEM;
 
-       res = do_open(bdev, filp, BD_MUTEX_NORMAL);
+       res = do_open(bdev, filp, 0);
        if (res)
                return res;
 
@@ -1168,6 +1056,56 @@ static int blkdev_open(struct inode * inode, struct file * filp)
        return res;
 }
 
+static int __blkdev_put(struct block_device *bdev, int for_part)
+{
+       int ret = 0;
+       struct inode *bd_inode = bdev->bd_inode;
+       struct gendisk *disk = bdev->bd_disk;
+       struct block_device *victim = NULL;
+
+       mutex_lock_nested(&bdev->bd_mutex, for_part);
+       lock_kernel();
+       if (for_part)
+               bdev->bd_part_count--;
+
+       if (!--bdev->bd_openers) {
+               sync_blockdev(bdev);
+               kill_bdev(bdev);
+       }
+       if (bdev->bd_contains == bdev) {
+               if (disk->fops->release)
+                       ret = disk->fops->release(bd_inode, NULL);
+       }
+       if (!bdev->bd_openers) {
+               struct module *owner = disk->fops->owner;
+
+               put_disk(disk);
+               module_put(owner);
+
+               if (bdev->bd_contains != bdev) {
+                       kobject_put(&bdev->bd_part->kobj);
+                       bdev->bd_part = NULL;
+               }
+               bdev->bd_disk = NULL;
+               bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
+               if (bdev != bdev->bd_contains)
+                       victim = bdev->bd_contains;
+               bdev->bd_contains = NULL;
+       }
+       unlock_kernel();
+       mutex_unlock(&bdev->bd_mutex);
+       bdput(bdev);
+       if (victim)
+               __blkdev_put(victim, 1);
+       return ret;
+}
+
+int blkdev_put(struct block_device *bdev)
+{
+       return __blkdev_put(bdev, 0);
+}
+EXPORT_SYMBOL(blkdev_put);
+
 static int blkdev_close(struct inode * inode, struct file * filp)
 {
        struct block_device *bdev = I_BDEV(filp->f_mapping->host);
index 35527dc..d1f1b54 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/hash.h>
 #include <linux/suspend.h>
 #include <linux/buffer_head.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/bio.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
@@ -724,20 +725,21 @@ int __set_page_dirty_buffers(struct page *page)
        }
        spin_unlock(&mapping->private_lock);
 
-       if (!TestSetPageDirty(page)) {
-               write_lock_irq(&mapping->tree_lock);
-               if (page->mapping) {    /* Race with truncate? */
-                       if (mapping_cap_account_dirty(mapping))
-                               __inc_zone_page_state(page, NR_FILE_DIRTY);
-                       radix_tree_tag_set(&mapping->page_tree,
-                                               page_index(page),
-                                               PAGECACHE_TAG_DIRTY);
+       if (TestSetPageDirty(page))
+               return 0;
+
+       write_lock_irq(&mapping->tree_lock);
+       if (page->mapping) {    /* Race with truncate? */
+               if (mapping_cap_account_dirty(mapping)) {
+                       __inc_zone_page_state(page, NR_FILE_DIRTY);
+                       task_io_account_write(PAGE_CACHE_SIZE);
                }
-               write_unlock_irq(&mapping->tree_lock);
-               __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-               return 1;
+               radix_tree_tag_set(&mapping->page_tree,
+                               page_index(page), PAGECACHE_TAG_DIRTY);
        }
-       return 0;
+       write_unlock_irq(&mapping->tree_lock);
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       return 1;
 }
 EXPORT_SYMBOL(__set_page_dirty_buffers);
 
@@ -2851,8 +2853,13 @@ int try_to_free_buffers(struct page *page)
                 * could encounter a non-uptodate page, which is unresolvable.
                 * This only applies in the rare case where try_to_free_buffers
                 * succeeds but the page is not freed.
+                *
+                * Also, during truncate, discard_buffer will have marked all
+                * the page's buffers clean.  We discover that here and clean
+                * the page also.
                 */
-               clear_page_dirty(page);
+               if (test_clear_page_dirty(page))
+                       task_io_account_cancelled_write(PAGE_CACHE_SIZE);
        }
 out:
        if (buffers_to_free) {
@@ -2908,7 +2915,7 @@ asmlinkage long sys_bdflush(int func, long data)
 /*
  * Buffer-head allocation
  */
-static kmem_cache_t *bh_cachep;
+static struct kmem_cache *bh_cachep;
 
 /*
  * Once the number of bh's in the machine exceeds this level, we start
@@ -2961,7 +2968,7 @@ void free_buffer_head(struct buffer_head *bh)
 EXPORT_SYMBOL(free_buffer_head);
 
 static void
-init_buffer_head(void *data, kmem_cache_t *cachep, unsigned long flags)
+init_buffer_head(void *data, struct kmem_cache *cachep, unsigned long flags)
 {
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
                            SLAB_CTOR_CONSTRUCTOR) {
@@ -2972,7 +2979,6 @@ init_buffer_head(void *data, kmem_cache_t *cachep, unsigned long flags)
        }
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void buffer_exit_cpu(int cpu)
 {
        int i;
@@ -2994,7 +3000,6 @@ static int buffer_cpu_notify(struct notifier_block *self,
                buffer_exit_cpu((unsigned long)hcpu);
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 void __init buffer_init(void)
 {
index 0b3c37e..3539d6e 100644 (file)
@@ -5,7 +5,8 @@ Allow null user to be specified on mount ("username="). Do not return
 EINVAL on readdir when filldir fails due to overwritten blocksize
 (fixes FC problem).  Return error in rename 2nd attempt retry (ie report
 if rename by handle also fails, after rename by path fails, we were
-not reporting whether the retry worked or not).
+not reporting whether the retry worked or not). Fix NTLMv2 to
+work to Windows servers (mount with option "sec=ntlmv2").
 
 Version 1.45
 ------------
index 4bc250b..fdeda51 100644 (file)
@@ -372,8 +372,10 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
        buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
        get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
        buf->reserved2 = 0;
-       buf->names[0].type = 0;
+       buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
        buf->names[0].length = 0;
+       buf->names[1].type = 0;
+       buf->names[1].length = 0;
 
        /* calculate buf->ntlmv2_hash */
        rc = calc_ntlmv2_hash(ses, nls_cp);
index 84976cd..10c9029 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mempool.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -81,7 +82,7 @@ extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
-extern kmem_cache_t *cifs_oplock_cachep;
+extern struct kmem_cache *cifs_oplock_cachep;
 
 static int
 cifs_read_super(struct super_block *sb, void *data,
@@ -232,11 +233,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
                return generic_permission(inode, mask, NULL);
 }
 
-static kmem_cache_t *cifs_inode_cachep;
-static kmem_cache_t *cifs_req_cachep;
-static kmem_cache_t *cifs_mid_cachep;
-kmem_cache_t *cifs_oplock_cachep;
-static kmem_cache_t *cifs_sm_req_cachep;
+static struct kmem_cache *cifs_inode_cachep;
+static struct kmem_cache *cifs_req_cachep;
+static struct kmem_cache *cifs_mid_cachep;
+struct kmem_cache *cifs_oplock_cachep;
+static struct kmem_cache *cifs_sm_req_cachep;
 mempool_t *cifs_sm_req_poolp;
 mempool_t *cifs_req_poolp;
 mempool_t *cifs_mid_poolp;
@@ -245,7 +246,7 @@ static struct inode *
 cifs_alloc_inode(struct super_block *sb)
 {
        struct cifsInodeInfo *cifs_inode;
-       cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
+       cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
        if (!cifs_inode)
                return NULL;
        cifs_inode->cifsAttrs = 0x20;   /* default */
@@ -497,7 +498,7 @@ cifs_get_sb(struct file_system_type *fs_type,
 static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                   unsigned long nr_segs, loff_t pos)
 {
-       struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+       struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
        ssize_t written;
 
        written = generic_file_aio_write(iocb, iov, nr_segs, pos);
@@ -510,7 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
        /* origin == SEEK_END => we must revalidate the cached file length */
        if (origin == SEEK_END) {
-               int retval = cifs_revalidate(file->f_dentry);
+               int retval = cifs_revalidate(file->f_path.dentry);
                if (retval < 0)
                        return (loff_t)retval;
        }
@@ -668,7 +669,7 @@ const struct file_operations cifs_dir_ops = {
 };
 
 static void
-cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
+cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
 {
        struct cifsInodeInfo *cifsi = inode;
 
index 6df9dad..068ef51 100644 (file)
@@ -580,6 +580,12 @@ typedef union smb_com_session_setup_andx {
 
 /* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
 
+#define NTLMSSP_SERVER_TYPE    1
+#define NTLMSSP_DOMAIN_TYPE    2
+#define NTLMSSP_FQ_DOMAIN_TYPE 3
+#define NTLMSSP_DNS_DOMAIN_TYPE        4
+#define NTLMSSP_DNS_PARENT_TYPE        5
+
 struct ntlmssp2_name {
        __le16 type;
        __le16 length;
@@ -593,7 +599,7 @@ struct ntlmv2_resp {
        __le64  time;
        __u64  client_chal; /* random */
        __u32  reserved2;
-       struct ntlmssp2_name names[1];
+       struct ntlmssp2_name names[2];
        /* array of name entries could follow ending in minimum 4 byte struct */
 } __attribute__((packed));
 
index 71f7791..2caca06 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/completion.h>
 #include <linux/pagevec.h>
+#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
index d91a3d4..da12b48 100644 (file)
@@ -83,10 +83,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
                return 0;
 
        xid = GetXid();
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_path.dentry);
 
        if(full_path == NULL) {
                rc = -ENOMEM;
index 2436ed8..0f05cab 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pagevec.h>
 #include <linux/smp_lock.h>
 #include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/delay.h>
 #include <asm/div64.h>
 #include "cifsfs.h"
@@ -122,34 +123,34 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
        /* if not oplocked, invalidate inode pages if mtime or file
           size changed */
        temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
-       if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
-                          (file->f_dentry->d_inode->i_size == 
+       if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
+                          (file->f_path.dentry->d_inode->i_size ==
                            (loff_t)le64_to_cpu(buf->EndOfFile))) {
                cFYI(1, ("inode unchanged on server"));
        } else {
-               if (file->f_dentry->d_inode->i_mapping) {
+               if (file->f_path.dentry->d_inode->i_mapping) {
                /* BB no need to lock inode until after invalidate
                   since namei code should already have it locked? */
-                       filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
+                       filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
                }
                cFYI(1, ("invalidating remote inode since open detected it "
                         "changed"));
-               invalidate_remote_inode(file->f_dentry->d_inode);
+               invalidate_remote_inode(file->f_path.dentry->d_inode);
        }
 
 client_can_cache:
        if (pTcon->ses->capabilities & CAP_UNIX)
-               rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+               rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
                        full_path, inode->i_sb, xid);
        else
-               rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+               rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
                        full_path, buf, inode->i_sb, xid);
 
        if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
                pCifsInode->clientCanCacheAll = TRUE;
                pCifsInode->clientCanCacheRead = TRUE;
                cFYI(1, ("Exclusive Oplock granted on inode %p",
-                        file->f_dentry->d_inode));
+                        file->f_path.dentry->d_inode));
        } else if ((*oplock & 0xF) == OPLOCK_READ)
                pCifsInode->clientCanCacheRead = TRUE;
 
@@ -178,7 +179,7 @@ int cifs_open(struct inode *inode, struct file *file)
 
        if (file->f_flags & O_CREAT) {
                /* search inode for this file and fill in file->private_data */
-               pCifsInode = CIFS_I(file->f_dentry->d_inode);
+               pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
                read_lock(&GlobalSMBSeslock);
                list_for_each(tmp, &pCifsInode->openFileList) {
                        pCifsFile = list_entry(tmp, struct cifsFileInfo,
@@ -206,7 +207,7 @@ int cifs_open(struct inode *inode, struct file *file)
                }
        }
 
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
                FreeXid(xid);
                return -ENOMEM;
@@ -291,7 +292,7 @@ int cifs_open(struct inode *inode, struct file *file)
        write_lock(&GlobalSMBSeslock);
        list_add(&pCifsFile->tlist, &pTcon->openFileList);
 
-       pCifsInode = CIFS_I(file->f_dentry->d_inode);
+       pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
        if (pCifsInode) {
                rc = cifs_open_inode_helper(inode, file, pCifsInode,
                                            pCifsFile, pTcon,
@@ -366,7 +367,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
                return 0;
        }
 
-       if (file->f_dentry == NULL) {
+       if (file->f_path.dentry == NULL) {
                up(&pCifsFile->fh_sem);
                cFYI(1, ("failed file reopen, no valid name if dentry freed"));
                FreeXid(xid);
@@ -378,7 +379,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
                up(&pCifsFile->fh_sem);
                FreeXid(xid);
@@ -444,7 +445,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
                                pCifsInode->clientCanCacheAll = TRUE;
                                pCifsInode->clientCanCacheRead = TRUE;
                                cFYI(1, ("Exclusive Oplock granted on inode %p",
-                                        file->f_dentry->d_inode));
+                                        file->f_path.dentry->d_inode));
                        } else if ((oplock & 0xF) == OPLOCK_READ) {
                                pCifsInode->clientCanCacheRead = TRUE;
                                pCifsInode->clientCanCacheAll = FALSE;
@@ -551,7 +552,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
 
        if (pCFileStruct) {
                struct cifsTconInfo *pTcon;
-               struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+               struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 
                pTcon = cifs_sb->tcon;
 
@@ -664,7 +665,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
        } else
                cFYI(1, ("Unknown type of lock"));
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
@@ -791,10 +792,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
        int xid, long_op;
        struct cifsFileInfo *open_file;
 
-       if (file->f_dentry == NULL)
+       if (file->f_path.dentry == NULL)
                return -EBADF;
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        if (cifs_sb == NULL)
                return -EBADF;
 
@@ -802,7 +803,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
 
        /* cFYI(1,
           (" write %d bytes to offset %lld of %s", write_size,
-          *poffset, file->f_dentry->d_name.name)); */
+          *poffset, file->f_path.dentry->d_name.name)); */
 
        if (file->private_data == NULL)
                return -EBADF;
@@ -810,12 +811,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                open_file = (struct cifsFileInfo *) file->private_data;
        
        xid = GetXid();
-       if (file->f_dentry->d_inode == NULL) {
+       if (file->f_path.dentry->d_inode == NULL) {
                FreeXid(xid);
                return -EBADF;
        }
 
-       if (*poffset > file->f_dentry->d_inode->i_size)
+       if (*poffset > file->f_path.dentry->d_inode->i_size)
                long_op = 2; /* writes past end of file can take a long time */
        else
                long_op = 1;
@@ -840,8 +841,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                                        return -EBADF;
                        }
                        if (open_file->invalidHandle) {
-                               if ((file->f_dentry == NULL) ||
-                                   (file->f_dentry->d_inode == NULL)) {
+                               if ((file->f_path.dentry == NULL) ||
+                                   (file->f_path.dentry->d_inode == NULL)) {
                                        FreeXid(xid);
                                        return total_written;
                                }
@@ -849,7 +850,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to server
                                   now */
-                               rc = cifs_reopen_file(file->f_dentry->d_inode,
+                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
                                        file, FALSE);
                                if (rc != 0)
                                        break;
@@ -878,17 +879,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
        cifs_stats_bytes_written(pTcon, total_written);
 
        /* since the write may have blocked check these pointers again */
-       if (file->f_dentry) {
-               if (file->f_dentry->d_inode) {
-                       struct inode *inode = file->f_dentry->d_inode;
+       if (file->f_path.dentry) {
+               if (file->f_path.dentry->d_inode) {
+                       struct inode *inode = file->f_path.dentry->d_inode;
                        inode->i_ctime = inode->i_mtime =
                                current_fs_time(inode->i_sb);
                        if (total_written > 0) {
-                               if (*poffset > file->f_dentry->d_inode->i_size)
-                                       i_size_write(file->f_dentry->d_inode,
+                               if (*poffset > file->f_path.dentry->d_inode->i_size)
+                                       i_size_write(file->f_path.dentry->d_inode,
                                        *poffset);
                        }
-                       mark_inode_dirty_sync(file->f_dentry->d_inode);
+                       mark_inode_dirty_sync(file->f_path.dentry->d_inode);
                }
        }
        FreeXid(xid);
@@ -906,17 +907,17 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        int xid, long_op;
        struct cifsFileInfo *open_file;
 
-       if (file->f_dentry == NULL)
+       if (file->f_path.dentry == NULL)
                return -EBADF;
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        if (cifs_sb == NULL)
                return -EBADF;
 
        pTcon = cifs_sb->tcon;
 
        cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
-          *poffset, file->f_dentry->d_name.name));
+          *poffset, file->f_path.dentry->d_name.name));
 
        if (file->private_data == NULL)
                return -EBADF;
@@ -924,12 +925,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                open_file = (struct cifsFileInfo *)file->private_data;
        
        xid = GetXid();
-       if (file->f_dentry->d_inode == NULL) {
+       if (file->f_path.dentry->d_inode == NULL) {
                FreeXid(xid);
                return -EBADF;
        }
 
-       if (*poffset > file->f_dentry->d_inode->i_size)
+       if (*poffset > file->f_path.dentry->d_inode->i_size)
                long_op = 2; /* writes past end of file can take a long time */
        else
                long_op = 1;
@@ -955,8 +956,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                                        return -EBADF;
                        }
                        if (open_file->invalidHandle) {
-                               if ((file->f_dentry == NULL) ||
-                                  (file->f_dentry->d_inode == NULL)) {
+                               if ((file->f_path.dentry == NULL) ||
+                                  (file->f_path.dentry->d_inode == NULL)) {
                                        FreeXid(xid);
                                        return total_written;
                                }
@@ -964,7 +965,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to 
                                   server now */
-                               rc = cifs_reopen_file(file->f_dentry->d_inode,
+                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
                                        file, FALSE);
                                if (rc != 0)
                                        break;
@@ -1011,16 +1012,16 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        cifs_stats_bytes_written(pTcon, total_written);
 
        /* since the write may have blocked check these pointers again */
-       if (file->f_dentry) {
-               if (file->f_dentry->d_inode) {
-                       file->f_dentry->d_inode->i_ctime = 
-                       file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+       if (file->f_path.dentry) {
+               if (file->f_path.dentry->d_inode) {
+                       file->f_path.dentry->d_inode->i_ctime =
+                       file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;
                        if (total_written > 0) {
-                               if (*poffset > file->f_dentry->d_inode->i_size)
-                                       i_size_write(file->f_dentry->d_inode, 
+                               if (*poffset > file->f_path.dentry->d_inode->i_size)
+                                       i_size_write(file->f_path.dentry->d_inode,
                                                     *poffset);
                        }
-                       mark_inode_dirty_sync(file->f_dentry->d_inode);
+                       mark_inode_dirty_sync(file->f_path.dentry->d_inode);
                }
        }
        FreeXid(xid);
@@ -1384,7 +1385,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
                                if ((open_file->invalidHandle) && 
                                    (!open_file->closePend)) {
                                        rc = cifs_reopen_file(
-                                               file->f_dentry->d_inode, file);
+                                               file->f_path.dentry->d_inode, file);
                                        if (rc != 0)
                                                break;
                                }
@@ -1434,7 +1435,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
        int xid;
        int rc = 0;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        xid = GetXid();
 
@@ -1482,7 +1483,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
  */
 int cifs_flush(struct file *file, fl_owner_t id)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        int rc = 0;
 
        /* Rather than do the steps manually:
@@ -1519,7 +1520,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
        struct smb_com_read_rsp *pSMBr;
 
        xid = GetXid();
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
@@ -1542,7 +1543,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
                        int buf_type = CIFS_NO_BUFFER;
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_dentry->d_inode,
+                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
                                        file, TRUE);
                                if (rc != 0)
                                        break;
@@ -1601,7 +1602,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
        int buf_type = CIFS_NO_BUFFER;
 
        xid = GetXid();
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
@@ -1629,7 +1630,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_dentry->d_inode,
+                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
                                        file, TRUE);
                                if (rc != 0)
                                        break;
@@ -1658,7 +1659,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
 
 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        int rc, xid;
 
        xid = GetXid();
@@ -1744,7 +1745,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                return -EBADF;
        }
        open_file = (struct cifsFileInfo *)file->private_data;
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
        pagevec_init(&lru_pvec, 0);
@@ -1786,7 +1787,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) && 
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file->f_dentry->d_inode,
+                               rc = cifs_reopen_file(file->f_path.dentry->d_inode,
                                        file, TRUE);
                                if (rc != 0)
                                        break;
@@ -1812,6 +1813,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                        cFYI(1, ("Read error in readpages: %d", rc));
                        break;
                } else if (bytes_read > 0) {
+                       task_io_account_read(bytes_read);
                        pSMBr = (struct smb_com_read_rsp *)smb_read_data;
                        cifs_copy_cache_pages(mapping, page_list, bytes_read,
                                smb_read_data + 4 /* RFC1001 hdr */ +
@@ -1880,8 +1882,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
        else
                cFYI(1, ("Bytes read %d",rc));
                                                                                                                            
-       file->f_dentry->d_inode->i_atime =
-               current_fs_time(file->f_dentry->d_inode->i_sb);
+       file->f_path.dentry->d_inode->i_atime =
+               current_fs_time(file->f_path.dentry->d_inode->i_sb);
                                                                                                                            
        if (PAGE_CACHE_SIZE > rc)
                memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
index bbc9cd3..aedf683 100644 (file)
@@ -153,7 +153,7 @@ cifs_buf_get(void)
    albeit slightly larger than necessary and maxbuffersize 
    defaults to this and can not be bigger */
        ret_buf =
-           (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS);
+           (struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS);
 
        /* clear the first few header bytes */
        /* for most paths, more is cleared in header_assemble */
@@ -192,7 +192,7 @@ cifs_small_buf_get(void)
    albeit slightly larger than necessary and maxbuffersize 
    defaults to this and can not be bigger */
        ret_buf =
-           (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS);
+           (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS);
        if (ret_buf) {
        /* No need to clear memory here, cleared in header assemble */
        /*      memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
index ed18c39..99dfb53 100644 (file)
@@ -68,30 +68,30 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
        int rc = 0;
 
        cFYI(1, ("For %s", qstring->name));
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
        qstring->hash = full_name_hash(qstring->name, qstring->len);
-       tmp_dentry = d_lookup(file->f_dentry, qstring);
+       tmp_dentry = d_lookup(file->f_path.dentry, qstring);
        if (tmp_dentry) {
                cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
                *ptmp_inode = tmp_dentry->d_inode;
 /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
                if(*ptmp_inode == NULL) {
-                       *ptmp_inode = new_inode(file->f_dentry->d_sb);
+                       *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
                        if(*ptmp_inode == NULL)
                                return rc;
                        rc = 1;
                }
        } else {
-               tmp_dentry = d_alloc(file->f_dentry, qstring);
+               tmp_dentry = d_alloc(file->f_path.dentry, qstring);
                if(tmp_dentry == NULL) {
                        cERROR(1,("Failed allocating dentry"));
                        *ptmp_inode = NULL;
                        return rc;
                }
 
-               *ptmp_inode = new_inode(file->f_dentry->d_sb);
+               *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
                if (pTcon->nocase)
                        tmp_dentry->d_op = &cifs_ci_dentry_ops;
                else
@@ -432,10 +432,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
        cifsFile->invalidHandle = TRUE;
        cifsFile->srch_inf.endOfSearch = FALSE;
 
-       if(file->f_dentry == NULL)
+       if(file->f_path.dentry == NULL)
                return -ENOENT;
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        if(cifs_sb == NULL)
                return -EINVAL;
 
@@ -443,7 +443,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
        if(pTcon == NULL)
                return -EINVAL;
 
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_path.dentry);
 
        if(full_path == NULL) {
                return -ENOMEM;
@@ -609,10 +609,10 @@ static int is_dir_changed(struct file * file)
        struct inode * inode;
        struct cifsInodeInfo *cifsInfo;
 
-       if(file->f_dentry == NULL)
+       if(file->f_path.dentry == NULL)
                return 0;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 
        if(inode == NULL)
                return 0;
@@ -839,7 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
        if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
                return -ENOENT;
 
-       if(file->f_dentry == NULL)
+       if(file->f_path.dentry == NULL)
                return -ENOENT;
 
        rc = cifs_entry_is_dot(pfindEntry,pCifsF);
@@ -847,7 +847,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
        if(rc != 0) 
                return 0;
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 
        qstring.name = scratch_buf;
        rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
@@ -985,12 +985,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 
        xid = GetXid();
 
-       if(file->f_dentry == NULL) {
+       if(file->f_path.dentry == NULL) {
                FreeXid(xid);
                return -EIO;
        }
 
-       cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
        if(pTcon == NULL)
                return -EINVAL;
@@ -998,7 +998,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
        switch ((int) file->f_pos) {
        case 0:
                if (filldir(direntry, ".", 1, file->f_pos,
-                    file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
+                    file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
                        cERROR(1, ("Filldir for current dir failed"));
                        rc = -ENOMEM;
                        break;
@@ -1006,7 +1006,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
                file->f_pos++;
        case 1:
                if (filldir(direntry, "..", 2, file->f_pos,
-                    file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+                    file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
                        cERROR(1, ("Filldir for parent dir failed"));
                        rc = -ENOMEM;
                        break;
index 48d47b4..f80007e 100644 (file)
@@ -34,7 +34,7 @@
 #include "cifs_debug.h"
   
 extern mempool_t *cifs_mid_poolp;
-extern kmem_cache_t *cifs_oplock_cachep;
+extern struct kmem_cache *cifs_oplock_cachep;
 
 static struct mid_q_entry *
 AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
@@ -51,7 +51,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
        }
        
        temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
-                                                   SLAB_KERNEL | SLAB_NOFS);
+                                                   GFP_KERNEL | GFP_NOFS);
        if (temp == NULL)
                return temp;
        else {
@@ -118,7 +118,7 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
                return NULL;
        }
        temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
-                                                      SLAB_KERNEL);
+                                                      GFP_KERNEL);
        if (temp == NULL)
                return temp;
        else {
index 0102b28..0c6f7f3 100644 (file)
@@ -441,7 +441,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
 /* file operations for directories */
 int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
 {
-       struct dentry *coda_dentry = coda_file->f_dentry;
+       struct dentry *coda_dentry = coda_file->f_path.dentry;
        struct coda_file_info *cfi;
        struct file *host_file;
        struct inode *host_inode;
@@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
 
        coda_vfs_stat.readdir++;
 
-       host_inode = host_file->f_dentry->d_inode;
+       host_inode = host_file->f_path.dentry->d_inode;
        mutex_lock(&host_inode->i_mutex);
        host_file->f_pos = coda_file->f_pos;
 
@@ -544,14 +544,14 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
                /* catch truncated reads */
                if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
                        printk("coda_venus_readdir: short read: %ld\n",
-                              filp->f_dentry->d_inode->i_ino);
+                              filp->f_path.dentry->d_inode->i_ino);
                        ret = -EBADF;
                        break;
                }
                /* validate whether the directory file actually makes sense */
                if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
                        printk("coda_venus_readdir: Invalid dir: %ld\n",
-                              filp->f_dentry->d_inode->i_ino);
+                              filp->f_path.dentry->d_inode->i_ino);
                        ret = -EBADF;
                        break;
                }
index dbfbcfa..5ef2b60 100644 (file)
@@ -66,7 +66,7 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
 static ssize_t
 coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
+       struct inode *host_inode, *coda_inode = coda_file->f_path.dentry->d_inode;
        struct coda_file_info *cfi;
        struct file *host_file;
        ssize_t ret;
@@ -78,7 +78,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
        if (!host_file->f_op || !host_file->f_op->write)
                return -EINVAL;
 
-       host_inode = host_file->f_dentry->d_inode;
+       host_inode = host_file->f_path.dentry->d_inode;
        mutex_lock(&coda_inode->i_mutex);
 
        ret = host_file->f_op->write(host_file, buf, count, ppos);
@@ -106,8 +106,8 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
        if (!host_file->f_op || !host_file->f_op->mmap)
                return -ENODEV;
 
-       coda_inode = coda_file->f_dentry->d_inode;
-       host_inode = host_file->f_dentry->d_inode;
+       coda_inode = coda_file->f_path.dentry->d_inode;
+       host_inode = host_file->f_path.dentry->d_inode;
        coda_file->f_mapping = host_file->f_mapping;
        if (coda_inode->i_mapping == &coda_inode->i_data)
                coda_inode->i_mapping = host_inode->i_mapping;
@@ -190,7 +190,7 @@ int coda_flush(struct file *coda_file, fl_owner_t id)
        cfi = CODA_FTOC(coda_file);
        BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 
-       coda_inode = coda_file->f_dentry->d_inode;
+       coda_inode = coda_file->f_path.dentry->d_inode;
 
        err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
                          coda_file->f_uid);
@@ -233,7 +233,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
                err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
                                  coda_flags, coda_file->f_uid);
 
-       host_inode = cfi->cfi_container->f_dentry->d_inode;
+       host_inode = cfi->cfi_container->f_path.dentry->d_inode;
        cii = ITOC(coda_inode);
 
        /* did we mmap this file? */
@@ -270,7 +270,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
        coda_vfs_stat.fsync++;
 
        if (host_file->f_op && host_file->f_op->fsync) {
-               host_dentry = host_file->f_dentry;
+               host_dentry = host_file->f_path.dentry;
                host_inode = host_dentry->d_inode;
                mutex_lock(&host_inode->i_mutex);
                err = host_file->f_op->fsync(host_file, host_dentry, datasync);
index 88d1233..01395de 100644 (file)
@@ -38,12 +38,12 @@ static void coda_clear_inode(struct inode *);
 static void coda_put_super(struct super_block *);
 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
 
-static kmem_cache_t * coda_inode_cachep;
+static struct kmem_cache * coda_inode_cachep;
 
 static struct inode *coda_alloc_inode(struct super_block *sb)
 {
        struct coda_inode_info *ei;
-       ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, SLAB_KERNEL);
+       ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        memset(&ei->c_fid, 0, sizeof(struct CodaFid));
@@ -58,7 +58,7 @@ static void coda_destroy_inode(struct inode *inode)
        kmem_cache_free(coda_inode_cachep, ITOC(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct coda_inode_info *ei = (struct coda_inode_info *) foo;
 
@@ -119,7 +119,7 @@ static int get_device_index(struct coda_mount_data *data)
        file = fget(data->fd);
        inode = NULL;
        if(file)
-               inode = file->f_dentry->d_inode;
+               inode = file->f_path.dentry->d_inode;
        
        if(!inode || !S_ISCHR(inode->i_mode) ||
           imajor(inode) != CODA_PSDEV_MAJOR) {
index 06dad66..0ec70e3 100644 (file)
@@ -232,7 +232,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs(file->f_dentry, &tmp);
+       error = vfs_statfs(file->f_path.dentry, &tmp);
        if (!error)
                error = put_compat_statfs(buf, &tmp);
        fput(file);
@@ -303,7 +303,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs(file->f_dentry, &tmp);
+       error = vfs_statfs(file->f_path.dentry, &tmp);
        if (!error)
                error = put_compat_statfs64(buf, &tmp);
        fput(file);
@@ -365,7 +365,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd,
        /* find the name of the device. */
        path = (char *)__get_free_page(GFP_KERNEL);
        if (path) {
-               fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE);
+               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
                if (IS_ERR(fn))
                        fn = "?";
        }
@@ -416,7 +416,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
        case FIBMAP:
        case FIGETBSZ:
        case FIONREAD:
-               if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
                        break;
                /*FALL THROUGH*/
 
@@ -438,7 +438,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
                        goto found_handler;
        }
 
-       if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
+       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
            cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                error = siocdevprivate_ioctl(fd, cmd, arg);
        } else {
@@ -871,7 +871,7 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
 
        retval = -EINVAL;
 
-       if (type_page) {
+       if (type_page && data_page) {
                if (!strcmp((char *)type_page, SMBFS_NAME)) {
                        do_smb_super_data_conv((void *)data_page);
                } else if (!strcmp((char *)type_page, NCPFS_NAME)) {
@@ -1144,7 +1144,9 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
        lastdirent = buf.previous;
        if (lastdirent) {
                typeof(lastdirent->d_off) d_off = file->f_pos;
-               __put_user_unaligned(d_off, &lastdirent->d_off);
+               error = -EFAULT;
+               if (__put_user_unaligned(d_off, &lastdirent->d_off))
+                       goto out_putf;
                error = count - buf.count;
        }
 
@@ -1257,7 +1259,7 @@ out:
        if (iov != iovstack)
                kfree(iov);
        if ((ret + (type == READ)) > 0) {
-               struct dentry *dentry = file->f_dentry;
+               struct dentry *dentry = file->f_path.dentry;
                if (type == READ)
                        fsnotify_access(dentry);
                else
@@ -1611,14 +1613,14 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                nr &= ~1UL;
                while (nr) {
                        unsigned long h, l;
-                       __get_user(l, ufdset);
-                       __get_user(h, ufdset+1);
+                       if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
+                               return -EFAULT;
                        ufdset += 2;
                        *fdset++ = h << 32 | l;
                        nr -= 2;
                }
-               if (odd)
-                       __get_user(*fdset, ufdset);
+               if (odd && __get_user(*fdset, ufdset))
+                       return -EFAULT;
        } else {
                /* Tricky, must clear full unsigned long in the
                 * kernel fdset at the end, this makes sure that
@@ -1630,14 +1632,14 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
 }
 
 static
-void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
-                       unsigned long *fdset)
+int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
+                     unsigned long *fdset)
 {
        unsigned long odd;
        nr = ROUND_UP(nr, __COMPAT_NFDBITS);
 
        if (!ufdset)
-               return;
+               return 0;
 
        odd = nr & 1UL;
        nr &= ~1UL;
@@ -1645,13 +1647,14 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                unsigned long h, l;
                l = *fdset++;
                h = l >> 32;
-               __put_user(l, ufdset);
-               __put_user(h, ufdset+1);
+               if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
+                       return -EFAULT;
                ufdset += 2;
                nr -= 2;
        }
-       if (odd)
-               __put_user(*fdset, ufdset);
+       if (odd && __put_user(*fdset, ufdset))
+               return -EFAULT;
+       return 0;
 }
 
 
@@ -1676,19 +1679,19 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
 {
        fd_set_bits fds;
        char *bits;
-       int size, max_fdset, ret = -EINVAL;
+       int size, max_fds, ret = -EINVAL;
        struct fdtable *fdt;
 
        if (n < 0)
                goto out_nofds;
 
-       /* max_fdset can increase, so grab it once to avoid race */
+       /* max_fds can increase, so grab it once to avoid race */
        rcu_read_lock();
        fdt = files_fdtable(current->files);
-       max_fdset = fdt->max_fdset;
+       max_fds = fdt->max_fds;
        rcu_read_unlock();
-       if (n > max_fdset)
-               n = max_fdset;
+       if (n > max_fds)
+               n = max_fds;
 
        /*
         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
@@ -1726,10 +1729,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
                ret = 0;
        }
 
-       compat_set_fd_set(n, inp, fds.res_in);
-       compat_set_fd_set(n, outp, fds.res_out);
-       compat_set_fd_set(n, exp, fds.res_ex);
-
+       if (compat_set_fd_set(n, inp, fds.res_in) ||
+           compat_set_fd_set(n, outp, fds.res_out) ||
+           compat_set_fd_set(n, exp, fds.res_ex))
+               ret = -EFAULT;
 out:
        kfree(bits);
 out_nofds:
index a91f262..c81c958 100644 (file)
@@ -211,8 +211,10 @@ static int do_video_stillpicture(unsigned int fd, unsigned int cmd, unsigned lon
        up_native =
                compat_alloc_user_space(sizeof(struct video_still_picture));
 
-       put_user(compat_ptr(fp), &up_native->iFrame);
-       put_user(size, &up_native->size);
+       err =  put_user(compat_ptr(fp), &up_native->iFrame);
+       err |= put_user(size, &up_native->size);
+       if (err)
+               return -EFAULT;
 
        err = sys_ioctl(fd, cmd, (unsigned long) up_native);
 
@@ -236,8 +238,10 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned
        err |= get_user(length, &up->length);
 
        up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
-       put_user(compat_ptr(palp), &up_native->palette);
-       put_user(length, &up_native->length);
+       err  = put_user(compat_ptr(palp), &up_native->palette);
+       err |= put_user(length, &up_native->length);
+       if (err)
+               return -EFAULT;
 
        err = sys_ioctl(fd, cmd, (unsigned long) up_native);
 
@@ -1173,7 +1177,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
 static int vt_check(struct file *file)
 {
        struct tty_struct *tty;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        
        if (file->f_op->ioctl != tty_ioctl)
                return -EINVAL;
@@ -2043,16 +2047,19 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
         struct serial_struct ss;
         mm_segment_t oldseg = get_fs();
         __u32 udata;
+       unsigned int base;
 
         if (cmd == TIOCSSERIAL) {
                 if (!access_ok(VERIFY_READ, ss32, sizeof(SS32)))
                         return -EFAULT;
                 if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)))
                        return -EFAULT;
-                __get_user(udata, &ss32->iomem_base);
+                if (__get_user(udata, &ss32->iomem_base))
+                       return -EFAULT;
                 ss.iomem_base = compat_ptr(udata);
-                __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
-                __get_user(ss.port_high, &ss32->port_high);
+                if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) ||
+                   __get_user(ss.port_high, &ss32->port_high))
+                       return -EFAULT;
                 ss.iomap_base = 0UL;
         }
         set_fs(KERNEL_DS);
@@ -2063,12 +2070,12 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
                         return -EFAULT;
                 if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)))
                        return -EFAULT;
-                __put_user((unsigned long)ss.iomem_base  >> 32 ?
-                            0xffffffff : (unsigned)(unsigned long)ss.iomem_base,
-                            &ss32->iomem_base);
-                __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
-                __put_user(ss.port_high, &ss32->port_high);
-
+               base = (unsigned long)ss.iomem_base  >> 32 ?
+                       0xffffffff : (unsigned)(unsigned long)ss.iomem_base;
+               if (__put_user(base, &ss32->iomem_base) ||
+                   __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) ||
+                   __put_user(ss.port_high, &ss32->port_high))
+                       return -EFAULT;
         }
         return err;
 }
@@ -2397,6 +2404,7 @@ HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFHWBROADCAST, dev_ifsioc)
 
 /* ioctls used by appletalk ddp.c */
 HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc)
index 3f4ff7a..f92cd30 100644 (file)
@@ -49,7 +49,7 @@ struct configfs_dirent {
 #define CONFIGFS_NOT_PINNED    (CONFIGFS_ITEM_ATTR)
 
 extern struct vfsmount * configfs_mount;
-extern kmem_cache_t *configfs_dir_cachep;
+extern struct kmem_cache *configfs_dir_cachep;
 
 extern int configfs_is_root(struct config_item *item);
 
index c398861..1814ba4 100644 (file)
@@ -980,7 +980,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name)
 
 static int configfs_dir_open(struct inode *inode, struct file *file)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        struct configfs_dirent * parent_sd = dentry->d_fsdata;
 
        mutex_lock(&dentry->d_inode->i_mutex);
@@ -993,7 +993,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
 
 static int configfs_dir_close(struct inode *inode, struct file *file)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        struct configfs_dirent * cursor = file->private_data;
 
        mutex_lock(&dentry->d_inode->i_mutex);
@@ -1013,7 +1013,7 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
 
 static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct configfs_dirent * parent_sd = dentry->d_fsdata;
        struct configfs_dirent *cursor = filp->private_data;
        struct list_head *p, *q = &cursor->s_sibling;
@@ -1070,7 +1070,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
 
 static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
 
        mutex_lock(&dentry->d_inode->i_mutex);
        switch (origin) {
@@ -1080,7 +1080,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+                       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
index cf33fac..2a7cb08 100644 (file)
@@ -134,7 +134,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
 
        down(&buffer->sem);
        if (buffer->needs_read_fill) {
-               if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+               if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
                        goto out;
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -222,7 +222,7 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
        down(&buffer->sem);
        len = fill_write_buffer(buffer, buf, count);
        if (len > 0)
-               len = flush_write_buffer(file->f_dentry, buffer, count);
+               len = flush_write_buffer(file->f_path.dentry, buffer, count);
        if (len > 0)
                *ppos += len;
        up(&buffer->sem);
@@ -231,8 +231,8 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
 
 static int check_perm(struct inode * inode, struct file * file)
 {
-       struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent);
-       struct configfs_attribute * attr = to_attr(file->f_dentry);
+       struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
+       struct configfs_attribute * attr = to_attr(file->f_path.dentry);
        struct configfs_buffer * buffer;
        struct configfs_item_operations * ops = NULL;
        int error = 0;
@@ -305,8 +305,8 @@ static int configfs_open_file(struct inode * inode, struct file * filp)
 
 static int configfs_release(struct inode * inode, struct file * filp)
 {
-       struct config_item * item = to_item(filp->f_dentry->d_parent);
-       struct configfs_attribute * attr = to_attr(filp->f_dentry);
+       struct config_item * item = to_item(filp->f_path.dentry->d_parent);
+       struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
        struct module * owner = attr->ca_owner;
        struct configfs_buffer * buffer = filp->private_data;
 
index 68bd5c9..ed67852 100644 (file)
@@ -38,7 +38,7 @@
 
 struct vfsmount * configfs_mount = NULL;
 struct super_block * configfs_sb = NULL;
-kmem_cache_t *configfs_dir_cachep;
+struct kmem_cache *configfs_dir_cachep;
 static int configfs_mnt_count = 0;
 
 static struct super_operations configfs_ops = {
index a624c3e..6db03fb 100644 (file)
@@ -338,7 +338,7 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  */
 static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        char *buf;
        unsigned int offset;
@@ -481,6 +481,8 @@ static int cramfs_readpage(struct file *file, struct page * page)
                pgdata = kmap(page);
                if (compr_len == 0)
                        ; /* hole */
+               else if (compr_len > (PAGE_CACHE_SIZE << 1))
+                       printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len);
                else {
                        mutex_lock(&read_mutex);
                        bytes_filled = cramfs_uncompress_block(pgdata,
index fd4a428..d68631f 100644 (file)
@@ -43,7 +43,7 @@ static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
 
 EXPORT_SYMBOL(dcache_lock);
 
-static kmem_cache_t *dentry_cache __read_mostly;
+static struct kmem_cache *dentry_cache __read_mostly;
 
 #define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
 
@@ -68,15 +68,19 @@ struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
 };
 
-static void d_callback(struct rcu_head *head)
+static void __d_free(struct dentry *dentry)
 {
-       struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu);
-
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
 }
 
+static void d_callback(struct rcu_head *head)
+{
+       struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu);
+       __d_free(dentry);
+}
+
 /*
  * no dcache_lock, please.  The caller must decrement dentry_stat.nr_dentry
  * inside dcache_lock.
@@ -85,7 +89,11 @@ static void d_free(struct dentry *dentry)
 {
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
-       call_rcu(&dentry->d_u.d_rcu, d_callback);
+       /* if dentry was never inserted into hash, immediate free is OK */
+       if (dentry->d_hash.pprev == NULL)
+               __d_free(dentry);
+       else
+               call_rcu(&dentry->d_u.d_rcu, d_callback);
 }
 
 /*
@@ -2072,10 +2080,10 @@ static void __init dcache_init(unsigned long mempages)
 }
 
 /* SLAB cache for __getname() consumers */
-kmem_cache_t *names_cachep __read_mostly;
+struct kmem_cache *names_cachep __read_mostly;
 
 /* SLAB cache for file structures */
-kmem_cache_t *filp_cachep __read_mostly;
+struct kmem_cache *filp_cachep __read_mostly;
 
 EXPORT_SYMBOL(d_genocide);
 
index 0c4b067..21af162 100644 (file)
@@ -37,7 +37,7 @@ struct dcookie_struct {
 
 static LIST_HEAD(dcookie_users);
 static DEFINE_MUTEX(dcookie_mutex);
-static kmem_cache_t *dcookie_cache __read_mostly;
+static struct kmem_cache *dcookie_cache __read_mostly;
 static struct list_head *dcookie_hashtable __read_mostly;
 static size_t hash_size __read_mostly;
 
index 5981e17..d9d0833 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/bio.h>
 #include <linux/wait.h>
 #include <linux/err.h>
@@ -121,8 +122,7 @@ struct dio {
 
        /* BIO completion state */
        spinlock_t bio_lock;            /* protects BIO fields below */
-       int bio_count;                  /* nr bios to be completed */
-       int bios_in_flight;             /* nr bios in flight */
+       unsigned long refcount;         /* direct_io_worker() and bios */
        struct bio *bio_list;           /* singly linked via bi_private */
        struct task_struct *waiter;     /* waiting task (NULL if none) */
 
@@ -209,76 +209,55 @@ static struct page *dio_get_page(struct dio *dio)
        return dio->pages[dio->head++];
 }
 
-/*
- * Called when all DIO BIO I/O has been completed - let the filesystem
- * know, if it registered an interest earlier via get_block.  Pass the
- * private field of the map buffer_head so that filesystems can use it
- * to hold additional state between get_block calls and dio_complete.
- */
-static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
-{
-       if (dio->end_io && dio->result)
-               dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
-       if (dio->lock_type == DIO_LOCKING)
-               /* lockdep: non-owner release */
-               up_read_non_owner(&dio->inode->i_alloc_sem);
-}
-
-/*
- * Called when a BIO has been processed.  If the count goes to zero then IO is
- * complete and we can signal this to the AIO layer.
+/**
+ * dio_complete() - called when all DIO BIO I/O has been completed
+ * @offset: the byte offset in the file of the completed operation
+ *
+ * This releases locks as dictated by the locking type, lets interested parties
+ * know that a DIO operation has completed, and calculates the resulting return
+ * code for the operation.
+ *
+ * It lets the filesystem know if it registered an interest earlier via
+ * get_block.  Pass the private field of the map buffer_head so that
+ * filesystems can use it to hold additional state between get_block calls and
+ * dio_complete.
  */
-static void finished_one_bio(struct dio *dio)
+static int dio_complete(struct dio *dio, loff_t offset, int ret)
 {
-       unsigned long flags;
+       ssize_t transferred = 0;
 
-       spin_lock_irqsave(&dio->bio_lock, flags);
-       if (dio->bio_count == 1) {
-               if (dio->is_async) {
-                       ssize_t transferred;
-                       loff_t offset;
-
-                       /*
-                        * Last reference to the dio is going away.
-                        * Drop spinlock and complete the DIO.
-                        */
-                       spin_unlock_irqrestore(&dio->bio_lock, flags);
+       /*
+        * AIO submission can race with bio completion to get here while
+        * expecting to have the last io completed by bio completion.
+        * In that case -EIOCBQUEUED is in fact not an error we want
+        * to preserve through this call.
+        */
+       if (ret == -EIOCBQUEUED)
+               ret = 0;
 
-                       /* Check for short read case */
-                       transferred = dio->result;
-                       offset = dio->iocb->ki_pos;
+       if (dio->result) {
+               transferred = dio->result;
 
-                       if ((dio->rw == READ) &&
-                           ((offset + transferred) > dio->i_size))
-                               transferred = dio->i_size - offset;
+               /* Check for short read case */
+               if ((dio->rw == READ) && ((offset + transferred) > dio->i_size))
+                       transferred = dio->i_size - offset;
+       }
 
-                       /* check for error in completion path */
-                       if (dio->io_error)
-                               transferred = dio->io_error;
+       if (dio->end_io && dio->result)
+               dio->end_io(dio->iocb, offset, transferred,
+                           dio->map_bh.b_private);
+       if (dio->lock_type == DIO_LOCKING)
+               /* lockdep: non-owner release */
+               up_read_non_owner(&dio->inode->i_alloc_sem);
 
-                       dio_complete(dio, offset, transferred);
+       if (ret == 0)
+               ret = dio->page_errors;
+       if (ret == 0)
+               ret = dio->io_error;
+       if (ret == 0)
+               ret = transferred;
 
-                       /* Complete AIO later if falling back to buffered i/o */
-                       if (dio->result == dio->size ||
-                               ((dio->rw == READ) && dio->result)) {
-                               aio_complete(dio->iocb, transferred, 0);
-                               kfree(dio);
-                               return;
-                       } else {
-                               /*
-                                * Falling back to buffered
-                                */
-                               spin_lock_irqsave(&dio->bio_lock, flags);
-                               dio->bio_count--;
-                               if (dio->waiter)
-                                       wake_up_process(dio->waiter);
-                               spin_unlock_irqrestore(&dio->bio_lock, flags);
-                               return;
-                       }
-               }
-       }
-       dio->bio_count--;
-       spin_unlock_irqrestore(&dio->bio_lock, flags);
+       return ret;
 }
 
 static int dio_bio_complete(struct dio *dio, struct bio *bio);
@@ -288,12 +267,27 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio);
 static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error)
 {
        struct dio *dio = bio->bi_private;
+       unsigned long remaining;
+       unsigned long flags;
 
        if (bio->bi_size)
                return 1;
 
        /* cleanup the bio */
        dio_bio_complete(dio, bio);
+
+       spin_lock_irqsave(&dio->bio_lock, flags);
+       remaining = --dio->refcount;
+       if (remaining == 1 && dio->waiter)
+               wake_up_process(dio->waiter);
+       spin_unlock_irqrestore(&dio->bio_lock, flags);
+
+       if (remaining == 0) {
+               int ret = dio_complete(dio, dio->iocb->ki_pos, 0);
+               aio_complete(dio->iocb, ret, 0);
+               kfree(dio);
+       }
+
        return 0;
 }
 
@@ -315,8 +309,7 @@ static int dio_bio_end_io(struct bio *bio, unsigned int bytes_done, int error)
        spin_lock_irqsave(&dio->bio_lock, flags);
        bio->bi_private = dio->bio_list;
        dio->bio_list = bio;
-       dio->bios_in_flight--;
-       if (dio->waiter && dio->bios_in_flight == 0)
+       if (--dio->refcount == 1 && dio->waiter)
                wake_up_process(dio->waiter);
        spin_unlock_irqrestore(&dio->bio_lock, flags);
        return 0;
@@ -347,6 +340,8 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev,
  * In the AIO read case we speculatively dirty the pages before starting IO.
  * During IO completion, any of these pages which happen to have been written
  * back will be redirtied by bio_check_pages_dirty().
+ *
+ * bios hold a dio reference between submit_bio and ->end_io.
  */
 static void dio_bio_submit(struct dio *dio)
 {
@@ -354,12 +349,14 @@ static void dio_bio_submit(struct dio *dio)
        unsigned long flags;
 
        bio->bi_private = dio;
+
        spin_lock_irqsave(&dio->bio_lock, flags);
-       dio->bio_count++;
-       dio->bios_in_flight++;
+       dio->refcount++;
        spin_unlock_irqrestore(&dio->bio_lock, flags);
+
        if (dio->is_async && dio->rw == READ)
                bio_set_pages_dirty(bio);
+
        submit_bio(dio->rw, bio);
 
        dio->bio = NULL;
@@ -376,28 +373,37 @@ static void dio_cleanup(struct dio *dio)
 }
 
 /*
- * Wait for the next BIO to complete.  Remove it and return it.
+ * Wait for the next BIO to complete.  Remove it and return it.  NULL is
+ * returned once all BIOs have been completed.  This must only be called once
+ * all bios have been issued so that dio->refcount can only decrease.  This
+ * requires that that the caller hold a reference on the dio.
  */
 static struct bio *dio_await_one(struct dio *dio)
 {
        unsigned long flags;
-       struct bio *bio;
+       struct bio *bio = NULL;
 
        spin_lock_irqsave(&dio->bio_lock, flags);
-       while (dio->bio_list == NULL) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               if (dio->bio_list == NULL) {
-                       dio->waiter = current;
-                       spin_unlock_irqrestore(&dio->bio_lock, flags);
-                       blk_run_address_space(dio->inode->i_mapping);
-                       io_schedule();
-                       spin_lock_irqsave(&dio->bio_lock, flags);
-                       dio->waiter = NULL;
-               }
-               set_current_state(TASK_RUNNING);
+
+       /*
+        * Wait as long as the list is empty and there are bios in flight.  bio
+        * completion drops the count, maybe adds to the list, and wakes while
+        * holding the bio_lock so we don't need set_current_state()'s barrier
+        * and can call it after testing our condition.
+        */
+       while (dio->refcount > 1 && dio->bio_list == NULL) {
+               __set_current_state(TASK_UNINTERRUPTIBLE);
+               dio->waiter = current;
+               spin_unlock_irqrestore(&dio->bio_lock, flags);
+               io_schedule();
+               /* wake up sets us TASK_RUNNING */
+               spin_lock_irqsave(&dio->bio_lock, flags);
+               dio->waiter = NULL;
+       }
+       if (dio->bio_list) {
+               bio = dio->bio_list;
+               dio->bio_list = bio->bi_private;
        }
-       bio = dio->bio_list;
-       dio->bio_list = bio->bi_private;
        spin_unlock_irqrestore(&dio->bio_lock, flags);
        return bio;
 }
@@ -426,34 +432,24 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
                }
                bio_put(bio);
        }
-       finished_one_bio(dio);
        return uptodate ? 0 : -EIO;
 }
 
 /*
- * Wait on and process all in-flight BIOs.
+ * Wait on and process all in-flight BIOs.  This must only be called once
+ * all bios have been issued so that the refcount can only decrease.
+ * This just waits for all bios to make it through dio_bio_complete.  IO
+ * errors are propogated through dio->io_error and should be propogated via
+ * dio_complete().
  */
-static int dio_await_completion(struct dio *dio)
+static void dio_await_completion(struct dio *dio)
 {
-       int ret = 0;
-
-       if (dio->bio)
-               dio_bio_submit(dio);
-
-       /*
-        * The bio_lock is not held for the read of bio_count.
-        * This is ok since it is the dio_bio_complete() that changes
-        * bio_count.
-        */
-       while (dio->bio_count) {
-               struct bio *bio = dio_await_one(dio);
-               int ret2;
-
-               ret2 = dio_bio_complete(dio, bio);
-               if (ret == 0)
-                       ret = ret2;
-       }
-       return ret;
+       struct bio *bio;
+       do {
+               bio = dio_await_one(dio);
+               if (bio)
+                       dio_bio_complete(dio, bio);
+       } while (bio);
 }
 
 /*
@@ -675,6 +671,13 @@ submit_page_section(struct dio *dio, struct page *page,
 {
        int ret = 0;
 
+       if (dio->rw & WRITE) {
+               /*
+                * Read accounting is performed in submit_bio()
+                */
+               task_io_account_write(len);
+       }
+
        /*
         * Can we just grow the current page's presence in the dio?
         */
@@ -953,6 +956,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
        struct dio *dio)
 {
        unsigned long user_addr; 
+       unsigned long flags;
        int seg;
        ssize_t ret = 0;
        ssize_t ret2;
@@ -983,17 +987,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
        dio->iocb = iocb;
        dio->i_size = i_size_read(inode);
 
-       /*
-        * BIO completion state.
-        *
-        * ->bio_count starts out at one, and we decrement it to zero after all
-        * BIOs are submitted.  This to avoid the situation where a really fast
-        * (or synchronous) device could take the count to zero while we're
-        * still submitting BIOs.
-        */
-       dio->bio_count = 1;
-       dio->bios_in_flight = 0;
        spin_lock_init(&dio->bio_lock);
+       dio->refcount = 1;
        dio->bio_list = NULL;
        dio->waiter = NULL;
 
@@ -1069,6 +1064,9 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
        if (dio->bio)
                dio_bio_submit(dio);
 
+       /* All IO is now issued, send it on its way */
+       blk_run_address_space(inode->i_mapping);
+
        /*
         * It is possible that, we return short IO due to end of file.
         * In that case, we need to release all the pages we got hold on.
@@ -1084,74 +1082,41 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
                mutex_unlock(&dio->inode->i_mutex);
 
        /*
-        * OK, all BIOs are submitted, so we can decrement bio_count to truly
-        * reflect the number of to-be-processed BIOs.
+        * The only time we want to leave bios in flight is when a successful
+        * partial aio read or full aio write have been setup.  In that case
+        * bio completion will call aio_complete.  The only time it's safe to
+        * call aio_complete is when we return -EIOCBQUEUED, so we key on that.
+        * This had *better* be the only place that raises -EIOCBQUEUED.
         */
-       if (dio->is_async) {
-               int should_wait = 0;
+       BUG_ON(ret == -EIOCBQUEUED);
+       if (dio->is_async && ret == 0 && dio->result &&
+           ((rw & READ) || (dio->result == dio->size)))
+               ret = -EIOCBQUEUED;
 
-               if (dio->result < dio->size && (rw & WRITE)) {
-                       dio->waiter = current;
-                       should_wait = 1;
-               }
-               if (ret == 0)
-                       ret = dio->result;
-               finished_one_bio(dio);          /* This can free the dio */
-               blk_run_address_space(inode->i_mapping);
-               if (should_wait) {
-                       unsigned long flags;
-                       /*
-                        * Wait for already issued I/O to drain out and
-                        * release its references to user-space pages
-                        * before returning to fallback on buffered I/O
-                        */
-
-                       spin_lock_irqsave(&dio->bio_lock, flags);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       while (dio->bio_count) {
-                               spin_unlock_irqrestore(&dio->bio_lock, flags);
-                               io_schedule();
-                               spin_lock_irqsave(&dio->bio_lock, flags);
-                               set_current_state(TASK_UNINTERRUPTIBLE);
-                       }
-                       spin_unlock_irqrestore(&dio->bio_lock, flags);
-                       set_current_state(TASK_RUNNING);
-                       kfree(dio);
-               }
-       } else {
-               ssize_t transferred = 0;
-
-               finished_one_bio(dio);
-               ret2 = dio_await_completion(dio);
-               if (ret == 0)
-                       ret = ret2;
-               if (ret == 0)
-                       ret = dio->page_errors;
-               if (dio->result) {
-                       loff_t i_size = i_size_read(inode);
-
-                       transferred = dio->result;
-                       /*
-                        * Adjust the return value if the read crossed a
-                        * non-block-aligned EOF.
-                        */
-                       if (rw == READ && (offset + transferred > i_size))
-                               transferred = i_size - offset;
-               }
-               dio_complete(dio, offset, transferred);
-               if (ret == 0)
-                       ret = transferred;
+       if (ret != -EIOCBQUEUED)
+               dio_await_completion(dio);
 
-               /* We could have also come here on an AIO file extend */
-               if (!is_sync_kiocb(iocb) && (rw & WRITE) &&
-                   ret >= 0 && dio->result == dio->size)
-                       /*
-                        * For AIO writes where we have completed the
-                        * i/o, we have to mark the the aio complete.
-                        */
-                       aio_complete(iocb, ret, 0);
+       /*
+        * Sync will always be dropping the final ref and completing the
+        * operation.  AIO can if it was a broken operation described above or
+        * in fact if all the bios race to complete before we get here.  In
+        * that case dio_complete() translates the EIOCBQUEUED into the proper
+        * return code that the caller will hand to aio_complete().
+        *
+        * This is managed by the bio_lock instead of being an atomic_t so that
+        * completion paths can drop their ref and use the remaining count to
+        * decide to wake the submission path atomically.
+        */
+       spin_lock_irqsave(&dio->bio_lock, flags);
+       ret2 = --dio->refcount;
+       spin_unlock_irqrestore(&dio->bio_lock, flags);
+       BUG_ON(!dio->is_async && ret2 != 0);
+       if (ret2 == 0) {
+               ret = dio_complete(dio, offset, ret);
                kfree(dio);
-       }
+       } else
+               BUG_ON(ret != -EIOCBQUEUED);
+
        return ret;
 }
 
index 81b2c64..b5654a2 100644 (file)
@@ -1,14 +1,32 @@
 menu "Distributed Lock Manager"
-       depends on INET && IP_SCTP && EXPERIMENTAL
+       depends on EXPERIMENTAL && INET
 
 config DLM
        tristate "Distributed Lock Manager (DLM)"
        depends on IPV6 || IPV6=n
        select CONFIGFS_FS
+       select IP_SCTP if DLM_SCTP
        help
        A general purpose distributed lock manager for kernel or userspace
        applications.
 
+choice
+       prompt "Select DLM communications protocol"
+       depends on DLM
+       default DLM_TCP
+       help
+       The DLM Can use TCP or SCTP for it's network communications.
+       SCTP supports multi-homed operations whereas TCP doesn't.
+       However, SCTP seems to have stability problems at the moment.
+
+config DLM_TCP
+       bool "TCP/IP"
+
+config DLM_SCTP
+       bool "SCTP"
+
+endchoice
+
 config DLM_DEBUG
        bool "DLM debugging"
        depends on DLM
index 1832e02..6538894 100644 (file)
@@ -4,7 +4,6 @@ dlm-y :=                        ast.o \
                                dir.o \
                                lock.o \
                                lockspace.o \
-                               lowcomms.o \
                                main.o \
                                member.o \
                                memory.o \
@@ -17,3 +16,6 @@ dlm-y :=                      ast.o \
                                util.o
 dlm-$(CONFIG_DLM_DEBUG) +=     debug_fs.o
 
+dlm-$(CONFIG_DLM_TCP)   += lowcomms-tcp.o
+
+dlm-$(CONFIG_DLM_SCTP)  += lowcomms-sctp.o
\ No newline at end of file
index 1e5cd67..1ee8195 100644 (file)
@@ -471,6 +471,7 @@ struct dlm_ls {
        char                    *ls_recover_buf;
        int                     ls_recover_nodeid; /* for debugging */
        uint64_t                ls_rcom_seq;
+       spinlock_t              ls_rcom_spin;
        struct list_head        ls_recover_list;
        spinlock_t              ls_recover_list_lock;
        int                     ls_recover_list_count;
@@ -488,7 +489,8 @@ struct dlm_ls {
 #define LSFL_RUNNING           1
 #define LSFL_RECOVERY_STOP     2
 #define LSFL_RCOM_READY                3
-#define LSFL_UEVENT_WAIT       4
+#define LSFL_RCOM_WAIT         4
+#define LSFL_UEVENT_WAIT       5
 
 /* much of this is just saving user space pointers associated with the
    lock that we pass back to the user lib with an ast */
index 3f2befa..30878de 100644 (file)
@@ -2372,6 +2372,7 @@ static int send_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms_in,
 static void receive_flags(struct dlm_lkb *lkb, struct dlm_message *ms)
 {
        lkb->lkb_exflags = ms->m_exflags;
+       lkb->lkb_sbflags = ms->m_sbflags;
        lkb->lkb_flags = (lkb->lkb_flags & 0xFFFF0000) |
                         (ms->m_flags & 0x0000FFFF);
 }
@@ -3028,10 +3029,17 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
 
        while (1) {
                if (dlm_locking_stopped(ls)) {
-                       if (!recovery)
-                               dlm_add_requestqueue(ls, nodeid, hd);
-                       error = -EINTR;
-                       goto out;
+                       if (recovery) {
+                               error = -EINTR;
+                               goto out;
+                       }
+                       error = dlm_add_requestqueue(ls, nodeid, hd);
+                       if (error == -EAGAIN)
+                               continue;
+                       else {
+                               error = -EINTR;
+                               goto out;
+                       }
                }
 
                if (lock_recovery_try(ls))
index f8842ca..59012b0 100644 (file)
@@ -22,6 +22,7 @@
 #include "memory.h"
 #include "lock.h"
 #include "recover.h"
+#include "requestqueue.h"
 
 #ifdef CONFIG_DLM_DEBUG
 int dlm_create_debug_file(struct dlm_ls *ls);
@@ -478,6 +479,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
        ls->ls_recoverd_task = NULL;
        mutex_init(&ls->ls_recoverd_active);
        spin_lock_init(&ls->ls_recover_lock);
+       spin_lock_init(&ls->ls_rcom_spin);
+       get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
        ls->ls_recover_status = 0;
        ls->ls_recover_seq = 0;
        ls->ls_recover_args = NULL;
@@ -684,6 +687,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
         * Free structures on any other lists
         */
 
+       dlm_purge_requestqueue(ls);
        kfree(ls->ls_recover_args);
        dlm_clear_free_entries(ls);
        dlm_clear_members(ls);
similarity index 87%
rename from fs/dlm/lowcomms.c
rename to fs/dlm/lowcomms-sctp.c
index 6da6b14..fe158d7 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -75,13 +75,13 @@ struct nodeinfo {
 };
 
 static DEFINE_IDR(nodeinfo_idr);
-static struct rw_semaphore     nodeinfo_lock;
-static int                     max_nodeid;
+static DECLARE_RWSEM(nodeinfo_lock);
+static int max_nodeid;
 
 struct cbuf {
-       unsigned                base;
-       unsigned                len;
-       unsigned                mask;
+       unsigned int base;
+       unsigned int len;
+       unsigned int mask;
 };
 
 /* Just the one of these, now. But this struct keeps
@@ -90,9 +90,9 @@ struct cbuf {
 #define CF_READ_PENDING 1
 
 struct connection {
-       struct socket          *sock;
+       struct socket           *sock;
        unsigned long           flags;
-       struct page            *rx_page;
+       struct page             *rx_page;
        atomic_t                waiting_requests;
        struct cbuf             cb;
        int                     eagain_flag;
@@ -102,36 +102,40 @@ struct connection {
 
 struct writequeue_entry {
        struct list_head        list;
-       struct page            *page;
+       struct page             *page;
        int                     offset;
        int                     len;
        int                     end;
        int                     users;
-       struct nodeinfo        *ni;
+       struct nodeinfo         *ni;
 };
 
-#define CBUF_ADD(cb, n) do { (cb)->len += n; } while(0)
-#define CBUF_EMPTY(cb) ((cb)->len == 0)
-#define CBUF_MAY_ADD(cb, n) (((cb)->len + (n)) < ((cb)->mask + 1))
-#define CBUF_DATA(cb) (((cb)->base + (cb)->len) & (cb)->mask)
+static void cbuf_add(struct cbuf *cb, int n)
+{
+       cb->len += n;
+}
 
-#define CBUF_INIT(cb, size) \
-do { \
-       (cb)->base = (cb)->len = 0; \
-       (cb)->mask = ((size)-1); \
-} while(0)
+static int cbuf_data(struct cbuf *cb)
+{
+       return ((cb->base + cb->len) & cb->mask);
+}
 
-#define CBUF_EAT(cb, n) \
-do { \
-       (cb)->len  -= (n); \
-       (cb)->base += (n); \
-       (cb)->base &= (cb)->mask; \
-} while(0)
+static void cbuf_init(struct cbuf *cb, int size)
+{
+       cb->base = cb->len = 0;
+       cb->mask = size-1;
+}
 
+static void cbuf_eat(struct cbuf *cb, int n)
+{
+       cb->len  -= n;
+       cb->base += n;
+       cb->base &= cb->mask;
+}
 
 /* List of nodes which have writes pending */
-static struct list_head write_nodes;
-static spinlock_t write_nodes_lock;
+static LIST_HEAD(write_nodes);
+static DEFINE_SPINLOCK(write_nodes_lock);
 
 /* Maximum number of incoming messages to process before
  * doing a schedule()
@@ -141,8 +145,7 @@ static spinlock_t write_nodes_lock;
 /* Manage daemons */
 static struct task_struct *recv_task;
 static struct task_struct *send_task;
-static wait_queue_head_t lowcomms_recv_wait;
-static atomic_t accepting;
+static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_wait);
 
 /* The SCTP connection */
 static struct connection sctp_con;
@@ -161,11 +164,11 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
                return error;
 
        if (dlm_local_addr[0]->ss_family == AF_INET) {
-               struct sockaddr_in *in4  = (struct sockaddr_in *) &addr;
+               struct sockaddr_in *in4  = (struct sockaddr_in *) &addr;
                struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr;
                ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
        } else {
-               struct sockaddr_in6 *in6  = (struct sockaddr_in6 *) &addr;
+               struct sockaddr_in6 *in6  = (struct sockaddr_in6 *) &addr;
                struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr;
                memcpy(&ret6->sin6_addr, &in6->sin6_addr,
                       sizeof(in6->sin6_addr));
@@ -174,6 +177,8 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
        return 0;
 }
 
+/* If alloc is 0 here we will not attempt to allocate a new
+   nodeinfo struct */
 static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc)
 {
        struct nodeinfo *ni;
@@ -184,44 +189,45 @@ static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc)
        ni = idr_find(&nodeinfo_idr, nodeid);
        up_read(&nodeinfo_lock);
 
-       if (!ni && alloc) {
-               down_write(&nodeinfo_lock);
+       if (ni || !alloc)
+               return ni;
 
-               ni = idr_find(&nodeinfo_idr, nodeid);
-               if (ni)
-                       goto out_up;
+       down_write(&nodeinfo_lock);
 
-               r = idr_pre_get(&nodeinfo_idr, alloc);
-               if (!r)
-                       goto out_up;
+       ni = idr_find(&nodeinfo_idr, nodeid);
+       if (ni)
+               goto out_up;
 
-               ni = kmalloc(sizeof(struct nodeinfo), alloc);
-               if (!ni)
-                       goto out_up;
+       r = idr_pre_get(&nodeinfo_idr, alloc);
+       if (!r)
+               goto out_up;
 
-               r = idr_get_new_above(&nodeinfo_idr, ni, nodeid, &n);
-               if (r) {
-                       kfree(ni);
-                       ni = NULL;
-                       goto out_up;
-               }
-               if (n != nodeid) {
-                       idr_remove(&nodeinfo_idr, n);
-                       kfree(ni);
-                       ni = NULL;
-                       goto out_up;
-               }
-               memset(ni, 0, sizeof(struct nodeinfo));
-               spin_lock_init(&ni->lock);
-               INIT_LIST_HEAD(&ni->writequeue);
-               spin_lock_init(&ni->writequeue_lock);
-               ni->nodeid = nodeid;
-
-               if (nodeid > max_nodeid)
-                       max_nodeid = nodeid;
-       out_up:
-               up_write(&nodeinfo_lock);
+       ni = kmalloc(sizeof(struct nodeinfo), alloc);
+       if (!ni)
+               goto out_up;
+
+       r = idr_get_new_above(&nodeinfo_idr, ni, nodeid, &n);
+       if (r) {
+               kfree(ni);
+               ni = NULL;
+               goto out_up;
        }
+       if (n != nodeid) {
+               idr_remove(&nodeinfo_idr, n);
+               kfree(ni);
+               ni = NULL;
+               goto out_up;
+       }
+       memset(ni, 0, sizeof(struct nodeinfo));
+       spin_lock_init(&ni->lock);
+       INIT_LIST_HEAD(&ni->writequeue);
+       spin_lock_init(&ni->writequeue_lock);
+       ni->nodeid = nodeid;
+
+       if (nodeid > max_nodeid)
+               max_nodeid = nodeid;
+out_up:
+       up_write(&nodeinfo_lock);
 
        return ni;
 }
@@ -279,13 +285,13 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
                in4_addr->sin_port = cpu_to_be16(port);
                memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero));
                memset(in4_addr+1, 0, sizeof(struct sockaddr_storage) -
-                                     sizeof(struct sockaddr_in));
+                      sizeof(struct sockaddr_in));
                *addr_len = sizeof(struct sockaddr_in);
        } else {
                struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
                in6_addr->sin6_port = cpu_to_be16(port);
                memset(in6_addr+1, 0, sizeof(struct sockaddr_storage) -
-                                     sizeof(struct sockaddr_in6));
+                      sizeof(struct sockaddr_in6));
                *addr_len = sizeof(struct sockaddr_in6);
        }
 }
@@ -324,7 +330,7 @@ static void send_shutdown(sctp_assoc_t associd)
        cmsg->cmsg_type = SCTP_SNDRCV;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
        outmessage.msg_controllen = cmsg->cmsg_len;
-       sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+       sinfo = CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
 
        sinfo->sinfo_flags |= MSG_EOF;
@@ -387,7 +393,7 @@ static void process_sctp_notification(struct msghdr *msg, char *buf)
 
                        if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) {
                                log_print("COMM_UP for invalid assoc ID %d",
-                                        (int)sn->sn_assoc_change.sac_assoc_id);
+                                         (int)sn->sn_assoc_change.sac_assoc_id);
                                init_failed();
                                return;
                        }
@@ -398,15 +404,18 @@ static void process_sctp_notification(struct msghdr *msg, char *buf)
                        fs = get_fs();
                        set_fs(get_ds());
                        ret = sctp_con.sock->ops->getsockopt(sctp_con.sock,
-                                               IPPROTO_SCTP, SCTP_PRIMARY_ADDR,
-                                               (char*)&prim, &prim_len);
+                                                            IPPROTO_SCTP,
+                                                            SCTP_PRIMARY_ADDR,
+                                                            (char*)&prim,
+                                                            &prim_len);
                        set_fs(fs);
                        if (ret < 0) {
                                struct nodeinfo *ni;
 
                                log_print("getsockopt/sctp_primary_addr on "
                                          "new assoc %d failed : %d",
-                                   (int)sn->sn_assoc_change.sac_assoc_id, ret);
+                                         (int)sn->sn_assoc_change.sac_assoc_id,
+                                         ret);
 
                                /* Retry INIT later */
                                ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id);
@@ -426,12 +435,10 @@ static void process_sctp_notification(struct msghdr *msg, char *buf)
                                return;
 
                        /* Save the assoc ID */
-                       spin_lock(&ni->lock);
                        ni->assoc_id = sn->sn_assoc_change.sac_assoc_id;
-                       spin_unlock(&ni->lock);
 
                        log_print("got new/restarted association %d nodeid %d",
-                              (int)sn->sn_assoc_change.sac_assoc_id, nodeid);
+                                 (int)sn->sn_assoc_change.sac_assoc_id, nodeid);
 
                        /* Send any pending writes */
                        clear_bit(NI_INIT_PENDING, &ni->flags);
@@ -507,13 +514,12 @@ static int receive_from_sock(void)
                sctp_con.rx_page = alloc_page(GFP_ATOMIC);
                if (sctp_con.rx_page == NULL)
                        goto out_resched;
-               CBUF_INIT(&sctp_con.cb, PAGE_CACHE_SIZE);
+               cbuf_init(&sctp_con.cb, PAGE_CACHE_SIZE);
        }
 
        memset(&incmsg, 0, sizeof(incmsg));
        memset(&msgname, 0, sizeof(msgname));
 
-       memset(incmsg, 0, sizeof(incmsg));
        msg.msg_name = &msgname;
        msg.msg_namelen = sizeof(msgname);
        msg.msg_flags = 0;
@@ -532,17 +538,17 @@ static int receive_from_sock(void)
         * iov[0] is the bit of the circular buffer between the current end
         * point (cb.base + cb.len) and the end of the buffer.
         */
-       iov[0].iov_len = sctp_con.cb.base - CBUF_DATA(&sctp_con.cb);
+       iov[0].iov_len = sctp_con.cb.base - cbuf_data(&sctp_con.cb);
        iov[0].iov_base = page_address(sctp_con.rx_page) +
-                         CBUF_DATA(&sctp_con.cb);
+               cbuf_data(&sctp_con.cb);
        iov[1].iov_len = 0;
 
        /*
         * iov[1] is the bit of the circular buffer between the start of the
         * buffer and the start of the currently used section (cb.base)
         */
-       if (CBUF_DATA(&sctp_con.cb) >= sctp_con.cb.base) {
-               iov[0].iov_len = PAGE_CACHE_SIZE - CBUF_DATA(&sctp_con.cb);
+       if (cbuf_data(&sctp_con.cb) >= sctp_con.cb.base) {
+               iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&sctp_con.cb);
                iov[1].iov_len = sctp_con.cb.base;
                iov[1].iov_base = page_address(sctp_con.rx_page);
                msg.msg_iovlen = 2;
@@ -557,7 +563,7 @@ static int receive_from_sock(void)
        msg.msg_control = incmsg;
        msg.msg_controllen = sizeof(incmsg);
        cmsg = CMSG_FIRSTHDR(&msg);
-       sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+       sinfo = CMSG_DATA(cmsg);
 
        if (msg.msg_flags & MSG_NOTIFICATION) {
                process_sctp_notification(&msg, page_address(sctp_con.rx_page));
@@ -583,29 +589,29 @@ static int receive_from_sock(void)
        if (r == 1)
                return 0;
 
-       CBUF_ADD(&sctp_con.cb, ret);
+       cbuf_add(&sctp_con.cb, ret);
        ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid),
                                          page_address(sctp_con.rx_page),
                                          sctp_con.cb.base, sctp_con.cb.len,
                                          PAGE_CACHE_SIZE);
        if (ret < 0)
                goto out_close;
-       CBUF_EAT(&sctp_con.cb, ret);
+       cbuf_eat(&sctp_con.cb, ret);
 
-      out:
+out:
        ret = 0;
        goto out_ret;
 
-      out_resched:
+out_resched:
        lowcomms_data_ready(sctp_con.sock->sk, 0);
        ret = 0;
-       schedule();
+       cond_resched();
        goto out_ret;
 
-      out_close:
+out_close:
        if (ret != -EAGAIN)
                log_print("error reading from sctp socket: %d", ret);
-      out_ret:
+out_ret:
        return ret;
 }
 
@@ -619,10 +625,12 @@ static int add_bind_addr(struct sockaddr_storage *addr, int addr_len, int num)
        set_fs(get_ds());
        if (num == 1)
                result = sctp_con.sock->ops->bind(sctp_con.sock,
-                                       (struct sockaddr *) addr, addr_len);
+                                                 (struct sockaddr *) addr,
+                                                 addr_len);
        else
                result = sctp_con.sock->ops->setsockopt(sctp_con.sock, SOL_SCTP,
-                               SCTP_SOCKOPT_BINDX_ADD, (char *)addr, addr_len);
+                                                       SCTP_SOCKOPT_BINDX_ADD,
+                                                       (char *)addr, addr_len);
        set_fs(fs);
 
        if (result < 0)
@@ -719,10 +727,10 @@ static int init_sock(void)
 
        return 0;
 
- create_delsock:
+create_delsock:
        sock_release(sock);
        sctp_con.sock = NULL;
- out:
+out:
        return result;
 }
 
@@ -756,16 +764,13 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
        int users = 0;
        struct nodeinfo *ni;
 
-       if (!atomic_read(&accepting))
-               return NULL;
-
        ni = nodeid2nodeinfo(nodeid, allocation);
        if (!ni)
                return NULL;
 
        spin_lock(&ni->writequeue_lock);
        e = list_entry(ni->writequeue.prev, struct writequeue_entry, list);
-       if (((struct list_head *) e == &ni->writequeue) ||
+       if ((&e->list == &ni->writequeue) ||
            (PAGE_CACHE_SIZE - e->end < len)) {
                e = NULL;
        } else {
@@ -776,7 +781,7 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
        spin_unlock(&ni->writequeue_lock);
 
        if (e) {
-             got_one:
+       got_one:
                if (users == 0)
                        kmap(e->page);
                *ppc = page_address(e->page) + offset;
@@ -803,9 +808,6 @@ void dlm_lowcomms_commit_buffer(void *arg)
        int users;
        struct nodeinfo *ni = e->ni;
 
-       if (!atomic_read(&accepting))
-               return;
-
        spin_lock(&ni->writequeue_lock);
        users = --e->users;
        if (users)
@@ -822,7 +824,7 @@ void dlm_lowcomms_commit_buffer(void *arg)
        }
        return;
 
-      out:
+out:
        spin_unlock(&ni->writequeue_lock);
        return;
 }
@@ -878,7 +880,7 @@ static void initiate_association(int nodeid)
        cmsg->cmsg_level = IPPROTO_SCTP;
        cmsg->cmsg_type = SCTP_SNDRCV;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-       sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+       sinfo = CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
        sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
 
@@ -892,7 +894,7 @@ static void initiate_association(int nodeid)
 }
 
 /* Send a message */
-static int send_to_sock(struct nodeinfo *ni)
+static void send_to_sock(struct nodeinfo *ni)
 {
        int ret = 0;
        struct writequeue_entry *e;
@@ -903,13 +905,13 @@ static int send_to_sock(struct nodeinfo *ni)
        struct sctp_sndrcvinfo *sinfo;
        struct kvec iov;
 
-        /* See if we need to init an association before we start
+       /* See if we need to init an association before we start
           sending precious messages */
        spin_lock(&ni->lock);
        if (!ni->assoc_id && !test_and_set_bit(NI_INIT_PENDING, &ni->flags)) {
                spin_unlock(&ni->lock);
                initiate_association(ni->nodeid);
-               return 0;
+               return;
        }
        spin_unlock(&ni->lock);
 
@@ -923,7 +925,7 @@ static int send_to_sock(struct nodeinfo *ni)
        cmsg->cmsg_level = IPPROTO_SCTP;
        cmsg->cmsg_type = SCTP_SNDRCV;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-       sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+       sinfo = CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
        sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
        sinfo->sinfo_assoc_id = ni->assoc_id;
@@ -955,7 +957,7 @@ static int send_to_sock(struct nodeinfo *ni)
                                goto send_error;
                } else {
                        /* Don't starve people filling buffers */
-                       schedule();
+                       cond_resched();
                }
 
                spin_lock(&ni->writequeue_lock);
@@ -964,15 +966,16 @@ static int send_to_sock(struct nodeinfo *ni)
 
                if (e->len == 0 && e->users == 0) {
                        list_del(&e->list);
+                       kunmap(e->page);
                        free_entry(e);
                        continue;
                }
        }
        spin_unlock(&ni->writequeue_lock);
- out:
-       return ret;
+out:
+       return;
 
- send_error:
+send_error:
        log_print("Error sending to node %d %d", ni->nodeid, ret);
        spin_lock(&ni->lock);
        if (!test_and_set_bit(NI_INIT_PENDING, &ni->flags)) {
@@ -982,7 +985,7 @@ static int send_to_sock(struct nodeinfo *ni)
        } else
                spin_unlock(&ni->lock);
 
-       return ret;
+       return;
 }
 
 /* Try to send any messages that are pending */
@@ -994,7 +997,7 @@ static void process_output_queue(void)
        spin_lock_bh(&write_nodes_lock);
        list_for_each_safe(list, temp, &write_nodes) {
                struct nodeinfo *ni =
-                   list_entry(list, struct nodeinfo, write_list);
+                       list_entry(list, struct nodeinfo, write_list);
                clear_bit(NI_WRITE_PENDING, &ni->flags);
                list_del(&ni->write_list);
 
@@ -1106,7 +1109,7 @@ static int dlm_recvd(void *data)
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&lowcomms_recv_wait, &wait);
                if (!test_bit(CF_READ_PENDING, &sctp_con.flags))
-                       schedule();
+                       cond_resched();
                remove_wait_queue(&lowcomms_recv_wait, &wait);
                set_current_state(TASK_RUNNING);
 
@@ -1118,12 +1121,12 @@ static int dlm_recvd(void *data)
 
                                /* Don't starve out everyone else */
                                if (++count >= MAX_RX_MSG_COUNT) {
-                                       schedule();
+                                       cond_resched();
                                        count = 0;
                                }
                        } while (!kthread_should_stop() && ret >=0);
                }
-               schedule();
+               cond_resched();
        }
 
        return 0;
@@ -1138,7 +1141,7 @@ static int dlm_sendd(void *data)
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (write_list_empty())
-                       schedule();
+                       cond_resched();
                set_current_state(TASK_RUNNING);
 
                if (sctp_con.eagain_flag) {
@@ -1166,7 +1169,7 @@ static int daemons_start(void)
 
        p = kthread_run(dlm_recvd, NULL, "dlm_recvd");
        error = IS_ERR(p);
-               if (error) {
+       if (error) {
                log_print("can't start dlm_recvd %d", error);
                return error;
        }
@@ -1174,7 +1177,7 @@ static int daemons_start(void)
 
        p = kthread_run(dlm_sendd, NULL, "dlm_sendd");
        error = IS_ERR(p);
-               if (error) {
+       if (error) {
                log_print("can't start dlm_sendd %d", error);
                kthread_stop(recv_task);
                return error;
@@ -1197,43 +1200,28 @@ int dlm_lowcomms_start(void)
        error = daemons_start();
        if (error)
                goto fail_sock;
-       atomic_set(&accepting, 1);
        return 0;
 
- fail_sock:
+fail_sock:
        close_connection();
        return error;
 }
 
-/* Set all the activity flags to prevent any socket activity. */
-
 void dlm_lowcomms_stop(void)
 {
-       atomic_set(&accepting, 0);
+       int i;
+
        sctp_con.flags = 0x7;
        daemons_stop();
        clean_writequeues();
        close_connection();
        dealloc_nodeinfo();
        max_nodeid = 0;
-}
 
-int dlm_lowcomms_init(void)
-{
-       init_waitqueue_head(&lowcomms_recv_wait);
-       spin_lock_init(&write_nodes_lock);
-       INIT_LIST_HEAD(&write_nodes);
-       init_rwsem(&nodeinfo_lock);
-       return 0;
-}
-
-void dlm_lowcomms_exit(void)
-{
-       int i;
+       dlm_local_count = 0;
+       dlm_local_nodeid = 0;
 
        for (i = 0; i < dlm_local_count; i++)
                kfree(dlm_local_addr[i]);
-       dlm_local_count = 0;
-       dlm_local_nodeid = 0;
 }
 
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
new file mode 100644 (file)
index 0000000..8f2791f
--- /dev/null
@@ -0,0 +1,1189 @@
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
+**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+**
+**  This copyrighted material is made available to anyone wishing to use,
+**  modify, copy, or redistribute it subject to the terms and conditions
+**  of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+/*
+ * lowcomms.c
+ *
+ * This is the "low-level" comms layer.
+ *
+ * It is responsible for sending/receiving messages
+ * from other nodes in the cluster.
+ *
+ * Cluster nodes are referred to by their nodeids. nodeids are
+ * simply 32 bit numbers to the locking module - if they need to
+ * be expanded for the cluster infrastructure then that is it's
+ * responsibility. It is this layer's
+ * responsibility to resolve these into IP address or
+ * whatever it needs for inter-node communication.
+ *
+ * The comms level is two kernel threads that deal mainly with
+ * the receiving of messages from other nodes and passing them
+ * up to the mid-level comms layer (which understands the
+ * message format) for execution by the locking core, and
+ * a send thread which does all the setting up of connections
+ * to remote nodes and the sending of data. Threads are not allowed
+ * to send their own data because it may cause them to wait in times
+ * of high load. Also, this way, the sending thread can collect together
+ * messages bound for one node and send them in one block.
+ *
+ * I don't see any problem with the recv thread executing the locking
+ * code on behalf of remote processes as the locking code is
+ * short, efficient and never waits.
+ *
+ */
+
+
+#include <asm/ioctls.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <linux/pagemap.h>
+
+#include "dlm_internal.h"
+#include "lowcomms.h"
+#include "midcomms.h"
+#include "config.h"
+
+struct cbuf {
+       unsigned int base;
+       unsigned int len;
+       unsigned int mask;
+};
+
+#define NODE_INCREMENT 32
+static void cbuf_add(struct cbuf *cb, int n)
+{
+       cb->len += n;
+}
+
+static int cbuf_data(struct cbuf *cb)
+{
+       return ((cb->base + cb->len) & cb->mask);
+}
+
+static void cbuf_init(struct cbuf *cb, int size)
+{
+       cb->base = cb->len = 0;
+       cb->mask = size-1;
+}
+
+static void cbuf_eat(struct cbuf *cb, int n)
+{
+       cb->len  -= n;
+       cb->base += n;
+       cb->base &= cb->mask;
+}
+
+static bool cbuf_empty(struct cbuf *cb)
+{
+       return cb->len == 0;
+}
+
+/* Maximum number of incoming messages to process before
+   doing a cond_resched()
+*/
+#define MAX_RX_MSG_COUNT 25
+
+struct connection {
+       struct socket *sock;    /* NULL if not connected */
+       uint32_t nodeid;        /* So we know who we are in the list */
+       struct rw_semaphore sock_sem; /* Stop connect races */
+       struct list_head read_list;   /* On this list when ready for reading */
+       struct list_head write_list;  /* On this list when ready for writing */
+       struct list_head state_list;  /* On this list when ready to connect */
+       unsigned long flags;    /* bit 1,2 = We are on the read/write lists */
+#define CF_READ_PENDING 1
+#define CF_WRITE_PENDING 2
+#define CF_CONNECT_PENDING 3
+#define CF_IS_OTHERCON 4
+       struct list_head writequeue;  /* List of outgoing writequeue_entries */
+       struct list_head listenlist;  /* List of allocated listening sockets */
+       spinlock_t writequeue_lock;
+       int (*rx_action) (struct connection *); /* What to do when active */
+       struct page *rx_page;
+       struct cbuf cb;
+       int retries;
+       atomic_t waiting_requests;
+#define MAX_CONNECT_RETRIES 3
+       struct connection *othercon;
+};
+#define sock2con(x) ((struct connection *)(x)->sk_user_data)
+
+/* An entry waiting to be sent */
+struct writequeue_entry {
+       struct list_head list;
+       struct page *page;
+       int offset;
+       int len;
+       int end;
+       int users;
+       struct connection *con;
+};
+
+static struct sockaddr_storage dlm_local_addr;
+
+/* Manage daemons */
+static struct task_struct *recv_task;
+static struct task_struct *send_task;
+
+static wait_queue_t lowcomms_send_waitq_head;
+static DECLARE_WAIT_QUEUE_HEAD(lowcomms_send_waitq);
+static wait_queue_t lowcomms_recv_waitq_head;
+static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_waitq);
+
+/* An array of pointers to connections, indexed by NODEID */
+static struct connection **connections;
+static DECLARE_MUTEX(connections_lock);
+static kmem_cache_t *con_cache;
+static int conn_array_size;
+
+/* List of sockets that have reads pending */
+static LIST_HEAD(read_sockets);
+static DEFINE_SPINLOCK(read_sockets_lock);
+
+/* List of sockets which have writes pending */
+static LIST_HEAD(write_sockets);
+static DEFINE_SPINLOCK(write_sockets_lock);
+
+/* List of sockets which have connects pending */
+static LIST_HEAD(state_sockets);
+static DEFINE_SPINLOCK(state_sockets_lock);
+
+static struct connection *nodeid2con(int nodeid, gfp_t allocation)
+{
+       struct connection *con = NULL;
+
+       down(&connections_lock);
+       if (nodeid >= conn_array_size) {
+               int new_size = nodeid + NODE_INCREMENT;
+               struct connection **new_conns;
+
+               new_conns = kzalloc(sizeof(struct connection *) *
+                                   new_size, allocation);
+               if (!new_conns)
+                       goto finish;
+
+               memcpy(new_conns, connections,  sizeof(struct connection *) * conn_array_size);
+               conn_array_size = new_size;
+               kfree(connections);
+               connections = new_conns;
+
+       }
+
+       con = connections[nodeid];
+       if (con == NULL && allocation) {
+               con = kmem_cache_zalloc(con_cache, allocation);
+               if (!con)
+                       goto finish;
+
+               con->nodeid = nodeid;
+               init_rwsem(&con->sock_sem);
+               INIT_LIST_HEAD(&con->writequeue);
+               spin_lock_init(&con->writequeue_lock);
+
+               connections[nodeid] = con;
+       }
+
+finish:
+       up(&connections_lock);
+       return con;
+}
+
+/* Data available on socket or listen socket received a connect */
+static void lowcomms_data_ready(struct sock *sk, int count_unused)
+{
+       struct connection *con = sock2con(sk);
+
+       atomic_inc(&con->waiting_requests);
+       if (test_and_set_bit(CF_READ_PENDING, &con->flags))
+               return;
+
+       spin_lock_bh(&read_sockets_lock);
+       list_add_tail(&con->read_list, &read_sockets);
+       spin_unlock_bh(&read_sockets_lock);
+
+       wake_up_interruptible(&lowcomms_recv_waitq);
+}
+
+static void lowcomms_write_space(struct sock *sk)
+{
+       struct connection *con = sock2con(sk);
+
+       if (test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+               return;
+
+       spin_lock_bh(&write_sockets_lock);
+       list_add_tail(&con->write_list, &write_sockets);
+       spin_unlock_bh(&write_sockets_lock);
+
+       wake_up_interruptible(&lowcomms_send_waitq);
+}
+
+static inline void lowcomms_connect_sock(struct connection *con)
+{
+       if (test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
+               return;
+
+       spin_lock_bh(&state_sockets_lock);
+       list_add_tail(&con->state_list, &state_sockets);
+       spin_unlock_bh(&state_sockets_lock);
+
+       wake_up_interruptible(&lowcomms_send_waitq);
+}
+
+static void lowcomms_state_change(struct sock *sk)
+{
+       if (sk->sk_state == TCP_ESTABLISHED)
+               lowcomms_write_space(sk);
+}
+
+/* Make a socket active */
+static int add_sock(struct socket *sock, struct connection *con)
+{
+       con->sock = sock;
+
+       /* Install a data_ready callback */
+       con->sock->sk->sk_data_ready = lowcomms_data_ready;
+       con->sock->sk->sk_write_space = lowcomms_write_space;
+       con->sock->sk->sk_state_change = lowcomms_state_change;
+
+       return 0;
+}
+
+/* Add the port number to an IP6 or 4 sockaddr and return the address
+   length */
+static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
+                         int *addr_len)
+{
+       saddr->ss_family =  dlm_local_addr.ss_family;
+       if (saddr->ss_family == AF_INET) {
+               struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
+               in4_addr->sin_port = cpu_to_be16(port);
+               *addr_len = sizeof(struct sockaddr_in);
+       } else {
+               struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
+               in6_addr->sin6_port = cpu_to_be16(port);
+               *addr_len = sizeof(struct sockaddr_in6);
+       }
+}
+
+/* Close a remote connection and tidy up */
+static void close_connection(struct connection *con, bool and_other)
+{
+       down_write(&con->sock_sem);
+
+       if (con->sock) {
+               sock_release(con->sock);
+               con->sock = NULL;
+       }
+       if (con->othercon && and_other) {
+               /* Will only re-enter once. */
+               close_connection(con->othercon, false);
+       }
+       if (con->rx_page) {
+               __free_page(con->rx_page);
+               con->rx_page = NULL;
+       }
+       con->retries = 0;
+       up_write(&con->sock_sem);
+}
+
+/* Data received from remote end */
+static int receive_from_sock(struct connection *con)
+{
+       int ret = 0;
+       struct msghdr msg;
+       struct iovec iov[2];
+       mm_segment_t fs;
+       unsigned len;
+       int r;
+       int call_again_soon = 0;
+
+       down_read(&con->sock_sem);
+
+       if (con->sock == NULL)
+               goto out;
+       if (con->rx_page == NULL) {
+               /*
+                * This doesn't need to be atomic, but I think it should
+                * improve performance if it is.
+                */
+               con->rx_page = alloc_page(GFP_ATOMIC);
+               if (con->rx_page == NULL)
+                       goto out_resched;
+               cbuf_init(&con->cb, PAGE_CACHE_SIZE);
+       }
+
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_iovlen = 1;
+       msg.msg_iov = iov;
+       msg.msg_name = NULL;
+       msg.msg_namelen = 0;
+       msg.msg_flags = 0;
+
+       /*
+        * iov[0] is the bit of the circular buffer between the current end
+        * point (cb.base + cb.len) and the end of the buffer.
+        */
+       iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
+       iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
+       iov[1].iov_len = 0;
+
+       /*
+        * iov[1] is the bit of the circular buffer between the start of the
+        * buffer and the start of the currently used section (cb.base)
+        */
+       if (cbuf_data(&con->cb) >= con->cb.base) {
+               iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
+               iov[1].iov_len = con->cb.base;
+               iov[1].iov_base = page_address(con->rx_page);
+               msg.msg_iovlen = 2;
+       }
+       len = iov[0].iov_len + iov[1].iov_len;
+
+       fs = get_fs();
+       set_fs(get_ds());
+       r = ret = sock_recvmsg(con->sock, &msg, len,
+                              MSG_DONTWAIT | MSG_NOSIGNAL);
+       set_fs(fs);
+
+       if (ret <= 0)
+               goto out_close;
+       if (ret == len)
+               call_again_soon = 1;
+       cbuf_add(&con->cb, ret);
+       ret = dlm_process_incoming_buffer(con->nodeid,
+                                         page_address(con->rx_page),
+                                         con->cb.base, con->cb.len,
+                                         PAGE_CACHE_SIZE);
+       if (ret == -EBADMSG) {
+               printk(KERN_INFO "dlm: lowcomms: addr=%p, base=%u, len=%u, "
+                      "iov_len=%u, iov_base[0]=%p, read=%d\n",
+                      page_address(con->rx_page), con->cb.base, con->cb.len,
+                      len, iov[0].iov_base, r);
+       }
+       if (ret < 0)
+               goto out_close;
+       cbuf_eat(&con->cb, ret);
+
+       if (cbuf_empty(&con->cb) && !call_again_soon) {
+               __free_page(con->rx_page);
+               con->rx_page = NULL;
+       }
+
+out:
+       if (call_again_soon)
+               goto out_resched;
+       up_read(&con->sock_sem);
+       return 0;
+
+out_resched:
+       lowcomms_data_ready(con->sock->sk, 0);
+       up_read(&con->sock_sem);
+       cond_resched();
+       return 0;
+
+out_close:
+       up_read(&con->sock_sem);
+       if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
+               close_connection(con, false);
+               /* Reconnect when there is something to send */
+       }
+
+       return ret;
+}
+
+/* Listening socket is busy, accept a connection */
+static int accept_from_sock(struct connection *con)
+{
+       int result;
+       struct sockaddr_storage peeraddr;
+       struct socket *newsock;
+       int len;
+       int nodeid;
+       struct connection *newcon;
+
+       memset(&peeraddr, 0, sizeof(peeraddr));
+       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
+                                 IPPROTO_TCP, &newsock);
+       if (result < 0)
+               return -ENOMEM;
+
+       down_read(&con->sock_sem);
+
+       result = -ENOTCONN;
+       if (con->sock == NULL)
+               goto accept_err;
+
+       newsock->type = con->sock->type;
+       newsock->ops = con->sock->ops;
+
+       result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK);
+       if (result < 0)
+               goto accept_err;
+
+       /* Get the connected socket's peer */
+       memset(&peeraddr, 0, sizeof(peeraddr));
+       if (newsock->ops->getname(newsock, (struct sockaddr *)&peeraddr,
+                                 &len, 2)) {
+               result = -ECONNABORTED;
+               goto accept_err;
+       }
+
+       /* Get the new node's NODEID */
+       make_sockaddr(&peeraddr, 0, &len);
+       if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
+               printk("dlm: connect from non cluster node\n");
+               sock_release(newsock);
+               up_read(&con->sock_sem);
+               return -1;
+       }
+
+       log_print("got connection from %d", nodeid);
+
+       /*  Check to see if we already have a connection to this node. This
+        *  could happen if the two nodes initiate a connection at roughly
+        *  the same time and the connections cross on the wire.
+        * TEMPORARY FIX:
+        *  In this case we store the incoming one in "othercon"
+        */
+       newcon = nodeid2con(nodeid, GFP_KERNEL);
+       if (!newcon) {
+               result = -ENOMEM;
+               goto accept_err;
+       }
+       down_write(&newcon->sock_sem);
+       if (newcon->sock) {
+               struct connection *othercon = newcon->othercon;
+
+               if (!othercon) {
+                       othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
+                       if (!othercon) {
+                               printk("dlm: failed to allocate incoming socket\n");
+                               up_write(&newcon->sock_sem);
+                               result = -ENOMEM;
+                               goto accept_err;
+                       }
+                       othercon->nodeid = nodeid;
+                       othercon->rx_action = receive_from_sock;
+                       init_rwsem(&othercon->sock_sem);
+                       set_bit(CF_IS_OTHERCON, &othercon->flags);
+                       newcon->othercon = othercon;
+               }
+               othercon->sock = newsock;
+               newsock->sk->sk_user_data = othercon;
+               add_sock(newsock, othercon);
+       }
+       else {
+               newsock->sk->sk_user_data = newcon;
+               newcon->rx_action = receive_from_sock;
+               add_sock(newsock, newcon);
+
+       }
+
+       up_write(&newcon->sock_sem);
+
+       /*
+        * Add it to the active queue in case we got data
+        * beween processing the accept adding the socket
+        * to the read_sockets list
+        */
+       lowcomms_data_ready(newsock->sk, 0);
+       up_read(&con->sock_sem);
+
+       return 0;
+
+accept_err:
+       up_read(&con->sock_sem);
+       sock_release(newsock);
+
+       if (result != -EAGAIN)
+               printk("dlm: error accepting connection from node: %d\n", result);
+       return result;
+}
+
+/* Connect a new socket to its peer */
+static void connect_to_sock(struct connection *con)
+{
+       int result = -EHOSTUNREACH;
+       struct sockaddr_storage saddr;
+       int addr_len;
+       struct socket *sock;
+
+       if (con->nodeid == 0) {
+               log_print("attempt to connect sock 0 foiled");
+               return;
+       }
+
+       down_write(&con->sock_sem);
+       if (con->retries++ > MAX_CONNECT_RETRIES)
+               goto out;
+
+       /* Some odd races can cause double-connects, ignore them */
+       if (con->sock) {
+               result = 0;
+               goto out;
+       }
+
+       /* Create a socket to communicate with */
+       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
+                                 IPPROTO_TCP, &sock);
+       if (result < 0)
+               goto out_err;
+
+       memset(&saddr, 0, sizeof(saddr));
+       if (dlm_nodeid_to_addr(con->nodeid, &saddr))
+               goto out_err;
+
+       sock->sk->sk_user_data = con;
+       con->rx_action = receive_from_sock;
+
+       make_sockaddr(&saddr, dlm_config.tcp_port, &addr_len);
+
+       add_sock(sock, con);
+
+       log_print("connecting to %d", con->nodeid);
+       result =
+               sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
+                                  O_NONBLOCK);
+       if (result == -EINPROGRESS)
+               result = 0;
+       if (result == 0)
+               goto out;
+
+out_err:
+       if (con->sock) {
+               sock_release(con->sock);
+               con->sock = NULL;
+       }
+       /*
+        * Some errors are fatal and this list might need adjusting. For other
+        * errors we try again until the max number of retries is reached.
+        */
+       if (result != -EHOSTUNREACH && result != -ENETUNREACH &&
+           result != -ENETDOWN && result != EINVAL
+           && result != -EPROTONOSUPPORT) {
+               lowcomms_connect_sock(con);
+               result = 0;
+       }
+out:
+       up_write(&con->sock_sem);
+       return;
+}
+
+static struct socket *create_listen_sock(struct connection *con,
+                                        struct sockaddr_storage *saddr)
+{
+       struct socket *sock = NULL;
+       mm_segment_t fs;
+       int result = 0;
+       int one = 1;
+       int addr_len;
+
+       if (dlm_local_addr.ss_family == AF_INET)
+               addr_len = sizeof(struct sockaddr_in);
+       else
+               addr_len = sizeof(struct sockaddr_in6);
+
+       /* Create a socket to communicate with */
+       result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, &sock);
+       if (result < 0) {
+               printk("dlm: Can't create listening comms socket\n");
+               goto create_out;
+       }
+
+       fs = get_fs();
+       set_fs(get_ds());
+       result = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                                (char *)&one, sizeof(one));
+       set_fs(fs);
+       if (result < 0) {
+               printk("dlm: Failed to set SO_REUSEADDR on socket: result=%d\n",
+                      result);
+       }
+       sock->sk->sk_user_data = con;
+       con->rx_action = accept_from_sock;
+       con->sock = sock;
+
+       /* Bind to our port */
+       make_sockaddr(saddr, dlm_config.tcp_port, &addr_len);
+       result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
+       if (result < 0) {
+               printk("dlm: Can't bind to port %d\n", dlm_config.tcp_port);
+               sock_release(sock);
+               sock = NULL;
+               con->sock = NULL;
+               goto create_out;
+       }
+
+       fs = get_fs();
+       set_fs(get_ds());
+
+       result = sock_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+                                (char *)&one, sizeof(one));
+       set_fs(fs);
+       if (result < 0) {
+               printk("dlm: Set keepalive failed: %d\n", result);
+       }
+
+       result = sock->ops->listen(sock, 5);
+       if (result < 0) {
+               printk("dlm: Can't listen on port %d\n", dlm_config.tcp_port);
+               sock_release(sock);
+               sock = NULL;
+               goto create_out;
+       }
+
+create_out:
+       return sock;
+}
+
+
+/* Listen on all interfaces */
+static int listen_for_all(void)
+{
+       struct socket *sock = NULL;
+       struct connection *con = nodeid2con(0, GFP_KERNEL);
+       int result = -EINVAL;
+
+       /* We don't support multi-homed hosts */
+       set_bit(CF_IS_OTHERCON, &con->flags);
+
+       sock = create_listen_sock(con, &dlm_local_addr);
+       if (sock) {
+               add_sock(sock, con);
+               result = 0;
+       }
+       else {
+               result = -EADDRINUSE;
+       }
+
+       return result;
+}
+
+
+
+static struct writequeue_entry *new_writequeue_entry(struct connection *con,
+                                                    gfp_t allocation)
+{
+       struct writequeue_entry *entry;
+
+       entry = kmalloc(sizeof(struct writequeue_entry), allocation);
+       if (!entry)
+               return NULL;
+
+       entry->page = alloc_page(allocation);
+       if (!entry->page) {
+               kfree(entry);
+               return NULL;
+       }
+
+       entry->offset = 0;
+       entry->len = 0;
+       entry->end = 0;
+       entry->users = 0;
+       entry->con = con;
+
+       return entry;
+}
+
+void *dlm_lowcomms_get_buffer(int nodeid, int len,
+                             gfp_t allocation, char **ppc)
+{
+       struct connection *con;
+       struct writequeue_entry *e;
+       int offset = 0;
+       int users = 0;
+
+       con = nodeid2con(nodeid, allocation);
+       if (!con)
+               return NULL;
+
+       e = list_entry(con->writequeue.prev, struct writequeue_entry, list);
+       if ((&e->list == &con->writequeue) ||
+           (PAGE_CACHE_SIZE - e->end < len)) {
+               e = NULL;
+       } else {
+               offset = e->end;
+               e->end += len;
+               users = e->users++;
+       }
+       spin_unlock(&con->writequeue_lock);
+
+       if (e) {
+       got_one:
+               if (users == 0)
+                       kmap(e->page);
+               *ppc = page_address(e->page) + offset;
+               return e;
+       }
+
+       e = new_writequeue_entry(con, allocation);
+       if (e) {
+               spin_lock(&con->writequeue_lock);
+               offset = e->end;
+               e->end += len;
+               users = e->users++;
+               list_add_tail(&e->list, &con->writequeue);
+               spin_unlock(&con->writequeue_lock);
+               goto got_one;
+       }
+       return NULL;
+}
+
+void dlm_lowcomms_commit_buffer(void *mh)
+{
+       struct writequeue_entry *e = (struct writequeue_entry *)mh;
+       struct connection *con = e->con;
+       int users;
+
+       users = --e->users;
+       if (users)
+               goto out;
+       e->len = e->end - e->offset;
+       kunmap(e->page);
+       spin_unlock(&con->writequeue_lock);
+
+       if (test_and_set_bit(CF_WRITE_PENDING, &con->flags) == 0) {
+               spin_lock_bh(&write_sockets_lock);
+               list_add_tail(&con->write_list, &write_sockets);
+               spin_unlock_bh(&write_sockets_lock);
+
+               wake_up_interruptible(&lowcomms_send_waitq);
+       }
+       return;
+
+out:
+       spin_unlock(&con->writequeue_lock);
+       return;
+}
+
+static void free_entry(struct writequeue_entry *e)
+{
+       __free_page(e->page);
+       kfree(e);
+}
+
+/* Send a message */
+static void send_to_sock(struct connection *con)
+{
+       int ret = 0;
+       ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int);
+       const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+       struct writequeue_entry *e;
+       int len, offset;
+
+       down_read(&con->sock_sem);
+       if (con->sock == NULL)
+               goto out_connect;
+
+       sendpage = con->sock->ops->sendpage;
+
+       spin_lock(&con->writequeue_lock);
+       for (;;) {
+               e = list_entry(con->writequeue.next, struct writequeue_entry,
+                              list);
+               if ((struct list_head *) e == &con->writequeue)
+                       break;
+
+               len = e->len;
+               offset = e->offset;
+               BUG_ON(len == 0 && e->users == 0);
+               spin_unlock(&con->writequeue_lock);
+
+               ret = 0;
+               if (len) {
+                       ret = sendpage(con->sock, e->page, offset, len,
+                                      msg_flags);
+                       if (ret == -EAGAIN || ret == 0)
+                               goto out;
+                       if (ret <= 0)
+                               goto send_error;
+               }
+               else {
+                       /* Don't starve people filling buffers */
+                       cond_resched();
+               }
+
+               spin_lock(&con->writequeue_lock);
+               e->offset += ret;
+               e->len -= ret;
+
+               if (e->len == 0 && e->users == 0) {
+                       list_del(&e->list);
+                       kunmap(e->page);
+                       free_entry(e);
+                       continue;
+               }
+       }
+       spin_unlock(&con->writequeue_lock);
+out:
+       up_read(&con->sock_sem);
+       return;
+
+send_error:
+       up_read(&con->sock_sem);
+       close_connection(con, false);
+       lowcomms_connect_sock(con);
+       return;
+
+out_connect:
+       up_read(&con->sock_sem);
+       lowcomms_connect_sock(con);
+       return;
+}
+
+static void clean_one_writequeue(struct connection *con)
+{
+       struct list_head *list;
+       struct list_head *temp;
+
+       spin_lock(&con->writequeue_lock);
+       list_for_each_safe(list, temp, &con->writequeue) {
+               struct writequeue_entry *e =
+                       list_entry(list, struct writequeue_entry, list);
+               list_del(&e->list);
+               free_entry(e);
+       }
+       spin_unlock(&con->writequeue_lock);
+}
+
+/* Called from recovery when it knows that a node has
+   left the cluster */
+int dlm_lowcomms_close(int nodeid)
+{
+       struct connection *con;
+
+       if (!connections)
+               goto out;
+
+       log_print("closing connection to node %d", nodeid);
+       con = nodeid2con(nodeid, 0);
+       if (con) {
+               clean_one_writequeue(con);
+               close_connection(con, true);
+               atomic_set(&con->waiting_requests, 0);
+       }
+       return 0;
+
+out:
+       return -1;
+}
+
+/* API send message call, may queue the request */
+/* N.B. This is the old interface - use the new one for new calls */
+int lowcomms_send_message(int nodeid, char *buf, int len, gfp_t allocation)
+{
+       struct writequeue_entry *e;
+       char *b;
+
+       e = dlm_lowcomms_get_buffer(nodeid, len, allocation, &b);
+       if (e) {
+               memcpy(b, buf, len);
+               dlm_lowcomms_commit_buffer(e);
+               return 0;
+       }
+       return -ENOBUFS;
+}
+
+/* Look for activity on active sockets */
+static void process_sockets(void)
+{
+       struct list_head *list;
+       struct list_head *temp;
+       int count = 0;
+
+       spin_lock_bh(&read_sockets_lock);
+       list_for_each_safe(list, temp, &read_sockets) {
+
+               struct connection *con =
+                       list_entry(list, struct connection, read_list);
+               list_del(&con->read_list);
+               clear_bit(CF_READ_PENDING, &con->flags);
+
+               spin_unlock_bh(&read_sockets_lock);
+
+               /* This can reach zero if we are processing requests
+                * as they come in.
+                */
+               if (atomic_read(&con->waiting_requests) == 0) {
+                       spin_lock_bh(&read_sockets_lock);
+                       continue;
+               }
+
+               do {
+                       con->rx_action(con);
+
+                       /* Don't starve out everyone else */
+                       if (++count >= MAX_RX_MSG_COUNT) {
+                               cond_resched();
+                               count = 0;
+                       }
+
+               } while (!atomic_dec_and_test(&con->waiting_requests) &&
+                        !kthread_should_stop());
+
+               spin_lock_bh(&read_sockets_lock);
+       }
+       spin_unlock_bh(&read_sockets_lock);
+}
+
+/* Try to send any messages that are pending
+ */
+static void process_output_queue(void)
+{
+       struct list_head *list;
+       struct list_head *temp;
+
+       spin_lock_bh(&write_sockets_lock);
+       list_for_each_safe(list, temp, &write_sockets) {
+               struct connection *con =
+                       list_entry(list, struct connection, write_list);
+               clear_bit(CF_WRITE_PENDING, &con->flags);
+               list_del(&con->write_list);
+
+               spin_unlock_bh(&write_sockets_lock);
+               send_to_sock(con);
+               spin_lock_bh(&write_sockets_lock);
+       }
+       spin_unlock_bh(&write_sockets_lock);
+}
+
+static void process_state_queue(void)
+{
+       struct list_head *list;
+       struct list_head *temp;
+
+       spin_lock_bh(&state_sockets_lock);
+       list_for_each_safe(list, temp, &state_sockets) {
+               struct connection *con =
+                       list_entry(list, struct connection, state_list);
+               list_del(&con->state_list);
+               clear_bit(CF_CONNECT_PENDING, &con->flags);
+               spin_unlock_bh(&state_sockets_lock);
+
+               connect_to_sock(con);
+               spin_lock_bh(&state_sockets_lock);
+       }
+       spin_unlock_bh(&state_sockets_lock);
+}
+
+
+/* Discard all entries on the write queues */
+static void clean_writequeues(void)
+{
+       int nodeid;
+
+       for (nodeid = 1; nodeid < conn_array_size; nodeid++) {
+               struct connection *con = nodeid2con(nodeid, 0);
+
+               if (con)
+                       clean_one_writequeue(con);
+       }
+}
+
+static int read_list_empty(void)
+{
+       int status;
+
+       spin_lock_bh(&read_sockets_lock);
+       status = list_empty(&read_sockets);
+       spin_unlock_bh(&read_sockets_lock);
+
+       return status;
+}
+
+/* DLM Transport comms receive daemon */
+static int dlm_recvd(void *data)
+{
+       init_waitqueue_entry(&lowcomms_recv_waitq_head, current);
+       add_wait_queue(&lowcomms_recv_waitq, &lowcomms_recv_waitq_head);
+
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (read_list_empty())
+                       cond_resched();
+               set_current_state(TASK_RUNNING);
+
+               process_sockets();
+       }
+
+       return 0;
+}
+
+static int write_and_state_lists_empty(void)
+{
+       int status;
+
+       spin_lock_bh(&write_sockets_lock);
+       status = list_empty(&write_sockets);
+       spin_unlock_bh(&write_sockets_lock);
+
+       spin_lock_bh(&state_sockets_lock);
+       if (list_empty(&state_sockets) == 0)
+               status = 0;
+       spin_unlock_bh(&state_sockets_lock);
+
+       return status;
+}
+
+/* DLM Transport send daemon */
+static int dlm_sendd(void *data)
+{
+       init_waitqueue_entry(&lowcomms_send_waitq_head, current);
+       add_wait_queue(&lowcomms_send_waitq, &lowcomms_send_waitq_head);
+
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (write_and_state_lists_empty())
+                       cond_resched();
+               set_current_state(TASK_RUNNING);
+
+               process_state_queue();
+               process_output_queue();
+       }
+
+       return 0;
+}
+
+static void daemons_stop(void)
+{
+       kthread_stop(recv_task);
+       kthread_stop(send_task);
+}
+
+static int daemons_start(void)
+{
+       struct task_struct *p;
+       int error;
+
+       p = kthread_run(dlm_recvd, NULL, "dlm_recvd");
+       error = IS_ERR(p);
+       if (error) {
+               log_print("can't start dlm_recvd %d", error);
+               return error;
+       }
+       recv_task = p;
+
+       p = kthread_run(dlm_sendd, NULL, "dlm_sendd");
+       error = IS_ERR(p);
+       if (error) {
+               log_print("can't start dlm_sendd %d", error);
+               kthread_stop(recv_task);
+               return error;
+       }
+       send_task = p;
+
+       return 0;
+}
+
+/*
+ * Return the largest buffer size we can cope with.
+ */
+int lowcomms_max_buffer_size(void)
+{
+       return PAGE_CACHE_SIZE;
+}
+
+void dlm_lowcomms_stop(void)
+{
+       int i;
+
+       /* Set all the flags to prevent any
+          socket activity.
+       */
+       for (i = 0; i < conn_array_size; i++) {
+               if (connections[i])
+                       connections[i]->flags |= 0xFF;
+       }
+
+       daemons_stop();
+       clean_writequeues();
+
+       for (i = 0; i < conn_array_size; i++) {
+               if (connections[i]) {
+                       close_connection(connections[i], true);
+                       if (connections[i]->othercon)
+                               kmem_cache_free(con_cache, connections[i]->othercon);
+                       kmem_cache_free(con_cache, connections[i]);
+               }
+       }
+
+       kfree(connections);
+       connections = NULL;
+
+       kmem_cache_destroy(con_cache);
+}
+
+/* This is quite likely to sleep... */
+int dlm_lowcomms_start(void)
+{
+       int error = 0;
+
+       error = -ENOMEM;
+       connections = kzalloc(sizeof(struct connection *) *
+                             NODE_INCREMENT, GFP_KERNEL);
+       if (!connections)
+               goto out;
+
+       conn_array_size = NODE_INCREMENT;
+
+       if (dlm_our_addr(&dlm_local_addr, 0)) {
+               log_print("no local IP address has been set");
+               goto fail_free_conn;
+       }
+       if (!dlm_our_addr(&dlm_local_addr, 1)) {
+               log_print("This dlm comms module does not support multi-homed clustering");
+               goto fail_free_conn;
+       }
+
+       con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection),
+                                     __alignof__(struct connection), 0,
+                                     NULL, NULL);
+       if (!con_cache)
+               goto fail_free_conn;
+
+
+       /* Start listening */
+       error = listen_for_all();
+       if (error)
+               goto fail_unlisten;
+
+       error = daemons_start();
+       if (error)
+               goto fail_unlisten;
+
+       return 0;
+
+fail_unlisten:
+       close_connection(connections[0], false);
+       kmem_cache_free(con_cache, connections[0]);
+       kmem_cache_destroy(con_cache);
+
+fail_free_conn:
+       kfree(connections);
+
+out:
+       return error;
+}
+
+/*
+ * 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 2d045e0..a9a9618 100644 (file)
@@ -14,8 +14,6 @@
 #ifndef __LOWCOMMS_DOT_H__
 #define __LOWCOMMS_DOT_H__
 
-int dlm_lowcomms_init(void);
-void dlm_lowcomms_exit(void);
 int dlm_lowcomms_start(void);
 void dlm_lowcomms_stop(void);
 int dlm_lowcomms_close(int nodeid);
index a8da8dc..162fbae 100644 (file)
@@ -16,7 +16,6 @@
 #include "lock.h"
 #include "user.h"
 #include "memory.h"
-#include "lowcomms.h"
 #include "config.h"
 
 #ifdef CONFIG_DLM_DEBUG
@@ -47,20 +46,14 @@ static int __init init_dlm(void)
        if (error)
                goto out_config;
 
-       error = dlm_lowcomms_init();
-       if (error)
-               goto out_debug;
-
        error = dlm_user_init();
        if (error)
-               goto out_lowcomms;
+               goto out_debug;
 
        printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
 
        return 0;
 
- out_lowcomms:
-       dlm_lowcomms_exit();
  out_debug:
        dlm_unregister_debugfs();
  out_config:
@@ -76,7 +69,6 @@ static int __init init_dlm(void)
 static void __exit exit_dlm(void)
 {
        dlm_user_exit();
-       dlm_lowcomms_exit();
        dlm_config_exit();
        dlm_memory_exit();
        dlm_lockspace_exit();
index a3f7de7..85e2897 100644 (file)
@@ -186,6 +186,14 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
        struct dlm_member *memb, *safe;
        int i, error, found, pos = 0, neg = 0, low = -1;
 
+       /* previously removed members that we've not finished removing need to
+          count as a negative change so the "neg" recovery steps will happen */
+
+       list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
+               log_debug(ls, "prev removed member %d", memb->nodeid);
+               neg++;
+       }
+
        /* move departed members from ls_nodes to ls_nodes_gone */
 
        list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) {
index 989b608..5352b03 100644 (file)
@@ -15,7 +15,7 @@
 #include "config.h"
 #include "memory.h"
 
-static kmem_cache_t *lkb_cache;
+static struct kmem_cache *lkb_cache;
 
 
 int dlm_memory_init(void)
index 518239a..4cc31be 100644 (file)
@@ -90,13 +90,28 @@ static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid)
        return 0;
 }
 
+static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq)
+{
+       spin_lock(&ls->ls_rcom_spin);
+       *new_seq = ++ls->ls_rcom_seq;
+       set_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
+       spin_unlock(&ls->ls_rcom_spin);
+}
+
+static void disallow_sync_reply(struct dlm_ls *ls)
+{
+       spin_lock(&ls->ls_rcom_spin);
+       clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
+       clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+       spin_unlock(&ls->ls_rcom_spin);
+}
+
 int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
 {
        struct dlm_rcom *rc;
        struct dlm_mhandle *mh;
        int error = 0;
 
-       memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
        ls->ls_recover_nodeid = nodeid;
 
        if (nodeid == dlm_our_nodeid()) {
@@ -108,12 +123,14 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
        error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 0, &rc, &mh);
        if (error)
                goto out;
-       rc->rc_id = ++ls->ls_rcom_seq;
+
+       allow_sync_reply(ls, &rc->rc_id);
+       memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
 
        send_rcom(ls, mh, rc);
 
        error = dlm_wait_function(ls, &rcom_response);
-       clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+       disallow_sync_reply(ls);
        if (error)
                goto out;
 
@@ -150,14 +167,21 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 
 static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 {
-       if (rc_in->rc_id != ls->ls_rcom_seq) {
-               log_debug(ls, "reject old reply %d got %llx wanted %llx",
-                         rc_in->rc_type, rc_in->rc_id, ls->ls_rcom_seq);
-               return;
+       spin_lock(&ls->ls_rcom_spin);
+       if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) ||
+           rc_in->rc_id != ls->ls_rcom_seq) {
+               log_debug(ls, "reject reply %d from %d seq %llx expect %llx",
+                         rc_in->rc_type, rc_in->rc_header.h_nodeid,
+                         (unsigned long long)rc_in->rc_id,
+                         (unsigned long long)ls->ls_rcom_seq);
+               goto out;
        }
        memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length);
        set_bit(LSFL_RCOM_READY, &ls->ls_flags);
+       clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
        wake_up(&ls->ls_wait_general);
+ out:
+       spin_unlock(&ls->ls_rcom_spin);
 }
 
 static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
@@ -171,7 +195,6 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
        struct dlm_mhandle *mh;
        int error = 0, len = sizeof(struct dlm_rcom);
 
-       memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
        ls->ls_recover_nodeid = nodeid;
 
        if (nodeid == dlm_our_nodeid()) {
@@ -185,12 +208,14 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
        if (error)
                goto out;
        memcpy(rc->rc_buf, last_name, last_len);
-       rc->rc_id = ++ls->ls_rcom_seq;
+
+       allow_sync_reply(ls, &rc->rc_id);
+       memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
 
        send_rcom(ls, mh, rc);
 
        error = dlm_wait_function(ls, &rcom_response);
-       clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+       disallow_sync_reply(ls);
  out:
        return error;
 }
@@ -370,9 +395,10 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
 {
        struct dlm_rcom *rc;
+       struct rcom_config *rf;
        struct dlm_mhandle *mh;
        char *mb;
-       int mb_len = sizeof(struct dlm_rcom);
+       int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
 
        mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb);
        if (!mh)
@@ -391,6 +417,9 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
        rc->rc_id = rc_in->rc_id;
        rc->rc_result = -ESRCH;
 
+       rf = (struct rcom_config *) rc->rc_buf;
+       rf->rf_lvblen = -1;
+
        dlm_rcom_out(rc);
        dlm_lowcomms_commit_buffer(mh);
 
@@ -412,9 +441,10 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
 
        ls = dlm_find_lockspace_global(hd->h_lockspace);
        if (!ls) {
-               log_print("lockspace %x from %d not found",
-                         hd->h_lockspace, nodeid);
-               send_ls_not_ready(nodeid, rc);
+               log_print("lockspace %x from %d type %x not found",
+                         hd->h_lockspace, nodeid, rc->rc_type);
+               if (rc->rc_type == DLM_RCOM_STATUS)
+                       send_ls_not_ready(nodeid, rc);
                return;
        }
 
index a5e6d18..cf9f683 100644 (file)
@@ -252,6 +252,7 @@ static void recover_list_clear(struct dlm_ls *ls)
        spin_lock(&ls->ls_recover_list_lock);
        list_for_each_entry_safe(r, s, &ls->ls_recover_list, res_recover_list) {
                list_del_init(&r->res_recover_list);
+               r->res_recover_locks_count = 0;
                dlm_put_rsb(r);
                ls->ls_recover_list_count--;
        }
index 362e3ef..650536a 100644 (file)
@@ -45,7 +45,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
        unsigned long start;
        int error, neg = 0;
 
-       log_debug(ls, "recover %llx", rv->seq);
+       log_debug(ls, "recover %llx", (unsigned long long)rv->seq);
 
        mutex_lock(&ls->ls_recoverd_active);
 
@@ -93,14 +93,6 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
                goto fail;
        }
 
-       /*
-        * Purge directory-related requests that are saved in requestqueue.
-        * All dir requests from before recovery are invalid now due to the dir
-        * rebuild and will be resent by the requesting nodes.
-        */
-
-       dlm_purge_requestqueue(ls);
-
        /*
         * Wait for all nodes to complete directory rebuild.
         */
@@ -164,10 +156,31 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
                 */
 
                dlm_recover_rsbs(ls);
+       } else {
+               /*
+                * Other lockspace members may be going through the "neg" steps
+                * while also adding us to the lockspace, in which case they'll
+                * be doing the recover_locks (RS_LOCKS) barrier.
+                */
+               dlm_set_recover_status(ls, DLM_RS_LOCKS);
+
+               error = dlm_recover_locks_wait(ls);
+               if (error) {
+                       log_error(ls, "recover_locks_wait failed %d", error);
+                       goto fail;
+               }
        }
 
        dlm_release_root_list(ls);
 
+       /*
+        * Purge directory-related requests that are saved in requestqueue.
+        * All dir requests from before recovery are invalid now due to the dir
+        * rebuild and will be resent by the requesting nodes.
+        */
+
+       dlm_purge_requestqueue(ls);
+
        dlm_set_recover_status(ls, DLM_RS_DONE);
        error = dlm_recover_done_wait(ls);
        if (error) {
@@ -199,7 +212,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
        dlm_astd_wake();
 
-       log_debug(ls, "recover %llx done: %u ms", rv->seq,
+       log_debug(ls, "recover %llx done: %u ms",
+                 (unsigned long long)rv->seq,
                  jiffies_to_msecs(jiffies - start));
        mutex_unlock(&ls->ls_recoverd_active);
 
@@ -207,11 +221,16 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
  fail:
        dlm_release_root_list(ls);
-       log_debug(ls, "recover %llx error %d", rv->seq, error);
+       log_debug(ls, "recover %llx error %d",
+                 (unsigned long long)rv->seq, error);
        mutex_unlock(&ls->ls_recoverd_active);
        return error;
 }
 
+/* The dlm_ls_start() that created the rv we take here may already have been
+   stopped via dlm_ls_stop(); in that case we need to leave the RECOVERY_STOP
+   flag set. */
+
 static void do_ls_recovery(struct dlm_ls *ls)
 {
        struct dlm_recover *rv = NULL;
@@ -219,7 +238,8 @@ static void do_ls_recovery(struct dlm_ls *ls)
        spin_lock(&ls->ls_recover_lock);
        rv = ls->ls_recover_args;
        ls->ls_recover_args = NULL;
-       clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
+       if (rv && ls->ls_recover_seq == rv->seq)
+               clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
        spin_unlock(&ls->ls_recover_lock);
 
        if (rv) {
index 7b2b089..65008d7 100644 (file)
@@ -30,26 +30,36 @@ struct rq_entry {
  * lockspace is enabled on some while still suspended on others.
  */
 
-void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
+int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
 {
        struct rq_entry *e;
        int length = hd->h_length;
-
-       if (dlm_is_removed(ls, nodeid))
-               return;
+       int rv = 0;
 
        e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL);
        if (!e) {
                log_print("dlm_add_requestqueue: out of memory\n");
-               return;
+               return 0;
        }
 
        e->nodeid = nodeid;
        memcpy(e->request, hd, length);
 
+       /* We need to check dlm_locking_stopped() after taking the mutex to
+          avoid a race where dlm_recoverd enables locking and runs
+          process_requestqueue between our earlier dlm_locking_stopped check
+          and this addition to the requestqueue. */
+
        mutex_lock(&ls->ls_requestqueue_mutex);
-       list_add_tail(&e->list, &ls->ls_requestqueue);
+       if (dlm_locking_stopped(ls))
+               list_add_tail(&e->list, &ls->ls_requestqueue);
+       else {
+               log_debug(ls, "dlm_add_requestqueue skip from %d", nodeid);
+               kfree(e);
+               rv = -EAGAIN;
+       }
        mutex_unlock(&ls->ls_requestqueue_mutex);
+       return rv;
 }
 
 int dlm_process_requestqueue(struct dlm_ls *ls)
@@ -120,6 +130,10 @@ static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid)
 {
        uint32_t type = ms->m_type;
 
+       /* the ls is being cleaned up and freed by release_lockspace */
+       if (!ls->ls_count)
+               return 1;
+
        if (dlm_is_removed(ls, nodeid))
                return 1;
 
index 349f0d2..6a53ea0 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef __REQUESTQUEUE_DOT_H__
 #define __REQUESTQUEUE_DOT_H__
 
-void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd);
+int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd);
 int dlm_process_requestqueue(struct dlm_ls *ls);
 void dlm_wait_requestqueue(struct dlm_ls *ls);
 void dlm_purge_requestqueue(struct dlm_ls *ls);
index 2b0442d..936409f 100644 (file)
@@ -23,7 +23,7 @@
 
 int dir_notify_enable __read_mostly = 1;
 
-static kmem_cache_t *dn_cache __read_mostly;
+static struct kmem_cache *dn_cache __read_mostly;
 
 static void redo_inode_mask(struct inode *inode)
 {
@@ -42,7 +42,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
        struct dnotify_struct **prev;
        struct inode *inode;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (!S_ISDIR(inode->i_mode))
                return;
        spin_lock(&inode->i_lock);
@@ -74,10 +74,10 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
        }
        if (!dir_notify_enable)
                return -EINVAL;
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (!S_ISDIR(inode->i_mode))
                return -ENOTDIR;
-       dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL);
+       dn = kmem_cache_alloc(dn_cache, GFP_KERNEL);
        if (dn == NULL)
                return -ENOMEM;
        spin_lock(&inode->i_lock);
index 9af7895..0952cc4 100644 (file)
@@ -131,7 +131,7 @@ static struct quota_format_type *quota_formats;     /* List of registered formats */
 static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
 
 /* SLAB cache for dquot structures */
-static kmem_cache_t *dquot_cachep;
+static struct kmem_cache *dquot_cachep;
 
 int register_quota_format(struct quota_format_type *fmt)
 {
@@ -600,7 +600,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
 {
        struct dquot *dquot;
 
-       dquot = kmem_cache_alloc(dquot_cachep, SLAB_NOFS);
+       dquot = kmem_cache_alloc(dquot_cachep, GFP_NOFS);
        if(!dquot)
                return NODQUOT;
 
@@ -694,9 +694,9 @@ restart:
        file_list_lock();
        list_for_each(p, &sb->s_files) {
                struct file *filp = list_entry(p, struct file, f_u.fu_list);
-               struct inode *inode = filp->f_dentry->d_inode;
+               struct inode *inode = filp->f_path.dentry->d_inode;
                if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
-                       struct dentry *dentry = dget(filp->f_dentry);
+                       struct dentry *dentry = dget(filp->f_path.dentry);
                        file_list_unlock();
                        sb->dq_op->initialize(inode, type);
                        dput(dentry);
@@ -828,6 +828,7 @@ static inline int need_print_warning(struct dquot *dquot)
 static void print_warning(struct dquot *dquot, const char warntype)
 {
        char *msg = NULL;
+       struct tty_struct *tty;
        int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B :
          ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0);
 
@@ -835,14 +836,15 @@ static void print_warning(struct dquot *dquot, const char warntype)
                return;
 
        mutex_lock(&tty_mutex);
-       if (!current->signal->tty)
+       tty = get_current_tty();
+       if (!tty)
                goto out_lock;
-       tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
+       tty_write_message(tty, dquot->dq_sb->s_id);
        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
-               tty_write_message(current->signal->tty, ": warning, ");
+               tty_write_message(tty, ": warning, ");
        else
-               tty_write_message(current->signal->tty, ": write failed, ");
-       tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]);
+               tty_write_message(tty, ": write failed, ");
+       tty_write_message(tty, quotatypes[dquot->dq_type]);
        switch (warntype) {
                case IHARDWARN:
                        msg = " file limit reached.\r\n";
@@ -863,7 +865,7 @@ static void print_warning(struct dquot *dquot, const char warntype)
                        msg = " block quota exceeded.\r\n";
                        break;
        }
-       tty_write_message(current->signal->tty, msg);
+       tty_write_message(tty, msg);
 out_lock:
        mutex_unlock(&tty_mutex);
 }
index f63a775..7196f50 100644 (file)
@@ -628,7 +628,7 @@ int ecryptfs_decrypt_page(struct file *file, struct page *page)
        num_extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
        base_extent = (page->index * num_extents_per_page);
        lower_page_virt = kmem_cache_alloc(ecryptfs_lower_page_cache,
-                                          SLAB_KERNEL);
+                                          GFP_KERNEL);
        if (!lower_page_virt) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Error getting page for encrypted "
@@ -1334,7 +1334,7 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
                goto out;
        }
        /* Released in this function */
-       page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, SLAB_USER);
+       page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, GFP_USER);
        if (!page_virt) {
                ecryptfs_printk(KERN_ERR, "Out of memory\n");
                rc = -ENOMEM;
@@ -1493,7 +1493,7 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
            &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
 
        /* Read the first page from the underlying file */
-       page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, SLAB_USER);
+       page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
        if (!page_virt) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Unable to allocate page_virt\n");
index 52d1e36..329efcd 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/fs_stack.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -61,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
                struct inode *lower_inode =
                        ecryptfs_inode_to_lower(dentry->d_inode);
 
-               ecryptfs_copy_attr_all(dentry->d_inode, lower_inode);
+               fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
        }
 out:
        return rc;
index f992533..afb64bd 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <keys/user-type.h>
 #include <linux/fs.h>
+#include <linux/fs_stack.h>
+#include <linux/namei.h>
 #include <linux/scatterlist.h>
 
 /* Version verification for shared data structures w/ userspace */
@@ -227,8 +229,7 @@ struct ecryptfs_inode_info {
 /* dentry private data. Each dentry must keep track of a lower
  * vfsmount too. */
 struct ecryptfs_dentry_info {
-       struct dentry *wdi_dentry;
-       struct vfsmount *lower_mnt;
+       struct path lower_path;
        struct ecryptfs_crypt_stat *crypt_stat;
 };
 
@@ -355,26 +356,26 @@ ecryptfs_set_dentry_private(struct dentry *dentry,
 static inline struct dentry *
 ecryptfs_dentry_to_lower(struct dentry *dentry)
 {
-       return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry;
+       return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry;
 }
 
 static inline void
 ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry)
 {
-       ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry =
+       ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry =
                lower_dentry;
 }
 
 static inline struct vfsmount *
 ecryptfs_dentry_to_lower_mnt(struct dentry *dentry)
 {
-       return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt;
+       return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt;
 }
 
 static inline void
 ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
 {
-       ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt =
+       ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt =
                lower_mnt;
 }
 
@@ -413,9 +414,6 @@ int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
                             const char *name, int length,
                             char **encoded_name);
 struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src);
-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src);
-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src);
 void ecryptfs_dump_hex(char *data, int bytes);
 int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
                        int sg_size);
index a92ef05..c5a2e52 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/security.h>
 #include <linux/smp_lock.h>
 #include <linux/compat.h>
+#include <linux/fs_stack.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -75,7 +76,7 @@ static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
        }
        ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
        if (expanding_file) {
-               rc = ecryptfs_truncate(file->f_dentry, new_end_pos);
+               rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
                if (rc) {
                        rv = rc;
                        ecryptfs_printk(KERN_ERR, "Error on attempt to "
@@ -116,8 +117,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
        if (-EIOCBQUEUED == rc)
                rc = wait_on_sync_kiocb(iocb);
        if (rc >= 0) {
-               lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry);
-               lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry);
+               lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
+               lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
                touch_atime(lower_vfsmount, lower_dentry);
        }
        return rc;
@@ -176,10 +177,10 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
 
        lower_file = ecryptfs_file_to_lower(file);
        lower_file->f_pos = file->f_pos;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        memset(&buf, 0, sizeof(buf));
        buf.dirent = dirent;
-       buf.dentry = file->f_dentry;
+       buf.dentry = file->f_path.dentry;
        buf.filldir = filldir;
 retry:
        buf.filldir_called = 0;
@@ -192,7 +193,7 @@ retry:
                goto retry;
        file->f_pos = lower_file->f_pos;
        if (rc >= 0)
-               ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
+               fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode);
        return rc;
 }
 
@@ -239,7 +240,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
        int rc = 0;
        struct ecryptfs_crypt_stat *crypt_stat = NULL;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
-       struct dentry *ecryptfs_dentry = file->f_dentry;
+       struct dentry *ecryptfs_dentry = file->f_path.dentry;
        /* Private value of ecryptfs_dentry allocated in
         * ecryptfs_lookup() */
        struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
@@ -250,7 +251,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
        int lower_flags;
 
        /* Released in ecryptfs_release or end of function if failure */
-       file_info = kmem_cache_alloc(ecryptfs_file_info_cache, SLAB_KERNEL);
+       file_info = kmem_cache_alloc(ecryptfs_file_info_cache, GFP_KERNEL);
        ecryptfs_set_file_private(file, file_info);
        if (!file_info) {
                ecryptfs_printk(KERN_ERR,
index dfcc684..11f5e50 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/crypto.h>
+#include <linux/fs_stack.h>
 #include "ecryptfs_kernel.h"
 
 static struct dentry *lock_parent(struct dentry *dentry)
@@ -53,48 +54,6 @@ static void unlock_dir(struct dentry *dir)
        dput(dir);
 }
 
-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src)
-{
-       i_size_write(dst, i_size_read((struct inode *)src));
-       dst->i_blocks = src->i_blocks;
-}
-
-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src)
-{
-       dest->i_atime = src->i_atime;
-}
-
-static void ecryptfs_copy_attr_times(struct inode *dest,
-                                    const struct inode *src)
-{
-       dest->i_atime = src->i_atime;
-       dest->i_mtime = src->i_mtime;
-       dest->i_ctime = src->i_ctime;
-}
-
-static void ecryptfs_copy_attr_timesizes(struct inode *dest,
-                                        const struct inode *src)
-{
-       dest->i_atime = src->i_atime;
-       dest->i_mtime = src->i_mtime;
-       dest->i_ctime = src->i_ctime;
-       ecryptfs_copy_inode_size(dest, src);
-}
-
-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src)
-{
-       dest->i_mode = src->i_mode;
-       dest->i_nlink = src->i_nlink;
-       dest->i_uid = src->i_uid;
-       dest->i_gid = src->i_gid;
-       dest->i_rdev = src->i_rdev;
-       dest->i_atime = src->i_atime;
-       dest->i_mtime = src->i_mtime;
-       dest->i_ctime = src->i_ctime;
-       dest->i_blkbits = src->i_blkbits;
-       dest->i_flags = src->i_flags;
-}
-
 /**
  * ecryptfs_create_underlying_file
  * @lower_dir_inode: inode of the parent in the lower fs of the new file
@@ -171,8 +130,8 @@ ecryptfs_do_create(struct inode *directory_inode,
                ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
                goto out_lock;
        }
-       ecryptfs_copy_attr_timesizes(directory_inode,
-                                    lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
+       fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
 out_lock:
        unlock_dir(lower_dir_dentry);
 out:
@@ -196,7 +155,7 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
        struct ecryptfs_file_info tmp_file_info;
 
        memset(&fake_file, 0, sizeof(fake_file));
-       fake_file.f_dentry = ecryptfs_dentry;
+       fake_file.f_path.dentry = ecryptfs_dentry;
        memset(&tmp_file_info, 0, sizeof(tmp_file_info));
        ecryptfs_set_file_private(&fake_file, &tmp_file_info);
        ecryptfs_set_file_lower(&fake_file, lower_file);
@@ -365,11 +324,11 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
                        "d_name.name = [%s]\n", lower_dentry,
                lower_dentry->d_name.name);
        lower_inode = lower_dentry->d_inode;
-       ecryptfs_copy_attr_atime(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode);
        BUG_ON(!atomic_read(&lower_dentry->d_count));
        ecryptfs_set_dentry_private(dentry,
                                    kmem_cache_alloc(ecryptfs_dentry_info_cache,
-                                                    SLAB_KERNEL));
+                                                    GFP_KERNEL));
        if (!ecryptfs_dentry_to_private(dentry)) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Out of memory whilst attempting "
@@ -404,7 +363,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
        /* Released in this function */
        page_virt =
            (char *)kmem_cache_alloc(ecryptfs_header_cache_2,
-                                    SLAB_USER);
+                                    GFP_USER);
        if (!page_virt) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR,
@@ -462,7 +421,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
        rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
        if (rc)
                goto out_lock;
-       ecryptfs_copy_attr_timesizes(dir, lower_new_dentry->d_inode);
+       fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
+       fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
        old_dentry->d_inode->i_nlink =
                ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
        i_size_write(new_dentry->d_inode, file_size_save);
@@ -488,7 +448,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
                printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
                goto out_unlock;
        }
-       ecryptfs_copy_attr_times(dir, lower_dir_inode);
+       fsstack_copy_attr_times(dir, lower_dir_inode);
        dentry->d_inode->i_nlink =
                ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
        dentry->d_inode->i_ctime = dir->i_ctime;
@@ -527,7 +487,8 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
        if (rc)
                goto out_lock;
-       ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
 out_lock:
        unlock_dir(lower_dir_dentry);
        dput(lower_dentry);
@@ -550,7 +511,8 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
        if (rc)
                goto out;
-       ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
        dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
 out:
        unlock_dir(lower_dir_dentry);
@@ -573,7 +535,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
        dput(lower_dentry);
        if (!rc)
                d_delete(lower_dentry);
-       ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
        unlock_dir(lower_dir_dentry);
        if (!rc)
@@ -597,7 +559,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
        if (rc)
                goto out;
-       ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
 out:
        unlock_dir(lower_dir_dentry);
        if (!dentry->d_inode)
@@ -626,9 +589,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        lower_new_dir_dentry->d_inode, lower_new_dentry);
        if (rc)
                goto out_lock;
-       ecryptfs_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
        if (new_dir != old_dir)
-               ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
+               fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
 out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        dput(lower_new_dentry->d_parent);
@@ -684,8 +647,8 @@ ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
                                rc = -EFAULT;
                }
                kfree(decoded_name);
-               ecryptfs_copy_attr_atime(dentry->d_inode,
-                                        lower_dentry->d_inode);
+               fsstack_copy_attr_atime(dentry->d_inode,
+                                       lower_dentry->d_inode);
        }
 out_free_lower_buf:
        kfree(lower_buf);
@@ -791,11 +754,11 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
         * the file in the underlying filesystem so that the
         * truncation has an effect there as well. */
        memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file));
-       fake_ecryptfs_file.f_dentry = dentry;
+       fake_ecryptfs_file.f_path.dentry = dentry;
        /* Released at out_free: label */
        ecryptfs_set_file_private(&fake_ecryptfs_file,
                                  kmem_cache_alloc(ecryptfs_file_info_cache,
-                                                  SLAB_KERNEL));
+                                                  GFP_KERNEL));
        if (unlikely(!ecryptfs_file_to_private(&fake_ecryptfs_file))) {
                rc = -ENOMEM;
                goto out;
@@ -915,7 +878,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        }
        rc = notify_change(lower_dentry, ia);
 out:
-       ecryptfs_copy_attr_all(inode, lower_inode);
+       fsstack_copy_attr_all(inode, lower_inode, NULL);
        return rc;
 }
 
index c3746f5..745c0f1 100644 (file)
@@ -207,7 +207,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
        /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
         * at end of function upon failure */
        auth_tok_list_item =
-           kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, SLAB_KERNEL);
+           kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
        if (!auth_tok_list_item) {
                ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
                rc = -ENOMEM;
index a78d87d..d0541ae 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/pagemap.h>
 #include <linux/key.h>
 #include <linux/parser.h>
+#include <linux/fs_stack.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -112,10 +113,10 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
                d_add(dentry, inode);
        else
                d_instantiate(dentry, inode);
-       ecryptfs_copy_attr_all(inode, lower_inode);
+       fsstack_copy_attr_all(inode, lower_inode, NULL);
        /* This size will be overwritten for real files w/ headers and
         * other metadata */
-       ecryptfs_copy_inode_size(inode, lower_inode);
+       fsstack_copy_inode_size(inode, lower_inode);
 out:
        return rc;
 }
@@ -378,7 +379,7 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent)
        /* Released in ecryptfs_put_super() */
        ecryptfs_set_superblock_private(sb,
                                        kmem_cache_alloc(ecryptfs_sb_info_cache,
-                                                        SLAB_KERNEL));
+                                                        GFP_KERNEL));
        if (!ecryptfs_superblock_to_private(sb)) {
                ecryptfs_printk(KERN_WARNING, "Out of memory\n");
                rc = -ENOMEM;
@@ -402,7 +403,7 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent)
        /* through deactivate_super(sb) from get_sb_nodev() */
        ecryptfs_set_dentry_private(sb->s_root,
                                    kmem_cache_alloc(ecryptfs_dentry_info_cache,
-                                                    SLAB_KERNEL));
+                                                    GFP_KERNEL));
        if (!ecryptfs_dentry_to_private(sb->s_root)) {
                ecryptfs_printk(KERN_ERR,
                                "dentry_info_cache alloc failed\n");
@@ -546,7 +547,7 @@ inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags)
 }
 
 static struct ecryptfs_cache_info {
-       kmem_cache_t **cache;
+       struct kmem_cache **cache;
        const char *name;
        size_t size;
        void (*ctor)(void*, struct kmem_cache *, unsigned long);
@@ -691,7 +692,7 @@ static ssize_t version_show(struct ecryptfs_obj *obj, char *buff)
 
 static struct ecryptfs_attribute sysfs_attr_version = __ATTR_RO(version);
 
-struct ecryptfs_version_str_map_elem {
+static struct ecryptfs_version_str_map_elem {
        u32 flag;
        char *str;
 } ecryptfs_version_str_map[] = {
index 924dd90..06843d2 100644 (file)
@@ -51,7 +51,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
        struct inode *inode;
        struct address_space *mapping;
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        inode = dentry->d_inode;
        mapping = inode->i_mapping;
        page = read_cache_page(mapping, index,
@@ -84,7 +84,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
 int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
 {
        int rc = 0;
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        pgoff_t old_end_page_index = 0;
        pgoff_t index = old_end_page_index;
@@ -218,7 +218,7 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
        char *lower_page_data;
        const struct address_space_operations *lower_a_ops;
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        lower_file = ecryptfs_file_to_lower(file);
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        inode = dentry->d_inode;
@@ -275,9 +275,9 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
        int rc = 0;
        struct ecryptfs_crypt_stat *crypt_stat;
 
-       BUG_ON(!(file && file->f_dentry && file->f_dentry->d_inode));
-       crypt_stat =
-               &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
+       BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode));
+       crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
+                       ->crypt_stat;
        if (!crypt_stat
            || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
            || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
@@ -638,8 +638,8 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
        lower_inode = ecryptfs_inode_to_lower(inode);
        lower_file = ecryptfs_file_to_lower(file);
        mutex_lock(&lower_inode->i_mutex);
-       crypt_stat =
-               &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
+       crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
+                               ->crypt_stat;
        if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
                ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
                        "crypt_stat at memory location [%p]\n", crypt_stat);
index 825757a..eaa5daa 100644 (file)
@@ -50,7 +50,7 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
        struct inode *inode = NULL;
 
        ecryptfs_inode = kmem_cache_alloc(ecryptfs_inode_info_cache,
-                                         SLAB_KERNEL);
+                                         GFP_KERNEL);
        if (unlikely(!ecryptfs_inode))
                goto out;
        ecryptfs_init_crypt_stat(&ecryptfs_inode->crypt_stat);
index 17f5b2d..b46c488 100644 (file)
@@ -20,7 +20,7 @@ struct inode_operations efs_dir_inode_operations = {
 };
 
 static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct buffer_head *bh;
 
        struct efs_dir          *dirblock;
index b3f5065..dfebf21 100644 (file)
@@ -52,12 +52,12 @@ static struct pt_types sgi_pt_types[] = {
 };
 
 
-static kmem_cache_t * efs_inode_cachep;
+static struct kmem_cache * efs_inode_cachep;
 
 static struct inode *efs_alloc_inode(struct super_block *sb)
 {
        struct efs_inode_info *ei;
-       ei = (struct efs_inode_info *)kmem_cache_alloc(efs_inode_cachep, SLAB_KERNEL);
+       ei = (struct efs_inode_info *)kmem_cache_alloc(efs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -68,7 +68,7 @@ static void efs_destroy_inode(struct inode *inode)
        kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct efs_inode_info *ei = (struct efs_inode_info *) foo;
 
index ae228ec..3ae644e 100644 (file)
@@ -283,10 +283,10 @@ static struct mutex epmutex;
 static struct poll_safewake psw;
 
 /* Slab cache used to allocate "struct epitem" */
-static kmem_cache_t *epi_cache __read_mostly;
+static struct kmem_cache *epi_cache __read_mostly;
 
 /* Slab cache used to allocate "struct eppoll_entry" */
-static kmem_cache_t *pwq_cache __read_mostly;
+static struct kmem_cache *pwq_cache __read_mostly;
 
 /* Virtual fs used to allocate inodes for eventpoll files */
 static struct vfsmount *eventpoll_mnt __read_mostly;
@@ -795,8 +795,8 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
                goto eexit_4;
        dentry->d_op = &eventpollfs_dentry_operations;
        d_add(dentry, inode);
-       file->f_vfsmnt = mntget(eventpoll_mnt);
-       file->f_dentry = dentry;
+       file->f_path.mnt = mntget(eventpoll_mnt);
+       file->f_path.dentry = dentry;
        file->f_mapping = inode->i_mapping;
 
        file->f_pos = 0;
@@ -961,7 +961,7 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
        struct epitem *epi = ep_item_from_epqueue(pt);
        struct eppoll_entry *pwq;
 
-       if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, SLAB_KERNEL))) {
+       if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
                init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
                pwq->whead = whead;
                pwq->base = epi;
@@ -1004,7 +1004,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
        struct ep_pqueue epq;
 
        error = -ENOMEM;
-       if (!(epi = kmem_cache_alloc(epi_cache, SLAB_KERNEL)))
+       if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
                goto eexit_1;
 
        /* Item initialization follow here ... */
index d993ea1..11fe93f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -38,6 +38,7 @@
 #include <linux/binfmts.h>
 #include <linux/swap.h>
 #include <linux/utsname.h>
+#include <linux/pid_namespace.h>
 #include <linux/module.h>
 #include <linux/namei.h>
 #include <linux/proc_fs.h>
@@ -404,7 +405,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
                bprm->loader += stack_base;
        bprm->exec += stack_base;
 
-       mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!mpnt)
                return -ENOMEM;
 
@@ -620,8 +621,8 @@ 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(tsk->group_leader == child_reaper))
-               child_reaper = tsk;
+       if (unlikely(tsk->group_leader == child_reaper(tsk)))
+               tsk->nsproxy->pid_ns->child_reaper = tsk;
 
        zap_other_threads(tsk);
        read_unlock(&tasklist_lock);
@@ -782,7 +783,7 @@ static void flush_old_files(struct files_struct * files)
                j++;
                i = j * __NFDBITS;
                fdt = files_fdtable(files);
-               if (i >= fdt->max_fds || i >= fdt->max_fdset)
+               if (i >= fdt->max_fds)
                        break;
                set = fdt->close_on_exec->fds_bits[j];
                if (!set)
@@ -912,7 +913,7 @@ EXPORT_SYMBOL(flush_old_exec);
 int prepare_binprm(struct linux_binprm *bprm)
 {
        int mode;
-       struct inode * inode = bprm->file->f_dentry->d_inode;
+       struct inode * inode = bprm->file->f_path.dentry->d_inode;
        int retval;
 
        mode = inode->i_mode;
@@ -922,7 +923,7 @@ int prepare_binprm(struct linux_binprm *bprm)
        bprm->e_uid = current->euid;
        bprm->e_gid = current->egid;
 
-       if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
+       if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
                /* Set-uid? */
                if (mode & S_ISUID) {
                        current->personality &= ~PER_CLEAR_ON_SETID;
@@ -1515,13 +1516,14 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                ispipe = 1;
        } else
                file = filp_open(corename,
-                                O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
+                                O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
+                                0600);
        if (IS_ERR(file))
                goto fail_unlock;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        if (inode->i_nlink > 1)
                goto close_fail;        /* multiple links - don't dump */
-       if (!ispipe && d_unhashed(file->f_dentry))
+       if (!ispipe && d_unhashed(file->f_path.dentry))
                goto close_fail;
 
        /* AK: actually i see no reason to not allow this for named pipes etc.,
@@ -1532,7 +1534,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                goto close_fail;
        if (!file->f_op->write)
                goto close_fail;
-       if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
+       if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
                goto close_fail;
 
        retval = binfmt->core_dump(signr, regs, file);
index 3e7a84a..0b02ba9 100644 (file)
@@ -248,7 +248,7 @@ static int
 ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 {
        loff_t pos = filp->f_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        unsigned int offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
index 1dfba77..4b099d3 100644 (file)
@@ -44,6 +44,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                if (!S_ISDIR(inode->i_mode))
                        flags &= ~EXT2_DIRSYNC_FL;
 
+               mutex_lock(&inode->i_mutex);
                oldflags = ei->i_flags;
 
                /*
@@ -53,13 +54,16 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                 * This test looks nicer. Thanks to Pauline Middelink
                 */
                if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
-                       if (!capable(CAP_LINUX_IMMUTABLE))
+                       if (!capable(CAP_LINUX_IMMUTABLE)) {
+                               mutex_unlock(&inode->i_mutex);
                                return -EPERM;
+                       }
                }
 
                flags = flags & EXT2_FL_USER_MODIFIABLE;
                flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
                ei->i_flags = flags;
+               mutex_unlock(&inode->i_mutex);
 
                ext2_set_inode_flags(inode);
                inode->i_ctime = CURRENT_TIME_SEC;
@@ -86,7 +90,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 #ifdef CONFIG_COMPAT
 long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int ret;
 
        /* These are just misnamed, they actually get/put from/to user an int */
index d8b9abd..6347c2d 100644 (file)
@@ -135,12 +135,12 @@ static void ext2_put_super (struct super_block * sb)
        return;
 }
 
-static kmem_cache_t * ext2_inode_cachep;
+static struct kmem_cache * ext2_inode_cachep;
 
 static struct inode *ext2_alloc_inode(struct super_block *sb)
 {
        struct ext2_inode_info *ei;
-       ei = (struct ext2_inode_info *)kmem_cache_alloc(ext2_inode_cachep, SLAB_KERNEL);
+       ei = (struct ext2_inode_info *)kmem_cache_alloc(ext2_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
@@ -156,7 +156,7 @@ static void ext2_destroy_inode(struct inode *inode)
        kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
 
@@ -597,8 +597,6 @@ static int ext2_check_descriptors (struct super_block * sb)
        return 1;
 }
 
-#define log2(n) ffz(~(n))
 /*
  * Maximal file size.  There is a direct, and {,double-,triple-}indirect
  * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -834,9 +832,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_sbh = bh;
        sbi->s_mount_state = le16_to_cpu(es->s_state);
        sbi->s_addr_per_block_bits =
-               log2 (EXT2_ADDR_PER_BLOCK(sb));
+               ilog2 (EXT2_ADDR_PER_BLOCK(sb));
        sbi->s_desc_per_block_bits =
-               log2 (EXT2_DESC_PER_BLOCK(sb));
+               ilog2 (EXT2_DESC_PER_BLOCK(sb));
 
        if (sb->s_magic != EXT2_SUPER_MAGIC)
                goto cantfind_ext2;
@@ -1090,8 +1088,10 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
 {
        struct super_block *sb = dentry->d_sb;
        struct ext2_sb_info *sbi = EXT2_SB(sb);
+       struct ext2_super_block *es = sbi->s_es;
        unsigned long overhead;
        int i;
+       u64 fsid;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -1104,7 +1104,7 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
                 * All of the blocks before first_data_block are
                 * overhead
                 */
-               overhead = le32_to_cpu(sbi->s_es->s_first_data_block);
+               overhead = le32_to_cpu(es->s_first_data_block);
 
                /*
                 * Add the overhead attributed to the superblock and
@@ -1125,14 +1125,18 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
 
        buf->f_type = EXT2_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
-       buf->f_blocks = le32_to_cpu(sbi->s_es->s_blocks_count) - overhead;
+       buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
        buf->f_bfree = ext2_count_free_blocks(sb);
-       buf->f_bavail = buf->f_bfree - le32_to_cpu(sbi->s_es->s_r_blocks_count);
-       if (buf->f_bfree < le32_to_cpu(sbi->s_es->s_r_blocks_count))
+       buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
+       if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
                buf->f_bavail = 0;
-       buf->f_files = le32_to_cpu(sbi->s_es->s_inodes_count);
-       buf->f_ffree = ext2_count_free_inodes (sb);
+       buf->f_files = le32_to_cpu(es->s_inodes_count);
+       buf->f_ffree = ext2_count_free_inodes(sb);
        buf->f_namelen = EXT2_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
+       buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
+       buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
        return 0;
 }
 
index af52a7f..247efd0 100644 (file)
@@ -342,12 +342,9 @@ static void ext2_xattr_update_super_block(struct super_block *sb)
        if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
                return;
 
-       lock_super(sb);
-       EXT2_SB(sb)->s_es->s_feature_compat |=
-               cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
+       EXT2_SET_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR);
        sb->s_dirt = 1;
        mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
-       unlock_super(sb);
 }
 
 /*
index 704cd44..e77766a 100644 (file)
@@ -5,7 +5,7 @@
 obj-$(CONFIG_EXT3_FS) += ext3.o
 
 ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-          ioctl.o namei.o super.o symlink.o hash.o resize.o
+          ioctl.o namei.o super.o symlink.o hash.o resize.o ext3_jbd.o
 
 ext3-$(CONFIG_EXT3_FS_XATTR)    += xattr.o xattr_user.o xattr_trusted.o
 ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
index b41a7d7..2216174 100644 (file)
@@ -144,7 +144,7 @@ restart:
 
        printk("Block Allocation Reservation Windows Map (%s):\n", fn);
        while (n) {
-               rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node);
+               rsv = rb_entry(n, struct ext3_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
                               "start:  %lu, end:  %lu\n",
@@ -730,7 +730,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
                here = 0;
 
        p = ((char *)bh->b_data) + (here >> 3);
-       r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+       r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
        next = (r - ((char *)bh->b_data)) << 3;
 
        if (next < maxblocks && next >= start && ext3_test_allocatable(next, bh))
@@ -949,7 +949,7 @@ static int find_next_reservable_window(
 
                prev = rsv;
                next = rb_next(&rsv->rsv_node);
-               rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node);
+               rsv = rb_entry(next,struct ext3_reserve_window_node,rsv_node);
 
                /*
                 * Reached the last reservation, we can just append to the
@@ -1148,7 +1148,7 @@ retry:
         * check if the first free block is within the
         * free space we just reserved
         */
-       if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+       if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
                return 0;               /* success */
        /*
         * if the first free bit we found is out of the reservable space
@@ -1193,7 +1193,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
        if (!next)
                my_rsv->rsv_end += size;
        else {
-               next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node);
+               next_rsv = rb_entry(next, struct ext3_reserve_window_node, rsv_node);
 
                if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
                        my_rsv->rsv_end += size;
@@ -1271,7 +1271,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
        }
        /*
         * grp_goal is a group relative block number (if there is a goal)
-        * 0 < grp_goal < EXT3_BLOCKS_PER_GROUP(sb)
+        * 0 <= grp_goal < EXT3_BLOCKS_PER_GROUP(sb)
         * first block is a filesystem wide block number
         * first block is the block number of the first block in this group
         */
@@ -1307,10 +1307,14 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        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)
-                       try_to_extend_reservation(my_rsv, sb,
-                                       *count-my_rsv->rsv_end + grp_goal - 1);
+               } else if (grp_goal >= 0) {
+                       int curr = my_rsv->rsv_end -
+                                       (grp_goal + group_first_block) + 1;
+
+                       if (curr < *count)
+                               try_to_extend_reservation(my_rsv, sb,
+                                                       *count - curr);
+               }
 
                if ((my_rsv->rsv_start > group_last_block) ||
                                (my_rsv->rsv_end < group_first_block)) {
@@ -1511,10 +1515,8 @@ retry_alloc:
                if (group_no >= ngroups)
                        group_no = 0;
                gdp = ext3_get_group_desc(sb, group_no, &gdp_bh);
-               if (!gdp) {
-                       *errp = -EIO;
-                       goto out;
-               }
+               if (!gdp)
+                       goto io_error;
                free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
                /*
                 * skip this group if the number of
@@ -1548,6 +1550,7 @@ retry_alloc:
         */
        if (my_rsv) {
                my_rsv = NULL;
+               windowsz = 0;
                group_no = goal_group;
                goto retry_alloc;
        }
index d0b54f3..665adee 100644 (file)
@@ -103,7 +103,7 @@ static int ext3_readdir(struct file * filp,
        struct ext3_dir_entry_2 *de;
        struct super_block *sb;
        int err;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int ret = 0;
 
        sb = inode->i_sb;
@@ -122,7 +122,7 @@ static int ext3_readdir(struct file * filp,
                 * We don't set the inode dirty flag since it's not
                 * critical that it get flushed back to the disk.
                 */
-               EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
+               EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
        }
 #endif
        stored = 0;
@@ -154,6 +154,9 @@ static int ext3_readdir(struct file * filp,
                        ext3_error (sb, "ext3_readdir",
                                "directory #%lu contains a hole at offset %lu",
                                inode->i_ino, (unsigned long)filp->f_pos);
+                       /* corrupt size?  Maybe no more blocks to read */
+                       if (filp->f_pos > inode->i_blocks << 9)
+                               break;
                        filp->f_pos += sb->s_blocksize - offset;
                        continue;
                }
@@ -399,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
 {
        struct dir_private_info *info = filp->private_data;
        loff_t  curr_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block * sb;
        int error;
 
@@ -429,7 +432,7 @@ static int ext3_dx_readdir(struct file * filp,
                         void * dirent, filldir_t filldir)
 {
        struct dir_private_info *info = filp->private_data;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct fname *fname;
        int     ret;
 
diff --git a/fs/ext3/ext3_jbd.c b/fs/ext3/ext3_jbd.c
new file mode 100644 (file)
index 0000000..e1f91fd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Interface between ext3 and JBD
+ */
+
+#include <linux/ext3_jbd.h>
+
+int __ext3_journal_get_undo_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = journal_get_undo_access(handle, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext3_journal_get_write_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = journal_get_write_access(handle, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext3_journal_forget(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = journal_forget(handle, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext3_journal_revoke(const char *where, handle_t *handle,
+                               unsigned long blocknr, struct buffer_head *bh)
+{
+       int err = journal_revoke(handle, blocknr, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext3_journal_get_create_access(const char *where,
+                               handle_t *handle, struct buffer_head *bh)
+{
+       int err = journal_get_create_access(handle, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext3_journal_dirty_metadata(const char *where,
+                               handle_t *handle, struct buffer_head *bh)
+{
+       int err = journal_dirty_metadata(handle, bh);
+       if (err)
+               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
index e96c388..881f636 100644 (file)
@@ -52,7 +52,7 @@ ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
                unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t ret;
        int err;
 
index 03ba5bc..beaf25f 100644 (file)
@@ -1148,37 +1148,102 @@ static int do_journal_get_write_access(handle_t *handle,
        return ext3_journal_get_write_access(handle, bh);
 }
 
+/*
+ * The idea of this helper function is following:
+ * if prepare_write has allocated some blocks, but not all of them, the
+ * transaction must include the content of the newly allocated blocks.
+ * This content is expected to be set to zeroes by block_prepare_write().
+ * 2006/10/14  SAW
+ */
+static int ext3_prepare_failure(struct file *file, struct page *page,
+                               unsigned from, unsigned to)
+{
+       struct address_space *mapping;
+       struct buffer_head *bh, *head, *next;
+       unsigned block_start, block_end;
+       unsigned blocksize;
+       int ret;
+       handle_t *handle = ext3_journal_current_handle();
+
+       mapping = page->mapping;
+       if (ext3_should_writeback_data(mapping->host)) {
+               /* optimization: no constraints about data */
+skip:
+               return ext3_journal_stop(handle);
+       }
+
+       head = page_buffers(page);
+       blocksize = head->b_size;
+       for (   bh = head, block_start = 0;
+               bh != head || !block_start;
+               block_start = block_end, bh = next)
+       {
+               next = bh->b_this_page;
+               block_end = block_start + blocksize;
+               if (block_end <= from)
+                       continue;
+               if (block_start >= to) {
+                       block_start = to;
+                       break;
+               }
+               if (!buffer_mapped(bh))
+               /* prepare_write failed on this bh */
+                       break;
+               if (ext3_should_journal_data(mapping->host)) {
+                       ret = do_journal_get_write_access(handle, bh);
+                       if (ret) {
+                               ext3_journal_stop(handle);
+                               return ret;
+                       }
+               }
+       /*
+        * block_start here becomes the first block where the current iteration
+        * of prepare_write failed.
+        */
+       }
+       if (block_start <= from)
+               goto skip;
+
+       /* commit allocated and zeroed buffers */
+       return mapping->a_ops->commit_write(file, page, from, block_start);
+}
+
 static int ext3_prepare_write(struct file *file, struct page *page,
                              unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
-       int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
+       int ret, ret2;
+       int needed_blocks = ext3_writepage_trans_blocks(inode);
        handle_t *handle;
        int retries = 0;
 
 retry:
        handle = ext3_journal_start(inode, needed_blocks);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               goto out;
-       }
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
        if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
                ret = nobh_prepare_write(page, from, to, ext3_get_block);
        else
                ret = block_prepare_write(page, from, to, ext3_get_block);
        if (ret)
-               goto prepare_write_failed;
+               goto failure;
 
        if (ext3_should_journal_data(inode)) {
                ret = walk_page_buffers(handle, page_buffers(page),
                                from, to, NULL, do_journal_get_write_access);
+               if (ret)
+                       /* fatal error, just put the handle and return */
+                       journal_stop(handle);
        }
-prepare_write_failed:
-       if (ret)
-               ext3_journal_stop(handle);
+       return ret;
+
+failure:
+       ret2 = ext3_prepare_failure(file, page, from, to);
+       if (ret2 < 0)
+               return ret2;
        if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
-out:
+       /* retry number exceeded, or other error like -EDQUOT */
        return ret;
 }
 
index 12daa68..9b8090d 100644 (file)
@@ -257,7 +257,7 @@ flags_err:
 #ifdef CONFIG_COMPAT
 long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int ret;
 
        /* These are just misnamed, they actually get/put from/to user an int */
index 906731a..4df39c4 100644 (file)
@@ -552,6 +552,15 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                                           dir->i_sb->s_blocksize -
                                           EXT3_DIR_REC_LEN(0));
        for (; de < top; de = ext3_next_entry(de)) {
+               if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
+                                       (block<<EXT3_BLOCK_SIZE_BITS(dir->i_sb))
+                                               +((char *)de - bh->b_data))) {
+                       /* On error, skip the f_pos to the next block. */
+                       dir_file->f_pos = (dir_file->f_pos |
+                                       (dir->i_sb->s_blocksize - 1)) + 1;
+                       brelse (bh);
+                       return count;
+               }
                ext3fs_dirhash(de->name, de->name_len, hinfo);
                if ((hinfo->hash < start_hash) ||
                    ((hinfo->hash == start_hash) &&
@@ -593,7 +602,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 
        dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
                       start_minor_hash));
-       dir = dir_file->f_dentry->d_inode;
+       dir = dir_file->f_path.dentry->d_inode;
        if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
                hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
                hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
@@ -604,7 +613,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
        }
        hinfo.hash = start_hash;
        hinfo.minor_hash = 0;
-       frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+       frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
        if (!frame)
                return err;
 
index afc2d4f..b348867 100644 (file)
@@ -436,7 +436,7 @@ static void ext3_put_super (struct super_block * sb)
        return;
 }
 
-static kmem_cache_t *ext3_inode_cachep;
+static struct kmem_cache *ext3_inode_cachep;
 
 /*
  * Called inside transaction, so use GFP_NOFS
@@ -445,7 +445,7 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
 {
        struct ext3_inode_info *ei;
 
-       ei = kmem_cache_alloc(ext3_inode_cachep, SLAB_NOFS);
+       ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
@@ -462,7 +462,7 @@ static void ext3_destroy_inode(struct inode *inode)
        kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
 
@@ -1264,6 +1264,12 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                return;
        }
 
+       if (bdev_read_only(sb->s_bdev)) {
+               printk(KERN_ERR "EXT3-fs: write access "
+                       "unavailable, skipping orphan cleanup.\n");
+               return;
+       }
+
        if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
                if (es->s_last_orphan)
                        jbd_debug(1, "Errors on filesystem, "
@@ -1341,8 +1347,6 @@ static void ext3_orphan_cleanup (struct super_block * sb,
        sb->s_flags = s_flags; /* Restore MS_RDONLY status */
 }
 
-#define log2(n) ffz(~(n))
-
 /*
  * Maximal file size.  There is a direct, and {,double-,triple-}indirect
  * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -1591,8 +1595,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
        sbi->s_sbh = bh;
        sbi->s_mount_state = le16_to_cpu(es->s_state);
-       sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
-       sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
+       sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb));
+       sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb));
        for (i=0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
@@ -2387,6 +2391,7 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
        struct ext3_super_block *es = sbi->s_es;
        ext3_fsblk_t overhead;
        int i;
+       u64 fsid;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -2433,6 +2438,10 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
        buf->f_namelen = EXT3_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
+       buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
+       buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
        return 0;
 }
 
index f86f248..99857a4 100644 (file)
@@ -459,14 +459,11 @@ static void ext3_xattr_update_super_block(handle_t *handle,
        if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
                return;
 
-       lock_super(sb);
        if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) {
-               EXT3_SB(sb)->s_es->s_feature_compat |=
-                       cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
+               EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR);
                sb->s_dirt = 1;
                ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
        }
-       unlock_super(sb);
 }
 
 /*
index a6acb96..ae6e7e5 100644 (file)
@@ -5,7 +5,8 @@
 obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o
 
 ext4dev-y      := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-          ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o
+                  ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+                  ext4_jbd2.o
 
 ext4dev-$(CONFIG_EXT4DEV_FS_XATTR)     += xattr.o xattr_user.o xattr_trusted.o
 ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o
index 5d45582..c4dd110 100644 (file)
@@ -165,7 +165,7 @@ restart:
 
        printk("Block Allocation Reservation Windows Map (%s):\n", fn);
        while (n) {
-               rsv = list_entry(n, struct ext4_reserve_window_node, rsv_node);
+               rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
                               "start:  %llu, end:  %llu\n",
@@ -747,7 +747,7 @@ find_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
                here = 0;
 
        p = ((char *)bh->b_data) + (here >> 3);
-       r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+       r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
        next = (r - ((char *)bh->b_data)) << 3;
 
        if (next < maxblocks && next >= start && ext4_test_allocatable(next, bh))
@@ -966,7 +966,7 @@ static int find_next_reservable_window(
 
                prev = rsv;
                next = rb_next(&rsv->rsv_node);
-               rsv = list_entry(next,struct ext4_reserve_window_node,rsv_node);
+               rsv = rb_entry(next,struct ext4_reserve_window_node,rsv_node);
 
                /*
                 * Reached the last reservation, we can just append to the
@@ -1165,7 +1165,7 @@ retry:
         * check if the first free block is within the
         * free space we just reserved
         */
-       if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+       if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
                return 0;               /* success */
        /*
         * if the first free bit we found is out of the reservable space
@@ -1210,7 +1210,7 @@ static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv,
        if (!next)
                my_rsv->rsv_end += size;
        else {
-               next_rsv = list_entry(next, struct ext4_reserve_window_node, rsv_node);
+               next_rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
 
                if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
                        my_rsv->rsv_end += size;
@@ -1288,7 +1288,7 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
        }
        /*
         * grp_goal is a group relative block number (if there is a goal)
-        * 0 < grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
+        * 0 <= grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
         * first block is a filesystem wide block number
         * first block is the block number of the first block in this group
         */
@@ -1324,10 +1324,14 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        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)
-                       try_to_extend_reservation(my_rsv, sb,
-                                       *count-my_rsv->rsv_end + grp_goal - 1);
+               } else if (grp_goal >= 0) {
+                       int curr = my_rsv->rsv_end -
+                                       (grp_goal + group_first_block) + 1;
+
+                       if (curr < *count)
+                               try_to_extend_reservation(my_rsv, sb,
+                                                       *count - curr);
+               }
 
                if ((my_rsv->rsv_start > group_last_block) ||
                                (my_rsv->rsv_end < group_first_block)) {
@@ -1525,10 +1529,8 @@ retry_alloc:
                if (group_no >= ngroups)
                        group_no = 0;
                gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
-               if (!gdp) {
-                       *errp = -EIO;
-                       goto out;
-               }
+               if (!gdp)
+                       goto io_error;
                free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
                /*
                 * skip this group if the number of
@@ -1562,6 +1564,7 @@ retry_alloc:
         */
        if (my_rsv) {
                my_rsv = NULL;
+               windowsz = 0;
                group_no = goal_group;
                goto retry_alloc;
        }
index f859578..da80368 100644 (file)
@@ -103,7 +103,7 @@ static int ext4_readdir(struct file * filp,
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
        int err;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int ret = 0;
 
        sb = inode->i_sb;
@@ -122,7 +122,7 @@ static int ext4_readdir(struct file * filp,
                 * We don't set the inode dirty flag since it's not
                 * critical that it get flushed back to the disk.
                 */
-               EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+               EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
        }
 #endif
        stored = 0;
@@ -153,6 +153,9 @@ static int ext4_readdir(struct file * filp,
                        ext4_error (sb, "ext4_readdir",
                                "directory #%lu contains a hole at offset %lu",
                                inode->i_ino, (unsigned long)filp->f_pos);
+                       /* corrupt size?  Maybe no more blocks to read */
+                       if (filp->f_pos > inode->i_blocks << 9)
+                               break;
                        filp->f_pos += sb->s_blocksize - offset;
                        continue;
                }
@@ -399,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
 {
        struct dir_private_info *info = filp->private_data;
        loff_t  curr_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block * sb;
        int error;
 
@@ -429,7 +432,7 @@ static int ext4_dx_readdir(struct file * filp,
                         void * dirent, filldir_t filldir)
 {
        struct dir_private_info *info = filp->private_data;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct fname *fname;
        int     ret;
 
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
new file mode 100644 (file)
index 0000000..d6afe4e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Interface between ext4 and JBD
+ */
+
+#include <linux/ext4_jbd2.h>
+
+int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = jbd2_journal_get_undo_access(handle, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = jbd2_journal_get_write_access(handle, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext4_journal_forget(const char *where, handle_t *handle,
+                               struct buffer_head *bh)
+{
+       int err = jbd2_journal_forget(handle, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext4_journal_revoke(const char *where, handle_t *handle,
+                               ext4_fsblk_t blocknr, struct buffer_head *bh)
+{
+       int err = jbd2_journal_revoke(handle, blocknr, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext4_journal_get_create_access(const char *where,
+                               handle_t *handle, struct buffer_head *bh)
+{
+       int err = jbd2_journal_get_create_access(handle, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
+
+int __ext4_journal_dirty_metadata(const char *where,
+                               handle_t *handle, struct buffer_head *bh)
+{
+       int err = jbd2_journal_dirty_metadata(handle, bh);
+       if (err)
+               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+       return err;
+}
index 2608dce..dc2724f 100644 (file)
@@ -48,7 +48,7 @@
  * ext_pblock:
  * combine low and high parts of physical block number into ext4_fsblk_t
  */
-static inline ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
+static ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
 {
        ext4_fsblk_t block;
 
@@ -61,7 +61,7 @@ static inline ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
  * idx_pblock:
  * combine low and high parts of a leaf physical block number into ext4_fsblk_t
  */
-static inline ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
+static ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
 {
        ext4_fsblk_t block;
 
@@ -75,7 +75,7 @@ static inline ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
  * stores a large physical block number into an extent struct,
  * breaking it into parts
  */
-static inline void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
+static void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
 {
        ex->ee_start = cpu_to_le32((unsigned long) (pb & 0xffffffff));
        ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
@@ -86,7 +86,7 @@ static inline void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb
  * stores a large physical block number into an index struct,
  * breaking it into parts
  */
-static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb)
+static void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb)
 {
        ix->ei_leaf = cpu_to_le32((unsigned long) (pb & 0xffffffff));
        ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
@@ -186,7 +186,8 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
                depth = path->p_depth;
 
                /* try to predict block placement */
-               if ((ex = path[depth].p_ext))
+               ex = path[depth].p_ext;
+               if (ex)
                        return ext_pblock(ex)+(block-le32_to_cpu(ex->ee_block));
 
                /* it looks like index is empty;
@@ -215,7 +216,7 @@ ext4_ext_new_block(handle_t *handle, struct inode *inode,
        return newblock;
 }
 
-static inline int ext4_ext_space_block(struct inode *inode)
+static int ext4_ext_space_block(struct inode *inode)
 {
        int size;
 
@@ -228,7 +229,7 @@ static inline int ext4_ext_space_block(struct inode *inode)
        return size;
 }
 
-static inline int ext4_ext_space_block_idx(struct inode *inode)
+static int ext4_ext_space_block_idx(struct inode *inode)
 {
        int size;
 
@@ -241,7 +242,7 @@ static inline int ext4_ext_space_block_idx(struct inode *inode)
        return size;
 }
 
-static inline int ext4_ext_space_root(struct inode *inode)
+static int ext4_ext_space_root(struct inode *inode)
 {
        int size;
 
@@ -255,7 +256,7 @@ static inline int ext4_ext_space_root(struct inode *inode)
        return size;
 }
 
-static inline int ext4_ext_space_root_idx(struct inode *inode)
+static int ext4_ext_space_root_idx(struct inode *inode)
 {
        int size;
 
@@ -476,13 +477,12 @@ ext4_ext_find_extent(struct inode *inode, int block, struct ext4_ext_path *path)
 
        /* account possible depth increase */
        if (!path) {
-               path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+               path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
                                GFP_NOFS);
                if (!path)
                        return ERR_PTR(-ENOMEM);
                alloc = 1;
        }
-       memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
        path[0].p_hdr = eh;
 
        /* walk through the tree */
@@ -543,7 +543,8 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
        struct ext4_extent_idx *ix;
        int len, err;
 
-       if ((err = ext4_ext_get_access(handle, inode, curp)))
+       err = ext4_ext_get_access(handle, inode, curp);
+       if (err)
                return err;
 
        BUG_ON(logical == le32_to_cpu(curp->p_idx->ei_block));
@@ -641,10 +642,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
         * We need this to handle errors and free blocks
         * upon them.
         */
-       ablocks = kmalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS);
+       ablocks = kzalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS);
        if (!ablocks)
                return -ENOMEM;
-       memset(ablocks, 0, sizeof(ext4_fsblk_t) * depth);
 
        /* allocate all needed blocks */
        ext_debug("allocate %d blocks for indexes/leaf\n", depth - at);
@@ -665,7 +665,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
        }
        lock_buffer(bh);
 
-       if ((err = ext4_journal_get_create_access(handle, bh)))
+       err = ext4_journal_get_create_access(handle, bh);
+       if (err)
                goto cleanup;
 
        neh = ext_block_hdr(bh);
@@ -702,18 +703,21 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
        set_buffer_uptodate(bh);
        unlock_buffer(bh);
 
-       if ((err = ext4_journal_dirty_metadata(handle, bh)))
+       err = ext4_journal_dirty_metadata(handle, bh);
+       if (err)
                goto cleanup;
        brelse(bh);
        bh = NULL;
 
        /* correct old leaf */
        if (m) {
-               if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+               err = ext4_ext_get_access(handle, inode, path + depth);
+               if (err)
                        goto cleanup;
                path[depth].p_hdr->eh_entries =
                     cpu_to_le16(le16_to_cpu(path[depth].p_hdr->eh_entries)-m);
-               if ((err = ext4_ext_dirty(handle, inode, path + depth)))
+               err = ext4_ext_dirty(handle, inode, path + depth);
+               if (err)
                        goto cleanup;
 
        }
@@ -736,7 +740,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                }
                lock_buffer(bh);
 
-               if ((err = ext4_journal_get_create_access(handle, bh)))
+               err = ext4_journal_get_create_access(handle, bh);
+               if (err)
                        goto cleanup;
 
                neh = ext_block_hdr(bh);
@@ -780,7 +785,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
 
-               if ((err = ext4_journal_dirty_metadata(handle, bh)))
+               err = ext4_journal_dirty_metadata(handle, bh);
+               if (err)
                        goto cleanup;
                brelse(bh);
                bh = NULL;
@@ -800,9 +806,6 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
        }
 
        /* insert new index */
-       if (err)
-               goto cleanup;
-
        err = ext4_ext_insert_index(handle, inode, path + at,
                                    le32_to_cpu(border), newblock);
 
@@ -857,7 +860,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
        }
        lock_buffer(bh);
 
-       if ((err = ext4_journal_get_create_access(handle, bh))) {
+       err = ext4_journal_get_create_access(handle, bh);
+       if (err) {
                unlock_buffer(bh);
                goto out;
        }
@@ -877,11 +881,13 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
        set_buffer_uptodate(bh);
        unlock_buffer(bh);
 
-       if ((err = ext4_journal_dirty_metadata(handle, bh)))
+       err = ext4_journal_dirty_metadata(handle, bh);
+       if (err)
                goto out;
 
        /* create index in new top-level index: num,max,pointer */
-       if ((err = ext4_ext_get_access(handle, inode, curp)))
+       err = ext4_ext_get_access(handle, inode, curp);
+       if (err)
                goto out;
 
        curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
@@ -1073,27 +1079,31 @@ int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
         */
        k = depth - 1;
        border = path[depth].p_ext->ee_block;
-       if ((err = ext4_ext_get_access(handle, inode, path + k)))
+       err = ext4_ext_get_access(handle, inode, path + k);
+       if (err)
                return err;
        path[k].p_idx->ei_block = border;
-       if ((err = ext4_ext_dirty(handle, inode, path + k)))
+       err = ext4_ext_dirty(handle, inode, path + k);
+       if (err)
                return err;
 
        while (k--) {
                /* change all left-side indexes */
                if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
                        break;
-               if ((err = ext4_ext_get_access(handle, inode, path + k)))
+               err = ext4_ext_get_access(handle, inode, path + k);
+               if (err)
                        break;
                path[k].p_idx->ei_block = border;
-               if ((err = ext4_ext_dirty(handle, inode, path + k)))
+               err = ext4_ext_dirty(handle, inode, path + k);
+               if (err)
                        break;
        }
 
        return err;
 }
 
-static int inline
+static int
 ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
                                struct ext4_extent *ex2)
 {
@@ -1145,7 +1155,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
                                le16_to_cpu(newext->ee_len),
                                le32_to_cpu(ex->ee_block),
                                le16_to_cpu(ex->ee_len), ext_pblock(ex));
-               if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+               err = ext4_ext_get_access(handle, inode, path + depth);
+               if (err)
                        return err;
                ex->ee_len = cpu_to_le16(le16_to_cpu(ex->ee_len)
                                         + le16_to_cpu(newext->ee_len));
@@ -1195,7 +1206,8 @@ repeat:
 has_space:
        nearex = path[depth].p_ext;
 
-       if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+       err = ext4_ext_get_access(handle, inode, path + depth);
+       if (err)
                goto cleanup;
 
        if (!nearex) {
@@ -1383,7 +1395,7 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block,
        return err;
 }
 
-static inline void
+static void
 ext4_ext_put_in_cache(struct inode *inode, __u32 block,
                        __u32 len, __u32 start, int type)
 {
@@ -1401,7 +1413,7 @@ ext4_ext_put_in_cache(struct inode *inode, __u32 block,
  * calculate boundaries of the gap that the requested block fits into
  * and cache this gap
  */
-static inline void
+static void
 ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
                                unsigned long block)
 {
@@ -1442,7 +1454,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
        ext4_ext_put_in_cache(inode, lblock, len, 0, EXT4_EXT_CACHE_GAP);
 }
 
-static inline int
+static int
 ext4_ext_in_cache(struct inode *inode, unsigned long block,
                        struct ext4_extent *ex)
 {
@@ -1489,10 +1501,12 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
        path--;
        leaf = idx_pblock(path->p_idx);
        BUG_ON(path->p_hdr->eh_entries == 0);
-       if ((err = ext4_ext_get_access(handle, inode, path)))
+       err = ext4_ext_get_access(handle, inode, path);
+       if (err)
                return err;
        path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
-       if ((err = ext4_ext_dirty(handle, inode, path)))
+       err = ext4_ext_dirty(handle, inode, path);
+       if (err)
                return err;
        ext_debug("index is empty, remove it, free block %llu\n", leaf);
        bh = sb_find_get_block(inode->i_sb, leaf);
@@ -1509,7 +1523,7 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
  * the caller should calculate credits under truncate_mutex and
  * pass the actual path.
  */
-int inline ext4_ext_calc_credits_for_insert(struct inode *inode,
+int ext4_ext_calc_credits_for_insert(struct inode *inode,
                                                struct ext4_ext_path *path)
 {
        int depth, needed;
@@ -1534,16 +1548,17 @@ int inline ext4_ext_calc_credits_for_insert(struct inode *inode,
 
        /*
         * tree can be full, so it would need to grow in depth:
-        * allocation + old root + new root
+        * we need one credit to modify old root, credits for
+        * new root will be added in split accounting
         */
-       needed += 2 + 1 + 1;
+       needed += 1;
 
        /*
         * Index split can happen, we would need:
         *    allocate intermediate indexes (bitmap + group)
         *  + change two blocks at each level, but root (already included)
         */
-       needed = (depth * 2) + (depth * 2);
+       needed += (depth * 2) + (depth * 2);
 
        /* any allocation modifies superblock */
        needed += 1;
@@ -1718,7 +1733,7 @@ out:
  * ext4_ext_more_to_rm:
  * returns 1 if current index has to be freed (even partial)
  */
-static int inline
+static int
 ext4_ext_more_to_rm(struct ext4_ext_path *path)
 {
        BUG_ON(path->p_idx == NULL);
@@ -1756,12 +1771,11 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start)
         * We start scanning from right side, freeing all the blocks
         * after i_size and walking into the tree depth-wise.
         */
-       path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
+       path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
        if (path == NULL) {
                ext4_journal_stop(handle);
                return -ENOMEM;
        }
-       memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
        path[0].p_hdr = ext_inode_hdr(inode);
        if (ext4_ext_check_header(__FUNCTION__, inode, path[0].p_hdr)) {
                err = -EIO;
@@ -1932,7 +1946,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
        mutex_lock(&EXT4_I(inode)->truncate_mutex);
 
        /* check in cache */
-       if ((goal = ext4_ext_in_cache(inode, iblock, &newex))) {
+       goal = ext4_ext_in_cache(inode, iblock, &newex);
+       if (goal) {
                if (goal == EXT4_EXT_CACHE_GAP) {
                        if (!create) {
                                /* block isn't allocated yet and
@@ -1971,7 +1986,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
         */
        BUG_ON(path[depth].p_ext == NULL && depth != 0);
 
-       if ((ex = path[depth].p_ext)) {
+       ex = path[depth].p_ext;
+       if (ex) {
                unsigned long ee_block = le32_to_cpu(ex->ee_block);
                ext4_fsblk_t ee_start = ext_pblock(ex);
                unsigned short ee_len  = le16_to_cpu(ex->ee_len);
index 0b622c0..3bbc24b 100644 (file)
@@ -52,7 +52,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
                unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t ret;
        int err;
 
index 0a60ec5..a127cc0 100644 (file)
@@ -1147,37 +1147,102 @@ static int do_journal_get_write_access(handle_t *handle,
        return ext4_journal_get_write_access(handle, bh);
 }
 
+/*
+ * The idea of this helper function is following:
+ * if prepare_write has allocated some blocks, but not all of them, the
+ * transaction must include the content of the newly allocated blocks.
+ * This content is expected to be set to zeroes by block_prepare_write().
+ * 2006/10/14  SAW
+ */
+static int ext4_prepare_failure(struct file *file, struct page *page,
+                               unsigned from, unsigned to)
+{
+       struct address_space *mapping;
+       struct buffer_head *bh, *head, *next;
+       unsigned block_start, block_end;
+       unsigned blocksize;
+       int ret;
+       handle_t *handle = ext4_journal_current_handle();
+
+       mapping = page->mapping;
+       if (ext4_should_writeback_data(mapping->host)) {
+               /* optimization: no constraints about data */
+skip:
+               return ext4_journal_stop(handle);
+       }
+
+       head = page_buffers(page);
+       blocksize = head->b_size;
+       for (   bh = head, block_start = 0;
+               bh != head || !block_start;
+               block_start = block_end, bh = next)
+       {
+               next = bh->b_this_page;
+               block_end = block_start + blocksize;
+               if (block_end <= from)
+                       continue;
+               if (block_start >= to) {
+                       block_start = to;
+                       break;
+               }
+               if (!buffer_mapped(bh))
+               /* prepare_write failed on this bh */
+                       break;
+               if (ext4_should_journal_data(mapping->host)) {
+                       ret = do_journal_get_write_access(handle, bh);
+                       if (ret) {
+                               ext4_journal_stop(handle);
+                               return ret;
+                       }
+               }
+       /*
+        * block_start here becomes the first block where the current iteration
+        * of prepare_write failed.
+        */
+       }
+       if (block_start <= from)
+               goto skip;
+
+       /* commit allocated and zeroed buffers */
+       return mapping->a_ops->commit_write(file, page, from, block_start);
+}
+
 static int ext4_prepare_write(struct file *file, struct page *page,
                              unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
-       int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
+       int ret, ret2;
+       int needed_blocks = ext4_writepage_trans_blocks(inode);
        handle_t *handle;
        int retries = 0;
 
 retry:
        handle = ext4_journal_start(inode, needed_blocks);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               goto out;
-       }
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
        if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
                ret = nobh_prepare_write(page, from, to, ext4_get_block);
        else
                ret = block_prepare_write(page, from, to, ext4_get_block);
        if (ret)
-               goto prepare_write_failed;
+               goto failure;
 
        if (ext4_should_journal_data(inode)) {
                ret = walk_page_buffers(handle, page_buffers(page),
                                from, to, NULL, do_journal_get_write_access);
+               if (ret)
+                       /* fatal error, just put the handle and return */
+                       ext4_journal_stop(handle);
        }
-prepare_write_failed:
-       if (ret)
-               ext4_journal_stop(handle);
+       return ret;
+
+failure:
+       ret2 = ext4_prepare_failure(file, page, from, to);
+       if (ret2 < 0)
+               return ret2;
        if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
-out:
+       /* retry number exceeded, or other error like -EDQUOT */
        return ret;
 }
 
index 22a737c..500567d 100644 (file)
@@ -256,7 +256,7 @@ flags_err:
 #ifdef CONFIG_COMPAT
 long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int ret;
 
        /* These are just misnamed, they actually get/put from/to user an int */
index 8b1bd03..e5a74a5 100644 (file)
@@ -552,6 +552,15 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                                           dir->i_sb->s_blocksize -
                                           EXT4_DIR_REC_LEN(0));
        for (; de < top; de = ext4_next_entry(de)) {
+               if (!ext4_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
+                                       (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
+                                               +((char *)de - bh->b_data))) {
+                       /* On error, skip the f_pos to the next block. */
+                       dir_file->f_pos = (dir_file->f_pos |
+                                       (dir->i_sb->s_blocksize - 1)) + 1;
+                       brelse (bh);
+                       return count;
+               }
                ext4fs_dirhash(de->name, de->name_len, hinfo);
                if ((hinfo->hash < start_hash) ||
                    ((hinfo->hash == start_hash) &&
@@ -593,7 +602,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 
        dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
                       start_minor_hash));
-       dir = dir_file->f_dentry->d_inode;
+       dir = dir_file->f_path.dentry->d_inode;
        if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
                hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
                hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
@@ -604,7 +613,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
        }
        hinfo.hash = start_hash;
        hinfo.minor_hash = 0;
-       frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+       frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
        if (!frame)
                return err;
 
index b4b022a..486a641 100644 (file)
@@ -486,7 +486,7 @@ static void ext4_put_super (struct super_block * sb)
        return;
 }
 
-static kmem_cache_t *ext4_inode_cachep;
+static struct kmem_cache *ext4_inode_cachep;
 
 /*
  * Called inside transaction, so use GFP_NOFS
@@ -495,7 +495,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 {
        struct ext4_inode_info *ei;
 
-       ei = kmem_cache_alloc(ext4_inode_cachep, SLAB_NOFS);
+       ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
 #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
@@ -513,7 +513,7 @@ static void ext4_destroy_inode(struct inode *inode)
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
@@ -1321,6 +1321,12 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                return;
        }
 
+       if (bdev_read_only(sb->s_bdev)) {
+               printk(KERN_ERR "EXT4-fs: write access "
+                       "unavailable, skipping orphan cleanup.\n");
+               return;
+       }
+
        if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
                if (es->s_last_orphan)
                        jbd_debug(1, "Errors on filesystem, "
@@ -2460,6 +2466,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
        struct ext4_super_block *es = sbi->s_es;
        ext4_fsblk_t overhead;
        int i;
+       u64 fsid;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -2506,6 +2513,10 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
        buf->f_namelen = EXT4_NAME_LEN;
+       fsid = le64_to_cpup((void *)es->s_uuid) ^
+              le64_to_cpup((void *)es->s_uuid + sizeof(u64));
+       buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
+       buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
        return 0;
 }
 
index 63233cd..dc969c3 100644 (file)
@@ -459,14 +459,11 @@ static void ext4_xattr_update_super_block(handle_t *handle,
        if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR))
                return;
 
-       lock_super(sb);
        if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
-               EXT4_SB(sb)->s_es->s_feature_compat |=
-                       cpu_to_le32(EXT4_FEATURE_COMPAT_EXT_ATTR);
+               EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR);
                sb->s_dirt = 1;
                ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
        }
-       unlock_super(sb);
 }
 
 /*
index 82cc4f5..05c2941 100644 (file)
@@ -34,9 +34,9 @@ static inline int fat_max_cache(struct inode *inode)
        return FAT_MAX_CACHE;
 }
 
-static kmem_cache_t *fat_cache_cachep;
+static struct kmem_cache *fat_cache_cachep;
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct fat_cache *cache = (struct fat_cache *)foo;
 
@@ -63,7 +63,7 @@ void fat_cache_destroy(void)
 
 static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
 {
-       return kmem_cache_alloc(fat_cache_cachep, SLAB_KERNEL);
+       return kmem_cache_alloc(fat_cache_cachep, GFP_KERNEL);
 }
 
 static inline void fat_cache_free(struct fat_cache *cache)
index 69c439f..c16af24 100644 (file)
@@ -579,7 +579,7 @@ parse_record:
        if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
                inum = inode->i_ino;
        else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
-               inum = parent_ino(filp->f_dentry);
+               inum = parent_ino(filp->f_path.dentry);
        } else {
                loff_t i_pos = fat_make_i_pos(sb, bh, de);
                struct inode *tmp = fat_iget(sb, i_pos);
@@ -643,7 +643,7 @@ out:
 
 static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
 }
 
@@ -782,7 +782,7 @@ static long fat_compat_dir_ioctl(struct file *file, unsigned cmd,
 
        set_fs(KERNEL_DS);
        lock_kernel();
-       ret = fat_dir_ioctl(file->f_dentry->d_inode, file,
+       ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file,
                            cmd, (unsigned long) &d);
        unlock_kernel();
        set_fs(oldfs);
index 0aa813d..c1237b7 100644 (file)
@@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
                }
 
                /* This MUST be done before doing anything irreversible... */
-               err = notify_change(filp->f_dentry, &ia);
+               err = notify_change(filp->f_path.dentry, &ia);
                if (err)
                        goto up;
 
index 78945b5..a9e4688 100644 (file)
@@ -477,12 +477,12 @@ static void fat_put_super(struct super_block *sb)
        kfree(sbi);
 }
 
-static kmem_cache_t *fat_inode_cachep;
+static struct kmem_cache *fat_inode_cachep;
 
 static struct inode *fat_alloc_inode(struct super_block *sb)
 {
        struct msdos_inode_info *ei;
-       ei = kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(fat_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -493,7 +493,7 @@ static void fat_destroy_inode(struct inode *inode)
        kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;
 
index e4f2616..8e382a5 100644 (file)
@@ -77,10 +77,9 @@ repeat:
                start = files->next_fd;
 
        newfd = start;
-       if (start < fdt->max_fdset) {
+       if (start < fdt->max_fds)
                newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
-                       fdt->max_fdset, start);
-       }
+                                          fdt->max_fds, start);
        
        error = -EMFILE;
        if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
@@ -204,7 +203,7 @@ asmlinkage long sys_dup(unsigned int fildes)
 
 static int setfl(int fd, struct file * filp, unsigned long arg)
 {
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        int error = 0;
 
        /*
@@ -553,7 +552,7 @@ int send_sigurg(struct fown_struct *fown)
 }
 
 static DEFINE_RWLOCK(fasync_lock);
-static kmem_cache_t *fasync_cache __read_mostly;
+static struct kmem_cache *fasync_cache __read_mostly;
 
 /*
  * fasync_helper() is used by some character device drivers (mainly mice)
@@ -567,7 +566,7 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap
        int result = 0;
 
        if (on) {
-               new = kmem_cache_alloc(fasync_cache, SLAB_KERNEL);
+               new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
                if (!new)
                        return -ENOMEM;
        }
index 8e81775..857fa49 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -21,7 +21,6 @@
 struct fdtable_defer {
        spinlock_t lock;
        struct work_struct wq;
-       struct timer_list timer;
        struct fdtable *next;
 };
 
@@ -33,66 +32,34 @@ struct fdtable_defer {
  */
 static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
-
-/*
- * Allocate an fd array, using kmalloc or vmalloc.
- * Note: the array isn't cleared at allocation time.
- */
-struct file ** alloc_fd_array(int num)
+static inline void * alloc_fdmem(unsigned int size)
 {
-       struct file **new_fds;
-       int size = num * sizeof(struct file *);
-
        if (size <= PAGE_SIZE)
-               new_fds = (struct file **) kmalloc(size, GFP_KERNEL);
-       else 
-               new_fds = (struct file **) vmalloc(size);
-       return new_fds;
-}
-
-void free_fd_array(struct file **array, int num)
-{
-       int size = num * sizeof(struct file *);
-
-       if (!array) {
-               printk (KERN_ERR "free_fd_array: array = 0 (num = %d)\n", num);
-               return;
-       }
-
-       if (num <= NR_OPEN_DEFAULT) /* Don't free the embedded fd array! */
-               return;
-       else if (size <= PAGE_SIZE)
-               kfree(array);
+               return kmalloc(size, GFP_KERNEL);
        else
-               vfree(array);
+               return vmalloc(size);
 }
 
-static void __free_fdtable(struct fdtable *fdt)
+static inline void free_fdarr(struct fdtable *fdt)
 {
-       free_fdset(fdt->open_fds, fdt->max_fdset);
-       free_fdset(fdt->close_on_exec, fdt->max_fdset);
-       free_fd_array(fdt->fd, fdt->max_fds);
-       kfree(fdt);
+       if (fdt->max_fds <= (PAGE_SIZE / sizeof(struct file *)))
+               kfree(fdt->fd);
+       else
+               vfree(fdt->fd);
 }
 
-static void fdtable_timer(unsigned long data)
+static inline void free_fdset(struct fdtable *fdt)
 {
-       struct fdtable_defer *fddef = (struct fdtable_defer *)data;
-
-       spin_lock(&fddef->lock);
-       /*
-        * If someone already emptied the queue return.
-        */
-       if (!fddef->next)
-               goto out;
-       if (!schedule_work(&fddef->wq))
-               mod_timer(&fddef->timer, 5);
-out:
-       spin_unlock(&fddef->lock);
+       if (fdt->max_fds <= (PAGE_SIZE * BITS_PER_BYTE / 2))
+               kfree(fdt->open_fds);
+       else
+               vfree(fdt->open_fds);
 }
 
-static void free_fdtable_work(struct fdtable_defer *f)
+static void free_fdtable_work(struct work_struct *work)
 {
+       struct fdtable_defer *f =
+               container_of(work, struct fdtable_defer, wq);
        struct fdtable *fdt;
 
        spin_lock_bh(&f->lock);
@@ -101,189 +68,113 @@ static void free_fdtable_work(struct fdtable_defer *f)
        spin_unlock_bh(&f->lock);
        while(fdt) {
                struct fdtable *next = fdt->next;
-               __free_fdtable(fdt);
+               vfree(fdt->fd);
+               free_fdset(fdt);
+               kfree(fdt);
                fdt = next;
        }
 }
 
-static void free_fdtable_rcu(struct rcu_head *rcu)
+void free_fdtable_rcu(struct rcu_head *rcu)
 {
        struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
-       int fdset_size, fdarray_size;
        struct fdtable_defer *fddef;
 
        BUG_ON(!fdt);
-       fdset_size = fdt->max_fdset / 8;
-       fdarray_size = fdt->max_fds * sizeof(struct file *);
 
-       if (fdt->free_files) {
-               /*
-                * The this fdtable was embedded in the files structure
-                * and the files structure itself was getting destroyed.
-                * It is now safe to free the files structure.
-                */
-               kmem_cache_free(files_cachep, fdt->free_files);
-               return;
-       }
-       if (fdt->max_fdset <= EMBEDDED_FD_SET_SIZE &&
-               fdt->max_fds <= NR_OPEN_DEFAULT) {
+       if (fdt->max_fds <= NR_OPEN_DEFAULT) {
                /*
-                * The fdtable was embedded
+                * This fdtable is embedded in the files structure and that
+                * structure itself is getting destroyed.
                 */
+               kmem_cache_free(files_cachep,
+                               container_of(fdt, struct files_struct, fdtab));
                return;
        }
-       if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
-               kfree(fdt->open_fds);
-               kfree(fdt->close_on_exec);
+       if (fdt->max_fds <= (PAGE_SIZE / sizeof(struct file *))) {
                kfree(fdt->fd);
+               kfree(fdt->open_fds);
                kfree(fdt);
        } else {
                fddef = &get_cpu_var(fdtable_defer_list);
                spin_lock(&fddef->lock);
                fdt->next = fddef->next;
                fddef->next = fdt;
-               /*
-                * vmallocs are handled from the workqueue context.
-                * If the per-cpu workqueue is running, then we
-                * defer work scheduling through a timer.
-                */
-               if (!schedule_work(&fddef->wq))
-                       mod_timer(&fddef->timer, 5);
+               /* vmallocs are handled from the workqueue context */
+               schedule_work(&fddef->wq);
                spin_unlock(&fddef->lock);
                put_cpu_var(fdtable_defer_list);
        }
 }
 
-void free_fdtable(struct fdtable *fdt)
-{
-       if (fdt->free_files ||
-               fdt->max_fdset > EMBEDDED_FD_SET_SIZE ||
-               fdt->max_fds > NR_OPEN_DEFAULT)
-               call_rcu(&fdt->rcu, free_fdtable_rcu);
-}
-
 /*
  * Expand the fdset in the files_struct.  Called with the files spinlock
  * held for write.
  */
-static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt)
+static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
 {
-       int i;
-       int count;
-
-       BUG_ON(nfdt->max_fdset < fdt->max_fdset);
-       BUG_ON(nfdt->max_fds < fdt->max_fds);
-       /* Copy the existing tables and install the new pointers */
-
-       i = fdt->max_fdset / (sizeof(unsigned long) * 8);
-       count = (nfdt->max_fdset - fdt->max_fdset) / 8;
-
-       /*
-        * Don't copy the entire array if the current fdset is
-        * not yet initialised.
-        */
-       if (i) {
-               memcpy (nfdt->open_fds, fdt->open_fds,
-                                               fdt->max_fdset/8);
-               memcpy (nfdt->close_on_exec, fdt->close_on_exec,
-                                               fdt->max_fdset/8);
-               memset (&nfdt->open_fds->fds_bits[i], 0, count);
-               memset (&nfdt->close_on_exec->fds_bits[i], 0, count);
-       }
+       unsigned int cpy, set;
 
-       /* Don't copy/clear the array if we are creating a new
-          fd array for fork() */
-       if (fdt->max_fds) {
-               memcpy(nfdt->fd, fdt->fd,
-                       fdt->max_fds * sizeof(struct file *));
-               /* clear the remainder of the array */
-               memset(&nfdt->fd[fdt->max_fds], 0,
-                      (nfdt->max_fds - fdt->max_fds) *
-                                       sizeof(struct file *));
-       }
-}
-
-/*
- * Allocate an fdset array, using kmalloc or vmalloc.
- * Note: the array isn't cleared at allocation time.
- */
-fd_set * alloc_fdset(int num)
-{
-       fd_set *new_fdset;
-       int size = num / 8;
+       BUG_ON(nfdt->max_fds < ofdt->max_fds);
+       if (ofdt->max_fds == 0)
+               return;
 
-       if (size <= PAGE_SIZE)
-               new_fdset = (fd_set *) kmalloc(size, GFP_KERNEL);
-       else
-               new_fdset = (fd_set *) vmalloc(size);
-       return new_fdset;
+       cpy = ofdt->max_fds * sizeof(struct file *);
+       set = (nfdt->max_fds - ofdt->max_fds) * sizeof(struct file *);
+       memcpy(nfdt->fd, ofdt->fd, cpy);
+       memset((char *)(nfdt->fd) + cpy, 0, set);
+
+       cpy = ofdt->max_fds / BITS_PER_BYTE;
+       set = (nfdt->max_fds - ofdt->max_fds) / BITS_PER_BYTE;
+       memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
+       memset((char *)(nfdt->open_fds) + cpy, 0, set);
+       memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy);
+       memset((char *)(nfdt->close_on_exec) + cpy, 0, set);
 }
 
-void free_fdset(fd_set *array, int num)
+static struct fdtable * alloc_fdtable(unsigned int nr)
 {
-       if (num <= EMBEDDED_FD_SET_SIZE) /* Don't free an embedded fdset */
-               return;
-       else if (num <= 8 * PAGE_SIZE)
-               kfree(array);
-       else
-               vfree(array);
-}
+       struct fdtable *fdt;
+       char *data;
 
-static struct fdtable *alloc_fdtable(int nr)
-{
-       struct fdtable *fdt = NULL;
-       int nfds = 0;
-       fd_set *new_openset = NULL, *new_execset = NULL;
-       struct file **new_fds;
+       /*
+        * Figure out how many fds we actually want to support in this fdtable.
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+        * and growing in powers of two from there on.
+        */
+       nr /= (1024 / sizeof(struct file *));
+       nr = roundup_pow_of_two(nr + 1);
+       nr *= (1024 / sizeof(struct file *));
+       if (nr > NR_OPEN)
+               nr = NR_OPEN;
 
-       fdt = kzalloc(sizeof(*fdt), GFP_KERNEL);
+       fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL);
        if (!fdt)
-               goto out;
-
-       nfds = max_t(int, 8 * L1_CACHE_BYTES, roundup_pow_of_two(nr + 1));
-       if (nfds > NR_OPEN)
-               nfds = NR_OPEN;
-
-       new_openset = alloc_fdset(nfds);
-       new_execset = alloc_fdset(nfds);
-       if (!new_openset || !new_execset)
-               goto out;
-       fdt->open_fds = new_openset;
-       fdt->close_on_exec = new_execset;
-       fdt->max_fdset = nfds;
+               goto out;
+       fdt->max_fds = nr;
+       data = alloc_fdmem(nr * sizeof(struct file *));
+       if (!data)
+               goto out_fdt;
+       fdt->fd = (struct file **)data;
+       data = alloc_fdmem(max_t(unsigned int,
+                                2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES));
+       if (!data)
+               goto out_arr;
+       fdt->open_fds = (fd_set *)data;
+       data += nr / BITS_PER_BYTE;
+       fdt->close_on_exec = (fd_set *)data;
+       INIT_RCU_HEAD(&fdt->rcu);
+       fdt->next = NULL;
 
-       nfds = NR_OPEN_DEFAULT;
-       /*
-        * Expand to the max in easy steps, and keep expanding it until
-        * we have enough for the requested fd array size.
-        */
-       do {
-#if NR_OPEN_DEFAULT < 256
-               if (nfds < 256)
-                       nfds = 256;
-               else
-#endif
-               if (nfds < (PAGE_SIZE / sizeof(struct file *)))
-                       nfds = PAGE_SIZE / sizeof(struct file *);
-               else {
-                       nfds = nfds * 2;
-                       if (nfds > NR_OPEN)
-                               nfds = NR_OPEN;
-               }
-       } while (nfds <= nr);
-       new_fds = alloc_fd_array(nfds);
-       if (!new_fds)
-               goto out2;
-       fdt->fd = new_fds;
-       fdt->max_fds = nfds;
-       fdt->free_files = NULL;
        return fdt;
-out2:
-       nfds = fdt->max_fdset;
-out:
-       free_fdset(new_openset, nfds);
-       free_fdset(new_execset, nfds);
+
+out_arr:
+       free_fdarr(fdt);
+out_fdt:
        kfree(fdt);
+out:
        return NULL;
 }
 
@@ -310,14 +201,17 @@ static int expand_fdtable(struct files_struct *files, int nr)
         * we dropped the lock
         */
        cur_fdt = files_fdtable(files);
-       if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) {
+       if (nr >= cur_fdt->max_fds) {
                /* Continue as planned */
                copy_fdtable(new_fdt, cur_fdt);
                rcu_assign_pointer(files->fdt, new_fdt);
-               free_fdtable(cur_fdt);
+               if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
+                       call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
        } else {
                /* Somebody else expanded, so undo our attempt */
-               __free_fdtable(new_fdt);
+               free_fdarr(new_fdt);
+               free_fdset(new_fdt);
+               kfree(new_fdt);
        }
        return 1;
 }
@@ -336,11 +230,10 @@ int expand_files(struct files_struct *files, int nr)
 
        fdt = files_fdtable(files);
        /* Do we need to expand? */
-       if (nr < fdt->max_fdset && nr < fdt->max_fds)
+       if (nr < fdt->max_fds)
                return 0;
        /* Can we expand? */
-       if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN ||
-           nr >= NR_OPEN)
+       if (nr >= NR_OPEN)
                return -EMFILE;
 
        /* All good, so we try */
@@ -351,10 +244,7 @@ static void __devinit fdtable_defer_list_init(int cpu)
 {
        struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
        spin_lock_init(&fddef->lock);
-       INIT_WORK(&fddef->wq, (void (*)(void *))free_fdtable_work, fddef);
-       init_timer(&fddef->timer);
-       fddef->timer.data = (unsigned long)fddef;
-       fddef->timer.function = fdtable_timer;
+       INIT_WORK(&fddef->wq, free_fdtable_work);
        fddef->next = NULL;
 }
 
index 24f25a0..4c17a18 100644 (file)
@@ -152,8 +152,8 @@ EXPORT_SYMBOL(fput);
  */
 void fastcall __fput(struct file *file)
 {
-       struct dentry *dentry = file->f_dentry;
-       struct vfsmount *mnt = file->f_vfsmnt;
+       struct dentry *dentry = file->f_path.dentry;
+       struct vfsmount *mnt = file->f_path.mnt;
        struct inode *inode = dentry->d_inode;
 
        might_sleep();
@@ -176,8 +176,8 @@ void fastcall __fput(struct file *file)
                put_write_access(inode);
        put_pid(file->f_owner.pid);
        file_kill(file);
-       file->f_dentry = NULL;
-       file->f_vfsmnt = NULL;
+       file->f_path.dentry = NULL;
+       file->f_path.mnt = NULL;
        file_free(file);
        dput(dentry);
        mntput(mnt);
@@ -271,7 +271,7 @@ int fs_may_remount_ro(struct super_block *sb)
        file_list_lock();
        list_for_each(p, &sb->s_files) {
                struct file *file = list_entry(p, struct file, f_u.fu_list);
-               struct inode *inode = file->f_dentry->d_inode;
+               struct inode *inode = file->f_path.dentry->d_inode;
 
                /* File with pending delete? */
                if (inode->i_nlink == 0)
index 4786d51..0b7ae89 100644 (file)
@@ -46,7 +46,7 @@ extern const struct address_space_operations vxfs_immed_aops;
 
 extern struct inode_operations vxfs_immed_symlink_iops;
 
-kmem_cache_t           *vxfs_inode_cachep;
+struct kmem_cache              *vxfs_inode_cachep;
 
 
 #ifdef DIAGNOSTIC
@@ -103,7 +103,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
                struct vxfs_inode_info  *vip;
                struct vxfs_dinode      *dip;
 
-               if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
+               if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
                        goto fail;
                dip = (struct vxfs_dinode *)(bp->b_data + offset);
                memcpy(vip, dip, sizeof(*vip));
@@ -145,7 +145,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
                struct vxfs_dinode      *dip;
                caddr_t                 kaddr = (char *)page_address(pp);
 
-               if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
+               if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
                        goto fail;
                dip = (struct vxfs_dinode *)(kaddr + offset);
                memcpy(vip, dip, sizeof(*vip));
index 43886fa..3995d7f 100644 (file)
@@ -240,7 +240,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
 static int
 vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
 {
-       struct inode            *ip = fp->f_dentry->d_inode;
+       struct inode            *ip = fp->f_path.dentry->d_inode;
        struct super_block      *sbp = ip->i_sb;
        u_long                  bsize = sbp->s_blocksize;
        u_long                  page, npages, block, pblocks, nblocks, offset;
index 16b39c0..8c58bd4 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->i_private;
+       fc = file->f_path.dentry->d_inode->i_private;
        if (fc)
                fc = fuse_conn_get(fc);
        mutex_unlock(&fuse_mutex);
index 66571ea..357764d 100644 (file)
@@ -19,7 +19,7 @@
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 
-static kmem_cache_t *fuse_req_cachep;
+static struct kmem_cache *fuse_req_cachep;
 
 static struct fuse_conn *fuse_get_conn(struct file *file)
 {
@@ -41,7 +41,7 @@ static void fuse_request_init(struct fuse_req *req)
 
 struct fuse_req *fuse_request_alloc(void)
 {
-       struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL);
+       struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL);
        if (req)
                fuse_request_init(req);
        return req;
index c71a6c0..4008047 100644 (file)
@@ -141,9 +141,6 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                struct fuse_req *forget_req;
                struct dentry *parent;
 
-               /* Doesn't hurt to "reset" the validity timeout */
-               fuse_invalidate_entry_cache(entry);
-
                /* For negative dentries, always do a fresh lookup */
                if (!inode)
                        return 0;
@@ -859,7 +856,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
        int err;
        size_t nbytes;
        struct page *page;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
 
@@ -1027,6 +1024,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
        if (attr->ia_valid & ATTR_SIZE) {
                unsigned long limit;
                is_truncate = 1;
+               if (IS_SWAPFILE(inode))
+                       return -ETXTBSY;
                limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
                if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
                        send_sig(SIGXFSZ, current, 0);
index 763a50d..1387749 100644 (file)
@@ -141,8 +141,8 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
                                        isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
 
                /* Hold vfsmount and dentry until release is finished */
-               req->vfsmount = mntget(file->f_vfsmnt);
-               req->dentry = dget(file->f_dentry);
+               req->vfsmount = mntget(file->f_path.mnt);
+               req->dentry = dget(file->f_path.dentry);
                request_send_background(fc, req);
        }
 
@@ -184,7 +184,7 @@ static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req;
@@ -533,7 +533,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
 static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
                              size_t count, loff_t *ppos, int write)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        size_t nmax = write ? fc->max_write : fc->max_read;
        loff_t pos = *ppos;
@@ -607,7 +607,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
 static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t res;
        /* Don't allow parallel writes to the same file */
        mutex_lock(&inode->i_mutex);
@@ -662,7 +662,7 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
 static void fuse_lk_fill(struct fuse_req *req, struct file *file,
                         const struct file_lock *fl, int opcode, pid_t pid)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_lk_in *arg = &req->misc.lk_in;
@@ -682,7 +682,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
 
 static int fuse_getlk(struct file *file, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_lk_out outarg;
@@ -707,7 +707,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
 
 static int fuse_setlk(struct file *file, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
@@ -734,7 +734,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
 
 static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
@@ -754,6 +754,42 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
        return err;
 }
 
+static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
+{
+       struct inode *inode = mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_bmap_in inarg;
+       struct fuse_bmap_out outarg;
+       int err;
+
+       if (!inode->i_sb->s_bdev || fc->no_bmap)
+               return 0;
+
+       req = fuse_get_req(fc);
+       if (IS_ERR(req))
+               return 0;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.block = block;
+       inarg.blocksize = inode->i_sb->s_blocksize;
+       req->in.h.opcode = FUSE_BMAP;
+       req->in.h.nodeid = get_node_id(inode);
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS)
+               fc->no_bmap = 1;
+
+       return err ? 0 : outarg.block;
+}
+
 static const struct file_operations fuse_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
@@ -787,6 +823,7 @@ static const struct address_space_operations fuse_file_aops  = {
        .commit_write   = fuse_commit_write,
        .readpages      = fuse_readpages,
        .set_page_dirty = fuse_set_page_dirty,
+       .bmap           = fuse_bmap,
 };
 
 void fuse_init_file_inode(struct inode *inode)
index 91edb89..b98b20d 100644 (file)
@@ -298,6 +298,9 @@ struct fuse_conn {
            reply, before any other request, and never cleared */
        unsigned conn_error : 1;
 
+       /** Connection successful.  Only set in INIT */
+       unsigned conn_init : 1;
+
        /** Do readpages asynchronously?  Only set in INIT */
        unsigned async_read : 1;
 
@@ -339,6 +342,9 @@ struct fuse_conn {
        /** Is interrupt not implemented by fs? */
        unsigned no_interrupt : 1;
 
+       /** Is bmap not implemented by fs? */
+       unsigned no_bmap : 1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
@@ -365,6 +371,9 @@ struct fuse_conn {
 
        /** Key for lock owner ID scrambling */
        u32 scramble_key[4];
+
+       /** Reserved request for the DESTROY message */
+       struct fuse_req *destroy_req;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
index fc42035..12450d2 100644 (file)
@@ -22,7 +22,7 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
 MODULE_LICENSE("GPL");
 
-static kmem_cache_t *fuse_inode_cachep;
+static struct kmem_cache *fuse_inode_cachep;
 struct list_head fuse_conn_list;
 DEFINE_MUTEX(fuse_mutex);
 
@@ -39,6 +39,7 @@ struct fuse_mount_data {
        unsigned group_id_present : 1;
        unsigned flags;
        unsigned max_read;
+       unsigned blksize;
 };
 
 static struct inode *fuse_alloc_inode(struct super_block *sb)
@@ -46,7 +47,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        struct inode *inode;
        struct fuse_inode *fi;
 
-       inode = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL);
+       inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL);
        if (!inode)
                return NULL;
 
@@ -205,10 +206,23 @@ static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
                fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
 }
 
+static void fuse_send_destroy(struct fuse_conn *fc)
+{
+       struct fuse_req *req = fc->destroy_req;
+       if (req && fc->conn_init) {
+               fc->destroy_req = NULL;
+               req->in.h.opcode = FUSE_DESTROY;
+               req->force = 1;
+               request_send(fc, req);
+               fuse_put_request(fc, req);
+       }
+}
+
 static void fuse_put_super(struct super_block *sb)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
+       fuse_send_destroy(fc);
        spin_lock(&fc->lock);
        fc->connected = 0;
        fc->blocked = 0;
@@ -274,6 +288,7 @@ enum {
        OPT_DEFAULT_PERMISSIONS,
        OPT_ALLOW_OTHER,
        OPT_MAX_READ,
+       OPT_BLKSIZE,
        OPT_ERR
 };
 
@@ -285,14 +300,16 @@ static match_table_t tokens = {
        {OPT_DEFAULT_PERMISSIONS,       "default_permissions"},
        {OPT_ALLOW_OTHER,               "allow_other"},
        {OPT_MAX_READ,                  "max_read=%u"},
+       {OPT_BLKSIZE,                   "blksize=%u"},
        {OPT_ERR,                       NULL}
 };
 
-static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
+static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev)
 {
        char *p;
        memset(d, 0, sizeof(struct fuse_mount_data));
        d->max_read = ~0;
+       d->blksize = 512;
 
        while ((p = strsep(&opt, ",")) != NULL) {
                int token;
@@ -345,6 +362,12 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
                        d->max_read = value;
                        break;
 
+               case OPT_BLKSIZE:
+                       if (!is_bdev || match_int(&args[0], &value))
+                               return 0;
+                       d->blksize = value;
+                       break;
+
                default:
                        return 0;
                }
@@ -400,6 +423,8 @@ static struct fuse_conn *new_conn(void)
 void fuse_conn_put(struct fuse_conn *fc)
 {
        if (atomic_dec_and_test(&fc->count)) {
+               if (fc->destroy_req)
+                       fuse_request_free(fc->destroy_req);
                mutex_destroy(&fc->inst_mutex);
                kfree(fc);
        }
@@ -456,6 +481,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
                fc->minor = arg->minor;
                fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
+               fc->conn_init = 1;
        }
        fuse_put_request(fc, req);
        fc->blocked = 0;
@@ -500,15 +526,23 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        struct dentry *root_dentry;
        struct fuse_req *init_req;
        int err;
+       int is_bdev = sb->s_bdev != NULL;
 
        if (sb->s_flags & MS_MANDLOCK)
                return -EINVAL;
 
-       if (!parse_fuse_opt((char *) data, &d))
+       if (!parse_fuse_opt((char *) data, &d, is_bdev))
                return -EINVAL;
 
-       sb->s_blocksize = PAGE_CACHE_SIZE;
-       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       if (is_bdev) {
+#ifdef CONFIG_BLOCK
+               if (!sb_set_blocksize(sb, d.blksize))
+                       return -EINVAL;
+#endif
+       } else {
+               sb->s_blocksize = PAGE_CACHE_SIZE;
+               sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       }
        sb->s_magic = FUSE_SUPER_MAGIC;
        sb->s_op = &fuse_super_operations;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -547,6 +581,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        if (!init_req)
                goto err_put_root;
 
+       if (is_bdev) {
+               fc->destroy_req = fuse_request_alloc();
+               if (!fc->destroy_req)
+                       goto err_put_root;
+       }
+
        mutex_lock(&fuse_mutex);
        err = -EINVAL;
        if (file->private_data)
@@ -598,10 +638,47 @@ static struct file_system_type fuse_fs_type = {
        .kill_sb        = kill_anon_super,
 };
 
+#ifdef CONFIG_BLOCK
+static int fuse_get_sb_blk(struct file_system_type *fs_type,
+                          int flags, const char *dev_name,
+                          void *raw_data, struct vfsmount *mnt)
+{
+       return get_sb_bdev(fs_type, flags, dev_name, raw_data, fuse_fill_super,
+                          mnt);
+}
+
+static struct file_system_type fuseblk_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "fuseblk",
+       .get_sb         = fuse_get_sb_blk,
+       .kill_sb        = kill_block_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+
+static inline int register_fuseblk(void)
+{
+       return register_filesystem(&fuseblk_fs_type);
+}
+
+static inline void unregister_fuseblk(void)
+{
+       unregister_filesystem(&fuseblk_fs_type);
+}
+#else
+static inline int register_fuseblk(void)
+{
+       return 0;
+}
+
+static inline void unregister_fuseblk(void)
+{
+}
+#endif
+
 static decl_subsys(fuse, NULL, NULL);
 static decl_subsys(connections, NULL, NULL);
 
-static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
+static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
                                 unsigned long flags)
 {
        struct inode * inode = foo;
@@ -617,24 +694,34 @@ static int __init fuse_fs_init(void)
 
        err = register_filesystem(&fuse_fs_type);
        if (err)
-               printk("fuse: failed to register filesystem\n");
-       else {
-               fuse_inode_cachep = kmem_cache_create("fuse_inode",
-                                                     sizeof(struct fuse_inode),
-                                                     0, SLAB_HWCACHE_ALIGN,
-                                                     fuse_inode_init_once, NULL);
-               if (!fuse_inode_cachep) {
-                       unregister_filesystem(&fuse_fs_type);
-                       err = -ENOMEM;
-               }
-       }
+               goto out;
 
+       err = register_fuseblk();
+       if (err)
+               goto out_unreg;
+
+       fuse_inode_cachep = kmem_cache_create("fuse_inode",
+                                             sizeof(struct fuse_inode),
+                                             0, SLAB_HWCACHE_ALIGN,
+                                             fuse_inode_init_once, NULL);
+       err = -ENOMEM;
+       if (!fuse_inode_cachep)
+               goto out_unreg2;
+
+       return 0;
+
+ out_unreg2:
+       unregister_fuseblk();
+ out_unreg:
+       unregister_filesystem(&fuse_fs_type);
+ out:
        return err;
 }
 
 static void fuse_fs_cleanup(void)
 {
        unregister_filesystem(&fuse_fs_type);
+       unregister_fuseblk();
        kmem_cache_destroy(fuse_inode_cachep);
 }
 
index 8c27de8..c0791cb 100644 (file)
@@ -2,6 +2,7 @@ config GFS2_FS
        tristate "GFS2 file system support"
        depends on EXPERIMENTAL
        select FS_POSIX_ACL
+       select CRC32
        help
        A cluster filesystem.
 
index 5f959b8..6e80844 100644 (file)
@@ -74,11 +74,11 @@ int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
 {
        if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
                return -EOPNOTSUPP;
-       if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER))
+       if (current->fsuid != ip->i_inode.i_uid && !capable(CAP_FOWNER))
                return -EPERM;
-       if (S_ISLNK(ip->i_di.di_mode))
+       if (S_ISLNK(ip->i_inode.i_mode))
                return -EOPNOTSUPP;
-       if (!access && !S_ISDIR(ip->i_di.di_mode))
+       if (!access && !S_ISDIR(ip->i_inode.i_mode))
                return -EACCES;
 
        return 0;
@@ -145,14 +145,14 @@ out:
 }
 
 /**
- * gfs2_check_acl_locked - Check an ACL to see if we're allowed to do something
+ * gfs2_check_acl - Check an ACL to see if we're allowed to do something
  * @inode: the file we want to do something to
  * @mask: what we want to do
  *
  * Returns: errno
  */
 
-int gfs2_check_acl_locked(struct inode *inode, int mask)
+int gfs2_check_acl(struct inode *inode, int mask)
 {
        struct posix_acl *acl = NULL;
        int error;
@@ -170,21 +170,6 @@ int gfs2_check_acl_locked(struct inode *inode, int mask)
        return -EAGAIN;
 }
 
-int gfs2_check_acl(struct inode *inode, int mask)
-{
-       struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_holder i_gh;
-       int error;
-
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-       if (!error) {
-               error = gfs2_check_acl_locked(inode, mask);
-               gfs2_glock_dq_uninit(&i_gh);
-       }
-
-       return error;
-}
-
 static int munge_mode(struct gfs2_inode *ip, mode_t mode)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
@@ -198,10 +183,10 @@ static int munge_mode(struct gfs2_inode *ip, mode_t mode)
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                gfs2_assert_withdraw(sdp,
-                               (ip->i_di.di_mode & S_IFMT) == (mode & S_IFMT));
-               ip->i_di.di_mode = mode;
+                               (ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT));
+               ip->i_inode.i_mode = mode;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -215,12 +200,12 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct posix_acl *acl = NULL, *clone;
        struct gfs2_ea_request er;
-       mode_t mode = ip->i_di.di_mode;
+       mode_t mode = ip->i_inode.i_mode;
        int error;
 
        if (!sdp->sd_args.ar_posix_acl)
                return 0;
-       if (S_ISLNK(ip->i_di.di_mode))
+       if (S_ISLNK(ip->i_inode.i_mode))
                return 0;
 
        memset(&er, 0, sizeof(struct gfs2_ea_request));
@@ -232,7 +217,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
                return error;
        if (!acl) {
                mode &= ~current->fs->umask;
-               if (mode != ip->i_di.di_mode)
+               if (mode != ip->i_inode.i_mode)
                        error = munge_mode(ip, mode);
                return error;
        }
@@ -244,7 +229,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
        posix_acl_release(acl);
        acl = clone;
 
-       if (S_ISDIR(ip->i_di.di_mode)) {
+       if (S_ISDIR(ip->i_inode.i_mode)) {
                er.er_name = GFS2_POSIX_ACL_DEFAULT;
                er.er_name_len = GFS2_POSIX_ACL_DEFAULT_LEN;
                error = gfs2_system_eaops.eo_set(ip, &er);
index 05c294f..6751930 100644 (file)
@@ -31,7 +31,6 @@ int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
                          struct gfs2_ea_request *er,
                          int *remove, mode_t *mode);
 int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access);
-int gfs2_check_acl_locked(struct inode *inode, int mask);
 int gfs2_check_acl(struct inode *inode, int mask);
 int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
 int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
index 06e9a8c..8240c1f 100644 (file)
@@ -38,8 +38,8 @@ struct metapath {
 };
 
 typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh,
-                            struct buffer_head *bh, u64 *top,
-                            u64 *bottom, unsigned int height,
+                            struct buffer_head *bh, __be64 *top,
+                            __be64 *bottom, unsigned int height,
                             void *data);
 
 struct strip_mine {
@@ -163,6 +163,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
        if (ip->i_di.di_size) {
                *(__be64 *)(di + 1) = cpu_to_be64(block);
                ip->i_di.di_blocks++;
+               gfs2_set_inode_blocks(&ip->i_inode);
                di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
        }
 
@@ -230,7 +231,7 @@ static int build_height(struct inode *inode, unsigned height)
        struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
        struct gfs2_dinode *di;
        int error;
-       u64 *bp;
+       __be64 *bp;
        u64 bn;
        unsigned n;
 
@@ -255,7 +256,7 @@ static int build_height(struct inode *inode, unsigned height)
                                          GFS2_FORMAT_IN);
                        gfs2_buffer_clear_tail(blocks[n],
                                               sizeof(struct gfs2_meta_header));
-                       bp = (u64 *)(blocks[n]->b_data +
+                       bp = (__be64 *)(blocks[n]->b_data +
                                     sizeof(struct gfs2_meta_header));
                        *bp = cpu_to_be64(blocks[n+1]->b_blocknr);
                        brelse(blocks[n]);
@@ -272,6 +273,7 @@ static int build_height(struct inode *inode, unsigned height)
        *(__be64 *)(di + 1) = cpu_to_be64(bn);
        ip->i_di.di_height += new_height;
        ip->i_di.di_blocks += new_height;
+       gfs2_set_inode_blocks(&ip->i_inode);
        di->di_height = cpu_to_be16(ip->i_di.di_height);
        di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
        brelse(dibh);
@@ -360,15 +362,15 @@ static void find_metapath(struct gfs2_inode *ip, u64 block,
  * metadata tree.
  */
 
-static inline u64 *metapointer(struct buffer_head *bh, int *boundary,
+static inline __be64 *metapointer(struct buffer_head *bh, int *boundary,
                               unsigned int height, const struct metapath *mp)
 {
        unsigned int head_size = (height > 0) ?
                sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
-       u64 *ptr;
+       __be64 *ptr;
        *boundary = 0;
-       ptr = ((u64 *)(bh->b_data + head_size)) + mp->mp_list[height];
-       if (ptr + 1 == (u64 *)(bh->b_data + bh->b_size))
+       ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
+       if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size))
                *boundary = 1;
        return ptr;
 }
@@ -394,7 +396,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
                        int *new, u64 *block)
 {
        int boundary;
-       u64 *ptr = metapointer(bh, &boundary, height, mp);
+       __be64 *ptr = metapointer(bh, &boundary, height, mp);
 
        if (*ptr) {
                *block = be64_to_cpu(*ptr);
@@ -415,17 +417,35 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
 
        *ptr = cpu_to_be64(*block);
        ip->i_di.di_blocks++;
+       gfs2_set_inode_blocks(&ip->i_inode);
 
        *new = 1;
        return 0;
 }
 
+static inline void bmap_lock(struct inode *inode, int create)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       if (create)
+               down_write(&ip->i_rw_mutex);
+       else
+               down_read(&ip->i_rw_mutex);
+}
+
+static inline void bmap_unlock(struct inode *inode, int create)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       if (create)
+               up_write(&ip->i_rw_mutex);
+       else
+               up_read(&ip->i_rw_mutex);
+}
+
 /**
- * gfs2_block_pointers - Map a block from an inode to a disk block
+ * gfs2_block_map - Map a block from an inode to a disk block
  * @inode: The inode
  * @lblock: The logical block number
- * @map_bh: The bh to be mapped
- * @mp: metapath to use
+ * @bh_map: The bh to be mapped
  *
  * Find the block number on the current device which corresponds to an
  * inode's block. If the block had to be created, "new" will be set.
@@ -433,8 +453,8 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
  * Returns: errno
  */
 
-static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
-                              struct buffer_head *bh_map, struct metapath *mp)
+int gfs2_block_map(struct inode *inode, u64 lblock, int create,
+                  struct buffer_head *bh_map)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -448,57 +468,61 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
        u64 dblock = 0;
        int boundary;
        unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
+       struct metapath mp;
+       u64 size;
 
        BUG_ON(maxlen == 0);
 
        if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
                return 0;
 
+       bmap_lock(inode, create);
+       clear_buffer_mapped(bh_map);
+       clear_buffer_new(bh_map);
+       clear_buffer_boundary(bh_map);
        bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
-
-       height = calc_tree_height(ip, (lblock + 1) * bsize);
-       if (ip->i_di.di_height < height) {
-               if (!create)
-                       return 0;
-
-               error = build_height(inode, height);
-               if (error)
-                       return error;
+       size = (lblock + 1) * bsize;
+
+       if (size > ip->i_di.di_size) {
+               height = calc_tree_height(ip, size);
+               if (ip->i_di.di_height < height) {
+                       if (!create)
+                               goto out_ok;
+       
+                       error = build_height(inode, height);
+                       if (error)
+                               goto out_fail;
+               }
        }
 
-       find_metapath(ip, lblock, mp);
+       find_metapath(ip, lblock, &mp);
        end_of_metadata = ip->i_di.di_height - 1;
-
        error = gfs2_meta_inode_buffer(ip, &bh);
        if (error)
-               return error;
+               goto out_fail;
 
        for (x = 0; x < end_of_metadata; x++) {
-               lookup_block(ip, bh, x, mp, create, &new, &dblock);
+               lookup_block(ip, bh, x, &mp, create, &new, &dblock);
                brelse(bh);
                if (!dblock)
-                       return 0;
+                       goto out_ok;
 
                error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh);
                if (error)
-                       return error;
+                       goto out_fail;
        }
 
-       boundary = lookup_block(ip, bh, end_of_metadata, mp, create, &new, &dblock);
-       clear_buffer_mapped(bh_map);
-       clear_buffer_new(bh_map);
-       clear_buffer_boundary(bh_map);
-
+       boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock);
        if (dblock) {
                map_bh(bh_map, inode->i_sb, dblock);
                if (boundary)
-                       set_buffer_boundary(bh);
+                       set_buffer_boundary(bh_map);
                if (new) {
                        struct buffer_head *dibh;
                        error = gfs2_meta_inode_buffer(ip, &dibh);
                        if (!error) {
                                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-                               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+                               gfs2_dinode_out(ip, dibh->b_data);
                                brelse(dibh);
                        }
                        set_buffer_new(bh_map);
@@ -507,8 +531,8 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
                while(--maxlen && !buffer_boundary(bh_map)) {
                        u64 eblock;
 
-                       mp->mp_list[end_of_metadata]++;
-                       boundary = lookup_block(ip, bh, end_of_metadata, mp, 0, &new, &eblock);
+                       mp.mp_list[end_of_metadata]++;
+                       boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock);
                        if (eblock != ++dblock)
                                break;
                        bh_map->b_size += (1 << inode->i_blkbits);
@@ -518,43 +542,15 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
        }
 out_brelse:
        brelse(bh);
-       return 0;
-}
-
-
-static inline void bmap_lock(struct inode *inode, int create)
-{
-       struct gfs2_inode *ip = GFS2_I(inode);
-       if (create)
-               down_write(&ip->i_rw_mutex);
-       else
-               down_read(&ip->i_rw_mutex);
-}
-
-static inline void bmap_unlock(struct inode *inode, int create)
-{
-       struct gfs2_inode *ip = GFS2_I(inode);
-       if (create)
-               up_write(&ip->i_rw_mutex);
-       else
-               up_read(&ip->i_rw_mutex);
-}
-
-int gfs2_block_map(struct inode *inode, u64 lblock, int create,
-                  struct buffer_head *bh)
-{
-       struct metapath mp;
-       int ret;
-
-       bmap_lock(inode, create);
-       ret = gfs2_block_pointers(inode, lblock, create, bh, &mp);
+out_ok:
+       error = 0;
+out_fail:
        bmap_unlock(inode, create);
-       return ret;
+       return error;
 }
 
 int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
 {
-       struct metapath mp;
        struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
        int ret;
        int create = *new;
@@ -564,9 +560,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
        BUG_ON(!new);
 
        bh.b_size = 1 << (inode->i_blkbits + 5);
-       bmap_lock(inode, create);
-       ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp);
-       bmap_unlock(inode, create);
+       ret = gfs2_block_map(inode, lblock, create, &bh);
        *extlen = bh.b_size >> inode->i_blkbits;
        *dblock = bh.b_blocknr;
        if (buffer_new(&bh))
@@ -600,7 +594,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct buffer_head *bh = NULL;
-       u64 *top, *bottom;
+       __be64 *top, *bottom;
        u64 bn;
        int error;
        int mh_size = sizeof(struct gfs2_meta_header);
@@ -611,17 +605,17 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
                        return error;
                dibh = bh;
 
-               top = (u64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
-               bottom = (u64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
+               top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
+               bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
        } else {
                error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
                if (error)
                        return error;
 
-               top = (u64 *)(bh->b_data + mh_size) +
+               top = (__be64 *)(bh->b_data + mh_size) +
                                  (first ? mp->mp_list[height] : 0);
 
-               bottom = (u64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
+               bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
        }
 
        error = bc(ip, dibh, bh, top, bottom, height, data);
@@ -660,7 +654,7 @@ out:
  */
 
 static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
-                   struct buffer_head *bh, u64 *top, u64 *bottom,
+                   struct buffer_head *bh, __be64 *top, __be64 *bottom,
                    unsigned int height, void *data)
 {
        struct strip_mine *sm = data;
@@ -668,7 +662,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
        struct gfs2_rgrp_list rlist;
        u64 bn, bstart;
        u32 blen;
-       u64 *p;
+       __be64 *p;
        unsigned int rg_blocks = 0;
        int metadata;
        unsigned int revokes = 0;
@@ -770,6 +764,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
                if (!ip->i_di.di_blocks)
                        gfs2_consist_inode(ip);
                ip->i_di.di_blocks--;
+               gfs2_set_inode_blocks(&ip->i_inode);
        }
        if (bstart) {
                if (metadata)
@@ -778,9 +773,9 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
                        gfs2_free_data(ip, bstart, blen);
        }
 
-       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
 
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
 
        up_write(&ip->i_rw_mutex);
 
@@ -819,7 +814,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
        if (error)
                goto out;
 
-       error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
+       error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
        if (error)
                goto out_gunlock_q;
 
@@ -853,14 +848,14 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
        }
 
        ip->i_di.di_size = size;
-       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
                goto out_end_trans;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
 out_end_trans:
@@ -968,9 +963,9 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
 
        if (gfs2_is_stuffed(ip)) {
                ip->i_di.di_size = size;
-               ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+               ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
                error = 1;
 
@@ -980,10 +975,10 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
 
                if (!error) {
                        ip->i_di.di_size = size;
-                       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+                       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
                        ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
                        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-                       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+                       gfs2_dinode_out(ip, dibh->b_data);
                }
        }
 
@@ -1053,11 +1048,11 @@ static int trunc_end(struct gfs2_inode *ip)
                        ip->i_num.no_addr;
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
        }
-       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
        ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
 out:
@@ -1109,7 +1104,7 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
 {
        int error;
 
-       if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_di.di_mode)))
+       if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
                return -EINVAL;
 
        if (size > ip->i_di.di_size)
index cab1f68..683cb5b 100644 (file)
@@ -112,6 +112,7 @@ int gfs2_logd(void *data)
        struct gfs2_sbd *sdp = data;
        struct gfs2_holder ji_gh;
        unsigned long t;
+       int need_flush;
 
        while (!kthread_should_stop()) {
                /* Advance the log tail */
@@ -120,8 +121,10 @@ int gfs2_logd(void *data)
                    gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
 
                gfs2_ail1_empty(sdp, DIO_ALL);
-
-               if (time_after_eq(jiffies, t)) {
+               gfs2_log_lock(sdp);
+               need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks);
+               gfs2_log_unlock(sdp);
+               if (need_flush || time_after_eq(jiffies, t)) {
                        gfs2_log_flush(sdp, NULL);
                        sdp->sd_log_flush_time = jiffies;
                }
index e24af28..0fdcb77 100644 (file)
@@ -131,8 +131,8 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
        memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
        if (ip->i_di.di_size < offset + size)
                ip->i_di.di_size = offset + size;
-       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+       gfs2_dinode_out(ip, dibh->b_data);
 
        brelse(dibh);
 
@@ -229,10 +229,10 @@ out:
 
        if (ip->i_di.di_size < offset + copied)
                ip->i_di.di_size = offset + copied;
-       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
+       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
        return copied;
@@ -340,10 +340,15 @@ fail:
        return (copied) ? copied : error;
 }
 
+static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
+{
+       return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0;
+}
+
 static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
                                     const struct qstr *name, int ret)
 {
-       if (dent->de_inum.no_addr != 0 &&
+       if (!gfs2_dirent_sentinel(dent) &&
            be32_to_cpu(dent->de_hash) == name->hash &&
            be16_to_cpu(dent->de_name_len) == name->len &&
            memcmp(dent+1, name->name, name->len) == 0)
@@ -388,7 +393,7 @@ static int gfs2_dirent_find_space(const struct gfs2_dirent *dent,
        unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
        unsigned totlen = be16_to_cpu(dent->de_rec_len);
 
-       if (!dent->de_inum.no_addr)
+       if (gfs2_dirent_sentinel(dent))
                actual = GFS2_DIRENT_SIZE(0);
        if (totlen - actual >= required)
                return 1;
@@ -405,7 +410,7 @@ static int gfs2_dirent_gather(const struct gfs2_dirent *dent,
                              void *opaque)
 {
        struct dirent_gather *g = opaque;
-       if (dent->de_inum.no_addr) {
+       if (!gfs2_dirent_sentinel(dent)) {
                g->pdent[g->offset++] = dent;
        }
        return 0;
@@ -433,10 +438,10 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset,
        if (unlikely(offset + size > len))
                goto error;
        msg = "zero inode number";
-       if (unlikely(!first && !dent->de_inum.no_addr))
+       if (unlikely(!first && gfs2_dirent_sentinel(dent)))
                goto error;
        msg = "name length is greater than space in dirent";
-       if (dent->de_inum.no_addr &&
+       if (!gfs2_dirent_sentinel(dent) &&
            unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) >
                     size))
                goto error;
@@ -598,7 +603,7 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh,
                return ret;
 
         /* Only the first dent could ever have de_inum.no_addr == 0 */
-       if (!tmp->de_inum.no_addr) {
+       if (gfs2_dirent_sentinel(tmp)) {
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -621,7 +626,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
 {
        u16 cur_rec_len, prev_rec_len;
 
-       if (!cur->de_inum.no_addr) {
+       if (gfs2_dirent_sentinel(cur)) {
                gfs2_consist_inode(dip);
                return;
        }
@@ -633,7 +638,8 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
           out the inode number and return.  */
 
        if (!prev) {
-               cur->de_inum.no_addr = 0;       /* No endianess worries */
+               cur->de_inum.no_addr = 0;
+               cur->de_inum.no_formal_ino = 0;
                return;
        }
 
@@ -664,7 +670,7 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
        struct gfs2_dirent *ndent;
        unsigned offset = 0, totlen;
 
-       if (dent->de_inum.no_addr)
+       if (!gfs2_dirent_sentinel(dent))
                offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
        totlen = be16_to_cpu(dent->de_rec_len);
        BUG_ON(offset + name->len > totlen);
@@ -713,12 +719,12 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
 static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
                       u64 *leaf_out)
 {
-       u64 leaf_no;
+       __be64 leaf_no;
        int error;
 
        error = gfs2_dir_read_data(dip, (char *)&leaf_no,
-                                   index * sizeof(u64),
-                                   sizeof(u64), 0);
+                                   index * sizeof(__be64),
+                                   sizeof(__be64), 0);
        if (error != sizeof(u64))
                return (error < 0) ? error : -EIO;
 
@@ -837,7 +843,8 @@ static int dir_make_exhash(struct inode *inode)
        struct gfs2_leaf *leaf;
        int y;
        u32 x;
-       u64 *lp, bn;
+       __be64 *lp;
+       u64 bn;
        int error;
 
        error = gfs2_meta_inode_buffer(dip, &dibh);
@@ -893,20 +900,20 @@ static int dir_make_exhash(struct inode *inode)
        gfs2_trans_add_bh(dip->i_gl, dibh, 1);
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
-       lp = (u64 *)(dibh->b_data + sizeof(struct gfs2_dinode));
+       lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode));
 
        for (x = sdp->sd_hash_ptrs; x--; lp++)
                *lp = cpu_to_be64(bn);
 
        dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
        dip->i_di.di_blocks++;
+       gfs2_set_inode_blocks(&dip->i_inode);
        dip->i_di.di_flags |= GFS2_DIF_EXHASH;
-       dip->i_di.di_payload_format = 0;
 
        for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
        dip->i_di.di_depth = y;
 
-       gfs2_dinode_out(&dip->i_di, dibh->b_data);
+       gfs2_dinode_out(dip, dibh->b_data);
 
        brelse(dibh);
 
@@ -929,7 +936,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
        struct gfs2_leaf *nleaf, *oleaf;
        struct gfs2_dirent *dent = NULL, *prev = NULL, *next = NULL, *new;
        u32 start, len, half_len, divider;
-       u64 bn, *lp, leaf_no;
+       u64 bn, leaf_no;
+       __be64 *lp;
        u32 index;
        int x, moved = 0;
        int error;
@@ -974,7 +982,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
        /* Change the pointers.
           Don't bother distinguishing stuffed from non-stuffed.
           This code is complicated enough already. */
-       lp = kmalloc(half_len * sizeof(u64), GFP_NOFS | __GFP_NOFAIL);
+       lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL);
        /*  Change the pointers  */
        for (x = 0; x < half_len; x++)
                lp[x] = cpu_to_be64(bn);
@@ -1000,7 +1008,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
                if (dirent_next(dip, obh, &next))
                        next = NULL;
 
-               if (dent->de_inum.no_addr &&
+               if (!gfs2_dirent_sentinel(dent) &&
                    be32_to_cpu(dent->de_hash) < divider) {
                        struct qstr str;
                        str.name = (char*)(dent+1);
@@ -1037,7 +1045,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
        error = gfs2_meta_inode_buffer(dip, &dibh);
        if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
                dip->i_di.di_blocks++;
-               gfs2_dinode_out(&dip->i_di, dibh->b_data);
+               gfs2_set_inode_blocks(&dip->i_inode);
+               gfs2_dinode_out(dip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -1117,7 +1126,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
        error = gfs2_meta_inode_buffer(dip, &dibh);
        if (!gfs2_assert_withdraw(sdp, !error)) {
                dip->i_di.di_depth++;
-               gfs2_dinode_out(&dip->i_di, dibh->b_data);
+               gfs2_dinode_out(dip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -1194,7 +1203,7 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
                           int *copied)
 {
        const struct gfs2_dirent *dent, *dent_next;
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        u64 off, off_next;
        unsigned int x, y;
        int run = 0;
@@ -1341,7 +1350,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
        u32 hsize, len = 0;
        u32 ht_offset, lp_offset, ht_offset_cur = -1;
        u32 hash, index;
-       u64 *lp;
+       __be64 *lp;
        int copied = 0;
        int error = 0;
        unsigned depth = 0;
@@ -1365,7 +1374,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
 
                if (ht_offset_cur != ht_offset) {
                        error = gfs2_dir_read_data(dip, (char *)lp,
-                                               ht_offset * sizeof(u64),
+                                               ht_offset * sizeof(__be64),
                                                sdp->sd_hash_bsize, 1);
                        if (error != sdp->sd_hash_bsize) {
                                if (error >= 0)
@@ -1456,7 +1465,7 @@ out:
  */
 
 int gfs2_dir_search(struct inode *dir, const struct qstr *name,
-                   struct gfs2_inum *inum, unsigned int *type)
+                   struct gfs2_inum_host *inum, unsigned int *type)
 {
        struct buffer_head *bh;
        struct gfs2_dirent *dent;
@@ -1515,7 +1524,8 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
                return error;
        gfs2_trans_add_bh(ip->i_gl, bh, 1);
        ip->i_di.di_blocks++;
-       gfs2_dinode_out(&ip->i_di, bh->b_data);
+       gfs2_set_inode_blocks(&ip->i_inode);
+       gfs2_dinode_out(ip, bh->b_data);
        brelse(bh);
        return 0;
 }
@@ -1531,7 +1541,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
  */
 
 int gfs2_dir_add(struct inode *inode, const struct qstr *name,
-                const struct gfs2_inum *inum, unsigned type)
+                const struct gfs2_inum_host *inum, unsigned type)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct buffer_head *bh;
@@ -1558,8 +1568,8 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
                                break;
                        gfs2_trans_add_bh(ip->i_gl, bh, 1);
                        ip->i_di.di_entries++;
-                       ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
-                       gfs2_dinode_out(&ip->i_di, bh->b_data);
+                       ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+                       gfs2_dinode_out(ip, bh->b_data);
                        brelse(bh);
                        error = 0;
                        break;
@@ -1644,8 +1654,8 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
                gfs2_consist_inode(dip);
        gfs2_trans_add_bh(dip->i_gl, bh, 1);
        dip->i_di.di_entries--;
-       dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-       gfs2_dinode_out(&dip->i_di, bh->b_data);
+       dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+       gfs2_dinode_out(dip, bh->b_data);
        brelse(bh);
        mark_inode_dirty(&dip->i_inode);
 
@@ -1666,7 +1676,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
  */
 
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-                  struct gfs2_inum *inum, unsigned int new_type)
+                  struct gfs2_inum_host *inum, unsigned int new_type)
 {
        struct buffer_head *bh;
        struct gfs2_dirent *dent;
@@ -1692,8 +1702,8 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
                gfs2_trans_add_bh(dip->i_gl, bh, 1);
        }
 
-       dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-       gfs2_dinode_out(&dip->i_di, bh->b_data);
+       dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+       gfs2_dinode_out(dip, bh->b_data);
        brelse(bh);
        return 0;
 }
@@ -1715,7 +1725,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
        u32 hsize, len;
        u32 ht_offset, lp_offset, ht_offset_cur = -1;
        u32 index = 0;
-       u64 *lp;
+       __be64 *lp;
        u64 leaf_no;
        int error = 0;
 
@@ -1735,7 +1745,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
 
                if (ht_offset_cur != ht_offset) {
                        error = gfs2_dir_read_data(dip, (char *)lp,
-                                               ht_offset * sizeof(u64),
+                                               ht_offset * sizeof(__be64),
                                                sdp->sd_hash_bsize, 1);
                        if (error != sdp->sd_hash_bsize) {
                                if (error >= 0)
@@ -1859,6 +1869,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
                if (!dip->i_di.di_blocks)
                        gfs2_consist_inode(dip);
                dip->i_di.di_blocks--;
+               gfs2_set_inode_blocks(&dip->i_inode);
        }
 
        error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
@@ -1873,7 +1884,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
                goto out_end_trans;
 
        gfs2_trans_add_bh(dip->i_gl, dibh, 1);
-       gfs2_dinode_out(&dip->i_di, dibh->b_data);
+       gfs2_dinode_out(dip, dibh->b_data);
        brelse(dibh);
 
 out_end_trans:
index 3712334..b21b336 100644 (file)
@@ -31,17 +31,17 @@ struct gfs2_inum;
 typedef int (*gfs2_filldir_t) (void *opaque,
                              const char *name, unsigned int length,
                              u64 offset,
-                             struct gfs2_inum *inum, unsigned int type);
+                             struct gfs2_inum_host *inum, unsigned int type);
 
 int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
-                   struct gfs2_inum *inum, unsigned int *type);
+                   struct gfs2_inum_host *inum, unsigned int *type);
 int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
-                const struct gfs2_inum *inum, unsigned int type);
+                const struct gfs2_inum_host *inum, unsigned int type);
 int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
 int gfs2_dir_read(struct inode *inode, u64 * offset, void *opaque,
                  gfs2_filldir_t filldir);
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-                  struct gfs2_inum *new_inum, unsigned int new_type);
+                  struct gfs2_inum_host *new_inum, unsigned int new_type);
 
 int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
 
index 92c54e9..cd747c0 100644 (file)
@@ -120,7 +120,7 @@ static int system_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
 
        if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) {
                if (!(er->er_flags & GFS2_ERF_MODE)) {
-                       er->er_mode = ip->i_di.di_mode;
+                       er->er_mode = ip->i_inode.i_mode;
                        er->er_flags |= GFS2_ERF_MODE;
                }
                error = gfs2_acl_validate_set(ip, 1, er,
index a65a4cc..ebebbdc 100644 (file)
@@ -112,7 +112,7 @@ fail:
 static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
 {
        struct buffer_head *bh, *eabh;
-       u64 *eablk, *end;
+       __be64 *eablk, *end;
        int error;
 
        error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &bh);
@@ -129,7 +129,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
                goto out;
        }
 
-       eablk = (u64 *)(bh->b_data + sizeof(struct gfs2_meta_header));
+       eablk = (__be64 *)(bh->b_data + sizeof(struct gfs2_meta_header));
        end = eablk + GFS2_SB(&ip->i_inode)->sd_inptrs;
 
        for (; eablk < end; eablk++) {
@@ -224,7 +224,8 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
        struct gfs2_rgrpd *rgd;
        struct gfs2_holder rg_gh;
        struct buffer_head *dibh;
-       u64 *dataptrs, bn = 0;
+       __be64 *dataptrs;
+       u64 bn = 0;
        u64 bstart = 0;
        unsigned int blen = 0;
        unsigned int blks = 0;
@@ -280,6 +281,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
                if (!ip->i_di.di_blocks)
                        gfs2_consist_inode(ip);
                ip->i_di.di_blocks--;
+               gfs2_set_inode_blocks(&ip->i_inode);
        }
        if (bstart)
                gfs2_free_meta(ip, bstart, blen);
@@ -299,9 +301,9 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               ip->i_di.di_ctime = get_seconds();
+               ip->i_inode.i_ctime.tv_sec = get_seconds();
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -444,7 +446,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
        struct buffer_head **bh;
        unsigned int amount = GFS2_EA_DATA_LEN(ea);
        unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
-       u64 *dataptrs = GFS2_EA2DATAPTRS(ea);
+       __be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
        unsigned int x;
        int error = 0;
 
@@ -597,6 +599,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
        ea->ea_num_ptrs = 0;
 
        ip->i_di.di_blocks++;
+       gfs2_set_inode_blocks(&ip->i_inode);
 
        return 0;
 }
@@ -629,7 +632,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
                ea->ea_num_ptrs = 0;
                memcpy(GFS2_EA2DATA(ea), er->er_data, er->er_data_len);
        } else {
-               u64 *dataptr = GFS2_EA2DATAPTRS(ea);
+               __be64 *dataptr = GFS2_EA2DATAPTRS(ea);
                const char *data = er->er_data;
                unsigned int data_len = er->er_data_len;
                unsigned int copy;
@@ -648,6 +651,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
                        gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
 
                        ip->i_di.di_blocks++;
+                       gfs2_set_inode_blocks(&ip->i_inode);
 
                        copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
                                                           data_len;
@@ -686,7 +690,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
        if (error)
                goto out;
 
-       error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
+       error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
        if (error)
                goto out_gunlock_q;
 
@@ -710,13 +714,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
        if (!error) {
                if (er->er_flags & GFS2_ERF_MODE) {
                        gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
-                                           (ip->i_di.di_mode & S_IFMT) ==
+                                           (ip->i_inode.i_mode & S_IFMT) ==
                                            (er->er_mode & S_IFMT));
-                       ip->i_di.di_mode = er->er_mode;
+                       ip->i_inode.i_mode = er->er_mode;
                }
-               ip->i_di.di_ctime = get_seconds();
+               ip->i_inode.i_ctime.tv_sec = get_seconds();
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -846,12 +850,12 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
 
        if (er->er_flags & GFS2_ERF_MODE) {
                gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
-                       (ip->i_di.di_mode & S_IFMT) == (er->er_mode & S_IFMT));
-               ip->i_di.di_mode = er->er_mode;
+                       (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
+               ip->i_inode.i_mode = er->er_mode;
        }
-       ip->i_di.di_ctime = get_seconds();
+       ip->i_inode.i_ctime.tv_sec = get_seconds();
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 out:
        gfs2_trans_end(GFS2_SB(&ip->i_inode));
@@ -931,12 +935,12 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct buffer_head *indbh, *newbh;
-       u64 *eablk;
+       __be64 *eablk;
        int error;
        int mh_size = sizeof(struct gfs2_meta_header);
 
        if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {
-               u64 *end;
+               __be64 *end;
 
                error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT,
                                       &indbh);
@@ -948,7 +952,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                        goto out;
                }
 
-               eablk = (u64 *)(indbh->b_data + mh_size);
+               eablk = (__be64 *)(indbh->b_data + mh_size);
                end = eablk + sdp->sd_inptrs;
 
                for (; eablk < end; eablk++)
@@ -971,11 +975,12 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
                gfs2_buffer_clear_tail(indbh, mh_size);
 
-               eablk = (u64 *)(indbh->b_data + mh_size);
+               eablk = (__be64 *)(indbh->b_data + mh_size);
                *eablk = cpu_to_be64(ip->i_di.di_eattr);
                ip->i_di.di_eattr = blk;
                ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
                ip->i_di.di_blocks++;
+               gfs2_set_inode_blocks(&ip->i_inode);
 
                eablk++;
        }
@@ -1129,9 +1134,9 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               ip->i_di.di_ctime = get_seconds();
+               ip->i_inode.i_ctime.tv_sec = get_seconds();
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -1202,7 +1207,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
        struct buffer_head **bh;
        unsigned int amount = GFS2_EA_DATA_LEN(ea);
        unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
-       u64 *dataptrs = GFS2_EA2DATAPTRS(ea);
+       __be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
        unsigned int x;
        int error;
 
@@ -1284,9 +1289,8 @@ int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el,
        if (!error) {
                error = inode_setattr(&ip->i_inode, attr);
                gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
-               gfs2_inode_attr_out(ip);
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -1300,7 +1304,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_rgrp_list rlist;
        struct buffer_head *indbh, *dibh;
-       u64 *eablk, *end;
+       __be64 *eablk, *end;
        unsigned int rg_blocks = 0;
        u64 bstart = 0;
        unsigned int blen = 0;
@@ -1319,7 +1323,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
                goto out;
        }
 
-       eablk = (u64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
+       eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
        end = eablk + sdp->sd_inptrs;
 
        for (; eablk < end; eablk++) {
@@ -1363,7 +1367,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
 
        gfs2_trans_add_bh(ip->i_gl, indbh, 1);
 
-       eablk = (u64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
+       eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
        bstart = 0;
        blen = 0;
 
@@ -1387,6 +1391,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
                if (!ip->i_di.di_blocks)
                        gfs2_consist_inode(ip);
                ip->i_di.di_blocks--;
+               gfs2_set_inode_blocks(&ip->i_inode);
        }
        if (bstart)
                gfs2_free_meta(ip, bstart, blen);
@@ -1396,7 +1401,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -1441,11 +1446,12 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
        if (!ip->i_di.di_blocks)
                gfs2_consist_inode(ip);
        ip->i_di.di_blocks--;
+       gfs2_set_inode_blocks(&ip->i_inode);
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
index ffa6594..c82dbe0 100644 (file)
@@ -19,7 +19,7 @@ struct iattr;
 #define GFS2_EA_SIZE(ea) \
 ALIGN(sizeof(struct gfs2_ea_header) + (ea)->ea_name_len + \
       ((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \
-                                  (sizeof(u64) * (ea)->ea_num_ptrs)), 8)
+                                  (sizeof(__be64) * (ea)->ea_num_ptrs)), 8)
 
 #define GFS2_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs)
 #define GFS2_EA_IS_LAST(ea) ((ea)->ea_flags & GFS2_EAFLAG_LAST)
@@ -29,13 +29,13 @@ ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + (er)->er_data_len, 8)
 
 #define GFS2_EAREQ_SIZE_UNSTUFFED(sdp, er) \
 ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + \
-      sizeof(u64) * DIV_ROUND_UP((er)->er_data_len, (sdp)->sd_jbsize), 8)
+      sizeof(__be64) * DIV_ROUND_UP((er)->er_data_len, (sdp)->sd_jbsize), 8)
 
 #define GFS2_EA2NAME(ea) ((char *)((struct gfs2_ea_header *)(ea) + 1))
 #define GFS2_EA2DATA(ea) (GFS2_EA2NAME(ea) + (ea)->ea_name_len)
 
 #define GFS2_EA2DATAPTRS(ea) \
-((u64 *)(GFS2_EA2NAME(ea) + ALIGN((ea)->ea_name_len, 8)))
+((__be64 *)(GFS2_EA2NAME(ea) + ALIGN((ea)->ea_name_len, 8)))
 
 #define GFS2_EA2NEXT(ea) \
 ((struct gfs2_ea_header *)((char *)(ea) + GFS2_EA_REC_LEN(ea)))
index 78fe0fa..4381469 100644 (file)
@@ -35,7 +35,7 @@
 
 struct greedy {
        struct gfs2_holder gr_gh;
-       struct work_struct gr_work;
+       struct delayed_work gr_work;
 };
 
 struct gfs2_gl_hash_bucket {
@@ -96,7 +96,7 @@ static inline rwlock_t *gl_lock_addr(unsigned int x)
        return &gl_hash_locks[x & (GL_HASH_LOCK_SZ-1)];
 }
 #else /* not SMP, so no spinlocks required */
-static inline rwlock_t *gl_lock_addr(x)
+static inline rwlock_t *gl_lock_addr(unsigned int x)
 {
        return NULL;
 }
@@ -769,7 +769,7 @@ restart:
        } else {
                spin_unlock(&gl->gl_spin);
 
-               new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_KERNEL);
+               new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_NOFS);
                if (!new_gh)
                        return;
                set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
@@ -785,21 +785,6 @@ out:
                gfs2_holder_put(new_gh);
 }
 
-void gfs2_glock_inode_squish(struct inode *inode)
-{
-       struct gfs2_holder gh;
-       struct gfs2_glock *gl = GFS2_I(inode)->i_gl;
-       gfs2_holder_init(gl, LM_ST_UNLOCKED, 0, &gh);
-       set_bit(HIF_DEMOTE, &gh.gh_iflags);
-       spin_lock(&gl->gl_spin);
-       gfs2_assert(inode->i_sb->s_fs_info, list_empty(&gl->gl_holders));
-       list_add_tail(&gh.gh_list, &gl->gl_waiters2);
-       run_queue(gl);
-       spin_unlock(&gl->gl_spin);
-       wait_for_completion(&gh.gh_wait);
-       gfs2_holder_uninit(&gh);
-}
-
 /**
  * state_change - record that the glock is now in a different state
  * @gl: the glock
@@ -847,12 +832,12 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
 
        if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
                if (glops->go_inval)
-                       glops->go_inval(gl, DIO_METADATA | DIO_DATA);
+                       glops->go_inval(gl, DIO_METADATA);
        } else if (gl->gl_state == LM_ST_DEFERRED) {
                /* We might not want to do this here.
                   Look at moving to the inode glops. */
                if (glops->go_inval)
-                       glops->go_inval(gl, DIO_DATA);
+                       glops->go_inval(gl, 0);
        }
 
        /*  Deal with each possible exit condition  */
@@ -954,7 +939,7 @@ void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
        gfs2_assert_warn(sdp, state != gl->gl_state);
 
        if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
-               glops->go_sync(gl, DIO_METADATA | DIO_DATA | DIO_RELEASE);
+               glops->go_sync(gl);
 
        gfs2_glock_hold(gl);
        gl->gl_req_bh = xmote_bh;
@@ -995,7 +980,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
        state_change(gl, LM_ST_UNLOCKED);
 
        if (glops->go_inval)
-               glops->go_inval(gl, DIO_METADATA | DIO_DATA);
+               glops->go_inval(gl, DIO_METADATA);
 
        if (gh) {
                spin_lock(&gl->gl_spin);
@@ -1041,7 +1026,7 @@ void gfs2_glock_drop_th(struct gfs2_glock *gl)
        gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
 
        if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
-               glops->go_sync(gl, DIO_METADATA | DIO_DATA | DIO_RELEASE);
+               glops->go_sync(gl);
 
        gfs2_glock_hold(gl);
        gl->gl_req_bh = drop_bh;
@@ -1244,9 +1229,6 @@ restart:
 
        clear_bit(GLF_PREFETCH, &gl->gl_flags);
 
-       if (error == GLR_TRYFAILED && (gh->gh_flags & GL_DUMP))
-               dump_glock(gl);
-
        return error;
 }
 
@@ -1368,9 +1350,9 @@ static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state,
        glops->go_xmote_th(gl, state, flags);
 }
 
-static void greedy_work(void *data)
+static void greedy_work(struct work_struct *work)
 {
-       struct greedy *gr = data;
+       struct greedy *gr = container_of(work, struct greedy, gr_work.work);
        struct gfs2_holder *gh = &gr->gr_gh;
        struct gfs2_glock *gl = gh->gh_gl;
        const struct gfs2_glock_operations *glops = gl->gl_ops;
@@ -1422,7 +1404,7 @@ int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time)
 
        gfs2_holder_init(gl, 0, 0, gh);
        set_bit(HIF_GREEDY, &gh->gh_iflags);
-       INIT_WORK(&gr->gr_work, greedy_work, gr);
+       INIT_DELAYED_WORK(&gr->gr_work, greedy_work);
 
        set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
        schedule_delayed_work(&gr->gr_work, time);
@@ -1923,7 +1905,7 @@ out:
 
 static void scan_glock(struct gfs2_glock *gl)
 {
-       if (gl->gl_ops == &gfs2_inode_glops)
+       if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object)
                return;
 
        if (gfs2_glmutex_trylock(gl)) {
@@ -2078,7 +2060,7 @@ static int dump_inode(struct gfs2_inode *ip)
        printk(KERN_INFO "    num = %llu %llu\n",
                    (unsigned long long)ip->i_num.no_formal_ino,
                    (unsigned long long)ip->i_num.no_addr);
-       printk(KERN_INFO "    type = %u\n", IF2DT(ip->i_di.di_mode));
+       printk(KERN_INFO "    type = %u\n", IF2DT(ip->i_inode.i_mode));
        printk(KERN_INFO "    i_flags =");
        for (x = 0; x < 32; x++)
                if (test_bit(x, &ip->i_flags))
index 2b2a889..fb39108 100644 (file)
@@ -27,8 +27,6 @@
 #define GL_ATIME               0x00000200
 #define GL_NOCACHE             0x00000400
 #define GL_NOCANCEL            0x00001000
-#define GL_AOP                 0x00004000
-#define GL_DUMP                        0x00008000
 
 #define GLR_TRYFAILED          13
 #define GLR_CANCELED           14
@@ -108,7 +106,6 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
 void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number,
                             const struct gfs2_glock_operations *glops,
                             unsigned int state, int flags);
-void gfs2_glock_inode_squish(struct inode *inode);
 
 /**
  * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
index 41a6b68..b068d10 100644 (file)
@@ -92,7 +92,7 @@ static void gfs2_pte_inval(struct gfs2_glock *gl)
 
        ip = gl->gl_object;
        inode = &ip->i_inode;
-       if (!ip || !S_ISREG(ip->i_di.di_mode))
+       if (!ip || !S_ISREG(inode->i_mode))
                return;
 
        if (!test_bit(GIF_PAGED, &ip->i_flags))
@@ -106,90 +106,21 @@ static void gfs2_pte_inval(struct gfs2_glock *gl)
        clear_bit(GIF_SW_PAGED, &ip->i_flags);
 }
 
-/**
- * gfs2_page_inval - Invalidate all pages associated with a glock
- * @gl: the glock
- *
- */
-
-static void gfs2_page_inval(struct gfs2_glock *gl)
-{
-       struct gfs2_inode *ip;
-       struct inode *inode;
-
-       ip = gl->gl_object;
-       inode = &ip->i_inode;
-       if (!ip || !S_ISREG(ip->i_di.di_mode))
-               return;
-
-       truncate_inode_pages(inode->i_mapping, 0);
-       gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
-       clear_bit(GIF_PAGED, &ip->i_flags);
-}
-
-/**
- * gfs2_page_wait - Wait for writeback of data
- * @gl: the glock
- *
- * Syncs data (not metadata) for a regular file.
- * No-op for all other types.
- */
-
-static void gfs2_page_wait(struct gfs2_glock *gl)
-{
-       struct gfs2_inode *ip = gl->gl_object;
-       struct inode *inode = &ip->i_inode;
-       struct address_space *mapping = inode->i_mapping;
-       int error;
-
-       if (!S_ISREG(ip->i_di.di_mode))
-               return;
-
-       error = filemap_fdatawait(mapping);
-
-       /* Put back any errors cleared by filemap_fdatawait()
-          so they can be caught by someone who can pass them
-          up to user space. */
-
-       if (error == -ENOSPC)
-               set_bit(AS_ENOSPC, &mapping->flags);
-       else if (error)
-               set_bit(AS_EIO, &mapping->flags);
-
-}
-
-static void gfs2_page_writeback(struct gfs2_glock *gl)
-{
-       struct gfs2_inode *ip = gl->gl_object;
-       struct inode *inode = &ip->i_inode;
-       struct address_space *mapping = inode->i_mapping;
-
-       if (!S_ISREG(ip->i_di.di_mode))
-               return;
-
-       filemap_fdatawrite(mapping);
-}
-
 /**
  * meta_go_sync - sync out the metadata for this glock
  * @gl: the glock
- * @flags: DIO_*
  *
  * Called when demoting or unlocking an EX glock.  We must flush
  * to disk all dirty buffers/pages relating to this glock, and must not
  * not return to caller to demote/unlock the glock until I/O is complete.
  */
 
-static void meta_go_sync(struct gfs2_glock *gl, int flags)
+static void meta_go_sync(struct gfs2_glock *gl)
 {
-       if (!(flags & DIO_METADATA))
-               return;
-
        if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
                gfs2_log_flush(gl->gl_sbd, gl);
                gfs2_meta_sync(gl);
-               if (flags & DIO_RELEASE)
-                       gfs2_ail_empty_gl(gl);
+               gfs2_ail_empty_gl(gl);
        }
 
 }
@@ -264,31 +195,31 @@ static void inode_go_drop_th(struct gfs2_glock *gl)
 /**
  * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
  * @gl: the glock protecting the inode
- * @flags:
  *
  */
 
-static void inode_go_sync(struct gfs2_glock *gl, int flags)
+static void inode_go_sync(struct gfs2_glock *gl)
 {
-       int meta = (flags & DIO_METADATA);
-       int data = (flags & DIO_DATA);
+       struct gfs2_inode *ip = gl->gl_object;
+
+       if (ip && !S_ISREG(ip->i_inode.i_mode))
+               ip = NULL;
 
        if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
-               if (meta && data) {
-                       gfs2_page_writeback(gl);
-                       gfs2_log_flush(gl->gl_sbd, gl);
-                       gfs2_meta_sync(gl);
-                       gfs2_page_wait(gl);
-                       clear_bit(GLF_DIRTY, &gl->gl_flags);
-               } else if (meta) {
-                       gfs2_log_flush(gl->gl_sbd, gl);
-                       gfs2_meta_sync(gl);
-               } else if (data) {
-                       gfs2_page_writeback(gl);
-                       gfs2_page_wait(gl);
+               gfs2_log_flush(gl->gl_sbd, gl);
+               if (ip)
+                       filemap_fdatawrite(ip->i_inode.i_mapping);
+               gfs2_meta_sync(gl);
+               if (ip) {
+                       struct address_space *mapping = ip->i_inode.i_mapping;
+                       int error = filemap_fdatawait(mapping);
+                       if (error == -ENOSPC)
+                               set_bit(AS_ENOSPC, &mapping->flags);
+                       else if (error)
+                               set_bit(AS_EIO, &mapping->flags);
                }
-               if (flags & DIO_RELEASE)
-                       gfs2_ail_empty_gl(gl);
+               clear_bit(GLF_DIRTY, &gl->gl_flags);
+               gfs2_ail_empty_gl(gl);
        }
 }
 
@@ -301,15 +232,20 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags)
 
 static void inode_go_inval(struct gfs2_glock *gl, int flags)
 {
+       struct gfs2_inode *ip = gl->gl_object;
        int meta = (flags & DIO_METADATA);
-       int data = (flags & DIO_DATA);
 
        if (meta) {
                gfs2_meta_inval(gl);
-               gl->gl_vn++;
+               if (ip)
+                       set_bit(GIF_INVALID, &ip->i_flags);
+       }
+
+       if (ip && S_ISREG(ip->i_inode.i_mode)) {
+               truncate_inode_pages(ip->i_inode.i_mapping, 0);
+               gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages);
+               clear_bit(GIF_PAGED, &ip->i_flags);
        }
-       if (data)
-               gfs2_page_inval(gl);
 }
 
 /**
@@ -351,11 +287,10 @@ static int inode_go_lock(struct gfs2_holder *gh)
        if (!ip)
                return 0;
 
-       if (ip->i_vn != gl->gl_vn) {
+       if (test_bit(GIF_INVALID, &ip->i_flags)) {
                error = gfs2_inode_refresh(ip);
                if (error)
                        return error;
-               gfs2_inode_attr_in(ip);
        }
 
        if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) &&
@@ -379,11 +314,8 @@ static void inode_go_unlock(struct gfs2_holder *gh)
        struct gfs2_glock *gl = gh->gh_gl;
        struct gfs2_inode *ip = gl->gl_object;
 
-       if (ip == NULL)
-               return;
-       if (test_bit(GLF_DIRTY, &gl->gl_flags))
-               gfs2_inode_attr_in(ip);
-       gfs2_meta_cache_flush(ip);
+       if (ip)
+               gfs2_meta_cache_flush(ip);
 }
 
 /**
@@ -491,13 +423,13 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
        struct gfs2_glock *j_gl = ip->i_gl;
-       struct gfs2_log_header head;
+       struct gfs2_log_header_host head;
        int error;
 
        if (gl->gl_state != LM_ST_UNLOCKED &&
            test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
                gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode));
-               j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);
+               j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
 
                error = gfs2_find_jhead(sdp->sd_jdesc, &head);
                if (error)
index 118dc69..734421e 100644 (file)
@@ -14,8 +14,6 @@
 
 #define DIO_WAIT       0x00000010
 #define DIO_METADATA   0x00000020
-#define DIO_DATA       0x00000040
-#define DIO_RELEASE    0x00000080
 #define DIO_ALL                0x00000100
 
 struct gfs2_log_operations;
@@ -41,7 +39,7 @@ struct gfs2_log_operations {
        void (*lo_before_commit) (struct gfs2_sbd *sdp);
        void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
        void (*lo_before_scan) (struct gfs2_jdesc *jd,
-                               struct gfs2_log_header *head, int pass);
+                               struct gfs2_log_header_host *head, int pass);
        int (*lo_scan_elements) (struct gfs2_jdesc *jd, unsigned int start,
                                 struct gfs2_log_descriptor *ld, __be64 *ptr,
                                 int pass);
@@ -67,8 +65,8 @@ struct gfs2_rgrpd {
        struct list_head rd_list_mru;
        struct list_head rd_recent;     /* Recently used rgrps */
        struct gfs2_glock *rd_gl;       /* Glock for this rgrp */
-       struct gfs2_rindex rd_ri;
-       struct gfs2_rgrp rd_rg;
+       struct gfs2_rindex_host rd_ri;
+       struct gfs2_rgrp_host rd_rg;
        u64 rd_rg_vn;
        struct gfs2_bitmap *rd_bits;
        unsigned int rd_bh_count;
@@ -103,18 +101,17 @@ struct gfs2_bufdata {
 };
 
 struct gfs2_glock_operations {
-       void (*go_xmote_th) (struct gfs2_glock * gl, unsigned int state,
-                            int flags);
-       void (*go_xmote_bh) (struct gfs2_glock * gl);
-       void (*go_drop_th) (struct gfs2_glock * gl);
-       void (*go_drop_bh) (struct gfs2_glock * gl);
-       void (*go_sync) (struct gfs2_glock * gl, int flags);
-       void (*go_inval) (struct gfs2_glock * gl, int flags);
-       int (*go_demote_ok) (struct gfs2_glock * gl);
-       int (*go_lock) (struct gfs2_holder * gh);
-       void (*go_unlock) (struct gfs2_holder * gh);
-       void (*go_callback) (struct gfs2_glock * gl, unsigned int state);
-       void (*go_greedy) (struct gfs2_glock * gl);
+       void (*go_xmote_th) (struct gfs2_glock *gl, unsigned int state, int flags);
+       void (*go_xmote_bh) (struct gfs2_glock *gl);
+       void (*go_drop_th) (struct gfs2_glock *gl);
+       void (*go_drop_bh) (struct gfs2_glock *gl);
+       void (*go_sync) (struct gfs2_glock *gl);
+       void (*go_inval) (struct gfs2_glock *gl, int flags);
+       int (*go_demote_ok) (struct gfs2_glock *gl);
+       int (*go_lock) (struct gfs2_holder *gh);
+       void (*go_unlock) (struct gfs2_holder *gh);
+       void (*go_callback) (struct gfs2_glock *gl, unsigned int state);
+       void (*go_greedy) (struct gfs2_glock *gl);
        const int go_type;
 };
 
@@ -217,6 +214,7 @@ struct gfs2_alloc {
 };
 
 enum {
+       GIF_INVALID             = 0,
        GIF_QD_LOCKED           = 1,
        GIF_PAGED               = 2,
        GIF_SW_PAGED            = 3,
@@ -224,12 +222,11 @@ enum {
 
 struct gfs2_inode {
        struct inode i_inode;
-       struct gfs2_inum i_num;
+       struct gfs2_inum_host i_num;
 
        unsigned long i_flags;          /* GIF_... */
 
-       u64 i_vn;
-       struct gfs2_dinode i_di; /* To be replaced by ref to block */
+       struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
 
        struct gfs2_glock *i_gl; /* Move into i_gh? */
        struct gfs2_holder i_iopen_gh;
@@ -450,7 +447,7 @@ struct gfs2_sbd {
        struct super_block *sd_vfs_meta;
        struct kobject sd_kobj;
        unsigned long sd_flags; /* SDF_... */
-       struct gfs2_sb sd_sb;
+       struct gfs2_sb_host sd_sb;
 
        /* Constants computed on mount */
 
@@ -503,8 +500,8 @@ struct gfs2_sbd {
 
        spinlock_t sd_statfs_spin;
        struct mutex sd_statfs_mutex;
-       struct gfs2_statfs_change sd_statfs_master;
-       struct gfs2_statfs_change sd_statfs_local;
+       struct gfs2_statfs_change_host sd_statfs_master;
+       struct gfs2_statfs_change_host sd_statfs_local;
        unsigned long sd_statfs_sync_time;
 
        /* Resource group stuff */
index d470e52..d122074 100644 (file)
 #include "trans.h"
 #include "util.h"
 
-/**
- * gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode
- * @ip: The GFS2 inode (with embedded disk inode data)
- * @inode:  The Linux VFS inode
- *
- */
-
-void gfs2_inode_attr_in(struct gfs2_inode *ip)
-{
-       struct inode *inode = &ip->i_inode;
-       struct gfs2_dinode *di = &ip->i_di;
-
-       inode->i_ino = ip->i_num.no_addr;
-
-       switch (di->di_mode & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
-               inode->i_rdev = MKDEV(di->di_major, di->di_minor);
-               break;
-       default:
-               inode->i_rdev = 0;
-               break;
-       };
-
-       inode->i_mode = di->di_mode;
-       inode->i_nlink = di->di_nlink;
-       inode->i_uid = di->di_uid;
-       inode->i_gid = di->di_gid;
-       i_size_write(inode, di->di_size);
-       inode->i_atime.tv_sec = di->di_atime;
-       inode->i_mtime.tv_sec = di->di_mtime;
-       inode->i_ctime.tv_sec = di->di_ctime;
-       inode->i_atime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
-       inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = di->di_blocks <<
-               (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
-
-       if (di->di_flags & GFS2_DIF_IMMUTABLE)
-               inode->i_flags |= S_IMMUTABLE;
-       else
-               inode->i_flags &= ~S_IMMUTABLE;
-
-       if (di->di_flags & GFS2_DIF_APPENDONLY)
-               inode->i_flags |= S_APPEND;
-       else
-               inode->i_flags &= ~S_APPEND;
-}
-
-/**
- * gfs2_inode_attr_out - Copy attributes from VFS inode into the dinode
- * @ip: The GFS2 inode
- *
- * Only copy out the attributes that we want the VFS layer
- * to be able to modify.
- */
-
-void gfs2_inode_attr_out(struct gfs2_inode *ip)
-{
-       struct inode *inode = &ip->i_inode;
-       struct gfs2_dinode *di = &ip->i_di;
-       gfs2_assert_withdraw(GFS2_SB(inode),
-               (di->di_mode & S_IFMT) == (inode->i_mode & S_IFMT));
-       di->di_mode = inode->i_mode;
-       di->di_uid = inode->i_uid;
-       di->di_gid = inode->i_gid;
-       di->di_atime = inode->i_atime.tv_sec;
-       di->di_mtime = inode->i_mtime.tv_sec;
-       di->di_ctime = inode->i_ctime.tv_sec;
-}
-
 static int iget_test(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_inum *inum = opaque;
+       struct gfs2_inum_host *inum = opaque;
 
-       if (ip && ip->i_num.no_addr == inum->no_addr)
+       if (ip->i_num.no_addr == inum->no_addr)
                return 1;
 
        return 0;
@@ -123,19 +52,20 @@ static int iget_test(struct inode *inode, void *opaque)
 static int iget_set(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_inum *inum = opaque;
+       struct gfs2_inum_host *inum = opaque;
 
        ip->i_num = *inum;
+       inode->i_ino = inum->no_addr;
        return 0;
 }
 
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum)
+struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
 {
        return ilookup5(sb, (unsigned long)inum->no_formal_ino,
                        iget_test, inum);
 }
 
-static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum)
+static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
 {
        return iget5_locked(sb, (unsigned long)inum->no_formal_ino,
                     iget_test, iget_set, inum);
@@ -150,7 +80,7 @@ static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum)
  * Returns: A VFS inode, or an error
  */
 
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
 {
        struct inode *inode = gfs2_iget(sb, inum);
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -188,7 +118,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum,
                if (unlikely(error))
                        goto fail_put;
 
-               ip->i_vn = ip->i_gl->gl_vn - 1;
+               set_bit(GIF_INVALID, &ip->i_flags);
                error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
                if (unlikely(error))
                        goto fail_iopen;
@@ -208,6 +138,63 @@ fail:
        return ERR_PTR(error);
 }
 
+static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+{
+       struct gfs2_dinode_host *di = &ip->i_di;
+       const struct gfs2_dinode *str = buf;
+
+       if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
+               if (gfs2_consist_inode(ip))
+                       gfs2_dinode_print(ip);
+               return -EIO;
+       }
+       if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
+               return -ESTALE;
+
+       ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
+       ip->i_inode.i_rdev = 0;
+       switch (ip->i_inode.i_mode & S_IFMT) {
+       case S_IFBLK:
+       case S_IFCHR:
+               ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major),
+                                          be32_to_cpu(str->di_minor));
+               break;
+       };
+
+       ip->i_inode.i_uid = be32_to_cpu(str->di_uid);
+       ip->i_inode.i_gid = be32_to_cpu(str->di_gid);
+       /*
+        * We will need to review setting the nlink count here in the
+        * light of the forthcoming ro bind mount work. This is a reminder
+        * to do that.
+        */
+       ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
+       di->di_size = be64_to_cpu(str->di_size);
+       i_size_write(&ip->i_inode, di->di_size);
+       di->di_blocks = be64_to_cpu(str->di_blocks);
+       gfs2_set_inode_blocks(&ip->i_inode);
+       ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
+       ip->i_inode.i_atime.tv_nsec = 0;
+       ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
+       ip->i_inode.i_mtime.tv_nsec = 0;
+       ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
+       ip->i_inode.i_ctime.tv_nsec = 0;
+
+       di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
+       di->di_goal_data = be64_to_cpu(str->di_goal_data);
+       di->di_generation = be64_to_cpu(str->di_generation);
+
+       di->di_flags = be32_to_cpu(str->di_flags);
+       gfs2_set_inode_flags(&ip->i_inode);
+       di->di_height = be16_to_cpu(str->di_height);
+
+       di->di_depth = be16_to_cpu(str->di_depth);
+       di->di_entries = be32_to_cpu(str->di_entries);
+
+       di->di_eattr = be64_to_cpu(str->di_eattr);
+       return 0;
+}
+
 /**
  * gfs2_inode_refresh - Refresh the incore copy of the dinode
  * @ip: The GFS2 inode
@@ -229,21 +216,11 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
                return -EIO;
        }
 
-       gfs2_dinode_in(&ip->i_di, dibh->b_data);
-
+       error = gfs2_dinode_in(ip, dibh->b_data);
        brelse(dibh);
+       clear_bit(GIF_INVALID, &ip->i_flags);
 
-       if (ip->i_num.no_addr != ip->i_di.di_num.no_addr) {
-               if (gfs2_consist_inode(ip))
-                       gfs2_dinode_print(&ip->i_di);
-               return -EIO;
-       }
-       if (ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino)
-               return -ESTALE;
-
-       ip->i_vn = ip->i_gl->gl_vn;
-
-       return 0;
+       return error;
 }
 
 int gfs2_dinode_dealloc(struct gfs2_inode *ip)
@@ -255,7 +232,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
 
        if (ip->i_di.di_blocks != 1) {
                if (gfs2_consist_inode(ip))
-                       gfs2_dinode_print(&ip->i_di);
+                       gfs2_dinode_print(ip);
                return -EIO;
        }
 
@@ -318,14 +295,14 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
        u32 nlink;
        int error;
 
-       BUG_ON(ip->i_di.di_nlink != ip->i_inode.i_nlink);
-       nlink = ip->i_di.di_nlink + diff;
+       BUG_ON(diff != 1 && diff != -1);
+       nlink = ip->i_inode.i_nlink + diff;
 
        /* If we are reducing the nlink count, but the new value ends up being
           bigger than the old one, we must have underflowed. */
-       if (diff < 0 && nlink > ip->i_di.di_nlink) {
+       if (diff < 0 && nlink > ip->i_inode.i_nlink) {
                if (gfs2_consist_inode(ip))
-                       gfs2_dinode_print(&ip->i_di);
+                       gfs2_dinode_print(ip);
                return -EIO;
        }
 
@@ -333,16 +310,19 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
        if (error)
                return error;
 
-       ip->i_di.di_nlink = nlink;
-       ip->i_di.di_ctime = get_seconds();
-       ip->i_inode.i_nlink = nlink;
+       if (diff > 0)
+               inc_nlink(&ip->i_inode);
+       else
+               drop_nlink(&ip->i_inode);
+
+       ip->i_inode.i_ctime.tv_sec = get_seconds();
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
        mark_inode_dirty(&ip->i_inode);
 
-       if (ip->i_di.di_nlink == 0) {
+       if (ip->i_inode.i_nlink == 0) {
                struct gfs2_rgrpd *rgd;
                struct gfs2_holder ri_gh, rg_gh;
 
@@ -357,7 +337,6 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
                if (error)
                        goto out_norgrp;
 
-               clear_nlink(&ip->i_inode);
                gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */
                gfs2_glock_dq_uninit(&rg_gh);
 out_norgrp:
@@ -394,7 +373,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
        struct super_block *sb = dir->i_sb;
        struct gfs2_inode *dip = GFS2_I(dir);
        struct gfs2_holder d_gh;
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        unsigned int type;
        int error = 0;
        struct inode *inode = NULL;
@@ -436,7 +415,7 @@ static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
 {
        struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
        struct buffer_head *bh;
-       struct gfs2_inum_range ir;
+       struct gfs2_inum_range_host ir;
        int error;
 
        error = gfs2_trans_begin(sdp, RES_DINODE, 0);
@@ -479,7 +458,7 @@ static int pick_formal_ino_2(struct gfs2_sbd *sdp, u64 *formal_ino)
        struct gfs2_inode *m_ip = GFS2_I(sdp->sd_inum_inode);
        struct gfs2_holder gh;
        struct buffer_head *bh;
-       struct gfs2_inum_range ir;
+       struct gfs2_inum_range_host ir;
        int error;
 
        error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
@@ -500,21 +479,22 @@ static int pick_formal_ino_2(struct gfs2_sbd *sdp, u64 *formal_ino)
        if (!ir.ir_length) {
                struct buffer_head *m_bh;
                u64 x, y;
+               __be64 z;
 
                error = gfs2_meta_inode_buffer(m_ip, &m_bh);
                if (error)
                        goto out_brelse;
 
-               x = *(u64 *)(m_bh->b_data + sizeof(struct gfs2_dinode));
-               x = y = be64_to_cpu(x);
+               z = *(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode));
+               x = y = be64_to_cpu(z);
                ir.ir_start = x;
                ir.ir_length = GFS2_INUM_QUANTUM;
                x += GFS2_INUM_QUANTUM;
                if (x < y)
                        gfs2_consist_inode(m_ip);
-               x = cpu_to_be64(x);
+               z = cpu_to_be64(x);
                gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);
-               *(u64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)) = x;
+               *(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)) = z;
 
                brelse(m_bh);
        }
@@ -567,7 +547,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
                return error;
 
        /*  Don't create entries in an unlinked directory  */
-       if (!dip->i_di.di_nlink)
+       if (!dip->i_inode.i_nlink)
                return -EPERM;
 
        error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
@@ -583,7 +563,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
 
        if (dip->i_di.di_entries == (u32)-1)
                return -EFBIG;
-       if (S_ISDIR(mode) && dip->i_di.di_nlink == (u32)-1)
+       if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1)
                return -EMLINK;
 
        return 0;
@@ -593,24 +573,24 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
                               unsigned int *uid, unsigned int *gid)
 {
        if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
-           (dip->i_di.di_mode & S_ISUID) && dip->i_di.di_uid) {
+           (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
                if (S_ISDIR(*mode))
                        *mode |= S_ISUID;
-               else if (dip->i_di.di_uid != current->fsuid)
+               else if (dip->i_inode.i_uid != current->fsuid)
                        *mode &= ~07111;
-               *uid = dip->i_di.di_uid;
+               *uid = dip->i_inode.i_uid;
        } else
                *uid = current->fsuid;
 
-       if (dip->i_di.di_mode & S_ISGID) {
+       if (dip->i_inode.i_mode & S_ISGID) {
                if (S_ISDIR(*mode))
                        *mode |= S_ISGID;
-               *gid = dip->i_di.di_gid;
+               *gid = dip->i_inode.i_gid;
        } else
                *gid = current->fsgid;
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum,
+static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
                        u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
@@ -650,9 +630,9 @@ out:
  */
 
 static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                       const struct gfs2_inum *inum, unsigned int mode,
+                       const struct gfs2_inum_host *inum, unsigned int mode,
                        unsigned int uid, unsigned int gid,
-                       const u64 *generation)
+                       const u64 *generation, dev_t dev)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_dinode *di;
@@ -669,14 +649,15 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        di->di_mode = cpu_to_be32(mode);
        di->di_uid = cpu_to_be32(uid);
        di->di_gid = cpu_to_be32(gid);
-       di->di_nlink = cpu_to_be32(0);
-       di->di_size = cpu_to_be64(0);
+       di->di_nlink = 0;
+       di->di_size = 0;
        di->di_blocks = cpu_to_be64(1);
        di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
-       di->di_major = di->di_minor = cpu_to_be32(0);
+       di->di_major = cpu_to_be32(MAJOR(dev));
+       di->di_minor = cpu_to_be32(MINOR(dev));
        di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
        di->di_generation = cpu_to_be64(*generation);
-       di->di_flags = cpu_to_be32(0);
+       di->di_flags = 0;
 
        if (S_ISREG(mode)) {
                if ((dip->i_di.di_flags & GFS2_DIF_INHERIT_JDATA) ||
@@ -693,22 +674,22 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        }
 
        di->__pad1 = 0;
-       di->di_payload_format = cpu_to_be32(0);
-       di->di_height = cpu_to_be32(0);
+       di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);
+       di->di_height = 0;
        di->__pad2 = 0;
        di->__pad3 = 0;
-       di->di_depth = cpu_to_be16(0);
-       di->di_entries = cpu_to_be32(0);
+       di->di_depth = 0;
+       di->di_entries = 0;
        memset(&di->__pad4, 0, sizeof(di->__pad4));
-       di->di_eattr = cpu_to_be64(0);
+       di->di_eattr = 0;
        memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
        brelse(dibh);
 }
 
 static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                      unsigned int mode, const struct gfs2_inum *inum,
-                      const u64 *generation)
+                      unsigned int mode, const struct gfs2_inum_host *inum,
+                      const u64 *generation, dev_t dev)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        unsigned int uid, gid;
@@ -729,7 +710,7 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        if (error)
                goto out_quota;
 
-       init_dinode(dip, gl, inum, mode, uid, gid, generation);
+       init_dinode(dip, gl, inum, mode, uid, gid, generation, dev);
        gfs2_quota_change(dip, +1, uid, gid);
        gfs2_trans_end(sdp);
 
@@ -759,8 +740,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
        if (alloc_required < 0)
                goto fail;
        if (alloc_required) {
-               error = gfs2_quota_check(dip, dip->i_di.di_uid,
-                                        dip->i_di.di_gid);
+               error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
                if (error)
                        goto fail_quota_locks;
 
@@ -782,16 +762,16 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
                        goto fail_quota_locks;
        }
 
-       error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_di.di_mode));
+       error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
        if (error)
                goto fail_end_trans;
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
                goto fail_end_trans;
-       ip->i_di.di_nlink = 1;
+       ip->i_inode.i_nlink = 1;
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
        return 0;
 
@@ -860,13 +840,13 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
  */
 
 struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
-                          unsigned int mode)
+                          unsigned int mode, dev_t dev)
 {
        struct inode *inode;
        struct gfs2_inode *dip = ghs->gh_gl->gl_object;
        struct inode *dir = &dip->i_inode;
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        int error;
        u64 generation;
 
@@ -890,35 +870,12 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
        if (error)
                goto fail_gunlock;
 
-       if (inum.no_addr < dip->i_num.no_addr) {
-               gfs2_glock_dq(ghs);
-
-               error = gfs2_glock_nq_num(sdp, inum.no_addr,
-                                         &gfs2_inode_glops, LM_ST_EXCLUSIVE,
-                                         GL_SKIP, ghs + 1);
-               if (error) {
-                       return ERR_PTR(error);
-               }
-
-               gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);
-               error = gfs2_glock_nq(ghs);
-               if (error) {
-                       gfs2_glock_dq_uninit(ghs + 1);
-                       return ERR_PTR(error);
-               }
-
-               error = create_ok(dip, name, mode);
-               if (error)
-                       goto fail_gunlock2;
-       } else {
-               error = gfs2_glock_nq_num(sdp, inum.no_addr,
-                                         &gfs2_inode_glops, LM_ST_EXCLUSIVE,
-                                         GL_SKIP, ghs + 1);
-               if (error)
-                       goto fail_gunlock;
-       }
+       error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,
+                                 LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       if (error)
+               goto fail_gunlock;
 
-       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation);
+       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev);
        if (error)
                goto fail_gunlock2;
 
@@ -975,7 +932,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 
        if (ip->i_di.di_entries != 2) {
                if (gfs2_consist_inode(ip))
-                       gfs2_dinode_print(&ip->i_di);
+                       gfs2_dinode_print(ip);
                return -EIO;
        }
 
@@ -997,7 +954,12 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
        if (error)
                return error;
 
-       error = gfs2_change_nlink(ip, -2);
+       /* It looks odd, but it really should be done twice */
+       error = gfs2_change_nlink(ip, -1);
+       if (error)
+               return error;
+
+       error = gfs2_change_nlink(ip, -1);
        if (error)
                return error;
 
@@ -1018,16 +980,16 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
                   struct gfs2_inode *ip)
 {
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        unsigned int type;
        int error;
 
        if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
                return -EPERM;
 
-       if ((dip->i_di.di_mode & S_ISVTX) &&
-           dip->i_di.di_uid != current->fsuid &&
-           ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER))
+       if ((dip->i_inode.i_mode & S_ISVTX) &&
+           dip->i_inode.i_uid != current->fsuid &&
+           ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))
                return -EPERM;
 
        if (IS_APPEND(&dip->i_inode))
@@ -1044,7 +1006,7 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
        if (!gfs2_inum_equal(&inum, &ip->i_num))
                return -ENOENT;
 
-       if (IF2DT(ip->i_di.di_mode) != type) {
+       if (IF2DT(ip->i_inode.i_mode) != type) {
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -1194,7 +1156,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
                return 0;
 
        curtime = get_seconds();
-       if (curtime - ip->i_di.di_atime >= quantum) {
+       if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
                gfs2_glock_dq(gh);
                gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
                                   gh);
@@ -1206,7 +1168,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
                   trying to get exclusive lock. */
 
                curtime = get_seconds();
-               if (curtime - ip->i_di.di_atime >= quantum) {
+               if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
                        struct buffer_head *dibh;
                        struct gfs2_dinode *di;
 
@@ -1220,11 +1182,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
                        if (error)
                                goto fail_end_trans;
 
-                       ip->i_di.di_atime = curtime;
+                       ip->i_inode.i_atime.tv_sec = curtime;
 
                        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                        di = (struct gfs2_dinode *)dibh->b_data;
-                       di->di_atime = cpu_to_be64(ip->i_di.di_atime);
+                       di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
                        brelse(dibh);
 
                        gfs2_trans_end(sdp);
@@ -1249,92 +1211,6 @@ fail:
        return error;
 }
 
-/**
- * glock_compare_atime - Compare two struct gfs2_glock structures for sort
- * @arg_a: the first structure
- * @arg_b: the second structure
- *
- * Returns: 1 if A > B
- *         -1 if A < B
- *          0 if A == B
- */
-
-static int glock_compare_atime(const void *arg_a, const void *arg_b)
-{
-       const struct gfs2_holder *gh_a = *(const struct gfs2_holder **)arg_a;
-       const struct gfs2_holder *gh_b = *(const struct gfs2_holder **)arg_b;
-       const struct lm_lockname *a = &gh_a->gh_gl->gl_name;
-       const struct lm_lockname *b = &gh_b->gh_gl->gl_name;
-
-       if (a->ln_number > b->ln_number)
-               return 1;
-       if (a->ln_number < b->ln_number)
-               return -1;
-       if (gh_a->gh_state == LM_ST_SHARED && gh_b->gh_state == LM_ST_EXCLUSIVE)
-               return 1;
-       if (gh_a->gh_state == LM_ST_SHARED && (gh_b->gh_flags & GL_ATIME))
-               return 1;
-
-       return 0;
-}
-
-/**
- * gfs2_glock_nq_m_atime - acquire multiple glocks where one may need an
- *      atime update
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs2_holder structures
- *
- * Returns: 0 on success (all glocks acquired),
- *          errno on failure (no glocks acquired)
- */
-
-int gfs2_glock_nq_m_atime(unsigned int num_gh, struct gfs2_holder *ghs)
-{
-       struct gfs2_holder **p;
-       unsigned int x;
-       int error = 0;
-
-       if (!num_gh)
-               return 0;
-
-       if (num_gh == 1) {
-               ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
-               if (ghs->gh_flags & GL_ATIME)
-                       error = gfs2_glock_nq_atime(ghs);
-               else
-                       error = gfs2_glock_nq(ghs);
-               return error;
-       }
-
-       p = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL);
-       if (!p)
-               return -ENOMEM;
-
-       for (x = 0; x < num_gh; x++)
-               p[x] = &ghs[x];
-
-       sort(p, num_gh, sizeof(struct gfs2_holder *), glock_compare_atime,NULL);
-
-       for (x = 0; x < num_gh; x++) {
-               p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
-
-               if (p[x]->gh_flags & GL_ATIME)
-                       error = gfs2_glock_nq_atime(p[x]);
-               else
-                       error = gfs2_glock_nq(p[x]);
-
-               if (error) {
-                       while (x--)
-                               gfs2_glock_dq(p[x]);
-                       break;
-               }
-       }
-
-       kfree(p);
-       return error;
-}
-
-
 static int
 __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
 {
@@ -1345,10 +1221,8 @@ __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
        if (!error) {
                error = inode_setattr(&ip->i_inode, attr);
                gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
-               gfs2_inode_attr_out(ip);
-
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
        return error;
index f5d8617..b57f448 100644 (file)
@@ -22,13 +22,19 @@ static inline int gfs2_is_jdata(struct gfs2_inode *ip)
 
 static inline int gfs2_is_dir(struct gfs2_inode *ip)
 {
-       return S_ISDIR(ip->i_di.di_mode);
+       return S_ISDIR(ip->i_inode.i_mode);
+}
+
+static inline void gfs2_set_inode_blocks(struct inode *inode)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       inode->i_blocks = ip->i_di.di_blocks <<
+               (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
 }
 
 void gfs2_inode_attr_in(struct gfs2_inode *ip);
-void gfs2_inode_attr_out(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned type);
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum);
+struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type);
+struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum);
 
 int gfs2_inode_refresh(struct gfs2_inode *ip);
 
@@ -37,19 +43,15 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff);
 struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
                           int is_root, struct nameidata *nd);
 struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
-                          unsigned int mode);
+                          unsigned int mode, dev_t dev);
 int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
                struct gfs2_inode *ip);
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
                   struct gfs2_inode *ip);
 int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
 int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
-
 int gfs2_glock_nq_atime(struct gfs2_holder *gh);
-int gfs2_glock_nq_m_atime(unsigned int num_gh, struct gfs2_holder *ghs);
-
 int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
-
 struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
 
 #endif /* __INODE_DOT_H__ */
index 0cace3d..291415d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
+#include <linux/delay.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -142,7 +143,7 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl
        return list_empty(&ai->ai_ail1_list);
 }
 
-void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
+static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
 {
        struct list_head *head = &sdp->sd_ail1_list;
        u64 sync_gen;
@@ -261,6 +262,12 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
  * @sdp: The GFS2 superblock
  * @blks: The number of blocks to reserve
  *
+ * Note that we never give out the last 6 blocks of the journal. Thats
+ * due to the fact that there is are a small number of header blocks
+ * associated with each log flush. The exact number can't be known until
+ * flush time, so we ensure that we have just enough free blocks at all
+ * times to avoid running out during a log flush.
+ *
  * Returns: errno
  */
 
@@ -274,7 +281,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
 
        mutex_lock(&sdp->sd_log_reserve_mutex);
        gfs2_log_lock(sdp);
-       while(sdp->sd_log_blks_free <= blks) {
+       while(sdp->sd_log_blks_free <= (blks + 6)) {
                gfs2_log_unlock(sdp);
                gfs2_ail1_empty(sdp, 0);
                gfs2_log_flush(sdp, NULL);
@@ -319,7 +326,8 @@ static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
        bh_map.b_size = 1 << inode->i_blkbits;
        error = gfs2_block_map(inode, lbn, 0, &bh_map);
        if (error || !bh_map.b_blocknr)
-               printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn);
+               printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error,
+                      (unsigned long long)bh_map.b_blocknr, lbn);
        gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
 
        return bh_map.b_blocknr;
@@ -643,12 +651,9 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
        up_read(&sdp->sd_log_flush_lock);
 
        gfs2_log_lock(sdp);
-       if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) {
-               gfs2_log_unlock(sdp);
-               gfs2_log_flush(sdp, NULL);
-       } else {
-               gfs2_log_unlock(sdp);
-       }
+       if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks))
+               wake_up_process(sdp->sd_logd_process);
+       gfs2_log_unlock(sdp);
 }
 
 /**
@@ -686,3 +691,21 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
        up_write(&sdp->sd_log_flush_lock);
 }
 
+
+/**
+ * gfs2_meta_syncfs - sync all the buffers in a filesystem
+ * @sdp: the filesystem
+ *
+ */
+
+void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
+{
+       gfs2_log_flush(sdp, NULL);
+       for (;;) {
+               gfs2_ail1_start(sdp, DIO_ALL);
+               if (gfs2_ail1_empty(sdp, DIO_ALL))
+                       break;
+               msleep(10);
+       }
+}
+
index 7f5737d..8e7aa0f 100644 (file)
@@ -48,7 +48,6 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
 unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
                            unsigned int ssize);
 
-void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags);
 int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags);
 
 int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
@@ -61,5 +60,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
 void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
 
 void gfs2_log_shutdown(struct gfs2_sbd *sdp);
+void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
 
 #endif /* __LOG_DOT_H__ */
index ab6d111..4d7f94d 100644 (file)
@@ -182,7 +182,7 @@ static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
 }
 
 static void buf_lo_before_scan(struct gfs2_jdesc *jd,
-                              struct gfs2_log_header *head, int pass)
+                              struct gfs2_log_header_host *head, int pass)
 {
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
 
@@ -328,7 +328,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 }
 
 static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
-                                 struct gfs2_log_header *head, int pass)
+                                 struct gfs2_log_header_host *head, int pass)
 {
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
 
@@ -509,7 +509,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
 {
        LIST_HEAD(started);
        struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
-       struct buffer_head *bh = NULL;
+       struct buffer_head *bh = NULL,*bh1 = NULL;
        unsigned int offset = sizeof(struct gfs2_log_descriptor);
        struct gfs2_log_descriptor *ld;
        unsigned int limit;
@@ -537,8 +537,13 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
                list_for_each_entry_safe_continue(bd1, bdt,
                                                  &sdp->sd_log_le_databuf,
                                                  bd_le.le_list) {
+                       /* store off the buffer head in a local ptr since
+                        * gfs2_bufdata might change when we drop the log lock
+                        */
+                       bh1 = bd1->bd_bh;
+
                        /* An ordered write buffer */
-                       if (bd1->bd_bh && !buffer_pinned(bd1->bd_bh)) {
+                       if (bh1 && !buffer_pinned(bh1)) {
                                list_move(&bd1->bd_le.le_list, &started);
                                if (bd1 == bd2) {
                                        bd2 = NULL;
@@ -547,20 +552,21 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
                                                        bd_le.le_list);
                                }
                                total_dbuf--;
-                               if (bd1->bd_bh) {
-                                       get_bh(bd1->bd_bh);
-                                       if (buffer_dirty(bd1->bd_bh)) {
+                               if (bh1) {
+                                       if (buffer_dirty(bh1)) {
+                                               get_bh(bh1);
+
                                                gfs2_log_unlock(sdp);
-                                               wait_on_buffer(bd1->bd_bh);
-                                               ll_rw_block(WRITE, 1,
-                                                           &bd1->bd_bh);
+
+                                               ll_rw_block(SWRITE, 1, &bh1);
+                                               brelse(bh1);
+
                                                gfs2_log_lock(sdp);
                                        }
-                                       brelse(bd1->bd_bh);
                                        continue;
                                }
                                continue;
-                       } else if (bd1->bd_bh) { /* A journaled buffer */
+                       } else if (bh1) { /* A journaled buffer */
                                int magic;
                                gfs2_log_unlock(sdp);
                                if (!bh) {
@@ -582,16 +588,16 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
                                        ld->ld_data2 = cpu_to_be32(0);
                                        memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
                                }
-                               magic = gfs2_check_magic(bd1->bd_bh);
-                               *ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr);
+                               magic = gfs2_check_magic(bh1);
+                               *ptr++ = cpu_to_be64(bh1->b_blocknr);
                                *ptr++ = cpu_to_be64((__u64)magic);
-                               clear_buffer_escaped(bd1->bd_bh);
+                               clear_buffer_escaped(bh1);
                                if (unlikely(magic != 0))
-                                       set_buffer_escaped(bd1->bd_bh);
+                                       set_buffer_escaped(bh1);
                                gfs2_log_lock(sdp);
                                if (n++ > num)
                                        break;
-                       } else if (!bd1->bd_bh) {
+                       } else if (!bh1) {
                                total_dbuf--;
                                sdp->sd_log_num_databuf--;
                                list_del_init(&bd1->bd_le.le_list);
index 5839c05..965bc65 100644 (file)
@@ -60,7 +60,7 @@ static inline void lops_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
 }
 
 static inline void lops_before_scan(struct gfs2_jdesc *jd,
-                                   struct gfs2_log_header *head,
+                                   struct gfs2_log_header_host *head,
                                    unsigned int pass)
 {
        int x;
index 9889c1e..7c1a9e2 100644 (file)
@@ -25,7 +25,7 @@
 #include "util.h"
 #include "glock.h"
 
-static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct gfs2_inode *ip = foo;
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
@@ -37,7 +37,7 @@ static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long
        }
 }
 
-static void gfs2_init_glock_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct gfs2_glock *gl = foo;
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
index 3912d6a..0e34d99 100644 (file)
@@ -127,17 +127,17 @@ void gfs2_meta_sync(struct gfs2_glock *gl)
 
 /**
  * getbuf - Get a buffer with a given address space
- * @sdp: the filesystem
- * @aspace: the address space
+ * @gl: the glock
  * @blkno: the block number (filesystem scope)
  * @create: 1 if the buffer should be created
  *
  * Returns: the buffer
  */
 
-static struct buffer_head *getbuf(struct gfs2_sbd *sdp, struct inode *aspace,
-                                 u64 blkno, int create)
+static struct buffer_head *getbuf(struct gfs2_glock *gl, u64 blkno, int create)
 {
+       struct address_space *mapping = gl->gl_aspace->i_mapping;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
        struct page *page;
        struct buffer_head *bh;
        unsigned int shift;
@@ -150,13 +150,13 @@ static struct buffer_head *getbuf(struct gfs2_sbd *sdp, struct inode *aspace,
 
        if (create) {
                for (;;) {
-                       page = grab_cache_page(aspace->i_mapping, index);
+                       page = grab_cache_page(mapping, index);
                        if (page)
                                break;
                        yield();
                }
        } else {
-               page = find_lock_page(aspace->i_mapping, index);
+               page = find_lock_page(mapping, index);
                if (!page)
                        return NULL;
        }
@@ -202,7 +202,7 @@ static void meta_prep_new(struct buffer_head *bh)
 struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
 {
        struct buffer_head *bh;
-       bh = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE);
+       bh = getbuf(gl, blkno, CREATE);
        meta_prep_new(bh);
        return bh;
 }
@@ -220,7 +220,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
 int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
                   struct buffer_head **bhp)
 {
-       *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE);
+       *bhp = getbuf(gl, blkno, CREATE);
        if (!buffer_uptodate(*bhp))
                ll_rw_block(READ_META, 1, bhp);
        if (flags & DIO_WAIT) {
@@ -379,11 +379,10 @@ void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
 void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct inode *aspace = ip->i_gl->gl_aspace;
        struct buffer_head *bh;
 
        while (blen) {
-               bh = getbuf(sdp, aspace, bstart, NO_CREATE);
+               bh = getbuf(ip->i_gl, bstart, NO_CREATE);
                if (bh) {
                        struct gfs2_bufdata *bd = bh->b_private;
 
@@ -472,6 +471,9 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
        struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height;
        int in_cache = 0;
 
+       BUG_ON(!gl);
+       BUG_ON(!sdp);
+
        spin_lock(&ip->i_spin);
        if (*bh_slot && (*bh_slot)->b_blocknr == num) {
                bh = *bh_slot;
@@ -481,7 +483,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
        spin_unlock(&ip->i_spin);
 
        if (!bh)
-               bh = getbuf(gl->gl_sbd, gl->gl_aspace, num, CREATE);
+               bh = getbuf(gl, num, CREATE);
 
        if (!bh)
                return -ENOBUFS;
@@ -532,7 +534,6 @@ err:
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
-       struct inode *aspace = gl->gl_aspace;
        struct buffer_head *first_bh, *bh;
        u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
                          sdp->sd_sb.sb_bsize_shift;
@@ -544,7 +545,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
        if (extlen > max_ra)
                extlen = max_ra;
 
-       first_bh = getbuf(sdp, aspace, dblock, CREATE);
+       first_bh = getbuf(gl, dblock, CREATE);
 
        if (buffer_uptodate(first_bh))
                goto out;
@@ -555,7 +556,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
        extlen--;
 
        while (extlen) {
-               bh = getbuf(sdp, aspace, dblock, CREATE);
+               bh = getbuf(gl, dblock, CREATE);
 
                if (!buffer_uptodate(bh) && !buffer_locked(bh))
                        ll_rw_block(READA, 1, &bh);
@@ -571,20 +572,3 @@ out:
        return first_bh;
 }
 
-/**
- * gfs2_meta_syncfs - sync all the buffers in a filesystem
- * @sdp: the filesystem
- *
- */
-
-void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
-{
-       gfs2_log_flush(sdp, NULL);
-       for (;;) {
-               gfs2_ail1_start(sdp, DIO_ALL);
-               if (gfs2_ail1_empty(sdp, DIO_ALL))
-                       break;
-               msleep(10);
-       }
-}
-
index 3ec939e..e037425 100644 (file)
@@ -67,7 +67,6 @@ static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
 }
 
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
-void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
 
 #define buffer_busy(bh) \
 ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned)))
index 1025960..f2495f1 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "gfs2.h"
 #include <linux/gfs2_ondisk.h>
+#include <linux/lm_interface.h>
+#include "incore.h"
 
 #define pv(struct, member, fmt) printk(KERN_INFO "  "#member" = "fmt"\n", \
                                       struct->member);
@@ -32,7 +34,7 @@
  * first arg: the cpu-order structure
  */
 
-void gfs2_inum_in(struct gfs2_inum *no, const void *buf)
+void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf)
 {
        const struct gfs2_inum *str = buf;
 
@@ -40,7 +42,7 @@ void gfs2_inum_in(struct gfs2_inum *no, const void *buf)
        no->no_addr = be64_to_cpu(str->no_addr);
 }
 
-void gfs2_inum_out(const struct gfs2_inum *no, void *buf)
+void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf)
 {
        struct gfs2_inum *str = buf;
 
@@ -48,13 +50,13 @@ void gfs2_inum_out(const struct gfs2_inum *no, void *buf)
        str->no_addr = cpu_to_be64(no->no_addr);
 }
 
-static void gfs2_inum_print(const struct gfs2_inum *no)
+static void gfs2_inum_print(const struct gfs2_inum_host *no)
 {
        printk(KERN_INFO "  no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino);
        printk(KERN_INFO "  no_addr = %llu\n", (unsigned long long)no->no_addr);
 }
 
-static void gfs2_meta_header_in(struct gfs2_meta_header *mh, const void *buf)
+static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf)
 {
        const struct gfs2_meta_header *str = buf;
 
@@ -63,23 +65,7 @@ static void gfs2_meta_header_in(struct gfs2_meta_header *mh, const void *buf)
        mh->mh_format = be32_to_cpu(str->mh_format);
 }
 
-static void gfs2_meta_header_out(const struct gfs2_meta_header *mh, void *buf)
-{
-       struct gfs2_meta_header *str = buf;
-
-       str->mh_magic = cpu_to_be32(mh->mh_magic);
-       str->mh_type = cpu_to_be32(mh->mh_type);
-       str->mh_format = cpu_to_be32(mh->mh_format);
-}
-
-static void gfs2_meta_header_print(const struct gfs2_meta_header *mh)
-{
-       pv(mh, mh_magic, "0x%.8X");
-       pv(mh, mh_type, "%u");
-       pv(mh, mh_format, "%u");
-}
-
-void gfs2_sb_in(struct gfs2_sb *sb, const void *buf)
+void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
 {
        const struct gfs2_sb *str = buf;
 
@@ -97,7 +83,7 @@ void gfs2_sb_in(struct gfs2_sb *sb, const void *buf)
        memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
 }
 
-void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf)
+void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf)
 {
        const struct gfs2_rindex *str = buf;
 
@@ -109,7 +95,7 @@ void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf)
 
 }
 
-void gfs2_rindex_print(const struct gfs2_rindex *ri)
+void gfs2_rindex_print(const struct gfs2_rindex_host *ri)
 {
        printk(KERN_INFO "  ri_addr = %llu\n", (unsigned long long)ri->ri_addr);
        pv(ri, ri_length, "%u");
@@ -120,22 +106,20 @@ void gfs2_rindex_print(const struct gfs2_rindex *ri)
        pv(ri, ri_bitbytes, "%u");
 }
 
-void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf)
+void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
 {
        const struct gfs2_rgrp *str = buf;
 
-       gfs2_meta_header_in(&rg->rg_header, buf);
        rg->rg_flags = be32_to_cpu(str->rg_flags);
        rg->rg_free = be32_to_cpu(str->rg_free);
        rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
        rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
 }
 
-void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf)
+void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
 {
        struct gfs2_rgrp *str = buf;
 
-       gfs2_meta_header_out(&rg->rg_header, buf);
        str->rg_flags = cpu_to_be32(rg->rg_flags);
        str->rg_free = cpu_to_be32(rg->rg_free);
        str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
@@ -144,7 +128,7 @@ void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf)
        memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
 }
 
-void gfs2_quota_in(struct gfs2_quota *qu, const void *buf)
+void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
 {
        const struct gfs2_quota *str = buf;
 
@@ -153,96 +137,56 @@ void gfs2_quota_in(struct gfs2_quota *qu, const void *buf)
        qu->qu_value = be64_to_cpu(str->qu_value);
 }
 
-void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf)
-{
-       const struct gfs2_dinode *str = buf;
-
-       gfs2_meta_header_in(&di->di_header, buf);
-       gfs2_inum_in(&di->di_num, &str->di_num);
-
-       di->di_mode = be32_to_cpu(str->di_mode);
-       di->di_uid = be32_to_cpu(str->di_uid);
-       di->di_gid = be32_to_cpu(str->di_gid);
-       di->di_nlink = be32_to_cpu(str->di_nlink);
-       di->di_size = be64_to_cpu(str->di_size);
-       di->di_blocks = be64_to_cpu(str->di_blocks);
-       di->di_atime = be64_to_cpu(str->di_atime);
-       di->di_mtime = be64_to_cpu(str->di_mtime);
-       di->di_ctime = be64_to_cpu(str->di_ctime);
-       di->di_major = be32_to_cpu(str->di_major);
-       di->di_minor = be32_to_cpu(str->di_minor);
-
-       di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
-       di->di_goal_data = be64_to_cpu(str->di_goal_data);
-       di->di_generation = be64_to_cpu(str->di_generation);
-
-       di->di_flags = be32_to_cpu(str->di_flags);
-       di->di_payload_format = be32_to_cpu(str->di_payload_format);
-       di->di_height = be16_to_cpu(str->di_height);
-
-       di->di_depth = be16_to_cpu(str->di_depth);
-       di->di_entries = be32_to_cpu(str->di_entries);
-
-       di->di_eattr = be64_to_cpu(str->di_eattr);
-
-}
-
-void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf)
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
 {
+       const struct gfs2_dinode_host *di = &ip->i_di;
        struct gfs2_dinode *str = buf;
 
-       gfs2_meta_header_out(&di->di_header, buf);
-       gfs2_inum_out(&di->di_num, (char *)&str->di_num);
+       str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
+       str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
+       str->di_header.__pad0 = 0;
+       str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
+       str->di_header.__pad1 = 0;
 
-       str->di_mode = cpu_to_be32(di->di_mode);
-       str->di_uid = cpu_to_be32(di->di_uid);
-       str->di_gid = cpu_to_be32(di->di_gid);
-       str->di_nlink = cpu_to_be32(di->di_nlink);
+       gfs2_inum_out(&ip->i_num, &str->di_num);
+
+       str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+       str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+       str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+       str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
        str->di_size = cpu_to_be64(di->di_size);
        str->di_blocks = cpu_to_be64(di->di_blocks);
-       str->di_atime = cpu_to_be64(di->di_atime);
-       str->di_mtime = cpu_to_be64(di->di_mtime);
-       str->di_ctime = cpu_to_be64(di->di_ctime);
-       str->di_major = cpu_to_be32(di->di_major);
-       str->di_minor = cpu_to_be32(di->di_minor);
+       str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+       str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+       str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
 
        str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
        str->di_goal_data = cpu_to_be64(di->di_goal_data);
        str->di_generation = cpu_to_be64(di->di_generation);
 
        str->di_flags = cpu_to_be32(di->di_flags);
-       str->di_payload_format = cpu_to_be32(di->di_payload_format);
        str->di_height = cpu_to_be16(di->di_height);
-
+       str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+                                            !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+                                            GFS2_FORMAT_DE : 0);
        str->di_depth = cpu_to_be16(di->di_depth);
        str->di_entries = cpu_to_be32(di->di_entries);
 
        str->di_eattr = cpu_to_be64(di->di_eattr);
-
 }
 
-void gfs2_dinode_print(const struct gfs2_dinode *di)
+void gfs2_dinode_print(const struct gfs2_inode *ip)
 {
-       gfs2_meta_header_print(&di->di_header);
-       gfs2_inum_print(&di->di_num);
+       const struct gfs2_dinode_host *di = &ip->i_di;
+
+       gfs2_inum_print(&ip->i_num);
 
-       pv(di, di_mode, "0%o");
-       pv(di, di_uid, "%u");
-       pv(di, di_gid, "%u");
-       pv(di, di_nlink, "%u");
        printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
        printk(KERN_INFO "  di_blocks = %llu\n", (unsigned long long)di->di_blocks);
-       printk(KERN_INFO "  di_atime = %lld\n", (long long)di->di_atime);
-       printk(KERN_INFO "  di_mtime = %lld\n", (long long)di->di_mtime);
-       printk(KERN_INFO "  di_ctime = %lld\n", (long long)di->di_ctime);
-       pv(di, di_major, "%u");
-       pv(di, di_minor, "%u");
-
        printk(KERN_INFO "  di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta);
        printk(KERN_INFO "  di_goal_data = %llu\n", (unsigned long long)di->di_goal_data);
 
        pv(di, di_flags, "0x%.8X");
-       pv(di, di_payload_format, "%u");
        pv(di, di_height, "%u");
 
        pv(di, di_depth, "%u");
@@ -251,7 +195,7 @@ void gfs2_dinode_print(const struct gfs2_dinode *di)
        printk(KERN_INFO "  di_eattr = %llu\n", (unsigned long long)di->di_eattr);
 }
 
-void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf)
+void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
 {
        const struct gfs2_log_header *str = buf;
 
@@ -263,7 +207,7 @@ void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf)
        lh->lh_hash = be32_to_cpu(str->lh_hash);
 }
 
-void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf)
+void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
 {
        const struct gfs2_inum_range *str = buf;
 
@@ -271,7 +215,7 @@ void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf)
        ir->ir_length = be64_to_cpu(str->ir_length);
 }
 
-void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf)
+void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
 {
        struct gfs2_inum_range *str = buf;
 
@@ -279,7 +223,7 @@ void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf)
        str->ir_length = cpu_to_be64(ir->ir_length);
 }
 
-void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf)
+void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
 {
        const struct gfs2_statfs_change *str = buf;
 
@@ -288,7 +232,7 @@ void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf)
        sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
 }
 
-void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf)
+void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
 {
        struct gfs2_statfs_change *str = buf;
 
@@ -297,7 +241,7 @@ void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf)
        str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
 }
 
-void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf)
+void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
 {
        const struct gfs2_quota_change *str = buf;
 
index 015640b..d8d69a7 100644 (file)
@@ -156,19 +156,6 @@ out_ignore:
        return 0;
 }
 
-static int zero_readpage(struct page *page)
-{
-       void *kaddr;
-
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr, 0, PAGE_CACHE_SIZE);
-       kunmap_atomic(kaddr, KM_USER0);
-
-       SetPageUptodate(page);
-
-       return 0;
-}
-
 /**
  * stuffed_readpage - Fill in a Linux page with stuffed file data
  * @ip: the inode
@@ -183,9 +170,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
        void *kaddr;
        int error;
 
-       /* Only the first page of a stuffed file might contain data */
-       if (unlikely(page->index))
-               return zero_readpage(page);
+       BUG_ON(page->index);
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
@@ -230,9 +215,9 @@ static int gfs2_readpage(struct file *file, struct page *page)
                                /* gfs2_sharewrite_nopage has grabbed the ip->i_gl already */
                                goto skip_lock;
                }
-               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh);
+               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
                do_unlock = 1;
-               error = gfs2_glock_nq_m_atime(1, &gh);
+               error = gfs2_glock_nq_atime(&gh);
                if (unlikely(error))
                        goto out_unlock;
        }
@@ -254,6 +239,8 @@ skip_lock:
 out:
        return error;
 out_unlock:
+       if (error == GLR_TRYFAILED)
+               error = AOP_TRUNCATED_PAGE;
        unlock_page(page);
        if (do_unlock)
                gfs2_holder_uninit(&gh);
@@ -293,9 +280,9 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
                                goto skip_lock;
                }
                gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
-                                LM_FLAG_TRY_1CB|GL_ATIME|GL_AOP, &gh);
+                                LM_FLAG_TRY_1CB|GL_ATIME, &gh);
                do_unlock = 1;
-               ret = gfs2_glock_nq_m_atime(1, &gh);
+               ret = gfs2_glock_nq_atime(&gh);
                if (ret == GLR_TRYFAILED)
                        goto out_noerror;
                if (unlikely(ret))
@@ -366,10 +353,13 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
        unsigned int write_len = to - from;
 
 
-       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|GL_AOP, &ip->i_gh);
-       error = gfs2_glock_nq_m_atime(1, &ip->i_gh);
-       if (error)
+       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh);
+       error = gfs2_glock_nq_atime(&ip->i_gh);
+       if (unlikely(error)) {
+               if (error == GLR_TRYFAILED)
+                       error = AOP_TRUNCATED_PAGE;
                goto out_uninit;
+       }
 
        gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks);
 
@@ -386,7 +376,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
                if (error)
                        goto out_alloc_put;
 
-               error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
+               error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
                if (error)
                        goto out_qunlock;
 
@@ -482,8 +472,10 @@ static int gfs2_commit_write(struct file *file, struct page *page,
 
                SetPageUptodate(page);
 
-               if (inode->i_size < file_size)
+               if (inode->i_size < file_size) {
                        i_size_write(inode, file_size);
+                       mark_inode_dirty(inode);
+               }
        } else {
                if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED ||
                    gfs2_is_jdata(ip))
@@ -498,11 +490,6 @@ static int gfs2_commit_write(struct file *file, struct page *page,
                di->di_size = cpu_to_be64(inode->i_size);
        }
 
-       di->di_mode = cpu_to_be32(inode->i_mode);
-       di->di_atime = cpu_to_be64(inode->i_atime.tv_sec);
-       di->di_mtime = cpu_to_be64(inode->i_mtime.tv_sec);
-       di->di_ctime = cpu_to_be64(inode->i_ctime.tv_sec);
-
        brelse(dibh);
        gfs2_trans_end(sdp);
        if (al->al_requested) {
@@ -624,7 +611,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
         * on this path. All we need change is atime.
         */
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-       rv = gfs2_glock_nq_m_atime(1, &gh);
+       rv = gfs2_glock_nq_atime(&gh);
        if (rv)
                goto out;
 
@@ -737,6 +724,9 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
                        if (!atomic_read(&aspace->i_writecount))
                                return 0;
 
+                       if (!(gfp_mask & __GFP_WAIT))
+                               return 0;
+
                        if (time_after_eq(jiffies, t)) {
                                stuck_releasepage(bh);
                                /* should we withdraw here? */
index 00041b1..d355899 100644 (file)
@@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
        struct inode *inode = dentry->d_inode;
        struct gfs2_holder d_gh;
        struct gfs2_inode *ip;
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        unsigned int type;
        int error;
 
@@ -76,7 +76,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
        if (!gfs2_inum_equal(&ip->i_num, &inum))
                goto invalid_gunlock;
 
-       if (IF2DT(ip->i_di.di_mode) != type) {
+       if (IF2DT(ip->i_inode.i_mode) != type) {
                gfs2_consist_inode(dip);
                goto fail_gunlock;
        }
index 86127d9..b4e7b87 100644 (file)
 #include "util.h"
 
 static struct dentry *gfs2_decode_fh(struct super_block *sb,
-                                    __u32 *fh,
+                                    __u32 *p,
                                     int fh_len,
                                     int fh_type,
                                     int (*acceptable)(void *context,
                                                       struct dentry *dentry),
                                     void *context)
 {
+       __be32 *fh = (__force __be32 *)p;
        struct gfs2_fh_obj fh_obj;
-       struct gfs2_inum *this, parent;
+       struct gfs2_inum_host *this, parent;
 
        if (fh_type != fh_len)
                return NULL;
@@ -65,9 +66,10 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb,
                                                    acceptable, context);
 }
 
-static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
+static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
                          int connectable)
 {
+       __be32 *fh = (__force __be32 *)p;
        struct inode *inode = dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -76,14 +78,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
            (connectable && *len < GFS2_LARGE_FH_SIZE))
                return 255;
 
-       fh[0] = ip->i_num.no_formal_ino >> 32;
-       fh[0] = cpu_to_be32(fh[0]);
-       fh[1] = ip->i_num.no_formal_ino & 0xFFFFFFFF;
-       fh[1] = cpu_to_be32(fh[1]);
-       fh[2] = ip->i_num.no_addr >> 32;
-       fh[2] = cpu_to_be32(fh[2]);
-       fh[3] = ip->i_num.no_addr & 0xFFFFFFFF;
-       fh[3] = cpu_to_be32(fh[3]);
+       fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
+       fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
+       fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32);
+       fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
        *len = GFS2_SMALL_FH_SIZE;
 
        if (!connectable || inode == sb->s_root->d_inode)
@@ -95,14 +93,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
        igrab(inode);
        spin_unlock(&dentry->d_lock);
 
-       fh[4] = ip->i_num.no_formal_ino >> 32;
-       fh[4] = cpu_to_be32(fh[4]);
-       fh[5] = ip->i_num.no_formal_ino & 0xFFFFFFFF;
-       fh[5] = cpu_to_be32(fh[5]);
-       fh[6] = ip->i_num.no_addr >> 32;
-       fh[6] = cpu_to_be32(fh[6]);
-       fh[7] = ip->i_num.no_addr & 0xFFFFFFFF;
-       fh[7] = cpu_to_be32(fh[7]);
+       fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
+       fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
+       fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32);
+       fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
 
        fh[8]  = cpu_to_be32(inode->i_mode);
        fh[9]  = 0;     /* pad to double word */
@@ -114,12 +108,12 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
 }
 
 struct get_name_filldir {
-       struct gfs2_inum inum;
+       struct gfs2_inum_host inum;
        char *name;
 };
 
 static int get_name_filldir(void *opaque, const char *name, unsigned int length,
-                           u64 offset, struct gfs2_inum *inum,
+                           u64 offset, struct gfs2_inum_host *inum,
                            unsigned int type)
 {
        struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque;
@@ -202,7 +196,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
-       struct gfs2_inum *inum = &fh_obj->this;
+       struct gfs2_inum_host *inum = &fh_obj->this;
        struct gfs2_holder i_gh, ri_gh, rgd_gh;
        struct gfs2_rgrpd *rgd;
        struct inode *inode;
index 09aca50..f925a95 100644 (file)
@@ -15,7 +15,7 @@
 
 extern struct export_operations gfs2_export_ops;
 struct gfs2_fh_obj {
-       struct gfs2_inum this;
+       struct gfs2_inum_host this;
        __u32            imode;
 };
 
index 3064f13..faa07e4 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
+#include <linux/writeback.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -71,7 +72,7 @@ static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
                size = count;
 
        kaddr = kmap(page);
-       memcpy(desc->arg.buf, kaddr + offset, size);
+       memcpy(desc->arg.data, kaddr + offset, size);
        kunmap(page);
 
        desc->count = count - size;
@@ -86,7 +87,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
        struct inode *inode = &ip->i_inode;
        read_descriptor_t desc;
        desc.written = 0;
-       desc.arg.buf = buf;
+       desc.arg.data = buf;
        desc.count = size;
        desc.error = 0;
        do_generic_mapping_read(inode->i_mapping, ra_state,
@@ -139,7 +140,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
  */
 
 static int filldir_func(void *opaque, const char *name, unsigned int length,
-                       u64 offset, struct gfs2_inum *inum,
+                       u64 offset, struct gfs2_inum_host *inum,
                        unsigned int type)
 {
        struct filldir_reg *fdr = (struct filldir_reg *)opaque;
@@ -246,14 +247,14 @@ static const u32 gfs2_to_fsflags[32] = {
 
 static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
        u32 fsflags;
 
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-       error = gfs2_glock_nq_m_atime(1, &gh);
+       error = gfs2_glock_nq_atime(&gh);
        if (error)
                return error;
 
@@ -266,6 +267,24 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
        return error;
 }
 
+void gfs2_set_inode_flags(struct inode *inode)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_dinode_host *di = &ip->i_di;
+       unsigned int flags = inode->i_flags;
+
+       flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+       if (di->di_flags & GFS2_DIF_IMMUTABLE)
+               flags |= S_IMMUTABLE;
+       if (di->di_flags & GFS2_DIF_APPENDONLY)
+               flags |= S_APPEND;
+       if (di->di_flags & GFS2_DIF_NOATIME)
+               flags |= S_NOATIME;
+       if (di->di_flags & GFS2_DIF_SYNC)
+               flags |= S_SYNC;
+       inode->i_flags = flags;
+}
+
 /* Flags that can be set by user space */
 #define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA|                   \
                             GFS2_DIF_DIRECTIO|                 \
@@ -286,7 +305,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
  */
 static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *bh;
@@ -336,8 +355,9 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
                goto out_trans_end;
        gfs2_trans_add_bh(ip->i_gl, bh, 1);
        ip->i_di.di_flags = new_flags;
-       gfs2_dinode_out(&ip->i_di, bh->b_data);
+       gfs2_dinode_out(ip, bh->b_data);
        brelse(bh);
+       gfs2_set_inode_flags(inode);
 out_trans_end:
        gfs2_trans_end(sdp);
 out:
@@ -425,7 +445,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
        gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
        file->private_data = fp;
 
-       if (S_ISREG(ip->i_di.di_mode)) {
+       if (S_ISREG(ip->i_inode.i_mode)) {
                error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
                                           &i_gh);
                if (error)
@@ -484,16 +504,40 @@ static int gfs2_close(struct inode *inode, struct file *file)
  * @file: the file that points to the dentry (we ignore this)
  * @dentry: the dentry that points to the inode to sync
  *
+ * The VFS will flush "normal" data for us. We only need to worry
+ * about metadata here. For journaled data, we just do a log flush
+ * as we can't avoid it. Otherwise we can just bale out if datasync
+ * is set. For stuffed inodes we must flush the log in order to
+ * ensure that all data is on disk.
+ *
+ * The call to write_inode_now() is there to write back metadata and
+ * the inode itself. It does also try and write the data, but thats
+ * (hopefully) a no-op due to the VFS having already called filemap_fdatawrite()
+ * for us.
+ *
  * Returns: errno
  */
 
 static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+       struct inode *inode = dentry->d_inode;
+       int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
+       int ret = 0;
 
-       gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
+       if (gfs2_is_jdata(GFS2_I(inode))) {
+               gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl);
+               return 0;
+       }
 
-       return 0;
+       if (sync_state != 0) {
+               if (!datasync)
+                       ret = write_inode_now(inode, 0);
+
+               if (gfs2_is_stuffed(GFS2_I(inode)))
+                       gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl);
+       }
+
+       return ret;
 }
 
 /**
@@ -515,7 +559,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 
        if (!(fl->fl_flags & FL_POSIX))
                return -ENOLCK;
-       if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+       if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
                return -ENOLCK;
 
        if (sdp->sd_args.ar_localflocks) {
@@ -544,7 +588,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
 {
        struct gfs2_file *fp = file->private_data;
        struct gfs2_holder *fl_gh = &fp->f_fl_gh;
-       struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
+       struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode);
        struct gfs2_glock *gl;
        unsigned int state;
        int flags;
@@ -617,7 +661,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
 
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
-       if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+       if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
                return -ENOLCK;
 
        if (sdp->sd_args.ar_localflocks)
index ce319f8..7e5d8ec 100644 (file)
@@ -17,7 +17,7 @@ extern struct file gfs2_internal_file_sentinel;
 extern int gfs2_internal_read(struct gfs2_inode *ip,
                              struct file_ra_state *ra_state,
                              char *buf, loff_t *pos, unsigned size);
-
+extern void gfs2_set_inode_flags(struct inode *inode);
 extern const struct file_operations gfs2_file_fops;
 extern const struct file_operations gfs2_dir_fops;
 
index 882873a..d14e139 100644 (file)
@@ -237,7 +237,7 @@ fail:
 }
 
 static struct inode *gfs2_lookup_root(struct super_block *sb,
-                                     struct gfs2_inum *inum)
+                                     struct gfs2_inum_host *inum)
 {
        return gfs2_inode_lookup(sb, inum, DT_DIR);
 }
@@ -246,7 +246,7 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 {
        struct super_block *sb = sdp->sd_vfs;
        struct gfs2_holder sb_gh;
-       struct gfs2_inum *inum;
+       struct gfs2_inum_host *inum;
        struct inode *inode;
        int error = 0;
 
index ef6e5ed..636dda4 100644 (file)
@@ -59,7 +59,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
        for (;;) {
-               inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode);
+               inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0);
                if (!IS_ERR(inode)) {
                        gfs2_trans_end(sdp);
                        if (dip->i_alloc.al_rgd)
@@ -144,7 +144,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        int alloc_required;
        int error;
 
-       if (S_ISDIR(ip->i_di.di_mode))
+       if (S_ISDIR(inode->i_mode))
                return -EPERM;
 
        gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
@@ -169,7 +169,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        error = -EINVAL;
-       if (!dip->i_di.di_nlink)
+       if (!dip->i_inode.i_nlink)
                goto out_gunlock;
        error = -EFBIG;
        if (dip->i_di.di_entries == (u32)-1)
@@ -178,10 +178,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto out_gunlock;
        error = -EINVAL;
-       if (!ip->i_di.di_nlink)
+       if (!ip->i_inode.i_nlink)
                goto out_gunlock;
        error = -EMLINK;
-       if (ip->i_di.di_nlink == (u32)-1)
+       if (ip->i_inode.i_nlink == (u32)-1)
                goto out_gunlock;
 
        alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
@@ -196,8 +196,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
                if (error)
                        goto out_alloc;
 
-               error = gfs2_quota_check(dip, dip->i_di.di_uid,
-                                        dip->i_di.di_gid);
+               error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
                if (error)
                        goto out_gunlock_q;
 
@@ -220,7 +219,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
-                            IF2DT(ip->i_di.di_mode));
+                            IF2DT(inode->i_mode));
        if (error)
                goto out_end_trans;
 
@@ -326,7 +325,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO);
+       inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
@@ -339,7 +338,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
        error = gfs2_meta_inode_buffer(ip, &dibh);
 
        if (!gfs2_assert_withdraw(sdp, !error)) {
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname,
                       size);
                brelse(dibh);
@@ -379,7 +378,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode);
+       inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
@@ -387,10 +386,9 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        ip = ghs[1].gh_gl->gl_object;
 
-       ip->i_di.di_nlink = 2;
+       ip->i_inode.i_nlink = 2;
        ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
        ip->i_di.di_flags |= GFS2_DIF_JDATA;
-       ip->i_di.di_payload_format = GFS2_FORMAT_DE;
        ip->i_di.di_entries = 2;
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -414,7 +412,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                gfs2_inum_out(&dip->i_num, &dent->de_inum);
                dent->de_type = cpu_to_be16(DT_DIR);
 
-               gfs2_dinode_out(&ip->i_di, di);
+               gfs2_dinode_out(ip, di);
 
                brelse(dibh);
        }
@@ -467,7 +465,7 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
 
        if (ip->i_di.di_entries < 2) {
                if (gfs2_consist_inode(ip))
-                       gfs2_dinode_print(&ip->i_di);
+                       gfs2_dinode_print(ip);
                error = -EIO;
                goto out_gunlock;
        }
@@ -504,47 +502,19 @@ out:
 static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
                      dev_t dev)
 {
-       struct gfs2_inode *dip = GFS2_I(dir), *ip;
+       struct gfs2_inode *dip = GFS2_I(dir);
        struct gfs2_sbd *sdp = GFS2_SB(dir);
        struct gfs2_holder ghs[2];
        struct inode *inode;
-       struct buffer_head *dibh;
-       u32 major = 0, minor = 0;
-       int error;
-
-       switch (mode & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
-               major = MAJOR(dev);
-               minor = MINOR(dev);
-               break;
-       case S_IFIFO:
-       case S_IFSOCK:
-               break;
-       default:
-               return -EOPNOTSUPP;
-       };
 
        gfs2_holder_init(dip->i_gl, 0, 0, ghs);
 
-       inode = gfs2_createi(ghs, &dentry->d_name, mode);
+       inode = gfs2_createi(ghs, &dentry->d_name, mode, dev);
        if (IS_ERR(inode)) {
                gfs2_holder_uninit(ghs);
                return PTR_ERR(inode);
        }
 
-       ip = ghs[1].gh_gl->gl_object;
-
-       ip->i_di.di_major = major;
-       ip->i_di.di_minor = minor;
-
-       error = gfs2_meta_inode_buffer(ip, &dibh);
-
-       if (!gfs2_assert_withdraw(sdp, !error)) {
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
-               brelse(dibh);
-       }
-
        gfs2_trans_end(sdp);
        if (dip->i_alloc.al_rgd)
                gfs2_inplace_release(dip);
@@ -592,11 +562,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 
        /* Make sure we aren't trying to move a dirctory into it's subdir */
 
-       if (S_ISDIR(ip->i_di.di_mode) && odip != ndip) {
+       if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) {
                dir_rename = 1;
 
-               error = gfs2_glock_nq_init(sdp->sd_rename_gl,
-                                          LM_ST_EXCLUSIVE, 0,
+               error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0,
                                           &r_gh);
                if (error)
                        goto out;
@@ -637,10 +606,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                if (error)
                        goto out_gunlock;
 
-               if (S_ISDIR(nip->i_di.di_mode)) {
+               if (S_ISDIR(nip->i_inode.i_mode)) {
                        if (nip->i_di.di_entries < 2) {
                                if (gfs2_consist_inode(nip))
-                                       gfs2_dinode_print(&nip->i_di);
+                                       gfs2_dinode_print(nip);
                                error = -EIO;
                                goto out_gunlock;
                        }
@@ -666,7 +635,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                };
 
                if (odip != ndip) {
-                       if (!ndip->i_di.di_nlink) {
+                       if (!ndip->i_inode.i_nlink) {
                                error = -EINVAL;
                                goto out_gunlock;
                        }
@@ -674,8 +643,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                                error = -EFBIG;
                                goto out_gunlock;
                        }
-                       if (S_ISDIR(ip->i_di.di_mode) &&
-                           ndip->i_di.di_nlink == (u32)-1) {
+                       if (S_ISDIR(ip->i_inode.i_mode) &&
+                           ndip->i_inode.i_nlink == (u32)-1) {
                                error = -EMLINK;
                                goto out_gunlock;
                        }
@@ -702,8 +671,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                if (error)
                        goto out_alloc;
 
-               error = gfs2_quota_check(ndip, ndip->i_di.di_uid,
-                                        ndip->i_di.di_gid);
+               error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid);
                if (error)
                        goto out_gunlock_q;
 
@@ -729,7 +697,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        /* Remove the target file, if it exists */
 
        if (nip) {
-               if (S_ISDIR(nip->i_di.di_mode))
+               if (S_ISDIR(nip->i_inode.i_mode))
                        error = gfs2_rmdiri(ndip, &ndentry->d_name, nip);
                else {
                        error = gfs2_dir_del(ndip, &ndentry->d_name);
@@ -760,9 +728,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                error = gfs2_meta_inode_buffer(ip, &dibh);
                if (error)
                        goto out_end_trans;
-               ip->i_di.di_ctime = get_seconds();
+               ip->i_inode.i_ctime.tv_sec = get_seconds();
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-               gfs2_dinode_out(&ip->i_di, dibh->b_data);
+               gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
 
@@ -771,7 +739,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                goto out_end_trans;
 
        error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
-                            IF2DT(ip->i_di.di_mode));
+                            IF2DT(ip->i_inode.i_mode));
        if (error)
                goto out_end_trans;
 
@@ -867,6 +835,10 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
  * @mask:
  * @nd: passed from Linux VFS, ignored by us
  *
+ * This may be called from the VFS directly, or from within GFS2 with the
+ * inode locked, so we look to see if the glock is already locked and only
+ * lock the glock if its not already been done.
+ *
  * Returns: errno
  */
 
@@ -875,15 +847,18 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder i_gh;
        int error;
+       int unlock = 0;
 
-       if (ip->i_vn == ip->i_gl->gl_vn)
-               return generic_permission(inode, mask, gfs2_check_acl);
+       if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+               if (error)
+                       return error;
+               unlock = 1;
+       }
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-       if (!error) {
-               error = generic_permission(inode, mask, gfs2_check_acl_locked);
+       error = generic_permission(inode, mask, gfs2_check_acl);
+       if (unlock)
                gfs2_glock_dq_uninit(&i_gh);
-       }
 
        return error;
 }
@@ -914,8 +889,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
        u32 ouid, ogid, nuid, ngid;
        int error;
 
-       ouid = ip->i_di.di_uid;
-       ogid = ip->i_di.di_gid;
+       ouid = inode->i_uid;
+       ogid = inode->i_gid;
        nuid = attr->ia_uid;
        ngid = attr->ia_gid;
 
@@ -946,10 +921,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
 
        error = inode_setattr(inode, attr);
        gfs2_assert_warn(sdp, !error);
-       gfs2_inode_attr_out(ip);
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(&ip->i_di, dibh->b_data);
+       gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
        if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
@@ -1018,6 +992,12 @@ out:
  * @dentry: The dentry to stat
  * @stat: The inode's stats
  *
+ * This may be called from the VFS directly, or from within GFS2 with the
+ * inode locked, so we look to see if the glock is already locked and only
+ * lock the glock if its not already been done. Note that its the NFS
+ * readdirplus operation which causes this to be called (from filldir)
+ * with the glock already held.
+ *
  * Returns: errno
  */
 
@@ -1028,14 +1008,20 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
+       int unlock = 0;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
-       if (!error) {
-               generic_fillattr(inode, stat);
-               gfs2_glock_dq_uninit(&gh);
+       if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
+               if (error)
+                       return error;
+               unlock = 1;
        }
 
-       return error;
+       generic_fillattr(inode, stat);
+       if (unlock);
+               gfs2_glock_dq_uninit(&gh);
+
+       return 0;
 }
 
 static int gfs2_setxattr(struct dentry *dentry, const char *name,
index b47d959..7685b46 100644 (file)
@@ -157,7 +157,8 @@ static void gfs2_write_super(struct super_block *sb)
 static int gfs2_sync_fs(struct super_block *sb, int wait)
 {
        sb->s_dirt = 0;
-       gfs2_log_flush(sb->s_fs_info, NULL);
+       if (wait)
+               gfs2_log_flush(sb->s_fs_info, NULL);
        return 0;
 }
 
@@ -215,7 +216,7 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_inode->i_sb;
        struct gfs2_sbd *sdp = sb->s_fs_info;
-       struct gfs2_statfs_change sc;
+       struct gfs2_statfs_change_host sc;
        int error;
 
        if (gfs2_tune_get(sdp, gt_statfs_slow))
@@ -293,8 +294,6 @@ static void gfs2_clear_inode(struct inode *inode)
         */
        if (inode->i_private) {
                struct gfs2_inode *ip = GFS2_I(inode);
-               gfs2_glock_inode_squish(inode);
-               gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED);
                ip->i_gl->gl_object = NULL;
                gfs2_glock_schedule_for_reclaim(ip->i_gl);
                gfs2_glock_put(ip->i_gl);
@@ -395,7 +394,7 @@ static void gfs2_delete_inode(struct inode *inode)
        if (!inode->i_private)
                goto out;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh);
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
        if (unlikely(error)) {
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
                goto out;
@@ -407,7 +406,7 @@ static void gfs2_delete_inode(struct inode *inode)
        if (error)
                goto out_uninit;
 
-       if (S_ISDIR(ip->i_di.di_mode) &&
+       if (S_ISDIR(inode->i_mode) &&
            (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
                error = gfs2_dir_exhash_dealloc(ip);
                if (error)
index 5453d29..45a5f11 100644 (file)
@@ -76,7 +76,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
        if (error)
                goto out;
 
-       error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
+       error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
        if (error)
                goto out_gunlock_q;
 
index a3deae7..d0db881 100644 (file)
@@ -452,19 +452,19 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
        if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
                return 0;
 
-       error = qdsb_get(sdp, QUOTA_USER, ip->i_di.di_uid, CREATE, qd);
+       error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, CREATE, qd);
        if (error)
                goto out;
        al->al_qd_num++;
        qd++;
 
-       error = qdsb_get(sdp, QUOTA_GROUP, ip->i_di.di_gid, CREATE, qd);
+       error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, CREATE, qd);
        if (error)
                goto out;
        al->al_qd_num++;
        qd++;
 
-       if (uid != NO_QUOTA_CHANGE && uid != ip->i_di.di_uid) {
+       if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) {
                error = qdsb_get(sdp, QUOTA_USER, uid, CREATE, qd);
                if (error)
                        goto out;
@@ -472,7 +472,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
                qd++;
        }
 
-       if (gid != NO_QUOTA_CHANGE && gid != ip->i_di.di_gid) {
+       if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) {
                error = qdsb_get(sdp, QUOTA_GROUP, gid, CREATE, qd);
                if (error)
                        goto out;
@@ -539,8 +539,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
                qc->qc_id = cpu_to_be32(qd->qd_id);
        }
 
-       x = qc->qc_change;
-       x = be64_to_cpu(x) + change;
+       x = be64_to_cpu(qc->qc_change) + change;
        qc->qc_change = cpu_to_be64(x);
 
        spin_lock(&sdp->sd_quota_spin);
@@ -743,7 +742,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
        struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
        struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
        struct gfs2_holder i_gh;
-       struct gfs2_quota q;
+       struct gfs2_quota_host q;
        char buf[sizeof(struct gfs2_quota)];
        struct file_ra_state ra_state;
        int error;
@@ -1103,7 +1102,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
 
                for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
                     y++, slot++) {
-                       struct gfs2_quota_change qc;
+                       struct gfs2_quota_change_host qc;
                        struct gfs2_quota_data *qd;
 
                        gfs2_quota_change_in(&qc, bh->b_data +
index 62cd223..d0c806b 100644 (file)
@@ -132,10 +132,11 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp)
  */
 
 static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
-                         struct gfs2_log_header *head)
+                         struct gfs2_log_header_host *head)
 {
        struct buffer_head *bh;
-       struct gfs2_log_header lh;
+       struct gfs2_log_header_host lh;
+       const u32 nothing = 0;
        u32 hash;
        int error;
 
@@ -143,11 +144,11 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
        if (error)
                return error;
 
-       memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header));
-       lh.lh_hash = 0;
-       hash = gfs2_disk_hash((char *)&lh, sizeof(struct gfs2_log_header));
+       hash = crc32_le((u32)~0, bh->b_data, sizeof(struct gfs2_log_header) -
+                                            sizeof(u32));
+       hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
+       hash ^= (u32)~0;
        gfs2_log_header_in(&lh, bh->b_data);
-
        brelse(bh);
 
        if (lh.lh_header.mh_magic != GFS2_MAGIC ||
@@ -174,7 +175,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
  */
 
 static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
-                       struct gfs2_log_header *head)
+                       struct gfs2_log_header_host *head)
 {
        unsigned int orig_blk = *blk;
        int error;
@@ -205,10 +206,10 @@ static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
  * Returns: errno
  */
 
-static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
+static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
 {
        unsigned int blk = head->lh_blkno;
-       struct gfs2_log_header lh;
+       struct gfs2_log_header_host lh;
        int error;
 
        for (;;) {
@@ -245,9 +246,9 @@ static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
  * Returns: errno
  */
 
-int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
+int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
 {
-       struct gfs2_log_header lh_1, lh_m;
+       struct gfs2_log_header_host lh_1, lh_m;
        u32 blk_1, blk_2, blk_m;
        int error;
 
@@ -320,7 +321,7 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
                length = be32_to_cpu(ld->ld_length);
 
                if (be32_to_cpu(ld->ld_header.mh_type) == GFS2_METATYPE_LH) {
-                       struct gfs2_log_header lh;
+                       struct gfs2_log_header_host lh;
                        error = get_log_header(jd, start, &lh);
                        if (!error) {
                                gfs2_replay_incr_blk(sdp, &start);
@@ -363,7 +364,7 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
  * Returns: errno
  */
 
-static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
+static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
 {
        struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
@@ -425,7 +426,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 {
        struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct gfs2_log_header head;
+       struct gfs2_log_header_host head;
        struct gfs2_holder j_gh, ji_gh, t_gh;
        unsigned long t;
        int ro = 0;
index 961feed..f7235e6 100644 (file)
@@ -26,7 +26,7 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where);
 void gfs2_revoke_clean(struct gfs2_sbd *sdp);
 
 int gfs2_find_jhead(struct gfs2_jdesc *jd,
-                   struct gfs2_log_header *head);
+                   struct gfs2_log_header_host *head);
 int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd);
 void gfs2_check_journals(struct gfs2_sbd *sdp);
 
index b261385..ff08465 100644 (file)
@@ -253,7 +253,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
 
 }
 
-static inline int rgrp_contains_block(struct gfs2_rindex *ri, u64 block)
+static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block)
 {
        u64 first = ri->ri_data0;
        u64 last = first + ri->ri_data;
@@ -1217,7 +1217,7 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
        al->al_alloced++;
 
        gfs2_statfs_change(sdp, 0, -1, 0);
-       gfs2_quota_change(ip, +1, ip->i_di.di_uid, ip->i_di.di_gid);
+       gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
 
        spin_lock(&sdp->sd_rindex_spin);
        rgd->rd_free_clone--;
@@ -1261,7 +1261,7 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip)
        al->al_alloced++;
 
        gfs2_statfs_change(sdp, 0, -1, 0);
-       gfs2_quota_change(ip, +1, ip->i_di.di_uid, ip->i_di.di_gid);
+       gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
        gfs2_trans_add_unrevoke(sdp, block);
 
        spin_lock(&sdp->sd_rindex_spin);
@@ -1337,8 +1337,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
        gfs2_trans_add_rg(rgd);
 
        gfs2_statfs_change(sdp, 0, +blen, 0);
-       gfs2_quota_change(ip, -(s64)blen,
-                        ip->i_di.di_uid, ip->i_di.di_gid);
+       gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
 }
 
 /**
@@ -1366,7 +1365,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
        gfs2_trans_add_rg(rgd);
 
        gfs2_statfs_change(sdp, 0, +blen, 0);
-       gfs2_quota_change(ip, -(s64)blen, ip->i_di.di_uid, ip->i_di.di_gid);
+       gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
        gfs2_meta_wipe(ip, bstart, blen);
 }
 
@@ -1411,7 +1410,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
 void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
 {
        gfs2_free_uninit_di(rgd, ip->i_num.no_addr);
-       gfs2_quota_change(ip, -1, ip->i_di.di_uid, ip->i_di.di_gid);
+       gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
        gfs2_meta_wipe(ip, ip->i_num.no_addr, 1);
 }
 
index 6a78b1b..43a24f2 100644 (file)
@@ -97,7 +97,7 @@ void gfs2_tune_init(struct gfs2_tune *gt)
  * changed.
  */
 
-int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent)
+int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
 {
        unsigned int x;
 
@@ -180,6 +180,24 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error)
        return 0;
 }
 
+/**
+ * gfs2_read_super - Read the gfs2 super block from disk
+ * @sb: The VFS super block
+ * @sector: The location of the super block
+ *
+ * This uses the bio functions to read the super block from disk
+ * because we want to be 100% sure that we never read cached data.
+ * A super block is read twice only during each GFS2 mount and is
+ * never written to by the filesystem. The first time its read no
+ * locks are held, and the only details which are looked at are those
+ * relating to the locking protocol. Once locking is up and working,
+ * the sb is read again under the lock to establish the location of
+ * the master directory (contains pointers to journals etc) and the
+ * root directory.
+ *
+ * Returns: A page containing the sb or NULL
+ */
+
 struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
 {
        struct page *page;
@@ -199,7 +217,7 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
                return NULL;
        }
 
-       bio->bi_sector = sector;
+       bio->bi_sector = sector * (sb->s_blocksize >> 9);
        bio->bi_bdev = sb->s_bdev;
        bio_add_page(bio, page, PAGE_SIZE, 0);
 
@@ -508,7 +526,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
        struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
        struct gfs2_glock *j_gl = ip->i_gl;
        struct gfs2_holder t_gh;
-       struct gfs2_log_header head;
+       struct gfs2_log_header_host head;
        int error;
 
        error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED,
@@ -517,7 +535,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
                return error;
 
        gfs2_meta_cache_flush(ip);
-       j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);
+       j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
 
        error = gfs2_find_jhead(sdp->sd_jdesc, &head);
        if (error)
@@ -587,9 +605,9 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 int gfs2_statfs_init(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
-       struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master;
+       struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
        struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
-       struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
+       struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
        struct buffer_head *m_bh, *l_bh;
        struct gfs2_holder gh;
        int error;
@@ -634,7 +652,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
                        s64 dinodes)
 {
        struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
-       struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
+       struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
        struct buffer_head *l_bh;
        int error;
 
@@ -660,8 +678,8 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
        struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
-       struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master;
-       struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
+       struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+       struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
        struct gfs2_holder gh;
        struct buffer_head *m_bh, *l_bh;
        int error;
@@ -727,10 +745,10 @@ out:
  * Returns: errno
  */
 
-int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc)
+int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
 {
-       struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master;
-       struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local;
+       struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+       struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
 
        spin_lock(&sdp->sd_statfs_spin);
 
@@ -760,7 +778,7 @@ int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc)
  */
 
 static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
-                           struct gfs2_statfs_change *sc)
+                           struct gfs2_statfs_change_host *sc)
 {
        gfs2_rgrp_verify(rgd);
        sc->sc_total += rgd->rd_ri.ri_data;
@@ -782,7 +800,7 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
  * Returns: errno
  */
 
-int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc)
+int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
 {
        struct gfs2_holder ri_gh;
        struct gfs2_rgrpd *rgd_next;
@@ -792,7 +810,7 @@ int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc)
        int done;
        int error = 0, err;
 
-       memset(sc, 0, sizeof(struct gfs2_statfs_change));
+       memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
        gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
        if (!gha)
                return -ENOMEM;
@@ -873,7 +891,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp,
        struct gfs2_jdesc *jd;
        struct lfcc *lfcc;
        LIST_HEAD(list);
-       struct gfs2_log_header lh;
+       struct gfs2_log_header_host lh;
        int error;
 
        error = gfs2_jindex_hold(sdp, &ji_gh);
index 5bb443a..e590b2d 100644 (file)
@@ -14,7 +14,7 @@
 
 void gfs2_tune_init(struct gfs2_tune *gt);
 
-int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent);
+int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
 int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
 struct page *gfs2_read_super(struct super_block *sb, sector_t sector);
 
@@ -45,8 +45,8 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp);
 void gfs2_statfs_change(struct gfs2_sbd *sdp,
                        s64 total, s64 free, s64 dinodes);
 int gfs2_statfs_sync(struct gfs2_sbd *sdp);
-int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc);
-int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc);
+int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc);
+int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc);
 
 int gfs2_freeze_fs(struct gfs2_sbd *sdp);
 void gfs2_unfreeze_fs(struct gfs2_sbd *sdp);
index 0e0ec98..983eaf1 100644 (file)
@@ -426,9 +426,6 @@ static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
 }                                                                             \
 TUNE_ATTR_2(name, name##_store)
 
-TUNE_ATTR(ilimit, 0);
-TUNE_ATTR(ilimit_tries, 0);
-TUNE_ATTR(ilimit_min, 0);
 TUNE_ATTR(demote_secs, 0);
 TUNE_ATTR(incore_log_blocks, 0);
 TUNE_ATTR(log_flush_secs, 0);
@@ -447,7 +444,6 @@ TUNE_ATTR(quota_simul_sync, 1);
 TUNE_ATTR(quota_cache_secs, 1);
 TUNE_ATTR(max_atomic_write, 1);
 TUNE_ATTR(stall_secs, 1);
-TUNE_ATTR(entries_per_readdir, 1);
 TUNE_ATTR(greedy_default, 1);
 TUNE_ATTR(greedy_quantum, 1);
 TUNE_ATTR(greedy_max, 1);
@@ -459,9 +455,6 @@ TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
 TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 
 static struct attribute *tune_attrs[] = {
-       &tune_attr_ilimit.attr,
-       &tune_attr_ilimit_tries.attr,
-       &tune_attr_ilimit_min.attr,
        &tune_attr_demote_secs.attr,
        &tune_attr_incore_log_blocks.attr,
        &tune_attr_log_flush_secs.attr,
@@ -478,7 +471,6 @@ static struct attribute *tune_attrs[] = {
        &tune_attr_quota_cache_secs.attr,
        &tune_attr_max_atomic_write.attr,
        &tune_attr_stall_secs.attr,
-       &tune_attr_entries_per_readdir.attr,
        &tune_attr_greedy_default.attr,
        &tune_attr_greedy_quantum.attr,
        &tune_attr_greedy_max.attr,
index 196c604..e5707a9 100644 (file)
@@ -23,9 +23,9 @@
 #include "lm.h"
 #include "util.h"
 
-kmem_cache_t *gfs2_glock_cachep __read_mostly;
-kmem_cache_t *gfs2_inode_cachep __read_mostly;
-kmem_cache_t *gfs2_bufdata_cachep __read_mostly;
+struct kmem_cache *gfs2_glock_cachep __read_mostly;
+struct kmem_cache *gfs2_inode_cachep __read_mostly;
+struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
 
 void gfs2_assert_i(struct gfs2_sbd *sdp)
 {
index 76a5089..28938a4 100644 (file)
@@ -83,8 +83,7 @@ static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp,
                                    char *file, unsigned int line)
 {
        struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data;
-       u32 magic = mh->mh_magic;
-       magic = be32_to_cpu(magic);
+       u32 magic = be32_to_cpu(mh->mh_magic);
        if (unlikely(magic != GFS2_MAGIC))
                return gfs2_meta_check_ii(sdp, bh, "magic number", function,
                                          file, line);
@@ -107,9 +106,8 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
                                        char *file, unsigned int line)
 {
        struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data;
-       u32 magic = mh->mh_magic;
+       u32 magic = be32_to_cpu(mh->mh_magic);
        u16 t = be32_to_cpu(mh->mh_type);
-       magic = be32_to_cpu(magic);
        if (unlikely(magic != GFS2_MAGIC))
                return gfs2_meta_check_ii(sdp, bh, "magic number", function,
                                          file, line);
@@ -146,9 +144,9 @@ int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
 gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
 
 
-extern kmem_cache_t *gfs2_glock_cachep;
-extern kmem_cache_t *gfs2_inode_cachep;
-extern kmem_cache_t *gfs2_bufdata_cachep;
+extern struct kmem_cache *gfs2_glock_cachep;
+extern struct kmem_cache *gfs2_inode_cachep;
+extern struct kmem_cache *gfs2_bufdata_cachep;
 
 static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
                                           unsigned int *p)
index 37d681b..e2e0358 100644 (file)
@@ -53,7 +53,7 @@ done:
  */
 static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        int len, err;
        char strbuf[HFS_MAX_NAMELEN];
index 02f5573..5cb7f8f 100644 (file)
@@ -102,7 +102,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+       struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
 
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, hfs_get_block, NULL);
index 85b17b3..a369879 100644 (file)
@@ -24,7 +24,7 @@
 #include "hfs_fs.h"
 #include "btree.h"
 
-static kmem_cache_t *hfs_inode_cachep;
+static struct kmem_cache *hfs_inode_cachep;
 
 MODULE_LICENSE("GPL");
 
@@ -145,7 +145,7 @@ static struct inode *hfs_alloc_inode(struct super_block *sb)
 {
        struct hfs_inode_info *i;
 
-       i = kmem_cache_alloc(hfs_inode_cachep, SLAB_KERNEL);
+       i = kmem_cache_alloc(hfs_inode_cachep, GFP_KERNEL);
        return i ? &i->vfs_inode : NULL;
 }
 
@@ -430,7 +430,7 @@ static struct file_system_type hfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void hfs_init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
 {
        struct hfs_inode_info *i = p;
 
index 7e30975..e886ac8 100644 (file)
@@ -111,7 +111,7 @@ fail:
 
 static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        int len, err;
        char strbuf[HFSPLUS_MAX_STRLEN + 1];
index 9e36752..75e8c4d 100644 (file)
@@ -97,7 +97,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+       struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
 
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, hfsplus_get_block, NULL);
index 194eede..0f513c6 100644 (file)
@@ -434,13 +434,13 @@ MODULE_AUTHOR("Brad Boyer");
 MODULE_DESCRIPTION("Extended Macintosh Filesystem");
 MODULE_LICENSE("GPL");
 
-static kmem_cache_t *hfsplus_inode_cachep;
+static struct kmem_cache *hfsplus_inode_cachep;
 
 static struct inode *hfsplus_alloc_inode(struct super_block *sb)
 {
        struct hfsplus_inode_info *i;
 
-       i = kmem_cache_alloc(hfsplus_inode_cachep, SLAB_KERNEL);
+       i = kmem_cache_alloc(hfsplus_inode_cachep, GFP_KERNEL);
        return i ? &i->vfs_inode : NULL;
 }
 
@@ -467,7 +467,7 @@ static struct file_system_type hfsplus_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void hfsplus_init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
 {
        struct hfsplus_inode_info *i = p;
 
index b6bd33c..1e6fc37 100644 (file)
@@ -35,7 +35,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
        return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
 }
 
-#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
+#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
 
 int hostfs_d_delete(struct dentry *dentry)
 {
@@ -325,7 +325,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
        unsigned long long next, ino;
        int error, len;
 
-       name = dentry_name(file->f_dentry, 0);
+       name = dentry_name(file->f_path.dentry, 0);
        if(name == NULL) return(-ENOMEM);
        dir = open_dir(name, &error);
        kfree(name);
@@ -366,7 +366,7 @@ int hostfs_file_open(struct inode *ino, struct file *file)
        if(w)
                r = 1;
 
-       name = dentry_name(file->f_dentry, 0);
+       name = dentry_name(file->f_path.dentry, 0);
        if(name == NULL)
                return(-ENOMEM);
 
index ecc9180..6916c41 100644 (file)
@@ -24,7 +24,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
        loff_t new_off = off + (whence == 1 ? filp->f_pos : 0);
        loff_t pos;
        struct quad_buffer_head qbh;
-       struct inode *i = filp->f_dentry->d_inode;
+       struct inode *i = filp->f_path.dentry->d_inode;
        struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
        struct super_block *s = i->i_sb;
 
@@ -52,7 +52,7 @@ fail:
 
 static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
@@ -84,7 +84,8 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                if (!fno->dirflag) {
                        e = 1;
-                       hpfs_error(inode->i_sb, "not a directory, fnode %08x",inode->i_ino);
+                       hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
+                                       (unsigned long)inode->i_ino);
                }
                if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) {
                        e = 1;
@@ -144,8 +145,11 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                if (de->first || de->last) {
                        if (hpfs_sb(inode->i_sb)->sb_chk) {
-                               if (de->first && !de->last && (de->namelen != 2 || de ->name[0] != 1 || de->name[1] != 1)) hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08x", old_pos);
-                               if (de->last && (de->namelen != 1 || de ->name[0] != 255)) hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08x", old_pos);
+                               if (de->first && !de->last && (de->namelen != 2
+                                   || de ->name[0] != 1 || de->name[1] != 1))
+                                       hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", old_pos);
+                               if (de->last && (de->namelen != 1 || de ->name[0] != 255))
+                                       hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", old_pos);
                        }
                        hpfs_brelse4(&qbh);
                        goto again;
index 229ff2f..fe83c2b 100644 (file)
@@ -533,10 +533,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                        struct buffer_head *bh;
                        struct dnode *d1;
                        struct quad_buffer_head qbh1;
-                       if (hpfs_sb(i->i_sb)->sb_chk) if (up != i->i_ino) {
-                               hpfs_error(i->i_sb, "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08x", dno, up, i->i_ino);
+                       if (hpfs_sb(i->i_sb)->sb_chk)
+                           if (up != i->i_ino) {
+                               hpfs_error(i->i_sb,
+                                       "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08lx",
+                                       dno, up, (unsigned long)i->i_ino);
                                return;
-                       }
+                           }
                        if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
                                d1->up = up;
                                d1->root_dnode = 1;
@@ -851,7 +854,9 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
        /* Going to the next dirent */
        if ((d = de_next_de(de)) < dnode_end_de(dnode)) {
                if (!(++*posp & 077)) {
-                       hpfs_error(inode->i_sb, "map_pos_dirent: pos crossed dnode boundary; pos = %08x", *posp);
+                       hpfs_error(inode->i_sb,
+                               "map_pos_dirent: pos crossed dnode boundary; pos = %08llx",
+                               (unsigned long long)*posp);
                        goto bail;
                }
                /* We're going down the tree */
index 66339dc..547a838 100644 (file)
@@ -243,8 +243,9 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data
                fnode->ea_offs = 0xc4;
        }
        if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) {
-               hpfs_error(s, "fnode %08x: ea_offs == %03x, ea_size_s == %03x",
-                       inode->i_ino, fnode->ea_offs, fnode->ea_size_s);
+               hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
+                       (unsigned long)inode->i_ino,
+                       fnode->ea_offs, fnode->ea_size_s);
                return;
        }
        if ((fnode->ea_size_s || !fnode->ea_size_l) &&
index 8b94d24..fb4c891 100644 (file)
@@ -115,7 +115,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
 
        retval = do_sync_write(file, buf, count, ppos);
        if (retval > 0)
-               hpfs_i(file->f_dentry->d_inode)->i_dirty = 1;
+               hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
        return retval;
 }
 
index 32ab51e..1c07aa8 100644 (file)
@@ -317,7 +317,8 @@ static inline struct hpfs_sb_info *hpfs_sb(struct super_block *sb)
 
 /* super.c */
 
-void hpfs_error(struct super_block *, char *, ...);
+void hpfs_error(struct super_block *, const char *, ...)
+       __attribute__((format (printf, 2, 3)));
 int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
 unsigned hpfs_count_one_bitmap(struct super_block *, secno);
 
index 7faef85..85d3e1d 100644 (file)
@@ -251,7 +251,10 @@ void hpfs_write_inode_nolock(struct inode *i)
                        de->file_size = 0;
                        hpfs_mark_4buffers_dirty(&qbh);
                        hpfs_brelse4(&qbh);
-               } else hpfs_error(i->i_sb, "directory %08x doesn't have '.' entry", i->i_ino);
+               } else
+                       hpfs_error(i->i_sb,
+                               "directory %08lx doesn't have '.' entry",
+                               (unsigned long)i->i_ino);
        }
        mark_buffer_dirty(bh);
        brelse(bh);
index 0fecdac..c472458 100644 (file)
@@ -126,32 +126,40 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
                        struct extended_attribute *ea;
                        struct extended_attribute *ea_end;
                        if (fnode->magic != FNODE_MAGIC) {
-                               hpfs_error(s, "bad magic on fnode %08x", ino);
+                               hpfs_error(s, "bad magic on fnode %08lx",
+                                       (unsigned long)ino);
                                goto bail;
                        }
                        if (!fnode->dirflag) {
                                if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
                                    (fnode->btree.internal ? 12 : 8)) {
-                                       hpfs_error(s, "bad number of nodes in fnode %08x", ino);
+                                       hpfs_error(s,
+                                          "bad number of nodes in fnode %08lx",
+                                           (unsigned long)ino);
                                        goto bail;
                                }
                                if (fnode->btree.first_free !=
                                    8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
-                                       hpfs_error(s, "bad first_free pointer in fnode %08x", ino);
+                                       hpfs_error(s,
+                                           "bad first_free pointer in fnode %08lx",
+                                           (unsigned long)ino);
                                        goto bail;
                                }
                        }
                        if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 ||
                           (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) {
-                               hpfs_error(s, "bad EA info in fnode %08x: ea_offs == %04x ea_size_s == %04x",
-                                       ino, fnode->ea_offs, fnode->ea_size_s);
+                               hpfs_error(s,
+                                       "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",
+                                       (unsigned long)ino,
+                                       fnode->ea_offs, fnode->ea_size_s);
                                goto bail;
                        }
                        ea = fnode_ea(fnode);
                        ea_end = fnode_end_ea(fnode);
                        while (ea != ea_end) {
                                if (ea > ea_end) {
-                                       hpfs_error(s, "bad EA in fnode %08x", ino);
+                                       hpfs_error(s, "bad EA in fnode %08lx",
+                                               (unsigned long)ino);
                                        goto bail;
                                }
                                ea = next_ea(ea);
index 450b5e0..d4abc1a 100644 (file)
@@ -46,21 +46,17 @@ static void unmark_dirty(struct super_block *s)
 }
 
 /* Filesystem error... */
+static char err_buf[1024];
 
-#define ERR_BUF_SIZE 1024
-
-void hpfs_error(struct super_block *s, char *m,...)
+void hpfs_error(struct super_block *s, const char *fmt, ...)
 {
-       char *buf;
-       va_list l;
-       va_start(l, m);
-       if (!(buf = kmalloc(ERR_BUF_SIZE, GFP_KERNEL)))
-               printk("HPFS: No memory for error message '%s'\n",m);
-       else if (vsprintf(buf, m, l) >= ERR_BUF_SIZE)
-               printk("HPFS: Grrrr... Kernel memory corrupted ... going on, but it'll crash very soon :-(\n");
-       printk("HPFS: filesystem error: ");
-       if (buf) printk("%s", buf);
-       else printk("%s\n",m);
+       va_list args;
+
+       va_start(args, fmt);
+       vsnprintf(err_buf, sizeof(err_buf), fmt, args);
+       va_end(args);
+
+       printk("HPFS: filesystem error: %s", err_buf);
        if (!hpfs_sb(s)->sb_was_error) {
                if (hpfs_sb(s)->sb_err == 2) {
                        printk("; crashing the system because you wanted it\n");
@@ -76,7 +72,6 @@ void hpfs_error(struct super_block *s, char *m,...)
                } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
                else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
        } else printk("\n");
-       kfree(buf);
        hpfs_sb(s)->sb_was_error = 1;
 }
 
@@ -160,12 +155,12 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
-static kmem_cache_t * hpfs_inode_cachep;
+static struct kmem_cache * hpfs_inode_cachep;
 
 static struct inode *hpfs_alloc_inode(struct super_block *sb)
 {
        struct hpfs_inode_info *ei;
-       ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, SLAB_NOFS);
+       ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
        if (!ei)
                return NULL;
        ei->vfs_inode.i_version = 1;
@@ -177,7 +172,7 @@ static void hpfs_destroy_inode(struct inode *inode)
        kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
 
index 642675f..afd340a 100644 (file)
@@ -221,7 +221,7 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
        ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
        ssize_t n;
 
-       read = file->f_dentry->d_inode->i_fop->read;
+       read = file->f_path.dentry->d_inode->i_fop->read;
 
        if(!is_user)
                set_fs(KERNEL_DS);
@@ -320,7 +320,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len
        ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
        int err;
 
-       write = proc_file->f_dentry->d_inode->i_fop->write;
+       write = proc_file->f_path.dentry->d_inode->i_fop->write;
 
        proc_file->f_pos = file->f_pos;
        err = (*write)(proc_file, buf, len, &proc_file->f_pos);
@@ -464,7 +464,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
        if(data == NULL)
                goto out;
 
-       host_file = dentry_name(file->f_dentry, strlen("/rw"));
+       host_file = dentry_name(file->f_path.dentry, strlen("/rw"));
        if(host_file == NULL)
                goto out_free2;
 
@@ -547,7 +547,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
        loff_t (*llseek)(struct file *, loff_t, int);
        loff_t ret;
 
-       llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
+       llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek;
        if(llseek != NULL){
                ret = (*llseek)(proc_file, off, where);
                if(ret < 0)
@@ -591,10 +591,10 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
        struct hppfs_dirent dirent = ((struct hppfs_dirent)
                                      { .vfs_dirent     = ent,
                                        .filldir        = filldir,
-                                       .dentry         = file->f_dentry } );
+                                       .dentry         = file->f_path.dentry } );
        int err;
 
-       readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
+       readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir;
 
        proc_file->f_pos = file->f_pos;
        err = (*readdir)(proc_file, &dirent, hppfs_filldir);
index 7f47569..ed2c223 100644 (file)
@@ -58,7 +58,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
 
 static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        loff_t len, vma_len;
        int ret;
 
@@ -513,7 +513,7 @@ static void hugetlbfs_inc_free_inodes(struct hugetlbfs_sb_info *sbinfo)
 }
 
 
-static kmem_cache_t *hugetlbfs_inode_cachep;
+static struct kmem_cache *hugetlbfs_inode_cachep;
 
 static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
 {
@@ -522,7 +522,7 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
 
        if (unlikely(!hugetlbfs_dec_free_inodes(sbinfo)))
                return NULL;
-       p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL);
+       p = kmem_cache_alloc(hugetlbfs_inode_cachep, GFP_KERNEL);
        if (unlikely(!p)) {
                hugetlbfs_inc_free_inodes(sbinfo);
                return NULL;
@@ -545,7 +545,7 @@ static const struct address_space_operations hugetlbfs_aops = {
 };
 
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
 
@@ -774,8 +774,8 @@ struct file *hugetlb_zero_setup(size_t size)
        d_instantiate(dentry, inode);
        inode->i_size = size;
        inode->i_nlink = 0;
-       file->f_vfsmnt = mntget(hugetlbfs_vfsmount);
-       file->f_dentry = dentry;
+       file->f_path.mnt = mntget(hugetlbfs_vfsmount);
+       file->f_path.dentry = dentry;
        file->f_mapping = inode->i_mapping;
        file->f_op = &hugetlbfs_file_operations;
        file->f_mode = FMODE_WRITE | FMODE_READ;
index 26cdb11..d00de18 100644 (file)
@@ -97,7 +97,7 @@ static DEFINE_MUTEX(iprune_mutex);
  */
 struct inodes_stat_t inodes_stat;
 
-static kmem_cache_t * inode_cachep __read_mostly;
+static struct kmem_cache * inode_cachep __read_mostly;
 
 static struct inode *alloc_inode(struct super_block *sb)
 {
@@ -109,7 +109,7 @@ static struct inode *alloc_inode(struct super_block *sb)
        if (sb->s_op->alloc_inode)
                inode = sb->s_op->alloc_inode(sb);
        else
-               inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
+               inode = (struct inode *) kmem_cache_alloc(inode_cachep, GFP_KERNEL);
 
        if (inode) {
                struct address_space * const mapping = &inode->i_data;
@@ -209,7 +209,7 @@ void inode_init_once(struct inode *inode)
 
 EXPORT_SYMBOL(inode_init_once);
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct inode * inode = (struct inode *) foo;
 
@@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(touch_atime);
 
 void file_update_time(struct file *file)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct timespec now;
        int sync_it = 0;
 
@@ -1242,9 +1242,6 @@ EXPORT_SYMBOL(inode_needs_sync);
  */
 #ifdef CONFIG_QUOTA
 
-/* Function back in dquot.c */
-int remove_inode_dquot_ref(struct inode *, int, struct list_head *);
-
 void remove_dquot_ref(struct super_block *sb, int type,
                        struct list_head *tofree_head)
 {
index 017cb0f..55f6da5 100644 (file)
@@ -34,8 +34,8 @@
 
 #include <asm/ioctls.h>
 
-static kmem_cache_t *watch_cachep __read_mostly;
-static kmem_cache_t *event_cachep __read_mostly;
+static struct kmem_cache *watch_cachep __read_mostly;
+static struct kmem_cache *event_cachep __read_mostly;
 
 static struct vfsmount *inotify_mnt __read_mostly;
 
@@ -570,9 +570,9 @@ asmlinkage long sys_inotify_init(void)
        dev->ih = ih;
 
        filp->f_op = &inotify_fops;
-       filp->f_vfsmnt = mntget(inotify_mnt);
-       filp->f_dentry = dget(inotify_mnt->mnt_root);
-       filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+       filp->f_path.mnt = mntget(inotify_mnt);
+       filp->f_path.dentry = dget(inotify_mnt->mnt_root);
+       filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
        filp->f_mode = FMODE_READ;
        filp->f_flags = O_RDONLY;
        filp->private_data = dev;
index 4b7660b..ff61772 100644 (file)
@@ -31,7 +31,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
                goto out;
        } else if (filp->f_op->ioctl) {
                lock_kernel();
-               error = filp->f_op->ioctl(filp->f_dentry->d_inode,
+               error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
                                          filp, cmd, arg);
                unlock_kernel();
        }
@@ -45,7 +45,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
 {
        int error;
        int block;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        int __user *p = (int __user *)arg;
 
        switch (cmd) {
@@ -137,17 +137,17 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned lon
                        break;
 
                case FIOQSIZE:
-                       if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
-                           S_ISREG(filp->f_dentry->d_inode->i_mode) ||
-                           S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
-                               loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
+                       if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
+                           S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
+                           S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
+                               loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode);
                                error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
                        }
                        else
                                error = -ENOTTY;
                        break;
                default:
-                       if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+                       if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
                                error = file_ioctl(filp, cmd, arg);
                        else
                                error = do_ioctl(filp, cmd, arg);
index 7318163..6bbbdb5 100644 (file)
@@ -42,7 +42,7 @@ static struct semaphore zisofs_zlib_semaphore;
  */
 static int zisofs_readpage(struct file *file, struct page *page)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
        unsigned int maxpage, xpage, fpage, blockindex;
        unsigned long offset;
index 27e2769..4af2548 100644 (file)
@@ -183,7 +183,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
 
                /* Handle the case of the '..' directory */
                if (de->name_len[0] == 1 && de->name[0] == 1) {
-                       inode_number = parent_ino(filp->f_dentry);
+                       inode_number = parent_ino(filp->f_path.dentry);
                        if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
                                break;
                        filp->f_pos += de_len;
@@ -255,8 +255,7 @@ static int isofs_readdir(struct file *filp,
        int result;
        char * tmpname;
        struct iso_directory_record * tmpde;
-       struct inode *inode = filp->f_dentry->d_inode;
-
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        tmpname = (char *)__get_free_page(GFP_KERNEL);
        if (tmpname == NULL)
index c34b862..ea55b6c 100644 (file)
@@ -57,12 +57,12 @@ static void isofs_put_super(struct super_block *sb)
 static void isofs_read_inode(struct inode *);
 static int isofs_statfs (struct dentry *, struct kstatfs *);
 
-static kmem_cache_t *isofs_inode_cachep;
+static struct kmem_cache *isofs_inode_cachep;
 
 static struct inode *isofs_alloc_inode(struct super_block *sb)
 {
        struct iso_inode_info *ei;
-       ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(isofs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -73,7 +73,7 @@ static void isofs_destroy_inode(struct inode *inode)
        kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct iso_inode_info *ei = foo;
 
index b85c686..10fff94 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/pagemap.h>
 #include <linux/kthread.h>
 #include <linux/poison.h>
@@ -1630,7 +1630,7 @@ void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 #define JBD_MAX_SLABS 5
 #define JBD_SLAB_INDEX(size)  (size >> 11)
 
-static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
+static struct kmem_cache *jbd_slab[JBD_MAX_SLABS];
 static const char *jbd_slab_names[JBD_MAX_SLABS] = {
        "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k"
 };
@@ -1693,7 +1693,7 @@ void jbd_slab_free(void *ptr,  size_t size)
 /*
  * Journal_head storage management
  */
-static kmem_cache_t *journal_head_cache;
+static struct kmem_cache *journal_head_cache;
 #ifdef CONFIG_JBD_DEBUG
 static atomic_t nr_journal_heads = ATOMIC_INIT(0);
 #endif
@@ -1996,7 +1996,7 @@ static void __exit remove_jbd_proc_entry(void)
 
 #endif
 
-kmem_cache_t *jbd_handle_cache;
+struct kmem_cache *jbd_handle_cache;
 
 static int __init journal_init_handle_cache(void)
 {
index c532429..d204ab3 100644 (file)
@@ -70,8 +70,8 @@
 #include <linux/init.h>
 #endif
 
-static kmem_cache_t *revoke_record_cache;
-static kmem_cache_t *revoke_table_cache;
+static struct kmem_cache *revoke_record_cache;
+static struct kmem_cache *revoke_table_cache;
 
 /* Each revoke record represents one single revoked block.  During
    journal replay, this involves recording the transaction ID of the
index 4f82bcd..cceaf57 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 
+static void __journal_temp_unlink_buffer(struct journal_head *jh);
+
 /*
  * get_transaction: obtain a new transaction_t object.
  *
@@ -53,7 +55,7 @@ get_transaction(journal_t *journal, transaction_t *transaction)
        spin_lock_init(&transaction->t_handle_lock);
 
        /* Set up the commit timer for the new transaction. */
-       journal->j_commit_timer.expires = transaction->t_expires;
+       journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
        add_timer(&journal->j_commit_timer);
 
        J_ASSERT(journal->j_running_transaction == NULL);
@@ -1499,7 +1501,7 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh)
  *
  * Called under j_list_lock.  The journal may not be locked.
  */
-void __journal_temp_unlink_buffer(struct journal_head *jh)
+static void __journal_temp_unlink_buffer(struct journal_head *jh)
 {
        struct journal_head **list = NULL;
        transaction_t *transaction;
index 70b2ae1..6bd8005 100644 (file)
@@ -248,8 +248,12 @@ write_out_data:
                                bufs = 0;
                                goto write_out_data;
                        }
-               }
-               else {
+               } else if (!locked && buffer_locked(bh)) {
+                       __jbd2_journal_file_buffer(jh, commit_transaction,
+                                               BJ_Locked);
+                       jbd_unlock_bh_state(bh);
+                       put_bh(bh);
+               } else {
                        BUFFER_TRACE(bh, "writeout complete: unfile");
                        __jbd2_journal_unfile_buffer(jh);
                        jbd_unlock_bh_state(bh);
index c60f378..44fc32b 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/pagemap.h>
 #include <linux/kthread.h>
 #include <linux/poison.h>
@@ -1641,7 +1641,7 @@ void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 #define JBD_MAX_SLABS 5
 #define JBD_SLAB_INDEX(size)  (size >> 11)
 
-static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
+static struct kmem_cache *jbd_slab[JBD_MAX_SLABS];
 static const char *jbd_slab_names[JBD_MAX_SLABS] = {
        "jbd2_1k", "jbd2_2k", "jbd2_4k", NULL, "jbd2_8k"
 };
@@ -1704,7 +1704,7 @@ void jbd2_slab_free(void *ptr,  size_t size)
 /*
  * Journal_head storage management
  */
-static kmem_cache_t *jbd2_journal_head_cache;
+static struct kmem_cache *jbd2_journal_head_cache;
 #ifdef CONFIG_JBD_DEBUG
 static atomic_t nr_journal_heads = ATOMIC_INIT(0);
 #endif
@@ -2007,7 +2007,7 @@ static void __exit jbd2_remove_jbd_proc_entry(void)
 
 #endif
 
-kmem_cache_t *jbd2_handle_cache;
+struct kmem_cache *jbd2_handle_cache;
 
 static int __init journal_init_handle_cache(void)
 {
index 380d199..f506646 100644 (file)
@@ -70,8 +70,8 @@
 #include <linux/init.h>
 #endif
 
-static kmem_cache_t *jbd2_revoke_record_cache;
-static kmem_cache_t *jbd2_revoke_table_cache;
+static struct kmem_cache *jbd2_revoke_record_cache;
+static struct kmem_cache *jbd2_revoke_table_cache;
 
 /* Each revoke record represents one single revoked block.  During
    journal replay, this involves recording the transaction ID of the
index c051a94..3a87001 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 
+static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
+
 /*
  * jbd2_get_transaction: obtain a new transaction_t object.
  *
index 3f7899e..7b40c69 100644 (file)
@@ -61,8 +61,8 @@ static const struct file_operations jffs_dir_operations;
 static struct inode_operations jffs_dir_inode_operations;
 static const struct address_space_operations jffs_address_operations;
 
-kmem_cache_t     *node_cache = NULL;
-kmem_cache_t     *fm_cache = NULL;
+struct kmem_cache     *node_cache = NULL;
+struct kmem_cache     *fm_cache = NULL;
 
 /* Called by the VFS at mount time to initialize the whole file system.  */
 static int jffs_fill_super(struct super_block *sb, void *data, int silent)
@@ -566,7 +566,7 @@ static int
 jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        struct jffs_file *f;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
        int j;
@@ -1372,7 +1372,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
        struct jffs_control *c;
        struct jffs_file *f;
        struct jffs_node *node;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int recoverable = 0;
        size_t written = 0;
@@ -1380,7 +1380,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
        loff_t pos = *ppos;
        int err;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
                  "filp: 0x%p, buf: 0x%p, count: %d\n",
index 4a543e1..d0e783f 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/ctype.h>
+#include <linux/freezer.h>
 
 #include "intrep.h"
 #include "jffs_fm.h"
@@ -591,7 +592,7 @@ jffs_add_virtual_root(struct jffs_control *c)
        D2(printk("jffs_add_virtual_root(): "
                  "Creating a virtual root directory.\n"));
 
-       if (!(root = kmalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
+       if (!(root = kzalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
                return -ENOMEM;
        }
        no_jffs_file++;
@@ -603,7 +604,6 @@ jffs_add_virtual_root(struct jffs_control *c)
        DJM(no_jffs_node++);
        memset(node, 0, sizeof(struct jffs_node));
        node->ino = JFFS_MIN_INO;
-       memset(root, 0, sizeof(struct jffs_file));
        root->ino = JFFS_MIN_INO;
        root->mode = S_IFDIR | S_IRWXU | S_IRGRP
                     | S_IXGRP | S_IROTH | S_IXOTH;
index 29b68d9..077258b 100644 (file)
@@ -29,8 +29,8 @@ static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
 static struct jffs_fm *jffs_alloc_fm(void);
 static void jffs_free_fm(struct jffs_fm *n);
 
-extern kmem_cache_t     *fm_cache;
-extern kmem_cache_t     *node_cache;
+extern struct kmem_cache     *fm_cache;
+extern struct kmem_cache     *node_cache;
 
 #if CONFIG_JFFS_FS_VERBOSE > 0
 void
index ff2a872..6eb3dae 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/freezer.h>
 #include "nodelist.h"
 
 
index 9def6ad..da6034d 100644 (file)
@@ -123,11 +123,11 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        struct jffs2_inode_info *f;
        struct jffs2_sb_info *c;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct jffs2_full_dirent *fd;
        unsigned long offset, curofs;
 
-       D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
+       D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_path.dentry->d_inode->i_ino));
 
        f = JFFS2_INODE_INFO(inode);
        c = JFFS2_SB_INFO(inode->i_sb);
@@ -141,7 +141,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
                offset++;
        }
        if (offset == 1) {
-               unsigned long pino = parent_ino(filp->f_dentry);
+               unsigned long pino = parent_ino(filp->f_path.dentry);
                D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino));
                if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0)
                        goto out;
index 33f2910..83f9881 100644 (file)
 
 /* These are initialised to NULL in the kernel startup code.
    If you're porting to other operating systems, beware */
-static kmem_cache_t *full_dnode_slab;
-static kmem_cache_t *raw_dirent_slab;
-static kmem_cache_t *raw_inode_slab;
-static kmem_cache_t *tmp_dnode_info_slab;
-static kmem_cache_t *raw_node_ref_slab;
-static kmem_cache_t *node_frag_slab;
-static kmem_cache_t *inode_cache_slab;
+static struct kmem_cache *full_dnode_slab;
+static struct kmem_cache *raw_dirent_slab;
+static struct kmem_cache *raw_inode_slab;
+static struct kmem_cache *tmp_dnode_info_slab;
+static struct kmem_cache *raw_node_ref_slab;
+static struct kmem_cache *node_frag_slab;
+static struct kmem_cache *inode_cache_slab;
 #ifdef CONFIG_JFFS2_FS_XATTR
-static kmem_cache_t *xattr_datum_cache;
-static kmem_cache_t *xattr_ref_cache;
+static struct kmem_cache *xattr_datum_cache;
+static struct kmem_cache *xattr_ref_cache;
 #endif
 
 int __init jffs2_create_slab_caches(void)
index bc4b810..7deb782 100644 (file)
 
 static void jffs2_put_super(struct super_block *);
 
-static kmem_cache_t *jffs2_inode_cachep;
+static struct kmem_cache *jffs2_inode_cachep;
 
 static struct inode *jffs2_alloc_inode(struct super_block *sb)
 {
        struct jffs2_inode_info *ei;
-       ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL);
+       ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -44,7 +44,7 @@ static void jffs2_destroy_inode(struct inode *inode)
        kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
 }
 
-static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
 
index ecb2216..47bc0b5 100644 (file)
@@ -3009,7 +3009,7 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
  */
 int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *ip = filp->f_dentry->d_inode;
+       struct inode *ip = filp->f_path.dentry->d_inode;
        struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
        int rc = 0;
        loff_t dtpos;   /* legacy OS/2 style position */
index b89c9ab..5065baa 100644 (file)
@@ -67,7 +67,7 @@
 #include <linux/kthread.h>
 #include <linux/buffer_head.h>         /* for sync_blockdev() */
 #include <linux/bio.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include "jfs_incore.h"
index 0cccd1c..b1a1c72 100644 (file)
@@ -74,7 +74,7 @@ static inline void lock_metapage(struct metapage *mp)
 }
 
 #define METAPOOL_MIN_PAGES 32
-static kmem_cache_t *metapage_cache;
+static struct kmem_cache *metapage_cache;
 static mempool_t *metapage_mempool;
 
 #define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE)
@@ -180,7 +180,7 @@ static inline void remove_metapage(struct page *page, struct metapage *mp)
 
 #endif
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct metapage *mp = (struct metapage *)foo;
 
index 81f6f04..d558e51 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kthread.h>
index 9c1c6e0..846ac8f 100644 (file)
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
 MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
 MODULE_LICENSE("GPL");
 
-static kmem_cache_t * jfs_inode_cachep;
+static struct kmem_cache * jfs_inode_cachep;
 
 static struct super_operations jfs_super_operations;
 static struct export_operations jfs_export_operations;
@@ -93,7 +93,7 @@ void jfs_error(struct super_block *sb, const char * function, ...)
        va_list args;
 
        va_start(args, function);
-       vsprintf(error_buf, function, args);
+       vsnprintf(error_buf, sizeof(error_buf), function, args);
        va_end(args);
 
        printk(KERN_ERR "ERROR: (device %s): %s\n", sb->s_id, error_buf);
@@ -748,7 +748,7 @@ static struct file_system_type jfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
 
index bd08e0e..503898d 100644 (file)
@@ -63,7 +63,7 @@ int dcache_dir_open(struct inode *inode, struct file *file)
 {
        static struct qstr cursor_name = {.len = 1, .name = "."};
 
-       file->private_data = d_alloc(file->f_dentry, &cursor_name);
+       file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
 
        return file->private_data ? 0 : -ENOMEM;
 }
@@ -76,7 +76,7 @@ int dcache_dir_close(struct inode *inode, struct file *file)
 
 loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
 {
-       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+       mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
        switch (origin) {
                case 1:
                        offset += file->f_pos;
@@ -84,7 +84,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+                       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
@@ -96,8 +96,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
 
                        spin_lock(&dcache_lock);
                        list_del(&cursor->d_u.d_child);
-                       p = file->f_dentry->d_subdirs.next;
-                       while (n && p != &file->f_dentry->d_subdirs) {
+                       p = file->f_path.dentry->d_subdirs.next;
+                       while (n && p != &file->f_path.dentry->d_subdirs) {
                                struct dentry *next;
                                next = list_entry(p, struct dentry, d_u.d_child);
                                if (!d_unhashed(next) && next->d_inode)
@@ -108,7 +108,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
                        spin_unlock(&dcache_lock);
                }
        }
-       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
        return offset;
 }
 
@@ -126,7 +126,7 @@ static inline unsigned char dt_type(struct inode *inode)
 
 int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct dentry *cursor = filp->private_data;
        struct list_head *p, *q = &cursor->d_u.d_child;
        ino_t ino;
index b85a0ad..92681c9 100644 (file)
@@ -126,7 +126,7 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock
                        continue;
                if (!nlm_cmp_addr(&block->b_host->h_addr, addr))
                        continue;
-               if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_dentry->d_inode) ,fh) != 0)
+               if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
                        continue;
                /* Alright, we found a lock. Set the return status
                 * and wake up the caller
index 3d84f60..80a1a6d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/utsname.h>
 #include <linux/smp_lock.h>
+#include <linux/freezer.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/lockd/lockd.h>
@@ -128,7 +129,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 
        nlmclnt_next_cookie(&argp->cookie);
        argp->state   = nsm_local_state;
-       memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
+       memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh));
        lock->caller  = utsname()->nodename;
        lock->oh.data = req->a_owner;
        lock->oh.len  = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
@@ -729,7 +730,7 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
                goto retry_cancel;
        }
 
-       dprintk("lockd: cancel status %d (task %d)\n",
+       dprintk("lockd: cancel status %u (task %u)\n",
                        req->a_res.status, task->tk_pid);
 
        switch (req->a_res.status) {
index fb24a97..3d4610c 100644 (file)
@@ -36,34 +36,14 @@ static DEFINE_MUTEX(nlm_host_mutex);
 static void                    nlm_gc_hosts(void);
 static struct nsm_handle *     __nsm_find(const struct sockaddr_in *,
                                        const char *, int, int);
-
-/*
- * Find an NLM server handle in the cache. If there is none, create it.
- */
-struct nlm_host *
-nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
-                       const char *hostname, int hostname_len)
-{
-       return nlm_lookup_host(0, sin, proto, version,
-                              hostname, hostname_len);
-}
-
-/*
- * Find an NLM client handle in the cache. If there is none, create it.
- */
-struct nlm_host *
-nlmsvc_lookup_host(struct svc_rqst *rqstp,
-                       const char *hostname, int hostname_len)
-{
-       return nlm_lookup_host(1, &rqstp->rq_addr,
-                              rqstp->rq_prot, rqstp->rq_vers,
-                              hostname, hostname_len);
-}
+static struct nsm_handle *     nsm_find(const struct sockaddr_in *sin,
+                                        const char *hostname,
+                                        int hostname_len);
 
 /*
  * Common host lookup routine for server & client
  */
-struct nlm_host *
+static struct nlm_host *
 nlm_lookup_host(int server, const struct sockaddr_in *sin,
                                        int proto, int version,
                                        const char *hostname,
@@ -194,6 +174,29 @@ nlm_destroy_host(struct nlm_host *host)
        kfree(host);
 }
 
+/*
+ * Find an NLM server handle in the cache. If there is none, create it.
+ */
+struct nlm_host *
+nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
+                       const char *hostname, int hostname_len)
+{
+       return nlm_lookup_host(0, sin, proto, version,
+                              hostname, hostname_len);
+}
+
+/*
+ * Find an NLM client handle in the cache. If there is none, create it.
+ */
+struct nlm_host *
+nlmsvc_lookup_host(struct svc_rqst *rqstp,
+                       const char *hostname, int hostname_len)
+{
+       return nlm_lookup_host(1, &rqstp->rq_addr,
+                              rqstp->rq_prot, rqstp->rq_vers,
+                              hostname, hostname_len);
+}
+
 /*
  * Create the NLM RPC client for an NLM peer
  */
@@ -495,7 +498,7 @@ out:
        return nsm;
 }
 
-struct nsm_handle *
+static struct nsm_handle *
 nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len)
 {
        return __nsm_find(sin, hostname, hostname_len, 1);
index 0ce5c81..f67146a 100644 (file)
@@ -234,7 +234,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
  */
 static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
 {
-       dprintk("lockd: %4d callback returned %d\n", task->tk_pid,
+       dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
                        -task->tk_status);
 }
 
index 7e219b9..5c054b2 100644 (file)
@@ -343,8 +343,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
        __be32                  ret;
 
        dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
-                               file->f_file->f_dentry->d_inode->i_sb->s_id,
-                               file->f_file->f_dentry->d_inode->i_ino,
+                               file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+                               file->f_file->f_path.dentry->d_inode->i_ino,
                                lock->fl.fl_type, lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end,
@@ -420,8 +420,8 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
                                       struct nlm_lock *conflock)
 {
        dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
-                               file->f_file->f_dentry->d_inode->i_sb->s_id,
-                               file->f_file->f_dentry->d_inode->i_ino,
+                               file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+                               file->f_file->f_path.dentry->d_inode->i_ino,
                                lock->fl.fl_type,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
@@ -454,8 +454,8 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
        int     error;
 
        dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
-                               file->f_file->f_dentry->d_inode->i_sb->s_id,
-                               file->f_file->f_dentry->d_inode->i_ino,
+                               file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+                               file->f_file->f_path.dentry->d_inode->i_ino,
                                lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
@@ -483,8 +483,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
        int status = 0;
 
        dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
-                               file->f_file->f_dentry->d_inode->i_sb->s_id,
-                               file->f_file->f_dentry->d_inode->i_ino,
+                               file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+                               file->f_file->f_path.dentry->d_inode->i_ino,
                                lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
index 32e99a6..3707c3a 100644 (file)
@@ -263,7 +263,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
  */
 static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 {
-       dprintk("lockd: %4d callback returned %d\n", task->tk_pid,
+       dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
                        -task->tk_status);
 }
 
index e83024e..c0df00c 100644 (file)
@@ -43,7 +43,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
 
 static inline void nlm_debug_print_file(char *msg, struct nlm_file *file)
 {
-       struct inode *inode = file->f_file->f_dentry->d_inode;
+       struct inode *inode = file->f_file->f_path.dentry->d_inode;
 
        dprintk("lockd: %s %s/%ld\n",
                msg, inode->i_sb->s_id, inode->i_ino);
index e0b6a80..52a8100 100644 (file)
@@ -142,12 +142,12 @@ int lease_break_time = 45;
 static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
-static kmem_cache_t *filelock_cache __read_mostly;
+static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
 static struct file_lock *locks_alloc_lock(void)
 {
-       return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
+       return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
 }
 
 static void locks_release_private(struct file_lock *fl)
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(locks_init_lock);
  * Initialises the fields of the file lock which are invariant for
  * free file_locks.
  */
-static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags)
 {
        struct file_lock *lock = (struct file_lock *) foo;
 
@@ -321,7 +321,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
                start = filp->f_pos;
                break;
        case SEEK_END:
-               start = i_size_read(filp->f_dentry->d_inode);
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -371,7 +371,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
                start = filp->f_pos;
                break;
        case SEEK_END:
-               start = i_size_read(filp->f_dentry->d_inode);
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -672,7 +672,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
        struct file_lock *cfl;
 
        lock_kernel();
-       for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+       for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
                if (!IS_POSIX(cfl))
                        continue;
                if (posix_locks_conflict(cfl, fl))
@@ -734,7 +734,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
 {
        struct file_lock *new_fl = NULL;
        struct file_lock **before;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        int error = 0;
        int found = 0;
 
@@ -1018,7 +1018,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
  */
 int posix_lock_file(struct file *filp, struct file_lock *fl)
 {
-       return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
 }
 EXPORT_SYMBOL(posix_lock_file);
 
@@ -1033,7 +1033,7 @@ EXPORT_SYMBOL(posix_lock_file);
 int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
                        struct file_lock *conflock)
 {
-       return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock);
 }
 EXPORT_SYMBOL(posix_lock_file_conf);
 
@@ -1333,8 +1333,8 @@ int fcntl_getlease(struct file *filp)
        int type = F_UNLCK;
 
        lock_kernel();
-       time_out_leases(filp->f_dentry->d_inode);
-       for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl);
+       time_out_leases(filp->f_path.dentry->d_inode);
+       for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
                        fl = fl->fl_next) {
                if (fl->fl_file == filp) {
                        type = fl->fl_type & ~F_INPROGRESS;
@@ -1359,7 +1359,7 @@ int fcntl_getlease(struct file *filp)
 static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
        struct file_lock *fl, **before, **my_before = NULL, *lease;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error, rdlease_count = 0, wrlease_count = 0;
 
@@ -1448,7 +1448,7 @@ out:
 
 int setlease(struct file *filp, long arg, struct file_lock **lease)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1482,7 +1482,7 @@ EXPORT_SYMBOL(setlease);
 int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
 {
        struct file_lock fl, *flp = &fl;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1692,7 +1692,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1835,7 +1835,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1922,7 +1922,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
         * posix_lock_file().  Another process could be setting a lock on this
         * file at the same time, but we wouldn't remove that lock anyway.
         */
-       if (!filp->f_dentry->d_inode->i_flock)
+       if (!filp->f_path.dentry->d_inode->i_flock)
                return;
 
        lock.fl_type = F_UNLCK;
@@ -1951,7 +1951,7 @@ EXPORT_SYMBOL(locks_remove_posix);
  */
 void locks_remove_flock(struct file *filp)
 {
-       struct inode * inode = filp->f_dentry->d_inode; 
+       struct inode * inode = filp->f_path.dentry->d_inode;
        struct file_lock *fl;
        struct file_lock **before;
 
@@ -2020,7 +2020,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
        struct inode *inode = NULL;
 
        if (fl->fl_file != NULL)
-               inode = fl->fl_file->f_dentry->d_inode;
+               inode = fl->fl_file->f_path.dentry->d_inode;
 
        out += sprintf(out, "%d:%s ", id, pfx);
        if (IS_POSIX(fl)) {
index 0ff7125..deeb9dc 100644 (file)
@@ -85,7 +85,7 @@ struct mb_cache {
 #ifndef MB_CACHE_INDEXES_COUNT
        int                             c_indexes_count;
 #endif
-       kmem_cache_t                    *c_entry_cache;
+       struct kmem_cache                       *c_entry_cache;
        struct list_head                *c_block_hash;
        struct list_head                *c_indexes_hash[0];
 };
index 2b0a389..ab782c4 100644 (file)
@@ -82,7 +82,7 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
 static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
        unsigned long pos = filp->f_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        unsigned offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
index 1e36bae..629e09b 100644 (file)
@@ -51,12 +51,12 @@ static void minix_put_super(struct super_block *sb)
        return;
 }
 
-static kmem_cache_t * minix_inode_cachep;
+static struct kmem_cache * minix_inode_cachep;
 
 static struct inode *minix_alloc_inode(struct super_block *sb)
 {
        struct minix_inode_info *ei;
-       ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, SLAB_KERNEL);
+       ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -67,7 +67,7 @@ static void minix_destroy_inode(struct inode *inode)
        kmem_cache_free(minix_inode_cachep, minix_i(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct minix_inode_info *ei = (struct minix_inode_info *) foo;
 
index 28d49b3..e4f108f 100644 (file)
@@ -249,9 +249,11 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
 
        /*
         * MAY_EXEC on regular files requires special handling: We override
-        * filesystem execute permissions if the mode bits aren't set.
+        * filesystem execute permissions if the mode bits aren't set or
+        * the fs is mounted with the "noexec" flag.
         */
-       if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+       if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
+                       (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
                return -EACCES;
 
        /* Ordinary permission routines do not understand MAY_APPEND. */
@@ -295,7 +297,7 @@ int vfs_permission(struct nameidata *nd, int mask)
  */
 int file_permission(struct file *file, int mask)
 {
-       return permission(file->f_dentry->d_inode, mask, NULL);
+       return permission(file->f_path.dentry->d_inode, mask, NULL);
 }
 
 /*
@@ -331,7 +333,7 @@ int get_write_access(struct inode * inode)
 
 int deny_write_access(struct file * file)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        spin_lock(&inode->i_lock);
        if (atomic_read(&inode->i_writecount) > 0) {
@@ -366,7 +368,7 @@ void path_release_on_umount(struct nameidata *nd)
  */
 void release_open_intent(struct nameidata *nd)
 {
-       if (nd->intent.open.file->f_dentry == NULL)
+       if (nd->intent.open.file->f_path.dentry == NULL)
                put_filp(nd->intent.open.file);
        else
                fput(nd->intent.open.file);
@@ -570,11 +572,6 @@ fail:
        return PTR_ERR(link);
 }
 
-struct path {
-       struct vfsmount *mnt;
-       struct dentry *dentry;
-};
-
 static inline void dput_path(struct path *path, struct nameidata *nd)
 {
        dput(path->dentry);
@@ -1141,7 +1138,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (!file)
                        goto out_fail;
 
-               dentry = file->f_dentry;
+               dentry = file->f_path.dentry;
 
                retval = -ENOTDIR;
                if (!S_ISDIR(dentry->d_inode->i_mode))
@@ -1151,7 +1148,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (retval)
                        goto fput_fail;
 
-               nd->mnt = mntget(file->f_vfsmnt);
+               nd->mnt = mntget(file->f_path.mnt);
                nd->dentry = dget(dentry);
 
                fput_light(file, fput_needed);
@@ -1996,8 +1993,7 @@ asmlinkage long sys_mkdir(const char __user *pathname, int mode)
 void dentry_unhash(struct dentry *dentry)
 {
        dget(dentry);
-       if (atomic_read(&dentry->d_count))
-               shrink_dcache_parent(dentry);
+       shrink_dcache_parent(dentry);
        spin_lock(&dcache_lock);
        spin_lock(&dentry->d_lock);
        if (atomic_read(&dentry->d_count) == 2)
index 55442a6..fde8553 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/sysfs.h>
 #include <linux/seq_file.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/mount.h>
@@ -36,7 +36,7 @@ static int event;
 
 static struct list_head *mount_hashtable __read_mostly;
 static int hash_mask __read_mostly, hash_bits __read_mostly;
-static kmem_cache_t *mnt_cache __read_mostly;
+static struct kmem_cache *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
 
 /* /sys/fs */
@@ -133,10 +133,10 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
 
 static inline int check_mnt(struct vfsmount *mnt)
 {
-       return mnt->mnt_namespace == current->nsproxy->namespace;
+       return mnt->mnt_ns == current->nsproxy->mnt_ns;
 }
 
-static void touch_namespace(struct namespace *ns)
+static void touch_mnt_namespace(struct mnt_namespace *ns)
 {
        if (ns) {
                ns->event = ++event;
@@ -144,7 +144,7 @@ static void touch_namespace(struct namespace *ns)
        }
 }
 
-static void __touch_namespace(struct namespace *ns)
+static void __touch_mnt_namespace(struct mnt_namespace *ns)
 {
        if (ns && ns->event != event) {
                ns->event = event;
@@ -187,19 +187,19 @@ static void commit_tree(struct vfsmount *mnt)
        struct vfsmount *parent = mnt->mnt_parent;
        struct vfsmount *m;
        LIST_HEAD(head);
-       struct namespace *n = parent->mnt_namespace;
+       struct mnt_namespace *n = parent->mnt_ns;
 
        BUG_ON(parent == mnt);
 
        list_add_tail(&head, &mnt->mnt_list);
        list_for_each_entry(m, &head, mnt_list)
-               m->mnt_namespace = n;
+               m->mnt_ns = n;
        list_splice(&head, n->list.prev);
 
        list_add_tail(&mnt->mnt_hash, mount_hashtable +
                                hash(parent, mnt->mnt_mountpoint));
        list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
-       touch_namespace(n);
+       touch_mnt_namespace(n);
 }
 
 static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
@@ -320,7 +320,7 @@ EXPORT_SYMBOL(mnt_unpin);
 /* iterator */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-       struct namespace *n = m->private;
+       struct mnt_namespace *n = m->private;
        struct list_head *p;
        loff_t l = *pos;
 
@@ -333,7 +333,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct namespace *n = m->private;
+       struct mnt_namespace *n = m->private;
        struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
        (*pos)++;
        return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
@@ -526,8 +526,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
        list_for_each_entry(p, kill, mnt_hash) {
                list_del_init(&p->mnt_expire);
                list_del_init(&p->mnt_list);
-               __touch_namespace(p->mnt_namespace);
-               p->mnt_namespace = NULL;
+               __touch_mnt_namespace(p->mnt_ns);
+               p->mnt_ns = NULL;
                list_del_init(&p->mnt_child);
                if (p->mnt_parent != p)
                        p->mnt_mountpoint->d_mounted--;
@@ -830,7 +830,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
        if (parent_nd) {
                detach_mnt(source_mnt, parent_nd);
                attach_mnt(source_mnt, nd);
-               touch_namespace(current->nsproxy->namespace);
+               touch_mnt_namespace(current->nsproxy->mnt_ns);
        } else {
                mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
                commit_tree(source_mnt);
@@ -1145,9 +1145,9 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
         */
        if (!propagate_mount_busy(mnt, 2)) {
                /* delete from the namespace */
-               touch_namespace(mnt->mnt_namespace);
+               touch_mnt_namespace(mnt->mnt_ns);
                list_del_init(&mnt->mnt_list);
-               mnt->mnt_namespace = NULL;
+               mnt->mnt_ns = NULL;
                umount_tree(mnt, 1, umounts);
                spin_unlock(&vfsmount_lock);
        } else {
@@ -1168,7 +1168,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
  */
 static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
 {
-       struct namespace *namespace;
+       struct mnt_namespace *ns;
        struct vfsmount *mnt;
 
        while (!list_empty(graveyard)) {
@@ -1178,10 +1178,10 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
 
                /* don't do anything if the namespace is dead - all the
                 * vfsmounts from it are going away anyway */
-               namespace = mnt->mnt_namespace;
-               if (!namespace || !namespace->root)
+               ns = mnt->mnt_ns;
+               if (!ns || !ns->root)
                        continue;
-               get_namespace(namespace);
+               get_mnt_ns(ns);
 
                spin_unlock(&vfsmount_lock);
                down_write(&namespace_sem);
@@ -1189,7 +1189,7 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
                up_write(&namespace_sem);
                release_mounts(&umounts);
                mntput(mnt);
-               put_namespace(namespace);
+               put_mnt_ns(ns);
                spin_lock(&vfsmount_lock);
        }
 }
@@ -1439,14 +1439,15 @@ dput_out:
  * Allocate a new namespace structure and populate it with contents
  * copied from the namespace of the passed in task structure.
  */
-struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
+struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
+               struct fs_struct *fs)
 {
-       struct namespace *namespace = tsk->nsproxy->namespace;
-       struct namespace *new_ns;
+       struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns;
+       struct mnt_namespace *new_ns;
        struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
        struct vfsmount *p, *q;
 
-       new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
+       new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
        if (!new_ns)
                return NULL;
 
@@ -1457,7 +1458,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
 
        down_write(&namespace_sem);
        /* First pass: copy the tree topology */
-       new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root,
+       new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
                                        CL_COPY_ALL | CL_EXPIRE);
        if (!new_ns->root) {
                up_write(&namespace_sem);
@@ -1473,10 +1474,10 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
         * as belonging to new namespace.  We have already acquired a private
         * fs_struct, so tsk->fs->lock is not needed.
         */
-       p = namespace->root;
+       p = mnt_ns->root;
        q = new_ns->root;
        while (p) {
-               q->mnt_namespace = new_ns;
+               q->mnt_ns = new_ns;
                if (fs) {
                        if (p == fs->rootmnt) {
                                rootmnt = p;
@@ -1491,7 +1492,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
                                fs->altrootmnt = mntget(q);
                        }
                }
-               p = next_mnt(p, namespace->root);
+               p = next_mnt(p, mnt_ns->root);
                q = next_mnt(q, new_ns->root);
        }
        up_write(&namespace_sem);
@@ -1506,16 +1507,16 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
        return new_ns;
 }
 
-int copy_namespace(int flags, struct task_struct *tsk)
+int copy_mnt_ns(int flags, struct task_struct *tsk)
 {
-       struct namespace *namespace = tsk->nsproxy->namespace;
-       struct namespace *new_ns;
+       struct mnt_namespace *ns = tsk->nsproxy->mnt_ns;
+       struct mnt_namespace *new_ns;
        int err = 0;
 
-       if (!namespace)
+       if (!ns)
                return 0;
 
-       get_namespace(namespace);
+       get_mnt_ns(ns);
 
        if (!(flags & CLONE_NEWNS))
                return 0;
@@ -1525,16 +1526,16 @@ int copy_namespace(int flags, struct task_struct *tsk)
                goto out;
        }
 
-       new_ns = dup_namespace(tsk, tsk->fs);
+       new_ns = dup_mnt_ns(tsk, tsk->fs);
        if (!new_ns) {
                err = -ENOMEM;
                goto out;
        }
 
-       tsk->nsproxy->namespace = new_ns;
+       tsk->nsproxy->mnt_ns = new_ns;
 
 out:
-       put_namespace(namespace);
+       put_mnt_ns(ns);
        return err;
 }
 
@@ -1754,7 +1755,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
        detach_mnt(user_nd.mnt, &root_parent);
        attach_mnt(user_nd.mnt, &old_nd);     /* mount old root on put_old */
        attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */
-       touch_namespace(current->nsproxy->namespace);
+       touch_mnt_namespace(current->nsproxy->mnt_ns);
        spin_unlock(&vfsmount_lock);
        chroot_fs_refs(&user_nd, &new_nd);
        security_sb_post_pivotroot(&user_nd, &new_nd);
@@ -1779,27 +1780,27 @@ out3:
 static void __init init_mount_tree(void)
 {
        struct vfsmount *mnt;
-       struct namespace *namespace;
+       struct mnt_namespace *ns;
 
        mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
        if (IS_ERR(mnt))
                panic("Can't create rootfs");
-       namespace = kmalloc(sizeof(*namespace), GFP_KERNEL);
-       if (!namespace)
+       ns = kmalloc(sizeof(*ns), GFP_KERNEL);
+       if (!ns)
                panic("Can't allocate initial namespace");
-       atomic_set(&namespace->count, 1);
-       INIT_LIST_HEAD(&namespace->list);
-       init_waitqueue_head(&namespace->poll);
-       namespace->event = 0;
-       list_add(&mnt->mnt_list, &namespace->list);
-       namespace->root = mnt;
-       mnt->mnt_namespace = namespace;
-
-       init_task.nsproxy->namespace = namespace;
-       get_namespace(namespace);
-
-       set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
-       set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
+       atomic_set(&ns->count, 1);
+       INIT_LIST_HEAD(&ns->list);
+       init_waitqueue_head(&ns->poll);
+       ns->event = 0;
+       list_add(&mnt->mnt_list, &ns->list);
+       ns->root = mnt;
+       mnt->mnt_ns = ns;
+
+       init_task.nsproxy->mnt_ns = ns;
+       get_mnt_ns(ns);
+
+       set_fs_pwd(current->fs, ns->root, ns->root->mnt_root);
+       set_fs_root(current->fs, ns->root, ns->root->mnt_root);
 }
 
 void __init mnt_init(unsigned long mempages)
@@ -1860,11 +1861,11 @@ void __init mnt_init(unsigned long mempages)
        init_mount_tree();
 }
 
-void __put_namespace(struct namespace *namespace)
+void __put_mnt_ns(struct mnt_namespace *ns)
 {
-       struct vfsmount *root = namespace->root;
+       struct vfsmount *root = ns->root;
        LIST_HEAD(umount_list);
-       namespace->root = NULL;
+       ns->root = NULL;
        spin_unlock(&vfsmount_lock);
        down_write(&namespace_sem);
        spin_lock(&vfsmount_lock);
@@ -1872,5 +1873,5 @@ void __put_namespace(struct namespace *namespace)
        spin_unlock(&vfsmount_lock);
        up_write(&namespace_sem);
        release_mounts(&umount_list);
-       kfree(namespace);
+       kfree(ns);
 }
index 458b3b7..7374777 100644 (file)
@@ -402,7 +402,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
 
 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct page *page = NULL;
        struct ncp_server *server = NCP_SERVER(inode);
@@ -554,7 +554,7 @@ static int
 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
                struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
 {
-       struct dentry *newdent, *dentry = filp->f_dentry;
+       struct dentry *newdent, *dentry = filp->f_path.dentry;
        struct inode *newino, *inode = dentry->d_inode;
        struct ncp_cache_control ctl = *ctrl;
        struct qstr qname;
@@ -649,7 +649,7 @@ static void
 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
                        struct ncp_cache_control *ctl)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct ncp_server *server = NCP_SERVER(inode);
        struct ncp_volume_info info;
@@ -685,7 +685,7 @@ static void
 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
                                                struct ncp_cache_control *ctl)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *dir = dentry->d_inode;
        struct ncp_server *server = NCP_SERVER(dir);
        struct nw_search_sequence seq;
index df37524..b91fea0 100644 (file)
@@ -101,7 +101,7 @@ out:
 static ssize_t
 ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        size_t already_read = 0;
        off_t pos;
@@ -182,7 +182,7 @@ outrel:
 static ssize_t
 ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        size_t already_written = 0;
        off_t pos;
index 42e3bef..47462ac 100644 (file)
@@ -40,12 +40,12 @@ static void ncp_delete_inode(struct inode *);
 static void ncp_put_super(struct super_block *);
 static int  ncp_statfs(struct dentry *, struct kstatfs *);
 
-static kmem_cache_t * ncp_inode_cachep;
+static struct kmem_cache * ncp_inode_cachep;
 
 static struct inode *ncp_alloc_inode(struct super_block *sb)
 {
        struct ncp_inode_info *ei;
-       ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, SLAB_KERNEL);
+       ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -56,7 +56,7 @@ static void ncp_destroy_inode(struct inode *inode)
        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
 
@@ -471,7 +471,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        if (!ncp_filp)
                goto out;
        error = -ENOTSOCK;
-       sock_inode = ncp_filp->f_dentry->d_inode;
+       sock_inode = ncp_filp->f_path.dentry->d_inode;
        if (!S_ISSOCK(sock_inode->i_mode))
                goto out_fput;
        sock = SOCKET_I(sock_inode);
@@ -504,7 +504,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                if (!server->info_filp)
                        goto out_fput;
                error = -ENOTSOCK;
-               sock_inode = server->info_filp->f_dentry->d_inode;
+               sock_inode = server->info_filp->f_path.dentry->d_inode;
                if (!S_ISSOCK(sock_inode->i_mode))
                        goto out_fput2;
                info_sock = SOCKET_I(sock_inode);
@@ -577,12 +577,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
                server->rcv.len = 10;
                server->rcv.state = 0;
-               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc, server);
-               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server);
+               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
+               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
                sock->sk->sk_write_space = ncp_tcp_write_space;
        } else {
-               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server);
-               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server);
+               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
+               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
                server->timeout_tm.data = (unsigned long)server;
                server->timeout_tm.function = ncpdgram_timeout_call;
        }
index 589d1ea..8843a83 100644 (file)
@@ -35,7 +35,7 @@ static int
 ncp_get_fs_info(struct ncp_server * server, struct file *file,
                struct ncp_fs_info __user *arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct ncp_fs_info info;
 
        if ((file_permission(file, MAY_WRITE) != 0)
@@ -65,7 +65,7 @@ static int
 ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
                   struct ncp_fs_info_v2 __user * arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct ncp_fs_info_v2 info2;
 
        if ((file_permission(file, MAY_WRITE) != 0)
@@ -136,7 +136,7 @@ static int
 ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
                   struct compat_ncp_fs_info_v2 __user * arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct compat_ncp_fs_info_v2 info2;
 
        if ((file_permission(file, MAY_WRITE) != 0)
@@ -824,7 +824,7 @@ outrel:
 #ifdef CONFIG_COMPAT
 long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int ret;
 
        lock_kernel();
index e7d5a30..70a6911 100644 (file)
@@ -29,7 +29,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
                                     unsigned long address, int *type)
 {
        struct file *file = area->vm_file;
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct page* page;
        char *pg_addr;
@@ -106,7 +106,7 @@ static struct vm_operations_struct ncp_file_mmap =
 /* This is used for a general mmap of a ncp file */
 int ncp_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        
        DPRINTK("ncp_mmap: called\n");
 
index 11c2b25..e496d8b 100644 (file)
@@ -350,9 +350,10 @@ static void info_server(struct ncp_server *server, unsigned int id, const void *
        }
 }
 
-void ncpdgram_rcv_proc(void *s)
+void ncpdgram_rcv_proc(struct work_struct *work)
 {
-       struct ncp_server *server = s;
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, rcv.tq);
        struct socket* sock;
        
        sock = server->ncp_sock;
@@ -468,9 +469,10 @@ static void __ncpdgram_timeout_proc(struct ncp_server *server)
        }
 }
 
-void ncpdgram_timeout_proc(void *s)
+void ncpdgram_timeout_proc(struct work_struct *work)
 {
-       struct ncp_server *server = s;
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, timeout_tq);
        mutex_lock(&server->rcv.creq_mutex);
        __ncpdgram_timeout_proc(server);
        mutex_unlock(&server->rcv.creq_mutex);
@@ -652,18 +654,20 @@ skipdata:;
        }
 }
 
-void ncp_tcp_rcv_proc(void *s)
+void ncp_tcp_rcv_proc(struct work_struct *work)
 {
-       struct ncp_server *server = s;
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, rcv.tq);
 
        mutex_lock(&server->rcv.creq_mutex);
        __ncptcp_rcv_proc(server);
        mutex_unlock(&server->rcv.creq_mutex);
 }
 
-void ncp_tcp_tx_proc(void *s)
+void ncp_tcp_tx_proc(struct work_struct *work)
 {
-       struct ncp_server *server = s;
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, tx.tq);
        
        mutex_lock(&server->rcv.creq_mutex);
        __ncptcp_try_send(server);
index 5fea638..23ab145 100644 (file)
@@ -143,7 +143,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
        INIT_LIST_HEAD(&clp->cl_state_owners);
        INIT_LIST_HEAD(&clp->cl_unused);
        spin_lock_init(&clp->cl_lock);
-       INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
+       INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
        rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
        clp->cl_boot_time = CURRENT_TIME;
        clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
index b34cd16..dee3d6c 100644 (file)
@@ -172,7 +172,7 @@ static
 int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 {
        struct file     *file = desc->file;
-       struct inode    *inode = file->f_dentry->d_inode;
+       struct inode    *inode = file->f_path.dentry->d_inode;
        struct rpc_cred *cred = nfs_file_cred(file);
        unsigned long   timestamp;
        int             error;
@@ -183,7 +183,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 
  again:
        timestamp = jiffies;
-       error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page,
+       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
                                          NFS_SERVER(inode)->dtsize, desc->plus);
        if (error < 0) {
                /* We requested READDIRPLUS, but the server doesn't grok it */
@@ -308,7 +308,7 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc)
 static inline
 int find_dirent_page(nfs_readdir_descriptor_t *desc)
 {
-       struct inode    *inode = desc->file->f_dentry->d_inode;
+       struct inode    *inode = desc->file->f_path.dentry->d_inode;
        struct page     *page;
        int             status;
 
@@ -464,7 +464,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                     filldir_t filldir)
 {
        struct file     *file = desc->file;
-       struct inode    *inode = file->f_dentry->d_inode;
+       struct inode    *inode = file->f_path.dentry->d_inode;
        struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        int             status;
@@ -477,7 +477,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                status = -ENOMEM;
                goto out;
        }
-       desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
+       desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
                                                page,
                                                NFS_SERVER(inode)->dtsize,
                                                desc->plus);
@@ -516,7 +516,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
  */
 static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dentry   *dentry = filp->f_dentry;
+       struct dentry   *dentry = filp->f_path.dentry;
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
@@ -599,7 +599,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
 {
-       mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+       mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
        switch (origin) {
                case 1:
                        offset += filp->f_pos;
@@ -615,7 +615,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
                ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
        }
 out:
-       mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
        return offset;
 }
 
@@ -1102,7 +1102,7 @@ no_open:
 
 static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
 {
-       struct dentry *parent = desc->file->f_dentry;
+       struct dentry *parent = desc->file->f_path.dentry;
        struct inode *dir = parent->d_inode;
        struct nfs_entry *entry = desc->entry;
        struct dentry *dentry, *alias;
index bdfabf8..bd21d7f 100644 (file)
@@ -58,7 +58,7 @@
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
-static kmem_cache_t *nfs_direct_cachep;
+static struct kmem_cache *nfs_direct_cachep;
 
 /*
  * This represents a set of asynchronous requests that we're waiting on
@@ -116,7 +116,7 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
 {
        dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
-                       iocb->ki_filp->f_dentry->d_name.name,
+                       iocb->ki_filp->f_path.dentry->d_name.name,
                        (long long) pos, nr_segs);
 
        return -EINVAL;
@@ -143,7 +143,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
 {
        struct nfs_direct_req *dreq;
 
-       dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL);
+       dreq = kmem_cache_alloc(nfs_direct_cachep, GFP_KERNEL);
        if (!dreq)
                return NULL;
 
@@ -307,9 +307,7 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
 
                data->task.tk_cookie = (unsigned long) inode;
 
-               lock_kernel();
                rpc_execute(&data->task);
-               unlock_kernel();
 
                dfprintk(VFS, "NFS: %5u initiated direct read call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
                                data->task.tk_pid,
@@ -475,9 +473,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 
        dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
-       lock_kernel();
        rpc_execute(&data->task);
-       unlock_kernel();
 }
 
 static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode)
@@ -641,9 +637,7 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
                data->task.tk_priority = RPC_PRIORITY_NORMAL;
                data->task.tk_cookie = (unsigned long) inode;
 
-               lock_kernel();
                rpc_execute(&data->task);
-               unlock_kernel();
 
                dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
                                data->task.tk_pid,
@@ -740,8 +734,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
        size_t count = iov[0].iov_len;
 
        dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
-               file->f_dentry->d_parent->d_name.name,
-               file->f_dentry->d_name.name,
+               file->f_path.dentry->d_parent->d_name.name,
+               file->f_path.dentry->d_name.name,
                (unsigned long) count, (long long) pos);
 
        if (nr_segs != 1)
@@ -804,8 +798,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
        size_t count = iov[0].iov_len;
 
        dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
-               file->f_dentry->d_parent->d_name.name,
-               file->f_dentry->d_name.name,
+               file->f_path.dentry->d_parent->d_name.name,
+               file->f_path.dentry->d_name.name,
                (unsigned long) count, (long long) pos);
 
        if (nr_segs != 1)
index cc93865..0dd6be3 100644 (file)
@@ -176,7 +176,7 @@ static int
 nfs_file_flush(struct file *file, fl_owner_t id)
 {
        struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
-       struct inode    *inode = file->f_dentry->d_inode;
+       struct inode    *inode = file->f_path.dentry->d_inode;
        int             status;
 
        dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
@@ -201,7 +201,7 @@ static ssize_t
 nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
                unsigned long nr_segs, loff_t pos)
 {
-       struct dentry * dentry = iocb->ki_filp->f_dentry;
+       struct dentry * dentry = iocb->ki_filp->f_path.dentry;
        struct inode * inode = dentry->d_inode;
        ssize_t result;
        size_t count = iov_length(iov, nr_segs);
@@ -226,7 +226,7 @@ static ssize_t
 nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
                read_actor_t actor, void *target)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        ssize_t res;
 
@@ -243,7 +243,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
 static int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int     status;
 
@@ -307,28 +307,28 @@ static int nfs_commit_write(struct file *file, struct page *page, unsigned offse
 
 static void nfs_invalidate_page(struct page *page, unsigned long offset)
 {
-       struct inode *inode = page->mapping->host;
-
+       if (offset != 0)
+               return;
        /* Cancel any unstarted writes on this page */
-       if (offset == 0)
-               nfs_sync_inode_wait(inode, page->index, 1, FLUSH_INVALIDATE);
+       nfs_wb_page_priority(page->mapping->host, page, FLUSH_INVALIDATE);
 }
 
 static int nfs_release_page(struct page *page, gfp_t gfp)
 {
-       if (gfp & __GFP_FS)
-               return !nfs_wb_page(page->mapping->host, page);
-       else
-               /*
-                * Avoid deadlock on nfs_wait_on_request().
-                */
+       /*
+        * Avoid deadlock on nfs_wait_on_request().
+        */
+       if (!(gfp & __GFP_FS))
                return 0;
+       /* Hack... Force nfs_wb_page() to write out the page */
+       SetPageDirty(page);
+       return !nfs_wb_page(page->mapping->host, page);
 }
 
 const struct address_space_operations nfs_file_aops = {
        .readpage = nfs_readpage,
        .readpages = nfs_readpages,
-       .set_page_dirty = __set_page_dirty_nobuffers,
+       .set_page_dirty = nfs_set_page_dirty,
        .writepage = nfs_writepage,
        .writepages = nfs_writepages,
        .prepare_write = nfs_prepare_write,
@@ -343,7 +343,7 @@ const struct address_space_operations nfs_file_aops = {
 static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
-       struct dentry * dentry = iocb->ki_filp->f_dentry;
+       struct dentry * dentry = iocb->ki_filp->f_path.dentry;
        struct inode * inode = dentry->d_inode;
        ssize_t result;
        size_t count = iov_length(iov, nr_segs);
@@ -375,6 +375,12 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
 
        nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
        result = generic_file_aio_write(iocb, iov, nr_segs, pos);
+       /* Return error values for O_SYNC and IS_SYNC() */
+       if (result >= 0 && (IS_SYNC(inode) || (iocb->ki_filp->f_flags & O_SYNC))) {
+               int err = nfs_fsync(iocb->ki_filp, dentry, 1);
+               if (err < 0)
+                       result = err;
+       }
 out:
        return result;
 
@@ -529,8 +535,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
        dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
-                       filp->f_dentry->d_inode->i_sb->s_id,
-                       filp->f_dentry->d_inode->i_ino,
+                       filp->f_path.dentry->d_inode->i_sb->s_id,
+                       filp->f_path.dentry->d_inode->i_ino,
                        fl->fl_type, fl->fl_flags);
 
        /*
index 20c6f39..8391bd7 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/security.h>
 
 #include <asm/system.h>
index 82ad711..9d4a6b2 100644 (file)
@@ -377,7 +377,7 @@ idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
 static ssize_t
 idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
-        struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+        struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
        struct idmap *idmap = (struct idmap *)rpci->private;
        struct idmap_msg im_in, *im = &idmap->idmap_im;
        struct idmap_hashtable *h;
index 08cc4c5..63e4702 100644 (file)
@@ -55,7 +55,7 @@ static int nfs_update_inode(struct inode *, struct nfs_fattr *);
 
 static void nfs_zap_acl_cache(struct inode *);
 
-static kmem_cache_t * nfs_inode_cachep;
+static struct kmem_cache * nfs_inode_cachep;
 
 static inline unsigned long
 nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
@@ -422,7 +422,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
        int err;
 
        /* Flush out writes to the server in order to update c/mtime */
-       nfs_sync_inode_wait(inode, 0, 0, FLUSH_NOCOMMIT);
+       nfs_sync_mapping_range(inode->i_mapping, 0, 0, FLUSH_NOCOMMIT);
 
        /*
         * We may force a getattr if the user cares about atime.
@@ -496,7 +496,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
  */
 static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        filp->private_data = get_nfs_open_context(ctx);
@@ -528,7 +528,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
 
 static void nfs_file_clear_open_context(struct file *filp)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
 
        if (ctx) {
@@ -551,7 +551,7 @@ int nfs_open(struct inode *inode, struct file *filp)
        cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred);
+       ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
        put_rpccred(cred);
        if (ctx == NULL)
                return -ENOMEM;
@@ -1080,7 +1080,7 @@ void nfs4_clear_inode(struct inode *inode)
 struct inode *nfs_alloc_inode(struct super_block *sb)
 {
        struct nfs_inode *nfsi;
-       nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
+       nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, GFP_KERNEL);
        if (!nfsi)
                return NULL;
        nfsi->flags = 0UL;
@@ -1111,7 +1111,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
 #endif
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct nfs_inode *nfsi = (struct nfs_inode *) foo;
 
index d205466..a28f6ce 100644 (file)
@@ -217,3 +217,21 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
        if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
                sb->s_maxbytes = MAX_LFS_FILESIZE;
 }
+
+/*
+ * Determine the number of bytes of data the page contains
+ */
+static inline
+unsigned int nfs_page_length(struct page *page)
+{
+       loff_t i_size = i_size_read(page->mapping->host);
+
+       if (i_size > 0) {
+               pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+               if (page->index < end_index)
+                       return PAGE_CACHE_SIZE;
+               if (page->index == end_index)
+                       return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1;
+       }
+       return 0;
+}
index ec1114b..371b804 100644 (file)
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
-static void nfs_expire_automounts(void *list);
+static void nfs_expire_automounts(struct work_struct *work);
 
 LIST_HEAD(nfs_automount_list);
-static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
+static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
 static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
@@ -164,9 +164,9 @@ struct inode_operations nfs_referral_inode_operations = {
        .follow_link    = nfs_follow_mountpoint,
 };
 
-static void nfs_expire_automounts(void *data)
+static void nfs_expire_automounts(struct work_struct *work)
 {
-       struct list_head *list = (struct list_head *)data;
+       struct list_head *list = &nfs_automount_list;
 
        mark_mounts_for_expiry(list);
        if (!list_empty(list))
index e5f128f..acd8fe9 100644 (file)
@@ -276,51 +276,6 @@ static int nfs3_proc_read(struct nfs_read_data *rdata)
        return status;
 }
 
-static int nfs3_proc_write(struct nfs_write_data *wdata)
-{
-       int                     rpcflags = wdata->flags;
-       struct inode *          inode = wdata->inode;
-       struct nfs_fattr *      fattr = wdata->res.fattr;
-       struct rpc_message      msg = {
-               .rpc_proc       = &nfs3_procedures[NFS3PROC_WRITE],
-               .rpc_argp       = &wdata->args,
-               .rpc_resp       = &wdata->res,
-               .rpc_cred       = wdata->cred,
-       };
-       int                     status;
-
-       dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
-                       (long long) wdata->args.offset);
-       nfs_fattr_init(fattr);
-       status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
-       if (status >= 0)
-               nfs_post_op_update_inode(inode, fattr);
-       dprintk("NFS reply write: %d\n", status);
-       return status < 0? status : wdata->res.count;
-}
-
-static int nfs3_proc_commit(struct nfs_write_data *cdata)
-{
-       struct inode *          inode = cdata->inode;
-       struct nfs_fattr *      fattr = cdata->res.fattr;
-       struct rpc_message      msg = {
-               .rpc_proc       = &nfs3_procedures[NFS3PROC_COMMIT],
-               .rpc_argp       = &cdata->args,
-               .rpc_resp       = &cdata->res,
-               .rpc_cred       = cdata->cred,
-       };
-       int                     status;
-
-       dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
-                       (long long) cdata->args.offset);
-       nfs_fattr_init(fattr);
-       status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-       if (status >= 0)
-               nfs_post_op_update_inode(inode, fattr);
-       dprintk("NFS reply commit: %d\n", status);
-       return status;
-}
-
 /*
  * Create a regular file.
  * For now, we don't implement O_EXCL.
@@ -369,7 +324,7 @@ again:
 
        /* If the server doesn't support the exclusive creation semantics,
         * try again with simple 'guarded' mode. */
-       if (status == NFSERR_NOTSUPP) {
+       if (status == -ENOTSUPP) {
                switch (arg.createmode) {
                        case NFS3_CREATE_EXCLUSIVE:
                                arg.createmode = NFS3_CREATE_GUARDED;
@@ -690,8 +645,6 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
        };
        int                     status;
 
-       lock_kernel();
-
        if (plus)
                msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
 
@@ -702,7 +655,6 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply readdir: %d\n", status);
-       unlock_kernel();
        return status;
 }
 
@@ -889,7 +841,7 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
-       return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
+       return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
 }
 
 const struct nfs_rpc_ops nfs_v3_clientops = {
@@ -904,8 +856,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .access         = nfs3_proc_access,
        .readlink       = nfs3_proc_readlink,
        .read           = nfs3_proc_read,
-       .write          = nfs3_proc_write,
-       .commit         = nfs3_proc_commit,
        .create         = nfs3_proc_create,
        .remove         = nfs3_proc_remove,
        .unlink_setup   = nfs3_proc_unlink_setup,
index 6f34667..c26cd97 100644 (file)
@@ -185,7 +185,7 @@ extern const u32 nfs4_fs_locations_bitmap[2];
 extern void nfs4_schedule_state_renewal(struct nfs_client *);
 extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
 extern void nfs4_kill_renewd(struct nfs_client *);
-extern void nfs4_renew_state(void *);
+extern void nfs4_renew_state(struct work_struct *);
 
 /* nfs4state.c */
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
index 8118036..ee458ae 100644 (file)
@@ -636,7 +636,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
                smp_wmb();
        } else
                status = data->rpc_status;
-       rpc_release_task(task);
+       rpc_put_task(task);
        return status;
 }
 
@@ -742,7 +742,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
                smp_wmb();
        } else
                status = data->rpc_status;
-       rpc_release_task(task);
+       rpc_put_task(task);
        if (status != 0)
                return status;
 
@@ -1775,89 +1775,6 @@ static int nfs4_proc_read(struct nfs_read_data *rdata)
        return err;
 }
 
-static int _nfs4_proc_write(struct nfs_write_data *wdata)
-{
-       int rpcflags = wdata->flags;
-       struct inode *inode = wdata->inode;
-       struct nfs_fattr *fattr = wdata->res.fattr;
-       struct nfs_server *server = NFS_SERVER(inode);
-       struct rpc_message msg = {
-               .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
-               .rpc_argp       = &wdata->args,
-               .rpc_resp       = &wdata->res,
-               .rpc_cred       = wdata->cred,
-       };
-       int status;
-
-       dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
-                       (long long) wdata->args.offset);
-
-       wdata->args.bitmask = server->attr_bitmask;
-       wdata->res.server = server;
-       wdata->timestamp = jiffies;
-       nfs_fattr_init(fattr);
-       status = rpc_call_sync(server->client, &msg, rpcflags);
-       dprintk("NFS reply write: %d\n", status);
-       if (status < 0)
-               return status;
-       renew_lease(server, wdata->timestamp);
-       nfs_post_op_update_inode(inode, fattr);
-       return wdata->res.count;
-}
-
-static int nfs4_proc_write(struct nfs_write_data *wdata)
-{
-       struct nfs4_exception exception = { };
-       int err;
-       do {
-               err = nfs4_handle_exception(NFS_SERVER(wdata->inode),
-                               _nfs4_proc_write(wdata),
-                               &exception);
-       } while (exception.retry);
-       return err;
-}
-
-static int _nfs4_proc_commit(struct nfs_write_data *cdata)
-{
-       struct inode *inode = cdata->inode;
-       struct nfs_fattr *fattr = cdata->res.fattr;
-       struct nfs_server *server = NFS_SERVER(inode);
-       struct rpc_message msg = {
-               .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
-               .rpc_argp       = &cdata->args,
-               .rpc_resp       = &cdata->res,
-               .rpc_cred       = cdata->cred,
-       };
-       int status;
-
-       dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
-                       (long long) cdata->args.offset);
-
-       cdata->args.bitmask = server->attr_bitmask;
-       cdata->res.server = server;
-       cdata->timestamp = jiffies;
-       nfs_fattr_init(fattr);
-       status = rpc_call_sync(server->client, &msg, 0);
-       if (status >= 0)
-               renew_lease(server, cdata->timestamp);
-       dprintk("NFS reply commit: %d\n", status);
-       if (status >= 0)
-               nfs_post_op_update_inode(inode, fattr);
-       return status;
-}
-
-static int nfs4_proc_commit(struct nfs_write_data *cdata)
-{
-       struct nfs4_exception exception = { };
-       int err;
-       do {
-               err = nfs4_handle_exception(NFS_SERVER(cdata->inode),
-                               _nfs4_proc_commit(cdata),
-                               &exception);
-       } while (exception.retry);
-       return err;
-}
-
 /*
  * Got race?
  * We will need to arrange for the VFS layer to provide an atomic open.
@@ -2223,13 +2140,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                        dentry->d_parent->d_name.name,
                        dentry->d_name.name,
                        (unsigned long long)cookie);
-       lock_kernel();
        nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
        res.pgbase = args.pgbase;
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        if (status == 0)
                memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
-       unlock_kernel();
        dprintk("%s: returns %d\n", __FUNCTION__, status);
        return status;
 }
@@ -3067,7 +2982,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
                if (status == 0)
                        nfs_post_op_update_inode(inode, &data->fattr);
        }
-       rpc_release_task(task);
+       rpc_put_task(task);
        return status;
 }
 
@@ -3314,7 +3229,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        if (IS_ERR(task))
                goto out;
        status = nfs4_wait_for_completion_rpc_task(task);
-       rpc_release_task(task);
+       rpc_put_task(task);
 out:
        return status;
 }
@@ -3430,7 +3345,7 @@ static void nfs4_lock_release(void *calldata)
                task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
                                data->arg.lock_seqid);
                if (!IS_ERR(task))
-                       rpc_release_task(task);
+                       rpc_put_task(task);
                dprintk("%s: cancelling lock!\n", __FUNCTION__);
        } else
                nfs_free_seqid(data->arg.lock_seqid);
@@ -3472,7 +3387,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
                        ret = -EAGAIN;
        } else
                data->cancelled = 1;
-       rpc_release_task(task);
+       rpc_put_task(task);
        dprintk("%s: done, ret = %d!\n", __FUNCTION__, ret);
        return ret;
 }
@@ -3732,8 +3647,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .access         = nfs4_proc_access,
        .readlink       = nfs4_proc_readlink,
        .read           = nfs4_proc_read,
-       .write          = nfs4_proc_write,
-       .commit         = nfs4_proc_commit,
        .create         = nfs4_proc_create,
        .remove         = nfs4_proc_remove,
        .unlink_setup   = nfs4_proc_unlink_setup,
index 7b6df18..8232985 100644 (file)
 #define NFSDBG_FACILITY        NFSDBG_PROC
 
 void
-nfs4_renew_state(void *data)
+nfs4_renew_state(struct work_struct *work)
 {
-       struct nfs_client *clp = (struct nfs_client *)data;
+       struct nfs_client *clp =
+               container_of(work, struct nfs_client, cl_renewd.work);
        struct rpc_cred *cred;
        long lease, timeout;
        unsigned long last, now;
index 829af32..ca4b1d4 100644 (file)
 #include <linux/nfs_page.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
+#include <linux/writeback.h>
 
 #define NFS_PARANOIA 1
 
-static kmem_cache_t *nfs_page_cachep;
+static struct kmem_cache *nfs_page_cachep;
 
 static inline struct nfs_page *
 nfs_page_alloc(void)
 {
        struct nfs_page *p;
-       p = kmem_cache_alloc(nfs_page_cachep, SLAB_KERNEL);
+       p = kmem_cache_alloc(nfs_page_cachep, GFP_KERNEL);
        if (p) {
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->wb_list);
@@ -268,11 +269,10 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
 
 #define NFS_SCAN_MAXENTRIES 16
 /**
- * nfs_scan_lock_dirty - Scan the radix tree for dirty requests
- * @nfsi: NFS inode
+ * nfs_scan_dirty - Scan the radix tree for dirty requests
+ * @mapping: pointer to address space
+ * @wbc: writeback_control structure
  * @dst: Destination list
- * @idx_start: lower bound of page->index to scan
- * @npages: idx_start + npages sets the upper bound to scan.
  *
  * Moves elements from one of the inode request lists.
  * If the number of requests is set to 0, the entire address_space
@@ -280,46 +280,63 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
  * The requests are *not* checked to ensure that they form a contiguous set.
  * You must be holding the inode's req_lock when calling this function
  */
-int
-nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
-             unsigned long idx_start, unsigned int npages)
+long nfs_scan_dirty(struct address_space *mapping,
+                       struct writeback_control *wbc,
+                       struct list_head *dst)
 {
+       struct nfs_inode *nfsi = NFS_I(mapping->host);
        struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
        struct nfs_page *req;
-       unsigned long idx_end;
+       pgoff_t idx_start, idx_end;
+       long res = 0;
        int found, i;
-       int res;
 
-       res = 0;
-       if (npages == 0)
-               idx_end = ~0;
-       else
-               idx_end = idx_start + npages - 1;
+       if (nfsi->ndirty == 0)
+               return 0;
+       if (wbc->range_cyclic) {
+               idx_start = 0;
+               idx_end = ULONG_MAX;
+       } else if (wbc->range_end == 0) {
+               idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
+               idx_end = ULONG_MAX;
+       } else {
+               idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
+               idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
+       }
 
        for (;;) {
+               unsigned int toscan = NFS_SCAN_MAXENTRIES;
+
                found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
-                               (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,
+                               (void **)&pgvec[0], idx_start, toscan,
                                NFS_PAGE_TAG_DIRTY);
+
+               /* Did we make progress? */
                if (found <= 0)
                        break;
+
                for (i = 0; i < found; i++) {
                        req = pgvec[i];
-                       if (req->wb_index > idx_end)
+                       if (!wbc->range_cyclic && req->wb_index > idx_end)
                                goto out;
 
+                       /* Try to lock request and mark it for writeback */
+                       if (!nfs_set_page_writeback_locked(req))
+                               goto next;
+                       radix_tree_tag_clear(&nfsi->nfs_page_tree,
+                                       req->wb_index, NFS_PAGE_TAG_DIRTY);
+                       nfsi->ndirty--;
+                       nfs_list_remove_request(req);
+                       nfs_list_add_request(req, dst);
+                       res++;
+                       if (res == LONG_MAX)
+                               goto out;
+next:
                        idx_start = req->wb_index + 1;
-
-                       if (nfs_set_page_writeback_locked(req)) {
-                               radix_tree_tag_clear(&nfsi->nfs_page_tree,
-                                               req->wb_index, NFS_PAGE_TAG_DIRTY);
-                               nfs_list_remove_request(req);
-                               nfs_list_add_request(req, dst);
-                               dec_zone_page_state(req->wb_page, NR_FILE_DIRTY);
-                               res++;
-                       }
                }
        }
 out:
+       WARN_ON ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty));
        return res;
 }
 
index 4529cc4..560536a 100644 (file)
@@ -215,32 +215,6 @@ static int nfs_proc_read(struct nfs_read_data *rdata)
        return status;
 }
 
-static int nfs_proc_write(struct nfs_write_data *wdata)
-{
-       int                     flags = wdata->flags;
-       struct inode *          inode = wdata->inode;
-       struct nfs_fattr *      fattr = wdata->res.fattr;
-       struct rpc_message      msg = {
-               .rpc_proc       = &nfs_procedures[NFSPROC_WRITE],
-               .rpc_argp       = &wdata->args,
-               .rpc_resp       = &wdata->res,
-               .rpc_cred       = wdata->cred,
-       };
-       int                     status;
-
-       dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
-                       (long long) wdata->args.offset);
-       nfs_fattr_init(fattr);
-       status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-       if (status >= 0) {
-               nfs_post_op_update_inode(inode, fattr);
-               wdata->res.count = wdata->args.count;
-               wdata->verf.committed = NFS_FILE_SYNC;
-       }
-       dprintk("NFS reply write: %d\n", status);
-       return status < 0? status : wdata->res.count;
-}
-
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                int flags, struct nameidata *nd)
@@ -545,13 +519,10 @@ nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
        };
        int                     status;
 
-       lock_kernel();
-
        dprintk("NFS call  readdir %d\n", (unsigned int)cookie);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 
        dprintk("NFS reply readdir: %d\n", status);
-       unlock_kernel();
        return status;
 }
 
@@ -680,7 +651,7 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
 static int
 nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
-       return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
+       return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
 }
 
 
@@ -696,8 +667,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .access         = NULL,                /* access */
        .readlink       = nfs_proc_readlink,
        .read           = nfs_proc_read,
-       .write          = nfs_proc_write,
-       .commit         = NULL,                /* commit */
        .create         = nfs_proc_create,
        .remove         = nfs_proc_remove,
        .unlink_setup   = nfs_proc_unlink_setup,
index c2e49c3..a9c2652 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <asm/system.h>
 
+#include "internal.h"
 #include "iostat.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
@@ -38,7 +39,7 @@ static int nfs_pagein_one(struct list_head *, struct inode *);
 static const struct rpc_call_ops nfs_read_partial_ops;
 static const struct rpc_call_ops nfs_read_full_ops;
 
-static kmem_cache_t *nfs_rdata_cachep;
+static struct kmem_cache *nfs_rdata_cachep;
 static mempool_t *nfs_rdata_mempool;
 
 #define MIN_POOL_READ  (32)
@@ -46,7 +47,7 @@ static mempool_t *nfs_rdata_mempool;
 struct nfs_read_data *nfs_readdata_alloc(size_t len)
 {
        unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
+       struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS);
 
        if (p) {
                memset(p, 0, sizeof(*p));
@@ -65,32 +66,22 @@ struct nfs_read_data *nfs_readdata_alloc(size_t len)
        return p;
 }
 
-static void nfs_readdata_free(struct nfs_read_data *p)
+static void nfs_readdata_rcu_free(struct rcu_head *head)
 {
+       struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_rdata_mempool);
 }
 
-void nfs_readdata_release(void *data)
+static void nfs_readdata_free(struct nfs_read_data *rdata)
 {
-        nfs_readdata_free(data);
+       call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
 }
 
-static
-unsigned int nfs_page_length(struct inode *inode, struct page *page)
+void nfs_readdata_release(void *data)
 {
-       loff_t i_size = i_size_read(inode);
-       unsigned long idx;
-
-       if (i_size <= 0)
-               return 0;
-       idx = (i_size - 1) >> PAGE_CACHE_SHIFT;
-       if (page->index > idx)
-               return 0;
-       if (page->index != idx)
-               return PAGE_CACHE_SIZE;
-       return 1 + ((i_size - 1) & (PAGE_CACHE_SIZE - 1));
+        nfs_readdata_free(data);
 }
 
 static
@@ -139,12 +130,12 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
 {
        unsigned int    rsize = NFS_SERVER(inode)->rsize;
        unsigned int    count = PAGE_CACHE_SIZE;
-       int             result;
+       int result = -ENOMEM;
        struct nfs_read_data *rdata;
 
        rdata = nfs_readdata_alloc(count);
        if (!rdata)
-               return -ENOMEM;
+               goto out_unlock;
 
        memset(rdata, 0, sizeof(*rdata));
        rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
@@ -212,8 +203,9 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
        result = 0;
 
 io_error:
-       unlock_page(page);
        nfs_readdata_free(rdata);
+out_unlock:
+       unlock_page(page);
        return result;
 }
 
@@ -224,7 +216,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
        struct nfs_page *new;
        unsigned int len;
 
-       len = nfs_page_length(inode, page);
+       len = nfs_page_length(page);
        if (len == 0)
                return nfs_return_empty_page(page);
        new = nfs_create_request(ctx, inode, page, 0, len);
@@ -316,9 +308,7 @@ static void nfs_execute_read(struct nfs_read_data *data)
        sigset_t oldset;
 
        rpc_clnt_sigmask(clnt, &oldset);
-       lock_kernel();
        rpc_execute(&data->task);
-       unlock_kernel();
        rpc_clnt_sigunmask(clnt, &oldset);
 }
 
@@ -454,6 +444,55 @@ nfs_pagein_list(struct list_head *head, int rpages)
        return error;
 }
 
+/*
+ * This is the callback from RPC telling us whether a reply was
+ * received or some error occurred (timeout or socket shutdown).
+ */
+int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
+{
+       int status;
+
+       dprintk("%s: %4d, (status %d)\n", __FUNCTION__, task->tk_pid,
+                       task->tk_status);
+
+       status = NFS_PROTO(data->inode)->read_done(task, data);
+       if (status != 0)
+               return status;
+
+       nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count);
+
+       if (task->tk_status == -ESTALE) {
+               set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode));
+               nfs_mark_for_revalidate(data->inode);
+       }
+       spin_lock(&data->inode->i_lock);
+       NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+       spin_unlock(&data->inode->i_lock);
+       return 0;
+}
+
+static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+{
+       struct nfs_readargs *argp = &data->args;
+       struct nfs_readres *resp = &data->res;
+
+       if (resp->eof || resp->count == argp->count)
+               return 0;
+
+       /* This is a short read! */
+       nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
+       /* Has the server at least made some progress? */
+       if (resp->count == 0)
+               return 0;
+
+       /* Yes, so retry the read at the end of the data */
+       argp->offset += resp->count;
+       argp->pgbase += resp->count;
+       argp->count -= resp->count;
+       rpc_restart_call(task);
+       return -EAGAIN;
+}
+
 /*
  * Handle a read reply that fills part of a page.
  */
@@ -463,12 +502,16 @@ static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
        struct nfs_page *req = data->req;
        struct page *page = req->wb_page;
  
-       if (likely(task->tk_status >= 0))
-               nfs_readpage_truncate_uninitialised_page(data);
-       else
-               SetPageError(page);
        if (nfs_readpage_result(task, data) != 0)
                return;
+
+       if (likely(task->tk_status >= 0)) {
+               nfs_readpage_truncate_uninitialised_page(data);
+               if (nfs_readpage_retry(task, data) != 0)
+                       return;
+       }
+       if (unlikely(task->tk_status < 0))
+               SetPageError(page);
        if (atomic_dec_and_test(&req->wb_complete)) {
                if (!PageError(page))
                        SetPageUptodate(page);
@@ -496,25 +539,13 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
        count += base;
        for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
                SetPageUptodate(*pages);
-       if (count != 0)
+       if (count == 0)
+               return;
+       /* Was this a short read? */
+       if (data->res.eof || data->res.count == data->args.count)
                SetPageUptodate(*pages);
 }
 
-static void nfs_readpage_set_pages_error(struct nfs_read_data *data)
-{
-       unsigned int count = data->args.count;
-       unsigned int base = data->args.pgbase;
-       struct page **pages;
-
-       pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
-       base &= ~PAGE_CACHE_MASK;
-       count += base;
-       for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
-               SetPageError(*pages);
-       if (count != 0)
-               SetPageError(*pages);
-}
-
 /*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
@@ -523,19 +554,20 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
 {
        struct nfs_read_data *data = calldata;
 
+       if (nfs_readpage_result(task, data) != 0)
+               return;
        /*
-        * Note: nfs_readpage_result may change the values of
+        * Note: nfs_readpage_retry may change the values of
         * data->args. In the multi-page case, we therefore need
-        * to ensure that we call the next nfs_readpage_set_page_uptodate()
-        * first in the multi-page case.
+        * to ensure that we call nfs_readpage_set_pages_uptodate()
+        * first.
         */
        if (likely(task->tk_status >= 0)) {
                nfs_readpage_truncate_uninitialised_page(data);
                nfs_readpage_set_pages_uptodate(data);
-       } else
-               nfs_readpage_set_pages_error(data);
-       if (nfs_readpage_result(task, data) != 0)
-               return;
+               if (nfs_readpage_retry(task, data) != 0)
+                       return;
+       }
        while (!list_empty(&data->pages)) {
                struct nfs_page *req = nfs_list_entry(data->pages.next);
 
@@ -549,50 +581,6 @@ static const struct rpc_call_ops nfs_read_full_ops = {
        .rpc_release = nfs_readdata_release,
 };
 
-/*
- * This is the callback from RPC telling us whether a reply was
- * received or some error occurred (timeout or socket shutdown).
- */
-int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
-{
-       struct nfs_readargs *argp = &data->args;
-       struct nfs_readres *resp = &data->res;
-       int status;
-
-       dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
-               task->tk_pid, task->tk_status);
-
-       status = NFS_PROTO(data->inode)->read_done(task, data);
-       if (status != 0)
-               return status;
-
-       nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count);
-
-       if (task->tk_status < 0) {
-               if (task->tk_status == -ESTALE) {
-                       set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode));
-                       nfs_mark_for_revalidate(data->inode);
-               }
-       } else if (resp->count < argp->count && !resp->eof) {
-               /* This is a short read! */
-               nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
-               /* Has the server at least made some progress? */
-               if (resp->count != 0) {
-                       /* Yes, so retry the read at the end of the data */
-                       argp->offset += resp->count;
-                       argp->pgbase += resp->count;
-                       argp->count -= resp->count;
-                       rpc_restart_call(task);
-                       return -EAGAIN;
-               }
-               task->tk_status = -EIO;
-       }
-       spin_lock(&data->inode->i_lock);
-       NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
-       spin_unlock(&data->inode->i_lock);
-       return 0;
-}
-
 /*
  * Read a page over NFS.
  * We read the page synchronously in the following case:
@@ -626,9 +614,10 @@ int nfs_readpage(struct file *file, struct page *page)
                goto out_error;
 
        if (file == NULL) {
+               error = -EBADF;
                ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
                if (ctx == NULL)
-                       return -EBADF;
+                       goto out_error;
        } else
                ctx = get_nfs_open_context((struct nfs_open_context *)
                                file->private_data);
@@ -663,7 +652,7 @@ readpage_async_filler(void *data, struct page *page)
        unsigned int len;
 
        nfs_wb_page(inode, page);
-       len = nfs_page_length(inode, page);
+       len = nfs_page_length(page);
        if (len == 0)
                return nfs_return_empty_page(page);
        new = nfs_create_request(desc->ctx, inode, page, 0, len);
index 600bbe6..6c68611 100644 (file)
@@ -33,9 +33,7 @@ static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
        int error;
 
-       lock_kernel();
        error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
-       unlock_kernel();
        if (error < 0)
                goto error;
        SetPageUptodate(page);
index 883dd4a..345492e 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/smp_lock.h>
 
 #include "delegation.h"
+#include "internal.h"
 #include "iostat.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
  * Local function declarations
  */
 static struct nfs_page * nfs_update_request(struct nfs_open_context*,
-                                           struct inode *,
                                            struct page *,
                                            unsigned int, unsigned int);
+static void nfs_mark_request_dirty(struct nfs_page *req);
 static int nfs_wait_on_write_congestion(struct address_space *, int);
 static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
-static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
-                          unsigned int npages, int how);
+static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how);
 static const struct rpc_call_ops nfs_write_partial_ops;
 static const struct rpc_call_ops nfs_write_full_ops;
 static const struct rpc_call_ops nfs_commit_ops;
 
-static kmem_cache_t *nfs_wdata_cachep;
+static struct kmem_cache *nfs_wdata_cachep;
 static mempool_t *nfs_wdata_mempool;
 static mempool_t *nfs_commit_mempool;
 
@@ -93,7 +93,7 @@ static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
 
 struct nfs_write_data *nfs_commit_alloc(void)
 {
-       struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
+       struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS);
 
        if (p) {
                memset(p, 0, sizeof(*p));
@@ -102,17 +102,23 @@ struct nfs_write_data *nfs_commit_alloc(void)
        return p;
 }
 
-void nfs_commit_free(struct nfs_write_data *p)
+void nfs_commit_rcu_free(struct rcu_head *head)
 {
+       struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_commit_mempool);
 }
 
+void nfs_commit_free(struct nfs_write_data *wdata)
+{
+       call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
+}
+
 struct nfs_write_data *nfs_writedata_alloc(size_t len)
 {
        unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
+       struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
 
        if (p) {
                memset(p, 0, sizeof(*p));
@@ -131,18 +137,47 @@ struct nfs_write_data *nfs_writedata_alloc(size_t len)
        return p;
 }
 
-static void nfs_writedata_free(struct nfs_write_data *p)
+static void nfs_writedata_rcu_free(struct rcu_head *head)
 {
+       struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_wdata_mempool);
 }
 
+static void nfs_writedata_free(struct nfs_write_data *wdata)
+{
+       call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
+}
+
 void nfs_writedata_release(void *wdata)
 {
        nfs_writedata_free(wdata);
 }
 
+static struct nfs_page *nfs_page_find_request_locked(struct page *page)
+{
+       struct nfs_page *req = NULL;
+
+       if (PagePrivate(page)) {
+               req = (struct nfs_page *)page_private(page);
+               if (req != NULL)
+                       atomic_inc(&req->wb_count);
+       }
+       return req;
+}
+
+static struct nfs_page *nfs_page_find_request(struct page *page)
+{
+       struct nfs_page *req = NULL;
+       spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+
+       spin_lock(req_lock);
+       req = nfs_page_find_request_locked(page);
+       spin_unlock(req_lock);
+       return req;
+}
+
 /* Adjust the file length if we're writing beyond the end */
 static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count)
 {
@@ -164,113 +199,34 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
  */
 static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count)
 {
-       loff_t end_offs;
-
        if (PageUptodate(page))
                return;
        if (base != 0)
                return;
-       if (count == PAGE_CACHE_SIZE) {
-               SetPageUptodate(page);
-               return;
-       }
-
-       end_offs = i_size_read(page->mapping->host) - 1;
-       if (end_offs < 0)
+       if (count != nfs_page_length(page))
                return;
-       /* Is this the last page? */
-       if (page->index != (unsigned long)(end_offs >> PAGE_CACHE_SHIFT))
-               return;
-       /* This is the last page: set PG_uptodate if we cover the entire
-        * extent of the data, then zero the rest of the page.
-        */
-       if (count == (unsigned int)(end_offs & (PAGE_CACHE_SIZE - 1)) + 1) {
+       if (count != PAGE_CACHE_SIZE)
                memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count);
-               SetPageUptodate(page);
-       }
+       SetPageUptodate(page);
 }
 
-/*
- * Write a page synchronously.
- * Offset is the data offset within the page.
- */
-static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
-               struct page *page, unsigned int offset, unsigned int count,
-               int how)
-{
-       unsigned int    wsize = NFS_SERVER(inode)->wsize;
-       int             result, written = 0;
-       struct nfs_write_data *wdata;
-
-       wdata = nfs_writedata_alloc(wsize);
-       if (!wdata)
-               return -ENOMEM;
-
-       wdata->flags = how;
-       wdata->cred = ctx->cred;
-       wdata->inode = inode;
-       wdata->args.fh = NFS_FH(inode);
-       wdata->args.context = ctx;
-       wdata->args.pages = &page;
-       wdata->args.stable = NFS_FILE_SYNC;
-       wdata->args.pgbase = offset;
-       wdata->args.count = wsize;
-       wdata->res.fattr = &wdata->fattr;
-       wdata->res.verf = &wdata->verf;
-
-       dprintk("NFS:      nfs_writepage_sync(%s/%Ld %d@%Ld)\n",
-               inode->i_sb->s_id,
-               (long long)NFS_FILEID(inode),
-               count, (long long)(page_offset(page) + offset));
-
-       set_page_writeback(page);
-       nfs_begin_data_update(inode);
-       do {
-               if (count < wsize)
-                       wdata->args.count = count;
-               wdata->args.offset = page_offset(page) + wdata->args.pgbase;
-
-               result = NFS_PROTO(inode)->write(wdata);
-
-               if (result < 0) {
-                       /* Must mark the page invalid after I/O error */
-                       ClearPageUptodate(page);
-                       goto io_error;
-               }
-               if (result < wdata->args.count)
-                       printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n",
-                                       wdata->args.count, result);
-
-               wdata->args.offset += result;
-               wdata->args.pgbase += result;
-               written += result;
-               count -= result;
-               nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result);
-       } while (count);
-       /* Update file length */
-       nfs_grow_file(page, offset, written);
-       /* Set the PG_uptodate flag? */
-       nfs_mark_uptodate(page, offset, written);
-
-       if (PageError(page))
-               ClearPageError(page);
-
-io_error:
-       nfs_end_data_update(inode);
-       end_page_writeback(page);
-       nfs_writedata_free(wdata);
-       return written ? written : result;
-}
-
-static int nfs_writepage_async(struct nfs_open_context *ctx,
-               struct inode *inode, struct page *page,
+static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
                unsigned int offset, unsigned int count)
 {
        struct nfs_page *req;
+       int ret;
 
-       req = nfs_update_request(ctx, inode, page, offset, count);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       for (;;) {
+               req = nfs_update_request(ctx, page, offset, count);
+               if (!IS_ERR(req))
+                       break;
+               ret = PTR_ERR(req);
+               if (ret != -EBUSY)
+                       return ret;
+               ret = nfs_wb_page(page->mapping->host, page);
+               if (ret != 0)
+                       return ret;
+       }
        /* Update file length */
        nfs_grow_file(page, offset, count);
        /* Set the PG_uptodate flag? */
@@ -288,74 +244,95 @@ static int wb_priority(struct writeback_control *wbc)
        return 0;
 }
 
+/*
+ * Find an associated nfs write request, and prepare to flush it out
+ * Returns 1 if there was no write request, or if the request was
+ * already tagged by nfs_set_page_dirty.Returns 0 if the request
+ * was not tagged.
+ * May also return an error if the user signalled nfs_wait_on_request().
+ */
+static int nfs_page_mark_flush(struct page *page)
+{
+       struct nfs_page *req;
+       spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+       int ret;
+
+       spin_lock(req_lock);
+       for(;;) {
+               req = nfs_page_find_request_locked(page);
+               if (req == NULL) {
+                       spin_unlock(req_lock);
+                       return 1;
+               }
+               if (nfs_lock_request_dontget(req))
+                       break;
+               /* Note: If we hold the page lock, as is the case in nfs_writepage,
+                *       then the call to nfs_lock_request_dontget() will always
+                *       succeed provided that someone hasn't already marked the
+                *       request as dirty (in which case we don't care).
+                */
+               spin_unlock(req_lock);
+               ret = nfs_wait_on_request(req);
+               nfs_release_request(req);
+               if (ret != 0)
+                       return ret;
+               spin_lock(req_lock);
+       }
+       spin_unlock(req_lock);
+       if (test_and_set_bit(PG_FLUSHING, &req->wb_flags) == 0) {
+               nfs_mark_request_dirty(req);
+               set_page_writeback(page);
+       }
+       ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
+       nfs_unlock_request(req);
+       return ret;
+}
+
 /*
  * Write an mmapped page to the server.
  */
-int nfs_writepage(struct page *page, struct writeback_control *wbc)
+static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
 {
        struct nfs_open_context *ctx;
        struct inode *inode = page->mapping->host;
-       unsigned long end_index;
-       unsigned offset = PAGE_CACHE_SIZE;
-       loff_t i_size = i_size_read(inode);
-       int inode_referenced = 0;
-       int priority = wb_priority(wbc);
+       unsigned offset;
        int err;
 
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
        nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
-       /*
-        * Note: We need to ensure that we have a reference to the inode
-        *       if we are to do asynchronous writes. If not, waiting
-        *       in nfs_wait_on_request() may deadlock with clear_inode().
-        *
-        *       If igrab() fails here, then it is in any case safe to
-        *       call nfs_wb_page(), since there will be no pending writes.
-        */
-       if (igrab(inode) != 0)
-               inode_referenced = 1;
-       end_index = i_size >> PAGE_CACHE_SHIFT;
-
-       /* Ensure we've flushed out any previous writes */
-       nfs_wb_page_priority(inode, page, priority);
-
-       /* easy case */
-       if (page->index < end_index)
-               goto do_it;
-       /* things got complicated... */
-       offset = i_size & (PAGE_CACHE_SIZE-1);
-
-       /* OK, are we completely out? */
-       err = 0; /* potential race with truncate - ignore */
-       if (page->index >= end_index+1 || !offset)
+       err = nfs_page_mark_flush(page);
+       if (err <= 0)
+               goto out;
+       err = 0;
+       offset = nfs_page_length(page);
+       if (!offset)
                goto out;
-do_it:
+
        ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
        if (ctx == NULL) {
                err = -EBADF;
                goto out;
        }
-       lock_kernel();
-       if (!IS_SYNC(inode) && inode_referenced) {
-               err = nfs_writepage_async(ctx, inode, page, 0, offset);
-               if (!wbc->for_writepages)
-                       nfs_flush_inode(inode, 0, 0, wb_priority(wbc));
-       } else {
-               err = nfs_writepage_sync(ctx, inode, page, 0,
-                                               offset, priority);
-               if (err >= 0) {
-                       if (err != offset)
-                               redirty_page_for_writepage(wbc, page);
-                       err = 0;
-               }
-       }
-       unlock_kernel();
+       err = nfs_writepage_setup(ctx, page, 0, offset);
        put_nfs_open_context(ctx);
+       if (err != 0)
+               goto out;
+       err = nfs_page_mark_flush(page);
+       if (err > 0)
+               err = 0;
 out:
+       if (!wbc->for_writepages)
+               nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc));
+       return err;
+}
+
+int nfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+       int err;
+
+       err = nfs_writepage_locked(page, wbc);
        unlock_page(page);
-       if (inode_referenced)
-               iput(inode);
        return err; 
 }
 
@@ -379,21 +356,18 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
                        return 0;
                nfs_wait_on_write_congestion(mapping, 0);
        }
-       err = nfs_flush_inode(inode, 0, 0, wb_priority(wbc));
+       err = nfs_flush_mapping(mapping, wbc, wb_priority(wbc));
        if (err < 0)
                goto out;
        nfs_add_stats(inode, NFSIOS_WRITEPAGES, err);
-       wbc->nr_to_write -= err;
        if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) {
                err = nfs_wait_on_requests(inode, 0, 0);
                if (err < 0)
                        goto out;
        }
        err = nfs_commit_inode(inode, wb_priority(wbc));
-       if (err > 0) {
-               wbc->nr_to_write -= err;
+       if (err > 0)
                err = 0;
-       }
 out:
        clear_bit(BDI_write_congested, &bdi->state);
        wake_up_all(&nfs_write_congestion);
@@ -420,6 +394,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                        nfsi->change_attr++;
        }
        SetPagePrivate(req->wb_page);
+       set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
        atomic_inc(&req->wb_count);
        return 0;
@@ -436,6 +411,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        BUG_ON (!NFS_WBACK_BUSY(req));
 
        spin_lock(&nfsi->req_lock);
+       set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
@@ -449,33 +425,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        nfs_release_request(req);
 }
 
-/*
- * Find a request
- */
-static inline struct nfs_page *
-_nfs_find_request(struct inode *inode, unsigned long index)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-       struct nfs_page *req;
-
-       req = (struct nfs_page*)radix_tree_lookup(&nfsi->nfs_page_tree, index);
-       if (req)
-               atomic_inc(&req->wb_count);
-       return req;
-}
-
-static struct nfs_page *
-nfs_find_request(struct inode *inode, unsigned long index)
-{
-       struct nfs_page         *req;
-       struct nfs_inode        *nfsi = NFS_I(inode);
-
-       spin_lock(&nfsi->req_lock);
-       req = _nfs_find_request(inode, index);
-       spin_unlock(&nfsi->req_lock);
-       return req;
-}
-
 /*
  * Add a request to the inode's dirty list.
  */
@@ -491,8 +440,14 @@ nfs_mark_request_dirty(struct nfs_page *req)
        nfs_list_add_request(req, &nfsi->dirty);
        nfsi->ndirty++;
        spin_unlock(&nfsi->req_lock);
-       inc_zone_page_state(req->wb_page, NR_FILE_DIRTY);
-       mark_inode_dirty(inode);
+       __mark_inode_dirty(inode, I_DIRTY_PAGES);
+}
+
+static void
+nfs_redirty_request(struct nfs_page *req)
+{
+       clear_bit(PG_FLUSHING, &req->wb_flags);
+       __set_page_dirty_nobuffers(req->wb_page);
 }
 
 /*
@@ -501,8 +456,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-       struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
-       return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty;
+       return test_bit(PG_FLUSHING, &req->wb_flags) == 0;
 }
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -520,7 +474,7 @@ nfs_mark_request_commit(struct nfs_page *req)
        nfsi->ncommit++;
        spin_unlock(&nfsi->req_lock);
        inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-       mark_inode_dirty(inode);
+       __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
 }
 #endif
 
@@ -597,31 +551,6 @@ static void nfs_cancel_commit_list(struct list_head *head)
        }
 }
 
-/*
- * nfs_scan_dirty - Scan an inode for dirty requests
- * @inode: NFS inode to scan
- * @dst: destination list
- * @idx_start: lower bound of page->index to scan.
- * @npages: idx_start + npages sets the upper bound to scan.
- *
- * Moves requests from the inode's dirty page list.
- * The requests are *not* checked to ensure that they form a contiguous set.
- */
-static int
-nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-       int res = 0;
-
-       if (nfsi->ndirty != 0) {
-               res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
-               nfsi->ndirty -= res;
-               if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
-                       printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
-       }
-       return res;
-}
-
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 /*
  * nfs_scan_commit - Scan an inode for commit requests
@@ -698,27 +627,27 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
  * Note: Should always be called with the Page Lock held!
  */
 static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
-               struct inode *inode, struct page *page,
-               unsigned int offset, unsigned int bytes)
+               struct page *page, unsigned int offset, unsigned int bytes)
 {
-       struct nfs_server *server = NFS_SERVER(inode);
+       struct inode *inode = page->mapping->host;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page         *req, *new = NULL;
        unsigned long           rqend, end;
 
        end = offset + bytes;
 
-       if (nfs_wait_on_write_congestion(page->mapping, server->flags & NFS_MOUNT_INTR))
+       if (nfs_wait_on_write_congestion(page->mapping, NFS_SERVER(inode)->flags & NFS_MOUNT_INTR))
                return ERR_PTR(-ERESTARTSYS);
        for (;;) {
                /* Loop over all inode entries and see if we find
                 * A request for the page we wish to update
                 */
                spin_lock(&nfsi->req_lock);
-               req = _nfs_find_request(inode, page->index);
+               req = nfs_page_find_request_locked(page);
                if (req) {
                        if (!nfs_lock_request_dontget(req)) {
                                int error;
+
                                spin_unlock(&nfsi->req_lock);
                                error = nfs_wait_on_request(req);
                                nfs_release_request(req);
@@ -745,7 +674,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                                return ERR_PTR(error);
                        }
                        spin_unlock(&nfsi->req_lock);
-                       nfs_mark_request_dirty(new);
                        return new;
                }
                spin_unlock(&nfsi->req_lock);
@@ -786,9 +714,8 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
 int nfs_flush_incompatible(struct file *file, struct page *page)
 {
        struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
-       struct inode    *inode = page->mapping->host;
        struct nfs_page *req;
-       int             status = 0;
+       int do_flush, status;
        /*
         * Look for a request corresponding to this page. If there
         * is one, and it belongs to another file, we flush it out
@@ -797,13 +724,18 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
         * Also do the same if we find a request from an existing
         * dropped page.
         */
-       req = nfs_find_request(inode, page->index);
-       if (req) {
-               if (req->wb_page != page || ctx != req->wb_context)
-                       status = nfs_wb_page(inode, page);
+       do {
+               req = nfs_page_find_request(page);
+               if (req == NULL)
+                       return 0;
+               do_flush = req->wb_page != page || req->wb_context != ctx
+                       || !nfs_dirty_request(req);
                nfs_release_request(req);
-       }
-       return (status < 0) ? status : 0;
+               if (!do_flush)
+                       return 0;
+               status = nfs_wb_page(page->mapping->host, page);
+       } while (status == 0);
+       return status;
 }
 
 /*
@@ -817,72 +749,27 @@ int nfs_updatepage(struct file *file, struct page *page,
 {
        struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
        struct inode    *inode = page->mapping->host;
-       struct nfs_page *req;
        int             status = 0;
 
        nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
 
        dprintk("NFS:      nfs_updatepage(%s/%s %d@%Ld)\n",
-               file->f_dentry->d_parent->d_name.name,
-               file->f_dentry->d_name.name, count,
+               file->f_path.dentry->d_parent->d_name.name,
+               file->f_path.dentry->d_name.name, count,
                (long long)(page_offset(page) +offset));
 
-       if (IS_SYNC(inode)) {
-               status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
-               if (status > 0) {
-                       if (offset == 0 && status == PAGE_CACHE_SIZE)
-                               SetPageUptodate(page);
-                       return 0;
-               }
-               return status;
-       }
-
        /* If we're not using byte range locks, and we know the page
         * is entirely in cache, it may be more efficient to avoid
         * fragmenting write requests.
         */
        if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
-               loff_t end_offs = i_size_read(inode) - 1;
-               unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
-
-               count += offset;
+               count = max(count + offset, nfs_page_length(page));
                offset = 0;
-               if (unlikely(end_offs < 0)) {
-                       /* Do nothing */
-               } else if (page->index == end_index) {
-                       unsigned int pglen;
-                       pglen = (unsigned int)(end_offs & (PAGE_CACHE_SIZE-1)) + 1;
-                       if (count < pglen)
-                               count = pglen;
-               } else if (page->index < end_index)
-                       count = PAGE_CACHE_SIZE;
        }
 
-       /*
-        * Try to find an NFS request corresponding to this page
-        * and update it.
-        * If the existing request cannot be updated, we must flush
-        * it out now.
-        */
-       do {
-               req = nfs_update_request(ctx, inode, page, offset, count);
-               status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
-               if (status != -EBUSY)
-                       break;
-               /* Request could not be updated. Flush it out and try again */
-               status = nfs_wb_page(inode, page);
-       } while (status >= 0);
-       if (status < 0)
-               goto done;
-
-       status = 0;
+       status = nfs_writepage_setup(ctx, page, offset, count);
+       __set_page_dirty_nobuffers(page);
 
-       /* Update file length */
-       nfs_grow_file(page, offset, count);
-       /* Set the PG_uptodate flag? */
-       nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
-       nfs_unlock_request(req);
-done:
         dprintk("NFS:      nfs_updatepage returns %d (isize %Ld)\n",
                        status, (long long)i_size_read(inode));
        if (status < 0)
@@ -897,7 +784,7 @@ static void nfs_writepage_release(struct nfs_page *req)
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
        if (!PageError(req->wb_page)) {
                if (NFS_NEED_RESCHED(req)) {
-                       nfs_mark_request_dirty(req);
+                       nfs_redirty_request(req);
                        goto out;
                } else if (NFS_NEED_COMMIT(req)) {
                        nfs_mark_request_commit(req);
@@ -979,9 +866,7 @@ static void nfs_execute_write(struct nfs_write_data *data)
        sigset_t oldset;
 
        rpc_clnt_sigmask(clnt, &oldset);
-       lock_kernel();
        rpc_execute(&data->task);
-       unlock_kernel();
        rpc_clnt_sigunmask(clnt, &oldset);
 }
 
@@ -1015,7 +900,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
        atomic_set(&req->wb_complete, requests);
 
        ClearPageError(page);
-       set_page_writeback(page);
        offset = 0;
        nbytes = req->wb_bytes;
        do {
@@ -1043,9 +927,9 @@ out_bad:
        while (!list_empty(&list)) {
                data = list_entry(list.next, struct nfs_write_data, pages);
                list_del(&data->pages);
-               nfs_writedata_free(data);
+               nfs_writedata_release(data);
        }
-       nfs_mark_request_dirty(req);
+       nfs_redirty_request(req);
        nfs_clear_page_writeback(req);
        return -ENOMEM;
 }
@@ -1076,7 +960,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
                nfs_list_remove_request(req);
                nfs_list_add_request(req, &data->pages);
                ClearPageError(req->wb_page);
-               set_page_writeback(req->wb_page);
                *pages++ = req->wb_page;
                count += req->wb_bytes;
        }
@@ -1091,7 +974,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
        while (!list_empty(head)) {
                struct nfs_page *req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
-               nfs_mark_request_dirty(req);
+               nfs_redirty_request(req);
                nfs_clear_page_writeback(req);
        }
        return -ENOMEM;
@@ -1126,7 +1009,7 @@ out_err:
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
-               nfs_mark_request_dirty(req);
+               nfs_redirty_request(req);
                nfs_clear_page_writeback(req);
        }
        return error;
@@ -1442,7 +1325,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                }
                /* We have a mismatch. Write the page again */
                dprintk(" mismatch\n");
-               nfs_mark_request_dirty(req);
+               nfs_redirty_request(req);
        next:
                nfs_clear_page_writeback(req);
        }
@@ -1459,18 +1342,17 @@ static inline int nfs_commit_list(struct inode *inode, struct list_head *head, i
 }
 #endif
 
-static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
-                          unsigned int npages, int how)
+static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_inode *nfsi = NFS_I(mapping->host);
        LIST_HEAD(head);
-       int res;
+       long res;
 
        spin_lock(&nfsi->req_lock);
-       res = nfs_scan_dirty(inode, &head, idx_start, npages);
+       res = nfs_scan_dirty(mapping, wbc, &head);
        spin_unlock(&nfsi->req_lock);
        if (res) {
-               int error = nfs_flush_list(inode, &head, res, how);
+               int error = nfs_flush_list(mapping->host, &head, res, how);
                if (error < 0)
                        return error;
        }
@@ -1496,38 +1378,62 @@ int nfs_commit_inode(struct inode *inode, int how)
 }
 #endif
 
-int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
-               unsigned int npages, int how)
+long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
+       struct inode *inode = mapping->host;
        struct nfs_inode *nfsi = NFS_I(inode);
+       unsigned long idx_start, idx_end;
+       unsigned int npages = 0;
        LIST_HEAD(head);
        int nocommit = how & FLUSH_NOCOMMIT;
-       int pages, ret;
-
+       long pages, ret;
+
+       /* FIXME */
+       if (wbc->range_cyclic)
+               idx_start = 0;
+       else {
+               idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
+               idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
+               if (idx_end > idx_start) {
+                       unsigned long l_npages = 1 + idx_end - idx_start;
+                       npages = l_npages;
+                       if (sizeof(npages) != sizeof(l_npages) &&
+                                       (unsigned long)npages != l_npages)
+                               npages = 0;
+               }
+       }
        how &= ~FLUSH_NOCOMMIT;
        spin_lock(&nfsi->req_lock);
        do {
+               wbc->pages_skipped = 0;
                ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
                if (ret != 0)
                        continue;
-               pages = nfs_scan_dirty(inode, &head, idx_start, npages);
+               pages = nfs_scan_dirty(mapping, wbc, &head);
                if (pages != 0) {
                        spin_unlock(&nfsi->req_lock);
-                       if (how & FLUSH_INVALIDATE)
+                       if (how & FLUSH_INVALIDATE) {
                                nfs_cancel_dirty_list(&head);
-                       else
+                               ret = pages;
+                       } else
                                ret = nfs_flush_list(inode, &head, pages, how);
                        spin_lock(&nfsi->req_lock);
                        continue;
                }
+               if (wbc->pages_skipped != 0)
+                       continue;
                if (nocommit)
                        break;
                pages = nfs_scan_commit(inode, &head, idx_start, npages);
-               if (pages == 0)
+               if (pages == 0) {
+                       if (wbc->pages_skipped != 0)
+                               continue;
                        break;
+               }
                if (how & FLUSH_INVALIDATE) {
                        spin_unlock(&nfsi->req_lock);
                        nfs_cancel_commit_list(&head);
+                       ret = pages;
                        spin_lock(&nfsi->req_lock);
                        continue;
                }
@@ -1540,6 +1446,106 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
        return ret;
 }
 
+/*
+ * flush the inode to disk.
+ */
+int nfs_wb_all(struct inode *inode)
+{
+       struct address_space *mapping = inode->i_mapping;
+       struct writeback_control wbc = {
+               .bdi = mapping->backing_dev_info,
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .for_writepages = 1,
+               .range_cyclic = 1,
+       };
+       int ret;
+
+       ret = generic_writepages(mapping, &wbc);
+       if (ret < 0)
+               goto out;
+       ret = nfs_sync_mapping_wait(mapping, &wbc, 0);
+       if (ret >= 0)
+               return 0;
+out:
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       return ret;
+}
+
+int nfs_sync_mapping_range(struct address_space *mapping, loff_t range_start, loff_t range_end, int how)
+{
+       struct writeback_control wbc = {
+               .bdi = mapping->backing_dev_info,
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .range_start = range_start,
+               .range_end = range_end,
+               .for_writepages = 1,
+       };
+       int ret;
+
+       if (!(how & FLUSH_NOWRITEPAGE)) {
+               ret = generic_writepages(mapping, &wbc);
+               if (ret < 0)
+                       goto out;
+       }
+       ret = nfs_sync_mapping_wait(mapping, &wbc, how);
+       if (ret >= 0)
+               return 0;
+out:
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       return ret;
+}
+
+int nfs_wb_page_priority(struct inode *inode, struct page *page, int how)
+{
+       loff_t range_start = page_offset(page);
+       loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
+       struct writeback_control wbc = {
+               .bdi = page->mapping->backing_dev_info,
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .range_start = range_start,
+               .range_end = range_end,
+       };
+       int ret;
+
+       BUG_ON(!PageLocked(page));
+       if (!(how & FLUSH_NOWRITEPAGE) && clear_page_dirty_for_io(page)) {
+               ret = nfs_writepage_locked(page, &wbc);
+               if (ret < 0)
+                       goto out;
+       }
+       ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
+       if (ret >= 0)
+               return 0;
+out:
+       __mark_inode_dirty(inode, I_DIRTY_PAGES);
+       return ret;
+}
+
+/*
+ * Write back all requests on one page - we do this before reading it.
+ */
+int nfs_wb_page(struct inode *inode, struct page* page)
+{
+       return nfs_wb_page_priority(inode, page, FLUSH_STABLE);
+}
+
+int nfs_set_page_dirty(struct page *page)
+{
+       struct nfs_page *req;
+
+       req = nfs_page_find_request(page);
+       if (req != NULL) {
+               /* Mark any existing write requests for flushing */
+               set_bit(PG_NEED_FLUSH, &req->wb_flags);
+               nfs_release_request(req);
+       }
+       return __set_page_dirty_nobuffers(page);
+}
+
+
 int __init nfs_init_writepagecache(void)
 {
        nfs_wdata_cachep = kmem_cache_create("nfs_write_data",
index e3eca08..edde5dc 100644 (file)
@@ -222,12 +222,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
 {
        struct dentry *dentry = resp->fh.fh_dentry;
        struct inode *inode = dentry->d_inode;
-       int w = nfsacl_size(
-               (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
-               (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
        struct kvec *head = rqstp->rq_res.head;
        unsigned int base;
        int n;
+       int w;
 
        if (dentry == NULL || dentry->d_inode == NULL)
                return 0;
@@ -239,7 +237,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
                return 0;
        base = (char *)p - (char *)head->iov_base;
 
-       rqstp->rq_res.page_len = w;
+       rqstp->rq_res.page_len = w = nfsacl_size(
+               (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
+               (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
        while (w > 0) {
                if (!rqstp->rq_respages[rqstp->rq_resused++])
                        return 0;
index fcad289..3e3f2de 100644 (file)
@@ -171,19 +171,19 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
        p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
        if (resp->status == 0 && dentry && dentry->d_inode) {
                struct inode *inode = dentry->d_inode;
-               int w = nfsacl_size(
-                       (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
-                       (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
                struct kvec *head = rqstp->rq_res.head;
                unsigned int base;
                int n;
+               int w;
 
                *p++ = htonl(resp->mask);
                if (!xdr_ressize_check(rqstp, p))
                        return 0;
                base = (char *)p - (char *)head->iov_base;
 
-               rqstp->rq_res.page_len = w;
+               rqstp->rq_res.page_len = w = nfsacl_size(
+                       (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
+                       (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
                while (w > 0) {
                        if (!rqstp->rq_respages[rqstp->rq_resused++])
                                return 0;
index b4baca3..277df40 100644 (file)
 
 #define NFSDDBG_FACILITY               NFSDDBG_XDR
 
-#ifdef NFSD_OPTIMIZE_SPACE
-# define inline
-#endif
-
 
 /*
  * Mapping of S_IF* types to NFS file types
@@ -42,14 +38,14 @@ static u32  nfs3_ftypes[] = {
 /*
  * XDR functions for basic NFS types
  */
-static inline __be32 *
+static __be32 *
 encode_time3(__be32 *p, struct timespec *time)
 {
        *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 decode_time3(__be32 *p, struct timespec *time)
 {
        time->tv_sec = ntohl(*p++);
@@ -57,7 +53,7 @@ decode_time3(__be32 *p, struct timespec *time)
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 decode_fh(__be32 *p, struct svc_fh *fhp)
 {
        unsigned int size;
@@ -77,7 +73,7 @@ __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
        return decode_fh(p, fhp);
 }
 
-static inline __be32 *
+static __be32 *
 encode_fh(__be32 *p, struct svc_fh *fhp)
 {
        unsigned int size = fhp->fh_handle.fh_size;
@@ -91,7 +87,7 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
  * Decode a file name and make sure that the path contains
  * no slashes or null bytes.
  */
-static inline __be32 *
+static __be32 *
 decode_filename(__be32 *p, char **namp, int *lenp)
 {
        char            *name;
@@ -107,7 +103,7 @@ decode_filename(__be32 *p, char **namp, int *lenp)
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 decode_sattr3(__be32 *p, struct iattr *iap)
 {
        u32     tmp;
@@ -153,7 +149,7 @@ decode_sattr3(__be32 *p, struct iattr *iap)
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
 {
@@ -186,7 +182,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
        struct inode    *inode = fhp->fh_dentry->d_inode;
@@ -776,7 +772,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
                return xdr_ressize_check(rqstp, p);
 }
 
-static inline __be32 *
+static __be32 *
 encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
             int namlen, ino_t ino)
 {
@@ -790,7 +786,7 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
                struct svc_fh *fhp)
 {
index 81b8565..c7774e3 100644 (file)
@@ -259,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
                printk("nfsd4: non-file found in client recovery directory\n");
                return -EINVAL;
        }
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
        status = vfs_unlink(dir->d_inode, dentry);
        mutex_unlock(&dir->d_inode->i_mutex);
        return status;
index 293b649..b7179bd 100644 (file)
@@ -84,10 +84,10 @@ static void nfs4_set_recdir(char *recdir);
  */
 static DEFINE_MUTEX(client_mutex);
 
-static kmem_cache_t *stateowner_slab = NULL;
-static kmem_cache_t *file_slab = NULL;
-static kmem_cache_t *stateid_slab = NULL;
-static kmem_cache_t *deleg_slab = NULL;
+static struct kmem_cache *stateowner_slab = NULL;
+static struct kmem_cache *file_slab = NULL;
+static struct kmem_cache *stateid_slab = NULL;
+static struct kmem_cache *deleg_slab = NULL;
 
 void
 nfs4_lock_state(void)
@@ -1003,7 +1003,7 @@ alloc_init_file(struct inode *ino)
 }
 
 static void
-nfsd4_free_slab(kmem_cache_t **slab)
+nfsd4_free_slab(struct kmem_cache **slab)
 {
        if (*slab == NULL)
                return;
@@ -1310,7 +1310,7 @@ static inline void
 nfs4_file_downgrade(struct file *filp, unsigned int share_access)
 {
        if (share_access & NFS4_SHARE_ACCESS_WRITE) {
-               put_write_access(filp->f_dentry->d_inode);
+               put_write_access(filp->f_path.dentry->d_inode);
                filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
        }
 }
@@ -1623,7 +1623,7 @@ static __be32
 nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
 {
        struct file *filp = stp->st_vfs_file;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        unsigned int share_access, new_writer;
        __be32 status;
 
@@ -1829,9 +1829,8 @@ out:
 }
 
 static struct workqueue_struct *laundry_wq;
-static struct work_struct laundromat_work;
-static void laundromat_main(void *);
-static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
+static void laundromat_main(struct work_struct *);
+static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
 
 __be32
 nfsd4_renew(clientid_t *clid)
@@ -1940,7 +1939,7 @@ nfs4_laundromat(void)
 }
 
 void
-laundromat_main(void *not_used)
+laundromat_main(struct work_struct *not_used)
 {
        time_t t;
 
@@ -1966,7 +1965,7 @@ search_close_lru(u32 st_id, int flags)
 static inline int
 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
 {
-       return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
+       return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
 }
 
 static int
@@ -2863,7 +2862,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
         * only the dentry:inode set.
         */
        memset(&file, 0, sizeof (struct file));
-       file.f_dentry = current_fh->fh_dentry;
+       file.f_path.dentry = current_fh->fh_dentry;
 
        status = nfs_ok;
        if (posix_test_lock(&file, &file_lock, &conflock)) {
@@ -2953,7 +2952,7 @@ static int
 check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
 {
        struct file_lock **flpp;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int status = 0;
 
        lock_kernel();
index 6100bbe..f90d704 100644 (file)
@@ -66,14 +66,13 @@ nfsd_cache_init(void)
                printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
                        CACHESIZE, CACHESIZE-i);
 
-       hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL);
+       hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
        if (!hash_list) {
                nfsd_cache_shutdown();
                printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
                        HASHSIZE * sizeof(struct hlist_head));
                return;
        }
-       memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
 
        cache_disabled = 0;
 }
index 39aed90..eedf2e3 100644 (file)
@@ -111,7 +111,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 
 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
-       ino_t ino =  file->f_dentry->d_inode->i_ino;
+       ino_t ino =  file->f_path.dentry->d_inode->i_ino;
        char *data;
        ssize_t rv;
 
index 56ebb14..f5243f9 100644 (file)
 
 #define NFSDDBG_FACILITY               NFSDDBG_XDR
 
-
-#ifdef NFSD_OPTIMIZE_SPACE
-# define inline
-#endif
-
 /*
  * Mapping of S_IF* types to NFS file types
  */
@@ -55,7 +50,7 @@ __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
        return decode_fh(p, fhp);
 }
 
-static inline __be32 *
+static __be32 *
 encode_fh(__be32 *p, struct svc_fh *fhp)
 {
        memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
@@ -66,7 +61,7 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
  * Decode a file name and make sure that the path contains
  * no slashes or null bytes.
  */
-static inline __be32 *
+static __be32 *
 decode_filename(__be32 *p, char **namp, int *lenp)
 {
        char            *name;
@@ -82,7 +77,7 @@ decode_filename(__be32 *p, char **namp, int *lenp)
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 decode_pathname(__be32 *p, char **namp, int *lenp)
 {
        char            *name;
@@ -98,7 +93,7 @@ decode_pathname(__be32 *p, char **namp, int *lenp)
        return p;
 }
 
-static inline __be32 *
+static __be32 *
 decode_sattr(__be32 *p, struct iattr *iap)
 {
        u32     tmp, tmp1;
index bb4d926..4883d75 100644 (file)
@@ -736,10 +736,10 @@ static int
 nfsd_sync(struct file *filp)
 {
         int err;
-       struct inode *inode = filp->f_dentry->d_inode;
-       dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
        mutex_lock(&inode->i_mutex);
-       err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+       err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
        mutex_unlock(&inode->i_mutex);
 
        return err;
@@ -845,7 +845,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        int             host_err;
 
        err = nfserr_perm;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
 #ifdef MSNFS
        if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
                (!lock_may_read(inode, offset, *count)))
@@ -883,7 +883,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
                nfsdstats.io_read += host_err;
                *count = host_err;
                err = 0;
-               fsnotify_access(file->f_dentry);
+               fsnotify_access(file->f_path.dentry);
        } else 
                err = nfserrno(host_err);
 out:
@@ -917,11 +917,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        err = nfserr_perm;
 
        if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-               (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
+               (!lock_may_write(file->f_path.dentry->d_inode, offset, cnt)))
                goto out;
 #endif
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        inode = dentry->d_inode;
        exp   = fhp->fh_export;
 
@@ -950,7 +950,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        set_fs(oldfs);
        if (host_err >= 0) {
                nfsdstats.io_write += cnt;
-               fsnotify_modify(file->f_dentry);
+               fsnotify_modify(file->f_path.dentry);
        }
 
        /* clear setuid/setgid flag after write */
@@ -1885,28 +1885,27 @@ nfsd_racache_init(int cache_size)
                return 0;
        if (cache_size < 2*RAPARM_HASH_SIZE)
                cache_size = 2*RAPARM_HASH_SIZE;
-       raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL);
-
-       if (raparml != NULL) {
-               dprintk("nfsd: allocating %d readahead buffers.\n",
-                       cache_size);
-               for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
-                       raparm_hash[i].pb_head = NULL;
-                       spin_lock_init(&raparm_hash[i].pb_lock);
-               }
-               nperbucket = cache_size >> RAPARM_HASH_BITS;
-               memset(raparml, 0, sizeof(struct raparms) * cache_size);
-               for (i = 0; i < cache_size - 1; i++) {
-                       if (i % nperbucket == 0)
-                               raparm_hash[j++].pb_head = raparml + i;
-                       if (i % nperbucket < nperbucket-1)
-                               raparml[i].p_next = raparml + i + 1;
-               }
-       } else {
+       raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL);
+
+       if (!raparml) {
                printk(KERN_WARNING
-                      "nfsd: Could not allocate memory read-ahead cache.\n");
+                       "nfsd: Could not allocate memory read-ahead cache.\n");
                return -ENOMEM;
        }
+
+       dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
+       for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
+               raparm_hash[i].pb_head = NULL;
+               spin_lock_init(&raparm_hash[i].pb_lock);
+       }
+       nperbucket = cache_size >> RAPARM_HASH_BITS;
+       for (i = 0; i < cache_size - 1; i++) {
+               if (i % nperbucket == 0)
+                       raparm_hash[j++].pb_head = raparml + i;
+               if (i % nperbucket < nperbucket-1)
+                       raparml[i].p_next = raparml + i + 1;
+       }
+
        nfsdstats.ra_size = cache_size;
        return 0;
 }
index 046fde8..65e640c 100644 (file)
@@ -4421,6 +4421,73 @@ static wchar_t *page_charset2uni[256] = {
        c2u_F8, c2u_F9, c2u_FA, c2u_FB, c2u_FC, c2u_FD, c2u_FE, NULL,   
 };
 
+static unsigned char u2c_00[512] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0C-0x0F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x13 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x14-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1C-0x1F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x23 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x24-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2C-0x2F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x33 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x34-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3C-0x3F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x43 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x44-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4C-0x4F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x53 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x54-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5C-0x5F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x63 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x64-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6C-0x6F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x73 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x74-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7C-0x7F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x83 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x84-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8C-0x8F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x93 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x94-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9B */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9C-0x9F */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0-0xA3 */
+       0xA1, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xEC, /* 0xA4-0xA7 */
+       0xA1, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA8-0xAB */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xAC-0xAF */
+       0xA1, 0xE3, 0xA1, 0xC0, 0x00, 0x00, 0x00, 0x00, /* 0xB0-0xB3 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA4, /* 0xB4-0xB7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB8-0xBB */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xBC-0xBF */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0-0xC3 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC4-0xC7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC8-0xCB */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xCC-0xCF */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0-0xD3 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC1, /* 0xD4-0xD7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
+       0xA8, 0xA4, 0xA8, 0xA2, 0x00, 0x00, 0x00, 0x00, /* 0xE0-0xE3 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
+       0xA8, 0xA8, 0xA8, 0xA6, 0xA8, 0xBA, 0x00, 0x00, /* 0xE8-0xEB */
+       0xA8, 0xAC, 0xA8, 0xAA, 0x00, 0x00, 0x00, 0x00, /* 0xEC-0xEF */
+       0x00, 0x00, 0x00, 0x00, 0xA8, 0xB0, 0xA8, 0xAE, /* 0xF0-0xF3 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC2, /* 0xF4-0xF7 */
+       0x00, 0x00, 0xA8, 0xB4, 0xA8, 0xB2, 0x00, 0x00, /* 0xF8-0xFB */
+       0xA8, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xFC-0xFF */
+};
+
 static unsigned char u2c_01[512] = {
        0xA8, 0xA1, 0xA8, 0xA1, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
@@ -10825,7 +10892,7 @@ static unsigned char u2c_FF[512] = {
 };
 
 static unsigned char *page_uni2charset[256] = {
-       NULL,   u2c_01, u2c_02, u2c_03, u2c_04, NULL,   NULL,   NULL,   
+       u2c_00, u2c_01, u2c_02, u2c_03, u2c_04, NULL,   NULL,   NULL,
        NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
        NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
        NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
@@ -10936,11 +11003,34 @@ static int uni2char(const wchar_t uni,
        unsigned char *uni2charset;
        unsigned char cl = uni&0xFF;
        unsigned char ch = (uni>>8)&0xFF;
-       int n;
+       unsigned char out0,out1;
 
        if (boundlen <= 0)
                return -ENAMETOOLONG;
 
+       if (uni == 0x20ac) {/* Euro symbol.The only exception with a non-ascii unicode */
+               out[0] = 0x80;
+               return 1;
+       }
+
+       if (ch == 0) { /* handle the U00 plane*/
+               /* if (cl == 0) return -EINVAL;*/ /*U0000 is legal in cp936*/
+               out0 = u2c_00[cl*2];
+               out1 = u2c_00[cl*2+1];
+               if (out0 == 0x00 && out1 == 0x00) {
+                       if (cl<0x80) {
+                               out[0] = cl;
+                               return 1;
+                       }
+                       return -EINVAL;
+               } else {
+                       if (boundlen <= 1)
+                               return -ENAMETOOLONG;
+                       out[0] = out0;
+                       out[1] = out1;
+                       return 2;
+               }
+       }
 
        uni2charset = page_uni2charset[ch];
        if (uni2charset) {
@@ -10950,15 +11040,10 @@ static int uni2char(const wchar_t uni,
                out[1] = uni2charset[cl*2+1];
                if (out[0] == 0x00 && out[1] == 0x00)
                        return -EINVAL;
-               n = 2;
-       } else if (ch==0 && cl) {
-               out[0] = cl;
-               n = 1;
+               return 2;
        }
        else
                return -EINVAL;
-
-       return n;
 }
 
 static int char2uni(const unsigned char *rawstring, int boundlen,
@@ -10972,7 +11057,11 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
                return -ENAMETOOLONG;
 
        if (boundlen == 1) {
-               *uni = rawstring[0];
+               if (rawstring[0]==0x80) { /* Euro symbol.The only exception with a non-ascii unicode */
+                       *uni = 0x20ac;
+               } else {
+                       *uni = rawstring[0];
+               }
                return 1;
        }
 
@@ -10986,7 +11075,11 @@ static int char2uni(const unsigned char *rawstring, int boundlen,
                        return -EINVAL;
                n = 2;
        } else{
-               *uni = ch;
+               if (ch==0x80) {/* Euro symbol.The only exception with a non-ascii unicode */
+                       *uni = 0x20ac;
+               } else {
+                       *uni = ch;
+               }
                n = 1;
        }
        return n;
index 9f08e85..c577d8e 100644 (file)
@@ -1272,7 +1272,7 @@ ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
 {
        ntfs_attr_search_ctx *ctx;
 
-       ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, SLAB_NOFS);
+       ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, GFP_NOFS);
        if (ctx)
                ntfs_attr_init_search_ctx(ctx, ni, mrec);
        return ctx;
index 85c36b8..8296c29 100644 (file)
@@ -1101,7 +1101,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;
        loff_t fpos, i_size;
-       struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode;
+       struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode;
        struct super_block *sb = vdir->i_sb;
        ntfs_inode *ndir = NTFS_I(vdir);
        ntfs_volume *vol = NTFS_SB(sb);
@@ -1136,9 +1136,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (fpos == 1) {
                ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "
                                "inode 0x%lx, DT_DIR.",
-                               (unsigned long)parent_ino(filp->f_dentry));
+                               (unsigned long)parent_ino(filp->f_path.dentry));
                rc = filldir(dirent, "..", 2, fpos,
-                               parent_ino(filp->f_dentry), DT_DIR);
+                               parent_ino(filp->f_path.dentry), DT_DIR);
                if (rc)
                        goto done;
                fpos++;
index ae2fe00..076c942 100644 (file)
@@ -2162,7 +2162,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
                goto out;
        if (!count)
                goto out;
-       err = remove_suid(file->f_dentry);
+       err = remove_suid(file->f_path.dentry);
        if (err)
                goto out;
        file_update_time(file);
index e32cde4..2194eff 100644 (file)
@@ -38,7 +38,7 @@ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni)
 {
        ntfs_index_context *ictx;
 
-       ictx = kmem_cache_alloc(ntfs_index_ctx_cache, SLAB_NOFS);
+       ictx = kmem_cache_alloc(ntfs_index_ctx_cache, GFP_NOFS);
        if (ictx)
                *ictx = (ntfs_index_context){ .idx_ni = idx_ni };
        return ictx;
index 2d3de9c..2479898 100644 (file)
@@ -324,7 +324,7 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb)
        ntfs_inode *ni;
 
        ntfs_debug("Entering.");
-       ni = kmem_cache_alloc(ntfs_big_inode_cache, SLAB_NOFS);
+       ni = kmem_cache_alloc(ntfs_big_inode_cache, GFP_NOFS);
        if (likely(ni != NULL)) {
                ni->state = 0;
                return VFS_I(ni);
@@ -349,7 +349,7 @@ static inline ntfs_inode *ntfs_alloc_extent_inode(void)
        ntfs_inode *ni;
 
        ntfs_debug("Entering.");
-       ni = kmem_cache_alloc(ntfs_inode_cache, SLAB_NOFS);
+       ni = kmem_cache_alloc(ntfs_inode_cache, GFP_NOFS);
        if (likely(ni != NULL)) {
                ni->state = 0;
                return ni;
index 6a495f7..005ca4b 100644 (file)
@@ -266,7 +266,7 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins,
 
        /* We do not trust outside sources. */
        if (likely(ins)) {
-               ucs = kmem_cache_alloc(ntfs_name_cache, SLAB_NOFS);
+               ucs = kmem_cache_alloc(ntfs_name_cache, GFP_NOFS);
                if (likely(ucs)) {
                        for (i = o = 0; i < ins_len; i += wc_len) {
                                wc_len = nls->char2uni(ins + i, ins_len - i,
index 85a048b..edc91ca 100644 (file)
@@ -1197,10 +1197,12 @@ int ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        return status;
 }
 
-static void ocfs2_truncate_log_worker(void *data)
+static void ocfs2_truncate_log_worker(struct work_struct *work)
 {
        int status;
-       struct ocfs2_super *osb = data;
+       struct ocfs2_super *osb =
+               container_of(work, struct ocfs2_super,
+                            osb_truncate_log_wq.work);
 
        mlog_entry_void();
 
@@ -1432,7 +1434,8 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
        /* ocfs2_truncate_log_shutdown keys on the existence of
         * osb->osb_tl_inode so we don't set any of the osb variables
         * until we're sure all is well. */
-       INIT_WORK(&osb->osb_truncate_log_wq, ocfs2_truncate_log_worker, osb);
+       INIT_DELAYED_WORK(&osb->osb_truncate_log_wq,
+                         ocfs2_truncate_log_worker);
        osb->osb_tl_bh    = tl_bh;
        osb->osb_tl_inode = tl_inode;
 
index 2f7268e..ef6cd30 100644 (file)
@@ -595,7 +595,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
                             ssize_t bytes,
                             void *private)
 {
-       struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+       struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
 
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -611,7 +611,7 @@ static ssize_t ocfs2_direct_IO(int rw,
                               unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+       struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
        int ret;
 
        mlog_entry_void();
index 305cba3..4cd9a95 100644 (file)
@@ -141,7 +141,7 @@ struct o2hb_region {
         * recognizes a node going up and down in one iteration */
        u64                     hr_generation;
 
-       struct work_struct      hr_write_timeout_work;
+       struct delayed_work     hr_write_timeout_work;
        unsigned long           hr_last_timeout_start;
 
        /* Used during o2hb_check_slot to hold a copy of the block
@@ -156,9 +156,11 @@ struct o2hb_bio_wait_ctxt {
        int               wc_error;
 };
 
-static void o2hb_write_timeout(void *arg)
+static void o2hb_write_timeout(struct work_struct *work)
 {
-       struct o2hb_region *reg = arg;
+       struct o2hb_region *reg =
+               container_of(work, struct o2hb_region,
+                            hr_write_timeout_work.work);
 
        mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u "
             "milliseconds\n", reg->hr_dev_name,
@@ -1404,7 +1406,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                goto out;
        }
 
-       INIT_WORK(&reg->hr_write_timeout_work, o2hb_write_timeout, reg);
+       INIT_DELAYED_WORK(&reg->hr_write_timeout_work, o2hb_write_timeout);
 
        /*
         * A node is considered live after it has beat LIVE_THRESHOLD
index 7bba98f..4705d65 100644 (file)
@@ -88,7 +88,7 @@ void o2quo_disk_timeout(void)
        o2quo_fence_self();
 }
 
-static void o2quo_make_decision(void *arg)
+static void o2quo_make_decision(struct work_struct *work)
 {
        int quorum;
        int lowest_hb, lowest_reachable = 0, fence = 0;
@@ -306,7 +306,7 @@ void o2quo_init(void)
        struct o2quo_state *qs = &o2quo_state;
 
        spin_lock_init(&qs->qs_lock);
-       INIT_WORK(&qs->qs_work, o2quo_make_decision, NULL);
+       INIT_WORK(&qs->qs_work, o2quo_make_decision);
 }
 
 void o2quo_exit(void)
index b650efa..9b3209d 100644 (file)
@@ -140,11 +140,11 @@ static int o2net_sys_err_translations[O2NET_ERR_MAX] =
                 [O2NET_ERR_DIED]       = -EHOSTDOWN,};
 
 /* can't quite avoid *all* internal declarations :/ */
-static void o2net_sc_connect_completed(void *arg);
-static void o2net_rx_until_empty(void *arg);
-static void o2net_shutdown_sc(void *arg);
+static void o2net_sc_connect_completed(struct work_struct *work);
+static void o2net_rx_until_empty(struct work_struct *work);
+static void o2net_shutdown_sc(struct work_struct *work);
 static void o2net_listen_data_ready(struct sock *sk, int bytes);
-static void o2net_sc_send_keep_req(void *arg);
+static void o2net_sc_send_keep_req(struct work_struct *work);
 static void o2net_idle_timer(unsigned long data);
 static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
 
@@ -308,10 +308,10 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node)
        o2nm_node_get(node);
        sc->sc_node = node;
 
-       INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed, sc);
-       INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty, sc);
-       INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc, sc);
-       INIT_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req, sc);
+       INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed);
+       INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty);
+       INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc);
+       INIT_DELAYED_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req);
 
        init_timer(&sc->sc_idle_timeout);
        sc->sc_idle_timeout.function = o2net_idle_timer;
@@ -342,7 +342,7 @@ static void o2net_sc_queue_work(struct o2net_sock_container *sc,
                sc_put(sc);
 }
 static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc,
-                                       struct work_struct *work,
+                                       struct delayed_work *work,
                                        int delay)
 {
        sc_get(sc);
@@ -350,7 +350,7 @@ static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc,
                sc_put(sc);
 }
 static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc,
-                                        struct work_struct *work)
+                                        struct delayed_work *work)
 {
        if (cancel_delayed_work(work))
                sc_put(sc);
@@ -564,9 +564,11 @@ static void o2net_ensure_shutdown(struct o2net_node *nn,
  * ourselves as state_change couldn't get the nn_lock and call set_nn_state
  * itself.
  */
-static void o2net_shutdown_sc(void *arg)
+static void o2net_shutdown_sc(struct work_struct *work)
 {
-       struct o2net_sock_container *sc = arg;
+       struct o2net_sock_container *sc =
+               container_of(work, struct o2net_sock_container,
+                            sc_shutdown_work);
        struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
 
        sclog(sc, "shutting down\n");
@@ -1201,9 +1203,10 @@ out:
 /* this work func is triggerd by data ready.  it reads until it can read no
  * more.  it interprets 0, eof, as fatal.  if data_ready hits while we're doing
  * our work the work struct will be marked and we'll be called again. */
-static void o2net_rx_until_empty(void *arg)
+static void o2net_rx_until_empty(struct work_struct *work)
 {
-       struct o2net_sock_container *sc = arg;
+       struct o2net_sock_container *sc =
+               container_of(work, struct o2net_sock_container, sc_rx_work);
        int ret;
 
        do {
@@ -1249,9 +1252,11 @@ static int o2net_set_nodelay(struct socket *sock)
 
 /* called when a connect completes and after a sock is accepted.  the
  * rx path will see the response and mark the sc valid */
-static void o2net_sc_connect_completed(void *arg)
+static void o2net_sc_connect_completed(struct work_struct *work)
 {
-       struct o2net_sock_container *sc = arg;
+       struct o2net_sock_container *sc =
+               container_of(work, struct o2net_sock_container,
+                            sc_connect_work);
 
        mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n",
               (unsigned long long)O2NET_PROTOCOL_VERSION,
@@ -1262,9 +1267,11 @@ static void o2net_sc_connect_completed(void *arg)
 }
 
 /* this is called as a work_struct func. */
-static void o2net_sc_send_keep_req(void *arg)
+static void o2net_sc_send_keep_req(struct work_struct *work)
 {
-       struct o2net_sock_container *sc = arg;
+       struct o2net_sock_container *sc =
+               container_of(work, struct o2net_sock_container,
+                            sc_keepalive_work.work);
 
        o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req));
        sc_put(sc);
@@ -1314,14 +1321,15 @@ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
  * having a connect attempt fail, etc. This centralizes the logic which decides
  * if a connect attempt should be made or if we should give up and all future
  * transmit attempts should fail */
-static void o2net_start_connect(void *arg)
+static void o2net_start_connect(struct work_struct *work)
 {
-       struct o2net_node *nn = arg;
+       struct o2net_node *nn =
+               container_of(work, struct o2net_node, nn_connect_work.work);
        struct o2net_sock_container *sc = NULL;
        struct o2nm_node *node = NULL, *mynode = NULL;
        struct socket *sock = NULL;
        struct sockaddr_in myaddr = {0, }, remoteaddr = {0, };
-       int ret = 0;
+       int ret = 0, stop;
 
        /* if we're greater we initiate tx, otherwise we accept */
        if (o2nm_this_node() <= o2net_num_from_nn(nn))
@@ -1342,10 +1350,9 @@ static void o2net_start_connect(void *arg)
 
        spin_lock(&nn->nn_lock);
        /* see if we already have one pending or have given up */
-       if (nn->nn_sc || nn->nn_persistent_error)
-               arg = NULL;
+       stop = (nn->nn_sc || nn->nn_persistent_error);
        spin_unlock(&nn->nn_lock);
-       if (arg == NULL) /* *shrug*, needed some indicator */
+       if (stop)
                goto out;
 
        nn->nn_last_connect_attempt = jiffies;
@@ -1421,9 +1428,10 @@ out:
        return;
 }
 
-static void o2net_connect_expired(void *arg)
+static void o2net_connect_expired(struct work_struct *work)
 {
-       struct o2net_node *nn = arg;
+       struct o2net_node *nn =
+               container_of(work, struct o2net_node, nn_connect_expired.work);
 
        spin_lock(&nn->nn_lock);
        if (!nn->nn_sc_valid) {
@@ -1436,9 +1444,10 @@ static void o2net_connect_expired(void *arg)
        spin_unlock(&nn->nn_lock);
 }
 
-static void o2net_still_up(void *arg)
+static void o2net_still_up(struct work_struct *work)
 {
-       struct o2net_node *nn = arg;
+       struct o2net_node *nn =
+               container_of(work, struct o2net_node, nn_still_up.work);
 
        o2quo_hb_still_up(o2net_num_from_nn(nn));
 }
@@ -1644,9 +1653,9 @@ out:
        return ret;
 }
 
-static void o2net_accept_many(void *arg)
+static void o2net_accept_many(struct work_struct *work)
 {
-       struct socket *sock = arg;
+       struct socket *sock = o2net_listen_sock;
        while (o2net_accept_one(sock) == 0)
                cond_resched();
 }
@@ -1700,7 +1709,7 @@ static int o2net_open_listening_sock(__be16 port)
        write_unlock_bh(&sock->sk->sk_callback_lock);
 
        o2net_listen_sock = sock;
-       INIT_WORK(&o2net_listen_work, o2net_accept_many, sock);
+       INIT_WORK(&o2net_listen_work, o2net_accept_many);
 
        sock->sk->sk_reuse = 1;
        ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
@@ -1819,9 +1828,10 @@ int o2net_init(void)
                struct o2net_node *nn = o2net_nn_from_num(i);
 
                spin_lock_init(&nn->nn_lock);
-               INIT_WORK(&nn->nn_connect_work, o2net_start_connect, nn);
-               INIT_WORK(&nn->nn_connect_expired, o2net_connect_expired, nn);
-               INIT_WORK(&nn->nn_still_up, o2net_still_up, nn);
+               INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect);
+               INIT_DELAYED_WORK(&nn->nn_connect_expired,
+                                 o2net_connect_expired);
+               INIT_DELAYED_WORK(&nn->nn_still_up, o2net_still_up);
                /* until we see hb from a node we'll return einval */
                nn->nn_persistent_error = -ENOTCONN;
                init_waitqueue_head(&nn->nn_sc_wq);
index 4b46aac..daebbd3 100644 (file)
@@ -86,18 +86,18 @@ struct o2net_node {
         * connect attempt fails and so can be self-arming.  shutdown is
         * careful to first mark the nn such that no connects will be attempted
         * before canceling delayed connect work and flushing the queue. */
-       struct work_struct              nn_connect_work;
+       struct delayed_work             nn_connect_work;
        unsigned long                   nn_last_connect_attempt;
 
        /* this is queued as nodes come up and is canceled when a connection is
         * established.  this expiring gives up on the node and errors out
         * transmits */
-       struct work_struct              nn_connect_expired;
+       struct delayed_work             nn_connect_expired;
 
        /* after we give up on a socket we wait a while before deciding
         * that it is still heartbeating and that we should do some
         * quorum work */
-       struct work_struct              nn_still_up;
+       struct delayed_work             nn_still_up;
 };
 
 struct o2net_sock_container {
@@ -129,7 +129,7 @@ struct o2net_sock_container {
        struct work_struct      sc_shutdown_work;
 
        struct timer_list       sc_idle_timeout;
-       struct work_struct      sc_keepalive_work;
+       struct delayed_work     sc_keepalive_work;
 
        unsigned                sc_handshake_ok:1;
 
index baad2aa..66821e1 100644 (file)
@@ -79,7 +79,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
        struct buffer_head * bh, * tmp;
        struct ocfs2_dir_entry * de;
        int err;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block * sb = inode->i_sb;
        unsigned int ra_sectors = 16;
        int lock_level = 0;
index fa96818..6b6ff76 100644 (file)
@@ -153,7 +153,7 @@ static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned
  * called functions that cannot be directly called from the
  * net message handlers for some reason, usually because
  * they need to send net messages of their own. */
-void dlm_dispatch_work(void *data);
+void dlm_dispatch_work(struct work_struct *work);
 
 struct dlm_lock_resource;
 struct dlm_work_item;
index f6cdab3..420a375 100644 (file)
@@ -1297,7 +1297,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
 
        spin_lock_init(&dlm->work_lock);
        INIT_LIST_HEAD(&dlm->work_list);
-       INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work, dlm);
+       INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work);
 
        kref_init(&dlm->dlm_refs);
        dlm->dlm_state = DLM_CTXT_NEW;
index 16b8d1b..b7f0ba9 100644 (file)
@@ -66,7 +66,7 @@ static struct file_operations dlmfs_file_operations;
 static struct inode_operations dlmfs_dir_inode_operations;
 static struct inode_operations dlmfs_root_inode_operations;
 static struct inode_operations dlmfs_file_inode_operations;
-static kmem_cache_t *dlmfs_inode_cache;
+static struct kmem_cache *dlmfs_inode_cache;
 
 struct workqueue_struct *user_dlm_worker;
 
@@ -176,7 +176,7 @@ static ssize_t dlmfs_file_read(struct file *filp,
        int bytes_left;
        ssize_t readlen;
        char *lvb_buf;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
                inode->i_ino, count, *ppos);
@@ -220,7 +220,7 @@ static ssize_t dlmfs_file_write(struct file *filp,
        int bytes_left;
        ssize_t writelen;
        char *lvb_buf;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
                inode->i_ino, count, *ppos);
@@ -257,7 +257,7 @@ static ssize_t dlmfs_file_write(struct file *filp,
 }
 
 static void dlmfs_init_once(void *foo,
-                           kmem_cache_t *cachep,
+                           struct kmem_cache *cachep,
                            unsigned long flags)
 {
        struct dlmfs_inode_private *ip =
@@ -276,7 +276,7 @@ static struct inode *dlmfs_alloc_inode(struct super_block *sb)
 {
        struct dlmfs_inode_private *ip;
 
-       ip = kmem_cache_alloc(dlmfs_inode_cache, SLAB_NOFS);
+       ip = kmem_cache_alloc(dlmfs_inode_cache, GFP_NOFS);
        if (!ip)
                return NULL;
 
index f784177..856012b 100644 (file)
@@ -221,7 +221,7 @@ EXPORT_SYMBOL_GPL(dlm_dump_all_mles);
 #endif  /*  0  */
 
 
-static kmem_cache_t *dlm_mle_cache = NULL;
+static struct kmem_cache *dlm_mle_cache = NULL;
 
 
 static void dlm_mle_release(struct kref *kref);
index 9d950d7..fb3e2b0 100644 (file)
@@ -153,9 +153,10 @@ static inline void dlm_reset_recovery(struct dlm_ctxt *dlm)
 }
 
 /* Worker function used during recovery. */
-void dlm_dispatch_work(void *data)
+void dlm_dispatch_work(struct work_struct *work)
 {
-       struct dlm_ctxt *dlm = (struct dlm_ctxt *)data;
+       struct dlm_ctxt *dlm =
+               container_of(work, struct dlm_ctxt, dispatched_work);
        LIST_HEAD(tmp_list);
        struct list_head *iter, *iter2;
        struct dlm_work_item *item;
index eead48b..7d2f578 100644 (file)
@@ -171,15 +171,14 @@ static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres)
                BUG();
 }
 
-static void user_dlm_unblock_lock(void *opaque);
+static void user_dlm_unblock_lock(struct work_struct *work);
 
 static void __user_dlm_queue_lockres(struct user_lock_res *lockres)
 {
        if (!(lockres->l_flags & USER_LOCK_QUEUED)) {
                user_dlm_grab_inode_ref(lockres);
 
-               INIT_WORK(&lockres->l_work, user_dlm_unblock_lock,
-                         lockres);
+               INIT_WORK(&lockres->l_work, user_dlm_unblock_lock);
 
                queue_work(user_dlm_worker, &lockres->l_work);
                lockres->l_flags |= USER_LOCK_QUEUED;
@@ -279,10 +278,11 @@ static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres)
        iput(inode);
 }
 
-static void user_dlm_unblock_lock(void *opaque)
+static void user_dlm_unblock_lock(struct work_struct *work)
 {
        int new_level, status;
-       struct user_lock_res *lockres = (struct user_lock_res *) opaque;
+       struct user_lock_res *lockres =
+               container_of(work, struct user_lock_res, l_work);
        struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
 
        mlog(0, "processing lockres %.*s\n", lockres->l_namelen,
index fcd4475..80ac69f 100644 (file)
@@ -61,7 +61,7 @@ struct ocfs2_em_insert_context {
        struct ocfs2_extent_map_entry *right_ent;
 };
 
-static kmem_cache_t *ocfs2_em_ent_cachep = NULL;
+static struct kmem_cache *ocfs2_em_ent_cachep = NULL;
 
 
 static struct ocfs2_extent_map_entry *
index 8786b3c..e9a82ad 100644 (file)
@@ -68,7 +68,7 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
        mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
-                  file->f_dentry->d_name.len, file->f_dentry->d_name.name);
+                  file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name);
 
        spin_lock(&oi->ip_lock);
 
@@ -98,8 +98,8 @@ static int ocfs2_file_release(struct inode *inode, struct file *file)
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
        mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
-                      file->f_dentry->d_name.len,
-                      file->f_dentry->d_name.name);
+                      file->f_path.dentry->d_name.len,
+                      file->f_path.dentry->d_name.name);
 
        spin_lock(&oi->ip_lock);
        if (!--oi->ip_open_count)
@@ -1131,13 +1131,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 {
        int ret, rw_level, have_alloc_sem = 0;
        struct file *filp = iocb->ki_filp;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int appending = filp->f_flags & O_APPEND ? 1 : 0;
 
        mlog_entry("(0x%p, %u, '%.*s')\n", filp,
                   (unsigned int)nr_segs,
-                  filp->f_dentry->d_name.len,
-                  filp->f_dentry->d_name.name);
+                  filp->f_path.dentry->d_name.len,
+                  filp->f_path.dentry->d_name.name);
 
        /* happy write of zero bytes */
        if (iocb->ki_left == 0)
@@ -1159,7 +1159,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
                goto out;
        }
 
-       ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos,
+       ret = ocfs2_prepare_inode_for_write(filp->f_path.dentry, &iocb->ki_pos,
                                            iocb->ki_left, appending);
        if (ret < 0) {
                mlog_errno(ret);
@@ -1207,12 +1207,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
                                       unsigned int flags)
 {
        int ret;
-       struct inode *inode = out->f_dentry->d_inode;
+       struct inode *inode = out->f_path.dentry->d_inode;
 
        mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
                   (unsigned int)len,
-                  out->f_dentry->d_name.len,
-                  out->f_dentry->d_name.name);
+                  out->f_path.dentry->d_name.len,
+                  out->f_path.dentry->d_name.name);
 
        inode_double_lock(inode, pipe->inode);
 
@@ -1222,7 +1222,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
                goto out;
        }
 
-       ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0);
+       ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_unlock;
@@ -1247,12 +1247,12 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
                                      unsigned int flags)
 {
        int ret = 0;
-       struct inode *inode = in->f_dentry->d_inode;
+       struct inode *inode = in->f_path.dentry->d_inode;
 
        mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe,
                   (unsigned int)len,
-                  in->f_dentry->d_name.len,
-                  in->f_dentry->d_name.name);
+                  in->f_path.dentry->d_name.len,
+                  in->f_path.dentry->d_name.name);
 
        /*
         * See the comment in ocfs2_file_aio_read()
@@ -1278,12 +1278,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
 {
        int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
        struct file *filp = iocb->ki_filp;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        mlog_entry("(0x%p, %u, '%.*s')\n", filp,
                   (unsigned int)nr_segs,
-                  filp->f_dentry->d_name.len,
-                  filp->f_dentry->d_name.name);
+                  filp->f_path.dentry->d_name.len,
+                  filp->f_path.dentry->d_name.name);
 
        if (!inode) {
                ret = -EINVAL;
index 46a378f..1a7dd29 100644 (file)
@@ -106,7 +106,7 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
 #define INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags & OCFS2_INODE_JOURNAL)
 #define SET_INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags |= OCFS2_INODE_JOURNAL)
 
-extern kmem_cache_t *ocfs2_inode_cache;
+extern struct kmem_cache *ocfs2_inode_cache;
 
 extern const struct address_space_operations ocfs2_aops;
 
index c0ad7cb..1d7f4ab 100644 (file)
@@ -703,11 +703,12 @@ struct ocfs2_la_recovery_item {
  * NOTE: This function can and will sleep on recovery of other nodes
  * during cluster locking, just like any other ocfs2 process.
  */
-void ocfs2_complete_recovery(void *data)
+void ocfs2_complete_recovery(struct work_struct *work)
 {
        int ret;
-       struct ocfs2_super *osb = data;
-       struct ocfs2_journal *journal = osb->journal;
+       struct ocfs2_journal *journal =
+               container_of(work, struct ocfs2_journal, j_recovery_work);
+       struct ocfs2_super *osb = journal->j_osb;
        struct ocfs2_dinode *la_dinode, *tl_dinode;
        struct ocfs2_la_recovery_item *item;
        struct list_head *p, *n;
index d86cb96..899112a 100644 (file)
@@ -133,7 +133,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
 }
 
 /* Exported only for the journal struct init code in super.c. Do not call. */
-void ocfs2_complete_recovery(void *data);
+void ocfs2_complete_recovery(struct work_struct *work);
 
 /*
  *  Journal Control:
index 0788837..b767fd7 100644 (file)
@@ -285,7 +285,7 @@ struct ocfs2_super
        /* Truncate log info */
        struct inode                    *osb_tl_inode;
        struct buffer_head              *osb_tl_bh;
-       struct work_struct              osb_truncate_log_wq;
+       struct delayed_work             osb_truncate_log_wq;
 
        struct ocfs2_node_map           osb_recovering_orphan_dirs;
        unsigned int                    *osb_orphan_wipes;
index b099257..4bf3954 100644 (file)
@@ -68,7 +68,7 @@
 
 #include "buffer_head_io.h"
 
-static kmem_cache_t *ocfs2_inode_cachep = NULL;
+static struct kmem_cache *ocfs2_inode_cachep = NULL;
 
 /* OCFS2 needs to schedule several differnt types of work which
  * require cluster locking, disk I/O, recovery waits, etc. Since these
@@ -303,7 +303,7 @@ static struct inode *ocfs2_alloc_inode(struct super_block *sb)
 {
        struct ocfs2_inode_info *oi;
 
-       oi = kmem_cache_alloc(ocfs2_inode_cachep, SLAB_NOFS);
+       oi = kmem_cache_alloc(ocfs2_inode_cachep, GFP_NOFS);
        if (!oi)
                return NULL;
 
@@ -914,7 +914,7 @@ bail:
 }
 
 static void ocfs2_inode_init_once(void *data,
-                                 kmem_cache_t *cachep,
+                                 struct kmem_cache *cachep,
                                  unsigned long flags)
 {
        struct ocfs2_inode_info *oi = data;
@@ -1365,7 +1365,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
        spin_lock_init(&journal->j_lock);
        journal->j_trans_id = (unsigned long) 1;
        INIT_LIST_HEAD(&journal->j_la_cleanups);
-       INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery, osb);
+       INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
        journal->j_state = OCFS2_JOURNAL_FREE;
 
        /* get some pseudo constants for clustersize bits */
@@ -1674,7 +1674,7 @@ void __ocfs2_error(struct super_block *sb,
        va_list args;
 
        va_start(args, fmt);
-       vsprintf(error_buf, fmt, args);
+       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
        va_end(args);
 
        /* Not using mlog here because we want to show the actual
@@ -1695,7 +1695,7 @@ void __ocfs2_abort(struct super_block* sb,
        va_list args;
 
        va_start(args, fmt);
-       vsprintf(error_buf, fmt, args);
+       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
        va_end(args);
 
        printk(KERN_CRIT "OCFS2: abort (device %s): %s: %s\n",
index 9707ed7..39814b9 100644 (file)
@@ -69,7 +69,7 @@ struct ocfs2_meta_cache_item {
        sector_t        c_block;
 };
 
-static kmem_cache_t *ocfs2_uptodate_cachep = NULL;
+static struct kmem_cache *ocfs2_uptodate_cachep = NULL;
 
 void ocfs2_metadata_cache_init(struct inode *inode)
 {
index 89e0c23..c989fb4 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -165,7 +165,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs_native(file->f_dentry, &tmp);
+       error = vfs_statfs_native(file->f_path.dentry, &tmp);
        if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                error = -EFAULT;
        fput(file);
@@ -186,7 +186,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user
        file = fget(fd);
        if (!file)
                goto out;
-       error = vfs_statfs64(file->f_dentry, &tmp);
+       error = vfs_statfs64(file->f_path.dentry, &tmp);
        if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                error = -EFAULT;
        fput(file);
@@ -302,7 +302,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
        if (file->f_flags & O_LARGEFILE)
                small = 0;
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        inode = dentry->d_inode;
        error = -EINVAL;
        if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
@@ -448,8 +448,8 @@ asmlinkage long sys_fchdir(unsigned int fd)
        if (!file)
                goto out;
 
-       dentry = file->f_dentry;
-       mnt = file->f_vfsmnt;
+       dentry = file->f_path.dentry;
+       mnt = file->f_path.mnt;
        inode = dentry->d_inode;
 
        error = -ENOTDIR;
@@ -503,7 +503,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        if (!file)
                goto out;
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        inode = dentry->d_inode;
 
        audit_inode(NULL, inode);
@@ -662,7 +662,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
        if (!file)
                goto out;
 
-       dentry = file->f_dentry;
+       dentry = file->f_path.dentry;
        audit_inode(NULL, dentry->d_inode);
        error = chown_common(dentry, user, group);
        fput(file);
@@ -688,8 +688,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        }
 
        f->f_mapping = inode->i_mapping;
-       f->f_dentry = dentry;
-       f->f_vfsmnt = mnt;
+       f->f_path.dentry = dentry;
+       f->f_path.mnt = mnt;
        f->f_pos = 0;
        f->f_op = fops_get(inode->i_fop);
        file_move(f, &inode->i_sb->s_files);
@@ -723,8 +723,8 @@ cleanup_all:
        if (f->f_mode & FMODE_WRITE)
                put_write_access(inode);
        file_kill(f);
-       f->f_dentry = NULL;
-       f->f_vfsmnt = NULL;
+       f->f_path.dentry = NULL;
+       f->f_path.mnt = NULL;
 cleanup_file:
        put_filp(f);
        dput(dentry);
@@ -822,7 +822,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
        /* Pick up the filp from the open intent */
        filp = nd->intent.open.file;
        /* Has the filesystem initialised the file for us? */
-       if (filp->f_dentry == NULL)
+       if (filp->f_path.dentry == NULL)
                filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
        else
                path_release(nd);
@@ -864,8 +864,7 @@ int get_unused_fd(void)
 
 repeat:
        fdt = files_fdtable(files);
-       fd = find_next_zero_bit(fdt->open_fds->fds_bits,
-                               fdt->max_fdset,
+       fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
                                files->next_fd);
 
        /*
@@ -965,7 +964,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
                                put_unused_fd(fd);
                                fd = PTR_ERR(f);
                        } else {
-                               fsnotify_open(f->f_dentry);
+                               fsnotify_open(f->f_path.dentry);
                                fd_install(fd, f);
                        }
                }
@@ -1087,6 +1086,7 @@ EXPORT_SYMBOL(sys_close);
 asmlinkage long sys_vhangup(void)
 {
        if (capable(CAP_SYS_TTY_CONFIG)) {
+               /* XXX: this needs locking */
                tty_vhangup(current->signal->tty);
                return 0;
        }
index 592a640..99c0bc3 100644 (file)
@@ -262,7 +262,7 @@ found:
 
 static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct op_inode_info *oi = OP_I(inode);
        struct device_node *dp = oi->u.node;
        struct device_node *child;
@@ -330,13 +330,13 @@ out:
        return 0;
 }
 
-static kmem_cache_t *op_inode_cachep;
+static struct kmem_cache *op_inode_cachep;
 
 static struct inode *openprom_alloc_inode(struct super_block *sb)
 {
        struct op_inode_info *oi;
 
-       oi = kmem_cache_alloc(op_inode_cachep, SLAB_KERNEL);
+       oi = kmem_cache_alloc(op_inode_cachep, GFP_KERNEL);
        if (!oi)
                return NULL;
 
@@ -415,7 +415,7 @@ static struct file_system_type openprom_fs_type = {
        .kill_sb        = kill_anon_super,
 };
 
-static void op_inode_init_once(void *data, kmem_cache_t * cachep, unsigned long flags)
+static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned long flags)
 {
        struct op_inode_info *oi = (struct op_inode_info *) data;
 
index e478f19..74552c6 100644 (file)
@@ -194,7 +194,7 @@ config LDM_DEBUG
 
 config SGI_PARTITION
        bool "SGI partition support" if PARTITION_ADVANCED
-       default y if (SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM200_PCI) && !CPU_LITTLE_ENDIAN))
+       default y if (SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM) && !CPU_LITTLE_ENDIAN))
        help
          Say Y here if you would like to be able to read the hard disk
          partition table format used by SGI machines.
index 3068528..9917a8c 100644 (file)
@@ -43,6 +43,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                        if (warn_no_part)
                                printk("Dev %s: unable to read RDB block %d\n",
                                       bdevname(bdev, b), blk);
+                       res = -1;
                        goto rdb_done;
                }
                if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
@@ -79,6 +80,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
                        if (warn_no_part)
                                printk("Dev %s: unable to read partition block %d\n",
                                       bdevname(bdev, b), blk);
+                       res = -1;
                        goto rdb_done;
                }
                pb  = (struct PartitionBlock *)data;
index 192a6ad..1f3572d 100644 (file)
@@ -88,7 +88,7 @@ int atari_partition(struct parsed_partitions *state, struct block_device *bdev)
                        if (!xrs) {
                                printk (" block %ld read failed\n", partsect);
                                put_dev_sector(sect);
-                               return 0;
+                               return -1;
                        }
 
                        /* ++roman: sanity check: bit 0 of flg field must be set */
index 6fb4b61..3d73d94 100644 (file)
@@ -153,7 +153,7 @@ static struct parsed_partitions *
 check_partition(struct gendisk *hd, struct block_device *bdev)
 {
        struct parsed_partitions *state;
-       int i, res;
+       int i, res, err;
 
        state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
        if (!state)
@@ -165,19 +165,30 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
                sprintf(state->name, "p");
 
        state->limit = hd->minors;
-       i = res = 0;
+       i = res = err = 0;
        while (!res && check_part[i]) {
                memset(&state->parts, 0, sizeof(state->parts));
                res = check_part[i++](state, bdev);
+               if (res < 0) {
+                       /* We have hit an I/O error which we don't report now.
+                       * But record it, and let the others do their job.
+                       */
+                       err = res;
+                       res = 0;
+               }
+
        }
        if (res > 0)
                return state;
+       if (!err)
+       /* The partition is unrecognized. So report I/O errors if there were any */
+               res = err;
        if (!res)
                printk(" unknown partition table\n");
        else if (warn_no_part)
                printk(" unable to read partition table\n");
        kfree(state);
-       return NULL;
+       return ERR_PTR(res);
 }
 
 /*
@@ -265,12 +276,39 @@ static struct part_attribute part_attr_stat = {
        .show   = part_stat_read
 };
 
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static ssize_t part_fail_store(struct hd_struct * p,
+                              const char *buf, size_t count)
+{
+       int i;
+
+       if (count > 0 && sscanf(buf, "%d", &i) > 0)
+               p->make_it_fail = (i == 0) ? 0 : 1;
+
+       return count;
+}
+static ssize_t part_fail_read(struct hd_struct * p, char *page)
+{
+       return sprintf(page, "%d\n", p->make_it_fail);
+}
+static struct part_attribute part_attr_fail = {
+       .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
+       .store  = part_fail_store,
+       .show   = part_fail_read
+};
+
+#endif
+
 static struct attribute * default_attrs[] = {
        &part_attr_uevent.attr,
        &part_attr_dev.attr,
        &part_attr_start.attr,
        &part_attr_size.attr,
        &part_attr_stat.attr,
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+       &part_attr_fail.attr,
+#endif
        NULL,
 };
 
@@ -494,6 +532,8 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
                disk->fops->revalidate_disk(disk);
        if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
                return 0;
+       if (IS_ERR(state))      /* I/O error reading the partition table */
+               return PTR_ERR(state);
        for (p = 1; p < state->limit; p++) {
                sector_t size = state->parts[p].size;
                sector_t from = state->parts[p].from;
index d352a73..9f7ad42 100644 (file)
@@ -43,7 +43,7 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
 int
 ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-       int blocksize, offset, size;
+       int blocksize, offset, size,res;
        loff_t i_size;
        dasd_information_t *info;
        struct hd_geometry *geo;
@@ -56,15 +56,16 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
        unsigned char *data;
        Sector sect;
 
+       res = 0;
        blocksize = bdev_hardsect_size(bdev);
        if (blocksize <= 0)
-               return 0;
+               goto out_exit;
        i_size = i_size_read(bdev->bd_inode);
        if (i_size == 0)
-               return 0;
+               goto out_exit;
 
        if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
-               goto out_noinfo;
+               goto out_exit;
        if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
                goto out_nogeo;
        if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
@@ -72,7 +73,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
 
        if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
            ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
-               goto out_noioctl;
+               goto out_freeall;
 
        /*
         * Get volume label, extract name and type.
@@ -92,6 +93,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
        EBCASC(type, 4);
        EBCASC(name, 6);
 
+       res = 1;
+
        /*
         * Three different types: CMS1, VOL1 and LNX1/unlabeled
         */
@@ -156,6 +159,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
                        counter++;
                        blk++;
                }
+               if (!data)
+               /* Are we not supposed to report this ? */
+                       goto out_readerr;
        } else {
                /*
                 * Old style LNX1 or unlabeled disk
@@ -171,18 +177,17 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
        }
 
        printk("\n");
-       kfree(label);
-       kfree(geo);
-       kfree(info);
-       return 1;
+       goto out_freeall;
+
 
 out_readerr:
-out_noioctl:
+       res = -1;
+out_freeall:
        kfree(label);
 out_nolab:
        kfree(geo);
 out_nogeo:
        kfree(info);
-out_noinfo:
-       return 0;
+out_exit:
+       return res;
 }
index b1626f2..f8b6bdc 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -222,7 +222,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
           unsigned long nr_segs, loff_t pos)
 {
        struct file *filp = iocb->ki_filp;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pipe_inode_info *pipe;
        int do_wakeup;
        ssize_t ret;
@@ -335,7 +335,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
            unsigned long nr_segs, loff_t ppos)
 {
        struct file *filp = iocb->ki_filp;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pipe_inode_info *pipe;
        ssize_t ret;
        int do_wakeup;
@@ -520,7 +520,7 @@ static int
 pipe_ioctl(struct inode *pino, struct file *filp,
           unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pipe_inode_info *pipe;
        int count, buf, nrbufs;
 
@@ -548,7 +548,7 @@ static unsigned int
 pipe_poll(struct file *filp, poll_table *wait)
 {
        unsigned int mask;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pipe_inode_info *pipe = inode->i_pipe;
        int nrbufs;
 
@@ -601,7 +601,7 @@ pipe_release(struct inode *inode, int decr, int decw)
 static int
 pipe_read_fasync(int fd, struct file *filp, int on)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int retval;
 
        mutex_lock(&inode->i_mutex);
@@ -618,7 +618,7 @@ pipe_read_fasync(int fd, struct file *filp, int on)
 static int
 pipe_write_fasync(int fd, struct file *filp, int on)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int retval;
 
        mutex_lock(&inode->i_mutex);
@@ -635,7 +635,7 @@ pipe_write_fasync(int fd, struct file *filp, int on)
 static int
 pipe_rdwr_fasync(int fd, struct file *filp, int on)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pipe_inode_info *pipe = inode->i_pipe;
        int retval;
 
@@ -830,7 +830,14 @@ void free_pipe_info(struct inode *inode)
 static struct vfsmount *pipe_mnt __read_mostly;
 static int pipefs_delete_dentry(struct dentry *dentry)
 {
-       return 1;
+       /*
+        * At creation time, we pretended this dentry was hashed
+        * (by clearing DCACHE_UNHASHED bit in d_flags)
+        * At delete time, we restore the truth : not hashed.
+        * (so that dput() can proceed correctly)
+        */
+       dentry->d_flags |= DCACHE_UNHASHED;
+       return 0;
 }
 
 static struct dentry_operations pipefs_dentry_operations = {
@@ -891,19 +898,24 @@ struct file *create_write_pipe(void)
        if (!inode)
                goto err_file;
 
-       sprintf(name, "[%lu]", inode->i_ino);
+       this.len = sprintf(name, "[%lu]", inode->i_ino);
        this.name = name;
-       this.len = strlen(name);
-       this.hash = inode->i_ino; /* will go */
+       this.hash = 0;
        err = -ENOMEM;
        dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
        if (!dentry)
                goto err_inode;
 
        dentry->d_op = &pipefs_dentry_operations;
-       d_add(dentry, inode);
-       f->f_vfsmnt = mntget(pipe_mnt);
-       f->f_dentry = dentry;
+       /*
+        * We dont want to publish this dentry into global dentry hash table.
+        * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
+        * This permits a working /proc/$pid/fd/XXX on pipes
+        */
+       dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(dentry, inode);
+       f->f_path.mnt = mntget(pipe_mnt);
+       f->f_path.dentry = dentry;
        f->f_mapping = inode->i_mapping;
 
        f->f_flags = O_WRONLY;
@@ -923,8 +935,8 @@ struct file *create_write_pipe(void)
 
 void free_write_pipe(struct file *f)
 {
-       mntput(f->f_vfsmnt);
-       dput(f->f_dentry);
+       mntput(f->f_path.mnt);
+       dput(f->f_path.dentry);
        put_filp(f);
 }
 
@@ -935,9 +947,9 @@ struct file *create_read_pipe(struct file *wrf)
                return ERR_PTR(-ENFILE);
 
        /* Grab pipe from the writer */
-       f->f_vfsmnt = mntget(wrf->f_vfsmnt);
-       f->f_dentry = dget(wrf->f_dentry);
-       f->f_mapping = wrf->f_dentry->d_inode->i_mapping;
+       f->f_path.mnt = mntget(wrf->f_path.mnt);
+       f->f_path.dentry = dget(wrf->f_path.dentry);
+       f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
 
        f->f_pos = 0;
        f->f_flags = O_RDONLY;
index da42ee6..56aacea 100644 (file)
@@ -6,7 +6,7 @@
  *     Author : Ram Pai (linuxram@us.ibm.com)
  *
  */
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/mount.h>
 #include <linux/fs.h>
 #include "pnode.h"
index 020e1bb..d45bd8e 100644 (file)
@@ -13,7 +13,7 @@
 
 #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED)
 #define IS_MNT_SLAVE(mnt) (mnt->mnt_master)
-#define IS_MNT_NEW(mnt)  (!mnt->mnt_namespace)
+#define IS_MNT_NEW(mnt)  (!mnt->mnt_ns)
 #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED)
 #define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE)
 
index 7431d7b..f6c7762 100644 (file)
@@ -8,8 +8,9 @@ proc-y                  := nommu.o task_nommu.o
 proc-$(CONFIG_MMU)     := mmu.o task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
-               kmsg.o proc_tty.o proc_misc.o
+               proc_tty.o proc_misc.o
 
 proc-$(CONFIG_PROC_KCORE)      += kcore.o
 proc-$(CONFIG_PROC_VMCORE)     += vmcore.o
 proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
+proc-$(CONFIG_PRINTK)  += kmsg.o
index 25e917f..70e4fab 100644 (file)
@@ -346,20 +346,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        sigemptyset(&sigcatch);
        cutime = cstime = utime = stime = cputime_zero;
 
-       mutex_lock(&tty_mutex);
        rcu_read_lock();
        if (lock_task_sighand(task, &flags)) {
                struct signal_struct *sig = task->signal;
-               struct tty_struct *tty = sig->tty;
-
-               if (tty) {
-                       /*
-                        * sig->tty is not stable, but tty_mutex
-                        * protects us from release_dev(tty)
-                        */
-                       barrier();
-                       tty_pgrp = tty->pgrp;
-                       tty_nr = new_encode_dev(tty_devnum(tty));
+
+               if (sig->tty) {
+                       tty_pgrp = sig->tty->pgrp;
+                       tty_nr = new_encode_dev(tty_devnum(sig->tty));
                }
 
                num_threads = atomic_read(&sig->count);
@@ -388,14 +381,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
                        stime = cputime_add(stime, sig->stime);
                }
 
-               sid = sig->session;
+               sid = signal_session(sig);
                pgid = process_group(task);
                ppid = rcu_dereference(task->real_parent)->tgid;
 
                unlock_task_sighand(task, &flags);
        }
        rcu_read_unlock();
-       mutex_unlock(&tty_mutex);
 
        if (!whole || num_threads<2)
                wchan = get_wchan(task);
index 795319c..77a57b5 100644 (file)
@@ -59,7 +59,7 @@
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/rcupdate.h>
@@ -365,33 +365,33 @@ struct proc_mounts {
 static int mounts_open(struct inode *inode, struct file *file)
 {
        struct task_struct *task = get_proc_task(inode);
-       struct namespace *namespace = NULL;
+       struct mnt_namespace *ns = NULL;
        struct proc_mounts *p;
        int ret = -EINVAL;
 
        if (task) {
                task_lock(task);
-               namespace = task->nsproxy->namespace;
-               if (namespace)
-                       get_namespace(namespace);
+               ns = task->nsproxy->mnt_ns;
+               if (ns)
+                       get_mnt_ns(ns);
                task_unlock(task);
                put_task_struct(task);
        }
 
-       if (namespace) {
+       if (ns) {
                ret = -ENOMEM;
                p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
                if (p) {
                        file->private_data = &p->m;
                        ret = seq_open(file, &mounts_op);
                        if (!ret) {
-                               p->m.private = namespace;
-                               p->event = namespace->event;
+                               p->m.private = ns;
+                               p->event = ns->event;
                                return 0;
                        }
                        kfree(p);
                }
-               put_namespace(namespace);
+               put_mnt_ns(ns);
        }
        return ret;
 }
@@ -399,15 +399,15 @@ static int mounts_open(struct inode *inode, struct file *file)
 static int mounts_release(struct inode *inode, struct file *file)
 {
        struct seq_file *m = file->private_data;
-       struct namespace *namespace = m->private;
-       put_namespace(namespace);
+       struct mnt_namespace *ns = m->private;
+       put_mnt_ns(ns);
        return seq_release(inode, file);
 }
 
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
        struct proc_mounts *p = file->private_data;
-       struct namespace *ns = p->m.private;
+       struct mnt_namespace *ns = p->m.private;
        unsigned res = 0;
 
        poll_wait(file, &ns->poll, wait);
@@ -437,21 +437,21 @@ static int mountstats_open(struct inode *inode, struct file *file)
 
        if (!ret) {
                struct seq_file *m = file->private_data;
-               struct namespace *namespace = NULL;
+               struct mnt_namespace *mnt_ns = NULL;
                struct task_struct *task = get_proc_task(inode);
 
                if (task) {
                        task_lock(task);
                        if (task->nsproxy)
-                               namespace = task->nsproxy->namespace;
-                       if (namespace)
-                               get_namespace(namespace);
+                               mnt_ns = task->nsproxy->mnt_ns;
+                       if (mnt_ns)
+                               get_mnt_ns(mnt_ns);
                        task_unlock(task);
                        put_task_struct(task);
                }
 
-               if (namespace)
-                       m->private = namespace;
+               if (mnt_ns)
+                       m->private = mnt_ns;
                else {
                        seq_release(inode, file);
                        ret = -EINVAL;
@@ -472,7 +472,7 @@ static struct file_operations proc_mountstats_operations = {
 static ssize_t proc_info_read(struct file * file, char __user * buf,
                          size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        unsigned long page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -512,7 +512,7 @@ static int mem_open(struct inode* inode, struct file* file)
 static ssize_t mem_read(struct file * file, char __user * buf,
                        size_t count, loff_t *ppos)
 {
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        char *page;
        unsigned long src = *ppos;
        int ret = -ESRCH;
@@ -584,7 +584,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
 {
        int copied;
        char *page;
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        unsigned long dst = *ppos;
 
        copied = -ESRCH;
@@ -654,7 +654,7 @@ static struct file_operations proc_mem_operations = {
 static ssize_t oom_adjust_read(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
        char buffer[PROC_NUMBUF];
        size_t len;
        int oom_adjust;
@@ -683,8 +683,6 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        char buffer[PROC_NUMBUF], *end;
        int oom_adjust;
 
-       if (!capable(CAP_SYS_RESOURCE))
-               return -EPERM;
        memset(buffer, 0, sizeof(buffer));
        if (count > sizeof(buffer) - 1)
                count = sizeof(buffer) - 1;
@@ -696,9 +694,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
                return -EINVAL;
        if (*end == '\n')
                end++;
-       task = get_proc_task(file->f_dentry->d_inode);
+       task = get_proc_task(file->f_path.dentry->d_inode);
        if (!task)
                return -ESRCH;
+       if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
+               put_task_struct(task);
+               return -EACCES;
+       }
        task->oomkilladj = oom_adjust;
        put_task_struct(task);
        if (end - buffer == 0)
@@ -716,7 +718,7 @@ static struct file_operations proc_oom_adjust_operations = {
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
        ssize_t length;
        char tmpbuf[TMPBUFLEN];
@@ -732,7 +734,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
 static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                                   size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        char *page, *tmp;
        ssize_t length;
        uid_t loginuid;
@@ -851,6 +853,65 @@ static struct file_operations proc_seccomp_operations = {
 };
 #endif /* CONFIG_SECCOMP */
 
+#ifdef CONFIG_FAULT_INJECTION
+static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       size_t len;
+       int make_it_fail;
+       loff_t __ppos = *ppos;
+
+       if (!task)
+               return -ESRCH;
+       make_it_fail = task->make_it_fail;
+       put_task_struct(task);
+
+       len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);
+       if (__ppos >= len)
+               return 0;
+       if (count > len-__ppos)
+               count = len-__ppos;
+       if (copy_to_user(buf, buffer + __ppos, count))
+               return -EFAULT;
+       *ppos = __ppos + count;
+       return count;
+}
+
+static ssize_t proc_fault_inject_write(struct file * file,
+                       const char __user * buf, size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF], *end;
+       int make_it_fail;
+
+       if (!capable(CAP_SYS_RESOURCE))
+               return -EPERM;
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count))
+               return -EFAULT;
+       make_it_fail = simple_strtol(buffer, &end, 0);
+       if (*end == '\n')
+               end++;
+       task = get_proc_task(file->f_dentry->d_inode);
+       if (!task)
+               return -ESRCH;
+       task->make_it_fail = make_it_fail;
+       put_task_struct(task);
+       if (end - buffer == 0)
+               return -EIO;
+       return end - buffer;
+}
+
+static struct file_operations proc_fault_inject_operations = {
+       .read           = proc_fault_inject_read,
+       .write          = proc_fault_inject_write,
+};
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
@@ -1076,7 +1137,7 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        char *name, int len,
        instantiate_t instantiate, struct task_struct *task, void *ptr)
 {
-       struct dentry *child, *dir = filp->f_dentry;
+       struct dentry *child, *dir = filp->f_path.dentry;
        struct inode *inode;
        struct qstr qname;
        ino_t ino = 0;
@@ -1155,8 +1216,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
-                       *mnt = mntget(file->f_vfsmnt);
-                       *dentry = dget(file->f_dentry);
+                       *mnt = mntget(file->f_path.mnt);
+                       *dentry = dget(file->f_path.dentry);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
@@ -1291,7 +1352,7 @@ static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir
 
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *p = get_proc_task(inode);
        unsigned int fd, tid, ino;
@@ -1438,7 +1499,7 @@ static int proc_pident_readdir(struct file *filp,
 {
        int i;
        int pid;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
        struct pid_entry *p, *last;
@@ -1494,7 +1555,7 @@ out_no_task:
 static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        unsigned long page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -1510,7 +1571,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
                goto out;
 
        length = security_getprocattr(task,
-                                     (char*)file->f_dentry->d_name.name,
+                                     (char*)file->f_path.dentry->d_name.name,
                                      (void*)page, count);
        if (length >= 0)
                length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
@@ -1524,7 +1585,7 @@ out_no_task:
 static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
                                   size_t count, loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        char *page;
        ssize_t length;
        struct task_struct *task = get_proc_task(inode);
@@ -1550,7 +1611,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
                goto out_free;
 
        length = security_setprocattr(task,
-                                     (char*)file->f_dentry->d_name.name,
+                                     (char*)file->f_path.dentry->d_name.name,
                                      (void*)page, count);
 out_free:
        free_page((unsigned long) page);
@@ -1743,6 +1804,27 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filld
                                proc_base_instantiate, task, p);
 }
 
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return sprintf(buffer,
+                       "rchar: %llu\n"
+                       "wchar: %llu\n"
+                       "syscr: %llu\n"
+                       "syscw: %llu\n"
+                       "read_bytes: %llu\n"
+                       "write_bytes: %llu\n"
+                       "cancelled_write_bytes: %llu\n",
+                       (unsigned long long)task->rchar,
+                       (unsigned long long)task->wchar,
+                       (unsigned long long)task->syscr,
+                       (unsigned long long)task->syscw,
+                       (unsigned long long)task->ioac.read_bytes,
+                       (unsigned long long)task->ioac.write_bytes,
+                       (unsigned long long)task->ioac.cancelled_write_bytes);
+}
+#endif
+
 /*
  * Thread groups
  */
@@ -1791,6 +1873,12 @@ static struct pid_entry tgid_base_stuff[] = {
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, loginuid),
 #endif
+#ifdef CONFIG_FAULT_INJECTION
+       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+       INF("io",       S_IRUGO, pid_io_accounting),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file * filp,
@@ -1883,8 +1971,9 @@ out:
        return;
 }
 
-struct dentry *proc_pid_instantiate(struct inode *dir,
-       struct dentry * dentry, struct task_struct *task, void *ptr)
+static struct dentry *proc_pid_instantiate(struct inode *dir,
+                                          struct dentry * dentry,
+                                          struct task_struct *task, void *ptr)
 {
        struct dentry *error = ERR_PTR(-ENOENT);
        struct inode *inode;
@@ -1991,7 +2080,7 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
        unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-       struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode);
+       struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
        struct task_struct *task;
        int tgid;
 
@@ -2065,6 +2154,9 @@ static struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, loginuid),
 #endif
+#ifdef CONFIG_FAULT_INJECTION
+       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file * filp,
@@ -2232,7 +2324,7 @@ static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filld
 /* for the /proc/TGID/task/ directories */
 static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *leader = get_proc_task(inode);
        struct task_struct *task;
index 4ba0300..853cb87 100644 (file)
@@ -52,7 +52,7 @@ static ssize_t
 proc_file_read(struct file *file, char __user *buf, size_t nbytes,
               loff_t *ppos)
 {
-       struct inode * inode = file->f_dentry->d_inode;
+       struct inode * inode = file->f_path.dentry->d_inode;
        char    *page;
        ssize_t retval=0;
        int     eof=0;
@@ -203,7 +203,7 @@ static ssize_t
 proc_file_write(struct file *file, const char __user *buffer,
                size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry * dp;
        
        dp = PDE(inode);
@@ -432,7 +432,7 @@ int proc_readdir(struct file * filp,
        struct proc_dir_entry * de;
        unsigned int ino;
        int i;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        int ret = 0;
 
        lock_kernel();
@@ -453,7 +453,7 @@ int proc_readdir(struct file * filp,
                        /* fall through */
                case 1:
                        if (filldir(dirent, "..", 2, i,
-                                   parent_ino(filp->f_dentry),
+                                   parent_ino(filp->f_path.dentry),
                                    DT_DIR) < 0)
                                goto out;
                        i++;
@@ -558,7 +558,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
        file_list_lock();
        list_for_each(p, &sb->s_files) {
                struct file * filp = list_entry(p, struct file, f_u.fu_list);
-               struct dentry * dentry = filp->f_dentry;
+               struct dentry * dentry = filp->f_path.dentry;
                struct inode * inode;
                const struct file_operations *fops;
 
index 49dfb2a..e26945b 100644 (file)
@@ -81,14 +81,14 @@ static void proc_read_inode(struct inode * inode)
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 }
 
-static kmem_cache_t * proc_inode_cachep;
+static struct kmem_cache * proc_inode_cachep;
 
 static struct inode *proc_alloc_inode(struct super_block *sb)
 {
        struct proc_inode *ei;
        struct inode *inode;
 
-       ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL);
+       ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        ei->pid = NULL;
@@ -105,7 +105,7 @@ static void proc_destroy_inode(struct inode *inode)
        kmem_cache_free(proc_inode_cachep, PROC_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct proc_inode *ei = (struct proc_inode *) foo;
 
index 1294eda..1be7308 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#define CORE_STR "CORE"
 
 static int open_kcore(struct inode * inode, struct file * filp)
 {
@@ -82,10 +83,11 @@ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
        }
        *elf_buflen =   sizeof(struct elfhdr) + 
                        (*nphdr + 2)*sizeof(struct elf_phdr) + 
-                       3 * (sizeof(struct elf_note) + 4) +
-                       sizeof(struct elf_prstatus) +
-                       sizeof(struct elf_prpsinfo) +
-                       sizeof(struct task_struct);
+                       3 * ((sizeof(struct elf_note)) +
+                            roundup(sizeof(CORE_STR), 4)) +
+                       roundup(sizeof(struct elf_prstatus), 4) +
+                       roundup(sizeof(struct elf_prpsinfo), 4) +
+                       roundup(sizeof(struct task_struct), 4);
        *elf_buflen = PAGE_ALIGN(*elf_buflen);
        return size + *elf_buflen;
 }
@@ -210,7 +212,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
        nhdr->p_offset  = offset;
 
        /* set up the process status */
-       notes[0].name = "CORE";
+       notes[0].name = CORE_STR;
        notes[0].type = NT_PRSTATUS;
        notes[0].datasz = sizeof(struct elf_prstatus);
        notes[0].data = &prstatus;
@@ -221,7 +223,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
        bufp = storenote(&notes[0], bufp);
 
        /* set up the process info */
-       notes[1].name   = "CORE";
+       notes[1].name   = CORE_STR;
        notes[1].type   = NT_PRPSINFO;
        notes[1].datasz = sizeof(struct elf_prpsinfo);
        notes[1].data   = &prpsinfo;
@@ -238,7 +240,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
        bufp = storenote(&notes[1], bufp);
 
        /* set up the task structure */
-       notes[2].name   = "CORE";
+       notes[2].name   = CORE_STR;
        notes[2].type   = NT_TASKSTRUCT;
        notes[2].datasz = sizeof(struct task_struct);
        notes[2].data   = current;
index d7dbdf9..5ec6725 100644 (file)
@@ -46,7 +46,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
        file = vma->vm_file;
 
        if (file) {
-               struct inode *inode = vma->vm_file->f_dentry->d_inode;
+               struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
                dev = inode->i_sb->s_dev;
                ino = inode->i_ino;
        }
@@ -67,7 +67,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
                if (len < 1)
                        len = 1;
                seq_printf(m, "%*c", len, ' ');
-               seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+               seq_path(m, file->f_path.mnt, file->f_path.dentry, "");
        }
 
        seq_putc(m, '\n');
index 93c43b6..92ea774 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/times.h>
 #include <linux/profile.h>
+#include <linux/utsname.h>
 #include <linux/blkdev.h>
 #include <linux/hugetlb.h>
 #include <linux/jiffies.h>
 #include <linux/sysrq.h>
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
-#include <linux/pspace.h>
+#include <linux/pid_namespace.h>
+#include <linux/compile.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -92,7 +94,7 @@ static int loadavg_read_proc(char *page, char **start, off_t off,
                LOAD_INT(a), LOAD_FRAC(a),
                LOAD_INT(b), LOAD_FRAC(b),
                LOAD_INT(c), LOAD_FRAC(c),
-               nr_running(), nr_threads, init_pspace.last_pid);
+               nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid);
        return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
@@ -252,8 +254,15 @@ static int version_read_proc(char *page, char **start, off_t off,
 {
        int len;
 
-       strcpy(page, linux_banner);
-       len = strlen(page);
+       /* FIXED STRING! Don't touch! */
+       len = snprintf(page, PAGE_SIZE,
+               "%s version %s"
+               " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+               " (" LINUX_COMPILER ")"
+               " %s\n",
+               utsname()->sysname,
+               utsname()->release,
+               utsname()->version);
        return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
@@ -696,9 +705,11 @@ void __init proc_misc_init(void)
        proc_symlink("mounts", NULL, "self/mounts");
 
        /* And now for trickier ones */
+#ifdef CONFIG_PRINTK
        entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
        if (entry)
                entry->proc_fops = &proc_kmsg_operations;
+#endif
        create_seq_entry("devices", 0, &proc_devinfo_operations);
        create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 #ifdef CONFIG_BLOCK
index 6b769af..55ade0d 100644 (file)
@@ -94,8 +94,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
        }
 
        if (vma) {
-               *mnt = mntget(vma->vm_file->f_vfsmnt);
-               *dentry = dget(vma->vm_file->f_dentry);
+               *mnt = mntget(vma->vm_file->f_path.mnt);
+               *dentry = dget(vma->vm_file->f_path.dentry);
                result = 0;
        }
 
@@ -135,7 +135,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
        int len;
 
        if (file) {
-               struct inode *inode = vma->vm_file->f_dentry->d_inode;
+               struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
                dev = inode->i_sb->s_dev;
                ino = inode->i_ino;
        }
@@ -156,7 +156,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
         */
        if (file) {
                pad_len_spaces(m, len);
-               seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
+               seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n");
        } else {
                const char *name = arch_vma_name(vma);
                if (!name) {
index 091aa8e..fcc5caf 100644 (file)
@@ -126,8 +126,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
        }
 
        if (vma) {
-               *mnt = mntget(vma->vm_file->f_vfsmnt);
-               *dentry = dget(vma->vm_file->f_dentry);
+               *mnt = mntget(vma->vm_file->f_path.mnt);
+               *dentry = dget(vma->vm_file->f_path.dentry);
                result = 0;
        }
 
index 0d7103f..c94db1d 100644 (file)
@@ -22,7 +22,7 @@
 
 static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        unsigned int offset;
        struct buffer_head *bh;
        struct qnx4_inode_entry *de;
index 5a41db2..c047dc6 100644 (file)
@@ -515,12 +515,12 @@ static void qnx4_read_inode(struct inode *inode)
        brelse(bh);
 }
 
-static kmem_cache_t *qnx4_inode_cachep;
+static struct kmem_cache *qnx4_inode_cachep;
 
 static struct inode *qnx4_alloc_inode(struct super_block *sb)
 {
        struct qnx4_inode_info *ei;
-       ei = kmem_cache_alloc(qnx4_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(qnx4_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -531,7 +531,7 @@ static void qnx4_destroy_inode(struct inode *inode)
        kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
 }
 
-static void init_once(void *foo, kmem_cache_t * cachep,
+static void init_once(void *foo, struct kmem_cache * cachep,
                      unsigned long flags)
 {
        struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
index bfe5dbf..61cbe1e 100644 (file)
@@ -232,7 +232,7 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
                                            unsigned long pgoff, unsigned long flags)
 {
        unsigned long maxpages, lpages, nr, loop, ret;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct page **pages = NULL, **ptr, *page;
        loff_t isize;
 
index f792000..1d3dda4 100644 (file)
@@ -64,13 +64,13 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
        lock_kernel();
        switch (origin) {
                case 2:
-                       offset += i_size_read(file->f_dentry->d_inode);
+                       offset += i_size_read(file->f_path.dentry->d_inode);
                        break;
                case 1:
                        offset += file->f_pos;
        }
        retval = -EINVAL;
-       if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
+       if (offset>=0 && offset<=file->f_path.dentry->d_inode->i_sb->s_maxbytes) {
                if (offset != file->f_pos) {
                        file->f_pos = offset;
                        file->f_version = 0;
@@ -95,7 +95,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
        lock_kernel();
        switch (origin) {
                case 2:
-                       offset += i_size_read(file->f_dentry->d_inode);
+                       offset += i_size_read(file->f_path.dentry->d_inode);
                        break;
                case 1:
                        offset += file->f_pos;
@@ -203,7 +203,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
        if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
                goto Einval;
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
                int retval = locks_mandatory_area(
                        read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
@@ -273,7 +273,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
                        else
                                ret = do_sync_read(file, buf, count, pos);
                        if (ret > 0) {
-                               fsnotify_access(file->f_dentry);
+                               fsnotify_access(file->f_path.dentry);
                                current->rchar += ret;
                        }
                        current->syscr++;
@@ -331,7 +331,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
                        else
                                ret = do_sync_write(file, buf, count, pos);
                        if (ret > 0) {
-                               fsnotify_modify(file->f_dentry);
+                               fsnotify_modify(file->f_path.dentry);
                                current->wchar += ret;
                        }
                        current->syscw++;
@@ -628,9 +628,9 @@ out:
                kfree(iov);
        if ((ret + (type == READ)) > 0) {
                if (type == READ)
-                       fsnotify_access(file->f_dentry);
+                       fsnotify_access(file->f_path.dentry);
                else
-                       fsnotify_modify(file->f_dentry);
+                       fsnotify_modify(file->f_path.dentry);
        }
        return ret;
 }
@@ -722,7 +722,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
        if (!(in_file->f_mode & FMODE_READ))
                goto fput_in;
        retval = -EINVAL;
-       in_inode = in_file->f_dentry->d_inode;
+       in_inode = in_file->f_path.dentry->d_inode;
        if (!in_inode)
                goto fput_in;
        if (!in_file->f_op || !in_file->f_op->sendfile)
@@ -754,7 +754,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
        retval = -EINVAL;
        if (!out_file->f_op || !out_file->f_op->sendpage)
                goto fput_out;
-       out_inode = out_file->f_dentry->d_inode;
+       out_inode = out_file->f_path.dentry->d_inode;
        retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
        if (retval < 0)
                goto fput_out;
index bff3ee5..f39f5b3 100644 (file)
@@ -21,7 +21,7 @@
 
 int vfs_readdir(struct file *file, filldir_t filler, void *buf)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int res = -ENOTDIR;
        if (!file->f_op || !file->f_op->readdir)
                goto out;
index e3d466a..b286ccb 100644 (file)
@@ -708,7 +708,7 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint)
  */
 static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
 {
-       struct path *path;
+       struct treepath *path;
        struct buffer_head *bh;
        struct item_head *ih;
        int pos_in_item;
index 657050a..96a2f88 100644 (file)
@@ -45,7 +45,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
 //
 static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
        INITIALIZE_PATH(path_to_entry);
        struct buffer_head *bh;
@@ -135,7 +135,7 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                /* Ignore the .reiserfs_priv entry */
                                if (reiserfs_xattrs(inode->i_sb) &&
                                    !old_format_only(inode->i_sb) &&
-                                   filp->f_dentry == inode->i_sb->s_root &&
+                                   filp->f_path.dentry == inode->i_sb->s_root &&
                                    REISERFS_SB(inode->i_sb)->priv_root &&
                                    REISERFS_SB(inode->i_sb)->priv_root->d_inode
                                    && deh_objectid(deh) ==
index ac14318..99b6f32 100644 (file)
@@ -317,12 +317,11 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
                        /* area filled with zeroes, to supply as list of zero blocknumbers
                           We allocate it outside of loop just in case loop would spin for
                           several iterations. */
-                       char *zeros = kmalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC);      // We cannot insert more than MAX_ITEM_LEN bytes anyway.
+                       char *zeros = kzalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC);      // We cannot insert more than MAX_ITEM_LEN bytes anyway.
                        if (!zeros) {
                                res = -ENOMEM;
                                goto error_exit_free_blocks;
                        }
-                       memset(zeros, 0, to_paste * UNFM_P_SIZE);
                        do {
                                to_paste =
                                    min_t(__u64, hole_size,
@@ -407,6 +406,8 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
                                   we restart it. This will also free the path. */
                                if (journal_transaction_should_end
                                    (th, th->t_blocks_allocated)) {
+                                       inode->i_size = cpu_key_k_offset(&key) +
+                                               (to_paste << inode->i_blkbits);
                                        res =
                                            restart_transaction(th, inode,
                                                                &path);
@@ -1045,6 +1046,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                        char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
                        memset(kaddr, 0, from);
                        kunmap_atomic(kaddr, KM_USER0);
+                       flush_dcache_page(prepared_pages[0]);
                }
                if (to != PAGE_CACHE_SIZE) {    /* Last page needs to be partially zeroed */
                        char *kaddr =
@@ -1052,6 +1054,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        KM_USER0);
                        memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
                        kunmap_atomic(kaddr, KM_USER0);
+                       flush_dcache_page(prepared_pages[num_pages - 1]);
                }
 
                /* Since all blocks are new - use already calculated value */
@@ -1185,6 +1188,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                        memset(kaddr + block_start, 0,
                                               from - block_start);
                                        kunmap_atomic(kaddr, KM_USER0);
+                                       flush_dcache_page(prepared_pages[0]);
                                        set_buffer_uptodate(bh);
                                }
                        }
@@ -1222,6 +1226,7 @@ static int reiserfs_prepare_file_region_for_write(struct inode *inode
                                                        KM_USER0);
                                        memset(kaddr + to, 0, block_end - to);
                                        kunmap_atomic(kaddr, KM_USER0);
+                                       flush_dcache_page(prepared_pages[num_pages - 1]);
                                        set_buffer_uptodate(bh);
                                }
                        }
@@ -1283,7 +1288,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
        loff_t pos;             // Current position in the file.
        ssize_t res;            // return value of various functions that we call.
        int err = 0;
-       struct inode *inode = file->f_dentry->d_inode;  // Inode of the file that we are writing to.
+       struct inode *inode = file->f_path.dentry->d_inode;     // Inode of the file that we are writing to.
        /* To simplify coding at this time, we store
           locked pages in array for now */
        struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
@@ -1307,56 +1312,8 @@ static ssize_t reiserfs_file_write(struct file *file,    /* the file we are going t
                        count = MAX_NON_LFS - (unsigned long)*ppos;
        }
 
-       if (file->f_flags & O_DIRECT) { // Direct IO needs treatment
-               ssize_t result, after_file_end = 0;
-               if ((*ppos + count >= inode->i_size)
-                   || (file->f_flags & O_APPEND)) {
-                       /* If we are appending a file, we need to put this savelink in here.
-                          If we will crash while doing direct io, finish_unfinished will
-                          cut the garbage from the file end. */
-                       reiserfs_write_lock(inode->i_sb);
-                       err =
-                           journal_begin(&th, inode->i_sb,
-                                         JOURNAL_PER_BALANCE_CNT);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       reiserfs_update_inode_transaction(inode);
-                       add_save_link(&th, inode, 1 /* Truncate */ );
-                       after_file_end = 1;
-                       err =
-                           journal_end(&th, inode->i_sb,
-                                       JOURNAL_PER_BALANCE_CNT);
-                       reiserfs_write_unlock(inode->i_sb);
-                       if (err)
-                               return err;
-               }
-               result = do_sync_write(file, buf, count, ppos);
-
-               if (after_file_end) {   /* Now update i_size and remove the savelink */
-                       struct reiserfs_transaction_handle th;
-                       reiserfs_write_lock(inode->i_sb);
-                       err = journal_begin(&th, inode->i_sb, 1);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       reiserfs_update_inode_transaction(inode);
-                       mark_inode_dirty(inode);
-                       err = journal_end(&th, inode->i_sb, 1);
-                       if (err) {
-                               reiserfs_write_unlock(inode->i_sb);
-                               return err;
-                       }
-                       err = remove_save_link(inode, 1 /* truncate */ );
-                       reiserfs_write_unlock(inode->i_sb);
-                       if (err)
-                               return err;
-               }
-
-               return result;
-       }
+       if (file->f_flags & O_DIRECT)
+               return do_sync_write(file, buf, count, ppos);
 
        if (unlikely((ssize_t) count < 0))
                return -EINVAL;
@@ -1378,7 +1335,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
        if (count == 0)
                goto out;
 
-       res = remove_suid(file->f_dentry);
+       res = remove_suid(file->f_path.dentry);
        if (res)
                goto out;
 
index 6d0e554..0ee35c6 100644 (file)
@@ -957,7 +957,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
 {
        struct buffer_head *p_s_parent;
        INITIALIZE_PATH(s_path_to_neighbor_father);
-       struct path *p_s_path = p_s_tb->tb_path;
+       struct treepath *p_s_path = p_s_tb->tb_path;
        struct cpu_key s_lr_father_key;
        int n_counter,
            n_position = INT_MAX,
@@ -1074,7 +1074,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
  */
 static int get_parents(struct tree_balance *p_s_tb, int n_h)
 {
-       struct path *p_s_path = p_s_tb->tb_path;
+       struct treepath *p_s_path = p_s_tb->tb_path;
        int n_position,
            n_ret_value,
            n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
@@ -1885,7 +1885,7 @@ static int check_balance(int mode,
 static int get_direct_parent(struct tree_balance *p_s_tb, int n_h)
 {
        struct buffer_head *p_s_bh;
-       struct path *p_s_path = p_s_tb->tb_path;
+       struct treepath *p_s_path = p_s_tb->tb_path;
        int n_position,
            n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
 
index 9c69bca..f3d1c4a 100644 (file)
@@ -207,7 +207,7 @@ static int file_capable(struct inode *inode, long block)
 }
 
 /*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
-                                  struct inode *inode, struct path *path)
+                                  struct inode *inode, struct treepath *path)
 {
        struct super_block *s = th->t_super;
        int len = th->t_blocks_allocated;
@@ -216,11 +216,12 @@ static int file_capable(struct inode *inode, long block)
        BUG_ON(!th->t_trans_id);
        BUG_ON(!th->t_refcount);
 
+       pathrelse(path);
+
        /* we cannot restart while nested */
        if (th->t_refcount > 1) {
                return 0;
        }
-       pathrelse(path);
        reiserfs_update_sd(th, inode);
        err = journal_end(th, s, len);
        if (!err) {
@@ -569,7 +570,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
                                  long block,
                                  struct inode *inode,
                                  b_blocknr_t * allocated_block_nr,
-                                 struct path *path, int flags)
+                                 struct treepath *path, int flags)
 {
        BUG_ON(!th->t_trans_id);
 
@@ -928,15 +929,12 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        if (blocks_needed == 1) {
                                un = &unf_single;
                        } else {
-                               un = kmalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC);      // We need to avoid scheduling.
+                               un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC);      // We need to avoid scheduling.
                                if (!un) {
                                        un = &unf_single;
                                        blocks_needed = 1;
                                        max_to_insert = 0;
-                               } else
-                                       memset(un, 0,
-                                              UNFM_P_SIZE * min(blocks_needed,
-                                                                max_to_insert));
+                               }
                        }
                        if (blocks_needed <= max_to_insert) {
                                /* we are going to add target block to the file. Use allocated
@@ -1109,7 +1107,7 @@ static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
 //
 
 // called by read_locked_inode
-static void init_inode(struct inode *inode, struct path *path)
+static void init_inode(struct inode *inode, struct treepath *path)
 {
        struct buffer_head *bh;
        struct item_head *ih;
@@ -1286,7 +1284,7 @@ static void inode2sd_v1(void *sd, struct inode *inode, loff_t size)
 /* NOTE, you must prepare the buffer head before sending it here,
 ** and then log it after the call
 */
-static void update_stat_data(struct path *path, struct inode *inode,
+static void update_stat_data(struct treepath *path, struct inode *inode,
                             loff_t size)
 {
        struct buffer_head *bh;
@@ -1655,7 +1653,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
    containing "." and ".." entries */
 static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
                                  struct inode *inode,
-                                 struct item_head *ih, struct path *path,
+                                 struct item_head *ih, struct treepath *path,
                                  struct inode *dir)
 {
        struct super_block *sb = th->t_super;
@@ -1714,7 +1712,7 @@ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
    containing the body of symlink */
 static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct inode *inode,   /* Inode of symlink */
                                struct item_head *ih,
-                               struct path *path, const char *symname,
+                               struct treepath *path, const char *symname,
                                int item_len)
 {
        struct super_block *sb = th->t_super;
index 9c57578..b484d29 100644 (file)
@@ -99,7 +99,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
                                unsigned long arg)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int ret;
 
        /* These are just misnamed, they actually get/put from/to user an int */
index ac93174..7280a23 100644 (file)
@@ -104,7 +104,7 @@ static int release_journal_dev(struct super_block *super,
                               struct reiserfs_journal *journal);
 static int dirty_one_transaction(struct super_block *s,
                                 struct reiserfs_journal_list *jl);
-static void flush_async_commits(void *p);
+static void flush_async_commits(struct work_struct *work);
 static void queue_log_writer(struct super_block *s);
 
 /* values for join in do_journal_begin_r */
@@ -2836,7 +2836,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
        if (reiserfs_mounted_fs_count <= 1)
                commit_wq = create_workqueue("reiserfs");
 
-       INIT_WORK(&journal->j_work, flush_async_commits, p_s_sb);
+       INIT_DELAYED_WORK(&journal->j_work, flush_async_commits);
+       journal->j_work_sb = p_s_sb;
        return 0;
       free_and_return:
        free_journal_ram(p_s_sb);
@@ -3447,10 +3448,11 @@ int journal_end_sync(struct reiserfs_transaction_handle *th,
 /*
 ** writeback the pending async commits to disk
 */
-static void flush_async_commits(void *p)
+static void flush_async_commits(struct work_struct *work)
 {
-       struct super_block *p_s_sb = p;
-       struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+       struct reiserfs_journal *journal =
+               container_of(work, struct reiserfs_journal, j_work.work);
+       struct super_block *p_s_sb = journal->j_work_sb;
        struct reiserfs_journal_list *jl;
        struct list_head *entry;
 
index abde1ed..23f5cd5 100644 (file)
@@ -54,7 +54,7 @@ static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off)
 
 // comment?  maybe something like set de to point to what the path points to?
 static inline void set_de_item_location(struct reiserfs_dir_entry *de,
-                                       struct path *path)
+                                       struct treepath *path)
 {
        de->de_bh = get_last_bh(path);
        de->de_ih = get_ih(path);
@@ -113,7 +113,7 @@ entry position in the item
 
 /* The function is NOT SCHEDULE-SAFE! */
 int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
-                       struct path *path, struct reiserfs_dir_entry *de)
+                       struct treepath *path, struct reiserfs_dir_entry *de)
 {
        int retval;
 
@@ -282,7 +282,7 @@ static int linear_search_in_dir_item(struct cpu_key *key,
 // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
 // FIXME: should add something like IOERROR
 static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
-                              struct path *path_to_entry,
+                              struct treepath *path_to_entry,
                               struct reiserfs_dir_entry *de)
 {
        struct cpu_key key_to_search;
index c533ec1..ecc9943 100644 (file)
@@ -295,7 +295,7 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
        }
 #if defined( REISERFS_USE_OIDMAPF )
        if (sb_info->oidmap.use_file && (sb_info->oidmap.mapf != NULL)) {
-               loff_t size = sb_info->oidmap.mapf->f_dentry->d_inode->i_size;
+               loff_t size = sb_info->oidmap.mapf->f_path.dentry->d_inode->i_size;
                total_used += size / sizeof(reiserfs_oidinterval_d_t);
        }
 #endif
index 5240abe..47e7027 100644 (file)
@@ -244,7 +244,7 @@ static const struct reiserfs_key MAX_KEY = {
    of the path, and going upwards.  We must check the path's validity at each step.  If the key is not in
    the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
    case we return a special key, either MIN_KEY or MAX_KEY. */
-static inline const struct reiserfs_key *get_lkey(const struct path
+static inline const struct reiserfs_key *get_lkey(const struct treepath
                                                  *p_s_chk_path,
                                                  const struct super_block
                                                  *p_s_sb)
@@ -290,7 +290,7 @@ static inline const struct reiserfs_key *get_lkey(const struct path
 }
 
 /* Get delimiting key of the buffer at the path and its right neighbor. */
-inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
+inline const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
                                           const struct super_block *p_s_sb)
 {
        int n_position, n_path_offset = p_s_chk_path->path_length;
@@ -337,7 +337,7 @@ inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
    the path.  These delimiting keys are stored at least one level above that buffer in the tree. If the
    buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
    this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
-static inline int key_in_buffer(struct path *p_s_chk_path,     /* Path which should be checked.  */
+static inline int key_in_buffer(struct treepath *p_s_chk_path, /* Path which should be checked.  */
                                const struct cpu_key *p_s_key,  /* Key which should be checked.   */
                                struct super_block *p_s_sb      /* Super block pointer.           */
     )
@@ -374,7 +374,7 @@ inline void decrement_bcount(struct buffer_head *p_s_bh)
 }
 
 /* Decrement b_count field of the all buffers in the path. */
-void decrement_counters_in_path(struct path *p_s_search_path)
+void decrement_counters_in_path(struct treepath *p_s_search_path)
 {
        int n_path_offset = p_s_search_path->path_length;
 
@@ -391,7 +391,7 @@ void decrement_counters_in_path(struct path *p_s_search_path)
        p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
 }
 
-int reiserfs_check_path(struct path *p)
+int reiserfs_check_path(struct treepath *p)
 {
        RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
               "path not properly relsed");
@@ -403,7 +403,7 @@ int reiserfs_check_path(struct path *p)
 **
 ** only called from fix_nodes()
 */
-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
+void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path)
 {
        int n_path_offset = p_s_search_path->path_length;
 
@@ -421,7 +421,7 @@ void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
 }
 
 /* Release all buffers in the path. */
-void pathrelse(struct path *p_s_search_path)
+void pathrelse(struct treepath *p_s_search_path)
 {
        int n_path_offset = p_s_search_path->path_length;
 
@@ -602,7 +602,7 @@ static void search_by_key_reada(struct super_block *s,
    correctness of the bottom of the path */
 /* The function is NOT SCHEDULE-SAFE! */
 int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key,   /* Key to search. */
-                 struct path *p_s_search_path, /* This structure was
+                 struct treepath *p_s_search_path,/* This structure was
                                                   allocated and initialized
                                                   by the calling
                                                   function. It is filled up
@@ -813,7 +813,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key,        /*
 /* The function is NOT SCHEDULE-SAFE! */
 int search_for_position_by_key(struct super_block *p_s_sb,     /* Pointer to the super block.          */
                               const struct cpu_key *p_cpu_key, /* Key to search (cpu variable)         */
-                              struct path *p_s_search_path     /* Filled up by this function.          */
+                              struct treepath *p_s_search_path /* Filled up by this function.          */
     )
 {
        struct item_head *p_le_ih;      /* pointer to on-disk structure */
@@ -884,7 +884,7 @@ int search_for_position_by_key(struct super_block *p_s_sb,  /* Pointer to the sup
 }
 
 /* Compare given item and item pointed to by the path. */
-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
+int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path)
 {
        struct buffer_head *p_s_bh;
        struct item_head *ih;
@@ -911,7 +911,7 @@ int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
 #define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh)))
 
 // prepare for delete or cut of direct item
-static inline int prepare_for_direct_item(struct path *path,
+static inline int prepare_for_direct_item(struct treepath *path,
                                          struct item_head *le_ih,
                                          struct inode *inode,
                                          loff_t new_file_length, int *cut_size)
@@ -952,7 +952,7 @@ static inline int prepare_for_direct_item(struct path *path,
        return M_CUT;           /* Cut from this item. */
 }
 
-static inline int prepare_for_direntry_item(struct path *path,
+static inline int prepare_for_direntry_item(struct treepath *path,
                                            struct item_head *le_ih,
                                            struct inode *inode,
                                            loff_t new_file_length,
@@ -987,7 +987,7 @@ static inline int prepare_for_direntry_item(struct path *path,
     In case of file truncate calculate whether this item must be deleted/truncated or last
     unformatted node of this item will be converted to a direct item.
     This function returns a determination of what balance mode the calling function should employ. */
-static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct path *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed,        /* Number of unformatted nodes which were removed
+static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed,    /* Number of unformatted nodes which were removed
                                                                                                                                                                                   from end of the file. */
                                      int *p_n_cut_size, unsigned long long n_new_file_length   /* MAX_KEY_OFFSET in case of delete. */
     )
@@ -1125,7 +1125,7 @@ static int calc_deleted_bytes_number(struct tree_balance *p_s_tb, char c_mode)
 static void init_tb_struct(struct reiserfs_transaction_handle *th,
                           struct tree_balance *p_s_tb,
                           struct super_block *p_s_sb,
-                          struct path *p_s_path, int n_size)
+                          struct treepath *p_s_path, int n_size)
 {
 
        BUG_ON(!th->t_trans_id);
@@ -1176,7 +1176,7 @@ char head2type(struct item_head *ih)
 #endif
 
 /* Delete object item. */
-int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct path *p_s_path,        /* Path to the deleted item. */
+int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,    /* Path to the deleted item. */
                         const struct cpu_key *p_s_item_key,    /* Key to search for the deleted item.  */
                         struct inode *p_s_inode,       /* inode is here just to update i_blocks and quotas */
                         struct buffer_head *p_s_un_bh)
@@ -1468,7 +1468,7 @@ static void unmap_buffers(struct page *page, loff_t pos)
 static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
                                    struct inode *p_s_inode,
                                    struct page *page,
-                                   struct path *p_s_path,
+                                   struct treepath *p_s_path,
                                    const struct cpu_key *p_s_item_key,
                                    loff_t n_new_file_size, char *p_c_mode)
 {
@@ -1503,7 +1503,7 @@ static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
    pointer being converted. Therefore we have to delete inserted
    direct item(s) */
 static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
-                                        struct inode *inode, struct path *path)
+                                        struct inode *inode, struct treepath *path)
 {
        struct cpu_key tail_key;
        int tail_len;
@@ -1545,7 +1545,7 @@ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
 
 /* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
 int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
-                          struct path *p_s_path,
+                          struct treepath *p_s_path,
                           struct cpu_key *p_s_item_key,
                           struct inode *p_s_inode,
                           struct page *page, loff_t n_new_file_size)
@@ -1920,7 +1920,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p
 
 #ifdef CONFIG_REISERFS_CHECK
 // this makes sure, that we __append__, not overwrite or add holes
-static void check_research_for_paste(struct path *path,
+static void check_research_for_paste(struct treepath *path,
                                     const struct cpu_key *p_s_key)
 {
        struct item_head *found_ih = get_ih(path);
@@ -1954,7 +1954,7 @@ static void check_research_for_paste(struct path *path,
 #endif                         /* config reiserfs check */
 
 /* Paste bytes to the existing item. Returns bytes number pasted into the item. */
-int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path *p_s_search_path,     /* Path to the pasted item.          */
+int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path, /* Path to the pasted item.          */
                             const struct cpu_key *p_s_key,     /* Key to search for the needed item. */
                             struct inode *inode,       /* Inode item belongs to */
                             const char *p_c_body,      /* Pointer to the bytes to paste.    */
@@ -2036,7 +2036,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path
 }
 
 /* Insert new item into the buffer at the path. */
-int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct path *p_s_path,        /* Path to the inserteded item.         */
+int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,    /* Path to the inserteded item.         */
                         const struct cpu_key *key, struct item_head *p_s_ih,   /* Pointer to the item header to insert. */
                         struct inode *inode, const char *p_c_body)
 {                              /* Pointer to the bytes to insert.      */
index 1724999..58ad455 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
@@ -490,13 +490,13 @@ static void reiserfs_put_super(struct super_block *s)
        return;
 }
 
-static kmem_cache_t *reiserfs_inode_cachep;
+static struct kmem_cache *reiserfs_inode_cachep;
 
 static struct inode *reiserfs_alloc_inode(struct super_block *sb)
 {
        struct reiserfs_inode_info *ei;
        ei = (struct reiserfs_inode_info *)
-           kmem_cache_alloc(reiserfs_inode_cachep, SLAB_KERNEL);
+           kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -507,7 +507,7 @@ static void reiserfs_destroy_inode(struct inode *inode)
        kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
 }
 
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
 
@@ -1549,13 +1549,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        struct reiserfs_sb_info *sbi;
        int errval = -EINVAL;
 
-       sbi = kmalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
        if (!sbi) {
                errval = -ENOMEM;
                goto error;
        }
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct reiserfs_sb_info));
        /* Set default values for options: non-aggressive tails, RO on errors */
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO);
index 36f108f..f8121a1 100644 (file)
@@ -15,7 +15,7 @@
 /* path points to first direct item of the file regarless of how many of
    them are there */
 int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
-                   struct path *path, struct buffer_head *unbh,
+                   struct treepath *path, struct buffer_head *unbh,
                    loff_t tail_offset)
 {
        struct super_block *sb = inode->i_sb;
@@ -171,7 +171,7 @@ void reiserfs_unmap_buffer(struct buffer_head *bh)
    what we expect from it (number of cut bytes). But when tail remains
    in the unformatted node, we set mode to SKIP_BALANCING and unlock
    inode */
-int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct path *p_s_path, /* path to the indirect item. */
+int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *p_s_path,     /* path to the indirect item. */
                    const struct cpu_key *p_s_item_key, /* Key to look for unformatted node pointer to be cut. */
                    loff_t n_new_file_size,     /* New file size. */
                    char *p_c_mode)
index 1e4d685..f01389f 100644 (file)
@@ -274,7 +274,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name,
  */
 static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
        INITIALIZE_PATH(path_to_entry);
        struct buffer_head *bh;
@@ -420,7 +420,7 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
 static
 int xattr_readdir(struct file *file, filldir_t filler, void *buf)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int res = -ENOTDIR;
        if (!file->f_op || !file->f_op->readdir)
                goto out;
@@ -508,7 +508,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
                goto out;
        }
 
-       xinode = fp->f_dentry->d_inode;
+       xinode = fp->f_path.dentry->d_inode;
        REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
 
        /* we need to copy it off.. */
@@ -527,7 +527,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
        newattrs.ia_size = buffer_size;
        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
        mutex_lock(&xinode->i_mutex);
-       err = notify_change(fp->f_dentry, &newattrs);
+       err = notify_change(fp->f_path.dentry, &newattrs);
        if (err)
                goto out_filp;
 
@@ -626,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
                goto out;
        }
 
-       xinode = fp->f_dentry->d_inode;
+       xinode = fp->f_path.dentry->d_inode;
        isize = xinode->i_size;
        REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
 
index ddcd9e1..d3e243a 100644 (file)
@@ -276,7 +276,7 @@ static unsigned char romfs_dtype_table[] = {
 static int
 romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *i = filp->f_dentry->d_inode;
+       struct inode *i = filp->f_path.dentry->d_inode;
        struct romfs_inode ri;
        unsigned long offset, maxoff;
        int j, ino, nextfh;
@@ -550,12 +550,12 @@ romfs_read_inode(struct inode *i)
        }
 }
 
-static kmem_cache_t * romfs_inode_cachep;
+static struct kmem_cache * romfs_inode_cachep;
 
 static struct inode *romfs_alloc_inode(struct super_block *sb)
 {
        struct romfs_inode_info *ei;
-       ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, SLAB_KERNEL);
+       ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -566,7 +566,7 @@ static void romfs_destroy_inode(struct inode *inode)
        kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct romfs_inode_info *ei = (struct romfs_inode_info *) foo;
 
index dcbc111..fe0893a 100644 (file)
@@ -311,7 +311,7 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
 {
        fd_set_bits fds;
        void *bits;
-       int ret, max_fdset;
+       int ret, max_fds;
        unsigned int size;
        struct fdtable *fdt;
        /* Allocate small arguments on the stack to save memory and be faster */
@@ -321,13 +321,13 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
        if (n < 0)
                goto out_nofds;
 
-       /* max_fdset can increase, so grab it once to avoid race */
+       /* max_fds can increase, so grab it once to avoid race */
        rcu_read_lock();
        fdt = files_fdtable(current->files);
-       max_fdset = fdt->max_fdset;
+       max_fds = fdt->max_fds;
        rcu_read_unlock();
-       if (n > max_fdset)
-               n = max_fdset;
+       if (n > max_fds)
+               n = max_fds;
 
        /*
         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
index 555b9ac..0ac22af 100644 (file)
@@ -26,7 +26,7 @@
  *     ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
  *     returns 0 in case of success and negative number in case of error.
  */
-int seq_open(struct file *file, struct seq_operations *op)
+int seq_open(struct file *file, const struct seq_operations *op)
 {
        struct seq_file *p = file->private_data;
 
@@ -269,7 +269,7 @@ EXPORT_SYMBOL(seq_lseek);
 /**
  *     seq_release -   free the structures associated with sequential file.
  *     @file: file in question
- *     @inode: file->f_dentry->d_inode
+ *     @inode: file->f_path.dentry->d_inode
  *
  *     Frees the structures associated with sequential file; can be used
  *     as ->f_op->release() if you don't have private data to destroy.
@@ -408,7 +408,7 @@ EXPORT_SYMBOL(single_open);
 
 int single_release(struct inode *inode, struct file *file)
 {
-       struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
+       const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
        int res = seq_release(inode, file);
        kfree(op);
        return res;
index 74b86d9..8182f05 100644 (file)
@@ -125,7 +125,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
               struct smb_cache_control *ctrl, struct qstr *qname,
               struct smb_fattr *entry)
 {
-       struct dentry *newdent, *dentry = filp->f_dentry;
+       struct dentry *newdent, *dentry = filp->f_path.dentry;
        struct inode *newino, *inode = dentry->d_inode;
        struct smb_cache_control ctl = *ctrl;
        int valid = 0;
index 70d9c5a..b1e58d1 100644 (file)
@@ -78,7 +78,7 @@ struct inode_operations smb_dir_inode_operations_unix =
 static int 
 smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *dir = dentry->d_inode;
        struct smb_sb_info *server = server_from_dentry(dentry);
        union  smb_dir_cache *cache = NULL;
@@ -238,12 +238,12 @@ out:
 static int
 smb_dir_open(struct inode *dir, struct file *file)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct smb_sb_info *server;
        int error = 0;
 
        VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
-               file->f_dentry->d_name.name);
+               file->f_path.dentry->d_name.name);
 
        /*
         * Directory timestamps in the core protocol aren't updated
index 50784d1..e50533a 100644 (file)
@@ -102,7 +102,7 @@ static int
 smb_readpage(struct file *file, struct page *page)
 {
        int             error;
-       struct dentry  *dentry = file->f_dentry;
+       struct dentry  *dentry = file->f_path.dentry;
 
        page_cache_get(page);
        error = smb_readpage_sync(dentry, page);
@@ -205,7 +205,7 @@ static int
 smb_updatepage(struct file *file, struct page *page, unsigned long offset,
               unsigned int count)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
 
        DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
                ((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
@@ -218,7 +218,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        unsigned long nr_segs, loff_t pos)
 {
        struct file * file = iocb->ki_filp;
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        ssize_t status;
 
        VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
@@ -243,7 +243,7 @@ out:
 static int
 smb_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        int     status;
 
        VERBOSE("file %s/%s, address %lu - %lu\n",
@@ -264,7 +264,7 @@ static ssize_t
 smb_file_sendfile(struct file *file, loff_t *ppos,
                  size_t count, read_actor_t actor, void *target)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        ssize_t status;
 
        VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
@@ -323,7 +323,7 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                               unsigned long nr_segs, loff_t pos)
 {
        struct file * file = iocb->ki_filp;
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        ssize_t result;
 
        VERBOSE("file %s/%s, count=%lu@%lu\n",
@@ -355,7 +355,7 @@ static int
 smb_file_open(struct inode *inode, struct file * file)
 {
        int result;
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        int smb_mode = (file->f_mode & O_ACCMODE) - 1;
 
        lock_kernel();
index 2c122ee..4af4cd7 100644 (file)
@@ -50,12 +50,12 @@ static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct dentry *, struct kstatfs *);
 static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
-static kmem_cache_t *smb_inode_cachep;
+static struct kmem_cache *smb_inode_cachep;
 
 static struct inode *smb_alloc_inode(struct super_block *sb)
 {
        struct smb_inode_info *ei;
-       ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, SLAB_KERNEL);
+       ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -66,7 +66,7 @@ static void smb_destroy_inode(struct inode *inode)
        kmem_cache_free(smb_inode_cachep, SMB_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct smb_inode_info *ei = (struct smb_inode_info *) foo;
        unsigned long flagmask = SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR;
index 40e174d..a5ced9e 100644 (file)
@@ -873,7 +873,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
        filp = fget(opt->fd);
        if (!filp)
                goto out;
-       if (!smb_valid_socket(filp->f_dentry->d_inode))
+       if (!smb_valid_socket(filp->f_path.dentry->d_inode))
                goto out_putf;
 
        server->sock_file = filp;
@@ -898,7 +898,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
        /*
         * Store the server in sock user_data (Only used by sunrpc)
         */
-       sk = SOCKET_I(filp->f_dentry->d_inode)->sk;
+       sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;
        sk->sk_user_data = server;
 
        /* chain into the data_ready callback */
@@ -1939,7 +1939,7 @@ static int
 smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
                       struct smb_cache_control *ctl)
 {
-       struct dentry *dir = filp->f_dentry;
+       struct dentry *dir = filp->f_path.dentry;
        struct smb_sb_info *server = server_from_dentry(dir);
        struct qstr qname;
        struct smb_fattr fattr;
@@ -2291,7 +2291,7 @@ static int
 smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
                      struct smb_cache_control *ctl)
 {
-       struct dentry *dir = filp->f_dentry;
+       struct dentry *dir = filp->f_path.dentry;
        struct smb_sb_info *server = server_from_dentry(dir);
        struct qstr qname;
        struct smb_fattr fattr;
@@ -2859,7 +2859,7 @@ static int
 smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
                      struct smb_cache_control *ctl)
 {
-       struct smb_sb_info *server = server_from_dentry(filp->f_dentry);
+       struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry);
 
        if (smb_proc_ops_wait(server) < 0)
                return -EIO;
index 0fb7469..a4bcae8 100644 (file)
@@ -25,7 +25,7 @@
 #define ROUND_UP(x) (((x)+3) & ~3)
 
 /* cache for request structures */
-static kmem_cache_t *req_cachep;
+static struct kmem_cache *req_cachep;
 
 static int smb_request_send_req(struct smb_request *req);
 
@@ -61,7 +61,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
        struct smb_request *req;
        unsigned char *buf = NULL;
 
-       req = kmem_cache_alloc(req_cachep, SLAB_KERNEL);
+       req = kmem_cache_alloc(req_cachep, GFP_KERNEL);
        VERBOSE("allocating request: %p\n", req);
        if (!req)
                goto out;
index 6815b1b..92ea6b2 100644 (file)
@@ -82,10 +82,10 @@ server_sock(struct smb_sb_info *server)
        if (server && (file = server->sock_file))
        {
 #ifdef SMBFS_PARANOIA
-               if (!smb_valid_socket(file->f_dentry->d_inode))
+               if (!smb_valid_socket(file->f_path.dentry->d_inode))
                        PARANOIA("bad socket!\n");
 #endif
-               return SOCKET_I(file->f_dentry->d_inode);
+               return SOCKET_I(file->f_path.dentry->d_inode);
        }
        return NULL;
 }
index da74583..bbd0aeb 100644 (file)
@@ -844,7 +844,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
        ssize_t ret;
        int err;
 
-       err = remove_suid(out->f_dentry);
+       err = remove_suid(out->f_path.dentry);
        if (unlikely(err))
                return err;
 
@@ -890,10 +890,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
        ssize_t ret;
        int err;
 
-       err = should_remove_suid(out->f_dentry);
+       err = should_remove_suid(out->f_path.dentry);
        if (unlikely(err)) {
                mutex_lock(&inode->i_mutex);
-               err = __remove_suid(out->f_dentry, err);
+               err = __remove_suid(out->f_path.dentry, err);
                mutex_unlock(&inode->i_mutex);
                if (err)
                        return err;
@@ -1008,7 +1008,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
         * randomly drop data for eg socket -> socket splicing. Use the
         * piped splicing for that!
         */
-       i_mode = in->f_dentry->d_inode->i_mode;
+       i_mode = in->f_path.dentry->d_inode->i_mode;
        if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
                return -EINVAL;
 
@@ -1132,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
        loff_t offset, *off;
        long ret;
 
-       pipe = pipe_info(in->f_dentry->d_inode);
+       pipe = pipe_info(in->f_path.dentry->d_inode);
        if (pipe) {
                if (off_in)
                        return -ESPIPE;
@@ -1153,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
                return ret;
        }
 
-       pipe = pipe_info(out->f_dentry->d_inode);
+       pipe = pipe_info(out->f_path.dentry->d_inode);
        if (pipe) {
                if (off_out)
                        return -ESPIPE;
@@ -1321,7 +1321,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
                .ops = &user_page_pipe_buf_ops,
        };
 
-       pipe = pipe_info(file->f_dentry->d_inode);
+       pipe = pipe_info(file->f_path.dentry->d_inode);
        if (!pipe)
                return -EBADF;
        if (unlikely(nr_segs > UIO_MAXIOV))
@@ -1549,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
 static long do_tee(struct file *in, struct file *out, size_t len,
                   unsigned int flags)
 {
-       struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
-       struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
+       struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode);
+       struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode);
        int ret = -EINVAL;
 
        /*
diff --git a/fs/stack.c b/fs/stack.c
new file mode 100644 (file)
index 0000000..5ddbc34
--- /dev/null
@@ -0,0 +1,40 @@
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/fs_stack.h>
+
+/* does _NOT_ require i_mutex to be held.
+ *
+ * This function cannot be inlined since i_size_{read,write} is rather
+ * heavy-weight on 32-bit systems
+ */
+void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+{
+       i_size_write(dst, i_size_read((struct inode *)src));
+       dst->i_blocks = src->i_blocks;
+}
+EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+
+/* copy all attributes; get_nlinks is optional way to override the i_nlink
+ * copying
+ */
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+                               int (*get_nlinks)(struct inode *))
+{
+       if (!get_nlinks)
+               dest->i_nlink = src->i_nlink;
+       else
+               dest->i_nlink = (*get_nlinks)(dest);
+
+       dest->i_mode = src->i_mode;
+       dest->i_uid = src->i_uid;
+       dest->i_gid = src->i_gid;
+       dest->i_rdev = src->i_rdev;
+       dest->i_atime = src->i_atime;
+       dest->i_mtime = src->i_mtime;
+       dest->i_ctime = src->i_ctime;
+       dest->i_blkbits = src->i_blkbits;
+       dest->i_flags = src->i_flags;
+
+       fsstack_copy_inode_size(dest, src);
+}
+EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
index bca07eb..38a8cb2 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -51,13 +51,6 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
                return inode->i_op->getattr(mnt, dentry, stat);
 
        generic_fillattr(inode, stat);
-       if (!stat->blksize) {
-               struct super_block *s = inode->i_sb;
-               unsigned blocks;
-               blocks = (stat->size+s->s_blocksize-1) >> s->s_blocksize_bits;
-               stat->blocks = (s->s_blocksize / 512) * blocks;
-               stat->blksize = s->s_blocksize;
-       }
        return 0;
 }
 
@@ -109,7 +102,7 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
        int error = -EBADF;
 
        if (f) {
-               error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
+               error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
                fput(f);
        }
        return error;
index 84c320f..f961e03 100644 (file)
@@ -570,7 +570,7 @@ static void mark_files_ro(struct super_block *sb)
 
        file_list_lock();
        list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
-               if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
+               if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
                        f->f_mode &= ~FMODE_WRITE;
        }
        file_list_unlock();
index 865f32b..d0feff6 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -94,7 +94,7 @@ long do_fsync(struct file *file, int datasync)
         * livelocks in fsync_buffers_list().
         */
        mutex_lock(&mapping->host->i_mutex);
-       err = file->f_op->fsync(file, file->f_dentry, datasync);
+       err = file->f_op->fsync(file, file->f_path.dentry, datasync);
        if (!ret)
                ret = err;
        mutex_unlock(&mapping->host->i_mutex);
@@ -223,7 +223,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
        if (!file)
                goto out;
 
-       i_mode = file->f_dentry->d_inode->i_mode;
+       i_mode = file->f_path.dentry->d_inode->i_mode;
        ret = -ESPIPE;
        if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
                        !S_ISLNK(i_mode))
index 98022e4..e8f540d 100644 (file)
@@ -35,7 +35,7 @@ static ssize_t
 read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
 {
        char *buffer = file->private_data;
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
        int ret;
@@ -81,7 +81,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
                     size_t count, loff_t * off)
 {
        char *buffer = file->private_data;
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
 
@@ -105,7 +105,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
 
 static int mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct bin_attribute *attr = to_bin_attr(dentry);
        struct kobject *kobj = to_kobj(dentry->d_parent);
 
@@ -117,8 +117,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
 
 static int open(struct inode * inode, struct file * file)
 {
-       struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
-       struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+       struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+       struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
        int error = -EINVAL;
 
        if (!kobj || !attr)
@@ -153,8 +153,8 @@ static int open(struct inode * inode, struct file * file)
 
 static int release(struct inode * inode, struct file * file)
 {
-       struct kobject * kobj = to_kobj(file->f_dentry->d_parent);
-       struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+       struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
+       struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
        u8 * buffer = file->private_data;
 
        if (kobj) 
index a5782e8..511edef 100644 (file)
@@ -419,7 +419,7 @@ out:
 
 static int sysfs_dir_open(struct inode *inode, struct file *file)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
 
        mutex_lock(&dentry->d_inode->i_mutex);
@@ -432,7 +432,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
 
 static int sysfs_dir_close(struct inode *inode, struct file *file)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
        struct sysfs_dirent * cursor = file->private_data;
 
        mutex_lock(&dentry->d_inode->i_mutex);
@@ -452,7 +452,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
 
 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
        struct sysfs_dirent *cursor = filp->private_data;
        struct list_head *p, *q = &cursor->s_sibling;
@@ -509,7 +509,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 
 static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
 {
-       struct dentry * dentry = file->f_dentry;
+       struct dentry * dentry = file->f_path.dentry;
 
        mutex_lock(&dentry->d_inode->i_mutex);
        switch (origin) {
@@ -519,7 +519,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+                       mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
index 95c1651..9cfe53e 100644 (file)
@@ -154,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
        down(&buffer->sem);
        if (buffer->needs_read_fill) {
-               if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+               if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
                        goto out;
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -245,7 +245,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
        down(&buffer->sem);
        len = fill_write_buffer(buffer, buf, count);
        if (len > 0)
-               len = flush_write_buffer(file->f_dentry, buffer, len);
+               len = flush_write_buffer(file->f_path.dentry, buffer, len);
        if (len > 0)
                *ppos += len;
        up(&buffer->sem);
@@ -254,8 +254,8 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
 
 static int check_perm(struct inode * inode, struct file * file)
 {
-       struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
-       struct attribute * attr = to_attr(file->f_dentry);
+       struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+       struct attribute * attr = to_attr(file->f_path.dentry);
        struct sysfs_buffer * buffer;
        struct sysfs_ops * ops = NULL;
        int error = 0;
@@ -337,8 +337,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
 
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
-       struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
-       struct attribute * attr = to_attr(filp->f_dentry);
+       struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+       struct attribute * attr = to_attr(filp->f_path.dentry);
        struct module * owner = attr->owner;
        struct sysfs_buffer * buffer = filp->private_data;
 
@@ -372,8 +372,8 @@ static int sysfs_release(struct inode * inode, struct file * filp)
 static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 {
        struct sysfs_buffer * buffer = filp->private_data;
-       struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
-       struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+       struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+       struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
        int res = 0;
 
        poll_wait(filp, &kobj->poll, wait);
index 20551a1..e503f85 100644 (file)
@@ -16,7 +16,7 @@
 
 struct vfsmount *sysfs_mount;
 struct super_block * sysfs_sb = NULL;
-kmem_cache_t *sysfs_dir_cachep;
+struct kmem_cache *sysfs_dir_cachep;
 
 static struct super_operations sysfs_ops = {
        .statfs         = simple_statfs,
index 6f3d6bd..bd7cec2 100644 (file)
@@ -1,6 +1,6 @@
 
 extern struct vfsmount * sysfs_mount;
-extern kmem_cache_t *sysfs_dir_cachep;
+extern struct kmem_cache *sysfs_dir_cachep;
 
 extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
 extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
diff --git a/fs/sysv/CHANGES b/fs/sysv/CHANGES
deleted file mode 100644 (file)
index 66ea6e9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-Mon, 15 Dec 1997         Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
-       *    namei.c: struct sysv_dir_inode_operations updated to use dentries.
-
-Fri, 23 Jan 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
-       *    inode.c: corrected 1 track offset setting (in sb->sv_block_base).
-                     Originally it was overridden (by setting to zero)
-                     in detected_[xenix,sysv4,sysv2,coherent]. Thanks
-                     to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
-                     for identifying the problem.
-
-Tue, 27 Jan 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
-        *    inode.c: added 2048-byte block support to SystemV FS.
-                     Merged detected_bs[512,1024,2048]() into one function:
-                     void detected_bs (u_char type, struct super_block *sb).
-                     Thanks to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
-                     for the patch.
-
-Wed, 4 Feb 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
-       *    namei.c: removed static subdir(); is_subdir() from dcache.c
-                     is used instead. Cosmetic changes.
-
-Thu, 3 Dec 1998   Al Viro (viro@parcelfarce.linux.theplanet.co.uk)
-       *    namei.c (sysv_rmdir):
-                     Bugectomy: old check for victim being busy
-                     (inode->i_count) wasn't replaced (with checking
-                     dentry->d_count) and escaped Linus in the last round
-                     of changes. Shot and buried.
-
-Wed, 9 Dec 1998   AV
-       *    namei.c (do_sysv_rename):
-                      Fixed incorrect check for other owners + race.
-                      Removed checks that went to VFS.
-       *    namei.c (sysv_unlink):
-                      Removed checks that went to VFS.
-
-Thu, 10 Dec 1998   AV
-       *    namei.c (do_mknod):
-                       Removed dead code - mknod is never asked to
-                       create a symlink or directory. Incidentially,
-                       it wouldn't do it right if it would be called.
-
-Sat, 26 Dec 1998   KGB
-       *    inode.c (detect_sysv4):
-                       Added detection of expanded s_type field (0x10,
-                       0x20 and 0x30).  Forced read-only access in this case.
-
-Sun, 21 Mar 1999   AV
-       *    namei.c (sysv_link):
-                       Fixed i_count usage that resulted in dcache corruption.
-       *    inode.c:
-                       Filled ->delete_inode() method with sysv_delete_inode().
-                       sysv_put_inode() is gone, as it tried to do ->delete_
-                       _inode()'s job.
-       *    ialloc.c: (sysv_free_inode):
-                       Fixed race.
-
-Sun, 30 Apr 1999   AV
-       *    namei.c (sysv_mknod):
-                       Removed dead code (S_IFREG case is now passed to
-                       ->create() by VFS).
diff --git a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
deleted file mode 100644 (file)
index f403f8b..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-Thu Feb 14 2002  Andrew Morton  <akpm@zip.com.au>
-
-       * dir_commit_chunk(): call writeout_one_page() as well as
-         waitfor_one_page() for IS_SYNC directories, so that we
-         actually do sync the directory. (forward-port from 2.4).
-
-Thu Feb  7 2002  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-
-       * super.c: switched to ->get_sb()
-       * ChangeLog: fixed dates ;-)
-
-2002-01-24  David S. Miller  <davem@redhat.com>
-
-       * inode.c: Include linux/init.h
-
-Mon Jan 21 2002  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-       * ialloc.c (sysv_new_inode): zero SYSV_I(inode)->i_data out.
-       * i_vnode renamed to vfs_inode.  Sorry, but let's keep that
-         consistent.
-
-Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
-
-       * include/linux/sysv_fs.h (SYSV_I): Get fs-private inode data using
-               list_entry() instead of inode->u.
-       * include/linux/sysv_fs_i.h: Add 'struct inode  i_vnode' field to
-               sysv_inode_info structure.
-       * inode.c: Include <linux/slab.h>, implement alloc_inode/destroy_inode
-               sop methods, add infrastructure for per-fs inode slab cache.
-       * super.c (init_sysv_fs): Initialize inode cache, recover properly
-               in the case of failed register_filesystem for V7.
-       (exit_sysv_fs): Destroy inode cache.
-
-Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
-
-       * include/linux/sysv_fs.h: Include <linux/sysv_fs_i.h>, declare SYSV_I().
-       * dir.c (sysv_find_entry): Use SYSV_I() instead of ->u.sysv_i to
-               access fs-private inode data.
-       * ialloc.c (sysv_new_inode): Likewise.
-       * inode.c (sysv_read_inode): Likewise.
-       (sysv_update_inode): Likewise.
-       * itree.c (get_branch): Likewise.
-       (sysv_truncate): Likewise.
-       * symlink.c (sysv_readlink): Likewise.
-       (sysv_follow_link): Likewise.
-
-Fri Jan  4 2002  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-
-       * ialloc.c (sysv_free_inode): Use sb->s_id instead of bdevname().
-       * inode.c (sysv_read_inode): Likewise.
-         (sysv_update_inode): Likewise.
-         (sysv_sync_inode): Likewise.
-       * super.c (detect_sysv): Likewise.
-         (complete_read_super): Likewise.
-         (sysv_read_super): Likewise.
-         (v7_read_super): Likewise.
-
-Sun Dec 30 2001  Manfred Spraul  <manfred@colorfullife.com>
-
-       * dir.c (dir_commit_chunk): Do not set dir->i_version.
-       (sysv_readdir): Likewise.
-
-Thu Dec 27 2001  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-
-       * itree.c (get_block): Use map_bh() to fill out bh_result.
-
-Tue Dec 25 2001  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-
-       * super.c (sysv_read_super): Use sb_set_blocksize() to set blocksize.
-         (v7_read_super): Likewise.
-
-Tue Nov 27 2001  Alexander Viro  <viro@parcelfarce.linux.theplanet.co.uk>
-
-       * itree.c (get_block): Change type for iblock argument to sector_t.
-       * super.c (sysv_read_super): Set s_blocksize early.
-         (v7_read_super): Likewise.
-       * balloc.c (sysv_new_block): Use sb_bread(). instead of bread().
-         (sysv_count_free_blocks): Likewise.
-       * ialloc.c (sysv_raw_inode): Likewise.
-       * itree.c (get_branch): Likewise.
-         (free_branches): Likewise.
-       * super.c (sysv_read_super): Likewise.
-         (v7_read_super): Likewise.
-
-Sat Dec 15 2001  Christoph Hellwig  <hch@infradead.org>
-
-       * inode.c (sysv_read_inode): Mark inode as bad in case of failure.
-       * super.c (complete_read_super): Check for bad root inode.
-
-Wed Nov 21 2001  Andrew Morton  <andrewm@uow.edu.au>
-
-       * file.c (sysv_sync_file): Call fsync_inode_data_buffers.
-
-Fri Oct 26 2001  Christoph Hellwig  <hch@infradead.org>
-
-       * dir.c, ialloc.c, namei.c, include/linux/sysv_fs_i.h:
-       Implement per-Inode lookup offset cache.
-       Modelled after Ted's ext2 patch.
-
-Fri Oct 26 2001  Christoph Hellwig  <hch@infradead.org>
-
-       * inode.c, super.c, include/linux/sysv_fs.h,
-         include/linux/sysv_fs_sb.h:
-       Remove symlink faking.  Noone really wants to use these as
-       linux filesystems and native OSes don't support it anyway.
-
-
diff --git a/fs/sysv/INTRO b/fs/sysv/INTRO
deleted file mode 100644 (file)
index de4e4d1..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-This is the implementation of the SystemV/Coherent filesystem for Linux.
-It grew out of separate filesystem implementations
-
-    Xenix FS      Doug Evans <dje@cygnus.com>  June 1992
-    SystemV FS    Paul B. Monday <pmonday@eecs.wsu.edu> March-June 1993
-    Coherent FS   B. Haible <haible@ma2s2.mathematik.uni-karlsruhe.de> June 1993
-
-and was merged together in July 1993.
-
-These filesystems are rather similar. Here is a comparison with Minix FS:
-
-* Linux fdisk reports on partitions
-  - Minix FS     0x81 Linux/Minix
-  - Xenix FS     ??
-  - SystemV FS   ??
-  - Coherent FS  0x08 AIX bootable
-
-* Size of a block or zone (data allocation unit on disk)
-  - Minix FS     1024
-  - Xenix FS     1024 (also 512 ??)
-  - SystemV FS   1024 (also 512 and 2048)
-  - Coherent FS   512
-
-* General layout: all have one boot block, one super block and
-  separate areas for inodes and for directories/data.
-  On SystemV Release 2 FS (e.g. Microport) the first track is reserved and
-  all the block numbers (including the super block) are offset by one track.
-
-* Byte ordering of "short" (16 bit entities) on disk:
-  - Minix FS     little endian  0 1
-  - Xenix FS     little endian  0 1
-  - SystemV FS   little endian  0 1
-  - Coherent FS  little endian  0 1
-  Of course, this affects only the file system, not the data of files on it!
-
-* Byte ordering of "long" (32 bit entities) on disk:
-  - Minix FS     little endian  0 1 2 3
-  - Xenix FS     little endian  0 1 2 3
-  - SystemV FS   little endian  0 1 2 3
-  - Coherent FS  PDP-11         2 3 0 1
-  Of course, this affects only the file system, not the data of files on it!
-
-* Inode on disk: "short", 0 means non-existent, the root dir ino is:
-  - Minix FS                            1
-  - Xenix FS, SystemV FS, Coherent FS   2
-
-* Maximum number of hard links to a file:
-  - Minix FS     250
-  - Xenix FS     ??
-  - SystemV FS   ??
-  - Coherent FS  >=10000
-
-* Free inode management:
-  - Minix FS                             a bitmap
-  - Xenix FS, SystemV FS, Coherent FS
-      There is a cache of a certain number of free inodes in the super-block.
-      When it is exhausted, new free inodes are found using a linear search.
-
-* Free block management:
-  - Minix FS                             a bitmap
-  - Xenix FS, SystemV FS, Coherent FS
-      Free blocks are organized in a "free list". Maybe a misleading term,
-      since it is not true that every free block contains a pointer to
-      the next free block. Rather, the free blocks are organized in chunks
-      of limited size, and every now and then a free block contains pointers
-      to the free blocks pertaining to the next chunk; the first of these
-      contains pointers and so on. The list terminates with a "block number"
-      0 on Xenix FS and SystemV FS, with a block zeroed out on Coherent FS.
-
-* Super-block location:
-  - Minix FS     block 1 = bytes 1024..2047
-  - Xenix FS     block 1 = bytes 1024..2047
-  - SystemV FS   bytes 512..1023
-  - Coherent FS  block 1 = bytes 512..1023
-
-* Super-block layout:
-  - Minix FS
-                    unsigned short s_ninodes;
-                    unsigned short s_nzones;
-                    unsigned short s_imap_blocks;
-                    unsigned short s_zmap_blocks;
-                    unsigned short s_firstdatazone;
-                    unsigned short s_log_zone_size;
-                    unsigned long s_max_size;
-                    unsigned short s_magic;
-  - Xenix FS, SystemV FS, Coherent FS
-                    unsigned short s_firstdatazone;
-                    unsigned long  s_nzones;
-                    unsigned short s_fzone_count;
-                    unsigned long  s_fzones[NICFREE];
-                    unsigned short s_finode_count;
-                    unsigned short s_finodes[NICINOD];
-                    char           s_flock;
-                    char           s_ilock;
-                    char           s_modified;
-                    char           s_rdonly;
-                    unsigned long  s_time;
-                    short          s_dinfo[4]; -- SystemV FS only
-                    unsigned long  s_free_zones;
-                    unsigned short s_free_inodes;
-                    short          s_dinfo[4]; -- Xenix FS only
-                    unsigned short s_interleave_m,s_interleave_n; -- Coherent FS only
-                    char           s_fname[6];
-                    char           s_fpack[6];
-    then they differ considerably:
-        Xenix FS
-                    char           s_clean;
-                    char           s_fill[371];
-                    long           s_magic;
-                    long           s_type;
-        SystemV FS
-                    long           s_fill[12 or 14];
-                    long           s_state;
-                    long           s_magic;
-                    long           s_type;
-        Coherent FS
-                    unsigned long  s_unique;
-    Note that Coherent FS has no magic.
-
-* Inode layout:
-  - Minix FS
-                    unsigned short i_mode;
-                    unsigned short i_uid;
-                    unsigned long  i_size;
-                    unsigned long  i_time;
-                    unsigned char  i_gid;
-                    unsigned char  i_nlinks;
-                    unsigned short i_zone[7+1+1];
-  - Xenix FS, SystemV FS, Coherent FS
-                    unsigned short i_mode;
-                    unsigned short i_nlink;
-                    unsigned short i_uid;
-                    unsigned short i_gid;
-                    unsigned long  i_size;
-                    unsigned char  i_zone[3*(10+1+1+1)];
-                    unsigned long  i_atime;
-                    unsigned long  i_mtime;
-                    unsigned long  i_ctime;
-
-* Regular file data blocks are organized as
-  - Minix FS
-               7 direct blocks
-               1 indirect block (pointers to blocks)
-               1 double-indirect block (pointer to pointers to blocks)
-  - Xenix FS, SystemV FS, Coherent FS
-              10 direct blocks
-               1 indirect block (pointers to blocks)
-               1 double-indirect block (pointer to pointers to blocks)
-               1 triple-indirect block (pointer to pointers to pointers to blocks)
-
-* Inode size, inodes per block
-  - Minix FS        32   32
-  - Xenix FS        64   16
-  - SystemV FS      64   16
-  - Coherent FS     64    8
-
-* Directory entry on disk
-  - Minix FS
-                    unsigned short inode;
-                    char name[14/30];
-  - Xenix FS, SystemV FS, Coherent FS
-                    unsigned short inode;
-                    char name[14];
-
-* Dir entry size, dir entries per block
-  - Minix FS     16/32    64/32
-  - Xenix FS     16       64
-  - SystemV FS   16       64
-  - Coherent FS  16       32
-
-* How to implement symbolic links such that the host fsck doesn't scream:
-  - Minix FS     normal
-  - Xenix FS     kludge: as regular files with  chmod 1000
-  - SystemV FS   ??
-  - Coherent FS  kludge: as regular files with  chmod 1000
-
-
-Notation: We often speak of a "block" but mean a zone (the allocation unit)
-and not the disk driver's notion of "block".
-
-
-Bruno Haible  <haible@ma2s2.mathematik.uni-karlsruhe.de>
index f2bef96..ebf7007 100644 (file)
@@ -70,7 +70,7 @@ fail:
 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
        unsigned long pos = filp->f_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        unsigned offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
index d63c5e4..ead9864 100644 (file)
@@ -301,13 +301,13 @@ static void sysv_delete_inode(struct inode *inode)
        unlock_kernel();
 }
 
-static kmem_cache_t *sysv_inode_cachep;
+static struct kmem_cache *sysv_inode_cachep;
 
 static struct inode *sysv_alloc_inode(struct super_block *sb)
 {
        struct sysv_inode_info *si;
 
-       si = kmem_cache_alloc(sysv_inode_cachep, SLAB_KERNEL);
+       si = kmem_cache_alloc(sysv_inode_cachep, GFP_KERNEL);
        if (!si)
                return NULL;
        return &si->vfs_inode;
@@ -318,7 +318,7 @@ static void sysv_destroy_inode(struct inode *inode)
        kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
 }
 
-static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
 {
        struct sysv_inode_info *si = (struct sysv_inode_info *)p;
 
index 8c28efa..2391c91 100644 (file)
@@ -77,7 +77,7 @@ const struct file_operations udf_dir_operations = {
 
 int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *dir = filp->f_dentry->d_inode;
+       struct inode *dir = filp->f_path.dentry->d_inode;
        int result;
 
        lock_kernel();
@@ -225,7 +225,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 
                if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT )
                {
-                       iblock = parent_ino(filp->f_dentry);
+                       iblock = parent_ino(filp->f_path.dentry);
                        flen = 2;
                        memcpy(fname, "..", flen);
                        dt_type = DT_DIR;
index 7aedd55..d81f2db 100644 (file)
@@ -108,7 +108,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 {
        ssize_t retval;
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int err, pos;
        size_t count = iocb->ki_left;
 
index 1aea6a4..1dbc295 100644 (file)
@@ -107,12 +107,12 @@ static struct file_system_type udf_fstype = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static kmem_cache_t * udf_inode_cachep;
+static struct kmem_cache * udf_inode_cachep;
 
 static struct inode *udf_alloc_inode(struct super_block *sb)
 {
        struct udf_inode_info *ei;
-       ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL);
+       ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
 
@@ -130,7 +130,7 @@ static void udf_destroy_inode(struct inode *inode)
        kmem_cache_free(udf_inode_cachep, UDF_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct udf_inode_info *ei = (struct udf_inode_info *) foo;
 
@@ -1709,7 +1709,7 @@ void udf_error(struct super_block *sb, const char *function,
                sb->s_dirt = 1;
        }
        va_start(args, fmt);
-       vsprintf(error_buf, fmt, args);
+       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
        va_end(args);
        printk (KERN_CRIT "UDF-fs error (device %s): %s: %s\n",
                sb->s_id, function, error_buf);
@@ -1721,7 +1721,7 @@ void udf_warning(struct super_block *sb, const char *function,
        va_list args;
 
        va_start (args, fmt);
-       vsprintf(error_buf, fmt, args);
+       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
        va_end(args);
        printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n",
                sb->s_id, function, error_buf);
index 7f0a0aa..433b6f6 100644 (file)
@@ -426,7 +426,7 @@ static int
 ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        loff_t pos = filp->f_pos;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct super_block *sb = inode->i_sb;
        unsigned int offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
index ec79e30..8a8e938 100644 (file)
@@ -224,7 +224,7 @@ void ufs_error (struct super_block * sb, const char * function,
                sb->s_flags |= MS_RDONLY;
        }
        va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
+       vsnprintf (error_buf, sizeof(error_buf), fmt, args);
        va_end (args);
        switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) {
        case UFS_MOUNT_ONERROR_PANIC:
@@ -255,7 +255,7 @@ void ufs_panic (struct super_block * sb, const char * function,
                sb->s_dirt = 1;
        }
        va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
+       vsnprintf (error_buf, sizeof(error_buf), fmt, args);
        va_end (args);
        sb->s_flags |= MS_RDONLY;
        printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
@@ -268,7 +268,7 @@ void ufs_warning (struct super_block * sb, const char * function,
        va_list args;
 
        va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
+       vsnprintf (error_buf, sizeof(error_buf), fmt, args);
        va_end (args);
        printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n",
                sb->s_id, function, error_buf);
@@ -1204,12 +1204,12 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
-static kmem_cache_t * ufs_inode_cachep;
+static struct kmem_cache * ufs_inode_cachep;
 
 static struct inode *ufs_alloc_inode(struct super_block *sb)
 {
        struct ufs_inode_info *ei;
-       ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, SLAB_KERNEL);
+       ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        ei->vfs_inode.i_version = 1;
@@ -1221,7 +1221,7 @@ static void ufs_destroy_inode(struct inode *inode)
        kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
 
index 28fce6c..7dd12bb 100644 (file)
@@ -299,7 +299,7 @@ static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
 
 #define ubh_get_addr16(ubh,begin) \
        (((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
-       ((begin) & (uspi->fsize>>1) - 1)))
+       ((begin) & ((uspi->fsize>>1) - 1)))
 
 #define ubh_get_addr32(ubh,begin) \
        (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
index 0901bdc..3864613 100644 (file)
@@ -268,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
        f = fget(fd);
        if (!f)
                return error;
-       dentry = f->f_dentry;
+       dentry = f->f_path.dentry;
        audit_inode(NULL, dentry->d_inode);
        error = setxattr(dentry, name, value, size, flags);
        fput(f);
@@ -351,7 +351,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
        f = fget(fd);
        if (!f)
                return error;
-       error = getxattr(f->f_dentry, name, value, size);
+       error = getxattr(f->f_path.dentry, name, value, size);
        fput(f);
        return error;
 }
@@ -423,7 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
        f = fget(fd);
        if (!f)
                return error;
-       error = listxattr(f->f_dentry, list, size);
+       error = listxattr(f->f_path.dentry, list, size);
        fput(f);
        return error;
 }
@@ -484,7 +484,7 @@ sys_fremovexattr(int fd, char __user *name)
        f = fget(fd);
        if (!f)
                return error;
-       dentry = f->f_dentry;
+       dentry = f->f_path.dentry;
        audit_inode(NULL, dentry->d_inode);
        error = removexattr(dentry, name);
        fput(f);
index 09360cf..b56eb75 100644 (file)
@@ -149,9 +149,10 @@ xfs_destroy_ioend(
  */
 STATIC void
 xfs_end_bio_delalloc(
-       void                    *data)
+       struct work_struct      *work)
 {
-       xfs_ioend_t             *ioend = data;
+       xfs_ioend_t             *ioend =
+               container_of(work, xfs_ioend_t, io_work);
 
        xfs_destroy_ioend(ioend);
 }
@@ -161,9 +162,10 @@ xfs_end_bio_delalloc(
  */
 STATIC void
 xfs_end_bio_written(
-       void                    *data)
+       struct work_struct      *work)
 {
-       xfs_ioend_t             *ioend = data;
+       xfs_ioend_t             *ioend =
+               container_of(work, xfs_ioend_t, io_work);
 
        xfs_destroy_ioend(ioend);
 }
@@ -176,9 +178,10 @@ xfs_end_bio_written(
  */
 STATIC void
 xfs_end_bio_unwritten(
-       void                    *data)
+       struct work_struct      *work)
 {
-       xfs_ioend_t             *ioend = data;
+       xfs_ioend_t             *ioend =
+               container_of(work, xfs_ioend_t, io_work);
        bhv_vnode_t             *vp = ioend->io_vnode;
        xfs_off_t               offset = ioend->io_offset;
        size_t                  size = ioend->io_size;
@@ -220,11 +223,11 @@ xfs_alloc_ioend(
        ioend->io_size = 0;
 
        if (type == IOMAP_UNWRITTEN)
-               INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend);
+               INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten);
        else if (type == IOMAP_DELAY)
-               INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc, ioend);
+               INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc);
        else
-               INIT_WORK(&ioend->io_work, xfs_end_bio_written, ioend);
+               INIT_WORK(&ioend->io_work, xfs_end_bio_written);
 
        return ioend;
 }
@@ -1403,7 +1406,7 @@ xfs_vm_direct_IO(
                        xfs_end_io_direct);
        }
 
-       if (unlikely(ret <= 0 && iocb->private))
+       if (unlikely(ret != -EIOCBQUEUED && iocb->private))
                xfs_destroy_ioend(iocb->private);
        return ret;
 }
index d338284..4fb01ff 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/kthread.h>
 #include <linux/migrate.h>
 #include <linux/backing-dev.h>
+#include <linux/freezer.h>
 
 STATIC kmem_zone_t *xfs_buf_zone;
 STATIC kmem_shaker_t xfs_buf_shake;
@@ -994,9 +995,10 @@ xfs_buf_wait_unpin(
 
 STATIC void
 xfs_buf_iodone_work(
-       void                    *v)
+       struct work_struct      *work)
 {
-       xfs_buf_t               *bp = (xfs_buf_t *)v;
+       xfs_buf_t               *bp =
+               container_of(work, xfs_buf_t, b_iodone_work);
 
        if (bp->b_iodone)
                (*(bp->b_iodone))(bp);
@@ -1017,10 +1019,10 @@ xfs_buf_ioend(
 
        if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) {
                if (schedule) {
-                       INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work, bp);
+                       INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work);
                        queue_work(xfslogd_workqueue, &bp->b_iodone_work);
                } else {
-                       xfs_buf_iodone_work(bp);
+                       xfs_buf_iodone_work(&bp->b_iodone_work);
                }
        } else {
                up(&bp->b_iodonesema);
@@ -1825,11 +1827,11 @@ xfs_buf_init(void)
        if (!xfs_buf_zone)
                goto out_free_trace_buf;
 
-       xfslogd_workqueue = create_workqueue("xfslogd");
+       xfslogd_workqueue = create_freezeable_workqueue("xfslogd");
        if (!xfslogd_workqueue)
                goto out_free_buf_zone;
 
-       xfsdatad_workqueue = create_workqueue("xfsdatad");
+       xfsdatad_workqueue = create_freezeable_workqueue("xfsdatad");
        if (!xfsdatad_workqueue)
                goto out_destroy_xfslogd_workqueue;
 
index d93d8dd..d26f5cd 100644 (file)
@@ -55,7 +55,7 @@ __xfs_file_read(
        loff_t                  pos)
 {
        struct file             *file = iocb->ki_filp;
-       bhv_vnode_t             *vp = vn_from_inode(file->f_dentry->d_inode);
+       bhv_vnode_t             *vp = vn_from_inode(file->f_path.dentry->d_inode);
 
        BUG_ON(iocb->ki_pos != pos);
        if (unlikely(file->f_flags & O_DIRECT))
@@ -131,7 +131,7 @@ xfs_file_sendfile(
        read_actor_t            actor,
        void                    *target)
 {
-       return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+       return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
                                filp, pos, 0, count, actor, target, NULL);
 }
 
@@ -143,7 +143,7 @@ xfs_file_sendfile_invis(
        read_actor_t            actor,
        void                    *target)
 {
-       return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+       return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
                                filp, pos, IO_INVIS, count, actor, target, NULL);
 }
 
@@ -155,7 +155,7 @@ xfs_file_splice_read(
        size_t                  len,
        unsigned int            flags)
 {
-       return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+       return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
                                   infilp, ppos, pipe, len, flags, 0, NULL);
 }
 
@@ -167,7 +167,7 @@ xfs_file_splice_read_invis(
        size_t                  len,
        unsigned int            flags)
 {
-       return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+       return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
                                   infilp, ppos, pipe, len, flags, IO_INVIS,
                                   NULL);
 }
@@ -180,7 +180,7 @@ xfs_file_splice_write(
        size_t                  len,
        unsigned int            flags)
 {
-       return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+       return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
                                    pipe, outfilp, ppos, len, flags, 0, NULL);
 }
 
@@ -192,7 +192,7 @@ xfs_file_splice_write_invis(
        size_t                  len,
        unsigned int            flags)
 {
-       return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+       return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
                                    pipe, outfilp, ppos, len, flags, IO_INVIS,
                                    NULL);
 }
@@ -212,7 +212,7 @@ xfs_file_close(
        struct file     *filp,
        fl_owner_t      id)
 {
-       return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
+       return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
                                file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
 }
 
@@ -251,7 +251,7 @@ xfs_vm_nopage(
        unsigned long           address,
        int                     *type)
 {
-       struct inode    *inode = area->vm_file->f_dentry->d_inode;
+       struct inode    *inode = area->vm_file->f_path.dentry->d_inode;
        bhv_vnode_t     *vp = vn_from_inode(inode);
 
        ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
@@ -268,7 +268,7 @@ xfs_file_readdir(
        filldir_t       filldir)
 {
        int             error = 0;
-       bhv_vnode_t     *vp = vn_from_inode(filp->f_dentry->d_inode);
+       bhv_vnode_t     *vp = vn_from_inode(filp->f_path.dentry->d_inode);
        uio_t           uio;
        iovec_t         iov;
        int             eof = 0;
@@ -345,7 +345,7 @@ xfs_file_mmap(
        vma->vm_ops = &xfs_file_vm_ops;
 
 #ifdef CONFIG_XFS_DMAPI
-       if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+       if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
                vma->vm_ops = &xfs_dmapi_file_vm_ops;
 #endif /* CONFIG_XFS_DMAPI */
 
@@ -360,7 +360,7 @@ xfs_file_ioctl(
        unsigned long   p)
 {
        int             error;
-       struct inode    *inode = filp->f_dentry->d_inode;
+       struct inode    *inode = filp->f_path.dentry->d_inode;
        bhv_vnode_t     *vp = vn_from_inode(inode);
 
        error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
@@ -382,7 +382,7 @@ xfs_file_ioctl_invis(
        unsigned long   p)
 {
        int             error;
-       struct inode    *inode = filp->f_dentry->d_inode;
+       struct inode    *inode = filp->f_path.dentry->d_inode;
        bhv_vnode_t     *vp = vn_from_inode(inode);
 
        error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
@@ -404,7 +404,7 @@ xfs_vm_mprotect(
        struct vm_area_struct *vma,
        unsigned int    newflags)
 {
-       bhv_vnode_t     *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
+       bhv_vnode_t     *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
        int             error = 0;
 
        if (vp->v_vfsp->vfs_flag & VFS_DMI) {
index 74d0948..f011c9c 100644 (file)
@@ -107,9 +107,9 @@ xfs_find_handle(
                if (!file)
                    return -EBADF;
 
-               ASSERT(file->f_dentry);
-               ASSERT(file->f_dentry->d_inode);
-               inode = igrab(file->f_dentry->d_inode);
+               ASSERT(file->f_path.dentry);
+               ASSERT(file->f_path.dentry->d_inode);
+               inode = igrab(file->f_path.dentry->d_inode);
                fput(file);
                break;
        }
@@ -333,10 +333,10 @@ xfs_open_by_handle(
        }
 
        /* Ensure umount returns EBUSY on umounts while this file is open. */
-       mntget(parfilp->f_vfsmnt);
+       mntget(parfilp->f_path.mnt);
 
        /* Create file pointer. */
-       filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
+       filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags);
        if (IS_ERR(filp)) {
                put_unused_fd(new_fd);
                return -XFS_ERROR(-PTR_ERR(filp));
index 270db0f..b83cebc 100644 (file)
@@ -112,7 +112,7 @@ xfs_compat_ioctl(
        unsigned        cmd,
        unsigned long   arg)
 {
-       struct inode    *inode = file->f_dentry->d_inode;
+       struct inode    *inode = file->f_path.dentry->d_inode;
        bhv_vnode_t     *vp = vn_from_inode(inode);
        int             error;
 
index fa842f1..65e79b4 100644 (file)
@@ -805,7 +805,7 @@ start:
             !capable(CAP_FSETID)) {
                error = xfs_write_clear_setuid(xip);
                if (likely(!error))
-                       error = -remove_suid(file->f_dentry);
+                       error = -remove_suid(file->f_path.dentry);
                if (unlikely(error)) {
                        xfs_iunlock(xip, iolock);
                        goto out_unlock_mutex;
index de05abb..b93265b 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/mempool.h>
 #include <linux/writeback.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 
 STATIC struct quotactl_ops xfs_quotactl_operations;
 STATIC struct super_operations xfs_super_operations;
index 80562b6..50d0fae 100644 (file)
@@ -71,7 +71,7 @@ xfs_swapext(
 
        /* Pull information for the target fd */
        if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) ||
-           ((vp = vn_from_inode(fp->f_dentry->d_inode)) == NULL))  {
+           ((vp = vn_from_inode(fp->f_path.dentry->d_inode)) == NULL))  {
                error = XFS_ERROR(EINVAL);
                goto error0;
        }
@@ -83,7 +83,7 @@ xfs_swapext(
        }
 
        if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
-           ((tvp = vn_from_inode(tfp->f_dentry->d_inode)) == NULL)) {
+           ((tvp = vn_from_inode(tfp->f_path.dentry->d_inode)) == NULL)) {
                error = XFS_ERROR(EINVAL);
                goto error0;
        }
index 47faf27..7f1e929 100644 (file)
@@ -64,7 +64,7 @@
 /* Host-dependent types and defines */
 
 #define ACPI_MACHINE_WIDTH          BITS_PER_LONG
-#define acpi_cache_t                        kmem_cache_t
+#define acpi_cache_t                        struct kmem_cache
 #define acpi_spinlock                   spinlock_t *
 #define ACPI_EXPORT_SYMBOL(symbol)  EXPORT_SYMBOL(symbol);
 #define strtoul                     simple_strtoul
index b9ff4d8..57e09f5 100644 (file)
@@ -51,7 +51,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 #define dma_alloc_noncoherent(d, s, h, f)      dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h)       dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(dev)                 (1)
+#define dma_is_consistent(d, h)                        (1)
 
 int dma_set_mask(struct device *dev, u64 mask);
 
@@ -60,7 +60,7 @@ int dma_set_mask(struct device *dev, u64 mask);
 #define dma_sync_single_range(dev, addr, off, size, dir)  do { } while (0)
 #define dma_sync_sg_for_cpu(dev, sg, nents, dir)         do { } while (0)
 #define dma_sync_sg_for_device(dev, sg, nents, dir)      do { } while (0)
-#define dma_cache_sync(va, size, dir)                    do { } while (0)
+#define dma_cache_sync(dev, va, size, dir)               do { } while (0)
 
 #define dma_get_cache_alignment()                        L1_CACHE_BYTES
 
index 5541101..ad854a4 100644 (file)
@@ -25,6 +25,19 @@ struct termios {
        speed_t c_ospeed;               /* output speed */
 };
 
+/* Alpha has matching termios and ktermios */
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_cc[NCCS];                /* control characters */
+       cc_t c_line;                    /* line discipline (== c_cc[19]) */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VEOF 0
 #define VEOL 1
index 2cabbd4..84313d1 100644 (file)
 
 #define NR_SYSCALLS                    447
 
-#if defined(__GNUC__)
-
-#define _syscall_return(type)                                          \
-       return (_sc_err ? errno = _sc_ret, _sc_ret = -1L : 0), (type) _sc_ret
-
-#define _syscall_clobbers                                              \
-       "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",                 \
-       "$22", "$23", "$24", "$25", "$27", "$28"                        \
-
-#define _syscall0(type, name)                                          \
-type name(void)                                                                \
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_19 __asm__("$19");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               __asm__("callsys # %0 %1 %2"                            \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0)                                    \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#define _syscall1(type,name,type1,arg1)                                        \
-type name(type1 arg1)                                                  \
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_19 __asm__("$19");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               __asm__("callsys # %0 %1 %2 %3"                         \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16)                       \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)                     \
-type name(type1 arg1,type2 arg2)                                       \
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_17 __asm__("$17");                    \
-               register long _sc_19 __asm__("$19");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               _sc_17 = (long) (arg2);                                 \
-               __asm__("callsys # %0 %1 %2 %3 %4"                      \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17)          \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)          \
-type name(type1 arg1,type2 arg2,type3 arg3)                            \
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_17 __asm__("$17");                    \
-               register long _sc_18 __asm__("$18");                    \
-               register long _sc_19 __asm__("$19");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               _sc_17 = (long) (arg2);                                 \
-               _sc_18 = (long) (arg3);                                 \
-               __asm__("callsys # %0 %1 %2 %3 %4 %5"                   \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),         \
-                         "r"(_sc_18)                                   \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4)              \
-{                                                                       \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_17 __asm__("$17");                    \
-               register long _sc_18 __asm__("$18");                    \
-               register long _sc_19 __asm__("$19");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               _sc_17 = (long) (arg2);                                 \
-               _sc_18 = (long) (arg3);                                 \
-               _sc_19 = (long) (arg4);                                 \
-               __asm__("callsys # %0 %1 %2 %3 %4 %5 %6"                \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),         \
-                         "r"(_sc_18), "1"(_sc_19)                      \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-} 
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5)                                                    \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)     \
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_17 __asm__("$17");                    \
-               register long _sc_18 __asm__("$18");                    \
-               register long _sc_19 __asm__("$19");                    \
-               register long _sc_20 __asm__("$20");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               _sc_17 = (long) (arg2);                                 \
-               _sc_18 = (long) (arg3);                                 \
-               _sc_19 = (long) (arg4);                                 \
-               _sc_20 = (long) (arg5);                                 \
-               __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7"             \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),         \
-                         "r"(_sc_18), "1"(_sc_19), "r"(_sc_20)         \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5,type6,arg6)                                         \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\
-{                                                                      \
-       long _sc_ret, _sc_err;                                          \
-       {                                                               \
-               register long _sc_0 __asm__("$0");                      \
-               register long _sc_16 __asm__("$16");                    \
-               register long _sc_17 __asm__("$17");                    \
-               register long _sc_18 __asm__("$18");                    \
-               register long _sc_19 __asm__("$19");                    \
-               register long _sc_20 __asm__("$20");                    \
-               register long _sc_21 __asm__("$21");                    \
-                                                                       \
-               _sc_0 = __NR_##name;                                    \
-               _sc_16 = (long) (arg1);                                 \
-               _sc_17 = (long) (arg2);                                 \
-               _sc_18 = (long) (arg3);                                 \
-               _sc_19 = (long) (arg4);                                 \
-               _sc_20 = (long) (arg5);                                 \
-               _sc_21 = (long) (arg6);                                 \
-               __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7 %8"          \
-                       : "=r"(_sc_0), "=r"(_sc_19)                     \
-                       : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17),         \
-                         "r"(_sc_18), "1"(_sc_19), "r"(_sc_20), "r"(_sc_21) \
-                       : _syscall_clobbers);                           \
-               _sc_ret = _sc_0, _sc_err = _sc_19;                      \
-       }                                                               \
-       _syscall_return(type);                                          \
-}
-
-#endif /* __GNUC__ */
-
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
index 24b51cc..9eceb41 100644 (file)
@@ -17,8 +17,6 @@
 #define __virt_to_bus(x)       __virt_to_phys(x)
 #define __bus_to_virt(x)       __phys_to_virt(x)
 
-#ifdef CONFIG_DISCONTIGMEM
-
 /*
  * The nodes are the followings:
  *
  *   node 2: 0xf800.0000 - 0xfbff.ffff
  *   node 3: 0xfc00.0000 - 0xffff.ffff
  */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(addr) \
-       (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
-
-/*
- * Given a page frame number, convert it to a node id.
- */
-#define PFN_TO_NID(pfn) \
-       (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
-
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and return the mem_map of that node.
- */
-#define ADDR_TO_MAPBASE(kaddr)  NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-
-/*
- * Given a page frame number, find the owning node of the memory
- * and return the mem_map of that node.
- */
-#define PFN_TO_MAPBASE(pfn)     NODE_MEM_MAP(PFN_TO_NID(pfn))
-
-/*
- *  Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
- *  and returns the index corresponding to the appropriate page in the
- *  node's mem_map.
- */
-#define LOCAL_MAP_NR(addr) \
-        (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
-
-#define NODE_MAX_MEM_SHIFT     26
-#define NODE_MAX_MEM_SIZE      (1 << NODE_MAX_MEM_SHIFT)
-
-#endif /* CONFIG_DISCONTIGMEM */
+#define NODE_MEM_SIZE_BITS     26
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-at91rm9200/at91_aic.h b/include/asm-arm/arch-at91rm9200/at91_aic.h
new file mode 100644 (file)
index 0000000..267e698
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_aic.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Advanced Interrupt Controller (AIC) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_AIC_H
+#define AT91_AIC_H
+
+#define AT91_AIC_SMR(n)                (AT91_AIC + ((n) * 4))  /* Source Mode Registers 0-31 */
+#define                AT91_AIC_PRIOR          (7 << 0)                /* Priority Level */
+#define                AT91_AIC_SRCTYPE        (3 << 5)                /* Interrupt Source Type */
+#define                        AT91_AIC_SRCTYPE_LOW            (0 << 5)
+#define                        AT91_AIC_SRCTYPE_FALLING        (1 << 5)
+#define                        AT91_AIC_SRCTYPE_HIGH           (2 << 5)
+#define                        AT91_AIC_SRCTYPE_RISING         (3 << 5)
+
+#define AT91_AIC_SVR(n)                (AT91_AIC + 0x80 + ((n) * 4))   /* Source Vector Registers 0-31 */
+#define AT91_AIC_IVR           (AT91_AIC + 0x100)      /* Interrupt Vector Register */
+#define AT91_AIC_FVR           (AT91_AIC + 0x104)      /* Fast Interrupt Vector Register */
+#define AT91_AIC_ISR           (AT91_AIC + 0x108)      /* Interrupt Status Register */
+#define                AT91_AIC_IRQID          (0x1f << 0)             /* Current Interrupt Identifier */
+
+#define AT91_AIC_IPR           (AT91_AIC + 0x10c)      /* Interrupt Pending Register */
+#define AT91_AIC_IMR           (AT91_AIC + 0x110)      /* Interrupt Mask Register */
+#define AT91_AIC_CISR          (AT91_AIC + 0x114)      /* Core Interrupt Status Register */
+#define                AT91_AIC_NFIQ           (1 << 0)                /* nFIQ Status */
+#define                AT91_AIC_NIRQ           (1 << 1)                /* nIRQ Status */
+
+#define AT91_AIC_IECR          (AT91_AIC + 0x120)      /* Interrupt Enable Command Register */
+#define AT91_AIC_IDCR          (AT91_AIC + 0x124)      /* Interrupt Disable Command Register */
+#define AT91_AIC_ICCR          (AT91_AIC + 0x128)      /* Interrupt Clear Command Register */
+#define AT91_AIC_ISCR          (AT91_AIC + 0x12c)      /* Interrupt Set Command Register */
+#define AT91_AIC_EOICR         (AT91_AIC + 0x130)      /* End of Interrupt Command Register */
+#define AT91_AIC_SPU           (AT91_AIC + 0x134)      /* Spurious Interrupt Vector Register */
+#define AT91_AIC_DCR           (AT91_AIC + 0x138)      /* Debug Control Register */
+#define                AT91_AIC_DCR_PROT       (1 << 0)                /* Protection Mode */
+#define                AT91_AIC_DCR_GMSK       (1 << 1)                /* General Mask */
+
+#define AT91_AIC_FFER          (AT91_AIC + 0x140)      /* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC_FFDR          (AT91_AIC + 0x144)      /* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC_FFSR          (AT91_AIC + 0x148)      /* Fast Forcing Status Register [SAM9 only] */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_dbgu.h b/include/asm-arm/arch-at91rm9200/at91_dbgu.h
new file mode 100644 (file)
index 0000000..e4b8b27
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_dbgu.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Debug Unit (DBGU) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_DBGU_H
+#define AT91_DBGU_H
+
+#define AT91_DBGU_CR           (AT91_DBGU + 0x00)      /* Control Register */
+#define AT91_DBGU_MR           (AT91_DBGU + 0x04)      /* Mode Register */
+#define AT91_DBGU_IER          (AT91_DBGU + 0x08)      /* Interrupt Enable Register */
+#define                AT91_DBGU_TXRDY         (1 << 1)                /* Transmitter Ready */
+#define                AT91_DBGU_TXEMPTY       (1 << 9)                /* Transmitter Empty */
+#define AT91_DBGU_IDR          (AT91_DBGU + 0x0c)      /* Interrupt Disable Register */
+#define AT91_DBGU_IMR          (AT91_DBGU + 0x10)      /* Interrupt Mask Register */
+#define AT91_DBGU_SR           (AT91_DBGU + 0x14)      /* Status Register */
+#define AT91_DBGU_RHR          (AT91_DBGU + 0x18)      /* Receiver Holding Register */
+#define AT91_DBGU_THR          (AT91_DBGU + 0x1c)      /* Transmitter Holding Register */
+#define AT91_DBGU_BRGR         (AT91_DBGU + 0x20)      /* Baud Rate Generator Register */
+
+#define AT91_DBGU_CIDR         (AT91_DBGU + 0x40)      /* Chip ID Register */
+#define AT91_DBGU_EXID         (AT91_DBGU + 0x44)      /* Chip ID Extension Register */
+#define                AT91_CIDR_VERSION       (0x1f << 0)             /* Version of the Device */
+#define                AT91_CIDR_EPROC         (7    << 5)             /* Embedded Processor */
+#define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
+#define                AT91_CIDR_NVPSIZ2       (0xf  << 12)            /* Second Nonvolatile Program Memory Size */
+#define                AT91_CIDR_SRAMSIZ       (0xf  << 16)            /* Internal SRAM Size */
+#define                AT91_CIDR_ARCH          (0xff << 20)            /* Architecture Identifier */
+#define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
+#define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
+
+#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
+#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91rm9200/at91_ecc.h
new file mode 100644 (file)
index 0000000..fddf256
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_ecc.h
+ *
+ * Error Corrected Code Controller (ECC) - System peripherals regsters.
+ * Based on AT91SAM9260 datasheet revision B.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef AT91_ECC_H
+#define AT91_ECC_H
+
+#define AT91_ECC_CR            (AT91_ECC + 0x00)       /* Control register */
+#define                AT91_ECC_RST            (1 << 0)                /* Reset parity */
+
+#define AT91_ECC_MR            (AT91_ECC + 0x04)       /* Mode register */
+#define                AT91_ECC_PAGESIZE       (3 << 0)                /* Page Size */
+#define                        AT91_ECC_PAGESIZE_528           (0)
+#define                        AT91_ECC_PAGESIZE_1056          (1)
+#define                        AT91_ECC_PAGESIZE_2112          (2)
+#define                        AT91_ECC_PAGESIZE_4224          (3)
+
+#define AT91_ECC_SR            (AT91_ECC + 0x08)       /* Status register */
+#define                AT91_ECC_RECERR         (1 << 0)                /* Recoverable Error */
+#define                AT91_ECC_ECCERR         (1 << 1)                /* ECC Single Bit Error */
+#define                AT91_ECC_MULERR         (1 << 2)                /* Multiple Errors */
+
+#define AT91_ECC_PR            (AT91_ECC + 0x0c)       /* Parity register */
+#define                AT91_ECC_BITADDR        (0xf << 0)              /* Bit Error Address */
+#define                AT91_ECC_WORDADDR       (0xfff << 4)            /* Word Error Address */
+
+#define AT91_ECC_NPR           (AT91_ECC + 0x10)       /* NParity register */
+#define                AT91_ECC_NPARITY        (0xffff << 0)           /* NParity */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_lcdc.h b/include/asm-arm/arch-at91rm9200/at91_lcdc.h
new file mode 100644 (file)
index 0000000..9cbfcdd
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_lcdc.h
+ *
+ * LCD Controller (LCDC).
+ * Based on AT91SAM9261 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_LCDC_H
+#define AT91_LCDC_H
+
+#define AT91_LCDC_DMABADDR1    0x00            /* DMA Base Address Register 1 */
+#define AT91_LCDC_DMABADDR2    0x04            /* DMA Base Address Register 2 */
+#define AT91_LCDC_DMAFRMPT1    0x08            /* DMA Frame Pointer Register 1 */
+#define AT91_LCDC_DMAFRMPT2    0x0c            /* DMA Frame Pointer Register 2 */
+#define AT91_LCDC_DMAFRMADD1   0x10            /* DMA Frame Address Register 1 */
+#define AT91_LCDC_DMAFRMADD2   0x14            /* DMA Frame Address Register 2 */
+
+#define AT91_LCDC_DMAFRMCFG    0x18            /* DMA Frame Configuration Register */
+#define                AT91_LCDC_FRSIZE        (0x7fffff <<  0)        /* Frame Size */
+#define                AT91_LCDC_BLENGTH       (0x7f     << 24)        /* Burst Length */
+
+#define AT91_LCDC_DMACON       0x1c            /* DMA Control Register */
+#define                AT91_LCDC_DMAEN         (0x1 << 0)      /* DMA Enable */
+#define                AT91_LCDC_DMARST        (0x1 << 1)      /* DMA Reset */
+#define                AT91_LCDC_DMABUSY       (0x1 << 2)      /* DMA Busy */
+
+#define AT91_LCDC_LCDCON1      0x0800          /* LCD Control Register 1 */
+#define                AT91_LCDC_BYPASS        (1     <<  0)   /* Bypass lcd_dotck divider */
+#define                AT91_LCDC_CLKVAL        (0x1ff << 12)   /* Clock Divider */
+#define                AT91_LCDC_LINCNT        (0x7ff << 21)   /* Line Counter */
+
+#define AT91_LCDC_LCDCON2      0x0804          /* LCD Control Register 2 */
+#define                AT91_LCDC_DISTYPE       (3 << 0)        /* Display Type */
+#define                        AT91_LCDC_DISTYPE_STNMONO       (0 << 0)
+#define                        AT91_LCDC_DISTYPE_STNCOLOR      (1 << 0)
+#define                        AT91_LCDC_DISTYPE_TFT           (2 << 0)
+#define                AT91_LCDC_SCANMOD       (1 << 2)        /* Scan Mode */
+#define                        AT91_LCDC_SCANMOD_SINGLE        (0 << 2)
+#define                        AT91_LCDC_SCANMOD_DUAL          (1 << 2)
+#define                AT91_LCDC_IFWIDTH       (3 << 3)        /*Interface Width */
+#define                        AT91_LCDC_IFWIDTH_4             (0 << 3)
+#define                        AT91_LCDC_IFWIDTH_8             (1 << 3)
+#define                        AT91_LCDC_IFWIDTH_16            (2 << 3)
+#define                AT91_LCDC_PIXELSIZE     (7 << 5)        /* Bits per pixel */
+#define                        AT91_LCDC_PIXELSIZE_1           (0 << 5)
+#define                        AT91_LCDC_PIXELSIZE_2           (1 << 5)
+#define                        AT91_LCDC_PIXELSIZE_4           (2 << 5)
+#define                        AT91_LCDC_PIXELSIZE_8           (3 << 5)
+#define                        AT91_LCDC_PIXELSIZE_16          (4 << 5)
+#define                        AT91_LCDC_PIXELSIZE_24          (5 << 5)
+#define                AT91_LCDC_INVVD         (1 << 8)        /* LCD Data polarity */
+#define                        AT91_LCDC_INVVD_NORMAL          (0 << 8)
+#define                        AT91_LCDC_INVVD_INVERTED        (1 << 8)
+#define                AT91_LCDC_INVFRAME      (1 << 9 )       /* LCD VSync polarity */
+#define                        AT91_LCDC_INVFRAME_NORMAL       (0 << 9)
+#define                        AT91_LCDC_INVFRAME_INVERTED     (1 << 9)
+#define                AT91_LCDC_INVLINE       (1 << 10)       /* LCD HSync polarity */
+#define                        AT91_LCDC_INVLINE_NORMAL        (0 << 10)
+#define                        AT91_LCDC_INVLINE_INVERTED      (1 << 10)
+#define                AT91_LCDC_INVCLK        (1 << 11)       /* LCD dotclk polarity */
+#define                        AT91_LCDC_INVCLK_NORMAL         (0 << 11)
+#define                        AT91_LCDC_INVCLK_INVERTED       (1 << 11)
+#define                AT91_LCDC_INVDVAL       (1 << 12)       /* LCD dval polarity */
+#define                        AT91_LCDC_INVDVAL_NORMAL        (0 << 12)
+#define                        AT91_LCDC_INVDVAL_INVERTED      (1 << 12)
+#define                AT91_LCDC_CLKMOD        (1 << 15)       /* LCD dotclk mode */
+#define                        AT91_LCDC_CLKMOD_ACTIVEDISPLAY  (0 << 15)
+#define                        AT91_LCDC_CLKMOD_ALWAYSACTIVE   (1 << 15)
+#define                AT91_LCDC_MEMOR         (1 << 31)       /* Memory Ordering Format */
+#define                        AT91_LCDC_MEMOR_BIG             (0 << 31)
+#define                        AT91_LCDC_MEMOR_LITTLE          (1 << 31)
+
+#define AT91_LCDC_TIM1         0x0808          /* LCD Timing Register 1 */
+#define                AT91_LCDC_VFP           (0xff <<  0)    /* Vertical Front Porch */
+#define                AT91_LCDC_VBP           (0xff <<  8)    /* Vertical Back Porch */
+#define                AT91_LCDC_VPW           (0x3f << 16)    /* Vertical Synchronization Pulse Width */
+#define                AT91_LCDC_VHDLY         (0xf  << 24)    /* Vertical to Horizontal Delay */
+
+#define AT91_LCDC_TIM2         0x080c          /* LCD Timing Register 2 */
+#define                AT91_LCDC_HBP           (0xff  <<  0)   /* Horizontal Back Porch */
+#define                AT91_LCDC_HPW           (0x3f  <<  8)   /* Horizontal Synchronization Pulse Width */
+#define                AT91_LCDC_HFP           (0x7ff << 21)   /* Horizontal Front Porch */
+
+#define AT91_LCDC_LCDFRMCFG    0x0810          /* LCD Frame Configuration Register */
+#define                AT91_LCDC_LINEVAL       (0x7ff <<  0)   /* Vertical Size of LCD Module */
+#define                AT91_LCDC_HOZVAL        (0x7ff << 21)   /* Horizontal Size of LCD Module */
+
+#define AT91_LCDC_FIFO         0x0814          /* LCD FIFO Register */
+#define                AT91_LCDC_FIFOTH        (0xffff)        /* FIFO Threshold */
+
+#define AT91_LCDC_DP1_2                0x081c          /* Dithering Pattern DP1_2 Register */
+#define AT91_LCDC_DP4_7                0x0820          /* Dithering Pattern DP4_7 Register */
+#define AT91_LCDC_DP3_5                0x0824          /* Dithering Pattern DP3_5 Register */
+#define AT91_LCDC_DP2_3                0x0828          /* Dithering Pattern DP2_3 Register */
+#define AT91_LCDC_DP5_7                0x082c          /* Dithering Pattern DP5_7 Register */
+#define AT91_LCDC_DP3_4                0x0830          /* Dithering Pattern DP3_4 Register */
+#define AT91_LCDC_DP4_5                0x0834          /* Dithering Pattern DP4_5 Register */
+#define AT91_LCDC_DP6_7                0x0838          /* Dithering Pattern DP6_7 Register */
+#define                AT91_LCDC_DP1_2_VAL     (0xff)
+#define                AT91_LCDC_DP4_7_VAL     (0xfffffff)
+#define                AT91_LCDC_DP3_5_VAL     (0xfffff)
+#define                AT91_LCDC_DP2_3_VAL     (0xfff)
+#define                AT91_LCDC_DP5_7_VAL     (0xfffffff)
+#define                AT91_LCDC_DP3_4_VAL     (0xffff)
+#define                AT91_LCDC_DP4_5_VAL     (0xfffff)
+#define                AT91_LCDC_DP6_7_VAL     (0xfffffff)
+
+#define AT91_LCDC_PWRCON       0x083c          /* Power Control Register */
+#define                AT91_LCDC_PWR           (1    <<  0)    /* LCD Module Power Control */
+#define                AT91_LCDC_GUARDT        (0x7f <<  1)    /* Delay in Frame Period */
+#define                AT91_LCDC_BUSY          (1    << 31)    /* LCD Busy */
+
+#define AT91_LCDC_CONTRAST_CTR 0x0840          /* Contrast Control Register */
+#define                AT91_LCDC_PS            (3 << 0)        /* Contrast Counter Prescaler */
+#define                        AT91_LCDC_PS_DIV1               (0 << 0)
+#define                        AT91_LCDC_PS_DIV2               (1 << 0)
+#define                        AT91_LCDC_PS_DIV4               (2 << 0)
+#define                        AT91_LCDC_PS_DIV8               (3 << 0)
+#define                AT91_LCDC_POL           (1 << 2)        /* Polarity of output Pulse */
+#define                        AT91_LCDC_POL_NEGATIVE          (0 << 2)
+#define                        AT91_LCDC_POL_POSITIVE          (1 << 2)
+#define                AT91_LCDC_ENA           (1 << 3)        /* PWM generator Control */
+#define                        AT91_LCDC_ENA_PWMDISABLE        (0 << 3)
+#define                        AT91_LCDC_ENA_PWMENABLE         (1 << 3)
+
+#define AT91_LCDC_CONTRAST_VAL 0x0844          /* Contrast Value Register */
+#define                AT91_LCDC_CVAL          (0xff)          /* PWM compare value */
+
+#define AT91_LCDC_IER          0x0848          /* Interrupt Enable Register */
+#define AT91_LCDC_IDR          0x084c          /* Interrupt Disable Register */
+#define AT91_LCDC_IMR          0x0850          /* Interrupt Mask Register */
+#define AT91_LCDC_ISR          0x0854          /* Interrupt Enable Register */
+#define AT91_LCDC_ICR          0x0858          /* Interrupt Clear Register */
+#define                AT91_LCDC_LNI           (1 << 0)        /* Line Interrupt */
+#define                AT91_LCDC_LSTLNI        (1 << 1)        /* Last Line Interrupt */
+#define                AT91_LCDC_EOFI          (1 << 2)        /* DMA End Of Frame Interrupt */
+#define                AT91_LCDC_UFLWI         (1 << 4)        /* FIFO Underflow Interrupt */
+#define                AT91_LCDC_OWRI          (1 << 5)        /* FIFO Overwrite Interrupt */
+#define                AT91_LCDC_MERI          (1 << 6)        /* DMA Memory Error Interrupt */
+
+#define AT91_LCDC_LUT_(n)      (0x0c00 + ((n)*4))      /* Palette Entry 0..255 */
+
+#endif
@@ -1,11 +1,11 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
+ * include/asm-arm/arch-at91rm9200/at91_mci.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
  *
  * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision E.
+ * Based on AT91RM9200 datasheet revision F.
  *
  * 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
@@ -13,8 +13,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_MCI_H
-#define AT91RM9200_MCI_H
+#ifndef AT91_MCI_H
+#define AT91_MCI_H
 
 #define AT91_MCI_CR            0x00            /* Control Register */
 #define                AT91_MCI_MCIEN          (1 <<  0)       /* Multi-Media Interface Enable */
 
 #define AT91_MCI_MR            0x04            /* Mode Register */
 #define                AT91_MCI_CLKDIV         (0xff  <<  0)   /* Clock Divider */
-#define                AT91_MCI_PWSDIV         (3     <<  8)   /* Power Saving Divider */
+#define                AT91_MCI_PWSDIV         (7     <<  8)   /* Power Saving Divider */
 #define                AT91_MCI_PDCPADV        (1     << 14)   /* PDC Padding Value */
 #define                AT91_MCI_PDCMODE        (1     << 15)   /* PDC-orientated Mode */
-#define                AT91_MCI_BLKLEN         (0xfff << 18)   /* Data Block Length */
+#define                AT91_MCI_BLKLEN         (0xfff << 18)   /* Data Block Length */
 
 #define AT91_MCI_DTOR          0x08            /* Data Timeout Register */
 #define                AT91_MCI_DTOCYC         (0xf << 0)      /* Data Timeout Cycle Number */
@@ -43,8 +43,8 @@
 #define                AT91_MCI_DTOMUL_1M              (7 <<  4)
 
 #define AT91_MCI_SDCR          0x0c            /* SD Card Register */
-#define                AT91_MCI_SDCSEL         (0xf << 0)      /* SD Card Selector */
-#define                AT91_MCI_SDCBUS         (1   << 7)      /* 1-bit or 4-bit bus */
+#define                AT91_MCI_SDCSEL         (3 << 0)        /* SD Card Selector */
+#define                AT91_MCI_SDCBUS         (1 << 7)        /* 1-bit or 4-bit bus */
 
 #define AT91_MCI_ARGR          0x10            /* Argument Register */
 
 
 #define AT91_MCI_SR            0x40            /* Status Register */
 #define                AT91_MCI_CMDRDY         (1 <<  0)       /* Command Ready */
-#define                AT91_MCI_RXRDY          (1 <<  1)       /* Receiver Ready */
+#define                AT91_MCI_RXRDY          (1 <<  1)       /* Receiver Ready */
 #define                AT91_MCI_TXRDY          (1 <<  2)       /* Transmit Ready */
 #define                AT91_MCI_BLKE           (1 <<  3)       /* Data Block Ended */
 #define                AT91_MCI_DTIP           (1 <<  4)       /* Data Transfer in Progress */
 #define                AT91_MCI_NOTBUSY        (1 <<  5)       /* Data Not Busy */
 #define                AT91_MCI_ENDRX          (1 <<  6)       /* End of RX Buffer */
 #define                AT91_MCI_ENDTX          (1 <<  7)       /* End fo TX Buffer */
+#define                AT91_MCI_SDIOIRQA       (1 <<  8)       /* SDIO Interrupt for Slot A */
+#define                At91_MCI_SDIOIRQB       (1 <<  9)       /* SDIO Interrupt for Slot B [AT91RM9200 only] */
 #define                AT91_MCI_RXBUFF         (1 << 14)       /* RX Buffer Full */
 #define                AT91_MCI_TXBUFE         (1 << 15)       /* TX Buffer Empty */
-#define                AT91_MCI_RINDE          (1 << 16)       /* Response Index Error */
+#define                AT91_MCI_RINDE          (1 << 16)       /* Response Index Error */
 #define                AT91_MCI_RDIRE          (1 << 17)       /* Response Direction Error */
-#define                AT91_MCI_RCRCE          (1 << 18)       /* Response CRC Error */
+#define                AT91_MCI_RCRCE          (1 << 18)       /* Response CRC Error */
 #define                AT91_MCI_RENDE          (1 << 19)       /* Response End Bit Error */
 #define                AT91_MCI_RTOE           (1 << 20)       /* Reponse Time-out Error */
 #define                AT91_MCI_DCRCE          (1 << 21)       /* Data CRC Error */
similarity index 92%
rename from include/asm-avr32/arch-at32ap/at91rm9200_pdc.h
rename to include/asm-arm/arch-at91rm9200/at91_pdc.h
index ce1150d..79d6e02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
+ * include/asm-arm/arch-at91rm9200/at91_pdc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -13,8 +13,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_PDC_H
-#define AT91RM9200_PDC_H
+#ifndef AT91_PDC_H
+#define AT91_PDC_H
 
 #define AT91_PDC_RPR           0x100   /* Receive Pointer Register */
 #define AT91_PDC_RCR           0x104   /* Receive Counter Register */
diff --git a/include/asm-arm/arch-at91rm9200/at91_pio.h b/include/asm-arm/arch-at91rm9200/at91_pio.h
new file mode 100644 (file)
index 0000000..680eaa1
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_pio.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Parallel I/O Controller (PIO) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_PIO_H
+#define AT91_PIO_H
+
+#define PIO_PER                0x00    /* Enable Register */
+#define PIO_PDR                0x04    /* Disable Register */
+#define PIO_PSR                0x08    /* Status Register */
+#define PIO_OER                0x10    /* Output Enable Register */
+#define PIO_ODR                0x14    /* Output Disable Register */
+#define PIO_OSR                0x18    /* Output Status Register */
+#define PIO_IFER       0x20    /* Glitch Input Filter Enable */
+#define PIO_IFDR       0x24    /* Glitch Input Filter Disable */
+#define PIO_IFSR       0x28    /* Glitch Input Filter Status */
+#define PIO_SODR       0x30    /* Set Output Data Register */
+#define PIO_CODR       0x34    /* Clear Output Data Register */
+#define PIO_ODSR       0x38    /* Output Data Status Register */
+#define PIO_PDSR       0x3c    /* Pin Data Status Register */
+#define PIO_IER                0x40    /* Interrupt Enable Register */
+#define PIO_IDR                0x44    /* Interrupt Disable Register */
+#define PIO_IMR                0x48    /* Interrupt Mask Register */
+#define PIO_ISR                0x4c    /* Interrupt Status Register */
+#define PIO_MDER       0x50    /* Multi-driver Enable Register */
+#define PIO_MDDR       0x54    /* Multi-driver Disable Register */
+#define PIO_MDSR       0x58    /* Multi-driver Status Register */
+#define PIO_PUDR       0x60    /* Pull-up Disable Register */
+#define PIO_PUER       0x64    /* Pull-up Enable Register */
+#define PIO_PUSR       0x68    /* Pull-up Status Register */
+#define PIO_ASR                0x70    /* Peripheral A Select Register */
+#define PIO_BSR                0x74    /* Peripheral B Select Register */
+#define PIO_ABSR       0x78    /* AB Status Register */
+#define PIO_OWER       0xa0    /* Output Write Enable Register */
+#define PIO_OWDR       0xa4    /* Output Write Disable Register */
+#define PIO_OWSR       0xa8    /* Output Write Status Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pit.h b/include/asm-arm/arch-at91rm9200/at91_pit.h
new file mode 100644 (file)
index 0000000..4a30d00
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_pit.h
+ *
+ * Periodic Interval Timer (PIT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_PIT_H
+#define AT91_PIT_H
+
+#define AT91_PIT_MR            (AT91_PIT + 0x00)       /* Mode Register */
+#define                AT91_PIT_PITIEN         (1 << 25)               /* Timer Interrupt Enable */
+#define                AT91_PIT_PITEN          (1 << 24)               /* Timer Enabled */
+#define                AT91_PIT_PIV            (0xfffff)               /* Periodic Interval Value */
+
+#define AT91_PIT_SR            (AT91_PIT + 0x04)       /* Status Register */
+#define                AT91_PIT_PITS           (1 << 0)                /* Timer Status */
+
+#define AT91_PIT_PIVR          (AT91_PIT + 0x08)       /* Periodic Interval Value Register */
+#define AT91_PIT_PIIR          (AT91_PIT + 0x0c)       /* Periodic Interval Image Register */
+#define                AT91_PIT_PICNT          (0xfff << 20)           /* Interval Counter */
+#define                AT91_PIT_CPIV           (0xfffff)               /* Inverval Value */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91rm9200/at91_pmc.h
new file mode 100644 (file)
index 0000000..de8c3da
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_pmc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Power Management Controller (PMC) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_PMC_H
+#define AT91_PMC_H
+
+#define        AT91_PMC_SCER           (AT91_PMC + 0x00)       /* System Clock Enable Register */
+#define        AT91_PMC_SCDR           (AT91_PMC + 0x04)       /* System Clock Disable Register */
+
+#define        AT91_PMC_SCSR           (AT91_PMC + 0x08)       /* System Clock Status Register */
+#define                AT91_PMC_PCK            (1 <<  0)               /* Processor Clock */
+#define                AT91RM9200_PMC_UDP      (1 <<  1)               /* USB Devcice Port Clock [AT91RM9200 only] */
+#define                AT91RM9200_PMC_MCKUDP   (1 <<  2)               /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
+#define                AT91RM9200_PMC_UHP      (1 <<  4)               /* USB Host Port Clock [AT91RM9200 only] */
+#define                AT91SAM926x_PMC_UHP     (1 <<  6)               /* USB Host Port Clock [AT91SAM926x only] */
+#define                AT91SAM926x_PMC_UDP     (1 <<  7)               /* USB Devcice Port Clock [AT91SAM926x only] */
+#define                AT91_PMC_PCK0           (1 <<  8)               /* Programmable Clock 0 */
+#define                AT91_PMC_PCK1           (1 <<  9)               /* Programmable Clock 1 */
+#define                AT91_PMC_PCK2           (1 << 10)               /* Programmable Clock 2 */
+#define                AT91_PMC_PCK3           (1 << 11)               /* Programmable Clock 3 */
+#define                AT91_PMC_HCK0           (1 << 16)               /* AHB Clock (USB host) [AT91SAM9261 only] */
+#define                AT91_PMC_HCK1           (1 << 17)               /* AHB Clock (LCD) [AT91SAM9261 only] */
+
+#define        AT91_PMC_PCER           (AT91_PMC + 0x10)       /* Peripheral Clock Enable Register */
+#define        AT91_PMC_PCDR           (AT91_PMC + 0x14)       /* Peripheral Clock Disable Register */
+#define        AT91_PMC_PCSR           (AT91_PMC + 0x18)       /* Peripheral Clock Status Register */
+
+#define        AT91_CKGR_MOR           (AT91_PMC + 0x20)       /* Main Oscillator Register */
+#define                AT91_PMC_MOSCEN         (1    << 0)             /* Main Oscillator Enable */
+#define                AT91_PMC_OSCBYPASS      (1    << 1)             /* Oscillator Bypass [AT91SAM926x only] */
+#define                AT91_PMC_OSCOUNT        (0xff << 8)             /* Main Oscillator Start-up Time */
+
+#define        AT91_CKGR_MCFR          (AT91_PMC + 0x24)       /* Main Clock Frequency Register */
+#define                AT91_PMC_MAINF          (0xffff <<  0)          /* Main Clock Frequency */
+#define                AT91_PMC_MAINRDY        (1      << 16)          /* Main Clock Ready */
+
+#define        AT91_CKGR_PLLAR         (AT91_PMC + 0x28)       /* PLL A Register */
+#define        AT91_CKGR_PLLBR         (AT91_PMC + 0x2c)       /* PLL B Register */
+#define                AT91_PMC_DIV            (0xff  <<  0)           /* Divider */
+#define                AT91_PMC_PLLCOUNT       (0x3f  <<  8)           /* PLL Counter */
+#define                AT91_PMC_OUT            (3     << 14)           /* PLL Clock Frequency Range */
+#define                AT91_PMC_MUL            (0x7ff << 16)           /* PLL Multiplier */
+#define                AT91_PMC_USB96M         (1     << 28)           /* Divider by 2 Enable (PLLB only) */
+
+#define        AT91_PMC_MCKR           (AT91_PMC + 0x30)       /* Master Clock Register */
+#define                AT91_PMC_CSS            (3 <<  0)               /* Master Clock Selection */
+#define                        AT91_PMC_CSS_SLOW               (0 << 0)
+#define                        AT91_PMC_CSS_MAIN               (1 << 0)
+#define                        AT91_PMC_CSS_PLLA               (2 << 0)
+#define                        AT91_PMC_CSS_PLLB               (3 << 0)
+#define                AT91_PMC_PRES           (7 <<  2)               /* Master Clock Prescaler */
+#define                AT91_PMC_PRES_1                 (0 << 2)
+#define                        AT91_PMC_PRES_2                 (1 << 2)
+#define                        AT91_PMC_PRES_4                 (2 << 2)
+#define                        AT91_PMC_PRES_8                 (3 << 2)
+#define                        AT91_PMC_PRES_16                (4 << 2)
+#define                        AT91_PMC_PRES_32                (5 << 2)
+#define                        AT91_PMC_PRES_64                (6 << 2)
+#define                AT91_PMC_MDIV           (3 <<  8)               /* Master Clock Division */
+#define                        AT91_PMC_MDIV_1                 (0 << 8)
+#define                        AT91_PMC_MDIV_2                 (1 << 8)
+#define                        AT91_PMC_MDIV_3                 (2 << 8)
+#define                        AT91_PMC_MDIV_4                 (3 << 8)
+
+#define        AT91_PMC_PCKR(n)        (AT91_PMC + 0x40 + ((n) * 4))   /* Programmable Clock 0-3 Registers */
+
+#define        AT91_PMC_IER            (AT91_PMC + 0x60)       /* Interrupt Enable Register */
+#define        AT91_PMC_IDR            (AT91_PMC + 0x64)       /* Interrupt Disable Register */
+#define        AT91_PMC_SR             (AT91_PMC + 0x68)       /* Status Register */
+#define                AT91_PMC_MOSCS          (1 <<  0)               /* MOSCS Flag */
+#define                AT91_PMC_LOCKA          (1 <<  1)               /* PLLA Lock */
+#define                AT91_PMC_LOCKB          (1 <<  2)               /* PLLB Lock */
+#define                AT91_PMC_MCKRDY         (1 <<  3)               /* Master Clock */
+#define                AT91_PMC_PCK0RDY        (1 <<  8)               /* Programmable Clock 0 */
+#define                AT91_PMC_PCK1RDY        (1 <<  9)               /* Programmable Clock 1 */
+#define                AT91_PMC_PCK2RDY        (1 << 10)               /* Programmable Clock 2 */
+#define                AT91_PMC_PCK3RDY        (1 << 11)               /* Programmable Clock 3 */
+#define        AT91_PMC_IMR            (AT91_PMC + 0x6c)       /* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91rm9200/at91_rstc.h
new file mode 100644 (file)
index 0000000..ccdc52d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_rstc.h
+ *
+ * Reset Controller (RSTC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_RSTC_H
+#define AT91_RSTC_H
+
+#define AT91_RSTC_CR           (AT91_RSTC + 0x00)      /* Reset Controller Control Register */
+#define                AT91_RSTC_PROCRST       (1 << 0)                /* Processor Reset */
+#define                AT91_RSTC_PERRST        (1 << 2)                /* Peripheral Reset */
+#define                AT91_RSTC_EXTRST        (1 << 3)                /* External Reset */
+#define                AT01_RSTC_KEY           (0xff << 24)            /* KEY Password */
+
+#define AT91_RSTC_SR           (AT91_RSTC + 0x04)      /* Reset Controller Status Register */
+#define                AT91_RSTC_URSTS         (1 << 0)                /* User Reset Status */
+#define                AT91_RSTC_RSTTYP        (7 << 8)                /* Reset Type */
+#define                        AT91_RSTC_RSTTYP_GENERAL        (0 << 8)
+#define                        AT91_RSTC_RSTTYP_WAKEUP         (1 << 8)
+#define                        AT91_RSTC_RSTTYP_WATCHDOG       (2 << 8)
+#define                        AT91_RSTC_RSTTYP_SOFTWARE       (3 << 8)
+#define                        AT91_RSTC_RSTTYP_USER   (4 << 8)
+#define                AT91_RSTC_NRSTL         (1 << 16)               /* NRST Pin Level */
+#define                AT91_RSTC_SRCMP         (1 << 17)               /* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR           (AT91_RSTC + 0x08)      /* Reset Controller Mode Register */
+#define                AT91_RSTC_URSTEN        (1 << 0)                /* User Reset Enable */
+#define                AT91_RSTC_URSTIEN       (1 << 4)                /* User Reset Interrupt Enable */
+#define                AT91_RSTC_ERSTL         (0xf << 8)              /* External Reset Length */
+#define                AT91_RSTC_KEY           (0xff << 24)            /* KEY Password */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91rm9200/at91_rtc.h
new file mode 100644 (file)
index 0000000..6e5065d
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_rtc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Real Time Clock (RTC) - System peripheral registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_RTC_H
+#define AT91_RTC_H
+
+#define        AT91_RTC_CR             (AT91_RTC + 0x00)       /* Control Register */
+#define                AT91_RTC_UPDTIM         (1 <<  0)               /* Update Request Time Register */
+#define                AT91_RTC_UPDCAL         (1 <<  1)               /* Update Request Calendar Register */
+#define                AT91_RTC_TIMEVSEL       (3 <<  8)               /* Time Event Selection */
+#define                        AT91_RTC_TIMEVSEL_MINUTE        (0 << 8)
+#define                AT91_RTC_TIMEVSEL_HOUR          (1 << 8)
+#define                AT91_RTC_TIMEVSEL_DAY24         (2 << 8)
+#define                AT91_RTC_TIMEVSEL_DAY12         (3 << 8)
+#define                AT91_RTC_CALEVSEL       (3 << 16)               /* Calendar Event Selection */
+#define                AT91_RTC_CALEVSEL_WEEK          (0 << 16)
+#define                AT91_RTC_CALEVSEL_MONTH         (1 << 16)
+#define                AT91_RTC_CALEVSEL_YEAR          (2 << 16)
+
+#define        AT91_RTC_MR             (AT91_RTC + 0x04)       /* Mode Register */
+#define        AT91_RTC_HRMOD          (1 <<  0)               /* 12/24 Hour Mode */
+
+#define        AT91_RTC_TIMR           (AT91_RTC + 0x08)       /* Time Register */
+#define                AT91_RTC_SEC            (0x7f <<  0)            /* Current Second */
+#define                AT91_RTC_MIN            (0x7f <<  8)            /* Current Minute */
+#define                AT91_RTC_HOUR           (0x3f << 16)            /* Current Hour */
+#define                AT91_RTC_AMPM           (1    << 22)            /* Ante Meridiem Post Meridiem Indicator */
+
+#define        AT91_RTC_CALR           (AT91_RTC + 0x0c)       /* Calendar Register */
+#define                AT91_RTC_CENT           (0x7f <<  0)            /* Current Century */
+#define                AT91_RTC_YEAR           (0xff <<  8)            /* Current Year */
+#define                AT91_RTC_MONTH          (0x1f << 16)            /* Current Month */
+#define                AT91_RTC_DAY            (7    << 21)            /* Current Day */
+#define                AT91_RTC_DATE           (0x3f << 24)            /* Current Date */
+
+#define        AT91_RTC_TIMALR         (AT91_RTC + 0x10)       /* Time Alarm Register */
+#define                AT91_RTC_SECEN          (1 <<  7)               /* Second Alarm Enable */
+#define                AT91_RTC_MINEN          (1 << 15)               /* Minute Alarm Enable */
+#define                AT91_RTC_HOUREN         (1 << 23)               /* Hour Alarm Enable */
+
+#define        AT91_RTC_CALALR         (AT91_RTC + 0x14)       /* Calendar Alarm Register */
+#define                AT91_RTC_MTHEN          (1 << 23)               /* Month Alarm Enable */
+#define                AT91_RTC_DATEEN         (1 << 31)               /* Date Alarm Enable */
+
+#define        AT91_RTC_SR             (AT91_RTC + 0x18)       /* Status Register */
+#define                AT91_RTC_ACKUPD         (1 <<  0)               /* Acknowledge for Update */
+#define                AT91_RTC_ALARM          (1 <<  1)               /* Alarm Flag */
+#define                AT91_RTC_SECEV          (1 <<  2)               /* Second Event */
+#define                AT91_RTC_TIMEV          (1 <<  3)               /* Time Event */
+#define                AT91_RTC_CALEV          (1 <<  4)               /* Calendar Event */
+
+#define        AT91_RTC_SCCR           (AT91_RTC + 0x1c)       /* Status Clear Command Register */
+#define        AT91_RTC_IER            (AT91_RTC + 0x20)       /* Interrupt Enable Register */
+#define        AT91_RTC_IDR            (AT91_RTC + 0x24)       /* Interrupt Disable Register */
+#define        AT91_RTC_IMR            (AT91_RTC + 0x28)       /* Interrupt Mask Register */
+
+#define        AT91_RTC_VER            (AT91_RTC + 0x2c)       /* Valid Entry Register */
+#define                AT91_RTC_NVTIM          (1 <<  0)               /* Non valid Time */
+#define                AT91_RTC_NVCAL          (1 <<  1)               /* Non valid Calendar */
+#define                AT91_RTC_NVTIMALR       (1 <<  2)               /* Non valid Time Alarm */
+#define                AT91_RTC_NVCALALR       (1 <<  3)               /* Non valid Calendar Alarm */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtt.h b/include/asm-arm/arch-at91rm9200/at91_rtt.h
new file mode 100644 (file)
index 0000000..c6751ba
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_rtt.h
+ *
+ * Real-time Timer (RTT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_RTT_H
+#define AT91_RTT_H
+
+#define AT91_RTT_MR            (AT91_RTT + 0x00)       /* Real-time Mode Register */
+#define                AT91_RTT_RTPRES         (0xffff << 0)           /* Real-time Timer Prescaler Value */
+#define                AT91_RTT_ALMIEN         (1 << 16)               /* Alarm Interrupt Enable */
+#define                AT91_RTT_RTTINCIEN      (1 << 17)               /* Real Time Timer Increment Interrupt Enable */
+#define                AT91_RTT_RTTRST         (1 << 18)               /* Real Time Timer Restart */
+
+#define AT91_RTT_AR            (AT91_RTT + 0x04)       /* Real-time Alarm Register */
+#define                AT91_RTT_ALMV           (0xffffffff)            /* Alarm Value */
+
+#define AT91_RTT_VR            (AT91_RTT + 0x08)       /* Real-time Value Register */
+#define                AT91_RTT_CRTV           (0xffffffff)            /* Current Real-time Value */
+
+#define AT91_RTT_SR            (AT91_RTT + 0x0c)       /* Real-time Status Register */
+#define                AT91_RTT_ALMS           (1 << 0)                /* Real-time Alarm Status */
+#define                AT91_RTT_RTTINC         (1 << 1)                /* Real-time Timer Increment */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_shdwc.h b/include/asm-arm/arch-at91rm9200/at91_shdwc.h
new file mode 100644 (file)
index 0000000..0439250
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_shdwc.h
+ *
+ * Shutdown Controller (SHDWC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_SHDWC_H
+#define AT91_SHDWC_H
+
+#define AT91_SHDW_CR           (AT91_SHDWC + 0x00)     /* Shut Down Control Register */
+#define                AT91_SHDW_SHDW          (1    << 0)             /* Processor Reset */
+#define                AT91_SHDW_KEY           (0xff << 24)            /* KEY Password */
+
+#define AT91_SHDW_MR           (AT91_SHDWC + 0x04)     /* Shut Down Mode Register */
+#define                AT91_SHDW_WKMODE0       (3 << 0)                /* Wake-up 0 Mode Selection */
+#define                        AT91_SHDW_WKMODE0_NONE          0
+#define                        AT91_SHDW_WKMODE0_HIGH          1
+#define                        AT91_SHDW_WKMODE0_LOW           2
+#define                        AT91_SHDW_WKMODE0_ANYLEVEL      3
+#define                AT91_SHDW_CPTWK0        (0xf << 4)              /* Counter On Wake Up 0 */
+#define                AT91_SHDW_RTTWKEN       (1   << 16)             /* Real Time Timer Wake-up Enable */
+
+#define AT91_SHDW_SR           (AT91_SHDWC + 0x08)     /* Shut Down Status Register */
+#define                AT91_SHDW_WAKEUP0       (1 <<  0)               /* Wake-up 0 Status */
+#define                AT91_SHDW_RTTWK         (1 << 16)               /* Real-time Timer Wake-up */
+
+#endif
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
+ * include/asm-arm/arch-at91rm9200/at91_spi.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -13,8 +13,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_SPI_H
-#define AT91RM9200_SPI_H
+#ifndef AT91_SPI_H
+#define AT91_SPI_H
 
 #define AT91_SPI_CR                    0x00            /* Control Register */
 #define                AT91_SPI_SPIEN          (1 <<  0)               /* SPI Enable */
@@ -28,7 +28,7 @@
 #define                        AT91_SPI_PS_FIXED       (0 << 1)
 #define                        AT91_SPI_PS_VARIABLE    (1 << 1)
 #define                AT91_SPI_PCSDEC         (1    <<  2)            /* Chip Select Decode */
-#define                AT91_SPI_DIV32          (1    <<  3)            /* Clock Selection */
+#define                AT91_SPI_DIV32          (1    <<  3)            /* Clock Selection [AT91RM9200 only] */
 #define                AT91_SPI_MODFDIS        (1    <<  4)            /* Mode Fault Detection */
 #define                AT91_SPI_LLB            (1    <<  7)            /* Local Loopback Enable */
 #define                AT91_SPI_PCS            (0xf  << 16)            /* Peripheral Chip Select */
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
+ * include/asm-arm/arch-at91rm9200/at91_ssc.h
  *
  * Copyright (C) SAN People
  *
@@ -12,8 +12,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_SSC_H
-#define AT91RM9200_SSC_H
+#ifndef AT91_SSC_H
+#define AT91_SSC_H
 
 #define AT91_SSC_CR            0x00    /* Control Register */
 #define                AT91_SSC_RXEN           (1 <<  0)       /* Receive Enable */
 #define                AT91_SSC_CKI            (1    <<  5)    /* Clock Inversion */
 #define                        AT91_SSC_CKI_FALLING            (0 << 5)
 #define                        AT91_SSC_CK_RISING              (1 << 5)
+#define                AT91_SSC_CKG            (1    <<  6)    /* Receive Clock Gating Selection [AT91SAM9261 only] */
+#define                        AT91_SSC_CKG_NONE               (0 << 6)
+#define                        AT91_SSC_CKG_RFLOW              (1 << 6)
+#define                        AT91_SSC_CKG_RFHIGH             (2 << 6)
 #define                AT91_SSC_START          (0xf  <<  8)    /* Start Selection */
 #define                        AT91_SSC_START_CONTINUOUS       (0 << 8)
 #define                        AT91_SSC_START_TX_RX            (1 << 8)
@@ -45,6 +49,7 @@
 #define                        AT91_SSC_START_RISING_RF        (5 << 8)
 #define                        AT91_SSC_START_LEVEL_RF         (6 << 8)
 #define                        AT91_SSC_START_EDGE_RF          (7 << 8)
+#define                AT91_SSC_STOP           (1    << 12)    /* Receive Stop Selection [AT91SAM9261 only] */
 #define                AT91_SSC_STTDLY         (0xff << 16)    /* Start Delay */
 #define                AT91_SSC_PERIOD         (0xff << 24)    /* Period Divider Selection */
 
@@ -75,6 +80,9 @@
 #define AT91_SSC_RSHR          0x30    /* Receive Sync Holding Register */
 #define AT91_SSC_TSHR          0x34    /* Transmit Sync Holding Register */
 
+#define AT91_SSC_RC0R          0x38    /* Receive Compare 0 Register [AT91SAM9261 only] */
+#define AT91_SSC_RC1R          0x3c    /* Receive Compare 1 Register [AT91SAM9261 only] */
+
 #define AT91_SSC_SR            0x40    /* Status Register */
 #define                AT91_SSC_TXRDY          (1 <<  0)       /* Transmit Ready */
 #define                AT91_SSC_TXEMPTY        (1 <<  1)       /* Transmit Empty */
@@ -84,6 +92,8 @@
 #define                AT91_SSC_OVRUN          (1 <<  5)       /* Receive Overrun */
 #define                AT91_SSC_ENDRX          (1 <<  6)       /* End of Reception */
 #define                AT91_SSC_RXBUFF         (1 <<  7)       /* Receive Buffer Full */
+#define                AT91_SSC_CP0            (1 <<  8)       /* Compare 0 [AT91SAM9261 only] */
+#define                AT91_SSC_CP1            (1 <<  9)       /* Compare 1 [AT91SAM9261 only] */
 #define                AT91_SSC_TXSYN          (1 << 10)       /* Transmit Sync */
 #define                AT91_SSC_RXSYN          (1 << 11)       /* Receive Sync */
 #define                AT91_SSC_TXENA          (1 << 16)       /* Transmit Enable */
diff --git a/include/asm-arm/arch-at91rm9200/at91_st.h b/include/asm-arm/arch-at91rm9200/at91_st.h
new file mode 100644 (file)
index 0000000..2432ddf
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_st.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * System Timer (ST) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_ST_H
+#define AT91_ST_H
+
+#define        AT91_ST_CR              (AT91_ST + 0x00)        /* Control Register */
+#define        AT91_ST_WDRST           (1 << 0)                /* Watchdog Timer Restart */
+
+#define        AT91_ST_PIMR            (AT91_ST + 0x04)        /* Period Interval Mode Register */
+#define                AT91_ST_PIV             (0xffff <<  0)          /* Period Interval Value */
+
+#define        AT91_ST_WDMR            (AT91_ST + 0x08)        /* Watchdog Mode Register */
+#define                AT91_ST_WDV             (0xffff <<  0)          /* Watchdog Counter Value */
+#define                AT91_ST_RSTEN           (1      << 16)          /* Reset Enable */
+#define                AT91_ST_EXTEN           (1      << 17)          /* External Signal Assertion Enable */
+
+#define        AT91_ST_RTMR            (AT91_ST + 0x0c)        /* Real-time Mode Register */
+#define                AT91_ST_RTPRES          (0xffff <<  0)          /* Real-time Prescalar Value */
+
+#define        AT91_ST_SR              (AT91_ST + 0x10)        /* Status Register */
+#define                AT91_ST_PITS            (1 << 0)                /* Period Interval Timer Status */
+#define                AT91_ST_WDOVF           (1 << 1)                /* Watchdog Overflow */
+#define                AT91_ST_RTTINC          (1 << 2)                /* Real-time Timer Increment */
+#define                AT91_ST_ALMS            (1 << 3)                /* Alarm Status */
+
+#define        AT91_ST_IER             (AT91_ST + 0x14)        /* Interrupt Enable Register */
+#define        AT91_ST_IDR             (AT91_ST + 0x18)        /* Interrupt Disable Register */
+#define        AT91_ST_IMR             (AT91_ST + 0x1c)        /* Interrupt Mask Register */
+
+#define        AT91_ST_RTAR            (AT91_ST + 0x20)        /* Real-time Alarm Register */
+#define                AT91_ST_ALMV            (0xfffff << 0)          /* Alarm Value */
+
+#define        AT91_ST_CRTR            (AT91_ST + 0x24)        /* Current Real-time Register */
+#define                AT91_ST_CRTV            (0xfffff << 0)          /* Current Real-Time Value */
+
+#endif
similarity index 98%
rename from include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
rename to include/asm-arm/arch-at91rm9200/at91_tc.h
index f4da752..8d06eb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
+ * include/asm-arm/arch-at91rm9200/at91_tc.h
  *
  * Copyright (C) SAN People
  *
@@ -12,8 +12,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_TC_H
-#define AT91RM9200_TC_H
+#ifndef AT91_TC_H
+#define AT91_TC_H
 
 #define AT91_TC_BCR            0xc0            /* TC Block Control Register */
 #define                AT91_TC_SYNC            (1 << 0)        /* Synchro Command */
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
+ * include/asm-arm/arch-at91rm9200/at91_twi.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -13,8 +13,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_TWI_H
-#define AT91RM9200_TWI_H
+#ifndef AT91_TWI_H
+#define AT91_TWI_H
 
 #define        AT91_TWI_CR             0x00            /* Control Register */
 #define                AT91_TWI_START          (1 <<  0)       /* Send a Start Condition */
@@ -43,8 +43,8 @@
 #define                AT91_TWI_TXCOMP         (1 <<  0)       /* Transmission Complete */
 #define                AT91_TWI_RXRDY          (1 <<  1)       /* Receive Holding Register Ready */
 #define                AT91_TWI_TXRDY          (1 <<  2)       /* Transmit Holding Register Ready */
-#define                AT91_TWI_OVRE           (1 <<  6)       /* Overrun Error */
-#define                AT91_TWI_UNRE           (1 <<  7)       /* Underrun Error */
+#define                AT91_TWI_OVRE           (1 <<  6)       /* Overrun Error [AT91RM9200 only] */
+#define                AT91_TWI_UNRE           (1 <<  7)       /* Underrun Error [AT91RM9200 only] */
 #define                AT91_TWI_NACK           (1 <<  8)       /* Not Acknowledged */
 
 #define        AT91_TWI_IER            0x24            /* Interrupt Enable Register */
diff --git a/include/asm-arm/arch-at91rm9200/at91_wdt.h b/include/asm-arm/arch-at91rm9200/at91_wdt.h
new file mode 100644 (file)
index 0000000..ac63e77
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91_wdt.h
+ *
+ * Watchdog Timer (WDT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_WDT_H
+#define AT91_WDT_H
+
+#define AT91_WDT_CR            (AT91_WDT + 0x00)       /* Watchdog Control Register */
+#define                AT91_WDT_WDRSTT         (1    << 0)             /* Restart */
+#define                AT91_WDT_KEY            (0xff << 24)            /* KEY Password */
+
+#define AT91_WDT_MR            (AT91_WDT + 0x04)       /* Watchdog Mode Register */
+#define                AT91_WDT_WDV            (0xfff << 0)            /* Counter Value */
+#define                AT91_WDT_WDFIEN         (1     << 12)           /* Fault Interrupt Enable */
+#define                AT91_WDT_WDRSTEN        (1     << 13)           /* Reset Processor */
+#define                AT91_WDT_WDRPROC        (1     << 14)           /* Timer Restart */
+#define                AT91_WDT_WDDIS          (1     << 15)           /* Watchdog Disable */
+#define                AT91_WDT_WDD            (0xfff << 16)           /* Delta Value */
+#define                AT91_WDT_WDDBGHLT       (1     << 28)           /* Debug Halt */
+#define                AT91_WDT_WDIDLEHLT      (1     << 29)           /* Idle Halt */
+
+#define AT91_WDT_SR            (AT91_WDT + 0x08)       /* Watchdog Status Register */
+#define                AT91_WDT_WDUNF          (1 << 0)                /* Watchdog Underflow */
+#define                AT91_WDT_WDERR          (1 << 1)                /* Watchdog Error */
+
+#endif
index a5a86b1..4d51177 100644 (file)
 #define AT91_BASE_SYS          0xfffff000
 
 
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)    /* Advanced Interrupt Controller */
+#define AT91_DBGU      (0xfffff200 - AT91_BASE_SYS)    /* Debug Unit */
+#define AT91_PIOA      (0xfffff400 - AT91_BASE_SYS)    /* PIO Controller A */
+#define AT91_PIOB      (0xfffff600 - AT91_BASE_SYS)    /* PIO Controller B */
+#define AT91_PIOC      (0xfffff800 - AT91_BASE_SYS)    /* PIO Controller C */
+#define AT91_PIOD      (0xfffffa00 - AT91_BASE_SYS)    /* PIO Controller D */
+#define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)    /* Power Management Controller */
+#define AT91_ST                (0xfffffd00 - AT91_BASE_SYS)    /* System Timer */
+#define AT91_RTC       (0xfffffe00 - AT91_BASE_SYS)    /* Real-Time Clock */
+#define AT91_MC                (0xffffff00 - AT91_BASE_SYS)    /* Memory Controllers */
+
+#define AT91_MATRIX    0       /* not supported */
+
 /*
  * Internal Memory.
  */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
new file mode 100644 (file)
index 0000000..0c0d814
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_MC_H
+#define AT91RM9200_MC_H
+
+/* Memory Controller */
+#define AT91_MC_RCR            (AT91_MC + 0x00)        /* MC Remap Control Register */
+#define                AT91_MC_RCB             (1 <<  0)               /* Remap Command Bit */
+
+#define AT91_MC_ASR            (AT91_MC + 0x04)        /* MC Abort Status Register */
+#define                AT91_MC_UNADD           (1 <<  0)               /* Undefined Address Abort Status */
+#define                AT91_MC_MISADD          (1 <<  1)               /* Misaligned Address Abort Status */
+#define                AT91_MC_ABTSZ           (3 <<  8)               /* Abort Size Status */
+#define                        AT91_MC_ABTSZ_BYTE              (0 << 8)
+#define                        AT91_MC_ABTSZ_HALFWORD          (1 << 8)
+#define                        AT91_MC_ABTSZ_WORD              (2 << 8)
+#define                AT91_MC_ABTTYP          (3 << 10)               /* Abort Type Status */
+#define                        AT91_MC_ABTTYP_DATAREAD         (0 << 10)
+#define                        AT91_MC_ABTTYP_DATAWRITE        (1 << 10)
+#define                        AT91_MC_ABTTYP_FETCH            (2 << 10)
+#define                AT91_MC_MST0            (1 << 16)               /* ARM920T Abort Source */
+#define                AT91_MC_MST1            (1 << 17)               /* PDC Abort Source */
+#define                AT91_MC_MST2            (1 << 18)               /* UHP Abort Source */
+#define                AT91_MC_MST3            (1 << 19)               /* EMAC Abort Source */
+#define                AT91_MC_SVMST0          (1 << 24)               /* Saved ARM920T Abort Source */
+#define                AT91_MC_SVMST1          (1 << 25)               /* Saved PDC Abort Source */
+#define                AT91_MC_SVMST2          (1 << 26)               /* Saved UHP Abort Source */
+#define                AT91_MC_SVMST3          (1 << 27)               /* Saved EMAC Abort Source */
+
+#define AT91_MC_AASR           (AT91_MC + 0x08)        /* MC Abort Address Status Register */
+
+#define AT91_MC_MPR            (AT91_MC + 0x0c)        /* MC Master Priority Register */
+#define                AT91_MPR_MSTP0          (7 <<  0)               /* ARM920T Priority */
+#define                AT91_MPR_MSTP1          (7 <<  4)               /* PDC Priority */
+#define                AT91_MPR_MSTP2          (7 <<  8)               /* UHP Priority */
+#define                AT91_MPR_MSTP3          (7 << 12)               /* EMAC Priority */
+
+/* External Bus Interface (EBI) registers */
+#define AT91_EBI_CSA           (AT91_MC + 0x60)        /* Chip Select Assignment Register */
+#define                AT91_EBI_CS0A           (1 << 0)                /* Chip Select 0 Assignment */
+#define                        AT91_EBI_CS0A_SMC               (0 << 0)
+#define                        AT91_EBI_CS0A_BFC               (1 << 0)
+#define                AT91_EBI_CS1A           (1 << 1)                /* Chip Select 1 Assignment */
+#define                        AT91_EBI_CS1A_SMC               (0 << 1)
+#define                        AT91_EBI_CS1A_SDRAMC            (1 << 1)
+#define                AT91_EBI_CS3A           (1 << 3)                /* Chip Select 2 Assignment */
+#define                        AT91_EBI_CS3A_SMC               (0 << 3)
+#define                        AT91_EBI_CS3A_SMC_SMARTMEDIA    (1 << 3)
+#define                AT91_EBI_CS4A           (1 << 4)                /* Chip Select 3 Assignment */
+#define                        AT91_EBI_CS4A_SMC               (0 << 4)
+#define                        AT91_EBI_CS4A_SMC_COMPACTFLASH  (1 << 4)
+#define AT91_EBI_CFGR          (AT91_MC + 0x64)        /* Configuration Register */
+#define                AT91_EBI_DBPUC          (1 << 0)                /* Data Bus Pull-Up Configuration */
+
+/* Static Memory Controller (SMC) registers */
+#define        AT91_SMC_CSR(n)         (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
+#define                AT91_SMC_NWS            (0x7f <<  0)            /* Number of Wait States */
+#define                        AT91_SMC_NWS_(x)        ((x) << 0)
+#define                AT91_SMC_WSEN           (1    <<  7)            /* Wait State Enable */
+#define                AT91_SMC_TDF            (0xf  <<  8)            /* Data Float Time */
+#define                        AT91_SMC_TDF_(x)        ((x) << 8)
+#define                AT91_SMC_BAT            (1    << 12)            /* Byte Access Type */
+#define                AT91_SMC_DBW            (3    << 13)            /* Data Bus Width */
+#define                        AT91_SMC_DBW_16         (1 << 13)
+#define                        AT91_SMC_DBW_8          (2 << 13)
+#define                AT91_SMC_DPR            (1 << 15)               /* Data Read Protocol */
+#define                AT91_SMC_ACSS           (3 << 16)               /* Address to Chip Select Setup */
+#define                        AT91_SMC_ACSS_STD       (0 << 16)
+#define                        AT91_SMC_ACSS_1         (1 << 16)
+#define                        AT91_SMC_ACSS_2         (2 << 16)
+#define                        AT91_SMC_ACSS_3         (3 << 16)
+#define                AT91_SMC_RWSETUP        (7 << 24)               /* Read & Write Signal Time Setup */
+#define                        AT91_SMC_RWSETUP_(x)    ((x) << 24)
+#define                AT91_SMC_RWHOLD         (7 << 28)               /* Read & Write Signal Hold Time */
+#define                        AT91_SMC_RWHOLD_(x)     ((x) << 28)
+
+/* SDRAM Controller registers */
+#define AT91_SDRAMC_MR         (AT91_MC + 0x90)        /* Mode Register */
+#define                AT91_SDRAMC_MODE        (0xf << 0)              /* Command Mode */
+#define                        AT91_SDRAMC_MODE_NORMAL         (0 << 0)
+#define                        AT91_SDRAMC_MODE_NOP            (1 << 0)
+#define                        AT91_SDRAMC_MODE_PRECHARGE      (2 << 0)
+#define                        AT91_SDRAMC_MODE_LMR            (3 << 0)
+#define                        AT91_SDRAMC_MODE_REFRESH        (4 << 0)
+#define                AT91_SDRAMC_DBW         (1   << 4)              /* Data Bus Width */
+#define                        AT91_SDRAMC_DBW_32      (0 << 4)
+#define                        AT91_SDRAMC_DBW_16      (1 << 4)
+
+#define AT91_SDRAMC_TR         (AT91_MC + 0x94)        /* Refresh Timer Register */
+#define                AT91_SDRAMC_COUNT       (0xfff << 0)            /* Refresh Timer Count */
+
+#define AT91_SDRAMC_CR         (AT91_MC + 0x98)        /* Configuration Register */
+#define                AT91_SDRAMC_NC          (3   <<  0)             /* Number of Column Bits */
+#define                        AT91_SDRAMC_NC_8        (0 << 0)
+#define                        AT91_SDRAMC_NC_9        (1 << 0)
+#define                        AT91_SDRAMC_NC_10       (2 << 0)
+#define                        AT91_SDRAMC_NC_11       (3 << 0)
+#define                AT91_SDRAMC_NR          (3   <<  2)             /* Number of Row Bits */
+#define                        AT91_SDRAMC_NR_11       (0 << 2)
+#define                        AT91_SDRAMC_NR_12       (1 << 2)
+#define                        AT91_SDRAMC_NR_13       (2 << 2)
+#define                AT91_SDRAMC_NB          (1   <<  4)             /* Number of Banks */
+#define                        AT91_SDRAMC_NB_2        (0 << 4)
+#define                        AT91_SDRAMC_NB_4        (1 << 4)
+#define                AT91_SDRAMC_CAS         (3   <<  5)             /* CAS Latency */
+#define                        AT91_SDRAMC_CAS_2       (2 << 5)
+#define                AT91_SDRAMC_TWR         (0xf <<  7)             /* Write Recovery Delay */
+#define                AT91_SDRAMC_TRC         (0xf << 11)             /* Row Cycle Delay */
+#define                AT91_SDRAMC_TRP         (0xf << 15)             /* Row Precharge Delay */
+#define                AT91_SDRAMC_TRCD        (0xf << 19)             /* Row to Column Delay */
+#define                AT91_SDRAMC_TRAS        (0xf << 23)             /* Active to Precharge Delay */
+#define                AT91_SDRAMC_TXSR        (0xf << 27)             /* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_SRR                (AT91_MC + 0x9c)        /* Self Refresh Register */
+#define AT91_SDRAMC_LPR                (AT91_MC + 0xa0)        /* Low Power Register */
+#define AT91_SDRAMC_IER                (AT91_MC + 0xa4)        /* Interrupt Enable Register */
+#define AT91_SDRAMC_IDR                (AT91_MC + 0xa8)        /* Interrupt Disable Register */
+#define AT91_SDRAMC_IMR                (AT91_MC + 0xac)        /* Interrupt Mask Register */
+#define AT91_SDRAMC_ISR                (AT91_MC + 0xb0)        /* Interrupt Status Register */
+
+/* Burst Flash Controller register */
+#define AT91_BFC_MR            (AT91_MC + 0xc0)        /* Mode Register */
+#define                AT91_BFC_BFCOM          (3   <<  0)             /* Burst Flash Controller Operating Mode */
+#define                        AT91_BFC_BFCOM_DISABLED (0 << 0)
+#define                        AT91_BFC_BFCOM_ASYNC    (1 << 0)
+#define                        AT91_BFC_BFCOM_BURST    (2 << 0)
+#define                AT91_BFC_BFCC           (3   <<  2)             /* Burst Flash Controller Clock */
+#define                        AT91_BFC_BFCC_MCK       (1 << 2)
+#define                        AT91_BFC_BFCC_DIV2      (2 << 2)
+#define                        AT91_BFC_BFCC_DIV4      (3 << 2)
+#define                AT91_BFC_AVL            (0xf <<  4)             /* Address Valid Latency */
+#define                AT91_BFC_PAGES          (7   <<  8)             /* Page Size */
+#define                        AT91_BFC_PAGES_NO_PAGE  (0 << 8)
+#define                        AT91_BFC_PAGES_16       (1 << 8)
+#define                        AT91_BFC_PAGES_32       (2 << 8)
+#define                        AT91_BFC_PAGES_64       (3 << 8)
+#define                        AT91_BFC_PAGES_128      (4 << 8)
+#define                        AT91_BFC_PAGES_256      (5 << 8)
+#define                        AT91_BFC_PAGES_512      (6 << 8)
+#define                        AT91_BFC_PAGES_1024     (7 << 8)
+#define                AT91_BFC_OEL            (3   << 12)             /* Output Enable Latency */
+#define                AT91_BFC_BAAEN          (1   << 16)             /* Burst Address Advance Enable */
+#define                AT91_BFC_BFOEH          (1   << 17)             /* Burst Flash Output Enable Handling */
+#define                AT91_BFC_MUXEN          (1   << 18)             /* Multiplexed Bus Enable */
+#define                AT91_BFC_RDYEN          (1   << 19)             /* Ready Enable Mode */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
deleted file mode 100644 (file)
index 73693fe..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * System peripherals registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91RM9200_SYS_H
-#define AT91RM9200_SYS_H
-
-/*
- * Advanced Interrupt Controller.
- */
-#define AT91_AIC       0x000
-
-#define AT91_AIC_SMR(n)                (AT91_AIC + ((n) * 4))  /* Source Mode Registers 0-31 */
-#define                AT91_AIC_PRIOR          (7 << 0)                /* Priority Level */
-#define                AT91_AIC_SRCTYPE        (3 << 5)                /* Interrupt Source Type */
-#define                        AT91_AIC_SRCTYPE_LOW            (0 << 5)
-#define                        AT91_AIC_SRCTYPE_FALLING        (1 << 5)
-#define                        AT91_AIC_SRCTYPE_HIGH           (2 << 5)
-#define                        AT91_AIC_SRCTYPE_RISING         (3 << 5)
-
-#define AT91_AIC_SVR(n)                (AT91_AIC + 0x80 + ((n) * 4))   /* Source Vector Registers 0-31 */
-#define AT91_AIC_IVR           (AT91_AIC + 0x100)      /* Interrupt Vector Register */
-#define AT91_AIC_FVR           (AT91_AIC + 0x104)      /* Fast Interrupt Vector Register */
-#define AT91_AIC_ISR           (AT91_AIC + 0x108)      /* Interrupt Status Register */
-#define                AT91_AIC_IRQID          (0x1f << 0)             /* Current Interrupt Identifier */
-
-#define AT91_AIC_IPR           (AT91_AIC + 0x10c)      /* Interrupt Pending Register */
-#define AT91_AIC_IMR           (AT91_AIC + 0x110)      /* Interrupt Mask Register */
-#define AT91_AIC_CISR          (AT91_AIC + 0x114)      /* Core Interrupt Status Register */
-#define                AT91_AIC_NFIQ           (1 << 0)                /* nFIQ Status */
-#define                AT91_AIC_NIRQ           (1 << 1)                /* nIRQ Status */
-
-#define AT91_AIC_IECR          (AT91_AIC + 0x120)      /* Interrupt Enable Command Register */
-#define AT91_AIC_IDCR          (AT91_AIC + 0x124)      /* Interrupt Disable Command Register */
-#define AT91_AIC_ICCR          (AT91_AIC + 0x128)      /* Interrupt Clear Command Register */
-#define AT91_AIC_ISCR          (AT91_AIC + 0x12c)      /* Interrupt Set Command Register */
-#define AT91_AIC_EOICR         (AT91_AIC + 0x130)      /* End of Interrupt Command Register */
-#define AT91_AIC_SPU           (AT91_AIC + 0x134)      /* Spurious Interrupt Vector Register */
-#define AT91_AIC_DCR           (AT91_AIC + 0x138)      /* Debug Control Register */
-#define                AT91_AIC_DCR_PROT       (1 << 0)                /* Protection Mode */
-#define                AT91_AIC_DCR_GMSK       (1 << 1)                /* General Mask */
-
-
-/*
- * Debug Unit.
- */
-#define AT91_DBGU      0x200
-
-#define AT91_DBGU_CR           (AT91_DBGU + 0x00)      /* Control Register */
-#define AT91_DBGU_MR           (AT91_DBGU + 0x04)      /* Mode Register */
-#define AT91_DBGU_IER          (AT91_DBGU + 0x08)      /* Interrupt Enable Register */
-#define                AT91_DBGU_TXRDY         (1 << 1)                /* Transmitter Ready */
-#define                AT91_DBGU_TXEMPTY       (1 << 9)                /* Transmitter Empty */
-#define AT91_DBGU_IDR          (AT91_DBGU + 0x0c)      /* Interrupt Disable Register */
-#define AT91_DBGU_IMR          (AT91_DBGU + 0x10)      /* Interrupt Mask Register */
-#define AT91_DBGU_SR           (AT91_DBGU + 0x14)      /* Status Register */
-#define AT91_DBGU_RHR          (AT91_DBGU + 0x18)      /* Receiver Holding Register */
-#define AT91_DBGU_THR          (AT91_DBGU + 0x1c)      /* Transmitter Holding Register */
-#define AT91_DBGU_BRGR         (AT91_DBGU + 0x20)      /* Baud Rate Generator Register */
-
-#define AT91_DBGU_CIDR         (AT91_DBGU + 0x40)      /* Chip ID Register */
-#define AT91_DBGU_EXID         (AT91_DBGU + 0x44)      /* Chip ID Extension Register */
-#define                AT91_CIDR_VERSION       (0x1f << 0)             /* Version of the Device */
-#define                AT91_CIDR_EPROC         (7    << 5)             /* Embedded Processor */
-#define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
-#define                AT91_CIDR_NVPSIZ2       (0xf  << 12)            /* Second Nonvolatile Program Memory Size */
-#define                AT91_CIDR_SRAMSIZ       (0xf  << 16)            /* Internal SRAM Size */
-#define                AT91_CIDR_ARCH          (0xff << 20)            /* Architecture Identifier */
-#define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
-#define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
-
-#define AT91_AIC_FFER          (AT91_AIC + 0x140)      /* Fast Forcing Enable Register [SAM9 only] */
-#define AT91_AIC_FFDR          (AT91_AIC + 0x144)      /* Fast Forcing Disable Register [SAM9 only] */
-#define AT91_AIC_FFSR          (AT91_AIC + 0x148)      /* Fast Forcing Status Register [SAM9 only] */
-
-/*
- * PIO Controllers.
- */
-#define AT91_PIOA      0x400
-#define AT91_PIOB      0x600
-#define AT91_PIOC      0x800
-#define AT91_PIOD      0xa00
-
-#define PIO_PER                0x00    /* Enable Register */
-#define PIO_PDR                0x04    /* Disable Register */
-#define PIO_PSR                0x08    /* Status Register */
-#define PIO_OER                0x10    /* Output Enable Register */
-#define PIO_ODR                0x14    /* Output Disable Register */
-#define PIO_OSR                0x18    /* Output Status Register */
-#define PIO_IFER       0x20    /* Glitch Input Filter Enable */
-#define PIO_IFDR       0x24    /* Glitch Input Filter Disable */
-#define PIO_IFSR       0x28    /* Glitch Input Filter Status */
-#define PIO_SODR       0x30    /* Set Output Data Register */
-#define PIO_CODR       0x34    /* Clear Output Data Register */
-#define PIO_ODSR       0x38    /* Output Data Status Register */
-#define PIO_PDSR       0x3c    /* Pin Data Status Register */
-#define PIO_IER                0x40    /* Interrupt Enable Register */
-#define PIO_IDR                0x44    /* Interrupt Disable Register */
-#define PIO_IMR                0x48    /* Interrupt Mask Register */
-#define PIO_ISR                0x4c    /* Interrupt Status Register */
-#define PIO_MDER       0x50    /* Multi-driver Enable Register */
-#define PIO_MDDR       0x54    /* Multi-driver Disable Register */
-#define PIO_MDSR       0x58    /* Multi-driver Status Register */
-#define PIO_PUDR       0x60    /* Pull-up Disable Register */
-#define PIO_PUER       0x64    /* Pull-up Enable Register */
-#define PIO_PUSR       0x68    /* Pull-up Status Register */
-#define PIO_ASR                0x70    /* Peripheral A Select Register */
-#define PIO_BSR                0x74    /* Peripheral B Select Register */
-#define PIO_ABSR       0x78    /* AB Status Register */
-#define PIO_OWER       0xa0    /* Output Write Enable Register */
-#define PIO_OWDR       0xa4    /* Output Write Disable Register */
-#define PIO_OWSR       0xa8    /* Output Write Status Register */
-
-#define AT91_PIO_P(n)  (1 << (n))
-
-
-/*
- * Power Management Controller.
- */
-#define        AT91_PMC        0xc00
-
-#define        AT91_PMC_SCER           (AT91_PMC + 0x00)       /* System Clock Enable Register */
-#define        AT91_PMC_SCDR           (AT91_PMC + 0x04)       /* System Clock Disable Register */
-
-#define        AT91_PMC_SCSR           (AT91_PMC + 0x08)       /* System Clock Status Register */
-#define                AT91_PMC_PCK            (1 <<  0)               /* Processor Clock */
-#define                AT91_PMC_UDP            (1 <<  1)               /* USB Devcice Port Clock */
-#define                AT91_PMC_MCKUDP         (1 <<  2)               /* USB Device Port Master Clock Automatic Disable on Suspend */
-#define                AT91_PMC_UHP            (1 <<  4)               /* USB Host Port Clock */
-#define                AT91_PMC_PCK0           (1 <<  8)               /* Programmable Clock 0 */
-#define                AT91_PMC_PCK1           (1 <<  9)               /* Programmable Clock 1 */
-#define                AT91_PMC_PCK2           (1 << 10)               /* Programmable Clock 2 */
-#define                AT91_PMC_PCK3           (1 << 11)               /* Programmable Clock 3 */
-
-#define        AT91_PMC_PCER           (AT91_PMC + 0x10)       /* Peripheral Clock Enable Register */
-#define        AT91_PMC_PCDR           (AT91_PMC + 0x14)       /* Peripheral Clock Disable Register */
-#define        AT91_PMC_PCSR           (AT91_PMC + 0x18)       /* Peripheral Clock Status Register */
-
-#define        AT91_CKGR_MOR           (AT91_PMC + 0x20)       /* Main Oscillator Register */
-#define                AT91_PMC_MOSCEN         (1    << 0)             /* Main Oscillator Enable */
-#define                AT91_PMC_OSCOUNT        (0xff << 8)             /* Main Oscillator Start-up Time */
-
-#define        AT91_CKGR_MCFR          (AT91_PMC + 0x24)       /* Main Clock Frequency Register */
-#define                AT91_PMC_MAINF          (0xffff <<  0)          /* Main Clock Frequency */
-#define                AT91_PMC_MAINRDY        (1      << 16)          /* Main Clock Ready */
-
-#define        AT91_CKGR_PLLAR         (AT91_PMC + 0x28)       /* PLL A Register */
-#define        AT91_CKGR_PLLBR         (AT91_PMC + 0x2c)       /* PLL B Register */
-#define                AT91_PMC_DIV            (0xff  <<  0)           /* Divider */
-#define                AT91_PMC_PLLCOUNT       (0x3f  <<  8)           /* PLL Counter */
-#define                AT91_PMC_OUT            (3     << 14)           /* PLL Clock Frequency Range */
-#define                AT91_PMC_MUL            (0x7ff << 16)           /* PLL Multiplier */
-#define                AT91_PMC_USB96M         (1     << 28)           /* Divider by 2 Enable (PLLB only) */
-
-#define        AT91_PMC_MCKR           (AT91_PMC + 0x30)       /* Master Clock Register */
-#define                AT91_PMC_CSS            (3 <<  0)               /* Master Clock Selection */
-#define                        AT91_PMC_CSS_SLOW               (0 << 0)
-#define                        AT91_PMC_CSS_MAIN               (1 << 0)
-#define                        AT91_PMC_CSS_PLLA               (2 << 0)
-#define                        AT91_PMC_CSS_PLLB               (3 << 0)
-#define                AT91_PMC_PRES           (7 <<  2)               /* Master Clock Prescaler */
-#define                AT91_PMC_PRES_1                 (0 << 2)
-#define                        AT91_PMC_PRES_2                 (1 << 2)
-#define                        AT91_PMC_PRES_4                 (2 << 2)
-#define                        AT91_PMC_PRES_8                 (3 << 2)
-#define                        AT91_PMC_PRES_16                (4 << 2)
-#define                        AT91_PMC_PRES_32                (5 << 2)
-#define                        AT91_PMC_PRES_64                (6 << 2)
-#define                AT91_PMC_MDIV           (3 <<  8)               /* Master Clock Division */
-#define                        AT91_PMC_MDIV_1                 (0 << 8)
-#define                        AT91_PMC_MDIV_2                 (1 << 8)
-#define                        AT91_PMC_MDIV_3                 (2 << 8)
-#define                        AT91_PMC_MDIV_4                 (3 << 8)
-
-#define        AT91_PMC_PCKR(n)        (AT91_PMC + 0x40 + ((n) * 4))   /* Programmable Clock 0-3 Registers */
-
-#define        AT91_PMC_IER            (AT91_PMC + 0x60)       /* Interrupt Enable Register */
-#define        AT91_PMC_IDR            (AT91_PMC + 0x64)       /* Interrupt Disable Register */
-#define        AT91_PMC_SR             (AT91_PMC + 0x68)       /* Status Register */
-#define                AT91_PMC_MOSCS          (1 <<  0)               /* MOSCS Flag */
-#define                AT91_PMC_LOCKA          (1 <<  1)               /* PLLA Lock */
-#define                AT91_PMC_LOCKB          (1 <<  2)               /* PLLB Lock */
-#define                AT91_PMC_MCKRDY         (1 <<  3)               /* Master Clock */
-#define                AT91_PMC_PCK0RDY        (1 <<  8)               /* Programmable Clock 0 */
-#define                AT91_PMC_PCK1RDY        (1 <<  9)               /* Programmable Clock 1 */
-#define                AT91_PMC_PCK2RDY        (1 << 10)               /* Programmable Clock 2 */
-#define                AT91_PMC_PCK3RDY        (1 << 11)               /* Programmable Clock 3 */
-#define        AT91_PMC_IMR            (AT91_PMC + 0x6c)       /* Interrupt Mask Register */
-
-
-/*
- * System Timer.
- */
-#define        AT91_ST         0xd00
-
-#define        AT91_ST_CR              (AT91_ST + 0x00)        /* Control Register */
-#define        AT91_ST_WDRST           (1 << 0)                /* Watchdog Timer Restart */
-#define        AT91_ST_PIMR            (AT91_ST + 0x04)        /* Period Interval Mode Register */
-#define                AT91_ST_PIV             (0xffff <<  0)          /* Period Interval Value */
-#define        AT91_ST_WDMR            (AT91_ST + 0x08)        /* Watchdog Mode Register */
-#define                AT91_ST_WDV             (0xffff <<  0)          /* Watchdog Counter Value */
-#define                AT91_ST_RSTEN           (1      << 16)          /* Reset Enable */
-#define                AT91_ST_EXTEN           (1      << 17)          /* External Signal Assertion Enable */
-#define        AT91_ST_RTMR            (AT91_ST + 0x0c)        /* Real-time Mode Register */
-#define                AT91_ST_RTPRES          (0xffff <<  0)          /* Real-time Prescalar Value */
-#define        AT91_ST_SR              (AT91_ST + 0x10)        /* Status Register */
-#define                AT91_ST_PITS            (1 << 0)                /* Period Interval Timer Status */
-#define                AT91_ST_WDOVF           (1 << 1)                /* Watchdog Overflow */
-#define                AT91_ST_RTTINC          (1 << 2)                /* Real-time Timer Increment */
-#define                AT91_ST_ALMS            (1 << 3)                /* Alarm Status */
-#define        AT91_ST_IER             (AT91_ST + 0x14)        /* Interrupt Enable Register */
-#define        AT91_ST_IDR             (AT91_ST + 0x18)        /* Interrupt Disable Register */
-#define        AT91_ST_IMR             (AT91_ST + 0x1c)        /* Interrupt Mask Register */
-#define        AT91_ST_RTAR            (AT91_ST + 0x20)        /* Real-time Alarm Register */
-#define                AT91_ST_ALMV            (0xfffff << 0)          /* Alarm Value */
-#define        AT91_ST_CRTR            (AT91_ST + 0x24)        /* Current Real-time Register */
-#define                AT91_ST_CRTV            (0xfffff << 0)          /* Current Real-Time Value */
-
-
-/*
- * Real-time Clock.
- */
-#define        AT91_RTC        0xe00
-
-#define        AT91_RTC_CR             (AT91_RTC + 0x00)       /* Control Register */
-#define                AT91_RTC_UPDTIM         (1 <<  0)               /* Update Request Time Register */
-#define                AT91_RTC_UPDCAL         (1 <<  1)               /* Update Request Calendar Register */
-#define                AT91_RTC_TIMEVSEL       (3 <<  8)               /* Time Event Selection */
-#define                        AT91_RTC_TIMEVSEL_MINUTE        (0 << 8)
-#define                AT91_RTC_TIMEVSEL_HOUR          (1 << 8)
-#define                AT91_RTC_TIMEVSEL_DAY24         (2 << 8)
-#define                AT91_RTC_TIMEVSEL_DAY12         (3 << 8)
-#define                AT91_RTC_CALEVSEL       (3 << 16)               /* Calendar Event Selection */
-#define                AT91_RTC_CALEVSEL_WEEK          (0 << 16)
-#define                AT91_RTC_CALEVSEL_MONTH         (1 << 16)
-#define                AT91_RTC_CALEVSEL_YEAR          (2 << 16)
-
-#define        AT91_RTC_MR             (AT91_RTC + 0x04)       /* Mode Register */
-#define        AT91_RTC_HRMOD          (1 <<  0)               /* 12/24 Hour Mode */
-
-#define        AT91_RTC_TIMR           (AT91_RTC + 0x08)       /* Time Register */
-#define                AT91_RTC_SEC            (0x7f <<  0)            /* Current Second */
-#define                AT91_RTC_MIN            (0x7f <<  8)            /* Current Minute */
-#define                AT91_RTC_HOUR           (0x3f << 16)            /* Current Hour */
-#define                AT91_RTC_AMPM           (1    << 22)            /* Ante Meridiem Post Meridiem Indicator */
-
-#define        AT91_RTC_CALR           (AT91_RTC + 0x0c)       /* Calendar Register */
-#define                AT91_RTC_CENT           (0x7f <<  0)            /* Current Century */
-#define                AT91_RTC_YEAR           (0xff <<  8)            /* Current Year */
-#define                AT91_RTC_MONTH          (0x1f << 16)            /* Current Month */
-#define                AT91_RTC_DAY            (7    << 21)            /* Current Day */
-#define                AT91_RTC_DATE           (0x3f << 24)            /* Current Date */
-
-#define        AT91_RTC_TIMALR         (AT91_RTC + 0x10)       /* Time Alarm Register */
-#define                AT91_RTC_SECEN          (1 <<  7)               /* Second Alarm Enable */
-#define                AT91_RTC_MINEN          (1 << 15)               /* Minute Alarm Enable */
-#define                AT91_RTC_HOUREN         (1 << 23)               /* Hour Alarm Enable */
-
-#define        AT91_RTC_CALALR         (AT91_RTC + 0x14)       /* Calendar Alarm Register */
-#define                AT91_RTC_MTHEN          (1 << 23)               /* Month Alarm Enable */
-#define                AT91_RTC_DATEEN         (1 << 31)               /* Date Alarm Enable */
-
-#define        AT91_RTC_SR             (AT91_RTC + 0x18)       /* Status Register */
-#define                AT91_RTC_ACKUPD         (1 <<  0)               /* Acknowledge for Update */
-#define                AT91_RTC_ALARM          (1 <<  1)               /* Alarm Flag */
-#define                AT91_RTC_SECEV          (1 <<  2)               /* Second Event */
-#define                AT91_RTC_TIMEV          (1 <<  3)               /* Time Event */
-#define                AT91_RTC_CALEV          (1 <<  4)               /* Calendar Event */
-
-#define        AT91_RTC_SCCR           (AT91_RTC + 0x1c)       /* Status Clear Command Register */
-#define        AT91_RTC_IER            (AT91_RTC + 0x20)       /* Interrupt Enable Register */
-#define        AT91_RTC_IDR            (AT91_RTC + 0x24)       /* Interrupt Disable Register */
-#define        AT91_RTC_IMR            (AT91_RTC + 0x28)       /* Interrupt Mask Register */
-
-#define        AT91_RTC_VER            (AT91_RTC + 0x2c)       /* Valid Entry Register */
-#define                AT91_RTC_NVTIM          (1 <<  0)               /* Non valid Time */
-#define                AT91_RTC_NVCAL          (1 <<  1)               /* Non valid Calendar */
-#define                AT91_RTC_NVTIMALR       (1 <<  2)               /* Non valid Time Alarm */
-#define                AT91_RTC_NVCALALR       (1 <<  3)               /* Non valid Calendar Alarm */
-
-
-/*
- * Memory Controller.
- */
-#define AT91_MC                0xf00
-
-#define AT91_MC_RCR            (AT91_MC + 0x00)        /* MC Remap Control Register */
-#define                AT91_MC_RCB             (1 <<  0)               /* Remap Command Bit */
-
-#define AT91_MC_ASR            (AT91_MC + 0x04)        /* MC Abort Status Register */
-#define                AT91_MC_UNADD           (1 <<  0)               /* Undefined Address Abort Status */
-#define                AT91_MC_MISADD          (1 <<  1)               /* Misaligned Address Abort Status */
-#define                AT91_MC_ABTSZ           (3 <<  8)               /* Abort Size Status */
-#define                        AT91_MC_ABTSZ_BYTE              (0 << 8)
-#define                        AT91_MC_ABTSZ_HALFWORD          (1 << 8)
-#define                        AT91_MC_ABTSZ_WORD              (2 << 8)
-#define                AT91_MC_ABTTYP          (3 << 10)               /* Abort Type Status */
-#define                        AT91_MC_ABTTYP_DATAREAD         (0 << 10)
-#define                        AT91_MC_ABTTYP_DATAWRITE        (1 << 10)
-#define                        AT91_MC_ABTTYP_FETCH            (2 << 10)
-#define                AT91_MC_MST0            (1 << 16)               /* ARM920T Abort Source */
-#define                AT91_MC_MST1            (1 << 17)               /* PDC Abort Source */
-#define                AT91_MC_MST2            (1 << 18)               /* UHP Abort Source */
-#define                AT91_MC_MST3            (1 << 19)               /* EMAC Abort Source */
-#define                AT91_MC_SVMST0          (1 << 24)               /* Saved ARM920T Abort Source */
-#define                AT91_MC_SVMST1          (1 << 25)               /* Saved PDC Abort Source */
-#define                AT91_MC_SVMST2          (1 << 26)               /* Saved UHP Abort Source */
-#define                AT91_MC_SVMST3          (1 << 27)               /* Saved EMAC Abort Source */
-
-#define AT91_MC_AASR           (AT91_MC + 0x08)        /* MC Abort Address Status Register */
-
-#define AT91_MC_MPR            (AT91_MC + 0x0c)        /* MC Master Priority Register */
-#define                AT91_MPR_MSTP0          (7 <<  0)               /* ARM920T Priority */
-#define                AT91_MPR_MSTP1          (7 <<  4)               /* PDC Priority */
-#define                AT91_MPR_MSTP2          (7 <<  8)               /* UHP Priority */
-#define                AT91_MPR_MSTP3          (7 << 12)               /* EMAC Priority */
-
-/* External Bus Interface (EBI) registers */
-#define AT91_EBI_CSA           (AT91_MC + 0x60)        /* Chip Select Assignment Register */
-#define                AT91_EBI_CS0A           (1 << 0)                /* Chip Select 0 Assignment */
-#define                        AT91_EBI_CS0A_SMC               (0 << 0)
-#define                        AT91_EBI_CS0A_BFC               (1 << 0)
-#define                AT91_EBI_CS1A           (1 << 1)                /* Chip Select 1 Assignment */
-#define                        AT91_EBI_CS1A_SMC               (0 << 1)
-#define                        AT91_EBI_CS1A_SDRAMC            (1 << 1)
-#define                AT91_EBI_CS3A           (1 << 3)                /* Chip Select 2 Assignment */
-#define                        AT91_EBI_CS3A_SMC               (0 << 3)
-#define                        AT91_EBI_CS3A_SMC_SMARTMEDIA    (1 << 3)
-#define                AT91_EBI_CS4A           (1 << 4)                /* Chip Select 3 Assignment */
-#define                        AT91_EBI_CS4A_SMC               (0 << 4)
-#define                        AT91_EBI_CS4A_SMC_COMPACTFLASH  (1 << 4)
-#define AT91_EBI_CFGR          (AT91_MC + 0x64)        /* Configuration Register */
-#define                AT91_EBI_DBPUC          (1 << 0)                /* Data Bus Pull-Up Configuration */
-
-/* Static Memory Controller (SMC) registers */
-#define        AT91_SMC_CSR(n)         (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
-#define                AT91_SMC_NWS            (0x7f <<  0)            /* Number of Wait States */
-#define                        AT91_SMC_NWS_(x)        ((x) << 0)
-#define                AT91_SMC_WSEN           (1    <<  7)            /* Wait State Enable */
-#define                AT91_SMC_TDF            (0xf  <<  8)            /* Data Float Time */
-#define                        AT91_SMC_TDF_(x)        ((x) << 8)
-#define                AT91_SMC_BAT            (1    << 12)            /* Byte Access Type */
-#define                AT91_SMC_DBW            (3    << 13)            /* Data Bus Width */
-#define                        AT91_SMC_DBW_16         (1 << 13)
-#define                        AT91_SMC_DBW_8          (2 << 13)
-#define                AT91_SMC_DPR            (1 << 15)               /* Data Read Protocol */
-#define                AT91_SMC_ACSS           (3 << 16)               /* Address to Chip Select Setup */
-#define                        AT91_SMC_ACSS_STD       (0 << 16)
-#define                        AT91_SMC_ACSS_1         (1 << 16)
-#define                        AT91_SMC_ACSS_2         (2 << 16)
-#define                        AT91_SMC_ACSS_3         (3 << 16)
-#define                AT91_SMC_RWSETUP        (7 << 24)               /* Read & Write Signal Time Setup */
-#define                        AT91_SMC_RWSETUP_(x)    ((x) << 24)
-#define                AT91_SMC_RWHOLD         (7 << 28)               /* Read & Write Signal Hold Time */
-#define                        AT91_SMC_RWHOLD_(x)     ((x) << 28)
-
-/* SDRAM Controller registers */
-#define AT91_SDRAMC_MR         (AT91_MC + 0x90)        /* Mode Register */
-#define                AT91_SDRAMC_MODE        (0xf << 0)              /* Command Mode */
-#define                        AT91_SDRAMC_MODE_NORMAL         (0 << 0)
-#define                        AT91_SDRAMC_MODE_NOP            (1 << 0)
-#define                        AT91_SDRAMC_MODE_PRECHARGE      (2 << 0)
-#define                        AT91_SDRAMC_MODE_LMR            (3 << 0)
-#define                        AT91_SDRAMC_MODE_REFRESH        (4 << 0)
-#define                AT91_SDRAMC_DBW         (1   << 4)              /* Data Bus Width */
-#define                        AT91_SDRAMC_DBW_32      (0 << 4)
-#define                        AT91_SDRAMC_DBW_16      (1 << 4)
-
-#define AT91_SDRAMC_TR         (AT91_MC + 0x94)        /* Refresh Timer Register */
-#define                AT91_SDRAMC_COUNT       (0xfff << 0)            /* Refresh Timer Count */
-
-#define AT91_SDRAMC_CR         (AT91_MC + 0x98)        /* Configuration Register */
-#define                AT91_SDRAMC_NC          (3   <<  0)             /* Number of Column Bits */
-#define                        AT91_SDRAMC_NC_8        (0 << 0)
-#define                        AT91_SDRAMC_NC_9        (1 << 0)
-#define                        AT91_SDRAMC_NC_10       (2 << 0)
-#define                        AT91_SDRAMC_NC_11       (3 << 0)
-#define                AT91_SDRAMC_NR          (3   <<  2)             /* Number of Row Bits */
-#define                        AT91_SDRAMC_NR_11       (0 << 2)
-#define                        AT91_SDRAMC_NR_12       (1 << 2)
-#define                        AT91_SDRAMC_NR_13       (2 << 2)
-#define                AT91_SDRAMC_NB          (1   <<  4)             /* Number of Banks */
-#define                        AT91_SDRAMC_NB_2        (0 << 4)
-#define                        AT91_SDRAMC_NB_4        (1 << 4)
-#define                AT91_SDRAMC_CAS         (3   <<  5)             /* CAS Latency */
-#define                        AT91_SDRAMC_CAS_2       (2 << 5)
-#define                AT91_SDRAMC_TWR         (0xf <<  7)             /* Write Recovery Delay */
-#define                AT91_SDRAMC_TRC         (0xf << 11)             /* Row Cycle Delay */
-#define                AT91_SDRAMC_TRP         (0xf << 15)             /* Row Precharge Delay */
-#define                AT91_SDRAMC_TRCD        (0xf << 19)             /* Row to Column Delay */
-#define                AT91_SDRAMC_TRAS        (0xf << 23)             /* Active to Precharge Delay */
-#define                AT91_SDRAMC_TXSR        (0xf << 27)             /* Exit Self Refresh to Active Delay */
-
-#define AT91_SDRAMC_SRR                (AT91_MC + 0x9c)        /* Self Refresh Register */
-#define AT91_SDRAMC_LPR                (AT91_MC + 0xa0)        /* Low Power Register */
-#define AT91_SDRAMC_IER                (AT91_MC + 0xa4)        /* Interrupt Enable Register */
-#define AT91_SDRAMC_IDR                (AT91_MC + 0xa8)        /* Interrupt Disable Register */
-#define AT91_SDRAMC_IMR                (AT91_MC + 0xac)        /* Interrupt Mask Register */
-#define AT91_SDRAMC_ISR                (AT91_MC + 0xb0)        /* Interrupt Status Register */
-
-/* Burst Flash Controller register */
-#define AT91_BFC_MR            (AT91_MC + 0xc0)        /* Mode Register */
-#define                AT91_BFC_BFCOM          (3   <<  0)             /* Burst Flash Controller Operating Mode */
-#define                        AT91_BFC_BFCOM_DISABLED (0 << 0)
-#define                        AT91_BFC_BFCOM_ASYNC    (1 << 0)
-#define                        AT91_BFC_BFCOM_BURST    (2 << 0)
-#define                AT91_BFC_BFCC           (3   <<  2)             /* Burst Flash Controller Clock */
-#define                        AT91_BFC_BFCC_MCK       (1 << 2)
-#define                        AT91_BFC_BFCC_DIV2      (2 << 2)
-#define                        AT91_BFC_BFCC_DIV4      (3 << 2)
-#define                AT91_BFC_AVL            (0xf <<  4)             /* Address Valid Latency */
-#define                AT91_BFC_PAGES          (7   <<  8)             /* Page Size */
-#define                        AT91_BFC_PAGES_NO_PAGE  (0 << 8)
-#define                        AT91_BFC_PAGES_16       (1 << 8)
-#define                        AT91_BFC_PAGES_32       (2 << 8)
-#define                        AT91_BFC_PAGES_64       (3 << 8)
-#define                        AT91_BFC_PAGES_128      (4 << 8)
-#define                        AT91_BFC_PAGES_256      (5 << 8)
-#define                        AT91_BFC_PAGES_512      (6 << 8)
-#define                        AT91_BFC_PAGES_1024     (7 << 8)
-#define                AT91_BFC_OEL            (3   << 12)             /* Output Enable Latency */
-#define                AT91_BFC_BAAEN          (1   << 16)             /* Burst Address Advance Enable */
-#define                AT91_BFC_BFOEH          (1   << 17)             /* Burst Flash Output Enable Handling */
-#define                AT91_BFC_MUXEN          (1   << 18)             /* Multiplexed Bus Enable */
-#define                AT91_BFC_RDYEN          (1   << 19)             /* Ready Enable Mode */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
deleted file mode 100644 (file)
index 951e3f6..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * USB Device Port (UDP) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91RM9200_UDP_H
-#define AT91RM9200_UDP_H
-
-#define AT91_UDP_FRM_NUM       0x00            /* Frame Number Register */
-#define                AT91_UDP_NUM            (0x7ff <<  0)           /* Frame Number */
-#define                AT91_UDP_FRM_ERR        (1     << 16)           /* Frame Error */
-#define                AT91_UDP_FRM_OK         (1     << 17)           /* Frame OK */
-
-#define AT91_UDP_GLB_STAT      0x04            /* Global State Register */
-#define                AT91_UDP_FADDEN         (1 <<  0)               /* Function Address Enable */
-#define                AT91_UDP_CONFG          (1 <<  1)               /* Configured */
-#define                AT91_UDP_ESR            (1 <<  2)               /* Enable Send Resume */
-#define                AT91_UDP_RSMINPR        (1 <<  3)               /* Resume has been sent */
-#define                AT91_UDP_RMWUPE         (1 <<  4)               /* Remote Wake Up Enable */
-
-#define AT91_UDP_FADDR         0x08            /* Function Address Register */
-#define                AT91_UDP_FADD           (0x7f << 0)             /* Function Address Value */
-#define                AT91_UDP_FEN            (1    << 8)             /* Function Enable */
-
-#define AT91_UDP_IER           0x10            /* Interrupt Enable Register */
-#define AT91_UDP_IDR           0x14            /* Interrupt Disable Register */
-#define AT91_UDP_IMR           0x18            /* Interrupt Mask Register */
-
-#define AT91_UDP_ISR           0x1c            /* Interrupt Status Register */
-#define                AT91_UDP_EP(n)          (1 << (n))              /* Endpoint Interrupt Status */
-#define                AT91_UDP_RXSUSP         (1 <<  8)               /* USB Suspend Interrupt Status */
-#define                AT91_UDP_RXRSM          (1 <<  9)               /* USB Resume Interrupt Status */
-#define                AT91_UDP_EXTRSM         (1 << 10)               /* External Resume Interrupt Status */
-#define                AT91_UDP_SOFINT         (1 << 11)               /* Start of Frame Interrupt Status */
-#define                AT91_UDP_ENDBUSRES      (1 << 12)               /* End of Bus Reset Interrpt Status */
-#define                AT91_UDP_WAKEUP         (1 << 13)               /* USB Wakeup Interrupt Status */
-
-#define AT91_UDP_ICR           0x20            /* Interrupt Clear Register */
-#define AT91_UDP_RST_EP                0x28            /* Reset Endpoint Register */
-
-#define AT91_UDP_CSR(n)                (0x30 + ((n) * 4))      /* Endpoint Control/Status Registers 0-7 */
-#define                AT91_UDP_TXCOMP         (1 <<  0)               /* Generates IN packet with data previously written in DPR */
-#define                AT91_UDP_RX_DATA_BK0    (1 <<  1)               /* Receive Data Bank 0 */
-#define                AT91_UDP_RXSETUP        (1 <<  2)               /* Send STALL to the host */
-#define                AT91_UDP_STALLSENT      (1 <<  3)               /* Stall Sent / Isochronous error (Isochronous endpoints) */
-#define                AT91_UDP_TXPKTRDY       (1 <<  4)               /* Transmit Packet Ready */
-#define                AT91_UDP_FORCESTALL     (1 <<  5)               /* Force Stall */
-#define                AT91_UDP_RX_DATA_BK1    (1 <<  6)               /* Receive Data Bank 1 */
-#define                AT91_UDP_DIR            (1 <<  7)               /* Transfer Direction */
-#define                AT91_UDP_EPTYPE         (7 <<  8)               /* Endpoint Type */
-#define                        AT91_UDP_EPTYPE_CTRL            (0 <<  8)
-#define                        AT91_UDP_EPTYPE_ISO_OUT         (1 <<  8)
-#define                        AT91_UDP_EPTYPE_BULK_OUT        (2 <<  8)
-#define                        AT91_UDP_EPTYPE_INT_OUT         (3 <<  8)
-#define                        AT91_UDP_EPTYPE_ISO_IN          (5 <<  8)
-#define                        AT91_UDP_EPTYPE_BULK_IN         (6 <<  8)
-#define                        AT91_UDP_EPTYPE_INT_IN          (7 <<  8)
-#define                AT91_UDP_DTGLE          (1 << 11)               /* Data Toggle */
-#define                AT91_UDP_EPEDS          (1 << 15)               /* Endpoint Enable/Disable */
-#define                AT91_UDP_RXBYTECNT      (0x7ff << 16)           /* Number of bytes in FIFO */
-
-#define AT91_UDP_FDR(n)                (0x50 + ((n) * 4))      /* Endpoint FIFO Data Registers 0-7 */
-
-#define AT91_UDP_TXVC          0x74            /* Transceiver Control Register */
-#define                AT91_UDP_TXVC_TXVDIS    (1 << 8)                /* Transceiver Disable */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260.h b/include/asm-arm/arch-at91rm9200/at91sam9260.h
new file mode 100644 (file)
index 0000000..46f4dd6
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91sam9260.h
+ *
+ * (C) 2006 Andrew Victor
+ *
+ * Common definitions.
+ * Based on AT91SAM9260 datasheet revision A (Preliminary).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91SAM9260_H
+#define AT91SAM9260_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ            0       /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS            1       /* System Peripherals */
+#define AT91SAM9260_ID_PIOA    2       /* Parallel IO Controller A */
+#define AT91SAM9260_ID_PIOB    3       /* Parallel IO Controller B */
+#define AT91SAM9260_ID_PIOC    4       /* Parallel IO Controller C */
+#define AT91SAM9260_ID_ADC     5       /* Analog-to-Digital Converter */
+#define AT91SAM9260_ID_US0     6       /* USART 0 */
+#define AT91SAM9260_ID_US1     7       /* USART 1 */
+#define AT91SAM9260_ID_US2     8       /* USART 2 */
+#define AT91SAM9260_ID_MCI     9       /* Multimedia Card Interface */
+#define AT91SAM9260_ID_UDP     10      /* USB Device Port */
+#define AT91SAM9260_ID_TWI     11      /* Two-Wire Interface */
+#define AT91SAM9260_ID_SPI0    12      /* Serial Peripheral Interface 0 */
+#define AT91SAM9260_ID_SPI1    13      /* Serial Peripheral Interface 1 */
+#define AT91SAM9260_ID_SSC     14      /* Serial Synchronous Controller */
+#define AT91SAM9260_ID_TC0     17      /* Timer Counter 0 */
+#define AT91SAM9260_ID_TC1     18      /* Timer Counter 1 */
+#define AT91SAM9260_ID_TC2     19      /* Timer Counter 2 */
+#define AT91SAM9260_ID_UHP     20      /* USB Host port */
+#define AT91SAM9260_ID_EMAC    21      /* Ethernet */
+#define AT91SAM9260_ID_ISI     22      /* Image Sensor Interface */
+#define AT91SAM9260_ID_US3     23      /* USART 3 */
+#define AT91SAM9260_ID_US4     24      /* USART 4 */
+#define AT91SAM9260_ID_US5     25      /* USART 5 */
+#define AT91SAM9260_ID_TC3     26      /* Timer Counter 3 */
+#define AT91SAM9260_ID_TC4     27      /* Timer Counter 4 */
+#define AT91SAM9260_ID_TC5     28      /* Timer Counter 5 */
+#define AT91SAM9260_ID_IRQ0    29      /* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9260_ID_IRQ1    30      /* Advanced Interrupt Controller (IRQ1) */
+#define AT91SAM9260_ID_IRQ2    31      /* Advanced Interrupt Controller (IRQ2) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9260_BASE_TCB0          0xfffa0000
+#define AT91SAM9260_BASE_TC0           0xfffa0000
+#define AT91SAM9260_BASE_TC1           0xfffa0040
+#define AT91SAM9260_BASE_TC2           0xfffa0080
+#define AT91SAM9260_BASE_UDP           0xfffa4000
+#define AT91SAM9260_BASE_MCI           0xfffa8000
+#define AT91SAM9260_BASE_TWI           0xfffac000
+#define AT91SAM9260_BASE_US0           0xfffb0000
+#define AT91SAM9260_BASE_US1           0xfffb4000
+#define AT91SAM9260_BASE_US2           0xfffb8000
+#define AT91SAM9260_BASE_SSC           0xfffbc000
+#define AT91SAM9260_BASE_ISI           0xfffc0000
+#define AT91SAM9260_BASE_EMAC          0xfffc4000
+#define AT91SAM9260_BASE_SPI0          0xfffc8000
+#define AT91SAM9260_BASE_SPI1          0xfffcc000
+#define AT91SAM9260_BASE_US3           0xfffd0000
+#define AT91SAM9260_BASE_US4           0xfffd4000
+#define AT91SAM9260_BASE_US5           0xfffd8000
+#define AT91SAM9260_BASE_TCB1          0xfffdc000
+#define AT91SAM9260_BASE_TC3           0xfffdc000
+#define AT91SAM9260_BASE_TC4           0xfffdc040
+#define AT91SAM9260_BASE_TC5           0xfffdc080
+#define AT91SAM9260_BASE_ADC           0xfffe0000
+#define AT91_BASE_SYS                  0xffffe800
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_ECC       (0xffffe800 - AT91_BASE_SYS)
+#define AT91_SDRAMC    (0xffffea00 - AT91_BASE_SYS)
+#define AT91_SMC       (0xffffec00 - AT91_BASE_SYS)
+#define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
+#define AT91_CCFG      (0xffffef10 - AT91_BASE_SYS)
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)
+#define AT91_DBGU      (0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOA      (0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOB      (0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOC      (0xfffff800 - AT91_BASE_SYS)
+#define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC     (0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT       (0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT       (0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT       (0xfffffd40 - AT91_BASE_SYS)
+#define AT91_GPBR      (0xfffffd50 - AT91_BASE_SYS)
+
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9260_ROM_BASE   0x00100000      /* Internal ROM base address */
+#define AT91SAM9260_ROM_SIZE   SZ_32K          /* Internal ROM size (32Kb) */
+
+#define AT91SAM9260_SRAM0_BASE 0x00200000      /* Internal SRAM 0 base address */
+#define AT91SAM9260_SRAM0_SIZE SZ_4K           /* Internal SRAM 0 size (4Kb) */
+#define AT91SAM9260_SRAM1_BASE 0x00300000      /* Internal SRAM 1 base address */
+#define AT91SAM9260_SRAM1_SIZE SZ_4K           /* Internal SRAM 1 size (4Kb) */
+
+#define AT91SAM9260_UHP_BASE   0x00500000      /* USB Host controller */
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+
+// TODO: Add
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
new file mode 100644 (file)
index 0000000..746d973
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9260 datasheet revision B.
+ *
+ * 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 AT91SAM9260_MATRIX_H
+#define AT91SAM9260_MATRIX_H
+
+#define AT91_MATRIX_MCFG0      (AT91_MATRIX + 0x00)    /* Master Configuration Register 0 */
+#define AT91_MATRIX_MCFG1      (AT91_MATRIX + 0x04)    /* Master Configuration Register 1 */
+#define AT91_MATRIX_MCFG2      (AT91_MATRIX + 0x08)    /* Master Configuration Register 2 */
+#define AT91_MATRIX_MCFG3      (AT91_MATRIX + 0x0C)    /* Master Configuration Register 3 */
+#define AT91_MATRIX_MCFG4      (AT91_MATRIX + 0x10)    /* Master Configuration Register 4 */
+#define AT91_MATRIX_MCFG5      (AT91_MATRIX + 0x04)    /* Master Configuration Register 5 */
+#define                AT91_MATRIX_ULBT                (7 << 0)        /* Undefined Length Burst Type */
+#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
+#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
+#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
+#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
+#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
+
+#define AT91_MATRIX_SCFG0      (AT91_MATRIX + 0x40)    /* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1      (AT91_MATRIX + 0x44)    /* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2      (AT91_MATRIX + 0x48)    /* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3      (AT91_MATRIX + 0x4C)    /* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4      (AT91_MATRIX + 0x50)    /* Slave Configuration Register 4 */
+#define                AT91_MATRIX_SLOT_CYCLE          (0xff <<  0)    /* Maximum Number of Allowed Cycles for a Burst */
+#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
+#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
+#define                AT91_MATRIX_FIXED_DEFMSTR       (7    << 18)    /* Fixed Index of Default Master */
+#define                AT91_MATRIX_ARBT                (3    << 24)    /* Arbitration Type */
+#define                        AT91_MATRIX_ARBT_ROUND_ROBIN    (0 << 24)
+#define                        AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
+
+#define AT91_MATRIX_PRAS0      (AT91_MATRIX + 0x80)    /* Priority Register A for Slave 0 */
+#define AT91_MATRIX_PRAS1      (AT91_MATRIX + 0x88)    /* Priority Register A for Slave 1 */
+#define AT91_MATRIX_PRAS2      (AT91_MATRIX + 0x90)    /* Priority Register A for Slave 2 */
+#define AT91_MATRIX_PRAS3      (AT91_MATRIX + 0x98)    /* Priority Register A for Slave 3 */
+#define AT91_MATRIX_PRAS4      (AT91_MATRIX + 0xA0)    /* Priority Register A for Slave 4 */
+#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
+#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
+#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
+#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
+#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
+#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
+
+#define AT91_MATRIX_MRCR       (AT91_MATRIX + 0x100)   /* Master Remap Control Register */
+#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+
+#define AT91_MATRIX_EBICSA     (AT91_MATRIX + 0x11C)   /* EBI Chip Select Assignment Register */
+#define                AT91_MATRIX_CS1A                (1 << 1)         /* Chip Select 1 Assignment */
+#define                        AT91_MATRIX_CS1A_SMC            (0 << 1)
+#define                        AT91_MATRIX_CS1A_SDRAMC         (1 << 1)
+#define                AT91_MATRIX_CS3A                (1 << 3)        /* Chip Select 3 Assignment */
+#define                        AT91_MATRIX_CS3A_SMC            (0 << 3)
+#define                        AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
+#define                AT91_MATRIX_CS4A                (1 << 4)        /* Chip Select 4 Assignment */
+#define                        AT91_MATRIX_CS4A_SMC            (0 << 4)
+#define                        AT91_MATRIX_CS4A_SMC_CF1        (1 << 4)
+#define                AT91_MATRIX_CS5A                (1 << 5 )       /* Chip Select 5 Assignment */
+#define                        AT91_MATRIX_CS5A_SMC            (0 << 5)
+#define                        AT91_MATRIX_CS5A_SMC_CF2        (1 << 5)
+#define                AT91_MATRIX_DBPUC               (1 << 8)        /* Data Bus Pull-up Configuration */
+#define                AT91_MATRIX_VDDIOMSEL           (1 << 16)       /* Memory voltage selection */
+#define                        AT91_MATRIX_VDDIOMSEL_1_8V      (0 << 16)
+#define                        AT91_MATRIX_VDDIOMSEL_3_3V      (1 << 16)
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261.h b/include/asm-arm/arch-at91rm9200/at91sam9261.h
new file mode 100644 (file)
index 0000000..8d39672
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91sam9261.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Common definitions.
+ * Based on AT91SAM9261 datasheet revision E. (Preliminary)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91SAM9261_H
+#define AT91SAM9261_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ            0       /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS            1       /* System Peripherals */
+#define AT91SAM9261_ID_PIOA    2       /* Parallel IO Controller A */
+#define AT91SAM9261_ID_PIOB    3       /* Parallel IO Controller B */
+#define AT91SAM9261_ID_PIOC    4       /* Parallel IO Controller C */
+#define AT91SAM9261_ID_US0     6       /* USART 0 */
+#define AT91SAM9261_ID_US1     7       /* USART 1 */
+#define AT91SAM9261_ID_US2     8       /* USART 2 */
+#define AT91SAM9261_ID_MCI     9       /* Multimedia Card Interface */
+#define AT91SAM9261_ID_UDP     10      /* USB Device Port */
+#define AT91SAM9261_ID_TWI     11      /* Two-Wire Interface */
+#define AT91SAM9261_ID_SPI0    12      /* Serial Peripheral Interface 0 */
+#define AT91SAM9261_ID_SPI1    13      /* Serial Peripheral Interface 1 */
+#define AT91SAM9261_ID_SSC0    14      /* Serial Synchronous Controller 0 */
+#define AT91SAM9261_ID_SSC1    15      /* Serial Synchronous Controller 1 */
+#define AT91SAM9261_ID_SSC2    16      /* Serial Synchronous Controller 2 */
+#define AT91SAM9261_ID_TC0     17      /* Timer Counter 0 */
+#define AT91SAM9261_ID_TC1     18      /* Timer Counter 1 */
+#define AT91SAM9261_ID_TC2     19      /* Timer Counter 2 */
+#define AT91SAM9261_ID_UHP     20      /* USB Host port */
+#define AT91SAM9261_ID_LCDC    21      /* LDC Controller */
+#define AT91SAM9261_ID_IRQ0    29      /* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9261_ID_IRQ1    30      /* Advanced Interrupt Controller (IRQ1) */
+#define AT91SAM9261_ID_IRQ2    31      /* Advanced Interrupt Controller (IRQ2) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9261_BASE_TCB0          0xfffa0000
+#define AT91SAM9261_BASE_TC0           0xfffa0000
+#define AT91SAM9261_BASE_TC1           0xfffa0040
+#define AT91SAM9261_BASE_TC2           0xfffa0080
+#define AT91SAM9261_BASE_UDP           0xfffa4000
+#define AT91SAM9261_BASE_MCI           0xfffa8000
+#define AT91SAM9261_BASE_TWI           0xfffac000
+#define AT91SAM9261_BASE_US0           0xfffb0000
+#define AT91SAM9261_BASE_US1           0xfffb4000
+#define AT91SAM9261_BASE_US2           0xfffb8000
+#define AT91SAM9261_BASE_SSC0          0xfffbc000
+#define AT91SAM9261_BASE_SSC1          0xfffc0000
+#define AT91SAM9261_BASE_SSC2          0xfffc4000
+#define AT91SAM9261_BASE_SPI0          0xfffc8000
+#define AT91SAM9261_BASE_SPI1          0xfffcc000
+#define AT91_BASE_SYS                  0xffffea00
+
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_SDRAMC    (0xffffea00 - AT91_BASE_SYS)
+#define AT91_SMC       (0xffffec00 - AT91_BASE_SYS)
+#define AT91_MATRIX    (0xffffee00 - AT91_BASE_SYS)
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)
+#define AT91_DBGU      (0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOA      (0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOB      (0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOC      (0xfffff800 - AT91_BASE_SYS)
+#define AT91_PMC       (0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC      (0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC     (0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT       (0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT       (0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT       (0xfffffd40 - AT91_BASE_SYS)
+#define AT91_GPBR      (0xfffffd50 - AT91_BASE_SYS)
+
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9261_SRAM_BASE  0x00300000      /* Internal SRAM base address */
+#define AT91SAM9261_SRAM_SIZE  0x00028000      /* Internal SRAM size (160Kb) */
+
+#define AT91SAM9261_ROM_BASE   0x00400000      /* Internal ROM base address */
+#define AT91SAM9261_ROM_SIZE   SZ_32K          /* Internal ROM size (32Kb) */
+
+#define AT91SAM9261_UHP_BASE   0x00500000      /* USB Host controller */
+#define AT91SAM9261_LCDC_BASE  0x00600000      /* LDC controller */
+
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+#define AT91_PA0_SPI0_MISO     (1 <<  0)       /* A: SPI0 Master In Slave */
+#define AT91_PA0_MCDA0         (1 <<  0)       /* B: Multimedia Card A Data 0 */
+#define AT91_PA1_SPI0_MOSI     (1 <<  1)       /* A: SPI0 Master Out Slave */
+#define AT91_PA1_MCCDA         (1 <<  1)       /* B: Multimedia Card A Command */
+#define AT91_PA2_SPI0_SPCK     (1 <<  2)       /* A: SPI0 Serial Clock */
+#define AT91_PA2_MCCK          (1 <<  2)       /* B: Multimedia Card Clock */
+#define AT91_PA3_SPI0_NPCS0    (1 <<  3)       /* A: SPI0 Peripheral Chip Select 0 */
+#define AT91_PA4_SPI0_NPCS1    (1 <<  4)       /* A: SPI0 Peripheral Chip Select 1 */
+#define AT91_PA4_MCDA1         (1 <<  4)       /* B: Multimedia Card A Data 1 */
+#define AT91_PA5_SPI0_NPCS2    (1 <<  5)       /* A: SPI0 Peripheral Chip Select 2 */
+#define AT91_PA5_MCDA2         (1 <<  5)       /* B: Multimedia Card A Data 2 */
+#define AT91_PA6_SPI0_NPCS3    (1 <<  6)       /* A: SPI0 Peripheral Chip Select 3 */
+#define AT91_PA6_MCDA3         (1 <<  6)       /* B: Multimedia Card A Data 3 */
+#define AT91_PA7_TWD           (1 <<  7)       /* A: TWI Two-wire Serial Data */
+#define AT91_PA7_PCK0          (1 <<  7)       /* B: PMC Programmable clock Output 0 */
+#define AT91_PA8_TWCK          (1 <<  8)       /* A: TWI Two-wire Serial Clock */
+#define AT91_PA8_PCK1          (1 <<  8)       /* B: PMC Programmable clock Output 1 */
+#define AT91_PA9_DRXD          (1 <<  9)       /* A: DBGU Debug Receive Data */
+#define AT91_PA9_PCK2          (1 <<  9)       /* B: PMC Programmable clock Output 2 */
+#define AT91_PA10_DTXD         (1 << 10)       /* A: DBGU Debug Transmit Data */
+#define AT91_PA10_PCK3         (1 << 10)       /* B: PMC Programmable clock Output 3 */
+#define AT91_PA11_TSYNC                (1 << 11)       /* A: Trace Synchronization Signal */
+#define AT91_PA11_SCK1         (1 << 11)       /* B: USART1 Serial Clock */
+#define AT91_PA12_TCLK         (1 << 12)       /* A: Trace Clock */
+#define AT91_PA12_RTS1         (1 << 12)       /* B: USART1 Ready To Send */
+#define AT91_PA13_TPS0         (1 << 13)       /* A: Trace ARM Pipeline Status 0 */
+#define AT91_PA13_CTS1         (1 << 13)       /* B: USART1 Clear To Send */
+#define AT91_PA14_TPS1         (1 << 14)       /* A: Trace ARM Pipeline Status 1 */
+#define AT91_PA14_SCK2         (1 << 14)       /* B: USART2 Serial Clock */
+#define AT91_PA15_TPS2         (1 << 15)       /* A: Trace ARM Pipeline Status 2 */
+#define AT91_PA15_RTS2         (1 << 15)       /* B: USART2 Ready To Send */
+#define AT91_PA16_TPK0         (1 << 16)       /* A: Trace Packet Port 0 */
+#define AT91_PA16_CTS2         (1 << 16)       /* B: USART2 Clear To Send */
+#define AT91_PA17_TPK1         (1 << 17)       /* A: Trace Packet Port 1 */
+#define AT91_PA17_TF1          (1 << 17)       /* B: SSC1 Transmit Frame Sync */
+#define AT91_PA18_TPK2         (1 << 18)       /* A: Trace Packet Port 2 */
+#define AT91_PA18_TK1          (1 << 18)       /* B: SSC1 Transmit Clock */
+#define AT91_PA19_TPK3         (1 << 19)       /* A: Trace Packet Port 3 */
+#define AT91_PA19_TD1          (1 << 19)       /* B: SSC1 Transmit Data */
+#define AT91_PA20_TPK4         (1 << 20)       /* A: Trace Packet Port 4 */
+#define AT91_PA20_RD1          (1 << 20)       /* B: SSC1 Receive Data */
+#define AT91_PA21_TPK5         (1 << 21)       /* A: Trace Packet Port 5 */
+#define AT91_PA21_RK1          (1 << 21)       /* B: SSC1 Receive Clock */
+#define AT91_PA22_TPK6         (1 << 22)       /* A: Trace Packet Port 6 */
+#define AT91_PA22_RF1          (1 << 22)       /* B: SSC1 Receive Frame Sync */
+#define AT91_PA23_TPK7         (1 << 23)       /* A: Trace Packet Port 7 */
+#define AT91_PA23_RTS0         (1 << 23)       /* B: USART0 Ready To Send */
+#define AT91_PA24_TPK8         (1 << 24)       /* A: Trace Packet Port 8 */
+#define AT91_PA24_SPI1_NPCS1   (1 << 24)       /* B: SPI1 Peripheral Chip Select 1 */
+#define AT91_PA25_TPK9         (1 << 25)       /* A: Trace Packet Port 9 */
+#define AT91_PA25_SPI1_NPCS2   (1 << 25)       /* B: SPI1 Peripheral Chip Select 2 */
+#define AT91_PA26_TPK10                (1 << 26)       /* A: Trace Packet Port 10 */
+#define AT91_PA26_SPI1_NPCS3   (1 << 26)       /* B: SPI1 Peripheral Chip Select 3 */
+#define AT91_PA27_TPK11                (1 << 27)       /* A: Trace Packet Port 11 */
+#define AT91_PA27_SPI0_NPCS1   (1 << 27)       /* B: SPI0 Peripheral Chip Select 1 */
+#define AT91_PA28_TPK12                (1 << 28)       /* A: Trace Packet Port 12 */
+#define AT91_PA28_SPI0_NPCS2   (1 << 28)       /* B: SPI0 Peripheral Chip Select 2 */
+#define AT91_PA29_TPK13                (1 << 29)       /* A: Trace Packet Port 13 */
+#define AT91_PA29_SPI0_NPCS3   (1 << 29)       /* B: SPI0 Peripheral Chip Select 3 */
+#define AT91_PA30_TPK14                (1 << 30)       /* A: Trace Packet Port 14 */
+#define AT91_PA30_A23          (1 << 30)       /* B: Address Bus bit 23 */
+#define AT91_PA31_TPK15                (1 << 31)       /* A: Trace Packet Port 15 */
+#define AT91_PA31_A24          (1 << 31)       /* B: Address Bus bit 24 */
+
+#define AT91_PB0_LCDVSYNC      (1 <<  0)       /* A: LCD Vertical Synchronization */
+#define AT91_PB1_LCDHSYNC      (1 <<  1)       /* A: LCD Horizontal Synchronization */
+#define AT91_PB2_LCDDOTCK      (1 <<  2)       /* A: LCD Dot Clock */
+#define AT91_PB2_PCK0          (1 <<  2)       /* B: PMC Programmable clock Output 0 */
+#define AT91_PB3_LCDDEN                (1 <<  3)       /* A: LCD Data Enable */
+#define AT91_PB4_LCDCC         (1 <<  4)       /* A: LCD Contrast Control */
+#define AT91_PB4_LCDD2         (1 <<  4)       /* B: LCD Data Bus Bit 2 */
+#define AT91_PB5_LCDD0         (1 <<  5)       /* A: LCD Data Bus Bit 0 */
+#define AT91_PB5_LCDD3         (1 <<  5)       /* B: LCD Data Bus Bit 3 */
+#define AT91_PB6_LCDD1         (1 <<  6)       /* A: LCD Data Bus Bit 1 */
+#define AT91_PB6_LCDD4         (1 <<  6)       /* B: LCD Data Bus Bit 4 */
+#define AT91_PB7_LCDD2         (1 <<  7)       /* A: LCD Data Bus Bit 2 */
+#define AT91_PB7_LCDD5         (1 <<  7)       /* B: LCD Data Bus Bit 5 */
+#define AT91_PB8_LCDD3         (1 <<  8)       /* A: LCD Data Bus Bit 3 */
+#define AT91_PB8_LCDD6         (1 <<  8)       /* B: LCD Data Bus Bit 6 */
+#define AT91_PB9_LCDD4         (1 <<  9)       /* A: LCD Data Bus Bit 4 */
+#define AT91_PB9_LCDD7         (1 <<  9)       /* B: LCD Data Bus Bit 7 */
+#define AT91_PB10_LCDD5                (1 << 10)       /* A: LCD Data Bus Bit 5 */
+#define AT91_PB10_LCDD10       (1 << 10)       /* B: LCD Data Bus Bit 10 */
+#define AT91_PB11_LCDD6                (1 << 11)       /* A: LCD Data Bus Bit 6 */
+#define AT91_PB11_LCDD11       (1 << 11)       /* B: LCD Data Bus Bit 11 */
+#define AT91_PB12_LCDD7                (1 << 12)       /* A: LCD Data Bus Bit 7 */
+#define AT91_PB12_LCDD12       (1 << 12)       /* B: LCD Data Bus Bit 12 */
+#define AT91_PB13_LCDD8                (1 << 13)       /* A: LCD Data Bus Bit 8 */
+#define AT91_PB13_LCDD13       (1 << 13)       /* B: LCD Data Bus Bit 13 */
+#define AT91_PB14_LCDD9                (1 << 14)       /* A: LCD Data Bus Bit 9 */
+#define AT91_PB14_LCDD14       (1 << 14)       /* B: LCD Data Bus Bit 14 */
+#define AT91_PB15_LCDD10       (1 << 15)       /* A: LCD Data Bus Bit 10 */
+#define AT91_PB15_LCDD15       (1 << 15)       /* B: LCD Data Bus Bit 15 */
+#define AT91_PB16_LCDD11       (1 << 16)       /* A: LCD Data Bus Bit 11 */
+#define AT91_PB16_LCDD19       (1 << 16)       /* B: LCD Data Bus Bit 19 */
+#define AT91_PB17_LCDD12       (1 << 17)       /* A: LCD Data Bus Bit 12 */
+#define AT91_PB17_LCDD20       (1 << 17)       /* B: LCD Data Bus Bit 20 */
+#define AT91_PB18_LCDD13       (1 << 18)       /* A: LCD Data Bus Bit 13 */
+#define AT91_PB18_LCDD21       (1 << 18)       /* B: LCD Data Bus Bit 21 */
+#define AT91_PB19_LCDD14       (1 << 19)       /* A: LCD Data Bus Bit 14 */
+#define AT91_PB19_LCDD22       (1 << 19)       /* B: LCD Data Bus Bit 22 */
+#define AT91_PB20_LCDD15       (1 << 20)       /* A: LCD Data Bus Bit 15 */
+#define AT91_PB20_LCDD23       (1 << 20)       /* B: LCD Data Bus Bit 23 */
+#define AT91_PB21_TF0          (1 << 21)       /* A: SSC0 Transmit Frame Sync */
+#define AT91_PB21_LCDD16       (1 << 21)       /* B: LCD Data Bus Bit 16 */
+#define AT91_PB22_TK0          (1 << 22)       /* A: SSC0 Transmit Clock */
+#define AT91_PB22_LCDD17       (1 << 22)       /* B: LCD Data Bus Bit 17 */
+#define AT91_PB23_TD0          (1 << 23)       /* A: SSC0 Transmit Data */
+#define AT91_PB23_LCDD18       (1 << 23)       /* B: LCD Data Bus Bit 18 */
+#define AT91_PB24_RD0          (1 << 24)       /* A: SSC0 Receive Data */
+#define AT91_PB24_LCDD19       (1 << 24)       /* B: LCD Data Bus Bit 19 */
+#define AT91_PB25_RK0          (1 << 25)       /* A: SSC0 Receive Clock */
+#define AT91_PB25_LCDD20       (1 << 25)       /* B: LCD Data Bus Bit 20 */
+#define AT91_PB26_RF0          (1 << 26)       /* A: SSC0 Receive Frame Sync */
+#define AT91_PB26_LCDD21       (1 << 26)       /* B: LCD Data Bus Bit 21 */
+#define AT91_PB27_SPI1_NPCS1   (1 << 27)       /* A: SPI1 Peripheral Chip Select 1 */
+#define AT91_PB27_LCDD22       (1 << 27)       /* B: LCD Data Bus Bit 22 */
+#define AT91_PB28_SPI1_NPCS0   (1 << 28)       /* A: SPI1 Peripheral Chip Select 0 */
+#define AT91_PB28_LCDD23       (1 << 28)       /* B: LCD Data Bus Bit 23 */
+#define AT91_PB29_SPI1_SPCK    (1 << 29)       /* A: SPI1 Serial Clock */
+#define AT91_PB29_IRQ2         (1 << 29)       /* B: Interrupt input 2 */
+#define AT91_PB30_SPI1_MISO    (1 << 30)       /* A: SPI1 Master In Slave */
+#define AT91_PB30_IRQ1         (1 << 30)       /* B: Interrupt input 1 */
+#define AT91_PB31_SPI1_MOSI    (1 << 31)       /* A: SPI1 Master Out Slave */
+#define AT91_PB31_PCK2         (1 << 31)       /* B: PMC Programmable clock Output 2 */
+
+#define AT91_PC0_SMOE          (1 << 0)        /* A: SmartMedia Output Enable */
+#define AT91_PC0_NCS6          (1 << 0)        /* B: Chip Select 6 */
+#define AT91_PC1_SMWE          (1 << 1)        /* A: SmartMedia Write Enable */
+#define AT91_PC1_NCS7          (1 << 1)        /* B: Chip Select 7 */
+#define AT91_PC2_NWAIT         (1 << 2)        /* A: NWAIT */
+#define AT91_PC2_IRQ0          (1 << 2)        /* B: Interrupt input 0 */
+#define AT91_PC3_A25_CFRNW     (1 << 3)        /* A: Address Bus[25] / Compact Flash Read Not Write */
+#define AT91_PC4_NCS4_CFCS0    (1 << 4)        /* A: Chip Select 4 / CompactFlash Chip Select 0 */
+#define AT91_PC5_NCS5_CFCS1    (1 << 5)        /* A: Chip Select 5 / CompactFlash Chip Select 1 */
+#define AT91_PC6_CFCE1         (1 << 6)        /* A: CompactFlash Chip Enable 1 */
+#define AT91_PC7_CFCE2         (1 << 7)        /* A: CompactFlash Chip Enable 2 */
+#define AT91_PC8_TXD0          (1 << 8)        /* A: USART0 Transmit Data */
+#define AT91_PC8_PCK2          (1 << 8)        /* B: PMC Programmable clock Output 2 */
+#define AT91_PC9_RXD0          (1 << 9)        /* A: USART0 Receive Data */
+#define AT91_PC9_PCK3          (1 << 9)        /* B: PMC Programmable clock Output 3 */
+#define AT91_PC10_RTS0         (1 << 10)       /* A: USART0 Ready To Send */
+#define AT91_PC10_SCK0         (1 << 10)       /* B: USART0 Serial Clock */
+#define AT91_PC11_CTS0         (1 << 11)       /* A: USART0 Clear To Send */
+#define AT91_PC11_FIQ          (1 << 11)       /* B: AIC Fast Interrupt Input */
+#define AT91_PC12_TXD1         (1 << 12)       /* A: USART1 Transmit Data */
+#define AT91_PC12_NCS6         (1 << 12)       /* B: Chip Select 6 */
+#define AT91_PC13_RXD1         (1 << 13)       /* A: USART1 Receive Data */
+#define AT91_PC13_NCS7         (1 << 13)       /* B: Chip Select 7 */
+#define AT91_PC14_TXD2         (1 << 14)       /* A: USART2 Transmit Data */
+#define AT91_PC14_SPI1_NPCS2   (1 << 14)       /* B: SPI1 Peripheral Chip Select 2 */
+#define AT91_PC15_RXD2         (1 << 15)       /* A: USART2 Receive Data */
+#define AT91_PC15_SPI1_NPCS3   (1 << 15)       /* B: SPI1 Peripheral Chip Select 3 */
+#define AT91_PC16_D16          (1 << 16)       /* A: Data Bus [16] */
+#define AT91_PC16_TCLK0                (1 << 16)       /* B: Timer Counter 0 external clock input */
+#define AT91_PC17_D17          (1 << 17)       /* A: Data Bus [17] */
+#define AT91_PC17_TCLK1                (1 << 17)       /* B: Timer Counter 1 external clock input */
+#define AT91_PC18_D18          (1 << 18)       /* A: Data Bus [18] */
+#define AT91_PC18_TCLK2                (1 << 18)       /* B: Timer Counter 2 external clock input */
+#define AT91_PC19_D19          (1 << 19)       /* A: Data Bus [19] */
+#define AT91_PC19_TIOA0                (1 << 19)       /* B: Timer Counter 0 Multipurpose Timer I/O Pin A */
+#define AT91_PC20_D20          (1 << 20)       /* A: Data Bus [20] */
+#define AT91_PC20_TIOB0                (1 << 20)       /* B: Timer Counter 0 Multipurpose Timer I/O Pin B */
+#define AT91_PC21_D21          (1 << 21)       /* A: Data Bus [21] */
+#define AT91_PC21_TIOA1                (1 << 21)       /* B: Timer Counter 1 Multipurpose Timer I/O Pin A */
+#define AT91_PC22_D22          (1 << 22)       /* A: Data Bus [22] */
+#define AT91_PC22_TIOB1                (1 << 22)       /* B: Timer Counter 1 Multipurpose Timer I/O Pin B */
+#define AT91_PC23_D23          (1 << 23)       /* A: Data Bus [23] */
+#define AT91_PC23_TIOA2                (1 << 23)       /* B: Timer Counter 2 Multipurpose Timer I/O Pin A */
+#define AT91_PC24_D24          (1 << 24)       /* A: Data Bus [24] */
+#define AT91_PC24_TIOB2                (1 << 24)       /* B: Timer Counter 2 Multipurpose Timer I/O Pin B */
+#define AT91_PC25_D25          (1 << 25)       /* A: Data Bus [25] */
+#define AT91_PC25_TF2          (1 << 25)       /* B: SSC2 Transmit Frame Sync */
+#define AT91_PC26_D26          (1 << 26)       /* A: Data Bus [26] */
+#define AT91_PC26_TK2          (1 << 26)       /* B: SSC2 Transmit Clock */
+#define AT91_PC27_D27          (1 << 27)       /* A: Data Bus [27] */
+#define AT91_PC27_TD2          (1 << 27)       /* B: SSC2 Transmit Data */
+#define AT91_PC28_D28          (1 << 28)       /* A: Data Bus [28] */
+#define AT91_PC28_RD2          (1 << 28)       /* B: SSC2 Receive Data */
+#define AT91_PC29_D29          (1 << 29)       /* A: Data Bus [29] */
+#define AT91_PC29_RK2          (1 << 29)       /* B: SSC2 Receive Clock */
+#define AT91_PC30_D30          (1 << 30)       /* A: Data Bus [30] */
+#define AT91_PC30_RF2          (1 << 30)       /* B: SSC2 Receive Frame Sync */
+#define AT91_PC31_D31          (1 << 31)       /* A: Data Bus [31] */
+#define AT91_PC31_PCK1         (1 << 31)       /* B: PMC Programmable clock Output 1 */
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
new file mode 100644 (file)
index 0000000..270a5dc
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91SAM9261_MATRIX_H
+#define AT91SAM9261_MATRIX_H
+
+#define AT91_MATRIX_MCFG       (AT91_MATRIX + 0x00)    /* Master Configuration Register */
+#define                AT91_MATRIX_RCB0        (1 << 0)                /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define                AT01_MATRIX_RCB1        (1 << 1)                /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+
+#define AT91_MATRIX_SCFG0      (AT91_MATRIX + 0x04)    /* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1      (AT91_MATRIX + 0x08)    /* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2      (AT91_MATRIX + 0x0C)    /* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3      (AT91_MATRIX + 0x10)    /* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4      (AT91_MATRIX + 0x14)    /* Slave Configuration Register 4 */
+#define                AT91_MATRIX_SLOT_CYCLE          (0xff << 0)     /* Maximum Number of Allowed Cycles for a Burst */
+#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
+#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
+#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
+#define                AT91_MATRIX_FIXED_DEFMSTR       (7    << 18)    /* Fixed Index of Default Master */
+
+#define AT91_MATRIX_TCR                (AT91_MATRIX + 0x24)    /* TCM Configuration Register */
+#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
+#define                        AT91_MATRIX_ITCM_0              (0 << 0)
+#define                        AT91_MATRIX_ITCM_16             (5 << 0)
+#define                        AT91_MATRIX_ITCM_32             (6 << 0)
+#define                        AT91_MATRIX_ITCM_64             (7 << 0)
+#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
+#define                        AT91_MATRIX_DTCM_0              (0 << 4)
+#define                        AT91_MATRIX_DTCM_16             (5 << 4)
+#define                        AT91_MATRIX_DTCM_32             (6 << 4)
+#define                        AT91_MATRIX_DTCM_64             (7 << 4)
+
+#define AT91_MATRIX_EBICSA     (AT91_MATRIX + 0x30)    /* EBI Chip Select Assignment Register */
+#define                AT91_MATRIX_CS1A                (1 << 1)        /* Chip Select 1 Assignment */
+#define                AT91_MATRIX_CS1A_SMC            (0 << 1)
+#define                AT91_MATRIX_CS1A_SDRAMC         (1 << 1)
+#define                AT91_MATRIX_CS3A                (1 << 3)        /* Chip Select 3 Assignment */
+#define                        AT91_MATRIX_CS3A_SMC            (0 << 3)
+#define                        AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
+#define                AT91_MATRIX_CS4A                (1 << 4)        /* Chip Select 4 Assignment */
+#define                        AT91_MATRIX_CS4A_SMC            (0 << 4)
+#define                        AT91_MATRIX_CS4A_SMC_CF1        (1 << 4)
+#define                AT91_MATRIX_CS5A                (1 << 5)        /* Chip Select 5 Assignment */
+#define                        AT91_MATRIX_CS5A_SMC            (0 << 5)
+#define                        AT91_MATRIX_CS5A_SMC_CF2        (1 << 5)
+#define                AT91_MATRIX_DBPUC               (1 << 8)        /* Data Bus Pull-up Configuration */
+
+#define AT91_MATRIX_USBPUCR    (AT91_MATRIX + 0x34)    /* USB Pad Pull-Up Control Register */
+#define                AT91_MATRIX_USBPUCR_PUON        (1 << 30)       /* USB Device PAD Pull-up Enable */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
new file mode 100644 (file)
index 0000000..7d94968
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+ *
+ * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91SAM926x_MC_H
+#define AT91SAM926x_MC_H
+
+/* SDRAM Controller (SDRAMC) registers */
+#define AT91_SDRAMC_MR         (AT91_SDRAMC + 0x00)    /* SDRAM Controller Mode Register */
+#define                AT91_SDRAMC_MODE        (0xf << 0)              /* Command Mode */
+#define                        AT91_SDRAMC_MODE_NORMAL         0
+#define                        AT91_SDRAMC_MODE_NOP            1
+#define                        AT91_SDRAMC_MODE_PRECHARGE      2
+#define                        AT91_SDRAMC_MODE_LMR            3
+#define                        AT91_SDRAMC_MODE_REFRESH        4
+#define                        AT91_SDRAMC_MODE_EXT_LMR        5
+#define                        AT91_SDRAMC_MODE_DEEP           6
+
+#define AT91_SDRAMC_TR         (AT91_SDRAMC + 0x04)    /* SDRAM Controller Refresh Timer Register */
+#define                AT91_SDRAMC_COUNT       (0xfff << 0)            /* Refresh Timer Counter */
+
+#define AT91_SDRAMC_CR         (AT91_SDRAMC + 0x08)    /* SDRAM Controller Configuration Register */
+#define                AT91_SDRAMC_NC          (3 << 0)                /* Number of Column Bits */
+#define                        AT91_SDRAMC_NC_8        (0 << 0)
+#define                        AT91_SDRAMC_NC_9        (1 << 0)
+#define                        AT91_SDRAMC_NC_10       (2 << 0)
+#define                        AT91_SDRAMC_NC_11       (3 << 0)
+#define        AT91_SDRAMC_NR          (3 << 2)                /* Number of Row Bits */
+#define                        AT91_SDRAMC_NR_11       (0 << 2)
+#define                        AT91_SDRAMC_NR_12       (1 << 2)
+#define                        AT91_SDRAMC_NR_13       (2 << 2)
+#define        AT91_SDRAMC_NB          (1 << 4)                /* Number of Banks */
+#define                        AT91_SDRAMC_NB_2        (0 << 4)
+#define                AT91_SDRAMC_NB_4        (1 << 4)
+#define        AT91_SDRAMC_CAS         (3 << 5)                /* CAS Latency */
+#define                        AT91_SDRAMC_CAS_1       (1 << 5)
+#define                        AT91_SDRAMC_CAS_2       (2 << 5)
+#define                        AT91_SDRAMC_CAS_3       (3 << 5)
+#define                AT91_SDRAMC_DBW         (1 << 7)                /* Data Bus Width */
+#define                        AT91_SDRAMC_DBW_32      (0 << 7)
+#define                        AT91_SDRAMC_DBW_16      (1 << 7)
+#define                AT91_SDRAMC_TWR         (0xf <<  8)             /* Write Recovery Delay */
+#define                AT91_SDRAMC_TRC         (0xf << 12)             /* Row Cycle Delay */
+#define                AT91_SDRAMC_TRP         (0xf << 16)             /* Row Precharge Delay */
+#define                AT91_SDRAMC_TRCD        (0xf << 20)             /* Row to Column Delay */
+#define                AT91_SDRAMC_TRAS        (0xf << 24)             /* Active to Precharge Delay */
+#define                AT91_SDRAMC_TXSR        (0xf << 28)             /* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_LPR                (AT91_SDRAMC + 0x10)    /* SDRAM Controller Low Power Register */
+#define                AT91_SDRAMC_LPCB                (3 << 0)        /* Low-power Configurations */
+#define                        AT91_SDRAMC_LPCB_DISABLE                0
+#define                        AT91_SDRAMC_LPCB_SELF_REFRESH           1
+#define                        AT91_SDRAMC_LPCB_POWER_DOWN             2
+#define                        AT91_SDRAMC_LPCB_DEEP_POWER_DOWN        3
+#define                AT91_SDRAMC_PASR                (7 << 4)        /* Partial Array Self Refresh */
+#define                AT91_SDRAMC_TCSR                (3 << 8)        /* Temperature Compensated Self Refresh */
+#define                AT91_SDRAMC_DS                  (3 << 10)       /* Drive Strenght */
+#define                AT91_SDRAMC_TIMEOUT             (3 << 12)       /* Time to define when Low Power Mode is enabled */
+#define                        AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES        (0 << 12)
+#define                        AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES       (1 << 12)
+#define                        AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES      (2 << 12)
+
+#define AT91_SDRAMC_IER                (AT91_SDRAMC + 0x14)    /* SDRAM Controller Interrupt Enable Register */
+#define AT91_SDRAMC_IDR                (AT91_SDRAMC + 0x18)    /* SDRAM Controller Interrupt Disable Register */
+#define AT91_SDRAMC_IMR                (AT91_SDRAMC + 0x1C)    /* SDRAM Controller Interrupt Mask Register */
+#define AT91_SDRAMC_ISR                (AT91_SDRAMC + 0x20)    /* SDRAM Controller Interrupt Status Register */
+#define                AT91_SDRAMC_RES         (1 << 0)                /* Refresh Error Status */
+
+#define AT91_SDRAMC_MDR                (AT91_SDRAMC + 0x24)    /* SDRAM Memory Device Register */
+#define                AT91_SDRAMC_MD          (3 << 0)                /* Memory Device Type */
+#define                        AT91_SDRAMC_MD_SDRAM            0
+#define                        AT91_SDRAMC_MD_LOW_POWER_SDRAM  1
+
+
+/* Static Memory Controller (SMC) registers */
+#define AT91_SMC_SETUP(n)      (AT91_SMC + 0x00 + ((n)*0x10))  /* Setup Register for CS n */
+#define                AT91_SMC_NWESETUP       (0x3f << 0)                     /* NWE Setup Length */
+#define                        AT91_SMC_NWESETUP_(x)   ((x) << 0)
+#define                AT91_SMC_NCS_WRSETUP    (0x3f << 8)                     /* NCS Setup Length in Write Access */
+#define                        AT91_SMC_NCS_WRSETUP_(x)        ((x) << 8)
+#define                AT91_SMC_NRDSETUP       (0x3f << 16)                    /* NRD Setup Length */
+#define                        AT91_SMC_NRDSETUP_(x)   ((x) << 16)
+#define                AT91_SMC_NCS_RDSETUP    (0x3f << 24)                    /* NCS Setup Length in Read Access */
+#define                        AT91_SMC_NCS_RDSETUP_(x)        ((x) << 24)
+
+#define AT91_SMC_PULSE(n)      (AT91_SMC + 0x04 + ((n)*0x10))  /* Pulse Register for CS n */
+#define                AT91_SMC_NWEPULSE       (0x7f <<  0)                    /* NWE Pulse Length */
+#define                        AT91_SMC_NWEPULSE_(x)   ((x) << 0)
+#define                AT91_SMC_NCS_WRPULSE    (0x7f <<  8)                    /* NCS Pulse Length in Write Access */
+#define                        AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
+#define                AT91_SMC_NRDPULSE       (0x7f << 16)                    /* NRD Pulse Length */
+#define                        AT91_SMC_NRDPULSE_(x)   ((x) << 16)
+#define                AT91_SMC_NCS_RDPULSE    (0x7f << 24)                    /* NCS Pulse Length in Read Access */
+#define                        AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
+
+#define AT91_SMC_CYCLE(n)      (AT91_SMC + 0x08 + ((n)*0x10))  /* Cycle Register for CS n */
+#define                AT91_SMC_NWECYCLE       (0x1ff << 0 )                   /* Total Write Cycle Length */
+#define                        AT91_SMC_NWECYCLE_(x)   ((x) << 0)
+#define                AT91_SMC_NRDCYCLE       (0x1ff << 16)                   /* Total Read Cycle Length */
+#define                        AT91_SMC_NRDCYCLE_(x)   ((x) << 16)
+
+#define AT91_SMC_MODE(n)       (AT91_SMC + 0x0c + ((n)*0x10))  /* Mode Register for CS n */
+#define                AT91_SMC_READMODE       (1 <<  0)                       /* Read Mode */
+#define                AT91_SMC_WRITEMODE      (1 <<  1)                       /* Write Mode */
+#define                AT91_SMC_EXNWMODE       (3 <<  5)                       /* NWAIT Mode */
+#define                        AT91_SMC_EXNWMODE_DISABLE       (0 << 5)
+#define                        AT91_SMC_EXNWMODE_FROZEN        (2 << 5)
+#define                        AT91_SMC_EXNWMODE_READY         (3 << 5)
+#define                AT91_SMC_BAT            (1 <<  8)                       /* Byte Access Type */
+#define                        AT91_SMC_BAT_SELECT             (0 << 8)
+#define                        AT91_SMC_BAT_WRITE              (1 << 8)
+#define                AT91_SMC_DBW            (3 << 12)                       /* Data Bus Width */
+#define                        AT91_SMC_DBW_8                  (0 << 12)
+#define                        AT91_SMC_DBW_16                 (1 << 12)
+#define                        AT91_SMC_DBW_32                 (2 << 12)
+#define                AT91_SMC_TDF            (0xf << 16)                     /* Data Float Time. */
+#define                        AT91_SMC_TDF_(x)                ((x) << 16)
+#define                AT91_SMC_TDFMODE        (1 << 20)                       /* TDF Optimization - Enabled */
+#define                AT91_SMC_PMEN           (1 << 24)                       /* Page Mode Enabled */
+#define                AT91_SMC_PS             (3 << 28)                       /* Page Size */
+#define                        AT91_SMC_PS_4                   (0 << 28)
+#define                        AT91_SMC_PS_8                   (1 << 28)
+#define                        AT91_SMC_PS_16                  (2 << 28)
+#define                        AT91_SMC_PS_32                  (3 << 28)
+
+#endif
index 3cc9aec..768e0fc 100644 (file)
@@ -48,13 +48,14 @@ struct at91_cf_data {
        u8      det_pin;                /* Card detect */
        u8      vcc_pin;                /* power switching */
        u8      rst_pin;                /* card reset */
+       u8      chipselect;             /* EBI Chip Select number */
 };
 extern void __init at91_add_device_cf(struct at91_cf_data *data);
 
  /* MMC / SD */
 struct at91_mmc_data {
        u8              det_pin;        /* card detect IRQ */
-       unsigned        is_b:1;         /* uses B side (vs A) */
+       unsigned        slot_b:1;       /* uses Slot B */
        unsigned        wire4:1;        /* (SD) supports DAT0..DAT3 */
        u8              wp_pin;         /* (SD) writeprotect detect */
        u8              vcc_pin;        /* power switching (high == on) */
@@ -81,7 +82,8 @@ struct at91_nand_data {
        u8              rdy_pin;        /* ready/busy */
        u8              ale;            /* address line number connected to ALE */
        u8              cle;            /* address line number connected to CLE */
-        struct mtd_partition* (*partition_info)(int, int*);
+       u8              bus_width_16;   /* buswidth is 16 bit */
+       struct mtd_partition* (*partition_info)(int, int*);
 };
 extern void __init at91_add_device_nand(struct at91_nand_data *data);
 
diff --git a/include/asm-arm/arch-at91rm9200/cpu.h b/include/asm-arm/arch-at91rm9200/cpu.h
new file mode 100644 (file)
index 0000000..6f8d09b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * include/asm-arm/arch-at91rm9200/cpu.h
+ *
+ *  Copyright (C) 2006 SAN People
+ *
+ * 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 __ASM_ARCH_CPU_H
+#define __ASM_ARCH_CPU_H
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+
+#define ARCH_ID_AT91RM9200     0x09290780
+#define ARCH_ID_AT91SAM9260    0x019803a0
+#define ARCH_ID_AT91SAM9261    0x019703a0
+
+
+static inline unsigned long at91_cpu_identify(void)
+{
+       return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
+}
+
+
+#ifdef CONFIG_ARCH_AT91RM9200
+#define cpu_is_at91rm9200()    (at91_cpu_identify() == ARCH_ID_AT91RM9200)
+#else
+#define cpu_is_at91rm9200()    (0)
+#endif
+
+#ifdef CONFIG_ARCH_AT91SAM9260
+#define cpu_is_at91sam9260()   (at91_cpu_identify() == ARCH_ID_AT91SAM9260)
+#else
+#define cpu_is_at91sam9260()   (0)
+#endif
+
+#ifdef CONFIG_ARCH_AT91SAM9261
+#define cpu_is_at91sam9261()   (at91_cpu_identify() == ARCH_ID_AT91SAM9261)
+#else
+#define cpu_is_at91sam9261()   (0)
+#endif
+
+#endif
index f496b54..85cdadf 100644 (file)
@@ -12,6 +12,7 @@
 */
 
 #include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
 
        .macro  addruart,rx
        mrc     p15, 0, \rx, c1, c0
index 61a326e..57248a7 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <asm/hardware.h>
+#include <asm/arch/at91_aic.h>
 
        .macro  disable_fiq
        .endm
index 9ca4cc9..9ea5bfe 100644 (file)
 
 #include <asm/sizes.h>
 
+#if defined(CONFIG_ARCH_AT91RM9200)
 #include <asm/arch/at91rm9200.h>
-#include <asm/arch/at91rm9200_sys.h>
+#elif defined(CONFIG_ARCH_AT91SAM9260)
+#include <asm/arch/at91sam9260.h>
+#elif defined(CONFIG_ARCH_AT91SAM9261)
+#include <asm/arch/at91sam9261.h>
+#else
+#error "Unsupported AT91 processor"
+#endif
+
 
 /*
  * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF
  * Virtual to Physical Address mapping for IO devices.
  */
 #define AT91_VA_BASE_SYS       AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_VA_BASE_SPI       AT91_IO_P2V(AT91RM9200_BASE_SPI)
 #define AT91_VA_BASE_EMAC      AT91_IO_P2V(AT91RM9200_BASE_EMAC)
-#define AT91_VA_BASE_TWI       AT91_IO_P2V(AT91RM9200_BASE_TWI)
-#define AT91_VA_BASE_MCI       AT91_IO_P2V(AT91RM9200_BASE_MCI)
-#define AT91_VA_BASE_UDP       AT91_IO_P2V(AT91RM9200_BASE_UDP)
 
  /* Internal SRAM is mapped below the IO devices */
-#define AT91_SRAM_VIRT_BASE    (AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE)
+#define AT91_SRAM_MAX          SZ_1M
+#define AT91_VIRT_BASE         (AT91_IO_VIRT_BASE - AT91_SRAM_MAX)
 
 /* Serial ports */
-#define ATMEL_MAX_UART         5               /* 4 USART3's and one DBGU port */
-
-/* FLASH */
-#define AT91_FLASH_BASE                0x10000000      /* NCS0: Flash physical base address */
+#define ATMEL_MAX_UART         7               /* 6 USART3's and one DBGU port (SAM9260) */
+
+/* External Memory Map */
+#define AT91_CHIPSELECT_0      0x10000000
+#define AT91_CHIPSELECT_1      0x20000000
+#define AT91_CHIPSELECT_2      0x30000000
+#define AT91_CHIPSELECT_3      0x40000000
+#define AT91_CHIPSELECT_4      0x50000000
+#define AT91_CHIPSELECT_5      0x60000000
+#define AT91_CHIPSELECT_6      0x70000000
+#define AT91_CHIPSELECT_7      0x80000000
 
 /* SDRAM */
-#define AT91_SDRAM_BASE                0x20000000      /* NCS1: SDRAM physical base address */
-
-/* SmartMedia */
-#define AT91_SMARTMEDIA_BASE   0x40000000      /* NCS3: Smartmedia physical base address */
-
-/* Compact Flash */
-#define AT91_CF_BASE           0x50000000      /* NCS4-NCS6: Compact Flash physical base address */
+#define AT91_SDRAM_BASE                AT91_CHIPSELECT_1
 
 /* Clocks */
 #define AT91_SLOW_CLOCK                32768           /* slow clock */
index 763cb96..c0679ea 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef __ASM_ARCH_IRQS_H
 #define __ASM_ARCH_IRQS_H
 
+#include <asm/arch/at91_aic.h>
+
 #define NR_AIC_IRQS 32
 
 
index 8a2ff47..9c67130 100644 (file)
@@ -22,6 +22,8 @@
 #define __ASM_ARCH_SYSTEM_H
 
 #include <asm/hardware.h>
+#include <asm/arch/at91_st.h>
+#include <asm/arch/at91_dbgu.h>
 
 static inline void arch_idle(void)
 {
@@ -39,21 +41,13 @@ static inline void arch_idle(void)
        cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
-{
-       /*
-        * Perform a hardware reset with the use of the Watchdog timer.
-        */
-       at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
-       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-#define ARCH_ID_AT91RM9200     0x09200080
-#define ARCH_ID_AT91SAM9261    0x019000a0
+void (*at91_arch_reset)(void);
 
-static inline unsigned long arch_identify(void)
+static inline void arch_reset(char mode)
 {
-       return at91_sys_read(AT91_DBGU_CIDR) & (AT91_CIDR_EPROC | AT91_CIDR_ARCH);
+       /* call the CPU-specific reset function */
+       if (at91_arch_reset)
+               (at91_arch_reset)();
 }
 
 #endif
index 88687ce..faeca45 100644 (file)
 
 #include <asm/hardware.h>
 
+#if defined(CONFIG_ARCH_AT91RM9200)
+
 #define CLOCK_TICK_RATE                (AT91_SLOW_CLOCK)
 
+#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261)
+
+#define AT91SAM9_MASTER_CLOCK  99300000
+#define CLOCK_TICK_RATE                (AT91SAM9_MASTER_CLOCK/16)
+
+#endif
+
 #endif
index ec7811a..34b4b93 100644 (file)
 #define __ASM_ARCH_UNCOMPRESS_H
 
 #include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
 
 /*
  * The following code assumes the serial port has already been
- * initialized by the bootloader.  We search for the first enabled
- * port in the most probable order.  If you didn't setup a port in
+ * initialized by the bootloader.  If you didn't setup a port in
  * your bootloader then nothing will appear (which might be desired).
  *
  * This does not append a newline
index 4c367eb..0a23b8c 100644 (file)
@@ -21,6 +21,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END            (AT91_SRAM_VIRT_BASE & PGDIR_MASK)
+#define VMALLOC_END            (AT91_VIRT_BASE & PGDIR_MASK)
 
 #endif
index c6e8dcf..42768cc 100644 (file)
  * memory bank.  For those systems, simply undefine CONFIG_DISCONTIGMEM.
  */
 
-#ifdef CONFIG_DISCONTIGMEM
+/*
+ * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211
+ * uses only one of the two banks (bank #1).  However, even within
+ * bank #1, memory is discontiguous.
+ *
+ * The EDB7211 has two 8MB DRAM areas with 8MB of empty space between
+ * them, so we use 24 for the node max shift to get 16MB node sizes.
+ */
+
 /*
  * Because of the wide memory address space between physical RAM banks on the 
  * SA1100, it's much more convenient to use Linux's NUMA support to implement
  *     node 2:  0xd0000000 - 0xd7ffffff
  *     node 3:  0xd8000000 - 0xdfffffff
  */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(addr) \
-               (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
-
-/*
- * Given a page frame number, convert it to a node id.
- */
-#define PFN_TO_NID(pfn) \
-       (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
-
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the mem_map of that node.
- */
-#define ADDR_TO_MAPBASE(kaddr) \
-                       NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
-
-#define PFN_TO_MAPBASE(pfn)    NODE_MEM_MAP(PFN_TO_NID(pfn))
-
-/*
- * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory
- * and returns the index corresponding to the appropriate page in the
- * node's mem_map.
- */
-#define LOCAL_MAP_NR(addr) \
-       (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
-
-/*
- * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211
- * uses only one of the two banks (bank #1).  However, even within
- * bank #1, memory is discontiguous.
- *
- * The EDB7211 has two 8MB DRAM areas with 8MB of empty space between
- * them, so we use 24 for the node max shift to get 16MB node sizes.
- */
-#define NODE_MAX_MEM_SHIFT     24
-#define NODE_MAX_MEM_SIZE      (1<<NODE_MAX_MEM_SHIFT)
-
-#endif /* CONFIG_DISCONTIGMEM */
+#define NODE_MEM_SIZE_BITS     24
 
 #endif
 
index 8c91674..e22ba78 100644 (file)
@@ -21,7 +21,6 @@
 #ifndef __ASM_ARCH_TIMEX_H
 #define __ASM_ARCH_TIMEX_H
 
-#include <asm/hardware.h>
-#define CLOCK_TICK_RATE                (CLK32)
+#define CLOCK_TICK_RATE                (16000000)
 
 #endif
diff --git a/include/asm-arm/arch-iop13xx/debug-macro.S b/include/asm-arm/arch-iop13xx/debug-macro.S
new file mode 100644 (file)
index 0000000..788b4e3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-iop13xx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+       .macro  addruart, rx
+       mrc     p15, 0, \rx, c1, c0
+       tst     \rx, #1                 @ mmu enabled?
+       moveq   \rx, #0xff000000        @ physical
+       orreq   \rx, \rx, #0x00d80000
+       movne   \rx, #0xfe000000        @ virtual
+       orrne   \rx, \rx, #0x00e80000
+       orr     \rx, \rx, #0x00002300
+       orr     \rx, \rx, #0x00000040
+       .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop13xx/dma.h b/include/asm-arm/arch-iop13xx/dma.h
new file mode 100644 (file)
index 0000000..2e15da5
--- /dev/null
@@ -0,0 +1,3 @@
+#ifndef _IOP13XX_DMA_H
+#define _IOP13XX_DMA_H_
+#endif
diff --git a/include/asm-arm/arch-iop13xx/entry-macro.S b/include/asm-arm/arch-iop13xx/entry-macro.S
new file mode 100644 (file)
index 0000000..94c5028
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * iop13xx low level irq macros
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+       .macro  disable_fiq
+       .endm
+
+       /*
+        * Note: a 1-cycle window exists where iintvec will return the value
+        * of iintbase, so we explicitly check for "bad zeros"
+        */
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+
+       mrc     p6, 0, \irqnr, c3, c2, 0        @ Read IINTVEC
+       cmp     \irqnr, #0
+       mrceq   p6, 0, \irqnr, c3, c2, 0        @ Re-read on potentially bad zero
+       adds    \irqstat, \irqnr, #1            @ Check for 0xffffffff
+       movne   \irqnr, \irqnr, lsr #2          @ Convert to irqnr
+
+       biceq   \tmp, \tmp, #(1 << 6)
+       mcreq   p15, 0, \tmp, c15, c1, 0        @ Disable cp6 access if no more interrupts
+       .endm
diff --git a/include/asm-arm/arch-iop13xx/hardware.h b/include/asm-arm/arch-iop13xx/hardware.h
new file mode 100644 (file)
index 0000000..8e1d562
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+#include <asm/types.h>
+
+#define pcibios_assign_all_busses() 1
+
+#ifndef __ASSEMBLY__
+extern unsigned long iop13xx_pcibios_min_io;
+extern unsigned long iop13xx_pcibios_min_mem;
+extern u16 iop13xx_dev_id(void);
+extern void iop13xx_set_atu_mmr_bases(void);
+#endif
+
+#define PCIBIOS_MIN_IO      (iop13xx_pcibios_min_io)
+#define PCIBIOS_MIN_MEM     (iop13xx_pcibios_min_mem)
+
+/*
+ * Generic chipset bits
+ *
+ */
+#include "iop13xx.h"
+
+/*
+ * Board specific bits
+ */
+#include "iq81340.h"
+
+#endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-iop13xx/io.h b/include/asm-arm/arch-iop13xx/io.h
new file mode 100644 (file)
index 0000000..db6de24
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * iop13xx custom ioremap implementation
+ * Copyright (c) 2005-2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)      (a)
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (a)
+
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop13xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags);
+extern void __iop13xx_iounmap(void __iomem *addr);
+
+extern u32 iop13xx_atue_mem_base;
+extern u32 iop13xx_atux_mem_base;
+extern size_t iop13xx_atue_mem_size;
+extern size_t iop13xx_atux_mem_size;
+
+#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
+#define __arch_iounmap(a)       __iop13xx_iounmap(a)
+
+#endif
diff --git a/include/asm-arm/arch-iop13xx/iop13xx.h b/include/asm-arm/arch-iop13xx/iop13xx.h
new file mode 100644 (file)
index 0000000..a88522a
--- /dev/null
@@ -0,0 +1,492 @@
+#ifndef _IOP13XX_HW_H_
+#define _IOP13XX_HW_H_
+
+#ifndef __ASSEMBLY__
+/* The ATU offsets can change based on the strapping */
+extern u32 iop13xx_atux_pmmr_offset;
+extern u32 iop13xx_atue_pmmr_offset;
+void iop13xx_init_irq(void);
+void iop13xx_map_io(void);
+void iop13xx_platform_init(void);
+void iop13xx_init_irq(void);
+void iop13xx_init_time(unsigned long tickrate);
+unsigned long iop13xx_gettimeoffset(void);
+
+/* handle cp6 access
+ * to do: handle access in entry-armv5.S and unify with
+ * the iop3xx implementation
+ * note: use iop13xx_cp6_enable_irq_save and iop13xx_cp6_irq_restore (irq.h)
+ * when interrupts are enabled
+ */
+static inline unsigned long iop13xx_cp6_save(void)
+{
+       u32 temp, cp_flags;
+
+       asm volatile (
+               "mrc    p15, 0, %1, c15, c1, 0\n\t"
+               "orr    %0, %1, #(1 << 6)\n\t"
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               : "=r" (temp), "=r"(cp_flags));
+
+       return cp_flags;
+}
+
+static inline void iop13xx_cp6_restore(unsigned long cp_flags)
+{
+       asm volatile (
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               : : "r" (cp_flags) );
+}
+
+/* CPUID CP6 R0 Page 0 */
+static inline int iop13xx_cpu_id(void)
+{
+       int id;
+       asm volatile("mrc p6, 0, %0, c0, c0, 0":"=r" (id));
+       return id;
+}
+
+#endif
+
+/*
+ * IOP13XX I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP13XX_MAX_RAM_SIZE    0x80000000UL  /* 2GB */
+#define IOP13XX_PCI_OFFSET      IOP13XX_MAX_RAM_SIZE
+
+/* PCI MAP
+ * 0x0000.0000 - 0x8000.0000           1:1 mapping with Physical RAM
+ * 0x8000.0000 - 0x8800.0000           PCIX/PCIE memory window (128MB)
+*/
+#define IOP13XX_PCIX_IO_WINDOW_SIZE   0x10000UL
+#define IOP13XX_PCIX_LOWER_IO_PA      0xfffb0000UL
+#define IOP13XX_PCIX_LOWER_IO_VA      0xfec60000UL
+#define IOP13XX_PCIX_LOWER_IO_BA      0x0fff0000UL
+#define IOP13XX_PCIX_UPPER_IO_PA      (IOP13XX_PCIX_LOWER_IO_PA +\
+                                      IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
+#define IOP13XX_PCIX_UPPER_IO_VA      (IOP13XX_PCIX_LOWER_IO_VA +\
+                                      IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
+#define IOP13XX_PCIX_IO_OFFSET        (IOP13XX_PCIX_LOWER_IO_VA -\
+                                      IOP13XX_PCIX_LOWER_IO_BA)
+#define IOP13XX_PCIX_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+                                          (IOP13XX_PCIX_LOWER_IO_PA\
+                                          - IOP13XX_PCIX_LOWER_IO_VA))
+
+#define IOP13XX_PCIX_MEM_PHYS_OFFSET  0x100000000ULL
+#define IOP13XX_PCIX_MEM_WINDOW_SIZE  0x3a000000UL
+#define IOP13XX_PCIX_LOWER_MEM_BA     (PHYS_OFFSET + IOP13XX_PCI_OFFSET)
+#define IOP13XX_PCIX_LOWER_MEM_PA     (IOP13XX_PCIX_MEM_PHYS_OFFSET +\
+                                      IOP13XX_PCIX_LOWER_MEM_BA)
+#define IOP13XX_PCIX_UPPER_MEM_PA     (IOP13XX_PCIX_LOWER_MEM_PA +\
+                                      IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PCIX_UPPER_MEM_BA     (IOP13XX_PCIX_LOWER_MEM_BA +\
+                                      IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
+
+#define IOP13XX_PCIX_MEM_COOKIE        0x80000000UL
+#define IOP13XX_PCIX_LOWER_MEM_RA      IOP13XX_PCIX_MEM_COOKIE
+#define IOP13XX_PCIX_UPPER_MEM_RA      (IOP13XX_PCIX_LOWER_MEM_RA +\
+                                       IOP13XX_PCIX_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PCIX_MEM_OFFSET        (IOP13XX_PCIX_MEM_COOKIE -\
+                                       IOP13XX_PCIX_LOWER_MEM_BA)
+
+/* PCI-E ranges */
+#define IOP13XX_PCIE_IO_WINDOW_SIZE     0x10000UL
+#define IOP13XX_PCIE_LOWER_IO_PA        0xfffd0000UL
+#define IOP13XX_PCIE_LOWER_IO_VA        0xfed70000UL
+#define IOP13XX_PCIE_LOWER_IO_BA        0x0fff0000UL
+#define IOP13XX_PCIE_UPPER_IO_PA        (IOP13XX_PCIE_LOWER_IO_PA +\
+                                        IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
+#define IOP13XX_PCIE_UPPER_IO_VA        (IOP13XX_PCIE_LOWER_IO_VA +\
+                                        IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
+#define IOP13XX_PCIE_UPPER_IO_BA        (IOP13XX_PCIE_LOWER_IO_BA +\
+                                        IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
+#define IOP13XX_PCIE_IO_OFFSET          (IOP13XX_PCIE_LOWER_IO_VA -\
+                                        IOP13XX_PCIE_LOWER_IO_BA)
+#define IOP13XX_PCIE_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+                                          (IOP13XX_PCIE_LOWER_IO_PA\
+                                          - IOP13XX_PCIE_LOWER_IO_VA))
+
+#define IOP13XX_PCIE_MEM_PHYS_OFFSET    0x200000000ULL
+#define IOP13XX_PCIE_MEM_WINDOW_SIZE    0x3a000000UL
+#define IOP13XX_PCIE_LOWER_MEM_BA       (PHYS_OFFSET + IOP13XX_PCI_OFFSET)
+#define IOP13XX_PCIE_LOWER_MEM_PA       (IOP13XX_PCIE_MEM_PHYS_OFFSET +\
+                                        IOP13XX_PCIE_LOWER_MEM_BA)
+#define IOP13XX_PCIE_UPPER_MEM_PA       (IOP13XX_PCIE_LOWER_MEM_PA +\
+                                        IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PCIE_UPPER_MEM_BA       (IOP13XX_PCIE_LOWER_MEM_BA +\
+                                        IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
+
+/* All 0xc000.0000 - 0xfdff.ffff addresses belong to PCIe */
+#define IOP13XX_PCIE_MEM_COOKIE         0xc0000000UL
+#define IOP13XX_PCIE_LOWER_MEM_RA       IOP13XX_PCIE_MEM_COOKIE
+#define IOP13XX_PCIE_UPPER_MEM_RA       (IOP13XX_PCIE_LOWER_MEM_RA +\
+                                        IOP13XX_PCIE_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PCIE_MEM_OFFSET         (IOP13XX_PCIE_MEM_COOKIE -\
+                                        IOP13XX_PCIE_LOWER_MEM_BA)
+
+/* PBI Ranges */
+#define IOP13XX_PBI_LOWER_MEM_PA         0xf0000000UL
+#define IOP13XX_PBI_MEM_WINDOW_SIZE      0x04000000UL
+#define IOP13XX_PBI_MEM_COOKIE           0xfa000000UL
+#define IOP13XX_PBI_LOWER_MEM_RA         IOP13XX_PBI_MEM_COOKIE
+#define IOP13XX_PBI_UPPER_MEM_RA         (IOP13XX_PBI_LOWER_MEM_RA +\
+                                         IOP13XX_PBI_MEM_WINDOW_SIZE - 1)
+
+/*
+ * IOP13XX chipset registers
+ */
+#define IOP13XX_PMMR_PHYS_MEM_BASE        0xffd80000UL  /* PMMR phys. address */
+#define IOP13XX_PMMR_VIRT_MEM_BASE        0xfee80000UL  /* PMMR phys. address */
+#define IOP13XX_PMMR_MEM_WINDOW_SIZE      0x80000
+#define IOP13XX_PMMR_UPPER_MEM_VA         (IOP13XX_PMMR_VIRT_MEM_BASE +\
+                                          IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PMMR_UPPER_MEM_PA         (IOP13XX_PMMR_PHYS_MEM_BASE +\
+                                          IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
+#define IOP13XX_PMMR_VIRT_TO_PHYS(addr)   (u32) ((u32) addr +\
+                                          (IOP13XX_PMMR_PHYS_MEM_BASE\
+                                          - IOP13XX_PMMR_VIRT_MEM_BASE))
+#define IOP13XX_PMMR_PHYS_TO_VIRT(addr)   (u32) ((u32) addr -\
+                                          (IOP13XX_PMMR_PHYS_MEM_BASE\
+                                          - IOP13XX_PMMR_VIRT_MEM_BASE))
+#define IOP13XX_REG_ADDR32(reg)           (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
+#define IOP13XX_REG_ADDR16(reg)           (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
+#define IOP13XX_REG_ADDR8(reg)            (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
+#define IOP13XX_REG_ADDR32_PHYS(reg)      (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
+#define IOP13XX_REG_ADDR16_PHYS(reg)      (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
+#define IOP13XX_REG_ADDR8_PHYS(reg)       (IOP13XX_PMMR_PHYS_MEM_BASE + (reg))
+#define IOP13XX_PMMR_SIZE                 0x00080000
+
+/*=================== Defines for Platform Devices =====================*/
+#define IOP13XX_UART0_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002300)
+#define IOP13XX_UART1_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002340)
+#define IOP13XX_UART0_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002300)
+#define IOP13XX_UART1_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002340)
+
+#define IOP13XX_I2C0_PHYS   (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002500)
+#define IOP13XX_I2C1_PHYS   (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002520)
+#define IOP13XX_I2C2_PHYS   (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002540)
+#define IOP13XX_I2C0_VIRT   (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002500)
+#define IOP13XX_I2C1_VIRT   (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002520)
+#define IOP13XX_I2C2_VIRT   (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002540)
+
+/* ATU selection flags */
+/* IOP13XX_INIT_ATU_DEFAULT = Rely on CONFIG_IOP13XX_ATU* */
+#define IOP13XX_INIT_ATU_DEFAULT     (0)
+#define IOP13XX_INIT_ATU_ATUX        (1 << 0)
+#define IOP13XX_INIT_ATU_ATUE        (1 << 1)
+#define IOP13XX_INIT_ATU_NONE        (1 << 2)
+
+/* UART selection flags */
+/* IOP13XX_INIT_UART_DEFAULT = Rely on CONFIG_IOP13XX_UART* */
+#define IOP13XX_INIT_UART_DEFAULT    (0)
+#define IOP13XX_INIT_UART_0          (1 << 0)
+#define IOP13XX_INIT_UART_1          (1 << 1)
+
+/* I2C selection flags */
+/* IOP13XX_INIT_I2C_DEFAULT = Rely on CONFIG_IOP13XX_I2C* */
+#define IOP13XX_INIT_I2C_DEFAULT     (0)
+#define IOP13XX_INIT_I2C_0           (1 << 0)
+#define IOP13XX_INIT_I2C_1           (1 << 1)
+#define IOP13XX_INIT_I2C_2           (1 << 2)
+
+#define IQ81340_NUM_UART     2
+#define IQ81340_NUM_I2C      3
+#define IQ81340_NUM_PHYS_MAP_FLASH 1
+#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
+                               IQ81340_NUM_I2C +\
+                               IQ81340_NUM_PHYS_MAP_FLASH)
+
+/*========================== PMMR offsets for key registers ============*/
+#define IOP13XX_ATU0_PMMR_OFFSET       0x00048000
+#define IOP13XX_ATU1_PMMR_OFFSET       0x0004c000
+#define IOP13XX_ATU2_PMMR_OFFSET       0x0004d000
+#define IOP13XX_ADMA0_PMMR_OFFSET      0x00000000
+#define IOP13XX_ADMA1_PMMR_OFFSET      0x00000200
+#define IOP13XX_ADMA2_PMMR_OFFSET      0x00000400
+#define IOP13XX_PBI_PMMR_OFFSET        0x00001580
+#define IOP13XX_ESSR0_PMMR_OFFSET      0x00002188
+#define IOP13XX_ESSR0                  IOP13XX_REG_ADDR32(0x00002188)
+
+#define IOP13XX_ESSR0_IFACE_MASK       0x00004000  /* Interface PCI-X / PCI-E */
+#define IOP13XX_CONTROLLER_ONLY        (1 << 14)
+#define IOP13XX_INTERFACE_SEL_PCIX     (1 << 15)
+
+#define IOP13XX_PMON_PMMR_OFFSET       0x0001A000
+#define IOP13XX_PMON_BASE              (IOP13XX_PMMR_VIRT_MEM_BASE +\
+                                       IOP13XX_PMON_PMMR_OFFSET)
+#define IOP13XX_PMON_PHYSBASE          (IOP13XX_PMMR_PHYS_MEM_BASE +\
+                                       IOP13XX_PMON_PMMR_OFFSET)
+
+#define IOP13XX_PMON_CMD0              (IOP13XX_PMON_BASE + 0x0)
+#define IOP13XX_PMON_EVR0              (IOP13XX_PMON_BASE + 0x4)
+#define IOP13XX_PMON_STS0              (IOP13XX_PMON_BASE + 0x8)
+#define IOP13XX_PMON_DATA0             (IOP13XX_PMON_BASE + 0xC)
+
+#define IOP13XX_PMON_CMD3              (IOP13XX_PMON_BASE + 0x30)
+#define IOP13XX_PMON_EVR3              (IOP13XX_PMON_BASE + 0x34)
+#define IOP13XX_PMON_STS3              (IOP13XX_PMON_BASE + 0x38)
+#define IOP13XX_PMON_DATA3             (IOP13XX_PMON_BASE + 0x3C)
+
+#define IOP13XX_PMON_CMD7              (IOP13XX_PMON_BASE + 0x70)
+#define IOP13XX_PMON_EVR7              (IOP13XX_PMON_BASE + 0x74)
+#define IOP13XX_PMON_STS7              (IOP13XX_PMON_BASE + 0x78)
+#define IOP13XX_PMON_DATA7             (IOP13XX_PMON_BASE + 0x7C)
+
+#define IOP13XX_PMONEN                 (IOP13XX_PMMR_VIRT_MEM_BASE + 0x4E040)
+#define IOP13XX_PMONSTAT               (IOP13XX_PMMR_VIRT_MEM_BASE + 0x4E044)
+
+/*================================ATU===================================*/
+#define IOP13XX_ATUX_OFFSET(ofs)       IOP13XX_REG_ADDR32(\
+                                       iop13xx_atux_pmmr_offset + (ofs))
+
+#define IOP13XX_ATUX_DID               IOP13XX_REG_ADDR16(\
+                                       iop13xx_atux_pmmr_offset + 0x2)
+
+#define IOP13XX_ATUX_ATUCMD            IOP13XX_REG_ADDR16(\
+                                       iop13xx_atux_pmmr_offset + 0x4)
+#define IOP13XX_ATUX_ATUSR             IOP13XX_REG_ADDR16(\
+                                       iop13xx_atux_pmmr_offset + 0x6)
+
+#define IOP13XX_ATUX_IABAR0            IOP13XX_ATUX_OFFSET(0x10)
+#define IOP13XX_ATUX_IAUBAR0           IOP13XX_ATUX_OFFSET(0x14)
+#define IOP13XX_ATUX_IABAR1            IOP13XX_ATUX_OFFSET(0x18)
+#define IOP13XX_ATUX_IAUBAR1           IOP13XX_ATUX_OFFSET(0x1c)
+#define IOP13XX_ATUX_IABAR2            IOP13XX_ATUX_OFFSET(0x20)
+#define IOP13XX_ATUX_IAUBAR2           IOP13XX_ATUX_OFFSET(0x24)
+#define IOP13XX_ATUX_IALR0             IOP13XX_ATUX_OFFSET(0x40)
+#define IOP13XX_ATUX_IATVR0            IOP13XX_ATUX_OFFSET(0x44)
+#define IOP13XX_ATUX_IAUTVR0           IOP13XX_ATUX_OFFSET(0x48)
+#define IOP13XX_ATUX_IALR1             IOP13XX_ATUX_OFFSET(0x4c)
+#define IOP13XX_ATUX_IATVR1            IOP13XX_ATUX_OFFSET(0x50)
+#define IOP13XX_ATUX_IAUTVR1           IOP13XX_ATUX_OFFSET(0x54)
+#define IOP13XX_ATUX_IALR2             IOP13XX_ATUX_OFFSET(0x58)
+#define IOP13XX_ATUX_IATVR2            IOP13XX_ATUX_OFFSET(0x5c)
+#define IOP13XX_ATUX_IAUTVR2           IOP13XX_ATUX_OFFSET(0x60)
+#define IOP13XX_ATUX_ATUCR             IOP13XX_ATUX_OFFSET(0x70)
+#define IOP13XX_ATUX_PCSR              IOP13XX_ATUX_OFFSET(0x74)
+#define IOP13XX_ATUX_ATUISR            IOP13XX_ATUX_OFFSET(0x78)
+#define IOP13XX_ATUX_PCIXSR            IOP13XX_ATUX_OFFSET(0xD4)
+#define IOP13XX_ATUX_IABAR3            IOP13XX_ATUX_OFFSET(0x200)
+#define IOP13XX_ATUX_IAUBAR3           IOP13XX_ATUX_OFFSET(0x204)
+#define IOP13XX_ATUX_IALR3             IOP13XX_ATUX_OFFSET(0x208)
+#define IOP13XX_ATUX_IATVR3            IOP13XX_ATUX_OFFSET(0x20c)
+#define IOP13XX_ATUX_IAUTVR3           IOP13XX_ATUX_OFFSET(0x210)
+
+#define IOP13XX_ATUX_OIOBAR            IOP13XX_ATUX_OFFSET(0x300)
+#define IOP13XX_ATUX_OIOWTVR           IOP13XX_ATUX_OFFSET(0x304)
+#define IOP13XX_ATUX_OUMBAR0           IOP13XX_ATUX_OFFSET(0x308)
+#define IOP13XX_ATUX_OUMWTVR0          IOP13XX_ATUX_OFFSET(0x30c)
+#define IOP13XX_ATUX_OUMBAR1           IOP13XX_ATUX_OFFSET(0x310)
+#define IOP13XX_ATUX_OUMWTVR1          IOP13XX_ATUX_OFFSET(0x314)
+#define IOP13XX_ATUX_OUMBAR2           IOP13XX_ATUX_OFFSET(0x318)
+#define IOP13XX_ATUX_OUMWTVR2          IOP13XX_ATUX_OFFSET(0x31c)
+#define IOP13XX_ATUX_OUMBAR3           IOP13XX_ATUX_OFFSET(0x320)
+#define IOP13XX_ATUX_OUMWTVR3          IOP13XX_ATUX_OFFSET(0x324)
+#define IOP13XX_ATUX_OUDMABAR          IOP13XX_ATUX_OFFSET(0x328)
+#define IOP13XX_ATUX_OUMSIBAR          IOP13XX_ATUX_OFFSET(0x32c)
+#define IOP13XX_ATUX_OCCAR             IOP13XX_ATUX_OFFSET(0x330)
+#define IOP13XX_ATUX_OCCDR             IOP13XX_ATUX_OFFSET(0x334)
+
+#define IOP13XX_ATUX_ATUCR_OUT_EN              (1 << 1)
+#define IOP13XX_ATUX_PCSR_CENTRAL_RES          (1 << 25)
+#define IOP13XX_ATUX_PCSR_P_RSTOUT             (1 << 21)
+#define IOP13XX_ATUX_PCSR_OUT_Q_BUSY           (1 << 15)
+#define IOP13XX_ATUX_PCSR_IN_Q_BUSY            (1 << 14)
+#define IOP13XX_ATUX_PCSR_FREQ_OFFSET          (16)
+
+#define IOP13XX_ATUX_STAT_PCI_IFACE_ERR        (1 << 18)
+#define IOP13XX_ATUX_STAT_VPD_ADDR             (1 << 17)
+#define IOP13XX_ATUX_STAT_INT_PAR_ERR          (1 << 16)
+#define IOP13XX_ATUX_STAT_CFG_WRITE            (1 << 15)
+#define IOP13XX_ATUX_STAT_ERR_COR              (1 << 14)
+#define IOP13XX_ATUX_STAT_TX_SCEM              (1 << 13)
+#define IOP13XX_ATUX_STAT_REC_SCEM             (1 << 12)
+#define IOP13XX_ATUX_STAT_POWER_TRAN           (1 << 11)
+#define IOP13XX_ATUX_STAT_TX_SERR              (1 << 10)
+#define IOP13XX_ATUX_STAT_DET_PAR_ERR          (1 << 9 )
+#define IOP13XX_ATUX_STAT_BIST                 (1 << 8 )
+#define IOP13XX_ATUX_STAT_INT_REC_MABORT       (1 << 7 )
+#define IOP13XX_ATUX_STAT_REC_SERR             (1 << 4 )
+#define IOP13XX_ATUX_STAT_EXT_REC_MABORT       (1 << 3 )
+#define IOP13XX_ATUX_STAT_EXT_REC_TABORT       (1 << 2 )
+#define IOP13XX_ATUX_STAT_EXT_SIG_TABORT       (1 << 1 )
+#define IOP13XX_ATUX_STAT_MASTER_DATA_PAR      (1 << 0 )
+
+#define IOP13XX_ATUX_PCIXSR_BUS_NUM    (8)
+#define IOP13XX_ATUX_PCIXSR_DEV_NUM    (3)
+#define IOP13XX_ATUX_PCIXSR_FUNC_NUM   (0)
+
+#define IOP13XX_ATUX_IALR_DISABLE      0x00000001
+#define IOP13XX_ATUX_OUMBAR_ENABLE     0x80000000
+
+#define IOP13XX_ATUE_OFFSET(ofs)       IOP13XX_REG_ADDR32(\
+                                       iop13xx_atue_pmmr_offset + (ofs))
+
+#define IOP13XX_ATUE_DID               IOP13XX_REG_ADDR16(\
+                                       iop13xx_atue_pmmr_offset + 0x2)
+#define IOP13XX_ATUE_ATUCMD            IOP13XX_REG_ADDR16(\
+                                       iop13xx_atue_pmmr_offset + 0x4)
+#define IOP13XX_ATUE_ATUSR             IOP13XX_REG_ADDR16(\
+                                       iop13xx_atue_pmmr_offset + 0x6)
+
+#define IOP13XX_ATUE_IABAR0            IOP13XX_ATUE_OFFSET(0x10)
+#define IOP13XX_ATUE_IAUBAR0           IOP13XX_ATUE_OFFSET(0x14)
+#define IOP13XX_ATUE_IABAR1            IOP13XX_ATUE_OFFSET(0x18)
+#define IOP13XX_ATUE_IAUBAR1           IOP13XX_ATUE_OFFSET(0x1c)
+#define IOP13XX_ATUE_IABAR2            IOP13XX_ATUE_OFFSET(0x20)
+#define IOP13XX_ATUE_IAUBAR2           IOP13XX_ATUE_OFFSET(0x24)
+#define IOP13XX_ATUE_IALR0             IOP13XX_ATUE_OFFSET(0x40)
+#define IOP13XX_ATUE_IATVR0            IOP13XX_ATUE_OFFSET(0x44)
+#define IOP13XX_ATUE_IAUTVR0           IOP13XX_ATUE_OFFSET(0x48)
+#define IOP13XX_ATUE_IALR1             IOP13XX_ATUE_OFFSET(0x4c)
+#define IOP13XX_ATUE_IATVR1            IOP13XX_ATUE_OFFSET(0x50)
+#define IOP13XX_ATUE_IAUTVR1           IOP13XX_ATUE_OFFSET(0x54)
+#define IOP13XX_ATUE_IALR2             IOP13XX_ATUE_OFFSET(0x58)
+#define IOP13XX_ATUE_IATVR2            IOP13XX_ATUE_OFFSET(0x5c)
+#define IOP13XX_ATUE_IAUTVR2           IOP13XX_ATUE_OFFSET(0x60)
+#define IOP13XX_ATUE_PE_LSTS           IOP13XX_REG_ADDR16(\
+                                       iop13xx_atue_pmmr_offset + 0xe2)
+#define IOP13XX_ATUE_OIOWTVR           IOP13XX_ATUE_OFFSET(0x304)
+#define IOP13XX_ATUE_OUMBAR0           IOP13XX_ATUE_OFFSET(0x308)
+#define IOP13XX_ATUE_OUMWTVR0          IOP13XX_ATUE_OFFSET(0x30c)
+#define IOP13XX_ATUE_OUMBAR1           IOP13XX_ATUE_OFFSET(0x310)
+#define IOP13XX_ATUE_OUMWTVR1          IOP13XX_ATUE_OFFSET(0x314)
+#define IOP13XX_ATUE_OUMBAR2           IOP13XX_ATUE_OFFSET(0x318)
+#define IOP13XX_ATUE_OUMWTVR2          IOP13XX_ATUE_OFFSET(0x31c)
+#define IOP13XX_ATUE_OUMBAR3           IOP13XX_ATUE_OFFSET(0x320)
+#define IOP13XX_ATUE_OUMWTVR3          IOP13XX_ATUE_OFFSET(0x324)
+
+#define IOP13XX_ATUE_ATUCR             IOP13XX_ATUE_OFFSET(0x70)
+#define IOP13XX_ATUE_PCSR              IOP13XX_ATUE_OFFSET(0x74)
+#define IOP13XX_ATUE_ATUISR            IOP13XX_ATUE_OFFSET(0x78)
+#define IOP13XX_ATUE_OIOBAR            IOP13XX_ATUE_OFFSET(0x300)
+#define IOP13XX_ATUE_OCCAR             IOP13XX_ATUE_OFFSET(0x32c)
+#define IOP13XX_ATUE_OCCDR             IOP13XX_ATUE_OFFSET(0x330)
+
+#define IOP13XX_ATUE_PIE_STS           IOP13XX_ATUE_OFFSET(0x384)
+#define IOP13XX_ATUE_PIE_MSK           IOP13XX_ATUE_OFFSET(0x388)
+
+#define IOP13XX_ATUE_ATUCR_IVM         (1 << 6)
+#define IOP13XX_ATUE_ATUCR_OUT_EN      (1 << 1)
+#define IOP13XX_ATUE_OCCAR_BUS_NUM     (24)
+#define IOP13XX_ATUE_OCCAR_DEV_NUM     (19)
+#define IOP13XX_ATUE_OCCAR_FUNC_NUM    (16)
+#define IOP13XX_ATUE_OCCAR_EXT_REG     (8)
+#define IOP13XX_ATUE_OCCAR_REG         (2)
+
+#define IOP13XX_ATUE_PCSR_BUS_NUM      (24)
+#define IOP13XX_ATUE_PCSR_DEV_NUM      (19)
+#define IOP13XX_ATUE_PCSR_FUNC_NUM     (16)
+#define IOP13XX_ATUE_PCSR_OUT_Q_BUSY   (1 << 15)
+#define IOP13XX_ATUE_PCSR_IN_Q_BUSY    (1 << 14)
+#define IOP13XX_ATUE_PCSR_END_POINT    (1 << 13)
+#define IOP13XX_ATUE_PCSR_LLRB_BUSY    (1 << 12)
+
+#define IOP13XX_ATUE_PCSR_BUS_NUM_MASK         (0xff)
+#define IOP13XX_ATUE_PCSR_DEV_NUM_MASK         (0x1f)
+#define IOP13XX_ATUE_PCSR_FUNC_NUM_MASK        (0x7)
+
+#define IOP13XX_ATUE_PCSR_CORE_RESET           (8)
+#define IOP13XX_ATUE_PCSR_FUNC_NUM             (16)
+
+#define IOP13XX_ATUE_LSTS_TRAINING             (1 << 11)
+#define IOP13XX_ATUE_STAT_SLOT_PWR_MSG         (1 << 28)
+#define IOP13XX_ATUE_STAT_PME                  (1 << 27)
+#define IOP13XX_ATUE_STAT_HOT_PLUG_MSG         (1 << 26)
+#define IOP13XX_ATUE_STAT_IVM                  (1 << 25)
+#define IOP13XX_ATUE_STAT_BIST                 (1 << 24)
+#define IOP13XX_ATUE_STAT_CFG_WRITE            (1 << 18)
+#define IOP13XX_ATUE_STAT_VPD_ADDR             (1 << 17)
+#define IOP13XX_ATUE_STAT_POWER_TRAN           (1 << 16)
+#define IOP13XX_ATUE_STAT_HALT_ON_ERROR        (1 << 13)
+#define IOP13XX_ATUE_STAT_ROOT_SYS_ERR         (1 << 12)
+#define IOP13XX_ATUE_STAT_ROOT_ERR_MSG         (1 << 11)
+#define IOP13XX_ATUE_STAT_PCI_IFACE_ERR        (1 << 10)
+#define IOP13XX_ATUE_STAT_ERR_COR              (1 << 9 )
+#define IOP13XX_ATUE_STAT_ERR_UNCOR            (1 << 8 )
+#define IOP13XX_ATUE_STAT_CRS                  (1 << 7 )
+#define IOP13XX_ATUE_STAT_LNK_DWN              (1 << 6 )
+#define IOP13XX_ATUE_STAT_INT_REC_MABORT       (1 << 5 )
+#define IOP13XX_ATUE_STAT_DET_PAR_ERR          (1 << 4 )
+#define IOP13XX_ATUE_STAT_EXT_REC_MABORT       (1 << 3 )
+#define IOP13XX_ATUE_STAT_SIG_TABORT           (1 << 2 )
+#define IOP13XX_ATUE_STAT_EXT_REC_TABORT       (1 << 1 )
+#define IOP13XX_ATUE_STAT_MASTER_DATA_PAR      (1 << 0 )
+
+#define IOP13XX_ATUE_ESTAT_REC_UNSUPPORTED_COMP_REQ    (1 << 31)
+#define IOP13XX_ATUE_ESTAT_REC_COMPLETER_ABORT         (1 << 30)
+#define IOP13XX_ATUE_ESTAT_TX_POISONED_TLP             (1 << 29)
+#define IOP13XX_ATUE_ESTAT_TX_PAR_ERR                  (1 << 28)
+#define IOP13XX_ATUE_ESTAT_REC_UNSUPPORTED_REQ         (1 << 20)
+#define IOP13XX_ATUE_ESTAT_REC_ECRC_ERR                (1 << 19)
+#define IOP13XX_ATUE_ESTAT_REC_MALFORMED_TLP           (1 << 18)
+#define IOP13XX_ATUE_ESTAT_TX_RECEIVER_OVERFLOW        (1 << 17)
+#define IOP13XX_ATUE_ESTAT_REC_UNEXPECTED_COMP         (1 << 16)
+#define IOP13XX_ATUE_ESTAT_INT_COMP_ABORT              (1 << 15)
+#define IOP13XX_ATUE_ESTAT_COMP_TIMEOUT                (1 << 14)
+#define IOP13XX_ATUE_ESTAT_FLOW_CONTROL_ERR            (1 << 13)
+#define IOP13XX_ATUE_ESTAT_REC_POISONED_TLP            (1 << 12)
+#define IOP13XX_ATUE_ESTAT_DATA_LNK_ERR                (1 << 4 )
+#define IOP13XX_ATUE_ESTAT_TRAINING_ERR                (1 << 0 )
+
+#define IOP13XX_ATUE_IALR_DISABLE              (0x00000001)
+#define IOP13XX_ATUE_OUMBAR_ENABLE             (0x80000000)
+#define IOP13XX_ATU_OUMBAR_FUNC_NUM            (28)
+#define IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK       (0x7)
+/*=======================================================================*/
+
+/*==============================ADMA UNITS===============================*/
+#define IOP13XX_ADMA_PHYS_BASE(chan)   IOP13XX_REG_ADDR32_PHYS((chan << 9))
+#define IOP13XX_ADMA_UPPER_PA(chan)    (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
+#define IOP13XX_ADMA_OFFSET(chan, ofs) IOP13XX_REG_ADDR32((chan << 9) + (ofs))
+
+#define IOP13XX_ADMA_ACCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x0)
+#define IOP13XX_ADMA_ACSR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x4)
+#define IOP13XX_ADMA_ADAR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x8)
+#define IOP13XX_ADMA_IIPCR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x18)
+#define IOP13XX_ADMA_IIPAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x1c)
+#define IOP13XX_ADMA_IIPUAR(chan)    IOP13XX_ADMA_OFFSET(chan, 0x20)
+#define IOP13XX_ADMA_ANDAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x24)
+#define IOP13XX_ADMA_ADCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x28)
+#define IOP13XX_ADMA_CARMD(chan)     IOP13XX_ADMA_OFFSET(chan, 0x2c)
+#define IOP13XX_ADMA_ABCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x30)
+#define IOP13XX_ADMA_DLADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x34)
+#define IOP13XX_ADMA_DUADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x38)
+#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
+#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
+
+/*==============================XSI BRIDGE===============================*/
+#define IOP13XX_XBG_BECSR              IOP13XX_REG_ADDR32(0x178c)
+#define IOP13XX_XBG_BERAR              IOP13XX_REG_ADDR32(0x1790)
+#define IOP13XX_XBG_BERUAR             IOP13XX_REG_ADDR32(0x1794)
+#define is_atue_occdr_error(x)         ((__raw_readl(IOP13XX_XBG_BERAR) == \
+                                       IOP13XX_PMMR_VIRT_TO_PHYS(\
+                                       IOP13XX_ATUE_OCCDR))\
+                                       && (__raw_readl(IOP13XX_XBG_BECSR) & 1))
+#define is_atux_occdr_error(x)         ((__raw_readl(IOP13XX_XBG_BERAR) == \
+                                       IOP13XX_PMMR_VIRT_TO_PHYS(\
+                                       IOP13XX_ATUX_OCCDR))\
+                                       && (__raw_readl(IOP13XX_XBG_BECSR) & 1))
+/*=======================================================================*/
+
+#define IOP13XX_PBI_OFFSET(ofs) IOP13XX_REG_ADDR32(IOP13XX_PBI_PMMR_OFFSET +\
+                                                       (ofs))
+
+#define IOP13XX_PBI_CR                 IOP13XX_PBI_OFFSET(0x0)
+#define IOP13XX_PBI_SR                 IOP13XX_PBI_OFFSET(0x4)
+#define IOP13XX_PBI_BAR0               IOP13XX_PBI_OFFSET(0x8)
+#define IOP13XX_PBI_LR0                IOP13XX_PBI_OFFSET(0xc)
+#define IOP13XX_PBI_BAR1               IOP13XX_PBI_OFFSET(0x10)
+#define IOP13XX_PBI_LR1                IOP13XX_PBI_OFFSET(0x14)
+
+#define IOP13XX_TMR_TC                 0x01
+#define IOP13XX_TMR_EN                 0x02
+#define IOP13XX_TMR_RELOAD             0x04
+#define IOP13XX_TMR_PRIVILEGED         0x08
+
+#define IOP13XX_TMR_RATIO_1_1          0x00
+#define IOP13XX_TMR_RATIO_4_1          0x10
+#define IOP13XX_TMR_RATIO_8_1          0x20
+#define IOP13XX_TMR_RATIO_16_1         0x30
+
+#endif /* _IOP13XX_HW_H_ */
diff --git a/include/asm-arm/arch-iop13xx/iq81340.h b/include/asm-arm/arch-iop13xx/iq81340.h
new file mode 100644 (file)
index 0000000..b98f8f1
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _IQ81340_H_
+#define _IQ81340_H_
+
+#define IQ81340_PCE_BAR0    IOP13XX_PBI_LOWER_MEM_RA
+#define IQ81340_PCE_BAR1    (IQ81340_PCE_BAR0 + 0x02000000)
+
+#define IQ81340_FLASHBASE   IQ81340_PCE_BAR0   /* Flash */
+
+#define IQ81340_PCE_BAR1_OFFSET(a) (IQ81340_PCE_BAR1 + (a))
+
+#define IQ81340_PRD_CODE    IQ81340_PCE_BAR1_OFFSET(0)
+#define IQ81340_BRD_STEP    IQ81340_PCE_BAR1_OFFSET(0x10000)
+#define IQ81340_CPLD_REV    IQ81340_PCE_BAR1_OFFSET(0x20000)
+#define IQ81340_LED         IQ81340_PCE_BAR1_OFFSET(0x30000)
+#define IQ81340_LHEX        IQ81340_PCE_BAR1_OFFSET(0x40000)
+#define IQ81340_RHEX        IQ81340_PCE_BAR1_OFFSET(0x50000)
+#define IQ81340_BUZZER      IQ81340_PCE_BAR1_OFFSET(0x60000)
+#define IQ81340_32K_NVRAM   IQ81340_PCE_BAR1_OFFSET(0x70000)
+#define IQ81340_256K_NVRAM  IQ81340_PCE_BAR1_OFFSET(0x80000)
+#define IQ81340_ROTARY_SW   IQ81340_PCE_BAR1_OFFSET(0xd0000)
+#define IQ81340_BATT_STAT   IQ81340_PCE_BAR1_OFFSET(0xf0000)
+#define IQ81340_CMP_FLSH    IQ81340_PCE_BAR1_OFFSET(0x1000000) /* 16MB */
+
+#define PBI_CF_IDE_BASE     (IQ81340_CMP_FLSH)
+#define PBI_CF_BAR_ADDR     (IOP13XX_PBI_BAR1)
+
+/* These are the values used in the Machine description */
+#define PHYS_IO         0xfeffff00
+#define IO_PG_OFFSET    0xffffff00
+#define BOOT_PARAM_OFFSET  0x00000100
+#endif /* _IQ81340_H_ */
diff --git a/include/asm-arm/arch-iop13xx/irqs.h b/include/asm-arm/arch-iop13xx/irqs.h
new file mode 100644 (file)
index 0000000..442e35a
--- /dev/null
@@ -0,0 +1,207 @@
+#ifndef _IOP13XX_IRQS_H_
+#define _IOP13XX_IRQS_H_
+
+#ifndef __ASSEMBLER__
+#include <linux/types.h>
+#include <asm/system.h> /* local_irq_save */
+#include <asm/arch/iop13xx.h> /* iop13xx_cp6_* */
+
+/* INTPND0 CP6 R0 Page 3
+ */
+static inline u32 read_intpnd_0(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c0, c3, 0":"=r" (val));
+       return val;
+}
+
+/* INTPND1 CP6 R1 Page 3
+ */
+static inline u32 read_intpnd_1(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c1, c3, 0":"=r" (val));
+       return val;
+}
+
+/* INTPND2 CP6 R2 Page 3
+ */
+static inline u32 read_intpnd_2(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c2, c3, 0":"=r" (val));
+       return val;
+}
+
+/* INTPND3 CP6 R3 Page 3
+ */
+static inline u32 read_intpnd_3(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c3, c3, 0":"=r" (val));
+       return val;
+}
+
+static inline void
+iop13xx_cp6_enable_irq_save(unsigned long *cp_flags, unsigned long *irq_flags)
+{
+       local_irq_save(*irq_flags);
+       *cp_flags = iop13xx_cp6_save();
+}
+
+static inline void
+iop13xx_cp6_irq_restore(unsigned long *cp_flags,
+       unsigned long *irq_flags)
+{
+       iop13xx_cp6_restore(*cp_flags);
+       local_irq_restore(*irq_flags);
+}
+#endif
+
+#define INTBASE 0
+#define INTSIZE_4 1
+
+/*
+ * iop34x chipset interrupts
+ */
+#define IOP13XX_IRQ(x)         (IOP13XX_IRQ_OFS + (x))
+
+/*
+ * On IRQ or FIQ register
+ */
+#define IRQ_IOP13XX_ADMA0_EOT  (0)
+#define IRQ_IOP13XX_ADMA0_EOC  (1)
+#define IRQ_IOP13XX_ADMA1_EOT  (2)
+#define IRQ_IOP13XX_ADMA1_EOC  (3)
+#define IRQ_IOP13XX_ADMA2_EOT  (4)
+#define IRQ_IOP13XX_ADMA2_EOC  (5)
+#define IRQ_IOP134_WATCHDOG    (6)
+#define IRQ_IOP13XX_RSVD_7     (7)
+#define IRQ_IOP13XX_TIMER0     (8)
+#define IRQ_IOP13XX_TIMER1     (9)
+#define IRQ_IOP13XX_I2C_0      (10)
+#define IRQ_IOP13XX_I2C_1      (11)
+#define IRQ_IOP13XX_MSG        (12)
+#define IRQ_IOP13XX_MSGIBQ     (13)
+#define IRQ_IOP13XX_ATU_IM     (14)
+#define IRQ_IOP13XX_ATU_BIST   (15)
+#define IRQ_IOP13XX_PPMU       (16)
+#define IRQ_IOP13XX_COREPMU    (17)
+#define IRQ_IOP13XX_CORECACHE  (18)
+#define IRQ_IOP13XX_RSVD_19    (19)
+#define IRQ_IOP13XX_RSVD_20    (20)
+#define IRQ_IOP13XX_RSVD_21    (21)
+#define IRQ_IOP13XX_RSVD_22    (22)
+#define IRQ_IOP13XX_RSVD_23    (23)
+#define IRQ_IOP13XX_XINT0      (24)
+#define IRQ_IOP13XX_XINT1      (25)
+#define IRQ_IOP13XX_XINT2      (26)
+#define IRQ_IOP13XX_XINT3      (27)
+#define IRQ_IOP13XX_XINT4      (28)
+#define IRQ_IOP13XX_XINT5      (29)
+#define IRQ_IOP13XX_XINT6      (30)
+#define IRQ_IOP13XX_XINT7      (31)
+                                     /* IINTSRC1 bit */
+#define IRQ_IOP13XX_XINT8      (32)  /* 0  */
+#define IRQ_IOP13XX_XINT9      (33)  /* 1  */
+#define IRQ_IOP13XX_XINT10     (34)  /* 2  */
+#define IRQ_IOP13XX_XINT11     (35)  /* 3  */
+#define IRQ_IOP13XX_XINT12     (36)  /* 4  */
+#define IRQ_IOP13XX_XINT13     (37)  /* 5  */
+#define IRQ_IOP13XX_XINT14     (38)  /* 6  */
+#define IRQ_IOP13XX_XINT15     (39)  /* 7  */
+#define IRQ_IOP13XX_RSVD_40    (40)  /* 8  */
+#define IRQ_IOP13XX_RSVD_41    (41)  /* 9  */
+#define IRQ_IOP13XX_RSVD_42    (42)  /* 10 */
+#define IRQ_IOP13XX_RSVD_43    (43)  /* 11 */
+#define IRQ_IOP13XX_RSVD_44    (44)  /* 12 */
+#define IRQ_IOP13XX_RSVD_45    (45)  /* 13 */
+#define IRQ_IOP13XX_RSVD_46    (46)  /* 14 */
+#define IRQ_IOP13XX_RSVD_47    (47)  /* 15 */
+#define IRQ_IOP13XX_RSVD_48    (48)  /* 16 */
+#define IRQ_IOP13XX_RSVD_49    (49)  /* 17 */
+#define IRQ_IOP13XX_RSVD_50    (50)  /* 18 */
+#define IRQ_IOP13XX_UART0      (51)  /* 19 */
+#define IRQ_IOP13XX_UART1      (52)  /* 20 */
+#define IRQ_IOP13XX_PBIE       (53)  /* 21 */
+#define IRQ_IOP13XX_ATU_CRW    (54)  /* 22 */
+#define IRQ_IOP13XX_ATU_ERR    (55)  /* 23 */
+#define IRQ_IOP13XX_MCU_ERR    (56)  /* 24 */
+#define IRQ_IOP13XX_ADMA0_ERR  (57)  /* 25 */
+#define IRQ_IOP13XX_ADMA1_ERR  (58)  /* 26 */
+#define IRQ_IOP13XX_ADMA2_ERR  (59)  /* 27 */
+#define IRQ_IOP13XX_RSVD_60    (60)  /* 28 */
+#define IRQ_IOP13XX_RSVD_61    (61)  /* 29 */
+#define IRQ_IOP13XX_MSG_ERR    (62)  /* 30 */
+#define IRQ_IOP13XX_RSVD_63    (63)  /* 31 */
+                                     /* IINTSRC2 bit */
+#define IRQ_IOP13XX_INTERPROC  (64)  /* 0  */
+#define IRQ_IOP13XX_RSVD_65    (65)  /* 1  */
+#define IRQ_IOP13XX_RSVD_66    (66)  /* 2  */
+#define IRQ_IOP13XX_RSVD_67    (67)  /* 3  */
+#define IRQ_IOP13XX_RSVD_68    (68)  /* 4  */
+#define IRQ_IOP13XX_RSVD_69    (69)  /* 5  */
+#define IRQ_IOP13XX_RSVD_70    (70)  /* 6  */
+#define IRQ_IOP13XX_RSVD_71    (71)  /* 7  */
+#define IRQ_IOP13XX_RSVD_72    (72)  /* 8  */
+#define IRQ_IOP13XX_RSVD_73    (73)  /* 9  */
+#define IRQ_IOP13XX_RSVD_74    (74)  /* 10 */
+#define IRQ_IOP13XX_RSVD_75    (75)  /* 11 */
+#define IRQ_IOP13XX_RSVD_76    (76)  /* 12 */
+#define IRQ_IOP13XX_RSVD_77    (77)  /* 13 */
+#define IRQ_IOP13XX_RSVD_78    (78)  /* 14 */
+#define IRQ_IOP13XX_RSVD_79    (79)  /* 15 */
+#define IRQ_IOP13XX_RSVD_80    (80)  /* 16 */
+#define IRQ_IOP13XX_RSVD_81    (81)  /* 17 */
+#define IRQ_IOP13XX_RSVD_82    (82)  /* 18 */
+#define IRQ_IOP13XX_RSVD_83    (83)  /* 19 */
+#define IRQ_IOP13XX_RSVD_84    (84)  /* 20 */
+#define IRQ_IOP13XX_RSVD_85    (85)  /* 21 */
+#define IRQ_IOP13XX_RSVD_86    (86)  /* 22 */
+#define IRQ_IOP13XX_RSVD_87    (87)  /* 23 */
+#define IRQ_IOP13XX_RSVD_88    (88)  /* 24 */
+#define IRQ_IOP13XX_RSVD_89    (89)  /* 25 */
+#define IRQ_IOP13XX_RSVD_90    (90)  /* 26 */
+#define IRQ_IOP13XX_RSVD_91    (91)  /* 27 */
+#define IRQ_IOP13XX_RSVD_92    (92)  /* 28 */
+#define IRQ_IOP13XX_RSVD_93    (93)  /* 29 */
+#define IRQ_IOP13XX_SIB_ERR    (94)  /* 30 */
+#define IRQ_IOP13XX_SRAM_ERR   (95)  /* 31 */
+                                     /* IINTSRC3 bit */
+#define IRQ_IOP13XX_I2C_2      (96)  /* 0  */
+#define IRQ_IOP13XX_ATUE_BIST  (97)  /* 1  */
+#define IRQ_IOP13XX_ATUE_CRW   (98)  /* 2  */
+#define IRQ_IOP13XX_ATUE_ERR   (99)  /* 3  */
+#define IRQ_IOP13XX_IMU        (100) /* 4  */
+#define IRQ_IOP13XX_RSVD_101   (101) /* 5  */
+#define IRQ_IOP13XX_RSVD_102   (102) /* 6  */
+#define IRQ_IOP13XX_TPMI0_OUT  (103) /* 7  */
+#define IRQ_IOP13XX_TPMI1_OUT  (104) /* 8  */
+#define IRQ_IOP13XX_TPMI2_OUT  (105) /* 9  */
+#define IRQ_IOP13XX_TPMI3_OUT  (106) /* 10 */
+#define IRQ_IOP13XX_ATUE_IMA   (107) /* 11 */
+#define IRQ_IOP13XX_ATUE_IMB   (108) /* 12 */
+#define IRQ_IOP13XX_ATUE_IMC   (109) /* 13 */
+#define IRQ_IOP13XX_ATUE_IMD   (110) /* 14 */
+#define IRQ_IOP13XX_MU_MSI_TB  (111) /* 15 */
+#define IRQ_IOP13XX_RSVD_112   (112) /* 16 */
+#define IRQ_IOP13XX_RSVD_113   (113) /* 17 */
+#define IRQ_IOP13XX_RSVD_114   (114) /* 18 */
+#define IRQ_IOP13XX_RSVD_115   (115) /* 19 */
+#define IRQ_IOP13XX_RSVD_116   (116) /* 20 */
+#define IRQ_IOP13XX_RSVD_117   (117) /* 21 */
+#define IRQ_IOP13XX_RSVD_118   (118) /* 22 */
+#define IRQ_IOP13XX_RSVD_119   (119) /* 23 */
+#define IRQ_IOP13XX_RSVD_120   (120) /* 24 */
+#define IRQ_IOP13XX_RSVD_121   (121) /* 25 */
+#define IRQ_IOP13XX_RSVD_122   (122) /* 26 */
+#define IRQ_IOP13XX_RSVD_123   (123) /* 27 */
+#define IRQ_IOP13XX_RSVD_124   (124) /* 28 */
+#define IRQ_IOP13XX_RSVD_125   (125) /* 29 */
+#define IRQ_IOP13XX_RSVD_126   (126) /* 30 */
+#define IRQ_IOP13XX_HPI        (127) /* 31 */
+
+#define NR_IOP13XX_IRQS        (IRQ_IOP13XX_HPI + 1)
+#define NR_IRQS                NR_IOP13XX_IRQS
+
+#endif /* _IOP13XX_IRQ_H_ */
diff --git a/include/asm-arm/arch-iop13xx/memory.h b/include/asm-arm/arch-iop13xx/memory.h
new file mode 100644 (file)
index 0000000..031a0fa
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <asm/arch/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET    UL(0x00000000)
+#define TASK_SIZE      UL(0x3f000000)
+#define PAGE_OFFSET    UL(0x40000000)
+#define TASK_UNMAPPED_BASE ((TASK_SIZE + 0x01000000) / 3)
+
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_ARCH_IOP13XX)
+#define IOP13XX_PMMR_V_START (IOP13XX_PMMR_VIRT_MEM_BASE)
+#define IOP13XX_PMMR_V_END   (IOP13XX_PMMR_VIRT_MEM_BASE + IOP13XX_PMMR_SIZE)
+#define IOP13XX_PMMR_P_START (IOP13XX_PMMR_PHYS_MEM_BASE)
+#define IOP13XX_PMMR_P_END   (IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_SIZE)
+
+/*
+ * Virtual view <-> PCI DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *             address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *             to an address that the kernel can use.
+ */
+
+/* RAM has 1:1 mapping on the PCIe/x Busses */
+#define __virt_to_bus(x)       (__virt_to_phys(x))
+#define __bus_to_virt(x)    (__phys_to_virt(x))
+
+#define virt_to_lbus(x)                                           \
+(( ((void*)(x) >= (void*)IOP13XX_PMMR_V_START) &&                 \
+((void*)(x) < (void*)IOP13XX_PMMR_V_END) ) ?                      \
+((x) - IOP13XX_PMMR_VIRT_MEM_BASE + IOP13XX_PMMR_PHYS_MEM_BASE) : \
+((x) - PAGE_OFFSET + PHYS_OFFSET))
+
+#define lbus_to_virt(x)                                            \
+(( ((x) >= IOP13XX_PMMR_P_START) && ((x) < IOP13XX_PMMR_P_END) ) ? \
+((x) - IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_VIRT_MEM_BASE ) : \
+((x) - PHYS_OFFSET + PAGE_OFFSET))
+
+/* Device is an lbus device if it is on the platform bus of the IOP13XX */
+#define is_lbus_device(dev) (dev &&\
+                            (strncmp(dev->bus->name, "platform", 8) == 0))
+
+#define __arch_page_to_dma(dev, page)                                  \
+({is_lbus_device(dev) ? (dma_addr_t)virt_to_lbus(page_address(page)) : \
+(dma_addr_t)__virt_to_bus(page_address(page));})
+
+#define __arch_dma_to_virt(dev, addr) \
+({is_lbus_device(dev) ? lbus_to_virt(addr) : __bus_to_virt(addr);})
+
+#define __arch_virt_to_dma(dev, addr) \
+({is_lbus_device(dev) ? virt_to_lbus(addr) : __virt_to_bus(addr);})
+
+#endif /* CONFIG_ARCH_IOP13XX */
+#endif /* !ASSEMBLY */
+
+#define PFN_TO_NID(addr)       (0)
+
+#endif
diff --git a/include/asm-arm/arch-iop13xx/pci.h b/include/asm-arm/arch-iop13xx/pci.h
new file mode 100644 (file)
index 0000000..4041f30
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef _IOP13XX_PCI_H_
+#define _IOP13XX_PCI_H_
+#include <asm/arch/irqs.h>
+#include <asm/io.h>
+
+struct pci_sys_data;
+struct hw_pci;
+int iop13xx_pci_setup(int nr, struct pci_sys_data *sys);
+struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *);
+void iop13xx_atu_select(struct hw_pci *plat_pci);
+void iop13xx_pci_init(void);
+void iop13xx_map_pci_memory(void);
+
+#define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY |           \
+                              PCI_STATUS_SIG_TARGET_ABORT | \
+                              PCI_STATUS_REC_TARGET_ABORT | \
+                              PCI_STATUS_REC_TARGET_ABORT | \
+                              PCI_STATUS_REC_MASTER_ABORT | \
+                              PCI_STATUS_SIG_SYSTEM_ERROR | \
+                              PCI_STATUS_DETECTED_PARITY)
+
+#define IOP13XX_ATUE_ATUISR_ERROR (IOP13XX_ATUE_STAT_HALT_ON_ERROR |  \
+                                   IOP13XX_ATUE_STAT_ROOT_SYS_ERR |   \
+                                   IOP13XX_ATUE_STAT_PCI_IFACE_ERR |  \
+                                   IOP13XX_ATUE_STAT_ERR_COR |        \
+                                   IOP13XX_ATUE_STAT_ERR_UNCOR |      \
+                                   IOP13XX_ATUE_STAT_CRS |            \
+                                   IOP13XX_ATUE_STAT_DET_PAR_ERR |    \
+                                   IOP13XX_ATUE_STAT_EXT_REC_MABORT | \
+                                   IOP13XX_ATUE_STAT_SIG_TABORT |     \
+                                   IOP13XX_ATUE_STAT_EXT_REC_TABORT | \
+                                   IOP13XX_ATUE_STAT_MASTER_DATA_PAR)
+
+#define IOP13XX_ATUX_ATUISR_ERROR (IOP13XX_ATUX_STAT_TX_SCEM |        \
+                                   IOP13XX_ATUX_STAT_REC_SCEM |       \
+                                   IOP13XX_ATUX_STAT_TX_SERR |        \
+                                   IOP13XX_ATUX_STAT_DET_PAR_ERR |    \
+                                   IOP13XX_ATUX_STAT_INT_REC_MABORT | \
+                                   IOP13XX_ATUX_STAT_REC_SERR |       \
+                                   IOP13XX_ATUX_STAT_EXT_REC_MABORT | \
+                                   IOP13XX_ATUX_STAT_EXT_REC_TABORT | \
+                                   IOP13XX_ATUX_STAT_EXT_SIG_TABORT | \
+                                   IOP13XX_ATUX_STAT_MASTER_DATA_PAR)
+
+/* PCI interrupts
+ */
+#define ATUX_INTA IRQ_IOP13XX_XINT0
+#define ATUX_INTB IRQ_IOP13XX_XINT1
+#define ATUX_INTC IRQ_IOP13XX_XINT2
+#define ATUX_INTD IRQ_IOP13XX_XINT3
+
+#define ATUE_INTA IRQ_IOP13XX_ATUE_IMA
+#define ATUE_INTB IRQ_IOP13XX_ATUE_IMB
+#define ATUE_INTC IRQ_IOP13XX_ATUE_IMC
+#define ATUE_INTD IRQ_IOP13XX_ATUE_IMD
+
+#endif /* _IOP13XX_PCI_H_ */
diff --git a/include/asm-arm/arch-iop13xx/system.h b/include/asm-arm/arch-iop13xx/system.h
new file mode 100644 (file)
index 0000000..ee3a625
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * linux/include/asm-arm/arch-iop13xx/system.h
+ *
+ *  Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/arch/iop13xx.h>
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+/* WDTCR CP6 R7 Page 9 */
+static inline u32 read_wdtcr(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c7, c9, 0":"=r" (val));
+       return val;
+}
+static inline void write_wdtcr(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c7, c9, 0"::"r" (val));
+}
+
+/* WDTSR CP6 R8 Page 9 */
+static inline u32 read_wdtsr(void)
+{
+       u32 val;
+       asm volatile("mrc p6, 0, %0, c8, c9, 0":"=r" (val));
+       return val;
+}
+static inline void write_wdtsr(u32 val)
+{
+       asm volatile("mcr p6, 0, %0, c8, c9, 0"::"r" (val));
+}
+
+#define IOP13XX_WDTCR_EN_ARM   0x1e1e1e1e
+#define IOP13XX_WDTCR_EN       0xe1e1e1e1
+#define IOP13XX_WDTCR_DIS_ARM  0x1f1f1f1f
+#define IOP13XX_WDTCR_DIS      0xf1f1f1f1
+#define IOP13XX_WDTSR_WRITE_EN (1 << 31)
+#define IOP13XX_WDTCR_IB_RESET (1 << 0)
+static inline void arch_reset(char mode)
+{
+       /*
+        * Reset the internal bus (warning both cores are reset)
+        */
+       u32 cp_flags = iop13xx_cp6_save();
+       write_wdtcr(IOP13XX_WDTCR_EN_ARM);
+       write_wdtcr(IOP13XX_WDTCR_EN);
+       write_wdtsr(IOP13XX_WDTSR_WRITE_EN | IOP13XX_WDTCR_IB_RESET);
+       write_wdtcr(0x1000);
+       iop13xx_cp6_restore(cp_flags);
+
+       for(;;);
+}
diff --git a/include/asm-arm/arch-iop13xx/timex.h b/include/asm-arm/arch-iop13xx/timex.h
new file mode 100644 (file)
index 0000000..f0c51dd
--- /dev/null
@@ -0,0 +1,3 @@
+#include <asm/hardware.h>
+
+#define CLOCK_TICK_RATE (100 * HZ)
diff --git a/include/asm-arm/arch-iop13xx/uncompress.h b/include/asm-arm/arch-iop13xx/uncompress.h
new file mode 100644 (file)
index 0000000..b9525d5
--- /dev/null
@@ -0,0 +1,24 @@
+#include <asm/types.h>
+#include <linux/serial_reg.h>
+#include <asm/hardware.h>
+#include <asm/processor.h>
+
+#define UART_BASE ((volatile u32 *)IOP13XX_UART1_PHYS)
+#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void putc(char c)
+{
+       while ((UART_BASE[UART_LSR] & TX_DONE) != TX_DONE)
+               cpu_relax();
+       UART_BASE[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop13xx/vmalloc.h b/include/asm-arm/arch-iop13xx/vmalloc.h
new file mode 100644 (file)
index 0000000..c534567
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _VMALLOC_H_
+#define _VMALLOC_H_
+#define VMALLOC_END    0xfa000000UL
+#endif
index 4281838..6b437f7 100644 (file)
@@ -76,6 +76,7 @@
 
 #define NSLU2_GPIO_BUZZ                4
 #define NSLU2_BZ_BM            (1L << NSLU2_GPIO_BUZZ)
+
 /* LEDs */
 
 #define NSLU2_LED_RED          NSLU2_GPIO0
@@ -84,8 +85,8 @@
 #define NSLU2_LED_RED_BM       (1L << NSLU2_LED_RED)
 #define NSLU2_LED_GRN_BM       (1L << NSLU2_LED_GRN)
 
-#define NSLU2_LED_DISK1                NSLU2_GPIO2
-#define NSLU2_LED_DISK2                NSLU2_GPIO3
+#define NSLU2_LED_DISK1                NSLU2_GPIO3
+#define NSLU2_LED_DISK2                NSLU2_GPIO2
 
 #define NSLU2_LED_DISK1_BM     (1L << NSLU2_GPIO2)
 #define NSLU2_LED_DISK2_BM     (1L << NSLU2_GPIO3)
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
new file mode 100644 (file)
index 0000000..dbdec36
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * linux/include/asm-arm/arch-ixp4xx/udc.h
+ *
+ */
+#include <asm/mach/udc_pxa2xx.h>
+
+extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
+
index d744d97..645dbdf 100644 (file)
 /*
  * There are not real ISA nor PCI buses, so we fake it.
  */
-#define __io_pci(a)            ((void __iomem *)(PCIO_BASE + (a)))
-#define __mem_pci(a)           (a)
-
-#define __ioaddr(p)             __io_pci(p)
-
-/*
- * Generic virtual read/write
- */
-#define __arch_getb(a)          (*(volatile unsigned char *)(a))
-#define __arch_getl(a)          (*(volatile unsigned int  *)(a))
-
-static inline unsigned int __arch_getw(unsigned long a)
-{
-       unsigned int value;
-       __asm__ __volatile__("ldrh    %0, [%1, #0]    @ getw"
-               : "=&r" (value)
-               : "r" (a) : "cc");
-       return value;
-}
-
-#define __arch_putb(v,a)        (*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a)        (*(volatile unsigned int  *)(a) = (v))
-
-static inline void __arch_putw(unsigned int value, unsigned long a)
+static inline void __iomem *__io(unsigned long addr)
 {
-        __asm__ __volatile__("strh    %0, [%1, #0]    @ putw"
-                : : "r" (value), "r" (a) : "cc");
+       return (void __iomem *)addr;
 }
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p)            (*(volatile unsigned char *)(p) = (v))
-#define inb_t(p)               (*(volatile unsigned char *)(p))
-#define outw_t(v,p)            (*(volatile unsigned int *)(p) = (v))
-#define inw_t(p)               (*(volatile unsigned int *)(p))
-#define outl_t(v,p)            (*(volatile unsigned long *)(p) = (v))
-#define inl_t(p)               (*(volatile unsigned long *)(p))
-
-/*
- * FIXME - These are to allow for linking. On all the other
- *         ARM platforms, the entire IO space is contiguous.
- *         The 7200 has three separate IO spaces. The below
- *         macros will eventually become more involved. Use
- *         with caution and don't be surprised by kernel oopses!!!
- */
-#define inb(p)                 inb_t(p)
-#define inw(p)                 inw_t(p)
-#define inl(p)                 inl_t(p)
-#define outb(v,p)              outb_t(v,p)
-#define outw(v,p)              outw_t(v,p)
-#define outl(v,p)              outl_t(v,p)
+#define __io(a)        __io(a)
+#define __mem_pci(a)           (a)
 
 #endif
index 9f1a58c..9b0c801 100644 (file)
     (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
 #endif
 
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and return the mem_map of that node.
- */
-# define ADDR_TO_MAPBASE(kaddr)        NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-
-/*
- * Given a page frame number, find the owning node of the memory
- * and return the mem_map of that node.
- */
-# define PFN_TO_MAPBASE(pfn)   NODE_MEM_MAP(PFN_TO_NID(pfn))
-
 /*
  * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
  * and returns the index corresponding to the appropriate page in the
index 805ae35..345a649 100644 (file)
@@ -24,7 +24,7 @@ struct omap_irda_config {
        /* Very specific to the needs of some platforms (h3,h4)
         * having calls which can sleep in irda_set_speed.
         */
-       struct work_struct gpio_expa;
+       struct delayed_work gpio_expa;
        int rx_channel;
        int tx_channel;
        unsigned long dest_start;
index eaf6d43..e17f988 100644 (file)
@@ -27,7 +27,6 @@
 #define __virt_to_bus(x)        __virt_to_phys(x)
 #define __bus_to_virt(x)        __phys_to_virt(x)
 
-#ifdef CONFIG_DISCONTIGMEM
 /*
  * The nodes are matched with the physical SDRAM banks as follows:
  *
  *     node 1:  0xa4000000-0xa7ffffff  -->  0xc4000000-0xc7ffffff
  *     node 2:  0xa8000000-0xabffffff  -->  0xc8000000-0xcbffffff
  *     node 3:  0xac000000-0xafffffff  -->  0xcc000000-0xcfffffff
+ *
+ * This needs a node mem size of 26 bits.
  */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 26)
-
-/*
- * Given a page frame number, convert it to a node id.
- */
-#define PFN_TO_NID(pfn)                (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
-
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the mem_map of that node.
- */
-#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-
-/*
- * Given a page frame number, find the owning node of the memory
- * and returns the mem_map of that node.
- */
-#define PFN_TO_MAPBASE(pfn)    NODE_MEM_MAP(PFN_TO_NID(pfn))
-
-/*
- * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
- * and returns the index corresponding to the appropriate page in the
- * node's mem_map.
- */
-#define LOCAL_MAP_NR(addr) \
-       (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
-
-#endif
+#define NODE_MEM_SIZE_BITS     26
 
 #endif
index cff752f..083e03c 100644 (file)
@@ -99,7 +99,7 @@
 #define DCSR_SETCMPST  (1 << 25)       /* Set Descriptor Compare Status */
 #define DCSR_CLRCMPST  (1 << 24)       /* Clear Descriptor Compare Status */
 #define DCSR_CMPST     (1 << 10)       /* The Descriptor Compare Status */
-#define DCSR_ENRINTR   (1 << 9)        /* The end of Receive */
+#define DCSR_EORINTR   (1 << 9)        /* The end of Receive */
 #endif
 #define DCSR_REQPEND   (1 << 8)        /* Request Pending (read-only) */
 #define DCSR_STOPSTATE (1 << 3)        /* Stop State (read-only) */
 #define UDCISR0         __REG(0x4060000C) /* UDC Interrupt Status Register 0 */
 #define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status Register 1 */
 #define UDCISR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
-#define UDCISR1_IECC   (1 << 31)       /* IntEn - Configuration Change */
-#define UDCISR1_IESOF  (1 << 30)       /* IntEn - Start of Frame */
-#define UDCISR1_IERU   (1 << 29)       /* IntEn - Resume */
-#define UDCISR1_IESU   (1 << 28)       /* IntEn - Suspend */
-#define UDCISR1_IERS   (1 << 27)       /* IntEn - Reset */
-
+#define UDCISR1_IRCC   (1 << 31)       /* IntReq - Configuration Change */
+#define UDCISR1_IRSOF  (1 << 30)       /* IntReq - Start of Frame */
+#define UDCISR1_IRRU   (1 << 29)       /* IntReq - Resume */
+#define UDCISR1_IRSU   (1 << 28)       /* IntReq - Suspend */
+#define UDCISR1_IRRS   (1 << 27)       /* IntReq - Reset */
 
 #define UDCFNR          __REG(0x40600014) /* UDC Frame Number Register */
 #define UDCOTGICR      __REG(0x40600018) /* UDC On-The-Go interrupt control */
index 915590c..acc7ec7 100644 (file)
 #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
 #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
 #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
-#define SSP_TIMEOUT_SCALE (2712)
 #elif defined(CONFIG_PXA27x)
 #define CLOCK_SPEED_HZ 13000000
 #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
 #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
 #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
-#define SSP_TIMEOUT_SCALE (769)
 #endif
 
-#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
 #define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
 #define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
 #define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
@@ -63,7 +60,7 @@ struct pxa2xx_spi_chip {
        u8 tx_threshold;
        u8 rx_threshold;
        u8 dma_burst_size;
-       u32 timeout_microsecs;
+       u32 timeout;
        u8 enable_loopback;
        void (*cs_control)(u32 command);
 };
index 9089421..93a58e7 100644 (file)
@@ -31,6 +31,9 @@ struct s3c2410fb_hw {
 struct s3c2410fb_mach_info {
        unsigned char   fixed_syncs;    /* do not update sync/border */
 
+       /* LCD types */
+       int             type;
+
        /* Screen size */
        int             width;
        int             height;
diff --git a/include/asm-arm/arch-s3c2410/h1940.h b/include/asm-arm/arch-s3c2410/h1940.h
new file mode 100644 (file)
index 0000000..6135592
--- /dev/null
@@ -0,0 +1,21 @@
+/* linux/include/asm-arm/arch-s3c2410/h1940.h
+ *
+ * Copyright 2006 Ben Dooks <ben-linux@fluff.org>
+ *
+ * H1940 definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_H1940_H
+#define __ASM_ARCH_H1940_H
+
+#define H1940_SUSPEND_CHECKSUM         (0x30003ff8)
+#define H1940_SUSPEND_RESUMEAT         (0x30081000)
+#define H1940_SUSPEND_CHECK            (0x30080000)
+
+extern void h1940_pm_return(void);
+
+#endif /* __ASM_ARCH_H1940_H */
index 718246d..4f72a85 100644 (file)
@@ -71,7 +71,7 @@ arch_reset(char mode)
 
        /* set the watchdog to go and reset... */
        __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
-                    S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+                    S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
 
        /* wait for reset to assert... */
        mdelay(5000);
diff --git a/include/asm-arm/arch-sa1100/jornada720.h b/include/asm-arm/arch-sa1100/jornada720.h
deleted file mode 100644 (file)
index 3f37ca0..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * linux/include/asm-arm/arch-sa1100/jornada720.h
- *
- * Created 2000/11/29 by John Ankcorn <jca@lcs.mit.edu>
- *
- * This file contains the hardware specific definitions for HP Jornada 720
- *
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#error "include <asm/hardware.h> instead"
-#endif
-
-#define SA1111_BASE             (0x40000000)
-
-#define GPIO_JORNADA720_KEYBOARD       GPIO_GPIO(0)
-#define GPIO_JORNADA720_MOUSE          GPIO_GPIO(9)
-
-#define GPIO_JORNADA720_KEYBOARD_IRQ   IRQ_GPIO0
-#define GPIO_JORNADA720_MOUSE_IRQ              IRQ_GPIO9
-
-/* MCU COMMANDS */
-#define MCU_GetBatteryData  0xc0
-#define MCU_GetScanKeyCode  0x90
-#define MCU_GetTouchSamples 0xa0
-#define MCU_GetContrast     0xD0
-#define MCU_SetContrast     0xD1
-#define MCU_GetBrightness   0xD2
-#define MCU_SetBrightness   0xD3
-#define MCU_ContrastOff     0xD8
-#define MCU_BrightnessOff   0xD9
-#define MCU_PWMOFF          0xDF
-#define MCU_TxDummy         0x11
-#define MCU_ErrorCode       0x00
-
-#ifndef __ASSEMBLY__
-
-void jornada720_mcu_init(void);
-void jornada_contrast(int arg_contrast);
-void jornada720_battery(void);
-int jornada720_getkey(unsigned char *data, int size);
-#endif
index 1ff172d..0e907fc 100644 (file)
@@ -39,7 +39,6 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes);
 #define __virt_to_bus(x)        __virt_to_phys(x)
 #define __bus_to_virt(x)        __phys_to_virt(x)
 
-#ifdef CONFIG_DISCONTIGMEM
 /*
  * Because of the wide memory address space between physical RAM banks on the 
  * SA1100, it's much convenient to use Linux's NUMA support to implement our 
@@ -57,38 +56,7 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes);
  *     node 2:  0xd0000000 - 0xd7ffffff
  *     node 3:  0xd8000000 - 0xdfffffff
  */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 27)
-
-/*
- * Given a page frame number, convert it to a node id.
- */
-#define PFN_TO_NID(pfn)                (((pfn) - PHYS_PFN_OFFSET) >> (27 - PAGE_SHIFT))
-
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and return the mem_map of that node.
- */
-#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-
-/*
- * Given a page frame number, find the owning node of the memory
- * and return the mem_map of that node.
- */
-#define PFN_TO_MAPBASE(pfn)    NODE_MEM_MAP(PFN_TO_NID(pfn))
-
-/*
- * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
- * and returns the index corresponding to the appropriate page in the
- * node's mem_map.
- */
-#define LOCAL_MAP_NR(addr) \
-       (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT)
-
-#endif
+#define NODE_MEM_SIZE_BITS     27
 
 /*
  * Cache flushing area - SA1100 zero bank
index 0e36fd5..7b62351 100644 (file)
@@ -4,10 +4,10 @@
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line, void *data) __attribute__((noreturn));
+extern void __bug(const char *file, int line) __attribute__((noreturn));
 
 /* give file/line information */
-#define BUG()          __bug(__FILE__, __LINE__, NULL)
+#define BUG()          __bug(__FILE__, __LINE__)
 
 #else
 
diff --git a/include/asm-arm/cnt32_to_63.h b/include/asm-arm/cnt32_to_63.h
new file mode 100644 (file)
index 0000000..480c873
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits
+ *
+ *  Author:    Nicolas Pitre
+ *  Created:   December 3, 2006
+ *  Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef __INCLUDE_CNT32_TO_63_H__
+#define __INCLUDE_CNT32_TO_63_H__
+
+#include <linux/compiler.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+/*
+ * Prototype: u64 cnt32_to_63(u32 cnt)
+ * Many hardware clock counters are only 32 bits wide and therefore have
+ * a relatively short period making wrap-arounds rather frequent.  This
+ * is a problem when implementing sched_clock() for example, where a 64-bit
+ * non-wrapping monotonic value is expected to be returned.
+ *
+ * To overcome that limitation, let's extend a 32-bit counter to 63 bits
+ * in a completely lock free fashion. Bits 0 to 31 of the clock are provided
+ * by the hardware while bits 32 to 62 are stored in memory.  The top bit in
+ * memory is used to synchronize with the hardware clock half-period.  When
+ * the top bit of both counters (hardware and in memory) differ then the
+ * memory is updated with a new value, incrementing it when the hardware
+ * counter wraps around.
+ *
+ * Because a word store in memory is atomic then the incremented value will
+ * always be in synch with the top bit indicating to any potential concurrent
+ * reader if the value in memory is up to date or not with regards to the
+ * needed increment.  And any race in updating the value in memory is harmless
+ * as the same value would simply be stored more than once.
+ *
+ * The only restriction for the algorithm to work properly is that this
+ * code must be executed at least once per each half period of the 32-bit
+ * counter to properly update the state bit in memory. This is usually not a
+ * problem in practice, but if it is then a kernel timer could be scheduled
+ * to manage for this code to be executed often enough.
+ *
+ * Note that the top bit (bit 63) in the returned value should be considered
+ * as garbage.  It is not cleared here because callers are likely to use a
+ * multiplier on the returned value which can get rid of the top bit
+ * implicitly by making the multiplier even, therefore saving on a runtime
+ * clear-bit instruction. Otherwise caller must remember to clear the top
+ * bit explicitly.
+ */
+
+/* this is used only to give gcc a clue about good code generation */
+typedef union {
+       struct {
+#if defined(__LITTLE_ENDIAN)
+               u32 lo, hi;
+#elif defined(__BIG_ENDIAN)
+               u32 hi, lo;
+#endif
+       };
+       u64 val;
+} cnt32_to_63_t;
+
+#define cnt32_to_63(cnt_lo) \
+({ \
+       static volatile u32 __m_cnt_hi = 0; \
+       cnt32_to_63_t __x; \
+       __x.hi = __m_cnt_hi; \
+       __x.lo = (cnt_lo); \
+       if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \
+               __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \
+       __x.val; \
+})
+
+#endif
index 3682616..37e0a96 100644 (file)
@@ -27,7 +27,7 @@
 #define __xh "r1"
 #endif
 
-#define do_div(n,base)                                         \
+#define __do_div_asm(n, base)                                  \
 ({                                                             \
        register unsigned int __base      asm("r4") = base;     \
        register unsigned long long __n   asm("r0") = n;        \
        __rem;                                                  \
 })
 
+#if __GNUC__ < 4
+
+/*
+ * gcc versions earlier than 4.0 are simply too problematic for the
+ * optimized implementation below. First there is gcc PR 15089 that
+ * tend to trig on more complex constructs, spurious .global __udivsi3
+ * are inserted even if none of those symbols are referenced in the
+ * generated code, and those gcc versions are not able to do constant
+ * propagation on long long values anyway.
+ */
+#define do_div(n, base) __do_div_asm(n, base)
+
+#elif __GNUC__ >= 4
+
+#include <asm/bug.h>
+
+/*
+ * If the divisor happens to be constant, we determine the appropriate
+ * inverse at compile time to turn the division into a few inline
+ * multiplications instead which is much faster. And yet only if compiling
+ * for ARMv4 or higher (we need umull/umlal) and if the gcc version is
+ * sufficiently recent to perform proper long long constant propagation.
+ * (It is unfortunate that gcc doesn't perform all this internally.)
+ */
+#define do_div(n, base)                                                        \
+({                                                                     \
+       unsigned int __r, __b = (base);                                 \
+       if (!__builtin_constant_p(__b) || __b == 0 ||                   \
+           (__LINUX_ARM_ARCH__ < 4 && (__b & (__b - 1)) != 0)) {       \
+               /* non-constant divisor (or zero): slow path */         \
+               __r = __do_div_asm(n, __b);                             \
+       } else if ((__b & (__b - 1)) == 0) {                            \
+               /* Trivial: __b is constant and a power of 2 */         \
+               /* gcc does the right thing with this code.  */         \
+               __r = n;                                                \
+               __r &= (__b - 1);                                       \
+               n /= __b;                                               \
+       } else {                                                        \
+               /* Multiply by inverse of __b: n/b = n*(p/b)/p       */ \
+               /* We rely on the fact that most of this code gets   */ \
+               /* optimized away at compile time due to constant    */ \
+               /* propagation and only a couple inline assembly     */ \
+               /* instructions should remain. Better avoid any      */ \
+               /* code construct that might prevent that.           */ \
+               unsigned long long __res, __x, __t, __m, __n = n;       \
+               unsigned int __c, __p, __z = 0;                         \
+               /* preserve low part of n for reminder computation */   \
+               __r = __n;                                              \
+               /* determine number of bits to represent __b */         \
+               __p = 1 << __div64_fls(__b);                            \
+               /* compute __m = ((__p << 64) + __b - 1) / __b */       \
+               __m = (~0ULL / __b) * __p;                              \
+               __m += (((~0ULL % __b + 1) * __p) + __b - 1) / __b;     \
+               /* compute __res = __m*(~0ULL/__b*__b-1)/(__p << 64) */ \
+               __x = ~0ULL / __b * __b - 1;                            \
+               __res = (__m & 0xffffffff) * (__x & 0xffffffff);        \
+               __res >>= 32;                                           \
+               __res += (__m & 0xffffffff) * (__x >> 32);              \
+               __t = __res;                                            \
+               __res += (__x & 0xffffffff) * (__m >> 32);              \
+               __t = (__res < __t) ? (1ULL << 32) : 0;                 \
+               __res = (__res >> 32) + __t;                            \
+               __res += (__m >> 32) * (__x >> 32);                     \
+               __res /= __p;                                           \
+               /* Now sanitize and optimize what we've got. */         \
+               if (~0ULL % (__b / (__b & -__b)) == 0) {                \
+                       /* those cases can be simplified with: */       \
+                       __n /= (__b & -__b);                            \
+                       __m = ~0ULL / (__b / (__b & -__b));             \
+                       __p = 1;                                        \
+                       __c = 1;                                        \
+               } else if (__res != __x / __b) {                        \
+                       /* We can't get away without a correction    */ \
+                       /* to compensate for bit truncation errors.  */ \
+                       /* To avoid it we'd need an additional bit   */ \
+                       /* to represent __m which would overflow it. */ \
+                       /* Instead we do m=p/b and n/b=(n*m+m)/p.    */ \
+                       __c = 1;                                        \
+                       /* Compute __m = (__p << 64) / __b */           \
+                       __m = (~0ULL / __b) * __p;                      \
+                       __m += ((~0ULL % __b + 1) * __p) / __b;         \
+               } else {                                                \
+                       /* Reduce __m/__p, and try to clear bit 31   */ \
+                       /* of __m when possible otherwise that'll    */ \
+                       /* need extra overflow handling later.       */ \
+                       unsigned int __bits = -(__m & -__m);            \
+                       __bits |= __m >> 32;                            \
+                       __bits = (~__bits) << 1;                        \
+                       /* If __bits == 0 then setting bit 31 is     */ \
+                       /* unavoidable.  Simply apply the maximum    */ \
+                       /* possible reduction in that case.          */ \
+                       /* Otherwise the MSB of __bits indicates the */ \
+                       /* best reduction we should apply.           */ \
+                       if (!__bits) {                                  \
+                               __p /= (__m & -__m);                    \
+                               __m /= (__m & -__m);                    \
+                       } else {                                        \
+                               __p >>= __div64_fls(__bits);            \
+                               __m >>= __div64_fls(__bits);            \
+                       }                                               \
+                       /* No correction needed. */                     \
+                       __c = 0;                                        \
+               }                                                       \
+               /* Now we have a combination of 2 conditions:        */ \
+               /* 1) whether or not we need a correction (__c), and */ \
+               /* 2) whether or not there might be an overflow in   */ \
+               /*    the cross product (__m & ((1<<63) | (1<<31)))  */ \
+               /* Select the best insn combination to perform the   */ \
+               /* actual __m * __n / (__p << 64) operation.         */ \
+               if (!__c) {                                             \
+                       asm (   "umull  %Q0, %R0, %1, %Q2\n\t"          \
+                               "mov    %Q0, #0"                        \
+                               : "=&r" (__res)                         \
+                               : "r" (__m), "r" (__n)                  \
+                               : "cc" );                               \
+               } else if (!(__m & ((1ULL << 63) | (1ULL << 31)))) {    \
+                       __res = __m;                                    \
+                       asm (   "umlal  %Q0, %R0, %Q1, %Q2\n\t"         \
+                               "mov    %Q0, #0"                        \
+                               : "+r" (__res)                          \
+                               : "r" (__m), "r" (__n)                  \
+                               : "cc" );                               \
+               } else {                                                \
+                       asm (   "umull  %Q0, %R0, %Q1, %Q2\n\t"         \
+                               "cmn    %Q0, %Q1\n\t"                   \
+                               "adcs   %R0, %R0, %R1\n\t"              \
+                               "adc    %Q0, %3, #0"                    \
+                               : "=&r" (__res)                         \
+                               : "r" (__m), "r" (__n), "r" (__z)       \
+                               : "cc" );                               \
+               }                                                       \
+               if (!(__m & ((1ULL << 63) | (1ULL << 31)))) {           \
+                       asm (   "umlal  %R0, %Q0, %R1, %Q2\n\t"         \
+                               "umlal  %R0, %Q0, %Q1, %R2\n\t"         \
+                               "mov    %R0, #0\n\t"                    \
+                               "umlal  %Q0, %R0, %R1, %R2"             \
+                               : "+r" (__res)                          \
+                               : "r" (__m), "r" (__n)                  \
+                               : "cc" );                               \
+               } else {                                                \
+                       asm (   "umlal  %R0, %Q0, %R2, %Q3\n\t"         \
+                               "umlal  %R0, %1, %Q2, %R3\n\t"          \
+                               "mov    %R0, #0\n\t"                    \
+                               "adds   %Q0, %1, %Q0\n\t"               \
+                               "adc    %R0, %R0, #0\n\t"               \
+                               "umlal  %Q0, %R0, %R2, %R3"             \
+                               : "+r" (__res), "+r" (__z)              \
+                               : "r" (__m), "r" (__n)                  \
+                               : "cc" );                               \
+               }                                                       \
+               __res /= __p;                                           \
+               /* The reminder can be computed with 32-bit regs     */ \
+               /* only, and gcc is good at that.                    */ \
+               {                                                       \
+                       unsigned int __res0 = __res;                    \
+                       unsigned int __b0 = __b;                        \
+                       __r -= __res0 * __b0;                           \
+               }                                                       \
+               /* BUG_ON(__r >= __b || __res * __b + __r != n); */     \
+               n = __res;                                              \
+       }                                                               \
+       __r;                                                            \
+})
+
+/* our own fls implementation to make sure constant propagation is fine */
+#define __div64_fls(bits)                                              \
+({                                                                     \
+       unsigned int __left = (bits), __nr = 0;                         \
+       if (__left & 0xffff0000) __nr += 16, __left >>= 16;             \
+       if (__left & 0x0000ff00) __nr +=  8, __left >>=  8;             \
+       if (__left & 0x000000f0) __nr +=  4, __left >>=  4;             \
+       if (__left & 0x0000000c) __nr +=  2, __left >>=  2;             \
+       if (__left & 0x00000002) __nr +=  1;                            \
+       __nr;                                                           \
+})
+
+#endif
+
 #endif
index 6666177..9bc46b4 100644 (file)
@@ -48,7 +48,7 @@ static inline int dma_get_cache_alignment(void)
        return 32;
 }
 
-static inline int dma_is_consistent(dma_addr_t handle)
+static inline int dma_is_consistent(struct device *dev, dma_addr_t handle)
 {
        return !!arch_is_coherent();
 }
index 17f0c65..642382d 100644 (file)
@@ -1,17 +1,22 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
-
+#ifndef __ASSEMBLY__
 /*
  * ELF register definitions..
  */
-
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
 typedef unsigned long elf_freg_t[3];
 
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_fp elf_fpregset_t;
+#endif
+
 #define EM_ARM 40
 #define EF_ARM_APCS26 0x08
 #define EF_ARM_SOFT_FLOAT 0x200
@@ -23,11 +28,6 @@ typedef unsigned long elf_freg_t[3];
 #define R_ARM_CALL     28
 #define R_ARM_JUMP24   29
 
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fp elf_fpregset_t;
-
 /*
  * These are used to set parameters in the core dumps.
  */
@@ -39,97 +39,99 @@ typedef struct user_fp elf_fpregset_t;
 #endif
 #define ELF_ARCH       EM_ARM
 
-#ifdef __KERNEL__
-#include <asm/procinfo.h>
-
 /*
- * This is used to ensure we don't load something for the wrong architecture.
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
  */
-#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) )
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE      4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE        (2 * TASK_SIZE / 3)
-
-/* When the program starts, a1 contains a pointer to a function to be 
-   registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
-   have no such handler.  */
-#define ELF_PLAT_INIT(_r, load_addr)   (_r)->ARM_r0 = 0
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports. */
+#define HWCAP_SWP      1
+#define HWCAP_HALF     2
+#define HWCAP_THUMB    4
+#define HWCAP_26BIT    8       /* Play it safe */
+#define HWCAP_FAST_MULT        16
+#define HWCAP_FPA      32
+#define HWCAP_VFP      64
+#define HWCAP_EDSP     128
+#define HWCAP_JAVA     256
+#define HWCAP_IWMMXT   512
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
 #define ELF_HWCAP      (elf_hwcap)
+extern unsigned int elf_hwcap;
 
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo. */
-
-/* For now we just provide a fairly general string that describes the
-   processor family.  This could be made more specific later if someone
-   implemented optimisations that require it.  26-bit CPUs give you
-   "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't
-   supported).  32-bit CPUs give you "v3[lb]" for anything based on an
-   ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1
-   core.  */
-
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ *
+ * For now we just provide a fairly general string that describes the
+ * processor family.  This could be made more specific later if someone
+ * implemented optimisations that require it.  26-bit CPUs give you
+ * "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't
+ * supported).  32-bit CPUs give you "v3[lb]" for anything based on an
+ * ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1
+ * core.
+ */
 #define ELF_PLATFORM_SIZE 8
-extern char elf_platform[];
 #define ELF_PLATFORM   (elf_platform)
 
+extern char elf_platform[];
+#endif
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_ARM && ELF_PROC_OK(x))
+
 /*
  * 32-bit code is always OK.  Some cpus can do 26-bit, some can't.
  */
 #define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x))
 
 #define ELF_THUMB_OK(x) \
-       (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \
+       ((elf_hwcap & HWCAP_THUMB && ((x)->e_entry & 1) == 1) || \
         ((x)->e_entry & 3) == 0)
 
 #define ELF_26BIT_OK(x) \
-       (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \
+       ((elf_hwcap & HWCAP_26BIT && (x)->e_flags & EF_ARM_APCS26) || \
          ((x)->e_flags & EF_ARM_APCS26) == 0)
 
-#ifndef CONFIG_IWMMXT
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE      4096
 
-/* Old NetWinder binaries were compiled in such a way that the iBCS
-   heuristic always trips on them.  Until these binaries become uncommon
-   enough not to care, don't trust the `ibcs' flag here.  In any case
-   there is no other ELF system currently supported by iBCS.
-   @@ Could print a warning message to encourage users to upgrade.  */
-#define SET_PERSONALITY(ex,ibcs2) \
-       set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT))
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
 
-#else
+#define ELF_ET_DYN_BASE        (2 * TASK_SIZE / 3)
+
+/* When the program starts, a1 contains a pointer to a function to be 
+   registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
+   have no such handler.  */
+#define ELF_PLAT_INIT(_r, load_addr)   (_r)->ARM_r0 = 0
 
 /*
- * All iWMMXt capable CPUs don't support 26-bit mode.  Yet they can run
- * legacy binaries which used to contain FPA11 floating point instructions
- * that have always been emulated by the kernel.  PFA11 and iWMMXt overlap
- * on coprocessor 1 space though.  We therefore must decide if given task
- * is allowed to use CP 0 and 1 for iWMMXt, or if they should be blocked
- * at all times for the prefetch exception handler to catch FPA11 opcodes
- * and emulate them.  The best indication to discriminate those two cases
- * is the SOFT_FLOAT flag in the ELF header.
+ * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0
+ * and CP1, we only enable access to the iWMMXt coprocessor if the
+ * binary is EABI or softfloat (and thus, guaranteed not to use
+ * FPA instructions.)
  */
-
-#define SET_PERSONALITY(ex,ibcs2) \
-do { \
-       set_personality(PER_LINUX_32BIT); \
-       if (((ex).e_flags & EF_ARM_EABI_MASK) || \
-           ((ex).e_flags & EF_ARM_SOFT_FLOAT)) \
-               set_thread_flag(TIF_USING_IWMMXT); \
-       else \
-               clear_thread_flag(TIF_USING_IWMMXT); \
-} while (0)
-
-#endif
+#define SET_PERSONALITY(ex, ibcs2)                                     \
+       do {                                                            \
+               if ((ex).e_flags & EF_ARM_APCS26) {                     \
+                       set_personality(PER_LINUX);                     \
+               } else {                                                \
+                       set_personality(PER_LINUX_32BIT);               \
+                       if (elf_hwcap & HWCAP_IWMMXT && (ex).e_flags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) \
+                               set_thread_flag(TIF_USING_IWMMXT);      \
+                       else                                            \
+                               clear_thread_flag(TIF_USING_IWMMXT);    \
+               }                                                       \
+       } while (0)
 
 #endif
 
index ae999fd..288f76b 100644 (file)
@@ -75,14 +75,6 @@ extern void __readwrite_bug(const char *fn);
  */
 #include <asm/arch/io.h>
 
-#ifdef __io_pci
-#warning machine class uses buggy __io_pci
-#endif
-#if defined(__arch_putb) || defined(__arch_putw) || defined(__arch_putl) || \
-    defined(__arch_getb) || defined(__arch_getw) || defined(__arch_getl)
-#warning machine class uses old __arch_putw or __arch_getw
-#endif
-
 /*
  *  IO port access primitives
  *  -------------------------
index 0e017ec..eb0bfba 100644 (file)
@@ -21,12 +21,6 @@ extern void (*init_arch_irq)(void);
 extern void init_FIQ(void);
 extern int show_fiq_list(struct seq_file *, void *);
 
-/*
- * Function wrappers
- */
-#define set_irq_chipdata(irq, d)       set_irq_chip_data(irq, d)
-#define get_irq_chipdata(irq)          get_irq_chip_data(irq)
-
 /*
  * Obsolete inline function for calling irq descriptor handlers.
  */
@@ -44,12 +38,6 @@ void set_irq_flags(unsigned int irq, unsigned int flags);
 /*
  * This is for easy migration, but should be changed in the source
  */
-#define do_level_IRQ   handle_level_irq
-#define do_edge_IRQ    handle_edge_irq
-#define do_simple_IRQ  handle_simple_irq
-#define irqdesc                irq_desc
-#define irqchip                irq_chip
-
 #define do_bad_IRQ(irq,desc)                           \
 do {                                                   \
        spin_lock(&desc->lock);                         \
index 91d536c..d9bfb39 100644 (file)
@@ -215,6 +215,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
  *  virt_addr_valid(k) indicates whether a virtual address is valid
  */
 #ifndef CONFIG_DISCONTIGMEM
+
 #define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
 #define pfn_valid(pfn)         ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
 
@@ -230,6 +231,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
  * around in memory.
  */
 #include <linux/numa.h>
+
 #define arch_pfn_to_nid(pfn)   PFN_TO_NID(pfn)
 #define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
 
@@ -256,6 +258,43 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
  */
 #define PHYS_TO_NID(addr)      PFN_TO_NID((addr) >> PAGE_SHIFT)
 
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn)    NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+#ifdef NODE_MEM_SIZE_BITS
+#define NODE_MEM_SIZE_MASK     ((1 << NODE_MEM_SIZE_BITS) - 1)
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+       (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MEM_SIZE_BITS)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+       (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MEM_SIZE_BITS - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ * and returns the index corresponding to the appropriate page in the
+ * node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+       (((unsigned long)(addr) & NODE_MEM_SIZE_MASK) >> PAGE_SHIFT)
+
+#endif /* NODE_MEM_SIZE_BITS */
+
 #endif /* !CONFIG_DISCONTIGMEM */
 
 /*
index c1b264d..7b1c9ac 100644 (file)
@@ -44,7 +44,6 @@
 #define PAGE_READONLY  __pgprot(0)
 #define PAGE_KERNEL    __pgprot(0)
 
-//extern void paging_init(struct meminfo *, struct machine_desc *);
 #define swapper_pg_dir ((pgd_t *) 0)
 
 #define __swp_type(x)          (0)
index ed8cb59..88cd5c7 100644 (file)
@@ -169,8 +169,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define L_PTE_WRITE            (1 << 5)
 #define L_PTE_EXEC             (1 << 6)
 #define L_PTE_DIRTY            (1 << 7)
-#define L_PTE_COHERENT         (1 << 9)        /* I/O coherent (xsc3) */
-#define L_PTE_SHARED           (1 << 10)       /* shared between CPUs (v6) */
+#define L_PTE_SHARED           (1 << 10)       /* shared(v6), coherent(xsc3) */
 #define L_PTE_ASID             (1 << 11)       /* non-global (use ASID, v6) */
 
 #ifndef __ASSEMBLY__
index 04f4d34..b442e8e 100644 (file)
@@ -20,7 +20,6 @@
 #ifdef __KERNEL__
 
 #include <asm/ptrace.h>
-#include <asm/procinfo.h>
 #include <asm/types.h>
 
 union debug_insn {
index 91a31ad..4d3c685 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __ASM_PROCINFO_H
 #define __ASM_PROCINFO_H
 
-#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
 
 struct cpu_tlb_fns;
 struct cpu_user_fns;
@@ -42,19 +42,8 @@ struct proc_info_list {
        struct cpu_cache_fns    *cache;
 };
 
-extern unsigned int elf_hwcap;
-
-#endif /* __ASSEMBLY__ */
-
-#define HWCAP_SWP      1
-#define HWCAP_HALF     2
-#define HWCAP_THUMB    4
-#define HWCAP_26BIT    8       /* Play it safe */
-#define HWCAP_FAST_MULT        16
-#define HWCAP_FPA      32
-#define HWCAP_VFP      64
-#define HWCAP_EDSP     128
-#define HWCAP_JAVA     256
-#define HWCAP_IWMMXT   512
-
+#else  /* __KERNEL__ */
+#include <asm/elf.h>
+#warning "Please include asm/elf.h instead"
+#endif /* __KERNEL__ */
 #endif
index aa4b578..e540739 100644 (file)
 #ifndef __ASMARM_SETUP_H
 #define __ASMARM_SETUP_H
 
+#include <asm/types.h>
+
 #define COMMAND_LINE_SIZE 1024
 
 /* The list ends with an ATAG_NONE node. */
 #define ATAG_NONE      0x00000000
 
 struct tag_header {
-       u32 size;
-       u32 tag;
+       __u32 size;
+       __u32 tag;
 };
 
 /* The list must start with an ATAG_CORE node */
 #define ATAG_CORE      0x54410001
 
 struct tag_core {
-       u32 flags;              /* bit 0 = read-only */
-       u32 pagesize;
-       u32 rootdev;
+       __u32 flags;            /* bit 0 = read-only */
+       __u32 pagesize;
+       __u32 rootdev;
 };
 
 /* it is allowed to have multiple ATAG_MEM nodes */
 #define ATAG_MEM       0x54410002
 
 struct tag_mem32 {
-       u32     size;
-       u32     start;  /* physical start address */
+       __u32   size;
+       __u32   start;  /* physical start address */
 };
 
 /* VGA text type displays */
 #define ATAG_VIDEOTEXT 0x54410003
 
 struct tag_videotext {
-       u8              x;
-       u8              y;
-       u16             video_page;
-       u8              video_mode;
-       u8              video_cols;
-       u16             video_ega_bx;
-       u8              video_lines;
-       u8              video_isvga;
-       u16             video_points;
+       __u8            x;
+       __u8            y;
+       __u16           video_page;
+       __u8            video_mode;
+       __u8            video_cols;
+       __u16           video_ega_bx;
+       __u8            video_lines;
+       __u8            video_isvga;
+       __u16           video_points;
 };
 
 /* describes how the ramdisk will be used in kernel */
 #define ATAG_RAMDISK   0x54410004
 
 struct tag_ramdisk {
-       u32 flags;      /* bit 0 = load, bit 1 = prompt */
-       u32 size;       /* decompressed ramdisk size in _kilo_ bytes */
-       u32 start;      /* starting block of floppy-based RAM disk image */
+       __u32 flags;    /* bit 0 = load, bit 1 = prompt */
+       __u32 size;     /* decompressed ramdisk size in _kilo_ bytes */
+       __u32 start;    /* starting block of floppy-based RAM disk image */
 };
 
 /* describes where the compressed ramdisk image lives (virtual address) */
@@ -76,23 +78,23 @@ struct tag_ramdisk {
 #define ATAG_INITRD2   0x54420005
 
 struct tag_initrd {
-       u32 start;      /* physical start address */
-       u32 size;       /* size of compressed ramdisk image in bytes */
+       __u32 start;    /* physical start address */
+       __u32 size;     /* size of compressed ramdisk image in bytes */
 };
 
 /* board serial number. "64 bits should be enough for everybody" */
 #define ATAG_SERIAL    0x54410006
 
 struct tag_serialnr {
-       u32 low;
-       u32 high;
+       __u32 low;
+       __u32 high;
 };
 
 /* board revision */
 #define ATAG_REVISION  0x54410007
 
 struct tag_revision {
-       u32 rev;
+       __u32 rev;
 };
 
 /* initial values for vesafb-type framebuffers. see struct screen_info
@@ -101,20 +103,20 @@ struct tag_revision {
 #define ATAG_VIDEOLFB  0x54410008
 
 struct tag_videolfb {
-       u16             lfb_width;
-       u16             lfb_height;
-       u16             lfb_depth;
-       u16             lfb_linelength;
-       u32             lfb_base;
-       u32             lfb_size;
-       u8              red_size;
-       u8              red_pos;
-       u8              green_size;
-       u8              green_pos;
-       u8              blue_size;
-       u8              blue_pos;
-       u8              rsvd_size;
-       u8              rsvd_pos;
+       __u16           lfb_width;
+       __u16           lfb_height;
+       __u16           lfb_depth;
+       __u16           lfb_linelength;
+       __u32           lfb_base;
+       __u32           lfb_size;
+       __u8            red_size;
+       __u8            red_pos;
+       __u8            green_size;
+       __u8            green_pos;
+       __u8            blue_size;
+       __u8            blue_pos;
+       __u8            rsvd_size;
+       __u8            rsvd_pos;
 };
 
 /* command line: \0 terminated string */
@@ -128,17 +130,17 @@ struct tag_cmdline {
 #define ATAG_ACORN     0x41000101
 
 struct tag_acorn {
-       u32 memc_control_reg;
-       u32 vram_pages;
-       u8 sounddefault;
-       u8 adfsdrives;
+       __u32 memc_control_reg;
+       __u32 vram_pages;
+       __u8 sounddefault;
+       __u8 adfsdrives;
 };
 
 /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
 #define ATAG_MEMCLK    0x41000402
 
 struct tag_memclk {
-       u32 fmemclk;
+       __u32 fmemclk;
 };
 
 struct tag {
@@ -167,24 +169,26 @@ struct tag {
 };
 
 struct tagtable {
-       u32 tag;
+       __u32 tag;
        int (*parse)(const struct tag *);
 };
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
-#define __tagtable(tag, fn) \
-static struct tagtable __tagtable_##fn __tag = { tag, fn }
-
 #define tag_member_present(tag,member)                         \
        ((unsigned long)(&((struct tag *)0L)->member + 1)       \
                <= (tag)->hdr.size * 4)
 
-#define tag_next(t)    ((struct tag *)((u32 *)(t) + (t)->hdr.size))
+#define tag_next(t)    ((struct tag *)((__u32 *)(t) + (t)->hdr.size))
 #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
 
 #define for_each_tag(t,base)           \
        for (t = base; t->hdr.size; t = tag_next(t))
 
+#ifdef __KERNEL__
+
+#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
+#define __tagtable(tag, fn) \
+static struct tagtable __tagtable_##fn __tag = { tag, fn }
+
 /*
  * Memory map description
  */
@@ -217,4 +221,6 @@ struct early_params {
 static struct early_params __early_##fn __attribute_used__     \
 __attribute__((__section__(".early_param.init"))) = { name, fn }
 
+#endif  /*  __KERNEL__  */
+
 #endif
index bbc6e1d..a3f4fe1 100644 (file)
@@ -15,6 +15,18 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index f28b236..d9b8bdd 100644 (file)
@@ -94,8 +94,18 @@ static inline struct thread_info *current_thread_info(void)
        return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
 }
 
-extern struct thread_info *alloc_thread_info(struct task_struct *task);
-extern void free_thread_info(struct thread_info *);
+/* thread information allocation */
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk) \
+       ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+               THREAD_SIZE_ORDER))
+#else
+#define alloc_thread_info(tsk) \
+       ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
+#endif
+
+#define free_thread_info(info) \
+       free_pages((unsigned long)info, THREAD_SIZE_ORDER);
 
 #define thread_saved_pc(tsk)   \
        ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))
index 14a87ee..d44c629 100644 (file)
 #endif
 
 #ifdef __KERNEL__
-#include <linux/err.h>
-#include <linux/linkage.h>
-
-#define __sys2(x) #x
-#define __sys1(x) __sys2(x)
-
-#ifndef __syscall
-#if defined(__thumb__) || defined(__ARM_EABI__)
-#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name;
-#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
-#define __syscall(name) "swi\t0"
-#else
-#define __SYS_REG(name)
-#define __SYS_REG_LIST(regs...) regs
-#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
-#endif
-#endif
-
-#define __syscall_return(type, res)                                    \
-do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {      \
-               errno = -(res);                                         \
-               res = -1;                                               \
-       }                                                               \
-       return (type) (res);                                            \
-} while (0)
-
-#define _syscall0(type,name)                                           \
-type name(void) {                                                      \
-  __SYS_REG(name)                                                      \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST()                                              \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall1(type,name,type1,arg1)                                \
-type name(type1 arg1) {                                                \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0) )                                  \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)                     \
-type name(type1 arg1,type2 arg2) {                                     \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0), "r" (__r1) )                      \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)          \
-type name(type1 arg1,type2 arg2,type3 arg3) {                          \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) )          \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {            \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-  
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)    \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {        \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __r4 __asm__("r4") = (long)arg5;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2),           \
-                         "r" (__r3), "r" (__r4) )                      \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) {    \
-  __SYS_REG(name)                                                      \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __r4 __asm__("r4") = (long)arg5;                       \
-  register long __r5 __asm__("r5") = (long)arg6;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2),           \
-                         "r" (__r3), "r" (__r4), "r" (__r5) )          \
-       : "memory" );                                                   \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
index 6437167..7725af3 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/tlbflush.h>
 #include <linux/slab.h>
 
-extern kmem_cache_t *pte_cache;
+extern struct kmem_cache *pte_cache;
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr){
        return kmem_cache_alloc(pte_cache, GFP_KERNEL);
index 6348931..1a867b4 100644 (file)
@@ -16,6 +16,8 @@
 
 #define COMMAND_LINE_SIZE 1024
 
+#ifdef __KERNEL__
+
 /* The list ends with an ATAG_NONE node. */
 #define ATAG_NONE      0x00000000
 
@@ -202,4 +204,6 @@ struct meminfo {
 
 extern struct meminfo meminfo;
 
+#endif  /*  __KERNEL__  */
+
 #endif
index bbc6e1d..a3f4fe1 100644 (file)
@@ -15,6 +15,18 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 25a5eea..4c3b919 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 __sys1(x) __sys2(x)
-
-#ifndef __syscall
-#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
-#endif
-
-#define __syscall_return(type, res)                                    \
-do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)-MAX_ERRNO) {        \
-               errno = -(res);                                         \
-               res = -1;                                               \
-       }                                                               \
-       return (type) (res);                                            \
-} while (0)
-
-#define _syscall0(type,name)                                           \
-type name(void) {                                                      \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       :                                                               \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall1(type,name,type1,arg1)                                \
-type name(type1 arg1) {                                                \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0)                                                    \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)                     \
-type name(type1 arg1,type2 arg2) {                                     \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0),"r" (__r1)                                         \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)          \
-type name(type1 arg1,type2 arg2,type3 arg3) {                          \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0),"r" (__r1),"r" (__r2)                              \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {            \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3)                   \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-  
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)    \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {        \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __r4 __asm__("r4") = (long)arg5;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4)        \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) {    \
-  register long __r0 __asm__("r0") = (long)arg1;                       \
-  register long __r1 __asm__("r1") = (long)arg2;                       \
-  register long __r2 __asm__("r2") = (long)arg3;                       \
-  register long __r3 __asm__("r3") = (long)arg4;                       \
-  register long __r4 __asm__("r4") = (long)arg5;                       \
-  register long __r5 __asm__("r5") = (long)arg6;                       \
-  register long __res_r0 __asm__("r0");                                        \
-  long __res;                                                          \
-  __asm__ __volatile__ (                                               \
-  __syscall(name)                                                      \
-       : "=r" (__res_r0)                                               \
-       : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5)            \
-       : "lr");                                                        \
-  __res = __res_r0;                                                    \
-  __syscall_return(type,__res);                                                \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
new file mode 100644 (file)
index 0000000..ba85e04
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Pin definitions for AT32AP7000.
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_AT32AP7000_H__
+#define __ASM_ARCH_AT32AP7000_H__
+
+#define GPIO_PERIPH_A  0
+#define GPIO_PERIPH_B  1
+
+#define NR_GPIO_CONTROLLERS    4
+
+/*
+ * Pin numbers identifying specific GPIO pins on the chip. They can
+ * also be converted to IRQ numbers by passing them through
+ * gpio_to_irq().
+ */
+#define GPIO_PIOA_BASE (0)
+#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
+#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
+#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
+
+#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
+#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
+#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
+#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
+
+#endif /* __ASM_ARCH_AT32AP7000_H__ */
similarity index 92%
rename from include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
rename to include/asm-avr32/arch-at32ap/at91_pdc.h
index ce1150d..79d6e02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
+ * include/asm-arm/arch-at91rm9200/at91_pdc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -13,8 +13,8 @@
  * (at your option) any later version.
  */
 
-#ifndef AT91RM9200_PDC_H
-#define AT91RM9200_PDC_H
+#ifndef AT91_PDC_H
+#define AT91_PDC_H
 
 #define AT91_PDC_RPR           0x100   /* Receive Pointer Register */
 #define AT91_PDC_RCR           0x104   /* Receive Counter Register */
index a39b3e9..b120ee0 100644 (file)
@@ -21,10 +21,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line);
 struct platform_device *at32_add_device_usart(unsigned int id);
 
 struct eth_platform_data {
-       u8      valid;
-       u8      mii_phy_addr;
        u8      is_rmii;
-       u8      hw_addr[6];
 };
 struct platform_device *
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
index 4d50421..83c6905 100644 (file)
@@ -7,10 +7,20 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_AVR32_AT32_PORTMUX_H__
-#define __ASM_AVR32_AT32_PORTMUX_H__
+#ifndef __ASM_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id);
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * The following flags determine the initial state of the pin.
+ */
+#define AT32_GPIOF_PULLUP      0x00000001      /* Enable pull-up */
+#define AT32_GPIOF_OUTPUT      0x00000002      /* Enable output driver */
+#define AT32_GPIOF_HIGH                0x00000004      /* Set output high */
+
+void at32_select_periph(unsigned int pin, unsigned int periph,
+                       unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
 
-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */
+#endif /* __ASM_ARCH_PORTMUX_H__ */
index 4c40cb4..5c01e27 100644 (file)
@@ -8,7 +8,8 @@
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 
-extern void dma_cache_sync(void *vaddr, size_t size, int direction);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+       int direction);
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -108,7 +109,7 @@ static inline dma_addr_t
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
               enum dma_data_direction direction)
 {
-       dma_cache_sync(cpu_addr, size, direction);
+       dma_cache_sync(dev, cpu_addr, size, direction);
        return virt_to_bus(cpu_addr);
 }
 
@@ -210,7 +211,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
                sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
                virt = page_address(sg[i].page) + sg[i].offset;
-               dma_cache_sync(virt, sg[i].length, direction);
+               dma_cache_sync(dev, virt, sg[i].length, direction);
        }
 
        return nents;
@@ -255,14 +256,14 @@ static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
                        size_t size, enum dma_data_direction direction)
 {
-       dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+       dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
                           size_t size, enum dma_data_direction direction)
 {
-       dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+       dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 /**
@@ -285,7 +286,7 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++) {
-               dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+               dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
                               sg[i].length, direction);
        }
 }
@@ -297,7 +298,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++) {
-               dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+               dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
                               sg[i].length, direction);
        }
 }
@@ -307,7 +308,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
-static inline int dma_is_consistent(dma_addr_t dma_addr)
+static inline int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 1;
 }
index 10193da..0a52242 100644 (file)
@@ -13,6 +13,8 @@
 
 #define COMMAND_LINE_SIZE 256
 
+#ifdef __KERNEL__
+
 /* Magic number indicating that a tag table is present */
 #define ATAG_MAGIC     0xa2a25441
 
@@ -138,4 +140,6 @@ void chip_enable_sdram(void);
 
 #endif /* !__ASSEMBLY__ */
 
+#endif  /*  __KERNEL__  */
+
 #endif /* __ASM_AVR32_SETUP_H__ */
index 9dc6eac..c215faf 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index b73f539..be85f6d 100644 (file)
@@ -10,7 +10,7 @@
  * number.  They differ in that the first function also inverts all bits
  * in the input.
  */
-extern inline unsigned long cris_swapnwbrlz(unsigned long w)
+static inline unsigned long cris_swapnwbrlz(unsigned long w)
 {
        /* Let's just say we return the result in the same register as the
           input.  Saying we clobber the input but can return the result
@@ -26,7 +26,7 @@ extern inline unsigned long cris_swapnwbrlz(unsigned long w)
        return res;
 }
 
-extern inline unsigned long cris_swapwbrlz(unsigned long w)
+static inline unsigned long cris_swapwbrlz(unsigned long w)
 {
        unsigned res;
        __asm__ ("swapwbr %0 \n\t"
@@ -40,7 +40,7 @@ extern inline unsigned long cris_swapwbrlz(unsigned long w)
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
  */
-extern inline unsigned long ffz(unsigned long w)
+static inline unsigned long ffz(unsigned long w)
 {
        return cris_swapnwbrlz(w);
 }
@@ -51,7 +51,7 @@ extern inline unsigned long ffz(unsigned long w)
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-extern inline unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
        return cris_swapnwbrlz(~word);
 }
@@ -65,7 +65,7 @@ extern inline unsigned long __ffs(unsigned long word)
  * differs in spirit from the above ffz (man ffs).
  */
 
-extern inline unsigned long kernel_ffs(unsigned long w)
+static inline unsigned long kernel_ffs(unsigned long w)
 {
        return w ? cris_swapwbrlz (w) + 1 : 0;
 }
index cbf1a98..662cea7 100644 (file)
@@ -156,10 +156,10 @@ dma_get_cache_alignment(void)
        return (1 << INTERNODE_CACHE_SHIFT);
 }
 
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
 }
index dbd0f30..a8e1e6c 100644 (file)
 /*
  * These two _must_ execute atomically wrt each other.
  */
-extern inline void wake_one_more(struct semaphore * sem)
+static inline void wake_one_more(struct semaphore * sem)
 {
        atomic_inc(&sem->waking);
 }
 
-extern inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem)
 {
        unsigned long flags;
        int ret = 0;
@@ -40,7 +40,7 @@ extern inline int waking_non_zero(struct semaphore *sem)
        return ret;
 }
 
-extern inline int waking_non_zero_interruptible(struct semaphore *sem,
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
                                                struct task_struct *tsk)
 {
        int ret = 0;
@@ -59,7 +59,7 @@ extern inline int waking_non_zero_interruptible(struct semaphore *sem,
        return ret;
 }
 
-extern inline int waking_non_zero_trylock(struct semaphore *sem)
+static inline int waking_non_zero_trylock(struct semaphore *sem)
 {
         int ret = 1;
        unsigned long flags;
index be0836d..8d8cec2 100644 (file)
@@ -19,6 +19,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 1f70d47..f8560ed 100644 (file)
@@ -256,6 +256,50 @@ int __ffs(unsigned long x)
        return 31 - bit;
 }
 
+/*
+ * special slimline version of fls() for calculating ilog2_u32()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U32
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+       int bit;
+       asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n));
+       return 31 - bit;
+}
+
+/*
+ * special slimline version of fls64() for calculating ilog2_u64()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U64
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+       union {
+               u64 ll;
+               struct { u32 h, l; };
+       } _;
+       int bit, x, y;
+
+       _.ll = n;
+
+       asm("   subcc           %3,gr0,gr0,icc0         \n"
+           "   ckeq            icc0,cc4                \n"
+           "   cscan.p         %3,gr0,%0       ,cc4,0  \n"
+           "   setlos          #63,%1                  \n"
+           "   cscan.p         %4,gr0,%0       ,cc4,1  \n"
+           "   setlos          #31,%2                  \n"
+           "   csub.p          %1,%0,%0        ,cc4,0  \n"
+           "   csub            %2,%0,%0        ,cc4,1  \n"
+           : "=&r"(bit), "=r"(x), "=r"(y)
+           : "0r"(_.h), "r"(_.l)
+           : "icc0", "cc4"
+           );
+       return bit;
+}
+
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
 
index e9fc1d4..bcb2df6 100644 (file)
@@ -172,10 +172,10 @@ int dma_get_cache_alignment(void)
        return 1 << L1_CACHE_SHIFT;
 }
 
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline
-void dma_cache_sync(void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                    enum dma_data_direction direction)
 {
        flush_write_buffers();
index 0f390f4..ff4d6cd 100644 (file)
@@ -115,7 +115,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
        unsigned long paddr;
 
-       inc_preempt_count();
+       pagefault_disable();
        paddr = page_to_phys(page);
 
        switch (type) {
@@ -170,8 +170,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
        default:
                BUG();
        }
-       dec_preempt_count();
-       preempt_check_resched();
+       pagefault_enable();
 }
 
 #endif /* !__ASSEMBLY__ */
index 168381e..365653b 100644 (file)
@@ -18,6 +18,5 @@
 #endif
 
 #define MAXHOSTNAMELEN         64      /* max length of hostname */
-#define COMMAND_LINE_SIZE      512
 
 #endif /* _ASM_PARAM_H */
index 0d293b9..afd787c 100644 (file)
 #ifndef _ASM_SETUP_H
 #define _ASM_SETUP_H
 
+#define COMMAND_LINE_SIZE       512
+
+#ifdef __KERNEL__
+
 #include <linux/init.h>
 
 #ifndef __ASSEMBLY__
@@ -22,4 +26,6 @@ extern unsigned long __initdata num_mappedpages;
 
 #endif /* !__ASSEMBLY__ */
 
+#endif  /*  __KERNEL__  */
+
 #endif /* _ASM_SETUP_H */
index 74f20d6..2d6d389 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 725e854..584c041 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
- * - user-visible error numbers are in the range -1 - -4095: see <asm-frv/errno.h>
- */
-#undef __syscall_return
-#define __syscall_return(type, res)                                    \
-do {                                                                   \
-        unsigned long __sr2 = (res);                                   \
-       if (__builtin_expect(__sr2 >= (unsigned long)(-MAX_ERRNO), 0)) { \
-               errno = (-__sr2);                                       \
-               __sr2 = ~0UL;                                           \
-       }                                                               \
-       return (type) __sr2;                                            \
-} while (0)
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-
-#undef _syscall0
-#define _syscall0(type,name)                                           \
-type name(void)                                                                \
-{                                                                      \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \
-       register unsigned long __sc0 __asm__ ("gr8");                   \
-       __asm__ __volatile__ ("tira gr0,#0"                             \
-                             : "=r" (__sc0)                            \
-                             : "r" (__scnum));                         \
-       __syscall_return(type, __sc0);                                  \
-}
-
-#undef _syscall1
-#define _syscall1(type,name,type1,arg1)                                                \
-type name(type1 arg1)                                                          \
-{                                                                              \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);         \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;    \
-       __asm__ __volatile__ ("tira gr0,#0"                                     \
-                             : "+r" (__sc0)                                    \
-                             : "r" (__scnum));                                 \
-       __syscall_return(type, __sc0);                                          \
-}
-
-#undef _syscall2
-#define _syscall2(type,name,type1,arg1,type2,arg2)                             \
-type name(type1 arg1,type2 arg2)                                               \
-{                                                                              \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);         \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;    \
-       register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;    \
-       __asm__ __volatile__ ("tira gr0,#0"                                     \
-                             : "+r" (__sc0)                                    \
-                             : "r" (__scnum), "r" (__sc1));                    \
-       __syscall_return(type, __sc0);                                          \
-}
-
-#undef _syscall3
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)                  \
-type name(type1 arg1,type2 arg2,type3 arg3)                                    \
-{                                                                              \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);         \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;    \
-       register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;    \
-       register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;   \
-       __asm__ __volatile__ ("tira gr0,#0"                                     \
-                             : "+r" (__sc0)                                    \
-                             : "r" (__scnum), "r" (__sc1), "r" (__sc2));       \
-       __syscall_return(type, __sc0);                                          \
-}
-
-#undef _syscall4
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)               \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4)                             \
-{                                                                                      \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);                 \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;            \
-       register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;            \
-       register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;           \
-       register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;           \
-       __asm__ __volatile__ ("tira gr0,#0"                                             \
-                             : "+r" (__sc0)                                            \
-                             : "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3));  \
-       __syscall_return(type, __sc0);                                                  \
-}
-
-#undef _syscall5
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)    \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)                 \
-{                                                                                      \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);                 \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;            \
-       register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;            \
-       register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;           \
-       register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;           \
-       register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;           \
-       __asm__ __volatile__ ("tira gr0,#0"                                             \
-                             : "+r" (__sc0)                                            \
-                             : "r" (__scnum), "r" (__sc1), "r" (__sc2),                \
-                             "r" (__sc3), "r" (__sc4));                                \
-       __syscall_return(type, __sc0);                                                  \
-}
-
-#undef _syscall6
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)              \
-{                                                                                               \
-       register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);                          \
-       register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;                     \
-       register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;                     \
-       register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;                    \
-       register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;                    \
-       register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;                    \
-       register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6;                    \
-       __asm__ __volatile__ ("tira gr0,#0"                                                      \
-                             : "+r" (__sc0)                                                     \
-                             : "r" (__scnum), "r" (__sc1), "r" (__sc2),                         \
-                             "r" (__sc3), "r" (__sc4), "r" (__sc5));                            \
-       __syscall_return(type, __sc0);                                                           \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
index 3c06be3..fa14f8c 100644 (file)
@@ -1,4 +1,3 @@
-header-y += atomic.h
 header-y += errno-base.h
 header-y += errno.h
 header-y += fcntl.h
index a84c3d8..a37e95f 100644 (file)
@@ -14,6 +14,7 @@ unifdef-y += posix_types.h
 unifdef-y += ptrace.h
 unifdef-y += resource.h
 unifdef-y += sembuf.h
+unifdef-y += setup.h
 unifdef-y += shmbuf.h
 unifdef-y += sigcontext.h
 unifdef-y += siginfo.h
index 42a95d9..b7e4a04 100644 (file)
@@ -66,7 +66,7 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
        atomic64_sub(i, v);
 }
 
-#else
+#else  /*  BITS_PER_LONG == 64  */
 
 typedef atomic_t atomic_long_t;
 
@@ -113,5 +113,6 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
        atomic_sub(i, v);
 }
 
-#endif
-#endif
+#endif  /*  BITS_PER_LONG == 64  */
+
+#endif  /*  _ASM_GENERIC_ATOMIC_H  */
index c92ae0f..a06eecd 100644 (file)
@@ -4,6 +4,22 @@
 #include <linux/compiler.h>
 
 #ifdef CONFIG_BUG
+
+#ifdef CONFIG_GENERIC_BUG
+#ifndef __ASSEMBLY__
+struct bug_entry {
+       unsigned long   bug_addr;
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+       const char      *file;
+       unsigned short  line;
+#endif
+       unsigned short  flags;
+};
+#endif         /* __ASSEMBLY__ */
+
+#define BUGFLAG_WARNING        (1<<0)
+#endif /* CONFIG_GENERIC_BUG */
+
 #ifndef HAVE_ARCH_BUG
 #define BUG() do { \
        printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
@@ -19,7 +35,7 @@
 #define WARN_ON(condition) ({                                          \
        typeof(condition) __ret_warn_on = (condition);                  \
        if (unlikely(__ret_warn_on)) {                                  \
-               printk("BUG: warning at %s:%d/%s()\n", __FILE__,        \
+               printk("WARNING at %s:%d %s()\n", __FILE__,     \
                        __LINE__, __FUNCTION__);                        \
                dump_stack();                                           \
        }                                                               \
index b541e48..783ab99 100644 (file)
@@ -266,7 +266,7 @@ dma_error(dma_addr_t dma_addr)
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline int
 dma_get_cache_alignment(void)
@@ -295,7 +295,7 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 }
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        /* could define this in terms of the dma_cache ... operations,
index df893c1..f422df0 100644 (file)
@@ -21,7 +21,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -33,7 +33,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index a96b5d9..b55052c 100644 (file)
@@ -4,21 +4,51 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/compiler.h>
+#include <linux/log2.h>
 
-/* Pure 2^n version of get_order */
-static __inline__ __attribute_const__ int get_order(unsigned long size)
+/*
+ * non-const pure 2^n version of get_order
+ * - the arch may override these in asm/bitops.h if they can be implemented
+ *   more efficiently than using the arch log2 routines
+ * - we use the non-const log2() instead if the arch has defined one suitable
+ */
+#ifndef ARCH_HAS_GET_ORDER
+static inline __attribute__((const))
+int __get_order(unsigned long size, int page_shift)
 {
+#if BITS_PER_LONG == 32 && defined(ARCH_HAS_ILOG2_U32)
+       int order = __ilog2_u32(size) - page_shift;
+       return order >= 0 ? order : 0;
+#elif BITS_PER_LONG == 64 && defined(ARCH_HAS_ILOG2_U64)
+       int order = __ilog2_u64(size) - page_shift;
+       return order >= 0 ? order : 0;
+#else
        int order;
 
-       size = (size - 1) >> (PAGE_SHIFT - 1);
+       size = (size - 1) >> (page_shift - 1);
        order = -1;
        do {
                size >>= 1;
                order++;
        } while (size);
        return order;
+#endif
 }
+#endif
+
+/**
+ * get_order - calculate log2(pages) to hold a block of the specified size
+ * @n - size
+ *
+ * calculate allocation order based on the current page size
+ * - this can be used to initialise global variables from constant data
+ */
+#define get_order(n)                                                   \
+(                                                                      \
+       __builtin_constant_p(n) ?                                       \
+       ((n < (1UL << PAGE_SHIFT)) ? 0 : ilog2(n) - PAGE_SHIFT) :       \
+       __get_order(n, PAGE_SHIFT)                                      \
+ )
 
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
index 1e58ca3..3769e6b 100644 (file)
@@ -11,7 +11,7 @@
 /*
  * Translate a "termio" structure into a "termios". Ugh.
  */
-static inline int user_termio_to_kernel_termios(struct termios *termios,
+static inline int user_termio_to_kernel_termios(struct ktermios *termios,
                                                struct termio __user *termio)
 {
        unsigned short tmp;
@@ -48,7 +48,7 @@ static inline int user_termio_to_kernel_termios(struct termios *termios,
  * Translate a "termios" structure into a "termio". Ugh.
  */
 static inline int kernel_termios_to_user_termio(struct termio __user *termio,
-                                               struct termios *termios)
+                                               struct ktermios *termios)
 {
        if (put_user(termios->c_iflag, &termio->c_iflag) < 0 ||
            put_user(termios->c_oflag, &termio->c_oflag) < 0 ||
index e60d6f2..7437cca 100644 (file)
@@ -11,8 +11,8 @@
 
 #define RODATA                                                         \
        . = ALIGN(4096);                                                \
-       __start_rodata = .;                                             \
        .rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {           \
+               VMLINUX_SYMBOL(__start_rodata) = .;                     \
                *(.rodata) *(.rodata.*)                                 \
                *(__vermagic)           /* Kernel version magic */      \
        }                                                               \
                *(__ksymtab_strings)                                    \
        }                                                               \
                                                                        \
+       EH_FRAME                                                        \
+                                                                       \
        /* Built-in module parameters. */                               \
        __param : AT(ADDR(__param) - LOAD_OFFSET) {                     \
                VMLINUX_SYMBOL(__start___param) = .;                    \
                *(__param)                                              \
                VMLINUX_SYMBOL(__stop___param) = .;                     \
+               VMLINUX_SYMBOL(__end_rodata) = .;                       \
        }                                                               \
                                                                        \
-       /* Unwind data binary search table */                           \
-       EH_FRAME_HDR                                                    \
-                                                                       \
-       __end_rodata = .;                                               \
        . = ALIGN(4096);
 
 #define SECURITY_INIT                                                  \
                VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #ifdef CONFIG_STACK_UNWIND
-               /* Unwind data binary search table */
-#define EH_FRAME_HDR                                                   \
+#define EH_FRAME                                                       \
+               /* Unwind data binary search table */                   \
+               . = ALIGN(8);                                           \
                .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
                        VMLINUX_SYMBOL(__start_unwind_hdr) = .;         \
                        *(.eh_frame_hdr)                                \
                        VMLINUX_SYMBOL(__end_unwind_hdr) = .;           \
+               }                                                       \
+               /* Unwind data */                                       \
+               . = ALIGN(8);                                           \
+               .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {         \
+                       VMLINUX_SYMBOL(__start_unwind) = .;             \
+                       *(.eh_frame)                                    \
+                       VMLINUX_SYMBOL(__end_unwind) = .;               \
                }
 #else
-#define EH_FRAME_HDR
+#define EH_FRAME
 #endif
 
                /* DWARF debug sections.
                .stab.indexstr 0 : { *(.stab.indexstr) }                \
                .comment 0 : { *(.comment) }
 
+#define BUG_TABLE                                                      \
+       . = ALIGN(8);                                                   \
+       __bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) {             \
+               __start___bug_table = .;                                \
+               *(__bug_table)                                          \
+               __stop___bug_table = .;                                 \
+       }
+
 #define NOTES                                                          \
                .notes : { *(.note.*) } :note
 
        *(.initcall4s.init)                                             \
        *(.initcall5.init)                                              \
        *(.initcall5s.init)                                             \
+       *(.initcallrootfs.init)                                         \
        *(.initcall6.init)                                              \
        *(.initcall6s.init)                                             \
        *(.initcall7.init)                                              \
index cbccbbd..743beba 100644 (file)
@@ -9,7 +9,7 @@
  * Delay routines, using a pre-computed "loops_per_second" value.
  */
 
-extern __inline__ void __delay(unsigned long loops)
+static inline void __delay(unsigned long loops)
 {
        __asm__ __volatile__ ("1:\n\t"
                              "dec.l #1,%0\n\t"
@@ -27,7 +27,7 @@ extern __inline__ void __delay(unsigned long loops)
 
 extern unsigned long loops_per_jiffy;
 
-extern __inline__ void udelay(unsigned long usecs)
+static inline void udelay(unsigned long usecs)
 {
        usecs *= 4295;          /* 2**32 / 1000000 */
        usecs /= (loops_per_jiffy*HZ);
index 855721a..5c165f7 100644 (file)
@@ -9,7 +9,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
-extern inline int
+static inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
        // mm->context = virt_to_phys(mm->pgd);
@@ -23,7 +23,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
 {
 }
 
-extern inline void activate_mm(struct mm_struct *prev_mm,
+static inline void activate_mm(struct mm_struct *prev_mm,
                               struct mm_struct *next_mm)
 {
 }
index 5edad5b..0c771b0 100644 (file)
 #define pcibios_assign_all_busses()    0
 #define pcibios_scan_all_fns(a, b)     0
 
-extern inline void pcibios_set_master(struct pci_dev *dev)
+static inline void pcibios_set_master(struct pci_dev *dev)
 {
        /* No special bus mastering setup handling */
 }
 
-extern inline void pcibios_penalize_isa_irq(int irq, int active)
+static inline void pcibios_penalize_isa_irq(int irq, int active)
 {
        /* We don't do dynamic PCI IRQ allocation */
 }
index fa69ae0..6a1f4d3 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index bbdffbe..9a2c5c9 100644 (file)
@@ -47,12 +47,12 @@ static inline void flush_tlb_range(struct mm_struct *mm,
        BUG();
 }
 
-extern inline void flush_tlb_kernel_page(unsigned long addr)
+static inline void flush_tlb_kernel_page(unsigned long addr)
 {
        BUG();
 }
 
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
                                      unsigned long start, unsigned long end)
 {
        BUG();
index 747788d..7ddd414 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 289
-#include <linux/err.h>
-
-/* 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)(-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); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-#define _syscall0(type, name)                          \
-type name(void)                                                \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name)             \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall1(type, name, atype, a)                        \
-type name(atype a)                                     \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  _a = (long)a;                                                \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall2(type, name, atype, a, btype, b)      \
-type name(atype a, btype b)                            \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  register long _b __asm__("er2");                     \
-  _a = (long)a;                                                \
-  _b = (long)b;                                                \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a),                     \
-                         "g" (_b)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall3(type, name, atype, a, btype, b, ctype, c)    \
-type name(atype a, btype b, ctype c)                   \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  register long _b __asm__("er2");                     \
-  register long _c __asm__("er3");                     \
-  _a = (long)a;                                                \
-  _b = (long)b;                                                \
-  _c = (long)c;                                                \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a),                     \
-                         "g" (_b),                     \
-                         "g" (_c)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall4(type, name, atype, a, btype, b,      \
-                  ctype, c, dtype, d)                  \
-type name(atype a, btype b, ctype c, dtype d)          \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  register long _b __asm__("er2");                     \
-  register long _c __asm__("er3");                     \
-  register long _d __asm__("er4");                     \
-  _a = (long)a;                                                \
-  _b = (long)b;                                                \
-  _c = (long)c;                                                \
-  _d = (long)d;                                                \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a),                     \
-                         "g" (_b),                     \
-                         "g" (_c),                     \
-                         "g" (_d)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall5(type, name, atype, a, btype, b,      \
-                  ctype, c, dtype, d, etype, e)                \
-type name(atype a, btype b, ctype c, dtype d, etype e) \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  register long _b __asm__("er2");                     \
-  register long _c __asm__("er3");                     \
-  register long _d __asm__("er4");                     \
-  register long _e __asm__("er5");                     \
-  _a = (long)a;                                        \
-  _b = (long)b;                                        \
-  _c = (long)c;                                        \
-  _d = (long)d;                                        \
-  _e = (long)e;                                        \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a),                     \
-                         "g" (_b),                     \
-                         "g" (_c),                     \
-                         "g" (_d),                     \
-                         "g" (_e)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
-
-#define _syscall6(type, name, atype, a, btype, b,      \
-                  ctype, c, dtype, d, etype, e, ftype, f)      \
-type name(atype a, btype b, ctype c, dtype d, etype e, ftype f)        \
-{                                                      \
-  register long __res __asm__("er0");                  \
-  register long _a __asm__("er1");                     \
-  register long _b __asm__("er2");                     \
-  register long _c __asm__("er3");                     \
-  register long _d __asm__("er4");                     \
-  register long _e __asm__("er5");                     \
-  register long _f __asm__("er6");                     \
-  _a = (long)a;                                        \
-  _b = (long)b;                                        \
-  _c = (long)c;                                        \
-  _d = (long)d;                                        \
-  _e = (long)e;                                        \
-  _f = (long)f;                                        \
-  __asm__ __volatile__ ("mov.l %1,er0\n\t"             \
-                        "trapa #0\n\t"                 \
-                       : "=r" (__res)                  \
-                       : "g" (__NR_##name),            \
-                         "g" (_a),                     \
-                         "g" (_b),                     \
-                         "g" (_c),                     \
-                         "g" (_d),                     \
-                         "g" (_e)                      \
-                         "g" (_f)                      \
-                       : "cc", "memory");              \
-  __syscall_return(type, __res);                       \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 147e4ac..5ae93af 100644 (file)
@@ -7,5 +7,4 @@ header-y += ptrace-abi.h
 header-y += ucontext.h
 
 unifdef-y += mtrr.h
-unifdef-y += setup.h
 unifdef-y += vm86.h
index b01a7ec..b8fa955 100644 (file)
@@ -4,7 +4,7 @@
 #ifdef __KERNEL__
 
 #include <asm/types.h>
-
+#include <linux/stddef.h>
 #include <linux/types.h>
 
 struct alt_instr {
@@ -118,4 +118,15 @@ static inline void alternatives_smp_switch(int smp) {}
 #define LOCK_PREFIX ""
 #endif
 
+struct paravirt_patch;
+#ifdef CONFIG_PARAVIRT
+void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
+#else
+static inline void
+apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
+{}
+#define __start_parainstructions NULL
+#define __stop_parainstructions NULL
+#endif
+
 #endif /* _I386_ALTERNATIVE_H */
index b952957..41a4431 100644 (file)
@@ -37,18 +37,27 @@ extern void generic_apic_probe(void);
 /*
  * Basic functions accessing APICs.
  */
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define apic_write native_apic_write
+#define apic_write_atomic native_apic_write_atomic
+#define apic_read native_apic_read
+#endif
 
-static __inline void apic_write(unsigned long reg, unsigned long v)
+static __inline fastcall void native_apic_write(unsigned long reg,
+                                               unsigned long v)
 {
        *((volatile unsigned long *)(APIC_BASE+reg)) = v;
 }
 
-static __inline void apic_write_atomic(unsigned long reg, unsigned long v)
+static __inline fastcall void native_apic_write_atomic(unsigned long reg,
+                                                      unsigned long v)
 {
        xchg((volatile unsigned long *)(APIC_BASE+reg), v);
 }
 
-static __inline unsigned long apic_read(unsigned long reg)
+static __inline fastcall unsigned long native_apic_read(unsigned long reg)
 {
        return *((volatile unsigned long *)(APIC_BASE+reg));
 }
index 51a1662..c57441b 100644 (file)
@@ -14,7 +14,7 @@
  * on us. We need to use _exactly_ the address the user gave us,
  * not some alias that contains the same information.
  */
-typedef struct { volatile int counter; } atomic_t;
+typedef struct { int counter; } atomic_t;
 
 #define ATOMIC_INIT(i) { (i) }
 
@@ -187,9 +187,9 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
        /* Modern 486+ processor */
        __i = i;
        __asm__ __volatile__(
-               LOCK_PREFIX "xaddl %0, %1;"
-               :"=r"(i)
-               :"m"(v->counter), "0"(i));
+               LOCK_PREFIX "xaddl %0, %1"
+               :"+r" (i), "+m" (v->counter)
+               : : "memory");
        return i + __i;
 
 #ifdef CONFIG_M386
index 96b228e..8ce79a6 100644 (file)
@@ -12,4 +12,8 @@
 #define EXTENDED_VGA   0xfffe          /* 80x50 mode */
 #define ASK_VGA                0xfffd          /* ask for it at bootup */
 
-#endif
+/* Physical address where kenrel should be loaded. */
+#define LOAD_PHYSICAL_ADDR ((0x100000 + CONFIG_PHYSICAL_ALIGN - 1) \
+                               & ~(CONFIG_PHYSICAL_ALIGN - 1))
+
+#endif /* _LINUX_BOOT_H */
index 8062cdb..b0fd78c 100644 (file)
@@ -4,20 +4,32 @@
 
 /*
  * Tell the user there is some problem.
- * The offending file and line are encoded after the "officially
- * undefined" opcode for parsing in the trap handler.
+ * The offending file and line are encoded encoded in the __bug_table section.
  */
 
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
+
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-#define BUG()                          \
- __asm__ __volatile__( "ud2\n"         \
-                       "\t.word %c0\n" \
-                       "\t.long %c1\n" \
-                        : : "i" (__LINE__), "i" (__FILE__))
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile("1:\tud2\n"                                \
+                            ".pushsection __bug_table,\"a\"\n"         \
+                            "2:\t.long 1b, %c0\n"                      \
+                            "\t.word %c1, 0\n"                         \
+                            "\t.org 2b+%c2\n"                          \
+                            ".popsection"                              \
+                            : : "i" (__FILE__), "i" (__LINE__),        \
+                            "i" (sizeof(struct bug_entry)));           \
+               for(;;) ;                                               \
+       } while(0)
+
 #else
-#define BUG() __asm__ __volatile__("ud2\n")
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile("ud2");                                    \
+               for(;;) ;                                               \
+       } while(0)
 #endif
 #endif
 
index 592ffee..38f1aeb 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/msr.h>
+#include <asm/paravirt.h>
 
 static int __init no_halt(char *s)
 {
@@ -91,6 +92,9 @@ static void __init check_fpu(void)
 
 static void __init check_hlt(void)
 {
+       if (paravirt_enabled())
+               return;
+
        printk(KERN_INFO "Checking 'hlt' instruction... ");
        if (!boot_cpu_data.hlt_works_ok) {
                printk("disabled\n");
index b1bc7b1..9d914e1 100644 (file)
@@ -13,6 +13,9 @@ struct i386_cpu {
 extern int arch_register_cpu(int num);
 #ifdef CONFIG_HOTPLUG_CPU
 extern void arch_unregister_cpu(int);
+extern int enable_cpu_hotplug;
+#else
+#define enable_cpu_hotplug     0
 #endif
 
 DECLARE_PER_CPU(int, cpu_state);
index d314ebb..3f92b94 100644 (file)
@@ -31,7 +31,7 @@
 #define X86_FEATURE_PSE36      (0*32+17) /* 36-bit PSEs */
 #define X86_FEATURE_PN         (0*32+18) /* Processor serial number */
 #define X86_FEATURE_CLFLSH     (0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DTES       (0*32+21) /* Debug Trace Store */
+#define X86_FEATURE_DS         (0*32+21) /* Debug Store */
 #define X86_FEATURE_ACPI       (0*32+22) /* ACPI via MSR */
 #define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
 #define X86_FEATURE_FXSR       (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
@@ -73,6 +73,8 @@
 #define X86_FEATURE_UP         (3*32+ 9) /* smp kernel running on up */
 #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS       (3*32+12)  /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS                (3*32+13)  /* Branch Trace Store */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define cpu_has_phe_enabled    boot_cpu_has(X86_FEATURE_PHE_EN)
 #define cpu_has_pmm            boot_cpu_has(X86_FEATURE_PMM)
 #define cpu_has_pmm_enabled    boot_cpu_has(X86_FEATURE_PMM_EN)
+#define cpu_has_ds             boot_cpu_has(X86_FEATURE_DS)
+#define cpu_has_pebs           boot_cpu_has(X86_FEATURE_PEBS)
+#define cpu_has_clflush                boot_cpu_has(X86_FEATURE_CLFLSH)
+#define cpu_has_bts            boot_cpu_has(X86_FEATURE_BTS)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
index 3cbbecd..5252ee0 100644 (file)
@@ -1,13 +1,14 @@
 #ifndef _I386_CURRENT_H
 #define _I386_CURRENT_H
 
-#include <linux/thread_info.h>
+#include <asm/pda.h>
+#include <linux/compiler.h>
 
 struct task_struct;
 
-static __always_inline struct task_struct * get_current(void)
+static __always_inline struct task_struct *get_current(void)
 {
-       return current_thread_info()->task;
+       return read_pda(pcurrent);
 }
  
 #define current get_current()
index b1c7650..32d6678 100644 (file)
@@ -7,6 +7,7 @@
  * Delay routines calling functions in arch/i386/lib/delay.c
  */
  
+/* Undefined functions to get compile-time errors */
 extern void __bad_udelay(void);
 extern void __bad_ndelay(void);
 
@@ -15,13 +16,23 @@ extern void __ndelay(unsigned long nsecs);
 extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
+#if defined(CONFIG_PARAVIRT) && !defined(USE_REAL_TIME_DELAY)
+#define udelay(n) paravirt_ops.const_udelay((n) * 0x10c7ul)
+
+#define ndelay(n) paravirt_ops.const_udelay((n) * 5ul)
+
+#else /* !PARAVIRT || USE_REAL_TIME_DELAY */
+
+/* 0x10c7 is 2**32 / 1000000 (rounded up) */
 #define udelay(n) (__builtin_constant_p(n) ? \
        ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
        __udelay(n))
-       
+
+/* 0x5 is 2**32 / 1000000000 (rounded up) */
 #define ndelay(n) (__builtin_constant_p(n) ? \
        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
        __ndelay(n))
+#endif
 
 void use_tsc_delay(void);
 
index 5874ef1..f398cc4 100644 (file)
@@ -4,8 +4,6 @@
 #include <asm/ldt.h>
 #include <asm/segment.h>
 
-#define CPU_16BIT_STACK_SIZE 1024
-
 #ifndef __ASSEMBLY__
 
 #include <linux/preempt.h>
@@ -16,8 +14,6 @@
 
 extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
 
-DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
-
 struct Xgt_desc_struct {
        unsigned short size;
        unsigned long address __attribute__((packed));
@@ -33,11 +29,6 @@ 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);
 
@@ -64,8 +55,10 @@ static inline void pack_gate(__u32 *a, __u32 *b,
 #define DESCTYPE_DPL3  0x60    /* DPL-3 */
 #define DESCTYPE_S     0x10    /* !system */
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #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))
@@ -88,6 +81,10 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 #undef C
 }
 
+#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 write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
 {
        __u32 *lp = (__u32 *)((char *)dt + entry*8);
@@ -95,9 +92,25 @@ static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entr
        *(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)
+#define set_ldt native_set_ldt
+#endif /* CONFIG_PARAVIRT */
+
+static inline fastcall void native_set_ldt(const void *addr,
+                                          unsigned int entries)
+{
+       if (likely(entries == 0))
+               __asm__ __volatile__("lldt %w0"::"q" (0));
+       else {
+               unsigned cpu = smp_processor_id();
+               __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);
+               __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+       }
+}
 
 static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
 {
@@ -115,14 +128,6 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo
        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)
 
@@ -153,35 +158,22 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entri
 
 static inline void clear_LDT(void)
 {
-       int cpu = get_cpu();
-
-       set_ldt_desc(cpu, &default_ldt[0], 5);
-       load_LDT_desc();
-       put_cpu();
+       set_ldt(NULL, 0);
 }
 
 /*
  * load one particular LDT into the current CPU
  */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
+static inline void load_LDT_nolock(mm_context_t *pc)
 {
-       void *segments = pc->ldt;
-       int count = pc->size;
-
-       if (likely(!count)) {
-               segments = &default_ldt[0];
-               count = 5;
-       }
-               
-       set_ldt_desc(cpu, segments, count);
-       load_LDT_desc();
+       set_ldt(pc->ldt, pc->size);
 }
 
 static inline void load_LDT(mm_context_t *pc)
 {
-       int cpu = get_cpu();
-       load_LDT_nolock(pc, cpu);
-       put_cpu();
+       preempt_disable();
+       load_LDT_nolock(pc);
+       preempt_enable();
 }
 
 static inline unsigned long get_desc_base(unsigned long *desc)
@@ -193,6 +185,29 @@ static inline unsigned long get_desc_base(unsigned long *desc)
        return base;
 }
 
+#else /* __ASSEMBLY__ */
+
+/*
+ * GET_DESC_BASE reads the descriptor base of the specified segment.
+ *
+ * Args:
+ *    idx - descriptor index
+ *    gdt - GDT pointer
+ *    base - 32bit register to which the base will be written
+ *    lo_w - lo word of the "base" register
+ *    lo_b - lo byte of the "base" register
+ *    hi_b - hi byte of the low word of the "base" register
+ *
+ * Example:
+ *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+ *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+       movb idx*8+4(gdt), lo_b; \
+       movb idx*8+7(gdt), hi_b; \
+       shll $16, base; \
+       movw idx*8+2(gdt), lo_w;
+
 #endif /* !__ASSEMBLY__ */
 
 #endif
index 81999a3..183eebe 100644 (file)
@@ -156,10 +156,10 @@ dma_get_cache_alignment(void)
        return (1 << INTERNODE_CACHE_SHIFT);
 }
 
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        flush_write_buffers();
index f7514fb..395077a 100644 (file)
@@ -38,6 +38,11 @@ extern struct e820map e820;
 
 extern int e820_all_mapped(unsigned long start, unsigned long end,
                           unsigned type);
+extern void find_max_pfn(void);
+extern void register_bootmem_low_pages(unsigned long max_low_pfn);
+extern void register_memory(void);
+extern void limit_regions(unsigned long long size);
+extern void print_memory_map(char *who);
 
 #endif/*!__ASSEMBLY__*/
 
index 3a05436..45d21a0 100644 (file)
@@ -91,7 +91,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
        pr_reg[7] = regs->xds;                          \
        pr_reg[8] = regs->xes;                          \
        savesegment(fs,pr_reg[9]);                      \
-       savesegment(gs,pr_reg[10]);                     \
+       pr_reg[10] = regs->xgs;                         \
        pr_reg[11] = regs->orig_eax;                    \
        pr_reg[12] = regs->eip;                         \
        pr_reg[13] = regs->xcs;                         \
index 946d97c..438ef0e 100644 (file)
@@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        if (op == FUTEX_OP_SET)
                __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
@@ -88,7 +88,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                }
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index 8ffbb0f..fd2be59 100644 (file)
@@ -122,6 +122,6 @@ struct genapic {
        APICFUNC(phys_pkg_id) \
        }
 
-extern struct genapic *genapic;
+extern struct genapic *genapic, apic_default;
 
 #endif
index bc1d6ed..434936c 100644 (file)
@@ -76,7 +76,9 @@ static inline void __save_init_fpu( struct task_struct *tsk )
 
 #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)
 
 #define __clear_fpu( tsk )                                     \
@@ -118,6 +120,7 @@ static inline void save_init_fpu( struct task_struct *tsk )
 extern unsigned short get_fpu_cwd( struct task_struct *tsk );
 extern unsigned short get_fpu_swd( struct task_struct *tsk );
 extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
+extern asmlinkage void math_state_restore(void);
 
 /*
  * Signal frame handlers...
index 73465d2..0fc240c 100644 (file)
@@ -40,13 +40,14 @@ static __inline__ int ide_default_irq(unsigned long base)
 
 static __inline__ unsigned long ide_default_io_base(int index)
 {
+       struct pci_dev *pdev;
        /*
         *      If PCI is present then it is not safe to poke around
         *      the other legacy IDE ports. Only 0x1f0 and 0x170 are
         *      defined compatibility mode ports for PCI. A user can 
         *      override this using ide= but we must default safe.
         */
-       if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) == NULL) {
+       if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) {
                switch(index) {
                        case 2: return 0x1e8;
                        case 3: return 0x168;
@@ -54,6 +55,7 @@ static __inline__ unsigned long ide_default_io_base(int index)
                        case 5: return 0x160;
                }
        }
+       pci_dev_put(pdev);
        switch (index) {
                case 0: return 0x1f0;
                case 1: return 0x170;
index 68df0dc..86ff5e8 100644 (file)
@@ -256,11 +256,11 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:"
+#if defined(CONFIG_PARAVIRT)
+#include <asm/paravirt.h>
 #else
+
 #define __SLOW_DOWN_IO "outb %%al,$0x80;"
-#endif
 
 static inline void slow_down_io(void) {
        __asm__ __volatile__(
@@ -271,6 +271,8 @@ static inline void slow_down_io(void) {
                : : );
 }
 
+#endif
+
 #ifdef CONFIG_X86_NUMAQ
 extern void *xquad_portio;    /* Where the IO area was mapped */
 #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
index 331726b..11761cd 100644 (file)
@@ -37,8 +37,13 @@ static __inline__ int irq_canonicalize(int irq)
 extern int irqbalance_disable(char *str);
 #endif
 
+extern void quirk_intel_irqbalance(void);
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void fixup_irqs(cpumask_t map);
 #endif
 
+void init_IRQ(void);
+void __init native_init_IRQ(void);
+
 #endif /* _ASM_IRQ_H */
index 3dd9c0b..a1b3f7f 100644 (file)
@@ -1 +1,27 @@
-#include <asm-generic/irq_regs.h>
+/*
+ * Per-cpu current frame pointer - the location of the last exception frame on
+ * the stack, stored in the PDA.
+ *
+ * Jeremy Fitzhardinge <jeremy@goop.org>
+ */
+#ifndef _ASM_I386_IRQ_REGS_H
+#define _ASM_I386_IRQ_REGS_H
+
+#include <asm/pda.h>
+
+static inline struct pt_regs *get_irq_regs(void)
+{
+       return read_pda(irq_regs);
+}
+
+static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
+{
+       struct pt_regs *old_regs;
+
+       old_regs = read_pda(irq_regs);
+       write_pda(irq_regs, new_regs);
+
+       return old_regs;
+}
+
+#endif /* _ASM_I386_IRQ_REGS_H */
index e1bdb97..17b18cf 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #ifndef __ASSEMBLY__
 
 static inline unsigned long __raw_local_save_flags(void)
@@ -25,9 +28,6 @@ static inline unsigned long __raw_local_save_flags(void)
        return flags;
 }
 
-#define raw_local_save_flags(flags) \
-               do { (flags) = __raw_local_save_flags(); } while (0)
-
 static inline void raw_local_irq_restore(unsigned long flags)
 {
        __asm__ __volatile__(
@@ -66,18 +66,6 @@ static inline void halt(void)
        __asm__ __volatile__("hlt": : :"memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
-{
-       return !(flags & (1 << 9));
-}
-
-static inline int raw_irqs_disabled(void)
-{
-       unsigned long flags = __raw_local_save_flags();
-
-       return raw_irqs_disabled_flags(flags);
-}
-
 /*
  * For spinlocks, etc:
  */
@@ -90,9 +78,33 @@ static inline unsigned long __raw_local_irq_save(void)
        return flags;
 }
 
+#else
+#define DISABLE_INTERRUPTS(clobbers)   cli
+#define ENABLE_INTERRUPTS(clobbers)    sti
+#define ENABLE_INTERRUPTS_SYSEXIT      sti; sysexit
+#define INTERRUPT_RETURN               iret
+#define GET_CR0_INTO_EAX               movl %cr0, %eax
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_PARAVIRT */
+
+#ifndef __ASSEMBLY__
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
 #define raw_local_irq_save(flags) \
                do { (flags) = __raw_local_irq_save(); } while (0)
 
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1 << 9));
+}
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
 #endif /* __ASSEMBLY__ */
 
 /*
index fb42099..605e3cc 100644 (file)
@@ -2,4 +2,6 @@
 
 /* no action for generic */
 
+#ifndef ARCH_SETUP
 #define ARCH_SETUP
+#endif
index 697673b..a4b0aa3 100644 (file)
@@ -21,6 +21,7 @@ struct info {
        long ___eax;
        long ___ds;
        long ___es;
+       long ___fs;
        long ___orig_eax;
        long ___eip;
        long ___cs;
index 62b7bf1..68ff102 100644 (file)
@@ -44,7 +44,7 @@ static inline void switch_mm(struct mm_struct *prev,
                 * load the LDT, if the LDT is different:
                 */
                if (unlikely(prev->context.ldt != next->context.ldt))
-                       load_LDT_nolock(&next->context, cpu);
+                       load_LDT_nolock(&next->context);
        }
 #ifdef CONFIG_SMP
        else {
@@ -56,14 +56,14 @@ static inline void switch_mm(struct mm_struct *prev,
                         * tlb flush IPI delivery. We must reload %cr3.
                         */
                        load_cr3(next->pgd);
-                       load_LDT_nolock(&next->context, cpu);
+                       load_LDT_nolock(&next->context);
                }
        }
 #endif
 }
 
-#define deactivate_mm(tsk, mm) \
-       asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
+#define deactivate_mm(tsk, mm)                 \
+       asm("movl %0,%%fs": :"r" (0));
 
 #define activate_mm(prev, next) \
        switch_mm((prev),(next),NULL)
index 61b0733..3503ad6 100644 (file)
@@ -120,13 +120,26 @@ static inline int pfn_valid(int pfn)
        __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low_pages(x) \
        __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-#define alloc_bootmem_node(ignore, x) \
-       __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_pages_node(ignore, x) \
-       __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low_pages_node(ignore, x) \
-       __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-
+#define alloc_bootmem_node(pgdat, x)                                   \
+({                                                                     \
+       struct pglist_data  __attribute__ ((unused))                    \
+                               *__alloc_bootmem_node__pgdat = (pgdat); \
+       __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES,        \
+                                               __pa(MAX_DMA_ADDRESS)); \
+})
+#define alloc_bootmem_pages_node(pgdat, x)                             \
+({                                                                     \
+       struct pglist_data  __attribute__ ((unused))                    \
+                               *__alloc_bootmem_node__pgdat = (pgdat); \
+       __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE,              \
+                                               __pa(MAX_DMA_ADDRESS))  \
+})
+#define alloc_bootmem_low_pages_node(pgdat, x)                         \
+({                                                                     \
+       struct pglist_data  __attribute__ ((unused))                    \
+                               *__alloc_bootmem_node__pgdat = (pgdat); \
+       __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0);          \
+})
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
 #endif /* _ASM_MMZONE_H_ */
index 424661d..02f8f54 100644 (file)
@@ -20,6 +20,8 @@ struct mod_arch_specific
 #define MODULE_PROC_FAMILY "586TSC "
 #elif defined CONFIG_M586MMX
 #define MODULE_PROC_FAMILY "586MMX "
+#elif defined CONFIG_MCORE2
+#define MODULE_PROC_FAMILY "CORE2 "
 #elif defined CONFIG_M686
 #define MODULE_PROC_FAMILY "686 "
 #elif defined CONFIG_MPENTIUMII
@@ -60,18 +62,12 @@ struct mod_arch_specific
 #error unknown processor family
 #endif
 
-#ifdef CONFIG_REGPARM
-#define MODULE_REGPARM "REGPARM "
-#else
-#define MODULE_REGPARM ""
-#endif
-
 #ifdef CONFIG_4KSTACKS
 #define MODULE_STACKSIZE "4KSTACKS "
 #else
 #define MODULE_STACKSIZE ""
 #endif
 
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
 
 #endif /* _ASM_I386_MODULE_H */
index 76feedf..13bafb1 100644 (file)
@@ -97,7 +97,6 @@ struct mpc_config_bus
 #define BUSTYPE_TC     "TC"
 #define BUSTYPE_VME    "VME"
 #define BUSTYPE_XPRESS "XPRESS"
-#define BUSTYPE_NEC98  "NEC98"
 
 struct mpc_config_ioapic
 {
@@ -182,7 +181,6 @@ enum mp_bustype {
        MP_BUS_EISA,
        MP_BUS_PCI,
        MP_BUS_MCA,
-       MP_BUS_NEC98
 };
 #endif
 
index 62b76cd..5679d49 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ASM_MSR_H
 #define __ASM_MSR_H
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+
 /*
  * Access to machine-specific registers (available on 586 and better only)
  * Note: the rd* operations modify the parameters directly (without using
@@ -77,6 +81,7 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
      __asm__ __volatile__("rdpmc" \
                          : "=a" (low), "=d" (high) \
                          : "c" (counter))
+#endif /* !CONFIG_PARAVIRT */
 
 /* symbolic names for some interesting MSRs */
 /* Intel defined MSRs. */
@@ -141,6 +146,10 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
 #define MSR_IA32_MC0_ADDR              0x402
 #define MSR_IA32_MC0_MISC              0x403
 
+#define MSR_IA32_PEBS_ENABLE           0x3f1
+#define MSR_IA32_DS_AREA               0x600
+#define MSR_IA32_PERF_CAPABILITIES     0x345
+
 /* Pentium IV performance counter MSRs */
 #define MSR_P4_BPU_PERFCTR0            0x300
 #define MSR_P4_BPU_PERFCTR1            0x301
@@ -284,4 +293,13 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
 #define MSR_TMTA_LRTI_READOUT          0x80868018
 #define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
 
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0       0x309
+#define MSR_CORE_PERF_FIXED_CTR1       0x30a
+#define MSR_CORE_PERF_FIXED_CTR2       0x30b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x38d
+#define MSR_CORE_PERF_GLOBAL_STATUS    0x38e
+#define MSR_CORE_PERF_GLOBAL_CTRL      0x38f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x390
+
 #endif /* __ASM_MSR_H */
index 269d315..b04333e 100644 (file)
@@ -5,6 +5,9 @@
 #define ASM_NMI_H
 
 #include <linux/pm.h>
+#include <asm/irq.h>
+
+#ifdef ARCH_HAS_NMI_WATCHDOG
 
 /**
  * do_nmi_callback
@@ -42,4 +45,9 @@ extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
                        void __user *, size_t *, loff_t *);
 extern int unknown_nmi_panic;
 
+void __trigger_all_cpu_backtrace(void);
+#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+
+#endif
+
 #endif /* ASM_NMI_H */
index f5bf544..fd3f64a 100644 (file)
@@ -52,6 +52,7 @@ typedef struct { unsigned long long pgprot; } pgprot_t;
 #define pte_val(x)     ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
 #define __pmd(x) ((pmd_t) { (x) } )
 #define HPAGE_SHIFT    21
+#include <asm-generic/pgtable-nopud.h>
 #else
 typedef struct { unsigned long pte_low; } pte_t;
 typedef struct { unsigned long pgd; } pgd_t;
@@ -59,6 +60,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define boot_pte_t pte_t /* or would you rather have a typedef */
 #define pte_val(x)     ((x).pte_low)
 #define HPAGE_SHIFT    22
+#include <asm-generic/pgtable-nopmd.h>
 #endif
 #define PTE_MASK       PAGE_MASK
 
@@ -112,18 +114,18 @@ extern int page_is_ram(unsigned long pagenr);
 
 #ifdef __ASSEMBLY__
 #define __PAGE_OFFSET          CONFIG_PAGE_OFFSET
-#define __PHYSICAL_START       CONFIG_PHYSICAL_START
 #else
 #define __PAGE_OFFSET          ((unsigned long)CONFIG_PAGE_OFFSET)
-#define __PHYSICAL_START       ((unsigned long)CONFIG_PHYSICAL_START)
 #endif
-#define __KERNEL_START         (__PAGE_OFFSET + __PHYSICAL_START)
 
 
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE                ((unsigned long)__VMALLOC_RESERVE)
 #define MAXMEM                 (-__PAGE_OFFSET-__VMALLOC_RESERVE)
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
+/* __pa_symbol should be used for C visible symbols.
+   This seems to be the official gcc blessed way to do such arithmetic. */
+#define __pa_symbol(x)          __pa(RELOC_HIDE((unsigned long)(x),0))
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 #ifdef CONFIG_FLATMEM
index 745dc5b..21b3246 100644 (file)
@@ -18,6 +18,5 @@
 #endif
 
 #define MAXHOSTNAMELEN 64      /* max length of hostname */
-#define COMMAND_LINE_SIZE 256
 
 #endif
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
new file mode 100644 (file)
index 0000000..9f06265
--- /dev/null
@@ -0,0 +1,505 @@
+#ifndef __ASM_PARAVIRT_H
+#define __ASM_PARAVIRT_H
+/* Various instructions on x86 need to be replaced for
+ * para-virtualization: those hooks are defined here. */
+#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <asm/page.h>
+
+#ifdef CONFIG_PARAVIRT
+/* These are the most performance critical ops, so we want to be able to patch
+ * callers */
+#define PARAVIRT_IRQ_DISABLE 0
+#define PARAVIRT_IRQ_ENABLE 1
+#define PARAVIRT_RESTORE_FLAGS 2
+#define PARAVIRT_SAVE_FLAGS 3
+#define PARAVIRT_SAVE_FLAGS_IRQ_DISABLE 4
+#define PARAVIRT_INTERRUPT_RETURN 5
+#define PARAVIRT_STI_SYSEXIT 6
+
+/* Bitmask of what can be clobbered: usually at least eax. */
+#define CLBR_NONE 0x0
+#define CLBR_EAX 0x1
+#define CLBR_ECX 0x2
+#define CLBR_EDX 0x4
+#define CLBR_ANY 0x7
+
+#ifndef __ASSEMBLY__
+struct thread_struct;
+struct Xgt_desc_struct;
+struct tss_struct;
+struct mm_struct;
+struct paravirt_ops
+{
+       unsigned int kernel_rpl;
+       int paravirt_enabled;
+       const char *name;
+
+       /*
+        * Patch may replace one of the defined code sequences with arbitrary
+        * code, subject to the same register constraints.  This generally
+        * means the code is not free to clobber any registers other than EAX.
+        * The patch function should return the number of bytes of code
+        * generated, as we nop pad the rest in generic code.
+        */
+       unsigned (*patch)(u8 type, u16 clobber, void *firstinsn, unsigned len);
+
+       void (*arch_setup)(void);
+       char *(*memory_setup)(void);
+       void (*init_IRQ)(void);
+
+       void (*banner)(void);
+
+       unsigned long (*get_wallclock)(void);
+       int (*set_wallclock)(unsigned long);
+       void (*time_init)(void);
+
+       /* All the function pointers here are declared as "fastcall"
+          so that we get a specific register-based calling
+          convention.  This makes it easier to implement inline
+          assembler replacements. */
+
+       void (fastcall *cpuid)(unsigned int *eax, unsigned int *ebx,
+                     unsigned int *ecx, unsigned int *edx);
+
+       unsigned long (fastcall *get_debugreg)(int regno);
+       void (fastcall *set_debugreg)(int regno, unsigned long value);
+
+       void (fastcall *clts)(void);
+
+       unsigned long (fastcall *read_cr0)(void);
+       void (fastcall *write_cr0)(unsigned long);
+
+       unsigned long (fastcall *read_cr2)(void);
+       void (fastcall *write_cr2)(unsigned long);
+
+       unsigned long (fastcall *read_cr3)(void);
+       void (fastcall *write_cr3)(unsigned long);
+
+       unsigned long (fastcall *read_cr4_safe)(void);
+       unsigned long (fastcall *read_cr4)(void);
+       void (fastcall *write_cr4)(unsigned long);
+
+       unsigned long (fastcall *save_fl)(void);
+       void (fastcall *restore_fl)(unsigned long);
+       void (fastcall *irq_disable)(void);
+       void (fastcall *irq_enable)(void);
+       void (fastcall *safe_halt)(void);
+       void (fastcall *halt)(void);
+       void (fastcall *wbinvd)(void);
+
+       /* err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
+       u64 (fastcall *read_msr)(unsigned int msr, int *err);
+       int (fastcall *write_msr)(unsigned int msr, u64 val);
+
+       u64 (fastcall *read_tsc)(void);
+       u64 (fastcall *read_pmc)(void);
+
+       void (fastcall *load_tr_desc)(void);
+       void (fastcall *load_gdt)(const struct Xgt_desc_struct *);
+       void (fastcall *load_idt)(const struct Xgt_desc_struct *);
+       void (fastcall *store_gdt)(struct Xgt_desc_struct *);
+       void (fastcall *store_idt)(struct Xgt_desc_struct *);
+       void (fastcall *set_ldt)(const void *desc, unsigned entries);
+       unsigned long (fastcall *store_tr)(void);
+       void (fastcall *load_tls)(struct thread_struct *t, unsigned int cpu);
+       void (fastcall *write_ldt_entry)(void *dt, int entrynum,
+                                        u32 low, u32 high);
+       void (fastcall *write_gdt_entry)(void *dt, int entrynum,
+                                        u32 low, u32 high);
+       void (fastcall *write_idt_entry)(void *dt, int entrynum,
+                                        u32 low, u32 high);
+       void (fastcall *load_esp0)(struct tss_struct *tss,
+                                  struct thread_struct *thread);
+
+       void (fastcall *set_iopl_mask)(unsigned mask);
+
+       void (fastcall *io_delay)(void);
+       void (*const_udelay)(unsigned long loops);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       void (fastcall *apic_write)(unsigned long reg, unsigned long v);
+       void (fastcall *apic_write_atomic)(unsigned long reg, unsigned long v);
+       unsigned long (fastcall *apic_read)(unsigned long reg);
+#endif
+
+       void (fastcall *flush_tlb_user)(void);
+       void (fastcall *flush_tlb_kernel)(void);
+       void (fastcall *flush_tlb_single)(u32 addr);
+
+       void (fastcall *set_pte)(pte_t *ptep, pte_t pteval);
+       void (fastcall *set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
+       void (fastcall *set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+       void (fastcall *pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+       void (fastcall *pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+#ifdef CONFIG_X86_PAE
+       void (fastcall *set_pte_atomic)(pte_t *ptep, pte_t pteval);
+       void (fastcall *set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
+       void (fastcall *set_pud)(pud_t *pudp, pud_t pudval);
+       void (fastcall *pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+       void (fastcall *pmd_clear)(pmd_t *pmdp);
+#endif
+
+       /* These two are jmp to, not actually called. */
+       void (fastcall *irq_enable_sysexit)(void);
+       void (fastcall *iret)(void);
+};
+
+/* Mark a paravirt probe function. */
+#define paravirt_probe(fn)                                             \
+ static asmlinkage void (*__paravirtprobe_##fn)(void) __attribute_used__ \
+               __attribute__((__section__(".paravirtprobe"))) = fn
+
+extern struct paravirt_ops paravirt_ops;
+
+#define paravirt_enabled() (paravirt_ops.paravirt_enabled)
+
+static inline void load_esp0(struct tss_struct *tss,
+                            struct thread_struct *thread)
+{
+       paravirt_ops.load_esp0(tss, thread);
+}
+
+#define ARCH_SETUP                     paravirt_ops.arch_setup();
+static inline unsigned long get_wallclock(void)
+{
+       return paravirt_ops.get_wallclock();
+}
+
+static inline int set_wallclock(unsigned long nowtime)
+{
+       return paravirt_ops.set_wallclock(nowtime);
+}
+
+static inline void do_time_init(void)
+{
+       return paravirt_ops.time_init();
+}
+
+/* The paravirtualized CPUID instruction. */
+static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+                          unsigned int *ecx, unsigned int *edx)
+{
+       paravirt_ops.cpuid(eax, ebx, ecx, edx);
+}
+
+/*
+ * These special macros can be used to get or set a debugging register
+ */
+#define get_debugreg(var, reg) var = paravirt_ops.get_debugreg(reg)
+#define set_debugreg(val, reg) paravirt_ops.set_debugreg(reg, val)
+
+#define clts() paravirt_ops.clts()
+
+#define read_cr0() paravirt_ops.read_cr0()
+#define write_cr0(x) paravirt_ops.write_cr0(x)
+
+#define read_cr2() paravirt_ops.read_cr2()
+#define write_cr2(x) paravirt_ops.write_cr2(x)
+
+#define read_cr3() paravirt_ops.read_cr3()
+#define write_cr3(x) paravirt_ops.write_cr3(x)
+
+#define read_cr4() paravirt_ops.read_cr4()
+#define read_cr4_safe(x) paravirt_ops.read_cr4_safe()
+#define write_cr4(x) paravirt_ops.write_cr4(x)
+
+static inline void raw_safe_halt(void)
+{
+       paravirt_ops.safe_halt();
+}
+
+static inline void halt(void)
+{
+       paravirt_ops.safe_halt();
+}
+#define wbinvd() paravirt_ops.wbinvd()
+
+#define get_kernel_rpl()  (paravirt_ops.kernel_rpl)
+
+#define rdmsr(msr,val1,val2) do {                              \
+       int _err;                                               \
+       u64 _l = paravirt_ops.read_msr(msr,&_err);              \
+       val1 = (u32)_l;                                         \
+       val2 = _l >> 32;                                        \
+} while(0)
+
+#define wrmsr(msr,val1,val2) do {                              \
+       u64 _l = ((u64)(val2) << 32) | (val1);                  \
+       paravirt_ops.write_msr((msr), _l);                      \
+} while(0)
+
+#define rdmsrl(msr,val) do {                                   \
+       int _err;                                               \
+       val = paravirt_ops.read_msr((msr),&_err);               \
+} while(0)
+
+#define wrmsrl(msr,val) (paravirt_ops.write_msr((msr),(val)))
+#define wrmsr_safe(msr,a,b) ({                                 \
+       u64 _l = ((u64)(b) << 32) | (a);                        \
+       paravirt_ops.write_msr((msr),_l);                       \
+})
+
+/* rdmsr with exception handling */
+#define rdmsr_safe(msr,a,b) ({                                 \
+       int _err;                                               \
+       u64 _l = paravirt_ops.read_msr(msr,&_err);              \
+       (*a) = (u32)_l;                                         \
+       (*b) = _l >> 32;                                        \
+       _err; })
+
+#define rdtsc(low,high) do {                                   \
+       u64 _l = paravirt_ops.read_tsc();                       \
+       low = (u32)_l;                                          \
+       high = _l >> 32;                                        \
+} while(0)
+
+#define rdtscl(low) do {                                       \
+       u64 _l = paravirt_ops.read_tsc();                       \
+       low = (int)_l;                                          \
+} while(0)
+
+#define rdtscll(val) (val = paravirt_ops.read_tsc())
+
+#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
+
+#define rdpmc(counter,low,high) do {                           \
+       u64 _l = paravirt_ops.read_pmc();                       \
+       low = (u32)_l;                                          \
+       high = _l >> 32;                                        \
+} while(0)
+
+#define load_TR_desc() (paravirt_ops.load_tr_desc())
+#define load_gdt(dtr) (paravirt_ops.load_gdt(dtr))
+#define load_idt(dtr) (paravirt_ops.load_idt(dtr))
+#define set_ldt(addr, entries) (paravirt_ops.set_ldt((addr), (entries)))
+#define store_gdt(dtr) (paravirt_ops.store_gdt(dtr))
+#define store_idt(dtr) (paravirt_ops.store_idt(dtr))
+#define store_tr(tr) ((tr) = paravirt_ops.store_tr())
+#define load_TLS(t,cpu) (paravirt_ops.load_tls((t),(cpu)))
+#define write_ldt_entry(dt, entry, low, high)                          \
+       (paravirt_ops.write_ldt_entry((dt), (entry), (low), (high)))
+#define write_gdt_entry(dt, entry, low, high)                          \
+       (paravirt_ops.write_gdt_entry((dt), (entry), (low), (high)))
+#define write_idt_entry(dt, entry, low, high)                          \
+       (paravirt_ops.write_idt_entry((dt), (entry), (low), (high)))
+#define set_iopl_mask(mask) (paravirt_ops.set_iopl_mask(mask))
+
+/* The paravirtualized I/O functions */
+static inline void slow_down_io(void) {
+       paravirt_ops.io_delay();
+#ifdef REALLY_SLOW_IO
+       paravirt_ops.io_delay();
+       paravirt_ops.io_delay();
+       paravirt_ops.io_delay();
+#endif
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+/*
+ * Basic functions accessing APICs.
+ */
+static inline void apic_write(unsigned long reg, unsigned long v)
+{
+       paravirt_ops.apic_write(reg,v);
+}
+
+static inline void apic_write_atomic(unsigned long reg, unsigned long v)
+{
+       paravirt_ops.apic_write_atomic(reg,v);
+}
+
+static inline unsigned long apic_read(unsigned long reg)
+{
+       return paravirt_ops.apic_read(reg);
+}
+#endif
+
+
+#define __flush_tlb() paravirt_ops.flush_tlb_user()
+#define __flush_tlb_global() paravirt_ops.flush_tlb_kernel()
+#define __flush_tlb_single(addr) paravirt_ops.flush_tlb_single(addr)
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+       paravirt_ops.set_pte(ptep, pteval);
+}
+
+static inline void set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
+{
+       paravirt_ops.set_pte_at(mm, addr, ptep, pteval);
+}
+
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+       paravirt_ops.set_pmd(pmdp, pmdval);
+}
+
+static inline void pte_update(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+       paravirt_ops.pte_update(mm, addr, ptep);
+}
+
+static inline void pte_update_defer(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+       paravirt_ops.pte_update_defer(mm, addr, ptep);
+}
+
+#ifdef CONFIG_X86_PAE
+static inline void set_pte_atomic(pte_t *ptep, pte_t pteval)
+{
+       paravirt_ops.set_pte_atomic(ptep, pteval);
+}
+
+static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+       paravirt_ops.set_pte_present(mm, addr, ptep, pte);
+}
+
+static inline void set_pud(pud_t *pudp, pud_t pudval)
+{
+       paravirt_ops.set_pud(pudp, pudval);
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       paravirt_ops.pte_clear(mm, addr, ptep);
+}
+
+static inline void pmd_clear(pmd_t *pmdp)
+{
+       paravirt_ops.pmd_clear(pmdp);
+}
+#endif
+
+/* These all sit in the .parainstructions section to tell us what to patch. */
+struct paravirt_patch {
+       u8 *instr;              /* original instructions */
+       u8 instrtype;           /* type of this instruction */
+       u8 len;                 /* length of original instruction */
+       u16 clobbers;           /* what registers you may clobber */
+};
+
+#define paravirt_alt(insn_string, typenum, clobber)    \
+       "771:\n\t" insn_string "\n" "772:\n"            \
+       ".pushsection .parainstructions,\"a\"\n"        \
+       "  .long 771b\n"                                \
+       "  .byte " __stringify(typenum) "\n"            \
+       "  .byte 772b-771b\n"                           \
+       "  .short " __stringify(clobber) "\n"           \
+       ".popsection"
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long f;
+
+       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
+                                          "call *%1;"
+                                          "popl %%edx; popl %%ecx",
+                                         PARAVIRT_SAVE_FLAGS, CLBR_NONE)
+                            : "=a"(f): "m"(paravirt_ops.save_fl)
+                            : "memory", "cc");
+       return f;
+}
+
+static inline void raw_local_irq_restore(unsigned long f)
+{
+       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
+                                          "call *%1;"
+                                          "popl %%edx; popl %%ecx",
+                                         PARAVIRT_RESTORE_FLAGS, CLBR_EAX)
+                            : "=a"(f) : "m" (paravirt_ops.restore_fl), "0"(f)
+                            : "memory", "cc");
+}
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
+                                          "call *%0;"
+                                          "popl %%edx; popl %%ecx",
+                                         PARAVIRT_IRQ_DISABLE, CLBR_EAX)
+                            : : "m" (paravirt_ops.irq_disable)
+                            : "memory", "eax", "cc");
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
+                                          "call *%0;"
+                                          "popl %%edx; popl %%ecx",
+                                         PARAVIRT_IRQ_ENABLE, CLBR_EAX)
+                            : : "m" (paravirt_ops.irq_enable)
+                            : "memory", "eax", "cc");
+}
+
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long f;
+
+       __asm__ __volatile__(paravirt_alt( "pushl %%ecx; pushl %%edx;"
+                                          "call *%1; pushl %%eax;"
+                                          "call *%2; popl %%eax;"
+                                          "popl %%edx; popl %%ecx",
+                                         PARAVIRT_SAVE_FLAGS_IRQ_DISABLE,
+                                         CLBR_NONE)
+                            : "=a"(f)
+                            : "m" (paravirt_ops.save_fl),
+                              "m" (paravirt_ops.irq_disable)
+                            : "memory", "cc");
+       return f;
+}
+
+#define CLI_STRING paravirt_alt("pushl %%ecx; pushl %%edx;"            \
+                    "call *paravirt_ops+%c[irq_disable];"              \
+                    "popl %%edx; popl %%ecx",                          \
+                    PARAVIRT_IRQ_DISABLE, CLBR_EAX)
+
+#define STI_STRING paravirt_alt("pushl %%ecx; pushl %%edx;"            \
+                    "call *paravirt_ops+%c[irq_enable];"               \
+                    "popl %%edx; popl %%ecx",                          \
+                    PARAVIRT_IRQ_ENABLE, CLBR_EAX)
+#define CLI_STI_CLOBBERS , "%eax"
+#define CLI_STI_INPUT_ARGS \
+       ,                                                               \
+       [irq_disable] "i" (offsetof(struct paravirt_ops, irq_disable)), \
+       [irq_enable] "i" (offsetof(struct paravirt_ops, irq_enable))
+
+#else  /* __ASSEMBLY__ */
+
+#define PARA_PATCH(ptype, clobbers, ops)       \
+771:;                                          \
+       ops;                                    \
+772:;                                          \
+       .pushsection .parainstructions,"a";     \
+        .long 771b;                            \
+        .byte ptype;                           \
+        .byte 772b-771b;                       \
+        .short clobbers;                       \
+       .popsection
+
+#define INTERRUPT_RETURN                               \
+       PARA_PATCH(PARAVIRT_INTERRUPT_RETURN, CLBR_ANY, \
+       jmp *%cs:paravirt_ops+PARAVIRT_iret)
+
+#define DISABLE_INTERRUPTS(clobbers)                   \
+       PARA_PATCH(PARAVIRT_IRQ_DISABLE, clobbers,      \
+       pushl %ecx; pushl %edx;                         \
+       call *paravirt_ops+PARAVIRT_irq_disable;        \
+       popl %edx; popl %ecx)                           \
+
+#define ENABLE_INTERRUPTS(clobbers)                    \
+       PARA_PATCH(PARAVIRT_IRQ_ENABLE, clobbers,       \
+       pushl %ecx; pushl %edx;                         \
+       call *%cs:paravirt_ops+PARAVIRT_irq_enable;     \
+       popl %edx; popl %ecx)
+
+#define ENABLE_INTERRUPTS_SYSEXIT                      \
+       PARA_PATCH(PARAVIRT_STI_SYSEXIT, CLBR_ANY,      \
+       jmp *%cs:paravirt_ops+PARAVIRT_irq_enable_sysexit)
+
+#define GET_CR0_INTO_EAX                       \
+       call *paravirt_ops+PARAVIRT_read_cr0
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_PARAVIRT */
+#endif /* __ASM_PARAVIRT_H */
diff --git a/include/asm-i386/pda.h b/include/asm-i386/pda.h
new file mode 100644 (file)
index 0000000..2ba2736
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+   Per-processor Data Areas
+   Jeremy Fitzhardinge <jeremy@goop.org> 2006
+   Based on asm-x86_64/pda.h by Andi Kleen.
+ */
+#ifndef _I386_PDA_H
+#define _I386_PDA_H
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+
+struct i386_pda
+{
+       struct i386_pda *_pda;          /* pointer to self */
+
+       int cpu_number;
+       struct task_struct *pcurrent;   /* current process */
+       struct pt_regs *irq_regs;
+};
+
+extern struct i386_pda *_cpu_pda[];
+
+#define cpu_pda(i)     (_cpu_pda[i])
+
+#define pda_offset(field) offsetof(struct i386_pda, field)
+
+extern void __bad_pda_field(void);
+
+/* This variable is never instantiated.  It is only used as a stand-in
+   for the real per-cpu PDA memory, so that gcc can understand what
+   memory operations the inline asms() below are performing.  This
+   eliminates the need to make the asms volatile or have memory
+   clobbers, so gcc can readily analyse them. */
+extern struct i386_pda _proxy_pda;
+
+#define pda_to_op(op,field,val)                                                \
+       do {                                                            \
+               typedef typeof(_proxy_pda.field) T__;                   \
+               if (0) { T__ tmp__; tmp__ = (val); }                    \
+               switch (sizeof(_proxy_pda.field)) {                     \
+               case 1:                                                 \
+                       asm(op "b %1,%%gs:%c2"                          \
+                           : "+m" (_proxy_pda.field)                   \
+                           :"ri" ((T__)val),                           \
+                            "i"(pda_offset(field)));                   \
+                       break;                                          \
+               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;                                          \
+               default: __bad_pda_field();                             \
+               }                                                       \
+       } while (0)
+
+#define pda_from_op(op,field)                                          \
+       ({                                                              \
+               typeof(_proxy_pda.field) ret__;                         \
+               switch (sizeof(_proxy_pda.field)) {                     \
+               case 1:                                                 \
+                       asm(op "b %%gs:%c1,%0"                          \
+                           : "=r" (ret__)                              \
+                           : "i" (pda_offset(field)),                  \
+                             "m" (_proxy_pda.field));                  \
+                       break;                                          \
+               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;                                          \
+               default: __bad_pda_field();                             \
+               }                                                       \
+               ret__; })
+
+/* Return a pointer to a pda field */
+#define pda_addr(field)                                                        \
+       ((typeof(_proxy_pda.field) *)((unsigned char *)read_pda(_pda) + \
+                                     pda_offset(field)))
+
+#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)
+#define sub_pda(field,val) pda_to_op("sub",field,val)
+#define or_pda(field,val) pda_to_op("or",field,val)
+
+#endif /* _I386_PDA_H */
index 5764afa..510ae1d 100644 (file)
@@ -1,6 +1,31 @@
 #ifndef __ARCH_I386_PERCPU__
 #define __ARCH_I386_PERCPU__
 
+#ifndef __ASSEMBLY__
 #include <asm-generic/percpu.h>
+#else
+
+/*
+ * PER_CPU finds an address of a per-cpu variable.
+ *
+ * Args:
+ *    var - variable name
+ *    cpu - 32bit register containing the current CPU number
+ *
+ * The resulting address is stored in the "cpu" argument.
+ *
+ * Example:
+ *    PER_CPU(cpu_gdt_descr, %ebx)
+ */
+#ifdef CONFIG_SMP
+#define PER_CPU(var, cpu) \
+       movl __per_cpu_offset(,cpu,4), cpu;     \
+       addl $per_cpu__/**/var, cpu;
+#else /* ! SMP */
+#define PER_CPU(var, cpu) \
+       movl $per_cpu__/**/var, cpu;
+#endif /* SMP */
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* __ARCH_I386_PERCPU__ */
index 8d8d3b9..38c3fcc 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _I386_PGTABLE_2LEVEL_H
 #define _I386_PGTABLE_2LEVEL_H
 
-#include <asm-generic/pgtable-nopmd.h>
-
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
 #define pgd_ERROR(e) \
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
+#ifndef CONFIG_PARAVIRT
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+#endif
+
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
 #define set_pte_present(mm,addr,ptep,pteval) set_pte_at(mm,addr,ptep,pteval)
-#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
 
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
 
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte_low, 0))
+#define raw_ptep_get_and_clear(xp)     __pte(xchg(&(xp)->pte_low, 0))
 
 #define pte_page(x)            pfn_to_page(pte_pfn(x))
 #define pte_none(x)            (!(x).pte_low)
index c2d701e..7a2318f 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _I386_PGTABLE_3LEVEL_H
 #define _I386_PGTABLE_3LEVEL_H
 
-#include <asm-generic/pgtable-nopud.h>
-
 /*
  * Intel Physical Address Extension (PAE) Mode - three-level page
  * tables on PPro+ CPUs.
@@ -44,6 +42,7 @@ static inline int pte_exec_kernel(pte_t pte)
        return pte_x(pte);
 }
 
+#ifndef CONFIG_PARAVIRT
 /* Rules for using set_pte: the pte being assigned *must* be
  * either not present or in a state where the hardware will
  * not attempt to update the pte.  In places where this is
@@ -80,25 +79,6 @@ static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte
 #define set_pud(pudptr,pudval) \
                (*(pudptr) = (pudval))
 
-/*
- * Pentium-II erratum A13: in PAE mode we explicitly have to flush
- * the TLB via cr3 if the top-level pgd is changed...
- * We do not let the generic code free and clear pgd entries due to
- * this erratum.
- */
-static inline void pud_clear (pud_t * pud) { }
-
-#define pud_page(pud) \
-((struct page *) __va(pud_val(pud) & PAGE_MASK))
-
-#define pud_page_vaddr(pud) \
-((unsigned long) __va(pud_val(pud) & PAGE_MASK))
-
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
-                       pmd_index(address))
-
 /*
  * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
  * entry, so clear the bottom half first and enforce ordering with a compiler
@@ -118,9 +98,28 @@ static inline void pmd_clear(pmd_t *pmd)
        smp_wmb();
        *(tmp + 1) = 0;
 }
+#endif
+
+/*
+ * Pentium-II erratum A13: in PAE mode we explicitly have to flush
+ * the TLB via cr3 if the top-level pgd is changed...
+ * We do not let the generic code free and clear pgd entries due to
+ * this erratum.
+ */
+static inline void pud_clear (pud_t * pud) { }
+
+#define pud_page(pud) \
+((struct page *) __va(pud_val(pud) & PAGE_MASK))
+
+#define pud_page_vaddr(pud) \
+((unsigned long) __va(pud_val(pud) & PAGE_MASK))
+
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+                       pmd_index(address))
 
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+static inline pte_t raw_ptep_get_and_clear(pte_t *ptep)
 {
        pte_t res;
 
index 7d398f4..e6a4723 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/processor.h>
 #include <asm/fixmap.h>
 #include <linux/threads.h>
+#include <asm/paravirt.h>
 
 #ifndef _I386_BITOPS_H
 #include <asm/bitops.h>
@@ -34,14 +35,14 @@ struct vm_area_struct;
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 extern unsigned long empty_zero_page[1024];
 extern pgd_t swapper_pg_dir[1024];
-extern kmem_cache_t *pgd_cache;
-extern kmem_cache_t *pmd_cache;
+extern struct kmem_cache *pgd_cache;
+extern struct kmem_cache *pmd_cache;
 extern spinlock_t pgd_lock;
 extern struct page *pgd_list;
 
-void pmd_ctor(void *, kmem_cache_t *, unsigned long);
-void pgd_ctor(void *, kmem_cache_t *, unsigned long);
-void pgd_dtor(void *, kmem_cache_t *, unsigned long);
+void pmd_ctor(void *, struct kmem_cache *, unsigned long);
+void pgd_ctor(void *, struct kmem_cache *, unsigned long);
+void pgd_dtor(void *, struct kmem_cache *, unsigned long);
 void pgtable_cache_init(void);
 void paging_init(void);
 
@@ -246,6 +247,7 @@ static inline pte_t pte_mkhuge(pte_t pte)   { (pte).pte_low |= _PAGE_PSE; return p
 # include <asm/pgtable-2level.h>
 #endif
 
+#ifndef CONFIG_PARAVIRT
 /*
  * Rules for using pte_update - it must be called after any PTE update which
  * has not been done using the set_pte / clear_pte interfaces.  It is used by
@@ -261,7 +263,7 @@ static inline pte_t pte_mkhuge(pte_t pte)   { (pte).pte_low |= _PAGE_PSE; return p
  */
 #define pte_update(mm, addr, ptep)             do { } while (0)
 #define pte_update_defer(mm, addr, ptep)       do { } while (0)
-
+#endif
 
 /*
  * We only update the dirty/accessed state if we set
@@ -275,7 +277,7 @@ static inline pte_t pte_mkhuge(pte_t pte)   { (pte).pte_low |= _PAGE_PSE; return p
 do {                                                                   \
        if (dirty) {                                                    \
                (ptep)->pte_low = (entry).pte_low;                      \
-               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
                flush_tlb_page(vma, address);                           \
        }                                                               \
 } while (0)
@@ -305,7 +307,7 @@ do {                                                                        \
        __dirty = pte_dirty(*(ptep));                                   \
        if (__dirty) {                                                  \
                clear_bit(_PAGE_BIT_DIRTY, &(ptep)->pte_low);           \
-               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
                flush_tlb_page(vma, address);                           \
        }                                                               \
        __dirty;                                                        \
@@ -318,12 +320,20 @@ do {                                                                      \
        __young = pte_young(*(ptep));                                   \
        if (__young) {                                                  \
                clear_bit(_PAGE_BIT_ACCESSED, &(ptep)->pte_low);        \
-               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
                flush_tlb_page(vma, address);                           \
        }                                                               \
        __young;                                                        \
 })
 
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+       pte_t pte = raw_ptep_get_and_clear(ptep);
+       pte_update(mm, addr, ptep);
+       return pte;
+}
+
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
 {
index e0ddca9..a52d654 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/threads.h>
 #include <asm/percpu.h>
 #include <linux/cpumask.h>
+#include <linux/init.h>
 
 /* flag for disabling the tsc */
 extern int tsc_disable;
@@ -72,6 +73,7 @@ struct cpuinfo_x86 {
 #endif
        unsigned char x86_max_cores;    /* cpuid returned max cores value */
        unsigned char apicid;
+       unsigned short x86_clflush_size;
 #ifdef CONFIG_SMP
        unsigned char booted_cores;     /* number of cores as seen by OS */
        __u8 phys_proc_id;              /* Physical processor id. */
@@ -111,6 +113,8 @@ extern struct cpuinfo_x86 cpu_data[];
 extern int cpu_llc_id[NR_CPUS];
 extern char ignore_fpu_irq;
 
+void __init cpu_detect(struct cpuinfo_x86 *c);
+
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
@@ -143,8 +147,8 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {}
 #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
 #define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
 
-static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
-                          unsigned int *ecx, unsigned int *edx)
+static inline fastcall void native_cpuid(unsigned int *eax, unsigned int *ebx,
+                                        unsigned int *ecx, unsigned int *edx)
 {
        /* ecx is often an input as well as an output. */
        __asm__("cpuid"
@@ -155,59 +159,6 @@ static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
                : "0" (*eax), "2" (*ecx));
 }
 
-/*
- * Generic CPUID function
- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
- * resulting in stale register contents being returned.
- */
-static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
-{
-       *eax = op;
-       *ecx = 0;
-       __cpuid(eax, ebx, ecx, edx);
-}
-
-/* Some CPUID calls want 'count' to be placed in ecx */
-static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
-                              int *edx)
-{
-       *eax = op;
-       *ecx = count;
-       __cpuid(eax, ebx, ecx, edx);
-}
-
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
-{
-       unsigned int eax, ebx, ecx, edx;
-
-       cpuid(op, &eax, &ebx, &ecx, &edx);
-       return eax;
-}
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
-       unsigned int eax, ebx, ecx, edx;
-
-       cpuid(op, &eax, &ebx, &ecx, &edx);
-       return ebx;
-}
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
-       unsigned int eax, ebx, ecx, edx;
-
-       cpuid(op, &eax, &ebx, &ecx, &edx);
-       return ecx;
-}
-static inline unsigned int cpuid_edx(unsigned int op)
-{
-       unsigned int eax, ebx, ecx, edx;
-
-       cpuid(op, &eax, &ebx, &ecx, &edx);
-       return edx;
-}
-
 #define load_cr3(pgdir) write_cr3(__pa(pgdir))
 
 /*
@@ -473,6 +424,7 @@ struct thread_struct {
        .vm86_info = NULL,                                              \
        .sysenter_cs = __KERNEL_CS,                                     \
        .io_bitmap_ptr = NULL,                                          \
+       .gs = __KERNEL_PDA,                                             \
 }
 
 /*
@@ -489,18 +441,9 @@ struct thread_struct {
        .io_bitmap      = { [ 0 ... IO_BITMAP_LONGS] = ~0 },            \
 }
 
-static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
-{
-       tss->esp0 = thread->esp0;
-       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
-       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
-               tss->ss1 = thread->sysenter_cs;
-               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
-       }
-}
-
 #define start_thread(regs, new_eip, new_esp) do {              \
-       __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));       \
+       __asm__("movl %0,%%fs": :"r" (0));                      \
+       regs->xgs = 0;                                          \
        set_fs(USER_DS);                                        \
        regs->xds = __USER_DS;                                  \
        regs->xes = __USER_DS;                                  \
@@ -510,33 +453,6 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa
        regs->esp = new_esp;                                    \
 } while (0)
 
-/*
- * These special macros can be used to get or set a debugging register
- */
-#define get_debugreg(var, register)                            \
-               __asm__("movl %%db" #register ", %0"            \
-                       :"=r" (var))
-#define set_debugreg(value, register)                  \
-               __asm__("movl %0,%%db" #register                \
-                       : /* no output */                       \
-                       :"r" (value))
-
-/*
- * Set IOPL bits in EFLAGS from given mask
- */
-static inline void set_iopl_mask(unsigned mask)
-{
-       unsigned int reg;
-       __asm__ __volatile__ ("pushfl;"
-                             "popl %0;"
-                             "andl %1, %0;"
-                             "orl %2, %0;"
-                             "pushl %0;"
-                             "popfl"
-                               : "=&r" (reg)
-                               : "i" (~X86_EFLAGS_IOPL), "r" (mask));
-}
-
 /* Forward declaration, a strange C thing */
 struct task_struct;
 struct mm_struct;
@@ -628,6 +544,105 @@ static inline void rep_nop(void)
 
 #define cpu_relax()    rep_nop()
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define paravirt_enabled() 0
+#define __cpuid native_cpuid
+
+static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+{
+       tss->esp0 = thread->esp0;
+       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
+       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+               tss->ss1 = thread->sysenter_cs;
+               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+       }
+}
+
+/*
+ * These special macros can be used to get or set a debugging register
+ */
+#define get_debugreg(var, register)                            \
+               __asm__("movl %%db" #register ", %0"            \
+                       :"=r" (var))
+#define set_debugreg(value, register)                  \
+               __asm__("movl %0,%%db" #register                \
+                       : /* no output */                       \
+                       :"r" (value))
+
+#define set_iopl_mask native_set_iopl_mask
+#endif /* CONFIG_PARAVIRT */
+
+/*
+ * Set IOPL bits in EFLAGS from given mask
+ */
+static fastcall inline void native_set_iopl_mask(unsigned mask)
+{
+       unsigned int reg;
+       __asm__ __volatile__ ("pushfl;"
+                             "popl %0;"
+                             "andl %1, %0;"
+                             "orl %2, %0;"
+                             "pushl %0;"
+                             "popfl"
+                               : "=&r" (reg)
+                               : "i" (~X86_EFLAGS_IOPL), "r" (mask));
+}
+
+/*
+ * Generic CPUID function
+ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ * resulting in stale register contents being returned.
+ */
+static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
+{
+       *eax = op;
+       *ecx = 0;
+       __cpuid(eax, ebx, ecx, edx);
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+                              int *edx)
+{
+       *eax = op;
+       *ecx = count;
+       __cpuid(eax, ebx, ecx, edx);
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       cpuid(op, &eax, &ebx, &ecx, &edx);
+       return eax;
+}
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       cpuid(op, &eax, &ebx, &ecx, &edx);
+       return ebx;
+}
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       cpuid(op, &eax, &ebx, &ecx, &edx);
+       return ecx;
+}
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       cpuid(op, &eax, &ebx, &ecx, &edx);
+       return edx;
+}
+
 /* generic versions from gas */
 #define GENERIC_NOP1   ".byte 0x90\n"
 #define GENERIC_NOP2           ".byte 0x89,0xf6\n"
@@ -727,4 +742,7 @@ extern unsigned long boot_option_idle_override;
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
+extern int init_gdt(int cpu, struct task_struct *idle);
+extern void secondary_cpu_init(void);
+
 #endif /* __ASM_I386_PROCESSOR_H */
index d505f50..bdbc894 100644 (file)
@@ -16,6 +16,8 @@ struct pt_regs {
        long eax;
        int  xds;
        int  xes;
+       /* int  xfs; */
+       int  xgs;
        long orig_eax;
        long eip;
        int  xcs;
index bc598d6..041906f 100644 (file)
@@ -75,8 +75,8 @@ struct rw_semaphore {
 
 
 #define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
-       __RWSEM_DEP_MAP_INIT(name) }
+{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
+  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name) \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
index b7ab596..3c796af 100644 (file)
@@ -39,7 +39,7 @@
  *  25 - APM BIOS support 
  *
  *  26 - ESPFIX small SS
- *  27 - unused
+ *  27 - PDA                           [ per-cpu private data area ]
  *  28 - unused
  *  29 - unused
  *  30 - unused
@@ -74,6 +74,9 @@
 #define GDT_ENTRY_ESPFIX_SS            (GDT_ENTRY_KERNEL_BASE + 14)
 #define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
 
+#define GDT_ENTRY_PDA                  (GDT_ENTRY_KERNEL_BASE + 15)
+#define __KERNEL_PDA (GDT_ENTRY_PDA * 8)
+
 #define GDT_ENTRY_DOUBLEFAULT_TSS      31
 
 /*
 #define SEGMENT_LDT            0x4
 #define SEGMENT_GDT            0x0
 
+#ifndef CONFIG_PARAVIRT
 #define get_kernel_rpl()  0
 #endif
+#endif
index 2734909..67659db 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef _i386_SETUP_H
 #define _i386_SETUP_H
 
+#define COMMAND_LINE_SIZE 256
+
 #ifdef __KERNEL__
 #include <linux/pfn.h>
 
  */
 #define MAXMEM_PFN     PFN_DOWN(MAXMEM)
 #define MAX_NONPAE_PFN (1 << 20)
-#endif
 
 #define PARAM_SIZE 4096
-#define COMMAND_LINE_SIZE 256
 
 #define OLD_CL_MAGIC_ADDR      0x90020
 #define OLD_CL_MAGIC           0xA33F
@@ -70,6 +70,7 @@ extern unsigned char boot_params[PARAM_SIZE];
 struct e820entry;
 
 char * __init machine_specific_memory_setup(void);
+char *memory_setup(void);
 
 int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
 int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
@@ -78,4 +79,6 @@ void __init add_memory_region(unsigned long long start,
 
 #endif /* __ASSEMBLY__ */
 
+#endif  /*  __KERNEL__  */
+
 #endif /* _i386_SETUP_H */
index bd59c15..64fe624 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
+#include <asm/pda.h>
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -56,7 +57,7 @@ extern void cpu_uninit(void);
  * from the initial startup. We map APIC_BASE very early in page_setup(),
  * so this is correct in the x86 case.
  */
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (read_pda(cpu_number))
 
 extern cpumask_t cpu_callout_map;
 extern cpumask_t cpu_callin_map;
index c18b71f..d3bcebe 100644 (file)
@@ -7,8 +7,14 @@
 #include <asm/processor.h>
 #include <linux/compiler.h>
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #define CLI_STRING     "cli"
 #define STI_STRING     "sti"
+#define CLI_STI_CLOBBERS
+#define CLI_STI_INPUT_ARGS
+#endif /* CONFIG_PARAVIRT */
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -53,25 +59,28 @@ static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long fla
 {
        asm volatile(
                "\n1:\t"
-               LOCK_PREFIX " ; decb %0\n\t"
+               LOCK_PREFIX " ; decb %[slock]\n\t"
                "jns 5f\n"
                "2:\t"
-               "testl $0x200, %1\n\t"
+               "testl $0x200, %[flags]\n\t"
                "jz 4f\n\t"
                STI_STRING "\n"
                "3:\t"
                "rep;nop\n\t"
-               "cmpb $0, %0\n\t"
+               "cmpb $0, %[slock]\n\t"
                "jle 3b\n\t"
                CLI_STRING "\n\t"
                "jmp 1b\n"
                "4:\t"
                "rep;nop\n\t"
-               "cmpb $0, %0\n\t"
+               "cmpb $0, %[slock]\n\t"
                "jg 1b\n\t"
                "jmp 4b\n"
                "5:\n\t"
-               : "+m" (lock->slock) : "r" (flags) : "memory");
+               : [slock] "+m" (lock->slock)
+               : [flags] "r" (flags)
+                 CLI_STI_INPUT_ARGS
+               : "memory" CLI_STI_CLOBBERS);
 }
 #endif
 
index 59efe84..4da9345 100644 (file)
@@ -6,13 +6,13 @@
 #endif
 
 typedef struct {
-       volatile unsigned int slock;
+       unsigned int slock;
 } raw_spinlock_t;
 
 #define __RAW_SPIN_LOCK_UNLOCKED       { 1 }
 
 typedef struct {
-       volatile unsigned int lock;
+       unsigned int lock;
 } raw_rwlock_t;
 
 #define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
index 08be1e5..8dbaafe 100644 (file)
@@ -6,29 +6,14 @@
 #include <asm/desc.h>
 #include <asm/i387.h>
 
-static inline int
-arch_prepare_suspend(void)
-{
-       /* If you want to make non-PSE machine work, turn off paging
-           in swsusp_arch_suspend. swsusp_pg_dir should have identity mapping, so
-           it could work...  */
-       if (!cpu_has_pse) {
-               printk(KERN_ERR "PSE is required for swsusp.\n");
-               return -EPERM;
-       }
-       return 0;
-}
+static inline int arch_prepare_suspend(void) { return 0; }
 
 /* image of the saved processor state */
 struct saved_context {
        u16 es, fs, gs, ss;
        unsigned long cr0, cr2, cr3, cr4;
-       u16 gdt_pad;
-       u16 gdt_limit;
-       unsigned long gdt_base;
-       u16 idt_pad;
-       u16 idt_limit;
-       unsigned long idt_base;
+       struct Xgt_desc_struct gdt;
+       struct Xgt_desc_struct idt;
        u16 ldt;
        u16 tss;
        unsigned long tr;
index a6dabbc..a6d20d9 100644 (file)
@@ -88,6 +88,9 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
 #define savesegment(seg, value) \
        asm volatile("mov %%" #seg ",%0":"=rm" (value))
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #define read_cr0() ({ \
        unsigned int __dummy; \
        __asm__ __volatile__( \
@@ -139,17 +142,18 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
 #define write_cr4(x) \
        __asm__ __volatile__("movl %0,%%cr4": :"r" (x))
 
-/*
- * Clear and set 'TS' bit respectively
- */
+#define wbinvd() \
+       __asm__ __volatile__ ("wbinvd": : :"memory")
+
+/* Clear the 'TS' bit */
 #define clts() __asm__ __volatile__ ("clts")
+#endif/* CONFIG_PARAVIRT */
+
+/* Set the 'TS' bit */
 #define stts() write_cr0(8 | read_cr0())
 
 #endif /* __KERNEL__ */
 
-#define wbinvd() \
-       __asm__ __volatile__ ("wbinvd": : :"memory")
-
 static inline unsigned long get_limit(unsigned long segment)
 {
        unsigned long __limit;
index 72c10e3..12baf1d 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 54d6d7a..46d32ad 100644 (file)
@@ -95,15 +95,7 @@ static inline struct thread_info *current_thread_info(void)
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)                                 \
-       ({                                                      \
-               struct thread_info *ret;                        \
-                                                               \
-               ret = kmalloc(THREAD_SIZE, GFP_KERNEL);         \
-               if (ret)                                        \
-                       memset(ret, 0, THREAD_SIZE);            \
-               ret;                                            \
-       })
+#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
 #else
 #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
 #endif
diff --git a/include/asm-i386/time.h b/include/asm-i386/time.h
new file mode 100644 (file)
index 0000000..ea8065a
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _ASMi386_TIME_H
+#define _ASMi386_TIME_H
+
+#include <linux/efi.h>
+#include "mach_time.h"
+
+static inline unsigned long native_get_wallclock(void)
+{
+       unsigned long retval;
+
+       if (efi_enabled)
+               retval = efi_get_time();
+       else
+               retval = mach_get_cmos_time();
+
+       return retval;
+}
+
+static inline int native_set_wallclock(unsigned long nowtime)
+{
+       int retval;
+
+       if (efi_enabled)
+               retval = efi_set_rtc_mmss(nowtime);
+       else
+               retval = mach_set_rtc_mmss(nowtime);
+
+       return retval;
+}
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else /* !CONFIG_PARAVIRT */
+
+#define get_wallclock() native_get_wallclock()
+#define set_wallclock(x) native_set_wallclock(x)
+#define do_time_init() time_init_hook()
+
+#endif /* CONFIG_PARAVIRT */
+
+#endif
index 360648b..4dd8284 100644 (file)
@@ -4,7 +4,15 @@
 #include <linux/mm.h>
 #include <asm/processor.h>
 
-#define __flush_tlb()                                                  \
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define __flush_tlb() __native_flush_tlb()
+#define __flush_tlb_global() __native_flush_tlb_global()
+#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
+#endif
+
+#define __native_flush_tlb()                                           \
        do {                                                            \
                unsigned int tmpreg;                                    \
                                                                        \
@@ -19,7 +27,7 @@
  * Global pages have to be flushed a bit differently. Not a real
  * performance problem because this does not happen often.
  */
-#define __flush_tlb_global()                                           \
+#define __native_flush_tlb_global()                                    \
        do {                                                            \
                unsigned int tmpreg, cr4, cr4_orig;                     \
                                                                        \
@@ -36,6 +44,9 @@
                        : "memory");                                    \
        } while (0)
 
+#define __native_flush_tlb_single(addr)                                \
+       __asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory")
+
 # define __flush_tlb_all()                                             \
        do {                                                            \
                if (cpu_has_pge)                                        \
@@ -46,9 +57,6 @@
 
 #define cpu_has_invlpg (boot_cpu_data.x86 > 3)
 
-#define __flush_tlb_single(addr) \
-       __asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory")
-
 #ifdef CONFIG_X86_INVLPG
 # define __flush_tlb_one(addr) __flush_tlb_single(addr)
 #else
index 978d095..ac58580 100644 (file)
@@ -89,6 +89,7 @@ static inline int node_to_first_cpu(int node)
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_FORK       \
+                               | SD_SERIALIZE          \
                                | SD_WAKE_BALANCE,      \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
index beeeaf6..833fa17 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 320
-#include <linux/err.h>
-
-/*
- * 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)(-MAX_ERRNO)) { \
-               errno = -(res); \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name)); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
-                 "d" ((long)(arg3)) : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
-__syscall_return(type,__res); \
-} 
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \
-                  "int $0x80 ; pop %%ebx" \
-       : "=a" (__res) \
-       : "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5,type6,arg6) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
-{ \
-long __res; \
-  struct { long __a1; long __a6; } __s = { (long)arg1, (long)arg6 }; \
-__asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \
-                  "movl 0(%2),%%ebx ; movl %1,%%eax ; int $0x80 ; " \
-                  "pop %%ebx ;  pop %%ebp" \
-       : "=a" (__res) \
-       : "i" (__NR_##name),"0" ((long)(&__s)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 5031d69..aa2c931 100644 (file)
@@ -71,6 +71,7 @@ static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
        info->regs.xss = __KERNEL_DS;
        info->regs.xds = __USER_DS;
        info->regs.xes = __USER_DS;
+       info->regs.xgs = __KERNEL_PDA;
 }
 
 extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
@@ -78,17 +79,13 @@ extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
                                                                           void *arg),
                                                void *arg);
 
-static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info)
 {
-#if 0 /* This can only work when selector register and EFLAGS saves/restores
-         are properly annotated (and tracked in UNW_REGISTER_INFO). */
-       return user_mode_vm(&info->regs);
-#else
-       return info->regs.eip < PAGE_OFFSET
+       return user_mode_vm(&info->regs)
+              || info->regs.eip < PAGE_OFFSET
               || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
-                   && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+                  && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
               || info->regs.esp < PAGE_OFFSET;
-#endif
 }
 
 #else
index 952fd69..a5edf51 100644 (file)
@@ -145,26 +145,13 @@ struct vm86plus_struct {
  * at the end of the structure. Look at ptrace.h to see the "normal"
  * setup. For user space layout see 'struct vm86_regs' above.
  */
+#include <asm/ptrace.h>
 
 struct kernel_vm86_regs {
 /*
  * normal regs, with special meaning for the segment descriptors..
  */
-       long ebx;
-       long ecx;
-       long edx;
-       long esi;
-       long edi;
-       long ebp;
-       long eax;
-       long __null_ds;
-       long __null_es;
-       long orig_eax;
-       long eip;
-       unsigned short cs, __csh;
-       long eflags;
-       long esp;
-       unsigned short ss, __ssh;
+       struct pt_regs pt;
 /*
  * these are specific to v86 mode:
  */
index 15818a1..4a1e48b 100644 (file)
@@ -10,7 +10,6 @@ header-y += intrinsics.h
 header-y += perfmon_default_smpl.h
 header-y += ptrace_offsets.h
 header-y += rse.h
-header-y += setup.h
 header-y += ucontext.h
 
 unifdef-y += perfmon.h
index bd40f47..2b78582 100644 (file)
@@ -70,4 +70,10 @@ static inline __sum16 csum_fold(__wsum csum)
        return (__force __sum16)~sum;
 }
 
+#define _HAVE_ARCH_IPV6_CSUM   1
+struct in6_addr;
+extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+       struct in6_addr *daddr, __u32 len, unsigned short proto,
+       unsigned int csum);
+
 #endif /* _ASM_IA64_CHECKSUM_H */
index 99a8f8e..ebd5887 100644 (file)
@@ -50,7 +50,8 @@ dma_set_mask (struct device *dev, u64 mask)
 extern int dma_get_cache_alignment(void);
 
 static inline void
-dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir)
+dma_cache_sync (struct device *dev, void *vaddr, size_t size,
+       enum dma_data_direction dir)
 {
        /*
         * IA-64 is cache-coherent, so this is mostly a no-op.  However, we do need to
@@ -59,6 +60,6 @@ dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir)
        mb();
 }
 
-#define dma_is_consistent(dma_handle)  (1)     /* all we do is coherent memory... */
+#define dma_is_consistent(d, h)        (1)     /* all we do is coherent memory... */
 
 #endif /* _ASM_IA64_DMA_MAPPING_H */
index 07d77f3..8a98a26 100644 (file)
@@ -59,7 +59,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -83,7 +83,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
diff --git a/include/asm-ia64/kexec.h b/include/asm-ia64/kexec.h
new file mode 100644 (file)
index 0000000..01c36b0
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _ASM_IA64_KEXEC_H
+#define _ASM_IA64_KEXEC_H
+
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE (8192 + 8192 + 4096)
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_IA_64
+
+#define MAX_NOTE_BYTES 1024
+
+#define kexec_flush_icache_page(page) do { \
+                unsigned long page_addr = (unsigned long)page_address(page); \
+                flush_icache_range(page_addr, page_addr + PAGE_SIZE); \
+        } while(0)
+
+extern struct kimage *ia64_kimage;
+DECLARE_PER_CPU(u64, ia64_mca_pal_base);
+const extern unsigned int relocate_new_kernel_size;
+extern void relocate_new_kernel(unsigned long, unsigned long,
+               struct ia64_boot_param *, unsigned long);
+static inline void
+crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
+{
+}
+extern struct resource efi_memmap_res;
+extern struct resource boot_param_res;
+extern void kdump_smp_send_stop(void);
+extern void kdump_smp_send_init(void);
+extern void kexec_disable_iosapic(void);
+extern void crash_save_this_cpu(void);
+struct rsvd_region;
+extern unsigned long kdump_find_rsvd_region(unsigned long size,
+               struct rsvd_region *rsvd_regions, int n);
+extern void kdump_cpu_freeze(struct unw_frame_info *info, void *arg);
+extern int kdump_status[];
+extern atomic_t kdump_cpu_freezed;
+extern atomic_t kdump_in_progress;
+
+#endif /* _ASM_IA64_KEXEC_H */
index 8f784f8..a3891eb 100644 (file)
@@ -37,6 +37,7 @@ typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
                                        u8 size);
 typedef void ia64_mv_migrate_t(struct task_struct * task);
 typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *);
+typedef void ia64_mv_kernel_launch_event_t(void);
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
@@ -218,6 +219,7 @@ struct ia64_machine_vector {
        ia64_mv_setup_msi_irq_t *setup_msi_irq;
        ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
        ia64_mv_pci_fixup_bus_t *pci_fixup_bus;
+       ia64_mv_kernel_launch_event_t *kernel_launch_event;
 } __attribute__((__aligned__(16))); /* align attrib? see above comment */
 
 #define MACHVEC_INIT(name)                     \
@@ -318,6 +320,9 @@ extern ia64_mv_dma_supported                swiotlb_dma_supported;
 #ifndef platform_tlb_migrate_finish
 # define platform_tlb_migrate_finish   machvec_noop_mm
 #endif
+#ifndef platform_kernel_launch_event
+# define platform_kernel_launch_event  machvec_noop
+#endif
 #ifndef platform_dma_init
 # define platform_dma_init             swiotlb_init
 #endif
index 83325f6..eaa2fce 100644 (file)
@@ -67,6 +67,7 @@ extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device;
 extern ia64_mv_dma_mapping_error       sn_dma_mapping_error;
 extern ia64_mv_dma_supported           sn_dma_supported;
 extern ia64_mv_migrate_t               sn_migrate;
+extern ia64_mv_kernel_launch_event_t   sn_kernel_launch_event;
 extern ia64_mv_setup_msi_irq_t         sn_setup_msi_irq;
 extern ia64_mv_teardown_msi_irq_t      sn_teardown_msi_irq;
 extern ia64_mv_pci_fixup_bus_t         sn_pci_fixup_bus;
@@ -121,6 +122,7 @@ extern ia64_mv_pci_fixup_bus_t              sn_pci_fixup_bus;
 #define platform_dma_mapping_error             sn_dma_mapping_error
 #define platform_dma_supported         sn_dma_supported
 #define platform_migrate               sn_migrate
+#define platform_kernel_launch_event    sn_kernel_launch_event
 #ifdef CONFIG_PCI_MSI
 #define platform_setup_msi_irq         sn_setup_msi_irq
 #define platform_teardown_msi_irq      sn_teardown_msi_irq
index c3b1f86..c8df759 100644 (file)
  *     - initrd (optional)
  *     - command line string
  *     - kernel code & data
+ *     - crash dumping code reserved region
  *     - Kernel memory map built from EFI memory map
  *
  * More could be added if necessary
  */
-#define IA64_MAX_RSVD_REGIONS 6
+#define IA64_MAX_RSVD_REGIONS 7
 
 struct rsvd_region {
        unsigned long start;    /* virtual address of beginning of element */
index 947cb72..485759b 100644 (file)
@@ -101,7 +101,7 @@ do {                                                \
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 extern int ia64_pfn_valid (unsigned long pfn);
-#elif defined(CONFIG_FLATMEM)
+#else
 # define ia64_pfn_valid(pfn) 1
 #endif
 
@@ -110,12 +110,11 @@ extern struct page *vmem_map;
 #ifdef CONFIG_DISCONTIGMEM
 # define page_to_pfn(page)     ((unsigned long) (page - vmem_map))
 # define pfn_to_page(pfn)      (vmem_map + (pfn))
+#else
+# include <asm-generic/memory_model.h>
 #endif
-#endif
-
-#if defined(CONFIG_FLATMEM) || defined(CONFIG_SPARSEMEM)
-/* FLATMEM always configures mem_map (mem_map = vmem_map if necessary) */
-#include <asm-generic/memory_model.h>
+#else
+# include <asm-generic/memory_model.h>
 #endif
 
 #ifdef CONFIG_FLATMEM
index 4283ddc..bc76815 100644 (file)
@@ -20,6 +20,8 @@
  * 00/05/24     eranian Updated to latest PAL spec, fix structures bugs, added
  * 00/05/25    eranian Support for stack calls, and static physical calls
  * 00/06/18    eranian Support for stacked physical calls
+ * 06/10/26    rja     Support for Intel Itanium Architecture Software Developer's
+ *                     Manual Rev 2.2 (Jan 2006)
  */
 
 /*
@@ -69,6 +71,8 @@
 #define PAL_PREFETCH_VISIBILITY        41      /* Make Processor Prefetches Visible */
 #define PAL_LOGICAL_TO_PHYSICAL 42     /* returns information on logical to physical processor mapping */
 #define PAL_CACHE_SHARED_INFO  43      /* returns information on caches shared by logical processor */
+#define PAL_GET_HW_POLICY      48      /* Get current hardware resource sharing policy */
+#define PAL_SET_HW_POLICY      49      /* Set current hardware resource sharing policy */
 
 #define PAL_COPY_PAL           256     /* relocate PAL procedures and PAL PMI */
 #define PAL_HALT_INFO          257     /* return the low power capabilities of processor */
 #define PAL_SET_PSTATE         263     /* set the P-state */
 #define PAL_BRAND_INFO         274     /* Processor branding information */
 
+#define PAL_GET_PSTATE_TYPE_LASTSET    0
+#define PAL_GET_PSTATE_TYPE_AVGANDRESET        1
+#define PAL_GET_PSTATE_TYPE_AVGNORESET 2
+#define PAL_GET_PSTATE_TYPE_INSTANT    3
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -102,6 +111,7 @@ typedef s64                         pal_status_t;
                                                 * cache without sideeffects
                                                 * and "restrict" was 1
                                                 */
+#define PAL_STATUS_REQUIRES_MEMORY     (-9)    /* Call requires PAL memory buffer */
 
 /* Processor cache level in the heirarchy */
 typedef u64                            pal_cache_level_t;
@@ -456,7 +466,9 @@ typedef struct pal_process_state_info_s {
                                                 * by the processor
                                                 */
 
-                       reserved2       : 11,
+                       se              : 1,    /* Shared error.  MCA in a
+                                                  shared structure */
+                       reserved2       : 10,
                        cc              : 1,    /* Cache check */
                        tc              : 1,    /* TLB check */
                        bc              : 1,    /* Bus check */
@@ -487,10 +499,12 @@ typedef struct pal_cache_check_info_s {
                                                 * error occurred
                                                 */
                        wiv             : 1,    /* Way field valid */
-                       reserved2       : 10,
+                       reserved2       : 1,
+                       dp              : 1,    /* Data poisoned on MBE */
+                       reserved3       : 8,
 
                        index           : 20,   /* Cache line index */
-                       reserved3       : 2,
+                       reserved4       : 2,
 
                        is              : 1,    /* instruction set (1 == ia32) */
                        iv              : 1,    /* instruction set field valid */
@@ -557,7 +571,7 @@ typedef struct pal_bus_check_info_s {
                        type            : 8,    /* Bus xaction type*/
                        sev             : 5,    /* Bus error severity*/
                        hier            : 2,    /* Bus hierarchy level */
-                       reserved1       : 1,
+                       dp              : 1,    /* Data poisoned on MBE */
                        bsi             : 8,    /* Bus error status
                                                 * info
                                                 */
@@ -834,7 +848,9 @@ typedef union pal_bus_features_u {
                u64     pbf_req_bus_parking                     :       1;
                u64     pbf_bus_lock_mask                       :       1;
                u64     pbf_enable_half_xfer_rate               :       1;
-               u64     pbf_reserved2                           :       22;
+               u64     pbf_reserved2                           :       20;
+               u64     pbf_enable_shared_line_replace          :       1;
+               u64     pbf_enable_exclusive_line_replace       :       1;
                u64     pbf_disable_xaction_queueing            :       1;
                u64     pbf_disable_resp_err_check              :       1;
                u64     pbf_disable_berr_check                  :       1;
@@ -1077,6 +1093,24 @@ ia64_pal_freq_ratios (struct pal_freq_ratio *proc_ratio, struct pal_freq_ratio *
        return iprv.status;
 }
 
+/*
+ * Get the current hardware resource sharing policy of the processor
+ */
+static inline s64
+ia64_pal_get_hw_policy (u64 proc_num, u64 *cur_policy, u64 *num_impacted,
+                       u64 *la)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL(iprv, PAL_GET_HW_POLICY, proc_num, 0, 0);
+       if (cur_policy)
+               *cur_policy = iprv.v0;
+       if (num_impacted)
+               *num_impacted = iprv.v1;
+       if (la)
+               *la = iprv.v2;
+       return iprv.status;
+}
+
 /* Make the processor enter HALT or one of the implementation dependent low
  * power states where prefetching and execution are suspended and cache and
  * TLB coherency is not maintained.
@@ -1112,10 +1146,10 @@ ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf)
 
 /* Get the current P-state information */
 static inline s64
-ia64_pal_get_pstate (u64 *pstate_index)
+ia64_pal_get_pstate (u64 *pstate_index, unsigned long type)
 {
        struct ia64_pal_retval iprv;
-       PAL_CALL_STK(iprv, PAL_GET_PSTATE, 0, 0, 0);
+       PAL_CALL_STK(iprv, PAL_GET_PSTATE, type, 0, 0);
        *pstate_index = iprv.v0;
        return iprv.status;
 }
@@ -1401,6 +1435,17 @@ ia64_pal_rse_info (u64 *num_phys_stacked, pal_hints_u_t *hints)
        return iprv.status;
 }
 
+/*
+ * Set the current hardware resource sharing policy of the processor
+ */
+static inline s64
+ia64_pal_set_hw_policy (u64 policy)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL(iprv, PAL_SET_HW_POLICY, policy, 0, 0);
+       return iprv.status;
+}
+
 /* Cause the processor to enter        SHUTDOWN state, where prefetching and execution are
  * suspended, but cause cache and TLB coherency to be maintained.
  * This is usually called in IA-32 mode.
@@ -1524,12 +1569,15 @@ typedef union pal_vm_info_1_u {
        } pal_vm_info_1_s;
 } pal_vm_info_1_u_t;
 
+#define PAL_MAX_PURGES         0xFFFF          /* all ones is means unlimited */
+
 typedef union pal_vm_info_2_u {
        u64                     pvi2_val;
        struct {
                u64             impl_va_msb     : 8,
                                rid_size        : 8,
-                               reserved        : 48;
+                               max_purges      : 16,
+                               reserved        : 32;
        } pal_vm_info_2_s;
 } pal_vm_info_2_u_t;
 
index 9cb68e9..393e04c 100644 (file)
@@ -60,7 +60,7 @@ static inline void *pgtable_quicklist_alloc(void)
 static inline void pgtable_quicklist_free(void *pgtable_entry)
 {
 #ifdef CONFIG_NUMA
-       unsigned long nid = page_to_nid(virt_to_page(pgtable_entry));
+       int nid = page_to_nid(virt_to_page(pgtable_entry));
 
        if (unlikely(nid != numa_node_id())) {
                free_page((unsigned long)pgtable_entry);
index be5d83a..2c4004e 100644 (file)
@@ -88,6 +88,8 @@
 #define  SN_SAL_INJECT_ERROR                      0x02000067
 #define  SN_SAL_SET_CPU_NUMBER                    0x02000068
 
+#define  SN_SAL_KERNEL_LAUNCH_EVENT               0x02000069
+
 /*
  * Service-specific constants
  */
@@ -1155,4 +1157,11 @@ ia64_sn_set_cpu_number(int cpu)
        SAL_CALL_NOLOCK(rv, SN_SAL_SET_CPU_NUMBER, cpu, 0, 0, 0, 0, 0, 0);
        return rv.status;
 }
+static inline int
+ia64_sn_kernel_launch_event(void)
+{
+       struct ia64_sal_retval rv;
+       SAL_CALL_NOLOCK(rv, SN_SAL_KERNEL_LAUNCH_EVENT, 0, 0, 0, 0, 0, 0, 0);
+       return rv.status;
+}
 #endif /* _ASM_IA64_SN_SN_SAL_H */
index b9e843f..4531a51 100644 (file)
@@ -26,6 +26,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index a6e3856..22ed674 100644 (file)
@@ -101,6 +101,7 @@ void build_cpu_to_node_map(void);
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_FORK       \
+                               | SD_SERIALIZE          \
                                | SD_WAKE_BALANCE,      \
        .last_balance           = jiffies,              \
        .balance_interval       = 64,                   \
index 219a0f7..c82ebe8 100644 (file)
@@ -32,7 +32,8 @@
 static __inline__ int ide_default_irq(unsigned long base)
 {
        switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
+       || defined(CONFIG_PLAT_OPSPUT)
                case 0x1f0: return PLD_IRQ_CFIREQ;
                default:
                        return 0;
index a1f0d1f..52807f8 100644 (file)
 #define M32R_MFT5RLD_PORTL     (0x0C+M32R_MFT5_OFFSET)  /* MFT4 reload */
 #define M32R_MFT5CMPRLD_PORTL  (0x10+M32R_MFT5_OFFSET)  /* MFT4 compare reload */
 
-#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32104)
+#if (defined(CONFIG_CHIP_M32700) && !defined(CONFIG_PLAT_MAPPI2)) \
+       || defined(CONFIG_CHIP_M32104)
 #define M32R_MFTCR_MFT0MSK  (1UL<<31)  /* b0 */
 #define M32R_MFTCR_MFT1MSK  (1UL<<30)  /* b1 */
 #define M32R_MFTCR_MFT2MSK  (1UL<<29)  /* b2 */
 #define M32R_MFTCR_MFT3EN   (1UL<<20)  /* b11 */
 #define M32R_MFTCR_MFT4EN   (1UL<<19)  /* b12 */
 #define M32R_MFTCR_MFT5EN   (1UL<<18)  /* b13 */
-#else  /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
+#else
 #define M32R_MFTCR_MFT0MSK  (1UL<<15)  /* b16 */
 #define M32R_MFTCR_MFT1MSK  (1UL<<14)  /* b17 */
 #define M32R_MFTCR_MFT2MSK  (1UL<<13)  /* b18 */
 #define M32R_MFTCR_MFT3EN   (1UL<<4)   /* b27 */
 #define M32R_MFTCR_MFT4EN   (1UL<<3)   /* b28 */
 #define M32R_MFTCR_MFT5EN   (1UL<<2)   /* b29 */
-#endif /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
+#endif
 
 #define M32R_MFTMOD_CC_MASK    (1UL<<15)  /* b16 */
 #define M32R_MFTMOD_TCCR       (1UL<<13)  /* b18 */
index 2d2a6c9..632b4ce 100644 (file)
 #define PT_R15         PT_SP
 
 /* processor status and miscellaneous context registers.  */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
 #define PT_ACC0H       15
 #define PT_ACC0L       16
-#define PT_ACC1H       17
-#define PT_ACC1L       18
-#define PT_ACCH                PT_ACC0H
-#define PT_ACCL                PT_ACC0L
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH                15
-#define PT_ACCL                16
-#define PT_DUMMY_ACC1H 17
-#define PT_DUMMY_ACC1L 18
-#else
-#error unknown isa conifiguration
-#endif
+#define PT_ACC1H       17      /* ISA_DSP_LEVEL2 only */
+#define PT_ACC1L       18      /* ISA_DSP_LEVEL2 only */
 #define PT_PSW         19
 #define PT_BPC         20
 #define PT_BBPSW       21
@@ -103,19 +92,10 @@ struct pt_regs {
        long syscall_nr;
 
        /* Saved main processor status and miscellaneous context registers. */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
        unsigned long acc0h;
        unsigned long acc0l;
-       unsigned long acc1h;
-       unsigned long acc1l;
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-       unsigned long acch;
-       unsigned long accl;
-       unsigned long dummy_acc1h;
-       unsigned long dummy_acc1l;
-#else
-#error unknown isa configuration
-#endif
+       unsigned long acc1h;    /* ISA_DSP_LEVEL2 only */
+       unsigned long acc1l;    /* ISA_DSP_LEVEL2 only */
        unsigned long psw;
        unsigned long bpc;              /* saved PC for TRAP syscalls */
        unsigned long bbpsw;
index 52f4fa2..6a0b322 100644 (file)
@@ -1,6 +1,11 @@
 /*
  * This is set up by the setup-routine at boot-time
  */
+
+#define COMMAND_LINE_SIZE       512
+
+#ifdef __KERNEL__
+
 #define PARAM                  ((unsigned char *)empty_zero_page)
 
 #define MOUNT_ROOT_RDONLY      (*(unsigned long *) (PARAM+0x000))
@@ -18,8 +23,6 @@
 
 #define SCREEN_INFO            (*(struct screen_info *) (PARAM+0x200))
 
-#define COMMAND_LINE_SIZE      (512)
-
 #define RAMDISK_IMAGE_START_MASK       (0x07FF)
 #define RAMDISK_PROMPT_FLAG            (0x8000)
 #define RAMDISK_LOAD_FLAG              (0x4000)
@@ -27,3 +30,5 @@
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
+#endif  /*  __KERNEL__  */
+
index 73025c0..62537dc 100644 (file)
@@ -23,19 +23,10 @@ struct sigcontext {
        unsigned long sc_r12;
 
        /* Saved main processor status and miscellaneous context registers. */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
        unsigned long sc_acc0h;
        unsigned long sc_acc0l;
-       unsigned long sc_acc1h;
-       unsigned long sc_acc1l;
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-       unsigned long sc_acch;
-       unsigned long sc_accl;
-       unsigned long sc_dummy_acc1h;
-       unsigned long sc_dummy_acc1l;
-#else
-#error unknown isa configuration
-#endif
+       unsigned long sc_acc1h; /* ISA_DSP_LEVEL2 only */
+       unsigned long sc_acc1l; /* ISA_DSP_LEVEL2 only */
        unsigned long sc_psw;
        unsigned long sc_bpc;           /* saved PC for TRAP syscalls */
        unsigned long sc_bbpsw;
index 5ace370..faf2bd0 100644 (file)
@@ -19,6 +19,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 95aa342..5b66bd3 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 285
-#include <linux/err.h>
-
-/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
- * <asm-m32r/errno.h>
- */
-
-#include <asm/syscall.h>       /* SYSCALL_* */
-
-#define __syscall_return(type, res) \
-do { \
-       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); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __res __asm__("r0"); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __res __asm__ ("r0") = (long)(arg1); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno), "0" (__res) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __arg2 __asm__ ("r1") = (long)(arg2); \
-register long __res __asm__ ("r0") = (long)(arg1); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno), "0" (__res), "r" (__arg2) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __arg3 __asm__ ("r2") = (long)(arg3); \
-register long __arg2 __asm__ ("r1") = (long)(arg2); \
-register long __res __asm__ ("r0") = (long)(arg1); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno), "0" (__res), "r" (__arg2), \
-               "r" (__arg3) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __arg4 __asm__ ("r3") = (long)(arg4); \
-register long __arg3 __asm__ ("r2") = (long)(arg3); \
-register long __arg2 __asm__ ("r1") = (long)(arg2); \
-register long __res __asm__ ("r0") = (long)(arg1); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno), "0" (__res), "r" (__arg2), \
-               "r" (__arg3), "r" (__arg4) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-       type5,arg5) \
-type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-register long __scno __asm__ ("r7") = __NR_##name; \
-register long __arg5 __asm__ ("r4") = (long)(arg5); \
-register long __arg4 __asm__ ("r3") = (long)(arg4); \
-register long __arg3 __asm__ ("r2") = (long)(arg3); \
-register long __arg2 __asm__ ("r1") = (long)(arg2); \
-register long __res __asm__ ("r0") = (long)(arg1); \
-__asm__ __volatile__ (\
-       "trap #" SYSCALL_VECTOR "|| nop"\
-       : "=r" (__res) \
-       : "r" (__scno), "0" (__res), "r" (__arg2), \
-               "r" (__arg3), "r" (__arg4), "r" (__arg5) \
-       : "memory"); \
-__syscall_return(type,__res); \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
index d90d841..00259ed 100644 (file)
@@ -21,7 +21,7 @@ static inline int dma_get_cache_alignment(void)
        return 1 << L1_CACHE_SHIFT;
 }
 
-static inline int dma_is_consistent(dma_addr_t dma_addr)
+static inline int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
@@ -41,7 +41,7 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
 {
        dma_free_coherent(dev, size, addr, handle);
 }
-static inline void dma_cache_sync(void *vaddr, size_t size,
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                                  enum dma_data_direction dir)
 {
        /* we use coherent allocation, so not much to do here. */
index 7facc9a..2a8853c 100644 (file)
 #define MACH_Q40     10
 #define MACH_SUN3X   11
 
+#define COMMAND_LINE_SIZE 256
+
 #ifdef __KERNEL__
 
+#define CL_SIZE COMMAND_LINE_SIZE
+
 #ifndef __ASSEMBLY__
 extern unsigned long m68k_machtype;
 #endif /* !__ASSEMBLY__ */
@@ -355,8 +359,6 @@ extern int m68k_is040or060;
      */
 
 #define NUM_MEMINFO    4
-#define CL_SIZE                256
-#define COMMAND_LINE_SIZE      CL_SIZE
 
 #ifndef __ASSEMBLY__
 struct mem_info {
index f799d95..e74f384 100644 (file)
@@ -4,7 +4,6 @@
 
 #define KERNBASE        0xE000000  /* First address the kernel will eventually be */
 #define LOAD_ADDR       0x4000      /* prom jumps to us here unless this is elf /boot */
-#define BI_START (KERNBASE + 0x3000) /* beginning of the bootinfo records */
 #define FC_CONTROL  3
 #define FC_SUPERD    5
 #define FC_CPU      7
index de91fa0..309d6e6 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/intersil.h>
 #include <asm/oplib.h>
 #include <asm/traps.h>
+#include <asm/irq.h>
 
 #define SUN3_INT_VECS 192
 
index e9eec3e..a194092 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index ad43480..fdbb60e 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            311
-#include <linux/err.h>
-
-/* 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)(-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); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-__asm__ __volatile__ ("trap  #0" \
-                      : "+d" (__res) ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall1(type,name,atype,a) \
-type name(atype a) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-register long __a __asm__ ("%d1") = (long)(a); \
-__asm__ __volatile__ ("trap  #0" \
-                     : "+d" (__res) \
-                     : "d" (__a)  ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall2(type,name,atype,a,btype,b) \
-type name(atype a,btype b) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-register long __a __asm__ ("%d1") = (long)(a); \
-register long __b __asm__ ("%d2") = (long)(b); \
-__asm__ __volatile__ ("trap  #0" \
-                     : "+d" (__res) \
-                      : "d" (__a), "d" (__b) \
-                    ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
-type name(atype a,btype b,ctype c) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-register long __a __asm__ ("%d1") = (long)(a); \
-register long __b __asm__ ("%d2") = (long)(b); \
-register long __c __asm__ ("%d3") = (long)(c); \
-__asm__ __volatile__ ("trap  #0" \
-                     : "+d" (__res) \
-                      : "d" (__a), "d" (__b), \
-                       "d" (__c) \
-                    ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
-type name (atype a, btype b, ctype c, dtype d) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-register long __a __asm__ ("%d1") = (long)(a); \
-register long __b __asm__ ("%d2") = (long)(b); \
-register long __c __asm__ ("%d3") = (long)(c); \
-register long __d __asm__ ("%d4") = (long)(d); \
-__asm__ __volatile__ ("trap  #0" \
-                      : "+d" (__res) \
-                      : "d" (__a), "d" (__b), \
-                       "d" (__c), "d" (__d)  \
-                    ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
-type name (atype a,btype b,ctype c,dtype d,etype e) \
-{ \
-register long __res __asm__ ("%d0") = __NR_##name; \
-register long __a __asm__ ("%d1") = (long)(a); \
-register long __b __asm__ ("%d2") = (long)(b); \
-register long __c __asm__ ("%d3") = (long)(c); \
-register long __d __asm__ ("%d4") = (long)(d); \
-register long __e __asm__ ("%d5") = (long)(e); \
-__asm__ __volatile__ ("trap  #0" \
-                     : "+d" (__res) \
-                     : "d" (__a), "d" (__b), \
-                       "d" (__c), "d" (__d), "d" (__e)  \
-                     ); \
-__syscall_return(type,__res); \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 45e7a2f..7b8f874 100644 (file)
@@ -86,5 +86,6 @@ extern void (*mach_disable_irq)(unsigned int);
 #define enable_irq(x)  do { } while (0)
 #define disable_irq(x) do { } while (0)
 #define disable_irq_nosync(x)  disable_irq(x)
+#define irq_canonicalize(irq)  (irq)
 
 #endif /* _M68K_IRQ_H_ */
diff --git a/include/asm-m68knommu/rtc.h b/include/asm-m68knommu/rtc.h
new file mode 100644 (file)
index 0000000..eaf18ec
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-m68k/rtc.h>
index d2b0fcc..fb86bb2 100644 (file)
@@ -1,5 +1,10 @@
+#ifdef __KERNEL__
+
 #include <asm-m68k/setup.h>
 
 /* We have a bigger command line buffer. */
 #undef COMMAND_LINE_SIZE
+
+#endif  /*  __KERNEL__  */
+
 #define COMMAND_LINE_SIZE      512
index 5d570ce..713a27f 100644 (file)
@@ -5,21 +5,17 @@ typedef int greg_t;
 #define NGREG 18
 typedef greg_t gregset_t[NGREG];
 
-#ifdef CONFIG_FPU
 typedef struct fpregset {
        int f_pcr;
        int f_psr;
        int f_fpiaddr;
        int f_fpregs[8][3];
 } fpregset_t;
-#endif
 
 struct mcontext {
        int version;
        gregset_t gregs;
-#ifdef CONFIG_FPU
        fpregset_t fpregs;
-#endif
 };
 
 #define MCONTEXT_VERSION 2
@@ -29,9 +25,7 @@ struct ucontext {
        struct ucontext  *uc_link;
        stack_t           uc_stack;
        struct mcontext   uc_mcontext;
-#ifdef CONFIG_FPU
        unsigned long     uc_filler[80];
-#endif
        sigset_t          uc_sigmask;   /* mask last for extensibility */
 };
 
index ebaf031..82e0319 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            311
-#include <linux/err.h>
-
-/* 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)(-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); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-#define _syscall0(type, name)                                                  \
-type name(void)                                                                        \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name)                                     \
-                       : "cc", "%d0");                                         \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
-
-#define _syscall1(type, name, atype, a)                                                \
-type name(atype a)                                                             \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %2, %%d1\n\t"                                   \
-                       "movel  %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name),                                    \
-                         "g" ((long)a)                                         \
-                       : "cc", "%d0", "%d1");                                  \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
-
-#define _syscall2(type, name, atype, a, btype, b)                              \
-type name(atype a, btype b)                                                    \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %3, %%d2\n\t"                                   \
-                       "movel  %2, %%d1\n\t"                                   \
-                       "movel  %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name),                                    \
-                         "a" ((long)a),                                        \
-                         "g" ((long)b)                                         \
-                       : "cc", "%d0", "%d1", "%d2");                           \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
-
-#define _syscall3(type, name, atype, a, btype, b, ctype, c)                    \
-type name(atype a, btype b, ctype c)                                           \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %4, %%d3\n\t"                                   \
-                       "movel  %3, %%d2\n\t"                                   \
-                       "movel  %2, %%d1\n\t"                                   \
-                       "movel  %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name),                                    \
-                         "a" ((long)a),                                        \
-                         "a" ((long)b),                                        \
-                         "g" ((long)c)                                         \
-                       : "cc", "%d0", "%d1", "%d2", "%d3");                    \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
-
-#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d)          \
-type name(atype a, btype b, ctype c, dtype d)                                  \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %5, %%d4\n\t"                                   \
-                       "movel  %4, %%d3\n\t"                                   \
-                       "movel  %3, %%d2\n\t"                                   \
-                       "movel  %2, %%d1\n\t"                                   \
-                       "movel  %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name),                                    \
-                         "a" ((long)a),                                        \
-                         "a" ((long)b),                                        \
-                         "a" ((long)c),                                        \
-                         "g" ((long)d)                                         \
-                       : "cc", "%d0", "%d1", "%d2", "%d3",                     \
-                         "%d4");                                               \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
-
-#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e)        \
-type name(atype a, btype b, ctype c, dtype d, etype e)                         \
-{                                                                              \
-  long __res;                                                                  \
-  __asm__ __volatile__ ("movel %6, %%d5\n\t"                                   \
-                       "movel  %5, %%d4\n\t"                                   \
-                       "movel  %4, %%d3\n\t"                                   \
-                       "movel  %3, %%d2\n\t"                                   \
-                       "movel  %2, %%d1\n\t"                                   \
-                       "movel  %1, %%d0\n\t"                                   \
-                       "trap   #0\n\t"                                         \
-                       "movel  %%d0, %0"                                       \
-                       : "=g" (__res)                                          \
-                       : "i" (__NR_##name),                                    \
-                         "a" ((long)a),                                        \
-                         "a" ((long)b),                                        \
-                         "a" ((long)c),                                        \
-                         "a" ((long)d),                                        \
-                         "g" ((long)e)                                         \
-                       : "cc", "%d0", "%d1", "%d2", "%d3",                     \
-                         "%d4", "%d5");                                        \
-  if ((unsigned long)(__res) >= (unsigned long)(-125)) {                               \
-    errno = -__res;                                                            \
-    __res = -1;                                                                        \
-  }                                                                            \
-  return (type)__res;                                                          \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 1e5ccda..8e321f5 100644 (file)
 #define  MACH_PHILIPS_NINO     0       /* Nino */
 #define  MACH_PHILIPS_VELO     1       /* Velo */
 #define  MACH_PHILIPS_JBS      2       /* JBS */
+#define  MACH_PHILIPS_STB810   3       /* STB810 */
 
 /*
  * Valid machtype for group SIBYTE
index 55a0152..432653d 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <linux/types.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
 
 #define COMPAT_USER_HZ 100
 
index 4328863..236d1a4 100644 (file)
@@ -63,9 +63,9 @@ dma_get_cache_alignment(void)
        return 128;
 }
 
-extern int dma_is_consistent(dma_addr_t dma_addr);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_addr);
 
-extern void dma_cache_sync(void *vaddr, size_t size,
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction);
 
 #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
index 927a216..47e5679 100644 (file)
@@ -88,7 +88,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -115,7 +115,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index c976bfa..f8c8182 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/uaccess.h>
 #include <asm/kmap_types.h>
 
 /* undef for production */
@@ -70,11 +71,16 @@ static inline void *kmap(struct page *page)
 
 static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
+       pagefault_disable();
        return page_address(page);
 }
 
-static inline void kunmap_atomic(void *kvaddr, enum km_type type) { }
-#define kmap_atomic_pfn(pfn, idx)      page_address(pfn_to_page(pfn))
+static inline void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+       pagefault_enable();
+}
+
+#define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx))
 
 #define kmap_atomic_to_page(ptr) virt_to_page(ptr)
 
index 0214abe..4df8d8b 100644 (file)
 
 #include <asm/io.h>
 
+/* i8259A PIC registers */
+#define PIC_MASTER_CMD         0x20
+#define PIC_MASTER_IMR         0x21
+#define PIC_MASTER_ISR         PIC_MASTER_CMD
+#define PIC_MASTER_POLL                PIC_MASTER_ISR
+#define PIC_MASTER_OCW3                PIC_MASTER_ISR
+#define PIC_SLAVE_CMD          0xa0
+#define PIC_SLAVE_IMR          0xa1
+
+/* i8259A PIC related value */
+#define PIC_CASCADE_IR         2
+#define MASTER_ICW4_DEFAULT    0x01
+#define SLAVE_ICW4_DEFAULT     0x01
+#define PIC_ICW4_AEOI          2
+
 extern spinlock_t i8259A_lock;
 
+extern void init_8259A(int auto_eoi);
+extern void enable_8259A_irq(unsigned int irq);
+extern void disable_8259A_irq(unsigned int irq);
+
 extern void init_i8259_irqs(void);
 
+#define I8259A_IRQ_BASE        0
+
 /*
  * Do the traditional i8259 interrupt polling thing.  This is for the few
  * cases where no better interrupt acknowledge method is available and we
@@ -35,15 +56,15 @@ static inline int i8259_irq(void)
        spin_lock(&i8259A_lock);
 
        /* Perform an interrupt acknowledge cycle on controller 1. */
-       outb(0x0C, 0x20);               /* prepare for poll */
-       irq = inb(0x20) & 7;
-       if (irq == 2) {
+       outb(0x0C, PIC_MASTER_CMD);             /* prepare for poll */
+       irq = inb(PIC_MASTER_CMD) & 7;
+       if (irq == PIC_CASCADE_IR) {
                /*
                 * Interrupt is cascaded so perform interrupt
                 * acknowledge on controller 2.
                 */
-               outb(0x0C, 0xA0);               /* prepare for poll */
-               irq = (inb(0xA0) & 7) + 8;
+               outb(0x0C, PIC_SLAVE_CMD);              /* prepare for poll */
+               irq = (inb(PIC_SLAVE_CMD) & 7) + 8;
        }
 
        if (unlikely(irq == 7)) {
@@ -54,14 +75,14 @@ static inline int i8259_irq(void)
                 * significant bit is not set then there is no valid
                 * interrupt.
                 */
-               outb(0x0B, 0x20);               /* ISR register */
-               if(~inb(0x20) & 0x80)
+               outb(0x0B, PIC_MASTER_ISR);             /* ISR register */
+               if(~inb(PIC_MASTER_ISR) & 0x80)
                        irq = -1;
        }
 
        spin_unlock(&i8259A_lock);
 
-       return irq;
+       return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq;
 }
 
 #endif /* _ASM_I8259_H */
index 806213c..25f0c3f 100644 (file)
@@ -10,8 +10,6 @@
 #ifndef __ASM_MACH_IP27_IRQ_H
 #define __ASM_MACH_IP27_IRQ_H
 
-#include <asm/sn/arch.h>
-
 /*
  * A hardwired interrupt number is completly stupid for this system - a
  * large configuration might have thousands if not tenthousands of
index a13b715..44790fd 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_MACH_TOPOLOGY_H
 #define _ASM_MACH_TOPOLOGY_H   1
 
-#include <asm/sn/arch.h>
 #include <asm/sn/hub.h>
 #include <asm/mmzone.h>
 
index c4d68be..7f0f120 100644 (file)
@@ -187,4 +187,10 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
+/* Chances are this interrupt is wired PC-style ...  */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       return channel ? 15 : 14;
+}
+
 #endif /* _ASM_PCI_H */
index d20f2e9..2fbd47e 100644 (file)
@@ -156,9 +156,9 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 #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))
-#define pte_offset_kernel(dir, address) \
-       ((pte_t *) pmd_page_vaddr(*(dir)) +  __pte_offset(address))
+       ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
+#define pte_offset_kernel(dir, address)                                        \
+       ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
 
 #define pte_offset_map(dir, address)                                    \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
index b9b1e86..a5b1871 100644 (file)
@@ -212,9 +212,9 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address)
 #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))
+       ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
 #define pte_offset_kernel(dir, address)                                        \
-       ((pte_t *) pmd_page_vaddr(*(dir)) +  __pte_offset(address))
+       ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
 #define pte_offset_map(dir, address)                                   \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_offset_map_nested(dir, address)                            \
index 30bf555..8a1f2b6 100644 (file)
@@ -82,6 +82,14 @@ struct pt_regs {
 
 extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
 
+extern NORET_TYPE void die(const char *, struct pt_regs *);
+
+static inline void die_if_kernel(const char *str, struct pt_regs *regs)
+{
+       if (unlikely(!user_mode(regs)))
+               die(str, regs);
+}
+
 #endif
 
 #endif /* _ASM_PTRACE_H */
index 737fa4a..70009a9 100644 (file)
@@ -1,8 +1,6 @@
-#ifdef __KERNEL__
 #ifndef _MIPS_SETUP_H
 #define _MIPS_SETUP_H
 
 #define COMMAND_LINE_SIZE      256
 
 #endif /* __SETUP_H */
-#endif /* __KERNEL__ */
index 51174af..da523de 100644 (file)
@@ -18,7 +18,6 @@
 #endif
 
 typedef u64    hubreg_t;
-typedef u64    nic_t;
 
 #define cputonasid(cpu)                        (cpu_data[(cpu)].p_nasid)
 #define cputoslice(cpu)                        (cpu_data[(cpu)].p_slice)
index 15d70ca..82aeb9e 100644 (file)
@@ -61,6 +61,8 @@
 #endif /* CONFIG_SGI_IP35 */
 #endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
 
+typedef u64  nic_t;
+
 #define KLCFGINFO_MAGIC        0xbeedbabe
 
 typedef s32 klconf_off_t;
index 9428057..5e1289c 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/dsp.h>
-#include <asm/ptrace.h>
 #include <asm/war.h>
 
 
@@ -336,14 +335,6 @@ extern void *set_except_vector(int n, void *addr);
 extern unsigned long ebase;
 extern void per_cpu_trap_init(void);
 
-extern NORET_TYPE void die(const char *, struct pt_regs *);
-
-static inline void die_if_kernel(const char *str, struct pt_regs *regs)
-{
-       if (unlikely(!user_mode(regs)))
-               die(str, regs);
-}
-
 extern int stop_a_enabled;
 
 /*
index b62ec7c..0bbe07b 100644 (file)
@@ -30,6 +30,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR           0              /* Interrupt character [ISIG].  */
 #define VQUIT           1              /* Quit character [ISIG].  */
index ec56aa5..696cff3 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-       register unsigned long __a3 asm("$7"); \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %2\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "=r" (__a3) \
-       : "i" (__NR_##name) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-/*
- * DANGER: This macro isn't usable for the pipe(2) call
- * which has a unusual return convention.
- */
-#define _syscall1(type,name,atype,a) \
-type name(atype a) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a3 asm("$7"); \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %3\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "=r" (__a3) \
-       : "r" (__a0), "i" (__NR_##name) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#define _syscall2(type,name,atype,a,btype,b) \
-type name(atype a, btype b) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a3 asm("$7"); \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %4\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "=r" (__a3) \
-       : "r" (__a0), "r" (__a1), "i" (__NR_##name) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
-type name(atype a, btype b, ctype c) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7"); \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %5\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "=r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
-type name(atype a, btype b, ctype c, dtype d) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7") = (unsigned long) d; \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %5\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "+r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#if (_MIPS_SIM == _MIPS_SIM_ABI32)
-
-/*
- * Using those means your brain needs more than an oil change ;-)
- */
-
-#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
-type name(atype a, btype b, ctype c, dtype d, etype e) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7") = (unsigned long) d; \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "lw\t$2, %6\n\t" \
-       "subu\t$29, 32\n\t" \
-       "sw\t$2, 16($29)\n\t" \
-       "li\t$2, %5\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       "addiu\t$29, 32\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "+r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
-         "m" ((unsigned long)e) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
-type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7") = (unsigned long) d; \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "lw\t$2, %6\n\t" \
-       "lw\t$8, %7\n\t" \
-       "subu\t$29, 32\n\t" \
-       "sw\t$2, 16($29)\n\t" \
-       "sw\t$8, 20($29)\n\t" \
-       "li\t$2, %5\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       "addiu\t$29, 32\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "+r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
-         "m" ((unsigned long)e), "m" ((unsigned long)f) \
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#endif /* (_MIPS_SIM == _MIPS_SIM_ABI32) */
-
-#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
-
-#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
-type name (atype a,btype b,ctype c,dtype d,etype e) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7") = (unsigned long) d; \
-       register unsigned long __a4 asm("$8") = (unsigned long) e; \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %6\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "+r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), "i" (__NR_##name) \
-       : "$2", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
-type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
-{ \
-       register unsigned long __a0 asm("$4") = (unsigned long) a; \
-       register unsigned long __a1 asm("$5") = (unsigned long) b; \
-       register unsigned long __a2 asm("$6") = (unsigned long) c; \
-       register unsigned long __a3 asm("$7") = (unsigned long) d; \
-       register unsigned long __a4 asm("$8") = (unsigned long) e; \
-       register unsigned long __a5 asm("$9") = (unsigned long) f; \
-       unsigned long __v0; \
-       \
-       __asm__ volatile ( \
-       ".set\tnoreorder\n\t" \
-       "li\t$2, %7\t\t\t# " #name "\n\t" \
-       "syscall\n\t" \
-       "move\t%0, $2\n\t" \
-       ".set\treorder" \
-       : "=&r" (__v0), "+r" (__a3) \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), "r" (__a5), \
-         "i" (__NR_##name) \
-       : "$2", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
-         "memory"); \
-       \
-       if (__a3 == 0) \
-               return (type) __v0; \
-       errno = __v0; \
-       return (type) -1; \
-}
-
-#endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */
-
-
 #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 3ac146c..13a3502 100644 (file)
@@ -76,7 +76,7 @@
 /*
  * But the RM200C seems to have been shipped only with V2.0 R4600s
  */
-#ifdef CONFIG_SNI_RM200_PCI
+#ifdef CONFIG_SNI_RM
 
 #define R4600_V2_HIT_CACHEOP_WAR       1
 
index 1e387e1..66f0b40 100644 (file)
@@ -191,13 +191,13 @@ dma_get_cache_alignment(void)
 }
 
 static inline int
-dma_is_consistent(dma_addr_t dma_addr)
+dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
 {
        return (hppa_dma_ops->dma_sync_single_for_cpu == NULL);
 }
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        if(hppa_dma_ops->dma_sync_single_for_cpu)
index d84bbb2..dbee6e6 100644 (file)
@@ -21,7 +21,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -33,7 +33,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index 372b634..a46e299 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 1e63738..703970f 100644 (file)
@@ -17,7 +17,6 @@ header-y += ipc.h
 header-y += poll.h
 header-y += shmparam.h
 header-y += sockios.h
-header-y += spu_info.h
 header-y += ucontext.h
 header-y += ioctl.h
 header-y += linkage.h
@@ -37,6 +36,7 @@ unifdef-y += posix_types.h
 unifdef-y += ptrace.h
 unifdef-y += seccomp.h
 unifdef-y += signal.h
+unifdef-y += spu_info.h
 unifdef-y += termios.h
 unifdef-y += types.h
 unifdef-y += unistd.h
index c341063..8f757f6 100644 (file)
@@ -190,7 +190,8 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr)
  * Return the zero-based bit position (LE, not IBM bit numbering) of
  * the most significant 1-bit in a double word.
  */
-static __inline__ int __ilog2(unsigned long x)
+static __inline__ __attribute__((const))
+int __ilog2(unsigned long x)
 {
        int lz;
 
@@ -198,6 +199,24 @@ static __inline__ int __ilog2(unsigned long x)
        return BITS_PER_LONG - 1 - lz;
 }
 
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+       int bit;
+       asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n));
+       return 31 - bit;
+}
+
+#ifdef __powerpc64__
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+       int bit;
+       asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n));
+       return 63 - bit;
+}
+#endif
+
 /*
  * Determines the bit position of the least significant 0 bit in the
  * specified double word. The returned bit position will be
index 978b2c7..7095688 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-struct bug_entry {
-       unsigned long   bug_addr;
-       long            line;
-       const char      *file;
-       const char      *function;
-};
-
-struct bug_entry *find_bug(unsigned long bugaddr);
-
-/*
- * If this bit is set in the line number it means that the trap
- * is for WARN_ON rather than BUG or BUG_ON.
- */
-#define BUG_WARNING_TRAP       0x1000000
-
 #ifdef CONFIG_BUG
 
+/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
+   sizeof(struct bug_entry), respectively */
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_BUG_ENTRY                                \
+       ".section __bug_table,\"a\"\n"          \
+       "2:\t" PPC_LONG "1b, %0\n"              \
+       "\t.short %1, %2\n"                     \
+       ".org 2b+%3\n"                          \
+       ".previous\n"
+#else
+#define _EMIT_BUG_ENTRY                                \
+       ".section __bug_table,\"a\"\n"          \
+       "2:\t" PPC_LONG "1b\n"                  \
+       "\t.short %2\n"                         \
+       ".org 2b+%3\n"                          \
+       ".previous\n"
+#endif
+
 /*
  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
  * optimisations. However depending on the complexity of the condition
  * some compiler versions may not produce optimal results.
  */
 
-#define BUG() do {                                                      \
-       __asm__ __volatile__(                                            \
-               "1:     twi 31,0,0\n"                                    \
-               ".section __bug_table,\"a\"\n"                           \
-               "\t"PPC_LONG"   1b,%0,%1,%2\n"                           \
-               ".previous"                                              \
-               : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+#define BUG() do {                                             \
+       __asm__ __volatile__(                                   \
+               "1:     twi 31,0,0\n"                           \
+               _EMIT_BUG_ENTRY                                 \
+               : : "i" (__FILE__), "i" (__LINE__),             \
+                   "i" (0), "i"  (sizeof(struct bug_entry)));  \
+       for(;;) ;                                               \
 } while (0)
 
 #define BUG_ON(x) do {                                         \
@@ -51,23 +54,21 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                        BUG();                                  \
        } else {                                                \
                __asm__ __volatile__(                           \
-               "1:     "PPC_TLNEI"     %0,0\n"                 \
-               ".section __bug_table,\"a\"\n"                  \
-               "\t"PPC_LONG"   1b,%1,%2,%3\n"                  \
-               ".previous"                                     \
-               : : "r" ((long)(x)), "i" (__LINE__),            \
-                   "i" (__FILE__), "i" (__FUNCTION__));        \
+               "1:     "PPC_TLNEI"     %4,0\n"                 \
+               _EMIT_BUG_ENTRY                                 \
+               : : "i" (__FILE__), "i" (__LINE__), "i" (0),    \
+                 "i" (sizeof(struct bug_entry)),               \
+                 "r" ((long)(x)));                             \
        }                                                       \
 } while (0)
 
 #define __WARN() do {                                          \
        __asm__ __volatile__(                                   \
                "1:     twi 31,0,0\n"                           \
-               ".section __bug_table,\"a\"\n"                  \
-               "\t"PPC_LONG"   1b,%0,%1,%2\n"                  \
-               ".previous"                                     \
-               : : "i" (__LINE__ + BUG_WARNING_TRAP),          \
-                   "i" (__FILE__), "i" (__FUNCTION__));        \
+               _EMIT_BUG_ENTRY                                 \
+               : : "i" (__FILE__), "i" (__LINE__),             \
+                 "i" (BUGFLAG_WARNING),                        \
+                 "i" (sizeof(struct bug_entry)));              \
 } while (0)
 
 #define WARN_ON(x) ({                                          \
@@ -77,13 +78,12 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                        __WARN();                               \
        } else {                                                \
                __asm__ __volatile__(                           \
-               "1:     "PPC_TLNEI"     %0,0\n"                 \
-               ".section __bug_table,\"a\"\n"                  \
-               "\t"PPC_LONG"   1b,%1,%2,%3\n"                  \
-               ".previous"                                     \
-               : : "r" (__ret_warn_on),                        \
-                   "i" (__LINE__ + BUG_WARNING_TRAP),          \
-                   "i" (__FILE__), "i" (__FUNCTION__));        \
+               "1:     "PPC_TLNEI"     %4,0\n"                 \
+               _EMIT_BUG_ENTRY                                 \
+               : : "i" (__FILE__), "i" (__LINE__),             \
+                 "i" (BUGFLAG_WARNING),                        \
+                 "i" (sizeof(struct bug_entry)),               \
+                 "r" (__ret_warn_on));                         \
        }                                                       \
        unlikely(__ret_warn_on);                                \
 })
index 6fe5c9d..7384b80 100644 (file)
@@ -126,6 +126,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_NODSISRALIGN           ASM_CONST(0x0000000000100000)
 #define CPU_FTR_PPC_LE                 ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE                        ASM_CONST(0x0000000000400000)
+#define CPU_FTR_FPU_UNAVAILABLE                ASM_CONST(0x0000000000800000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -152,6 +153,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_PURR                   LONG_ASM_CONST(0x0000400000000000)
 #define CPU_FTR_CELL_TB_BUG            LONG_ASM_CONST(0x0000800000000000)
 #define CPU_FTR_SPURR                  LONG_ASM_CONST(0x0001000000000000)
+#define CPU_FTR_DSCR                   LONG_ASM_CONST(0x0002000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -295,6 +297,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTRS_E300  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
            CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_COMMON)
+#define CPU_FTRS_E300C2        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
 #define CPU_FTRS_CLASSIC32     (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
            CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_8XX   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
@@ -330,13 +335,14 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-           CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+           CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+           CPU_FTR_DSCR)
 #define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \
-           CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+           CPU_FTR_SPURR | CPU_FTR_REAL_LE | CPU_FTR_DSCR)
 #define CPU_FTRS_CELL  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -364,7 +370,8 @@ enum {
            CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
            CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
            CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
-           CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 |
+           CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
+           CPU_FTRS_CLASSIC32 |
 #else
            CPU_FTRS_GENERIC_32 |
 #endif
@@ -403,7 +410,8 @@ enum {
            CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
            CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
            CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
-           CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 &
+           CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
+           CPU_FTRS_CLASSIC32 &
 #else
            CPU_FTRS_GENERIC_32 &
 #endif
index fd4a5f5..d7a1bc1 100644 (file)
@@ -20,8 +20,7 @@
 #ifndef _ASM_POWERPC_DCR_NATIVE_H
 #define _ASM_POWERPC_DCR_NATIVE_H
 #ifdef __KERNEL__
-
-#include <asm/reg.h>
+#ifndef __ASSEMBLY__
 
 typedef struct {} dcr_host_t;
 
@@ -32,7 +31,41 @@ typedef struct {} dcr_host_t;
 #define dcr_read(host, dcr_n)          mfdcr(dcr_n)
 #define dcr_write(host, dcr_n, value)  mtdcr(dcr_n, value)
 
+/* Device Control Registers */
+void __mtdcr(int reg, unsigned int val);
+unsigned int __mfdcr(int reg);
+#define mfdcr(rn)                                              \
+       ({unsigned int rval;                                    \
+       if (__builtin_constant_p(rn))                           \
+               asm volatile("mfdcr %0," __stringify(rn)        \
+                             : "=r" (rval));                   \
+       else                                                    \
+               rval = __mfdcr(rn);                             \
+       rval;})
+
+#define mtdcr(rn, v)                                           \
+do {                                                           \
+       if (__builtin_constant_p(rn))                           \
+               asm volatile("mtdcr " __stringify(rn) ",%0"     \
+                             : : "r" (v));                     \
+       else                                                    \
+               __mtdcr(rn, v);                                 \
+} while (0)
+
+/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
+#define mfdcri(base, reg)                      \
+({                                             \
+       mtdcr(base ## _CFGADDR, base ## _ ## reg);      \
+       mfdcr(base ## _CFGDATA);                        \
+})
+
+#define mtdcri(base, reg, data)                        \
+do {                                           \
+       mtdcr(base ## _CFGADDR, base ## _ ## reg);      \
+       mtdcr(base ## _CFGDATA, data);          \
+} while (0)
 
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DCR_NATIVE_H */
 
index 473f2c7..b66c5e6 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef _ASM_POWERPC_DCR_H
 #define _ASM_POWERPC_DCR_H
 #ifdef __KERNEL__
+#ifdef CONFIG_PPC_DCR
 
 #ifdef CONFIG_PPC_DCR_NATIVE
 #include <asm/dcr-native.h>
@@ -38,5 +39,6 @@ extern unsigned int dcr_resource_len(struct device_node *np,
                                     unsigned int index);
 #endif /* CONFIG_PPC_MERGE */
 
+#endif /* CONFIG_PPC_DCR */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DCR_H */
index 7e38b5f..7c7de87 100644 (file)
@@ -342,9 +342,9 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 #ifdef CONFIG_NOT_COHERENT_CACHE
-#define dma_is_consistent(d)   (0)
+#define dma_is_consistent(d, h)        (0)
 #else
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 #endif
 
 static inline int dma_get_cache_alignment(void)
@@ -378,7 +378,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
        dma_sync_single_for_device(dev, dma_handle, offset + size, direction);
 }
 
-static inline void dma_cache_sync(void *vaddr, size_t size,
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
index b543664..d36426c 100644 (file)
@@ -124,12 +124,10 @@ typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
 # define ELF_DATA      ELFDATA2MSB
   typedef elf_greg_t64 elf_greg_t;
   typedef elf_gregset_t64 elf_gregset_t;
-# define elf_addr_t unsigned long
 #else
   /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
   typedef elf_greg_t32 elf_greg_t;
   typedef elf_gregset_t32 elf_gregset_t;
-# define elf_addr_t __u32
 #endif /* ELF_ARCH */
 
 /* Floating point registers */
index 936422e..3f3673f 100644 (file)
@@ -43,7 +43,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index d604863..9e4dd98 100644 (file)
@@ -107,25 +107,6 @@ static inline void local_irq_save_ptr(unsigned long *flags)
 
 #endif /* CONFIG_PPC64 */
 
-#define mask_irq(irq)                                          \
-       ({                                                      \
-               irq_desc_t *desc = get_irq_desc(irq);           \
-               if (desc->chip && desc->chip->disable)  \
-                       desc->chip->disable(irq);               \
-       })
-#define unmask_irq(irq)                                                \
-       ({                                                      \
-               irq_desc_t *desc = get_irq_desc(irq);           \
-               if (desc->chip && desc->chip->enable)   \
-                       desc->chip->enable(irq);                \
-       })
-#define ack_irq(irq)                                           \
-       ({                                                      \
-               irq_desc_t *desc = get_irq_desc(irq);           \
-               if (desc->chip && desc->chip->ack)      \
-                       desc->chip->ack(irq);           \
-       })
-
 /*
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
index 584fabf..e5f14b1 100644 (file)
@@ -46,8 +46,6 @@ struct mod_arch_specific {
        unsigned int num_bugs;
 };
 
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
 /*
  * Select ELF headers.
  * Make empty section for module_frob_arch_sections to expand.
index 2677bad..07f6d3c 100644 (file)
@@ -26,15 +26,7 @@ extern void clear_pages(void *page, int order);
 static inline void clear_page(void *page) { clear_pages(page, 0); }
 extern void copy_page(void *to, void *from);
 
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
-       int lz;
-
-       size = (size-1) >> PAGE_SHIFT;
-       asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
-       return 32 - lz;
-}
+#include <asm-generic/page.h>
 
 #endif /* __ASSEMBLY__ */
 
index 7bb7f90..cb02c9d 100644 (file)
@@ -31,12 +31,12 @@ struct pci_controller {
        int last_busno;
 
        void __iomem *io_base_virt;
-       unsigned long io_base_phys;
+       resource_size_t io_base_phys;
 
        /* Some machines have a non 1:1 mapping of
         * the PCI memory space in the CPU bus space
         */
-       unsigned long pci_mem_offset;
+       resource_size_t pci_mem_offset;
        unsigned long pci_io_size;
 
        struct pci_ops *ops;
index 16f1331..ac656ee 100644 (file)
@@ -143,8 +143,13 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
 #define HAVE_PCI_MMAP  1
 
-#ifdef CONFIG_PPC64
-/* pci_unmap_{single,page} is not a nop, thus... */
+#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE)
+/*
+ * For 64-bit kernels, pci_unmap_{single,page} is not a nop.
+ * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and
+ * so on are not nops.
+ * and thus...
+ */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
        dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
@@ -158,6 +163,20 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
        (((PTR)->LEN_NAME) = (VAL))
 
+#else /* 32-bit && coherent */
+
+/* pci_unmap_{page,single} is a nop so... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME)         (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)        do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)           (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
+
+#endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */
+
+#ifdef CONFIG_PPC64
+
 /* The PCI address space does not equal the physical memory address
  * space (we have an IOMMU).  The IDE and SCSI device layers use
  * this boolean for bounce buffer decisions.
@@ -172,16 +191,8 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
  */
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)         (0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)        do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)           (0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
-
 #endif /* CONFIG_PPC64 */
-       
+
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
                        struct pci_bus_region *region,
                        struct resource *res);
index ae63db7..b0830db 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 
-extern kmem_cache_t *pgtable_cache[];
+extern struct kmem_cache *pgtable_cache[];
 
 #ifdef CONFIG_PPC_64K_PAGES
 #define PTE_CACHE_NUM  0
index 6faae7b..a3631b1 100644 (file)
 
 /* Special Purpose Registers (SPRNs)*/
 #define SPRN_CTR       0x009   /* Count Register */
+#define SPRN_DSCR      0x11
 #define SPRN_CTRLF     0x088
 #define SPRN_CTRLT     0x098
 #define   CTRL_CT      0xc0000000      /* current thread */
 #define SPRN_TBRU      0x10D   /* Time Base Read Upper Register (user, R/O) */
 #define SPRN_TBWL      0x11C   /* Time Base Lower Register (super, R/W) */
 #define SPRN_TBWU      0x11D   /* Time Base Upper Register (super, R/W) */
+#define SPRN_SPURR     0x134   /* Scaled PURR */
 #define SPRN_HIOR      0x137   /* 970 Hypervisor interrupt offset */
 #define SPRN_DBAT0L    0x219   /* Data BAT 0 Lower Register */
 #define SPRN_DBAT0U    0x218   /* Data BAT 0 Upper Register */
index 5a0c136..8eaa7b2 100644 (file)
@@ -159,6 +159,7 @@ extern struct rtas_t rtas;
 
 extern void enter_rtas(unsigned long);
 extern int rtas_token(const char *service);
+extern int rtas_service_present(const char *service);
 extern int rtas_call(int token, int, int, int *, ...);
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(void);
@@ -221,8 +222,6 @@ extern int rtas_get_error_log_max(void);
 extern spinlock_t rtas_data_buf_lock;
 extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
 
-extern void rtas_stop_self(void);
-
 /* RMO buffer reserved for user-space RTAS use */
 extern unsigned long rtas_rmo_buf;
 
index 3d9740a..817fac0 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef _ASM_POWERPC_SETUP_H
 #define _ASM_POWERPC_SETUP_H
 
-#ifdef __KERNEL__
-
 #define COMMAND_LINE_SIZE      512
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SETUP_H */
index 6d533b0..5e79198 100644 (file)
@@ -30,6 +30,19 @@ struct termios {
        speed_t c_ospeed;               /* output speed */
 };
 
+/* For PowerPC the termios and ktermios are the same */
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_cc[NCCS];                /* control characters */
+       cc_t c_line;                    /* line discipline (== c_cc[19]) */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR           0
 #define VQUIT           1
index 50c0140..6610495 100644 (file)
@@ -66,6 +66,7 @@ static inline int pcibus_to_node(struct pci_bus *bus)
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_NEWIDLE    \
                                | SD_WAKE_IDLE          \
+                               | SD_SERIALIZE          \
                                | SD_WAKE_BALANCE,      \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
index 04b6c17..0ae954e 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-/* On powerpc a system call basically clobbers the same registers like a
- * function call, with the exception of LR (which is needed for the
- * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
- * an error return status).
- */
-
-#define __syscall_nr(nr, type, name, args...)                          \
-       unsigned long __sc_ret, __sc_err;                               \
-       {                                                               \
-               register unsigned long __sc_0  __asm__ ("r0");          \
-               register unsigned long __sc_3  __asm__ ("r3");          \
-               register unsigned long __sc_4  __asm__ ("r4");          \
-               register unsigned long __sc_5  __asm__ ("r5");          \
-               register unsigned long __sc_6  __asm__ ("r6");          \
-               register unsigned long __sc_7  __asm__ ("r7");          \
-               register unsigned long __sc_8  __asm__ ("r8");          \
-                                                                       \
-               __sc_loadargs_##nr(name, args);                         \
-               __asm__ __volatile__                                    \
-                       ("sc           \n\t"                            \
-                        "mfcr %0      "                                \
-                       : "=&r" (__sc_0),                               \
-                         "=&r" (__sc_3),  "=&r" (__sc_4),              \
-                         "=&r" (__sc_5),  "=&r" (__sc_6),              \
-                         "=&r" (__sc_7),  "=&r" (__sc_8)               \
-                       : __sc_asm_input_##nr                           \
-                       : "cr0", "ctr", "memory",                       \
-                         "r9", "r10","r11", "r12");                    \
-               __sc_ret = __sc_3;                                      \
-               __sc_err = __sc_0;                                      \
-       }                                                               \
-       if (__sc_err & 0x10000000)                                      \
-       {                                                               \
-               errno = __sc_ret;                                       \
-               __sc_ret = -1;                                          \
-       }                                                               \
-       return (type) __sc_ret
-
-#define __sc_loadargs_0(name, dummy...)                                        \
-       __sc_0 = __NR_##name
-#define __sc_loadargs_1(name, arg1)                                    \
-       __sc_loadargs_0(name);                                          \
-       __sc_3 = (unsigned long) (arg1)
-#define __sc_loadargs_2(name, arg1, arg2)                              \
-       __sc_loadargs_1(name, arg1);                                    \
-       __sc_4 = (unsigned long) (arg2)
-#define __sc_loadargs_3(name, arg1, arg2, arg3)                                \
-       __sc_loadargs_2(name, arg1, arg2);                              \
-       __sc_5 = (unsigned long) (arg3)
-#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4)                  \
-       __sc_loadargs_3(name, arg1, arg2, arg3);                        \
-       __sc_6 = (unsigned long) (arg4)
-#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5)            \
-       __sc_loadargs_4(name, arg1, arg2, arg3, arg4);                  \
-       __sc_7 = (unsigned long) (arg5)
-#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6)      \
-       __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5);            \
-       __sc_8 = (unsigned long) (arg6)
-
-#define __sc_asm_input_0 "0" (__sc_0)
-#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
-#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
-#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
-#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
-#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
-#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8)
-
-#define _syscall0(type,name)                                           \
-type name(void)                                                                \
-{                                                                      \
-       __syscall_nr(0, type, name);                                    \
-}
-
-#define _syscall1(type,name,type1,arg1)                                        \
-type name(type1 arg1)                                                  \
-{                                                                      \
-       __syscall_nr(1, type, name, arg1);                              \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)                     \
-type name(type1 arg1, type2 arg2)                                      \
-{                                                                      \
-       __syscall_nr(2, type, name, arg1, arg2);                        \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)          \
-type name(type1 arg1, type2 arg2, type3 arg3)                          \
-{                                                                      \
-       __syscall_nr(3, type, name, arg1, arg2, arg3);                  \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4)              \
-{                                                                      \
-       __syscall_nr(4, type, name, arg1, arg2, arg3, arg4);            \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)  \
-{                                                                      \
-       __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5);      \
-}
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
-{                                                                      \
-       __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
-}
-
-
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/linkage.h>
index 1d2c4ef..f7b21ee 100644 (file)
@@ -79,7 +79,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
        unsigned long vaddr;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-       inc_preempt_count();
+       pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
@@ -101,8 +101,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
        unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
 
        if (vaddr < KMAP_FIX_BEGIN) { // FIXME
-               dec_preempt_count();
-               preempt_check_resched();
+               pagefault_enable();
                return;
        }
 
@@ -115,8 +114,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
        pte_clear(&init_mm, vaddr, kmap_pte+idx);
        flush_tlb_page(NULL, vaddr);
 #endif
-       dec_preempt_count();
-       preempt_check_resched();
+       pagefault_enable();
 }
 
 static inline struct page *kmap_atomic_to_page(void *ptr)
index 6c955d0..4d35b84 100644 (file)
@@ -20,8 +20,8 @@ extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
 extern struct pci_controller* pcibios_alloc_controller(void);
 
 /* Helper function for setting up resources */
-extern void pci_init_resource(struct resource *res, unsigned long start,
-                             unsigned long end, int flags, char *name);
+extern void pci_init_resource(struct resource *res, resource_size_t start,
+                             resource_size_t end, int flags, char *name);
 
 /* Get the PCI host controller for a bus */
 extern struct pci_controller* pci_bus_to_hose(int bus);
@@ -50,12 +50,12 @@ struct pci_controller {
        int bus_offset;
 
        void __iomem *io_base_virt;
-       unsigned long io_base_phys;
+       resource_size_t io_base_phys;
 
        /* Some machines (PReP) have a non 1:1 mapping of
         * the PCI memory space in the CPU bus space
         */
-       unsigned long pci_mem_offset;
+       resource_size_t pci_mem_offset;
 
        struct pci_ops *ops;
        volatile unsigned int __iomem *cfg_addr;
index 11ffaaa..9d16202 100644 (file)
@@ -61,6 +61,27 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
  */
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
+#ifdef CONFIG_NOT_COHERENT_CACHE
+/*
+ * pci_unmap_{page,single} are NOPs but pci_dma_sync_single_for_cpu()
+ * and so on are not, so...
+ */
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
+       dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
+       __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)                 \
+       ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)                \
+       (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)                   \
+       ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
+       (((PTR)->LEN_NAME) = (VAL))
+
+#else /* coherent */
+
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
@@ -69,6 +90,8 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
index 602fbad..a263fc1 100644 (file)
@@ -9,41 +9,9 @@
 #ifndef __ASM_PPC_REG_BOOKE_H__
 #define __ASM_PPC_REG_BOOKE_H__
 
-#ifndef __ASSEMBLY__
-/* Device Control Registers */
-void __mtdcr(int reg, unsigned int val);
-unsigned int __mfdcr(int reg);
-#define mfdcr(rn)                                              \
-       ({unsigned int rval;                                    \
-       if (__builtin_constant_p(rn))                           \
-               asm volatile("mfdcr %0," __stringify(rn)        \
-                             : "=r" (rval));                   \
-       else                                                    \
-               rval = __mfdcr(rn);                             \
-       rval;})
-
-#define mtdcr(rn, v)                                           \
-do {                                                           \
-       if (__builtin_constant_p(rn))                           \
-               asm volatile("mtdcr " __stringify(rn) ",%0"     \
-                             : : "r" (v));                     \
-       else                                                    \
-               __mtdcr(rn, v);                                 \
-} while (0)
-
-/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
-#define mfdcri(base, reg)                      \
-({                                             \
-       mtdcr(base ## _CFGADDR, base ## _ ## reg);      \
-       mfdcr(base ## _CFGDATA);                        \
-})
-
-#define mtdcri(base, reg, data)                        \
-do {                                           \
-       mtdcr(base ## _CFGADDR, base ## _ ## reg);      \
-       mtdcr(base ## _CFGDATA, data);          \
-} while (0)
+#include <asm/dcr.h>
 
+#ifndef __ASSEMBLY__
 /* Performance Monitor Registers */
 #define mfpmr(rn)      ({unsigned int rval; \
                        asm volatile("mfpmr %0," __stringify(rn) \
index c042f95..604f68f 100644 (file)
@@ -69,11 +69,13 @@ typedef struct dasd_information2_t {
  * 0x01: readonly (ro)
  * 0x02: use diag discipline (diag)
  * 0x04: set the device initially online (internal use only)
+ * 0x08: enable ERP related logging
  */
 #define DASD_FEATURE_DEFAULT        0x00
 #define DASD_FEATURE_READONLY       0x01
 #define DASD_FEATURE_USEDIAG        0x02
 #define DASD_FEATURE_INITIAL_ONLINE  0x04
+#define DASD_FEATURE_ERPLOG         0x08
 
 #define DASD_PARTN_BITS 2
 
index 363ea76..05ea6f1 100644 (file)
@@ -127,6 +127,26 @@ page_get_storage_key(unsigned long addr)
        return skey;
 }
 
+extern unsigned long max_pfn;
+
+static inline int pfn_valid(unsigned long pfn)
+{
+       unsigned long dummy;
+       int ccode;
+
+       if (pfn >= max_pfn)
+               return 0;
+
+       asm volatile(
+               "       lra     %0,0(%2)\n"
+               "       ipm     %1\n"
+               "       srl     %1,28\n"
+               : "=d" (dummy), "=d" (ccode)
+               : "a" (pfn << PAGE_SHIFT)
+               : "cc");
+       return !ccode;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
@@ -138,8 +158,6 @@ page_get_storage_key(unsigned long addr)
 #define __va(x)                 (void *)(unsigned long)(x)
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
-
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
index 28619de..0707a7e 100644 (file)
@@ -25,8 +25,11 @@ extern void diag10(unsigned long addr);
  * Page allocation orders.
  */
 #ifndef __s390x__
+# define PTE_ALLOC_ORDER       0
+# define PMD_ALLOC_ORDER       0
 # define PGD_ALLOC_ORDER       1
 #else /* __s390x__ */
+# define PTE_ALLOC_ORDER       0
 # define PMD_ALLOC_ORDER       2
 # define PGD_ALLOC_ORDER       2
 #endif /* __s390x__ */
index 2d968a6..ae61aca 100644 (file)
@@ -107,23 +107,25 @@ extern char empty_zero_page[PAGE_SIZE];
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
+extern unsigned long vmalloc_end;
 #define VMALLOC_OFFSET  (8*1024*1024)
 #define VMALLOC_START   (((unsigned long) high_memory + VMALLOC_OFFSET) \
                         & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END    vmalloc_end
 
 /*
  * We need some free virtual space to be able to do vmalloc.
  * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc
  * area. On a machine with 2GB memory we make sure that we
  * have at least 128MB free space for vmalloc. On a machine
- * with 4TB we make sure we have at least 1GB.
+ * with 4TB we make sure we have at least 128GB.
  */
 #ifndef __s390x__
 #define VMALLOC_MIN_SIZE       0x8000000UL
-#define VMALLOC_END            0x80000000UL
+#define VMALLOC_END_INIT       0x80000000UL
 #else /* __s390x__ */
-#define VMALLOC_MIN_SIZE       0x40000000UL
-#define VMALLOC_END            0x40000000000UL
+#define VMALLOC_MIN_SIZE       0x2000000000UL
+#define VMALLOC_END_INIT       0x40000000000UL
 #endif /* __s390x__ */
 
 /*
@@ -815,11 +817,17 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 
 #define kern_addr_valid(addr)   (1)
 
+extern int add_shared_memory(unsigned long start, unsigned long size);
+extern int remove_shared_memory(unsigned long start, unsigned long size);
+
 /*
  * No page table caches to initialise
  */
 #define pgtable_cache_init()   do { } while (0)
 
+#define __HAVE_ARCH_MEMMAP_INIT
+extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
+
 #define __HAVE_ARCH_PTEP_ESTABLISH
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
index 7664bac..9574fe8 100644 (file)
@@ -8,12 +8,13 @@
 #ifndef _ASM_S390_SETUP_H
 #define _ASM_S390_SETUP_H
 
+#define COMMAND_LINE_SIZE      896
+
 #ifdef __KERNEL__
 
 #include <asm/types.h>
 
 #define PARMAREA               0x10400
-#define COMMAND_LINE_SIZE      896
 #define MEMORY_CHUNKS          16      /* max 0x7fff */
 #define IPL_PARMBLOCK_ORIGIN   0x2000
 
index eb3f8bf..585c78a 100644 (file)
@@ -25,6 +25,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 71d3c21..fb6fef9 100644 (file)
 
 #ifdef __KERNEL__
 
-#include <linux/err.h>
-
-#define __syscall_return(type, res)                         \
-do {                                                        \
-       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
-               errno = -(res);                              \
-               res = -1;                                    \
-       }                                                    \
-       return (type) (res);                                 \
-} while (0)
-
-#define _svc_clobber "1", "cc", "memory"
-
-#define _syscall0(type,name)                                   \
-type name(void) {                                              \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name)                             \
-               : _svc_clobber);                                \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
-#define _syscall1(type,name,type1,arg1)                                \
-type name(type1 arg1) {                                                \
-       register type1 __arg1 asm("2") = arg1;                  \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name),                            \
-                 "0" (__arg1)                                  \
-               : _svc_clobber);                                \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2)             \
-type name(type1 arg1, type2 arg2) {                            \
-       register type1 __arg1 asm("2") = arg1;                  \
-       register type2 __arg2 asm("3") = arg2;                  \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name),                            \
-                 "0" (__arg1),                                 \
-                 "d" (__arg2)                                  \
-               : _svc_clobber );                               \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)  \
-type name(type1 arg1, type2 arg2, type3 arg3) {                        \
-       register type1 __arg1 asm("2") = arg1;                  \
-       register type2 __arg2 asm("3") = arg2;                  \
-       register type3 __arg3 asm("4") = arg3;                  \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name),                            \
-                 "0" (__arg1),                                 \
-                 "d" (__arg2),                                 \
-                 "d" (__arg3)                                  \
-               : _svc_clobber);                                \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,  \
-                 type4,name4)                                  \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {    \
-       register type1 __arg1 asm("2") = arg1;                  \
-       register type2 __arg2 asm("3") = arg2;                  \
-       register type3 __arg3 asm("4") = arg3;                  \
-       register type4 __arg4 asm("5") = arg4;                  \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name),                            \
-                 "0" (__arg1),                                 \
-                 "d" (__arg2),                                 \
-                 "d" (__arg3),                                 \
-                 "d" (__arg4)                                  \
-               : _svc_clobber);                                \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,  \
-                 type4,name4,type5,name5)                      \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,      \
-         type5 arg5) {                                         \
-       register type1 __arg1 asm("2") = arg1;                  \
-       register type2 __arg2 asm("3") = arg2;                  \
-       register type3 __arg3 asm("4") = arg3;                  \
-       register type4 __arg4 asm("5") = arg4;                  \
-       register type5 __arg5 asm("6") = arg5;                  \
-       register long __svcres asm("2");                        \
-       long __res;                                             \
-       asm volatile(                                           \
-               "       .if     %1 < 256\n"                     \
-               "       svc     %b1\n"                          \
-               "       .else\n"                                \
-               "       la      %%r1,%1\n"                      \
-               "       svc     0\n"                            \
-               "       .endif"                                 \
-               : "=d" (__svcres)                               \
-               : "i" (__NR_##name),                            \
-                 "0" (__arg1),                                 \
-                 "d" (__arg2),                                 \
-                 "d" (__arg3),                                 \
-                 "d" (__arg4),                                 \
-                 "d" (__arg5)                                  \
-               : _svc_clobber);                                \
-       __res = __svcres;                                       \
-       __syscall_return(type,__res);                           \
-}
-
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
index 8bdc1ba..28305c3 100644 (file)
@@ -28,11 +28,11 @@ static inline void atomic_add(int i, atomic_t *v)
        unsigned long tmp;
 
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_add    \n"
-"      add     %2, %0                          \n"
-"      movco.l %0, @%3                         \n"
+"1:    movli.l @%2, %0         ! atomic_add    \n"
+"      add     %1, %0                          \n"
+"      movco.l %0, @%2                         \n"
 "      bf      1b                              \n"
-       : "=&z" (tmp), "=r" (&v->counter)
+       : "=&z" (tmp)
        : "r" (i), "r" (&v->counter)
        : "t");
 #else
@@ -50,11 +50,11 @@ static inline void atomic_sub(int i, atomic_t *v)
        unsigned long tmp;
 
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_sub    \n"
-"      sub     %2, %0                          \n"
-"      movco.l %0, @%3                         \n"
+"1:    movli.l @%2, %0         ! atomic_sub    \n"
+"      sub     %1, %0                          \n"
+"      movco.l %0, @%2                         \n"
 "      bf      1b                              \n"
-       : "=&z" (tmp), "=r" (&v->counter)
+       : "=&z" (tmp)
        : "r" (i), "r" (&v->counter)
        : "t");
 #else
@@ -80,12 +80,12 @@ static inline int atomic_add_return(int i, atomic_t *v)
 
 #ifdef CONFIG_CPU_SH4A
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_add_return     \n"
-"      add     %2, %0                                  \n"
-"      movco.l %0, @%3                                 \n"
+"1:    movli.l @%2, %0         ! atomic_add_return     \n"
+"      add     %1, %0                                  \n"
+"      movco.l %0, @%2                                 \n"
 "      bf      1b                                      \n"
 "      synco                                           \n"
-       : "=&z" (temp), "=r" (&v->counter)
+       : "=&z" (temp)
        : "r" (i), "r" (&v->counter)
        : "t");
 #else
@@ -109,12 +109,12 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 
 #ifdef CONFIG_CPU_SH4A
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_sub_return     \n"
-"      sub     %2, %0                                  \n"
-"      movco.l %0, @%3                                 \n"
+"1:    movli.l @%2, %0         ! atomic_sub_return     \n"
+"      sub     %1, %0                                  \n"
+"      movco.l %0, @%2                                 \n"
 "      bf      1b                                      \n"
 "      synco                                           \n"
-       : "=&z" (temp), "=r" (&v->counter)
+       : "=&z" (temp)
        : "r" (i), "r" (&v->counter)
        : "t");
 #else
@@ -186,11 +186,11 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
        unsigned long tmp;
 
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_clear_mask     \n"
-"      and     %2, %0                                  \n"
-"      movco.l %0, @%3                                 \n"
+"1:    movli.l @%2, %0         ! atomic_clear_mask     \n"
+"      and     %1, %0                                  \n"
+"      movco.l %0, @%2                                 \n"
 "      bf      1b                                      \n"
-       : "=&z" (tmp), "=r" (&v->counter)
+       : "=&z" (tmp)
        : "r" (~mask), "r" (&v->counter)
        : "t");
 #else
@@ -208,11 +208,11 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
        unsigned long tmp;
 
        __asm__ __volatile__ (
-"1:    movli.l @%3, %0         ! atomic_set_mask       \n"
-"      or      %2, %0                                  \n"
-"      movco.l %0, @%3                                 \n"
+"1:    movli.l @%2, %0         ! atomic_set_mask       \n"
+"      or      %1, %0                                  \n"
+"      movco.l %0, @%2                                 \n"
 "      bf      1b                                      \n"
-       : "=&z" (tmp), "=r" (&v->counter)
+       : "=&z" (tmp)
        : "r" (mask), "r" (&v->counter)
        : "t");
 #else
index beeea40..795047d 100644 (file)
@@ -23,16 +23,20 @@ static void __init check_bugs(void)
        cpu_data->loops_per_jiffy = loops_per_jiffy;
 
        switch (cpu_data->type) {
-       case CPU_SH7604:
+       case CPU_SH7604 ... CPU_SH7619:
                *p++ = '2';
                break;
+       case CPU_SH7206:
+               *p++ = '2';
+               *p++ = 'a';
+               break;
        case CPU_SH7705 ... CPU_SH7300:
                *p++ = '3';
                break;
        case CPU_SH7750 ... CPU_SH4_501:
                *p++ = '4';
                break;
-       case CPU_SH7770 ... CPU_SH7781:
+       case CPU_SH7770 ... CPU_SH7785:
                *p++ = '4';
                *p++ = 'a';
                break;
index fdfb75b..1df9280 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/seq_file.h>
+#include <linux/clk.h>
 
 struct clk;
 
@@ -18,7 +19,7 @@ struct clk_ops {
 struct clk {
        struct list_head        node;
        const char              *name;
-
+       int                     id;
        struct module           *owner;
 
        struct clk              *parent;
@@ -40,22 +41,13 @@ void arch_init_clk_ops(struct clk_ops **, int type);
 int clk_init(void);
 
 int __clk_enable(struct clk *);
-int clk_enable(struct clk *);
-
 void __clk_disable(struct clk *);
-void clk_disable(struct clk *);
 
-int clk_set_rate(struct clk *, unsigned long rate);
-unsigned long clk_get_rate(struct clk *);
 void clk_recalc_rate(struct clk *);
 
-struct clk *clk_get(const char *id);
-void clk_put(struct clk *);
-
 int clk_register(struct clk *);
 void clk_unregister(struct clk *);
 
 int show_clocks(struct seq_file *m);
 
 #endif /* __ASM_SH_CLOCK_H */
-
index cd96402..20b9796 100644 (file)
@@ -12,6 +12,7 @@
 
 #define L1_CACHE_SHIFT 4
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7604)
 #define CCR            0xfffffe92      /* Address of Cache Control Register */
 
 #define CCR_CACHE_CE   0x01    /* Cache enable */
 #define CCR_CACHE_ORA          CCR_CACHE_TW
 #define CCR_CACHE_WT           0x00    /* SH-2 is _always_ write-through */
 
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#define CCR1           0xffffffec
+#define CCR            CCR1
+
+#define CCR_CACHE_CE   0x01    /* Cache enable */
+#define CCR_CACHE_WT   0x06    /* CCR[bit1=1,bit2=1] */
+                               /* 0x00000000-0x7fffffff: Write-through  */
+                               /* 0x80000000-0x9fffffff: Write-back     */
+                                /* 0xc0000000-0xdfffffff: Write-through  */
+#define CCR_CACHE_CB   0x00    /* CCR[bit1=0,bit2=0] */
+                               /* 0x00000000-0x7fffffff: Write-back     */
+                               /* 0x80000000-0x9fffffff: Write-through  */
+                                /* 0xc0000000-0xdfffffff: Write-back     */
+#define CCR_CACHE_CF   0x08    /* Cache invalidate */
+
+#define CACHE_OC_ADDRESS_ARRAY 0xf0000000
+#define CACHE_OC_DATA_ARRAY    0xf1000000
+
+#define CCR_CACHE_ENABLE       CCR_CACHE_CE
+#define CCR_CACHE_INVALIDATE   CCR_CACHE_CF
+#endif
 #endif /* __ASM_CPU_SH2_CACHE_H */
 
diff --git a/include/asm-sh/cpu-sh2/freq.h b/include/asm-sh/cpu-sh2/freq.h
new file mode 100644 (file)
index 0000000..31de475
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/asm-sh/cpu-sh2/freq.h
+ *
+ * Copyright (C) 2006  Yoshinori Sato
+ *
+ * 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_FREQ_H
+#define __ASM_CPU_SH2_FREQ_H
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
+#define FREQCR 0xf815ff80
+#endif
+
+#endif /* __ASM_CPU_SH2_FREQ_H */
+
diff --git a/include/asm-sh/cpu-sh2/mmu_context.h b/include/asm-sh/cpu-sh2/mmu_context.h
new file mode 100644 (file)
index 0000000..beeb299
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * include/asm-sh/cpu-sh2/mmu_context.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_MMU_CONTEXT_H
+#define __ASM_CPU_SH2_MMU_CONTEXT_H
+
+/* No MMU */
+
+#endif /* __ASM_CPU_SH2_MMU_CONTEXT_H */
+
diff --git a/include/asm-sh/cpu-sh2/timer.h b/include/asm-sh/cpu-sh2/timer.h
new file mode 100644 (file)
index 0000000..a39c241
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_CPU_SH2_TIMER_H
+#define __ASM_CPU_SH2_TIMER_H
+
+/* Nothing needed yet */
+
+#endif /* __ASM_CPU_SH2_TIMER_H */
diff --git a/include/asm-sh/cpu-sh2a/addrspace.h b/include/asm-sh/cpu-sh2a/addrspace.h
new file mode 100644 (file)
index 0000000..3d2e9aa
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/addrspace.h>
diff --git a/include/asm-sh/cpu-sh2a/cache.h b/include/asm-sh/cpu-sh2a/cache.h
new file mode 100644 (file)
index 0000000..3e4b9e4
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-sh/cpu-sh2a/cache.h
+ *
+ * Copyright (C) 2004 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_SH2A_CACHE_H
+#define __ASM_CPU_SH2A_CACHE_H
+
+#define L1_CACHE_SHIFT 4
+
+#define CCR1           0xfffc1000
+#define CCR2           0xfffc1004
+
+/* CCR1 behaves more like the traditional CCR */
+#define CCR            CCR1
+
+/*
+ * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not
+ * listed here are reserved.
+ */
+#define CCR_CACHE_CB   0x0000  /* Hack */
+#define CCR_CACHE_OCE  0x0001
+#define CCR_CACHE_WT   0x0002
+#define CCR_CACHE_OCI  0x0008  /* OCF */
+#define CCR_CACHE_ICE  0x0100
+#define CCR_CACHE_ICI  0x0800  /* ICF */
+
+#define CACHE_IC_ADDRESS_ARRAY 0xf0000000
+#define CACHE_OC_ADDRESS_ARRAY 0xf0800000
+
+#define CCR_CACHE_ENABLE       (CCR_CACHE_OCE | CCR_CACHE_ICE)
+#define CCR_CACHE_INVALIDATE   (CCR_CACHE_OCI | CCR_CACHE_ICI)
+
+#endif /* __ASM_CPU_SH2A_CACHE_H */
+
diff --git a/include/asm-sh/cpu-sh2a/cacheflush.h b/include/asm-sh/cpu-sh2a/cacheflush.h
new file mode 100644 (file)
index 0000000..fa3186c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/cacheflush.h>
diff --git a/include/asm-sh/cpu-sh2a/dma.h b/include/asm-sh/cpu-sh2a/dma.h
new file mode 100644 (file)
index 0000000..0d5ad85
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/dma.h>
diff --git a/include/asm-sh/cpu-sh2a/freq.h b/include/asm-sh/cpu-sh2a/freq.h
new file mode 100644 (file)
index 0000000..e518fff
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/asm-sh/cpu-sh2a/freq.h
+ *
+ * Copyright (C) 2006  Yoshinori Sato
+ *
+ * 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_SH2A_FREQ_H
+#define __ASM_CPU_SH2A_FREQ_H
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7206)
+#define FREQCR 0xfffe0010
+#endif
+
+#endif /* __ASM_CPU_SH2A_FREQ_H */
+
diff --git a/include/asm-sh/cpu-sh2a/mmu_context.h b/include/asm-sh/cpu-sh2a/mmu_context.h
new file mode 100644 (file)
index 0000000..cd2387f
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/mmu_context.h>
diff --git a/include/asm-sh/cpu-sh2a/timer.h b/include/asm-sh/cpu-sh2a/timer.h
new file mode 100644 (file)
index 0000000..fee504a
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/timer.h>
diff --git a/include/asm-sh/cpu-sh2a/ubc.h b/include/asm-sh/cpu-sh2a/ubc.h
new file mode 100644 (file)
index 0000000..cf28062
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/ubc.h>
diff --git a/include/asm-sh/cpu-sh2a/watchdog.h b/include/asm-sh/cpu-sh2a/watchdog.h
new file mode 100644 (file)
index 0000000..c1b3e24
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/cpu-sh2/watchdog.h>
index 56cd4b9..37ab0c1 100644 (file)
@@ -53,7 +53,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
        consistent_free(vaddr, size);
 }
 
-static inline void dma_cache_sync(void *vaddr, size_t size,
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                                  enum dma_data_direction dir)
 {
        consistent_sync(vaddr, size, (int)dir);
index d9daa02..faf3051 100644 (file)
@@ -14,9 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/sysdev.h>
-#include <linux/device.h>
 #include <asm/cpu/dma.h>
-#include <asm/semaphore.h>
 
 /* The maximum address that we can perform a DMA transfer to on this platform */
 /* Don't define MAX_DMA_ADDRESS; it's useless on the SuperH and any
  * DMAC (dma_info) flags
  */
 enum {
-       DMAC_CHANNELS_CONFIGURED        = 0x00,
-       DMAC_CHANNELS_TEI_CAPABLE       = 0x01,
+       DMAC_CHANNELS_CONFIGURED        = 0x01,
+       DMAC_CHANNELS_TEI_CAPABLE       = 0x02, /* Transfer end interrupt */
 };
 
 /*
  * DMA channel capabilities / flags
  */
 enum {
-       DMA_TEI_CAPABLE                 = 0x01,
-       DMA_CONFIGURED                  = 0x02,
+       DMA_CONFIGURED                  = 0x01,
+
+       /*
+        * Transfer end interrupt, inherited from DMAC.
+        * wait_queue used in dma_wait_for_completion.
+        */
+       DMA_TEI_CAPABLE                 = 0x02,
 };
 
 extern spinlock_t dma_spin_lock;
@@ -68,28 +71,31 @@ struct dma_ops {
 
        int (*get_residue)(struct dma_channel *chan);
        int (*xfer)(struct dma_channel *chan);
-       void (*configure)(struct dma_channel *chan, unsigned long flags);
+       int (*configure)(struct dma_channel *chan, unsigned long flags);
+       int (*extend)(struct dma_channel *chan, unsigned long op, void *param);
 };
 
 struct dma_channel {
-       char dev_id[16];
+       char dev_id[16];                /* unique name per DMAC of channel */
 
-       unsigned int chan;              /* Physical channel number */
+       unsigned int chan;              /* DMAC channel number */
        unsigned int vchan;             /* Virtual channel number */
+
        unsigned int mode;
        unsigned int count;
 
        unsigned long sar;
        unsigned long dar;
 
+       const char **caps;
+
        unsigned long flags;
        atomic_t busy;
 
-       struct semaphore sem;
        wait_queue_head_t wait_queue;
 
        struct sys_device dev;
-       char *name;
+       void *priv_data;
 };
 
 struct dma_info {
@@ -103,6 +109,12 @@ struct dma_info {
        struct dma_channel *channels;
 
        struct list_head list;
+       int first_channel_nr;
+};
+
+struct dma_chan_caps {
+       int ch_num;
+       const char **caplist;
 };
 
 #define to_dma_channel(channel) container_of(channel, struct dma_channel, dev)
@@ -121,6 +133,8 @@ extern int dma_xfer(unsigned int chan, unsigned long from,
 #define dma_read_page(chan, from, to)  \
        dma_read(chan, from, to, PAGE_SIZE)
 
+extern int request_dma_bycap(const char **dmac, const char **caps,
+                            const char *dev_id);
 extern int request_dma(unsigned int chan, const char *dev_id);
 extern void free_dma(unsigned int chan);
 extern int get_dma_residue(unsigned int chan);
@@ -131,6 +145,10 @@ extern void dma_configure_channel(unsigned int chan, unsigned long flags);
 
 extern int register_dmac(struct dma_info *info);
 extern void unregister_dmac(struct dma_info *info);
+extern struct dma_info *get_dma_info_by_name(const char *dmac_name);
+
+extern int dma_extend(unsigned int chan, unsigned long op, void *param);
+extern int register_chan_caps(const char *dmac, struct dma_chan_caps *capslist);
 
 #ifdef CONFIG_SYSFS
 /* arch/sh/drivers/dma/dma-sysfs.c */
index fc050fd..43ca244 100644 (file)
@@ -74,7 +74,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
 #define ELF_ARCH       EM_SH
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE      4096
+#define ELF_EXEC_PAGESIZE      PAGE_SIZE
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
    use of this is to invoke "./ld.so someprog" to test out a new version of
diff --git a/include/asm-sh/entry-macros.S b/include/asm-sh/entry-macros.S
new file mode 100644 (file)
index 0000000..500030e
--- /dev/null
@@ -0,0 +1,33 @@
+! entry.S macro define
+       
+       .macro  cli
+       stc     sr, r0
+       or      #0xf0, r0
+       ldc     r0, sr
+       .endm
+
+       .macro  sti
+       mov     #0xf0, r11
+       extu.b  r11, r11
+       not     r11, r11
+       stc     sr, r10
+       and     r11, r10
+#ifdef CONFIG_HAS_SR_RB
+       stc     k_g_imask, r11
+       or      r11, r10
+#endif
+       ldc     r10, sr
+       .endm
+
+       .macro  get_current_thread_info, ti, tmp
+#ifdef CONFIG_HAS_SR_RB
+       stc     r7_bank, \ti
+#else
+       mov     #((THREAD_SIZE - 1) >> 10) ^ 0xff, \tmp
+       shll8   \tmp
+       shll2   \tmp
+       mov     r15, \ti
+       and     \tmp, \ti
+#endif 
+       .endm
+
diff --git a/include/asm-sh/irq-sh73180.h b/include/asm-sh/irq-sh73180.h
deleted file mode 100644 (file)
index b28af9a..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-#ifndef __ASM_SH_IRQ_SH73180_H
-#define __ASM_SH_IRQ_SH73180_H
-
-/*
- * linux/include/asm-sh/irq-sh73180.h
- *
- * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp>
- */
-
-#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_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_IPRG
-#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_SH73180_H */
diff --git a/include/asm-sh/irq-sh7343.h b/include/asm-sh/irq-sh7343.h
deleted file mode 100644 (file)
index 5d15419..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-#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 */
diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h
deleted file mode 100644 (file)
index 19912ae..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-#ifndef __ASM_SH_IRQ_SH7780_H
-#define __ASM_SH_IRQ_SH7780_H
-
-/*
- * linux/include/asm-sh/irq-sh7780.h
- *
- * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp>
- */
-#define INTC_BASE      0xffd00000
-#define INTC_ICR0      (INTC_BASE+0x0)
-#define INTC_ICR1      (INTC_BASE+0x1c)
-#define INTC_INTPRI    (INTC_BASE+0x10)
-#define INTC_INTREQ    (INTC_BASE+0x24)
-#define INTC_INTMSK0   (INTC_BASE+0x44)
-#define INTC_INTMSK1   (INTC_BASE+0x48)
-#define INTC_INTMSK2   (INTC_BASE+0x40080)
-#define INTC_INTMSKCLR0        (INTC_BASE+0x64)
-#define INTC_INTMSKCLR1        (INTC_BASE+0x68)
-#define INTC_INTMSKCLR2        (INTC_BASE+0x40084)
-#define INTC_NMIFCR    (INTC_BASE+0xc0)
-#define INTC_USERIMASK (INTC_BASE+0x30000)
-
-#define        INTC_INT2PRI0   (INTC_BASE+0x40000)
-#define        INTC_INT2PRI1   (INTC_BASE+0x40004)
-#define        INTC_INT2PRI2   (INTC_BASE+0x40008)
-#define        INTC_INT2PRI3   (INTC_BASE+0x4000c)
-#define        INTC_INT2PRI4   (INTC_BASE+0x40010)
-#define        INTC_INT2PRI5   (INTC_BASE+0x40014)
-#define        INTC_INT2PRI6   (INTC_BASE+0x40018)
-#define        INTC_INT2PRI7   (INTC_BASE+0x4001c)
-#define        INTC_INT2A0     (INTC_BASE+0x40030)
-#define        INTC_INT2A1     (INTC_BASE+0x40034)
-#define        INTC_INT2MSKR   (INTC_BASE+0x40038)
-#define        INTC_INT2MSKCR  (INTC_BASE+0x4003c)
-#define        INTC_INT2B0     (INTC_BASE+0x40040)
-#define        INTC_INT2B1     (INTC_BASE+0x40044)
-#define        INTC_INT2B2     (INTC_BASE+0x40048)
-#define        INTC_INT2B3     (INTC_BASE+0x4004c)
-#define        INTC_INT2B4     (INTC_BASE+0x40050)
-#define        INTC_INT2B5     (INTC_BASE+0x40054)
-#define        INTC_INT2B6     (INTC_BASE+0x40058)
-#define        INTC_INT2B7     (INTC_BASE+0x4005c)
-#define        INTC_INT2GPIC   (INTC_BASE+0x40090)
-/*
-  NOTE:
-  *_IRQ = (INTEVT2 - 0x200)/0x20
-*/
-/* IRQ 0-7 line external int*/
-#define IRQ0_IRQ       2
-#define IRQ0_IPR_ADDR  INTC_INTPRI
-#define IRQ0_IPR_POS   7
-#define IRQ0_PRIORITY  2
-
-#define IRQ1_IRQ       4
-#define IRQ1_IPR_ADDR  INTC_INTPRI
-#define IRQ1_IPR_POS   6
-#define IRQ1_PRIORITY  2
-
-#define IRQ2_IRQ       6
-#define IRQ2_IPR_ADDR  INTC_INTPRI
-#define IRQ2_IPR_POS   5
-#define IRQ2_PRIORITY  2
-
-#define IRQ3_IRQ       8
-#define IRQ3_IPR_ADDR  INTC_INTPRI
-#define IRQ3_IPR_POS   4
-#define IRQ3_PRIORITY  2
-
-#define IRQ4_IRQ       10
-#define IRQ4_IPR_ADDR  INTC_INTPRI
-#define IRQ4_IPR_POS   3
-#define IRQ4_PRIORITY  2
-
-#define IRQ5_IRQ       12
-#define IRQ5_IPR_ADDR  INTC_INTPRI
-#define IRQ5_IPR_POS   2
-#define IRQ5_PRIORITY  2
-
-#define IRQ6_IRQ       14
-#define IRQ6_IPR_ADDR  INTC_INTPRI
-#define IRQ6_IPR_POS   1
-#define IRQ6_PRIORITY  2
-
-#define IRQ7_IRQ       0
-#define IRQ7_IPR_ADDR  INTC_INTPRI
-#define IRQ7_IPR_POS   0
-#define IRQ7_PRIORITY  2
-
-/* TMU */
-/* ch0 */
-#define TMU_IRQ                28
-#define        TMU_IPR_ADDR    INTC_INT2PRI0
-#define        TMU_IPR_POS     3
-#define TMU_PRIORITY   2
-
-#define TIMER_IRQ      28
-#define        TIMER_IPR_ADDR  INTC_INT2PRI0
-#define        TIMER_IPR_POS   3
-#define TIMER_PRIORITY 2
-
-/* ch 1*/
-#define TMU_CH1_IRQ            29
-#define        TMU_CH1_IPR_ADDR        INTC_INT2PRI0
-#define        TMU_CH1_IPR_POS         2
-#define TMU_CH1_PRIORITY       2
-
-#define TIMER1_IRQ     29
-#define        TIMER1_IPR_ADDR INTC_INT2PRI0
-#define        TIMER1_IPR_POS  2
-#define TIMER1_PRIORITY        2
-
-/* ch 2*/
-#define TMU_CH2_IRQ            30
-#define        TMU_CH2_IPR_ADDR        INTC_INT2PRI0
-#define        TMU_CH2_IPR_POS         1
-#define TMU_CH2_PRIORITY       2
-/* ch 2 Input capture */
-#define TMU_CH2IC_IRQ          31
-#define        TMU_CH2IC_IPR_ADDR      INTC_INT2PRI0
-#define        TMU_CH2IC_IPR_POS       0
-#define TMU_CH2IC_PRIORITY     2
-/* ch 3 */
-#define TMU_CH3_IRQ            96
-#define        TMU_CH3_IPR_ADDR        INTC_INT2PRI1
-#define        TMU_CH3_IPR_POS         3
-#define TMU_CH3_PRIORITY       2
-/* ch 4 */
-#define TMU_CH4_IRQ            97
-#define        TMU_CH4_IPR_ADDR        INTC_INT2PRI1
-#define        TMU_CH4_IPR_POS         2
-#define TMU_CH4_PRIORITY       2
-/* ch 5*/
-#define TMU_CH5_IRQ            98
-#define        TMU_CH5_IPR_ADDR        INTC_INT2PRI1
-#define        TMU_CH5_IPR_POS         1
-#define TMU_CH5_PRIORITY       2
-
-/* SCIF0 */
-#define SCIF0_ERI_IRQ  40
-#define SCIF0_RXI_IRQ  41
-#define SCIF0_BRI_IRQ  42
-#define SCIF0_TXI_IRQ  43
-#define        SCIF0_IPR_ADDR  INTC_INT2PRI2
-#define        SCIF0_IPR_POS   3
-#define SCIF0_PRIORITY 3
-
-/* SCIF1 */
-#define SCIF1_ERI_IRQ  76
-#define SCIF1_RXI_IRQ  77
-#define SCIF1_BRI_IRQ  78
-#define SCIF1_TXI_IRQ  79
-#define        SCIF1_IPR_ADDR  INTC_INT2PRI2
-#define        SCIF1_IPR_POS   2
-#define SCIF1_PRIORITY 3
-
-#define        WDT_IRQ         27
-#define        WDT_IPR_ADDR    INTC_INT2PRI2
-#define        WDT_IPR_POS     1
-#define        WDT_PRIORITY    2
-
-/* DMAC(0) */
-#define        DMINT0_IRQ      34
-#define        DMINT1_IRQ      35
-#define        DMINT2_IRQ      36
-#define        DMINT3_IRQ      37
-#define        DMINT4_IRQ      44
-#define        DMINT5_IRQ      45
-#define        DMINT6_IRQ      46
-#define        DMINT7_IRQ      47
-#define        DMAE_IRQ        38
-#define        DMA0_IPR_ADDR   INTC_INT2PRI3
-#define        DMA0_IPR_POS    2
-#define        DMA0_PRIORITY   7
-
-/* DMAC(1) */
-#define        DMINT8_IRQ      92
-#define        DMINT9_IRQ      93
-#define        DMINT10_IRQ     94
-#define        DMINT11_IRQ     95
-#define        DMA1_IPR_ADDR   INTC_INT2PRI3
-#define        DMA1_IPR_POS    1
-#define        DMA1_PRIORITY   7
-
-#define        DMTE0_IRQ       DMINT0_IRQ
-#define        DMTE4_IRQ       DMINT4_IRQ
-#define        DMA_IPR_ADDR    DMA0_IPR_ADDR
-#define        DMA_IPR_POS     DMA0_IPR_POS
-#define        DMA_PRIORITY    DMA0_PRIORITY
-
-/* CMT */
-#define        CMT_IRQ         56
-#define        CMT_IPR_ADDR    INTC_INT2PRI4
-#define        CMT_IPR_POS     3
-#define        CMT_PRIORITY    0
-
-/* HAC */
-#define        HAC_IRQ         60
-#define        HAC_IPR_ADDR    INTC_INT2PRI4
-#define        HAC_IPR_POS     2
-#define        CMT_PRIORITY    0
-
-/* PCIC(0) */
-#define        PCIC0_IRQ       64
-#define        PCIC0_IPR_ADDR  INTC_INT2PRI4
-#define        PCIC0_IPR_POS   1
-#define        PCIC0_PRIORITY  2
-
-/* PCIC(1) */
-#define        PCIC1_IRQ       65
-#define        PCIC1_IPR_ADDR  INTC_INT2PRI4
-#define        PCIC1_IPR_POS   0
-#define        PCIC1_PRIORITY  2
-
-/* PCIC(2) */
-#define        PCIC2_IRQ       66
-#define        PCIC2_IPR_ADDR  INTC_INT2PRI5
-#define        PCIC2_IPR_POS   3
-#define        PCIC2_PRIORITY  2
-
-/* PCIC(3) */
-#define        PCIC3_IRQ       67
-#define        PCIC3_IPR_ADDR  INTC_INT2PRI5
-#define        PCIC3_IPR_POS   2
-#define        PCIC3_PRIORITY  2
-
-/* PCIC(4) */
-#define        PCIC4_IRQ       68
-#define        PCIC4_IPR_ADDR  INTC_INT2PRI5
-#define        PCIC4_IPR_POS   1
-#define        PCIC4_PRIORITY  2
-
-/* PCIC(5) */
-#define        PCICERR_IRQ     69
-#define        PCICPWD3_IRQ    70
-#define        PCICPWD2_IRQ    71
-#define        PCICPWD1_IRQ    72
-#define        PCICPWD0_IRQ    73
-#define        PCIC5_IPR_ADDR  INTC_INT2PRI5
-#define        PCIC5_IPR_POS   0
-#define        PCIC5_PRIORITY  2
-
-/* SIOF */
-#define        SIOF_IRQ        80
-#define        SIOF_IPR_ADDR   INTC_INT2PRI6
-#define        SIOF_IPR_POS    3
-#define        SIOF_PRIORITY   3
-
-/* HSPI */
-#define        HSPI_IRQ        84
-#define        HSPI_IPR_ADDR   INTC_INT2PRI6
-#define        HSPI_IPR_POS    2
-#define        HSPI_PRIORITY   3
-
-/* MMCIF */
-#define        MMCIF_FSTAT_IRQ 88
-#define        MMCIF_TRAN_IRQ  89
-#define        MMCIF_ERR_IRQ   90
-#define        MMCIF_FRDY_IRQ  91
-#define        MMCIF_IPR_ADDR  INTC_INT2PRI6
-#define        MMCIF_IPR_POS   1
-#define        HSPI_PRIORITY   3
-
-/* SSI */
-#define        SSI_IRQ         100
-#define        SSI_IPR_ADDR    INTC_INT2PRI6
-#define        SSI_IPR_POS     0
-#define        SSI_PRIORITY    3
-
-/* FLCTL */
-#define        FLCTL_FLSTE_IRQ         104
-#define        FLCTL_FLTEND_IRQ        105
-#define        FLCTL_FLTRQ0_IRQ        106
-#define        FLCTL_FLTRQ1_IRQ        107
-#define        FLCTL_IPR_ADDR          INTC_INT2PRI7
-#define        FLCTL_IPR_POS           3
-#define        FLCTL_PRIORITY          3
-
-/* GPIO */
-#define        GPIO0_IRQ       108
-#define        GPIO1_IRQ       109
-#define        GPIO2_IRQ       110
-#define        GPIO3_IRQ       111
-#define        GPIO_IPR_ADDR   INTC_INT2PRI7
-#define        GPIO_IPR_POS    2
-#define        GPIO_PRIORITY   3
-
-#define        INTC_TMU0_MSK   0
-#define        INTC_TMU3_MSK   1
-#define        INTC_RTC_MSK    2
-#define        INTC_SCIF0_MSK  3
-#define        INTC_SCIF1_MSK  4
-#define        INTC_WDT_MSK    5
-#define        INTC_HUID_MSK   7
-#define        INTC_DMAC0_MSK  8
-#define        INTC_DMAC1_MSK  9
-#define        INTC_CMT_MSK    12
-#define        INTC_HAC_MSK    13
-#define        INTC_PCIC0_MSK  14
-#define        INTC_PCIC1_MSK  15
-#define        INTC_PCIC2_MSK  16
-#define        INTC_PCIC3_MSK  17
-#define        INTC_PCIC4_MSK  18
-#define        INTC_PCIC5_MSK  19
-#define        INTC_SIOF_MSK   20
-#define        INTC_HSPI_MSK   21
-#define        INTC_MMCIF_MSK  22
-#define        INTC_SSI_MSK    23
-#define        INTC_FLCTL_MSK  24
-#define        INTC_GPIO_MSK   25
-
-#endif /* __ASM_SH_IRQ_SH7780_H */
index 6cd3e9e..fd57608 100644 (file)
@@ -1,233 +1,9 @@
 #ifndef __ASM_SH_IRQ_H
 #define __ASM_SH_IRQ_H
 
-/*
- *
- * linux/include/asm-sh/irq.h
- *
- * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
- * Copyright (C) 2000  Kazumoto Kojima
- * Copyright (C) 2003  Paul Mundt
- *
- */
-
 #include <asm/machvec.h>
 #include <asm/ptrace.h>                /* for pt_regs */
 
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
-
-#define INTC_DMAC0_MSK 0
-
-#if defined(CONFIG_CPU_SH3)
-#define INTC_IPRA      0xfffffee2UL
-#define INTC_IPRB      0xfffffee4UL
-#elif defined(CONFIG_CPU_SH4)
-#define INTC_IPRA      0xffd00004UL
-#define INTC_IPRB      0xffd00008UL
-#define INTC_IPRC      0xffd0000cUL
-#define INTC_IPRD      0xffd00010UL
-#endif
-
-#define TIMER_IRQ      16
-#define TIMER_IPR_ADDR INTC_IPRA
-#define TIMER_IPR_POS   3
-#define TIMER_PRIORITY  2
-
-#define TIMER1_IRQ     17
-#define TIMER1_IPR_ADDR        INTC_IPRA
-#define TIMER1_IPR_POS  2
-#define TIMER1_PRIORITY         4
-
-#define RTC_IRQ                22
-#define RTC_IPR_ADDR   INTC_IPRA
-#define RTC_IPR_POS     0
-#define RTC_PRIORITY   TIMER_PRIORITY
-
-#if defined(CONFIG_CPU_SH3)
-#define DMTE0_IRQ      48
-#define DMTE1_IRQ      49
-#define DMTE2_IRQ      50
-#define DMTE3_IRQ      51
-#define DMA_IPR_ADDR   INTC_IPRE
-#define DMA_IPR_POS    3
-#define DMA_PRIORITY   7
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-/* TMU2 */
-#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
-
-/* SIM (SIM Card Module) */
-#define SIM_ERI_IRQ    23
-#define SIM_RXI_IRQ    24
-#define SIM_TXI_IRQ    25
-#define SIM_TEND_IRQ   26
-#define SIM_IPR_ADDR   INTC_IPRB
-#define SIM_IPR_POS     1
-#define SIM_PRIORITY    2
-
-/* VIO (Video I/O) */
-#define VIO_IRQ                52
-#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
-
-/* KEY (Key Scan Interface) */
-#define KEY_IRQ                79
-#define KEY_IPR_ADDR   INTC_IPRF
-#define KEY_IPR_POS     3
-#define KEY_PRIORITY    2
-
-/* CMT (Compare Match Timer) */
-#define CMT_IRQ                104
-#define CMT_IPR_ADDR   INTC_IPRF
-#define CMT_IPR_POS     0
-#define CMT_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
-
-/* 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 (IIC Bus Interface) */
-#define IIC_ALI_IRQ    96
-#define IIC_TACKI_IRQ  97
-#define IIC_WAITI_IRQ  98
-#define IIC_DTEI_IRQ   99
-#define IIC_IPR_ADDR   INTC_IPRH
-#define IIC_IPR_POS    0
-#define IIC_PRIORITY   3
-
-/* SIO0 */
-#define SIO0_IRQ       88
-#define SIO0_IPR_ADDR  INTC_IPRI
-#define SIO0_IPR_POS   3
-#define SIO0_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
-
-#endif
-#elif defined(CONFIG_CPU_SH4)
-#define DMTE0_IRQ      34
-#define DMTE1_IRQ      35
-#define DMTE2_IRQ      36
-#define DMTE3_IRQ      37
-#define DMTE4_IRQ      44      /* 7751R only */
-#define DMTE5_IRQ      45      /* 7751R only */
-#define DMTE6_IRQ      46      /* 7751R only */
-#define DMTE7_IRQ      47      /* 7751R only */
-#define DMAE_IRQ       38
-#define DMA_IPR_ADDR   INTC_IPRC
-#define DMA_IPR_POS    2
-#define DMA_PRIORITY   7
-#endif
-
-#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_SH7706)
-#define SCI_ERI_IRQ    23
-#define SCI_RXI_IRQ    24
-#define SCI_TXI_IRQ    25
-#define SCI_IPR_ADDR   INTC_IPRB
-#define SCI_IPR_POS    1
-#define SCI_PRIORITY   3
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define SCIF0_IRQ      80
-#define SCIF0_IPR_ADDR INTC_IPRG
-#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
-#define SCIF_RXI_IRQ   57
-#define SCIF_BRI_IRQ   58
-#define SCIF_TXI_IRQ   59
-#define SCIF_IPR_ADDR  INTC_IPRE
-#define SCIF_IPR_POS   1
-#define SCIF_PRIORITY  3
-
-#define IRDA_ERI_IRQ   52
-#define IRDA_RXI_IRQ   53
-#define IRDA_BRI_IRQ   54
-#define IRDA_TXI_IRQ   55
-#define IRDA_IPR_ADDR  INTC_IPRE
-#define IRDA_IPR_POS   2
-#define IRDA_PRIORITY  3
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-      defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202)
-#define SCIF_ERI_IRQ   40
-#define SCIF_RXI_IRQ   41
-#define SCIF_BRI_IRQ   42
-#define SCIF_TXI_IRQ   43
-#define SCIF_IPR_ADDR  INTC_IPRC
-#define SCIF_IPR_POS   1
-#define SCIF_PRIORITY  3
-#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-#define SCIF1_ERI_IRQ  23
-#define SCIF1_RXI_IRQ  24
-#define SCIF1_BRI_IRQ  25
-#define SCIF1_TXI_IRQ  26
-#define SCIF1_IPR_ADDR INTC_IPRB
-#define SCIF1_IPR_POS  1
-#define SCIF1_PRIORITY 3
-#endif /* ST40STB1 */
-
-#endif /* 775x / SH4-202 / ST40STB1 */
-#endif /* 7780 */
-
 /* NR_IRQS is made from three components:
  *   1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules
  *   2. PINT_NR_IRQS   - number of PINT interrupts
 # define ONCHIP_NR_IRQS 109
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define ONCHIP_NR_IRQS 111
+#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
+# define ONCHIP_NR_IRQS 256
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+# define ONCHIP_NR_IRQS 128
 #elif defined(CONFIG_SH_UNKNOWN)       /* Most be last */
 # define ONCHIP_NR_IRQS 144
 #endif
 /* NR_IRQS. 1+2+3 */
 #define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS)
 
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
+/*
+ * Convert back and forth between INTEVT and IRQ values.
+ */
+#define evt2irq(evt)           (((evt) >> 5) - 16)
+#define irq2evt(irq)           (((irq) + 16) << 5)
 
 /*
  * Simple Mask Register Support
@@ -327,362 +109,36 @@ extern unsigned short *irq_mask_register;
  */
 void init_IRQ_pint(void);
 
+/*
+ * The shift value is now the number of bits to shift, not the number of
+ * bits/4. This is to make it easier to read the value directly from the
+ * datasheets. The IPR address, addr, will be set from ipr_idx via the
+ * map_ipridx_to_addr function.
+ */
 struct ipr_data {
        unsigned int irq;
-       unsigned int addr;      /* Address of Interrupt Priority Register */
-       int shift;              /* Shifts of the 16-bit data */
+       int ipr_idx;            /* Index for the IPR registered */
+       int shift;              /* Number of bits to shift the data */
        int priority;           /* The priority */
+       unsigned int addr;      /* Address of Interrupt Priority Register */
 };
 
 /*
- * Function for "on chip support modules".
+ * Given an IPR IDX, map the value to an IPR register address.
  */
-extern void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
-extern void make_imask_irq(unsigned int irq);
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#undef INTC_IPRA
-#undef INTC_IPRB
-#define INTC_IPRA      0xA414FEE2UL
-#define INTC_IPRB      0xA414FEE4UL
-#define INTC_IPRC      0xA4140016UL
-#define INTC_IPRD      0xA4140018UL
-#define INTC_IPRE      0xA414001AUL
-#define INTC_IPRF      0xA4080000UL
-#define INTC_IPRG      0xA4080002UL
-#define INTC_IPRH      0xA4080004UL
-#define INTC_IPRI      0xA4080006UL
-#define INTC_IPRJ      0xA4080008UL
-
-#define INTC_IMR0      0xA4080040UL
-#define INTC_IMR1      0xA4080042UL
-#define INTC_IMR2      0xA4080044UL
-#define INTC_IMR3      0xA4080046UL
-#define INTC_IMR4      0xA4080048UL
-#define INTC_IMR5      0xA408004AUL
-#define INTC_IMR6      0xA408004CUL
-#define INTC_IMR7      0xA408004EUL
-#define INTC_IMR8      0xA4080050UL
-#define INTC_IMR9      0xA4080052UL
-#define INTC_IMR10     0xA4080054UL
-
-#define INTC_IMCR0     0xA4080060UL
-#define INTC_IMCR1     0xA4080062UL
-#define INTC_IMCR2     0xA4080064UL
-#define INTC_IMCR3     0xA4080066UL
-#define INTC_IMCR4     0xA4080068UL
-#define INTC_IMCR5     0xA408006AUL
-#define INTC_IMCR6     0xA408006CUL
-#define INTC_IMCR7     0xA408006EUL
-#define INTC_IMCR8     0xA4080070UL
-#define INTC_IMCR9     0xA4080072UL
-#define INTC_IMCR10    0xA4080074UL
-
-#define INTC_ICR0      0xA414FEE0UL
-#define INTC_ICR1      0xA4140010UL
-
-#define INTC_IRR0      0xA4140004UL
-
-#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_PSELA     0xA4050140UL
-#define PORT_PSELB     0xA4050142UL
-#define PORT_PSELC     0xA4050144UL
-
-#define PORT_HIZCRA    0xA4050146UL
-#define PORT_HIZCRB    0xA4050148UL
-#define PORT_DRVCR     0xA4050150UL
-
-#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 IRQ0_IRQ       32
-#define IRQ1_IRQ       33
-#define IRQ2_IRQ       34
-#define IRQ3_IRQ       35
-#define IRQ4_IRQ       36
-#define IRQ5_IRQ       37
-
-#define IRQ0_IPR_ADDR  INTC_IPRC
-#define IRQ1_IPR_ADDR  INTC_IPRC
-#define IRQ2_IPR_ADDR  INTC_IPRC
-#define IRQ3_IPR_ADDR  INTC_IPRC
-#define IRQ4_IPR_ADDR  INTC_IPRD
-#define IRQ5_IPR_ADDR  INTC_IPRD
-
-#define IRQ0_IPR_POS   0
-#define IRQ1_IPR_POS   1
-#define IRQ2_IPR_POS   2
-#define IRQ3_IPR_POS   3
-#define IRQ4_IPR_POS   0
-#define IRQ5_IPR_POS   1
+unsigned int map_ipridx_to_addr(int idx);
 
-#define IRQ0_PRIORITY  1
-#define IRQ1_PRIORITY  1
-#define IRQ2_PRIORITY  1
-#define IRQ3_PRIORITY  1
-#define IRQ4_PRIORITY  1
-#define IRQ5_PRIORITY  1
-
-extern int ipr_irq_demux(int irq);
-#define __irq_demux(irq) ipr_irq_demux(irq)
-
-#elif defined(CONFIG_CPU_SUBTYPE_SH7604)
-#define INTC_IPRA      0xfffffee2UL
-#define INTC_IPRB      0xfffffe60UL
-
-#define INTC_VCRA      0xfffffe62UL
-#define INTC_VCRB      0xfffffe64UL
-#define INTC_VCRC      0xfffffe66UL
-#define INTC_VCRD      0xfffffe68UL
-
-#define INTC_VCRWDT    0xfffffee4UL
-#define INTC_VCRDIV    0xffffff0cUL
-#define INTC_VCRDMA0   0xffffffa0UL
-#define INTC_VCRDMA1   0xffffffa8UL
-
-#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_SH7710)
-#define INTC_IRR0      0xa4000004UL
-#define INTC_IRR1      0xa4000006UL
-#define INTC_IRR2      0xa4000008UL
-
-#define INTC_ICR0      0xfffffee0UL
-#define INTC_ICR1      0xa4000010UL
-#define INTC_ICR2      0xa4000012UL
-#define INTC_INTER     0xa4000014UL
-
-#define INTC_IPRC      0xa4000016UL
-#define INTC_IPRD      0xa4000018UL
-#define INTC_IPRE      0xa400001aUL
-#if defined(CONFIG_CPU_SUBTYPE_SH7707)
-#define INTC_IPRF      0xa400001cUL
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define INTC_IPRF      0xa4080000UL
-#define INTC_IPRG      0xa4080002UL
-#define INTC_IPRH      0xa4080004UL
-#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
-#define PORT_PFCR      0xa400010aUL
-#define PORT_PADR      0xa4000120UL
-#define PORT_PBDR      0xa4000122UL
-#define PORT_PCDR      0xa4000124UL
-#define PORT_PFDR      0xa400012aUL
-#endif
-
-#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 IRQ0_IPR_ADDR  INTC_IPRC
-#define IRQ1_IPR_ADDR  INTC_IPRC
-#define IRQ2_IPR_ADDR  INTC_IPRC
-#define IRQ3_IPR_ADDR  INTC_IPRC
-#define IRQ4_IPR_ADDR  INTC_IPRD
-#define IRQ5_IPR_ADDR  INTC_IPRD
-
-#define IRQ0_IPR_POS   0
-#define IRQ1_IPR_POS   1
-#define IRQ2_IPR_POS   2
-#define IRQ3_IPR_POS   3
-#define IRQ4_IPR_POS   0
-#define IRQ5_IPR_POS   1
-
-#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 PINT0_IRQ      40
-#define PINT8_IRQ      41
-
-#define PINT0_IPR_ADDR INTC_IPRD
-#define PINT8_IPR_ADDR INTC_IPRD
-
-#define PINT0_IPR_POS  3
-#define PINT8_IPR_POS  2
-#define PINT0_PRIORITY 2
-#define PINT8_PRIORITY 2
-
-extern int ipr_irq_demux(int irq);
-#define __irq_demux(irq) ipr_irq_demux(irq)
-#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-    defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202)
-#define INTC_ICR        0xffd00000
-#define INTC_ICR_NMIL  (1<<15)
-#define INTC_ICR_MAI   (1<<14)
-#define INTC_ICR_NMIB  (1<<9)
-#define INTC_ICR_NMIE  (1<<8)
-#define INTC_ICR_IRLM  (1<<7)
-#endif
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7780
-#include <asm/irq-sh7780.h>
-#endif
-
-/* SH with INTC2-style interrupts */
-#ifdef CONFIG_CPU_HAS_INTC2_IRQ
-#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-#define INTC2_BASE     0xfe080000
-#define INTC2_FIRST_IRQ 64
-#define INTC2_INTREQ_OFFSET    0x20
-#define INTC2_INTMSK_OFFSET    0x40
-#define INTC2_INTMSKCLR_OFFSET 0x60
-#define NR_INTC2_IRQS  25
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define INTC2_BASE     0xfe080000
-#define INTC2_FIRST_IRQ 48     /* INTEVT 0x800 */
-#define INTC2_INTREQ_OFFSET    0x20
-#define INTC2_INTMSK_OFFSET    0x40
-#define INTC2_INTMSKCLR_OFFSET 0x60
-#define NR_INTC2_IRQS  64
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-#define INTC2_BASE     0xffd40000
-#define INTC2_FIRST_IRQ        21
-#define INTC2_INTMSK_OFFSET    (0x38)
-#define INTC2_INTMSKCLR_OFFSET (0x3c)
-#define NR_INTC2_IRQS  60
-#endif
+/*
+ * Enable individual interrupt mode for external IPR IRQs.
+ */
+void ipr_irq_enable_irlm(void);
 
-#define INTC2_INTPRI_OFFSET    0x00
+/*
+ * Function for "on chip support modules".
+ */
+void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
+void make_imask_irq(unsigned int irq);
+void init_IRQ_ipr(void);
 
 struct intc2_data {
        unsigned short irq;
@@ -693,20 +149,14 @@ struct intc2_data {
 
 void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs);
 void init_IRQ_intc2(void);
-#endif
-
-extern int shmse_irq_demux(int irq);
 
 static inline int generic_irq_demux(int irq)
 {
        return irq;
 }
 
-#ifndef __irq_demux
-#define __irq_demux(irq)       (irq)
-#endif
 #define irq_canonicalize(irq)  (irq)
-#define irq_demux(irq)         __irq_demux(sh_mv.mv_irq_demux(irq))
+#define irq_demux(irq)         sh_mv.mv_irq_demux(irq)
 
 #ifdef CONFIG_4KSTACKS
 extern void irq_ctx_init(int cpu);
@@ -717,12 +167,4 @@ extern void irq_ctx_exit(int cpu);
 # 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 */
diff --git a/include/asm-sh/irqflags.h b/include/asm-sh/irqflags.h
new file mode 100644 (file)
index 0000000..9dedc1b
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef __ASM_SH_IRQFLAGS_H
+#define __ASM_SH_IRQFLAGS_H
+
+static inline void raw_local_irq_enable(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    %1, %0\n\t"
+#ifdef CONFIG_CPU_HAS_SR_RB
+               "stc    r6_bank, %1\n\t"
+               "or     %1, %0\n\t"
+#endif
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x000000f0)
+               : "memory"
+       );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "or     #0xf0, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&z" (flags)
+               : /* no inputs */
+               : "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\n\t"
+               : "=&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\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x10000000)
+               : "memory"
+       );
+}
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    #0xf0, %0\n\t"
+               : "=&z" (flags)
+               : /* no inputs */
+               : "memory"
+       );
+
+       return flags;
+}
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags != 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
+
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long flags, __dummy;
+
+       __asm__ __volatile__ (
+               "stc    sr, %1\n\t"
+               "mov    %1, %0\n\t"
+               "or     #0xf0, %0\n\t"
+               "ldc    %0, sr\n\t"
+               "mov    %1, %0\n\t"
+               "and    #0xf0, %0\n\t"
+               : "=&z" (flags), "=&r" (__dummy)
+               : /* no inputs */
+               : "memory"
+       );
+
+       return flags;
+}
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       if ((flags & 0xf0) != 0xf0)
+               raw_local_irq_enable();
+}
+
+#endif /* __ASM_SH_IRQFLAGS_H */
index c7088ef..46f04e2 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <asm/cpu/mmu_context.h>
 #include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -42,10 +41,8 @@ extern unsigned long mmu_context_cache;
 /*
  * Get MMU context if needed.
  */
-static __inline__ void
-get_mmu_context(struct mm_struct *mm)
+static inline void get_mmu_context(struct mm_struct *mm)
 {
-       extern void flush_tlb_all(void);
        unsigned long mc = mmu_context_cache;
 
        /* Check if we have old version of context. */
@@ -61,6 +58,7 @@ get_mmu_context(struct mm_struct *mm)
                 * Flush all TLB and start new cycle.
                 */
                flush_tlb_all();
+
                /*
                 * Fix version; Note that we avoid version #0
                 * to distingush NO_CONTEXT.
@@ -75,11 +73,10 @@ get_mmu_context(struct mm_struct *mm)
  * Initialize the context related info for a new mm_struct
  * instance.
  */
-static __inline__ int init_new_context(struct task_struct *tsk,
+static inline int init_new_context(struct task_struct *tsk,
                                       struct mm_struct *mm)
 {
        mm->context.id = NO_CONTEXT;
-
        return 0;
 }
 
@@ -87,12 +84,12 @@ static __inline__ int init_new_context(struct task_struct *tsk,
  * Destroy context related info for an mm_struct that is about
  * to be put to rest.
  */
-static __inline__ void destroy_context(struct mm_struct *mm)
+static inline void destroy_context(struct mm_struct *mm)
 {
        /* Do nothing */
 }
 
-static __inline__ void set_asid(unsigned long asid)
+static inline void set_asid(unsigned long asid)
 {
        unsigned long __dummy;
 
@@ -105,7 +102,7 @@ static __inline__ void set_asid(unsigned long asid)
                                "r" (0xffffff00));
 }
 
-static __inline__ unsigned long get_asid(void)
+static inline unsigned long get_asid(void)
 {
        unsigned long asid;
 
@@ -120,24 +117,29 @@ static __inline__ unsigned long get_asid(void)
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-static __inline__ void activate_context(struct mm_struct *mm)
+static inline void activate_context(struct mm_struct *mm)
 {
        get_mmu_context(mm);
        set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);
 }
 
-/* MMU_TTB can be used for optimizing the fault handling.
-   (Currently not used) */
-static __inline__ void switch_mm(struct mm_struct *prev,
-                                struct mm_struct *next,
-                                struct task_struct *tsk)
+/* MMU_TTB is used for optimizing the fault handling. */
+static inline void set_TTB(pgd_t *pgd)
 {
-       if (likely(prev != next)) {
-               unsigned long __pgdir = (unsigned long)next->pgd;
+       ctrl_outl((unsigned long)pgd, MMU_TTB);
+}
 
-               __asm__ __volatile__("mov.l     %0, %1"
-                                    : /* no output */
-                                    : "r" (__pgdir), "m" (__m(MMU_TTB)));
+static inline pgd_t *get_TTB(void)
+{
+       return (pgd_t *)ctrl_inl(MMU_TTB);
+}
+
+static inline void switch_mm(struct mm_struct *prev,
+                            struct mm_struct *next,
+                            struct task_struct *tsk)
+{
+       if (likely(prev != next)) {
+               set_TTB(next->pgd);
                activate_context(next);
        }
 }
@@ -147,7 +149,7 @@ static __inline__ void switch_mm(struct mm_struct *prev,
 #define activate_mm(prev, next) \
        switch_mm((prev),(next),NULL)
 
-static __inline__ void
+static inline void
 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
index ca8b26d..380fd62 100644 (file)
    [ P4 control   ]            0xE0000000
  */
 
-
 /* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT     12
+#if defined(CONFIG_PAGE_SIZE_4KB)
+# define PAGE_SHIFT    12
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+# define PAGE_SHIFT    13
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+# define PAGE_SHIFT    16
+#else
+# error "Bogus kernel page size?"
+#endif
 
 #ifdef __ASSEMBLY__
 #define PAGE_SIZE      (1 << PAGE_SHIFT)
 
 #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
 #define HPAGE_SHIFT    16
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K)
+#define HPAGE_SHIFT    18
 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
 #define HPAGE_SHIFT    20
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#define HPAGE_SHIFT    22
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
+#define HPAGE_SHIFT    26
 #endif
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -69,15 +82,25 @@ extern void __copy_user_page(void *to, void *from, void *orig_to);
 /*
  * These are used to make use of C type-checking..
  */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pgd; } pgd_t;
+#ifdef CONFIG_X2TLB
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+typedef struct { unsigned long long pgprot; } pgprot_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 pte_low; } pte_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
+#define pte_val(x)     ((x).pte_low)
+#define __pte(x) ((pte_t) { (x) } )
+#endif
+
+typedef struct { unsigned long pgd; } pgd_t;
 
-#define pte_val(x)     ((x).pte)
 #define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
 
-#define __pte(x) ((pte_t) { (x) } )
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
index e841465..888e452 100644 (file)
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
-#define pmd_populate_kernel(mm, pmd, pte) \
-               set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+                                      pte_t *pte)
+{
+       set_pmd(pmd, __pmd((unsigned long)pte));
+}
 
 static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
                                struct page *pte)
 {
-       set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
+       set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
 }
 
 /*
@@ -15,7 +18,16 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
+
+       if (pgd) {
+               memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+               memcpy(pgd + USER_PTRS_PER_PGD,
+                      swapper_pg_dir + USER_PTRS_PER_PGD,
+                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+       }
+
+       return pgd;
 }
 
 static inline void pgd_free(pgd_t *pgd)
diff --git a/include/asm-sh/pgtable-2level.h b/include/asm-sh/pgtable-2level.h
deleted file mode 100644 (file)
index b525db6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef __ASM_SH_PGTABLE_2LEVEL_H
-#define __ASM_SH_PGTABLE_2LEVEL_H
-
-/*
- * traditional two-level paging structure:
- */
-
-#define PGDIR_SHIFT    22
-#define PTRS_PER_PGD   1024
-
-/*
- * this is two-level, so we don't really have any
- * PMD directory physically.
- */
-#define PMD_SHIFT      22
-#define PTRS_PER_PMD   1
-
-#define PTRS_PER_PTE   1024
-
-#ifndef __ASSEMBLY__
-#define pte_ERROR(e) \
-       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-#define pmd_ERROR(e) \
-       printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
-#define pgd_ERROR(e) \
-       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-static inline int pgd_none(pgd_t pgd)          { return 0; }
-static inline int pgd_bad(pgd_t pgd)           { return 0; }
-static inline int pgd_present(pgd_t pgd)       { return 1; }
-static inline void pgd_clear (pgd_t * pgdp)    { }
-
-/*
- * 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 set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
-
-#define pgd_page_vaddr(pgd) \
-((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
-
-#define pgd_page(pgd) \
-       (phys_to_page(pgd_val(pgd)))
-
-static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
-{
-       return (pmd_t *) dir;
-}
-
-#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))
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ASM_SH_PGTABLE_2LEVEL_H */
index 2c8682a..c84901d 100644 (file)
 #include <asm-generic/pgtable-nopmd.h>
 #include <asm/page.h>
 
-#define PTRS_PER_PGD           1024
-
 #ifndef __ASSEMBLY__
 #include <asm/addrspace.h>
 #include <asm/fixmap.h>
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-extern void paging_init(void);
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
@@ -33,15 +28,28 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 #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)
+/*
+ * traditional two-level paging structure
+ */
+/* PTE bits */
+#ifdef CONFIG_X2TLB
+# define PTE_MAGNITUDE 3       /* 64-bit PTEs on extended mode SH-X2 TLB */
+#else
+# define PTE_MAGNITUDE 2       /* 32-bit PTEs */
+#endif
+#define PTE_SHIFT      PAGE_SHIFT
+#define PTE_BITS       (PTE_SHIFT - PTE_MAGNITUDE)
+
+/* PGD bits */
+#define PGDIR_SHIFT    (PTE_SHIFT + PTE_BITS)
+#define PGDIR_BITS     (32 - PGDIR_SHIFT)
+#define PGDIR_SIZE     (1 << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
+/* Entries per level */
+#define PTRS_PER_PTE   (PAGE_SIZE / 4)
+#define PTRS_PER_PGD   (PAGE_SIZE / 4)
+
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS     0
 
@@ -49,7 +57,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 /*
  * First 1MB map is used by fixed purpose.
- * Currently only 4-enty (16kB) is used (see arch/sh/mm/cache.c)
+ * Currently only 4-entry (16kB) is used (see arch/sh/mm/cache.c)
  */
 #define VMALLOC_START  (P3SEG+0x00100000)
 #define VMALLOC_END    (FIXADDR_START-2*PAGE_SIZE)
@@ -57,7 +65,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 /*
  * Linux PTEL encoding.
  *
- * Hardware and software bit definitions for the PTEL value:
+ * Hardware and software bit definitions for the PTEL value (see below for
+ * notes on SH-X2 MMUs and 64-bit PTEs):
  *
  * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4).
  *
@@ -76,20 +85,57 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  *
  * - 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.
+ *
+ * XXX: Leave the _PAGE_FILE and _PAGE_WT overhaul for a rainy day.
+ *
+ * SH-X2 MMUs and extended PTEs
+ *
+ * SH-X2 supports an extended mode TLB with split data arrays due to the
+ * number of bits needed for PR and SZ (now EPR and ESZ) encodings. The PR and
+ * SZ bit placeholders still exist in data array 1, but are implemented as
+ * reserved bits, with the real logic existing in data array 2.
+ *
+ * The downside to this is that we can no longer fit everything in to a 32-bit
+ * PTE encoding, so a 64-bit pte_t is necessary for these parts. On the plus
+ * side, this gives us quite a few spare bits to play with for future usage.
  */
+/* Legacy and compat mode bits */
 #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) */
+#ifndef CONFIG_X2TLB
+# 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) */
+#endif
 #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? */
 
+/* Extended mode bits */
+#define _PAGE_EXT_ESZ0         0x0010  /* ESZ0-bit: Size of page */
+#define _PAGE_EXT_ESZ1         0x0020  /* ESZ1-bit: Size of page */
+#define _PAGE_EXT_ESZ2         0x0040  /* ESZ2-bit: Size of page */
+#define _PAGE_EXT_ESZ3         0x0080  /* ESZ3-bit: Size of page */
+
+#define _PAGE_EXT_USER_EXEC    0x0100  /* EPR0-bit: User space executable */
+#define _PAGE_EXT_USER_WRITE   0x0200  /* EPR1-bit: User space writable */
+#define _PAGE_EXT_USER_READ    0x0400  /* EPR2-bit: User space readable */
+
+#define _PAGE_EXT_KERN_EXEC    0x0800  /* EPR3-bit: Kernel space executable */
+#define _PAGE_EXT_KERN_WRITE   0x1000  /* EPR4-bit: Kernel space writable */
+#define _PAGE_EXT_KERN_READ    0x2000  /* EPR5-bit: Kernel space readable */
+
+/* Wrapper for extended mode pgprot twiddling */
+#ifdef CONFIG_X2TLB
+# define _PAGE_EXT(x)          ((unsigned long long)(x) << 32)
+#else
+# define _PAGE_EXT(x)          (0)
+#endif
+
 /* software: moves to PTEA.TC (Timing Control) */
 #define _PAGE_PCC_AREA5        0x00000000      /* use BSC registers for area5 */
 #define _PAGE_PCC_AREA6        0x80000000      /* use BSC registers for area6 */
@@ -114,37 +160,160 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 #define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS))
 
-/* Hardware flags: SZ0=1 (4k-byte) */
-#define _PAGE_FLAGS_HARD       _PAGE_SZ0
+/* Hardware flags, page size encoding */
+#if defined(CONFIG_X2TLB)
+# if defined(CONFIG_PAGE_SIZE_4KB)
+#  define _PAGE_FLAGS_HARD     _PAGE_EXT(_PAGE_EXT_ESZ0)
+# elif defined(CONFIG_PAGE_SIZE_8KB)
+#  define _PAGE_FLAGS_HARD     _PAGE_EXT(_PAGE_EXT_ESZ1)
+# elif defined(CONFIG_PAGE_SIZE_64KB)
+#  define _PAGE_FLAGS_HARD     _PAGE_EXT(_PAGE_EXT_ESZ2)
+# endif
+#else
+# if defined(CONFIG_PAGE_SIZE_4KB)
+#  define _PAGE_FLAGS_HARD     _PAGE_SZ0
+# elif defined(CONFIG_PAGE_SIZE_64KB)
+#  define _PAGE_FLAGS_HARD     _PAGE_SZ1
+# endif
+#endif
 
-#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
-#define _PAGE_SZHUGE   (_PAGE_SZ1)
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
-#define _PAGE_SZHUGE   (_PAGE_SZ0 | _PAGE_SZ1)
+#if defined(CONFIG_X2TLB)
+# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
+#  define _PAGE_SZHUGE (_PAGE_EXT_ESZ2)
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K)
+#  define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ2)
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
+#  define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ1 | _PAGE_EXT_ESZ2)
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#  define _PAGE_SZHUGE (_PAGE_EXT_ESZ3)
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
+#  define _PAGE_SZHUGE (_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3)
+# endif
+#else
+# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
+#  define _PAGE_SZHUGE (_PAGE_SZ1)
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
+#  define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1)
+# endif
+#endif
+
+/*
+ * Stub out _PAGE_SZHUGE if we don't have a good definition for it,
+ * to make pte_mkhuge() happy.
+ */
+#ifndef _PAGE_SZHUGE
+# define _PAGE_SZHUGE  (_PAGE_FLAGS_HARD)
 #endif
 
-#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)
+#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_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)
+#if defined(CONFIG_X2TLB) /* SH-X2 TLB */
+#define PAGE_NONE      __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \
+                                _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
+
+#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                                _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_USER_READ | \
+                                          _PAGE_EXT_USER_WRITE))
+
+#define PAGE_EXECREAD  __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                                _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_USER_EXEC | \
+                                          _PAGE_EXT_USER_READ))
+
+#define PAGE_COPY      PAGE_EXECREAD
+
+#define PAGE_READONLY  __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                                _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_USER_READ))
+
+#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                                _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_USER_WRITE))
+
+#define PAGE_RWX       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
+                                _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_USER_WRITE | \
+                                          _PAGE_EXT_USER_READ  | \
+                                          _PAGE_EXT_USER_EXEC))
+
+#define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \
+                                _PAGE_DIRTY | _PAGE_ACCESSED | \
+                                _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_KERN_READ | \
+                                          _PAGE_EXT_KERN_WRITE | \
+                                          _PAGE_EXT_KERN_EXEC))
+
 #define PAGE_KERNEL_NOCACHE \
-                       __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
-#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
+                       __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \
+                                _PAGE_ACCESSED | _PAGE_HW_SHARED | \
+                                _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_KERN_READ | \
+                                          _PAGE_EXT_KERN_WRITE | \
+                                          _PAGE_EXT_KERN_EXEC))
+
+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \
+                                _PAGE_DIRTY | _PAGE_ACCESSED | \
+                                _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_KERN_READ | \
+                                          _PAGE_EXT_KERN_EXEC))
+
+#define PAGE_KERNEL_PCC(slot, type) \
+                       __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \
+                                _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \
+                                _PAGE_EXT(_PAGE_EXT_KERN_READ | \
+                                          _PAGE_EXT_KERN_WRITE | \
+                                          _PAGE_EXT_KERN_EXEC) \
+                                (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \
+                                (type))
+
+#elif defined(CONFIG_MMU) /* SH-X TLB */
+#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_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_EXECREAD  PAGE_READONLY
+#define PAGE_RWX       PAGE_SHARED
+#define PAGE_WRITEONLY PAGE_SHARED
+
+#define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | \
+                                _PAGE_DIRTY | _PAGE_ACCESSED | \
+                                _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
+
+#define PAGE_KERNEL_NOCACHE \
+                       __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \
+                                _PAGE_ACCESSED | _PAGE_HW_SHARED | \
+                                _PAGE_FLAGS_HARD)
+
+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \
+                                _PAGE_DIRTY | _PAGE_ACCESSED | \
+                                _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
+
 #define PAGE_KERNEL_PCC(slot, type) \
-                       __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD | (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | (type))
+                       __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \
+                                _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \
+                                (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \
+                                (type))
 #else /* no mmu */
 #define PAGE_NONE              __pgprot(0)
 #define PAGE_SHARED            __pgprot(0)
 #define PAGE_COPY              __pgprot(0)
+#define PAGE_EXECREAD          __pgprot(0)
+#define PAGE_RWX               __pgprot(0)
 #define PAGE_READONLY          __pgprot(0)
+#define PAGE_WRITEONLY         __pgprot(0)
 #define PAGE_KERNEL            __pgprot(0)
 #define PAGE_KERNEL_NOCACHE    __pgprot(0)
 #define PAGE_KERNEL_RO         __pgprot(0)
@@ -154,27 +323,32 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #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..
+ * SH-X and lower (legacy) SuperH parts (SH-3, SH-4, some SH-4A) can't do page
+ * protection for execute, and considers it the same as a read. Also, write
+ * permission implies read permission. This is the closest we can get..
+ *
+ * SH-X2 (SH7785) and later parts take this to the opposite end of the extreme,
+ * not only supporting separate execute, read, and write bits, but having
+ * completely separate permission bits for user and kernel space.
  */
+        /*xwr*/
 #define __P000 PAGE_NONE
 #define __P001 PAGE_READONLY
 #define __P010 PAGE_COPY
 #define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
+#define __P100 PAGE_EXECREAD
+#define __P101 PAGE_EXECREAD
 #define __P110 PAGE_COPY
 #define __P111 PAGE_COPY
 
 #define __S000 PAGE_NONE
 #define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
+#define __S010 PAGE_WRITEONLY
 #define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
+#define __S100 PAGE_EXECREAD
+#define __S101 PAGE_EXECREAD
+#define __S110 PAGE_RWX
+#define __S111 PAGE_RWX
 
 #ifndef __ASSEMBLY__
 
@@ -183,7 +357,17 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
+#ifdef CONFIG_X2TLB
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
+}
+#else
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#endif
+
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 /*
@@ -192,18 +376,18 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  */
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
 
-#define pte_pfn(x)             ((unsigned long)(((x).pte >> PAGE_SHIFT)))
+#define pte_pfn(x)             ((unsigned long)(((x).pte_low >> 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)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pmd_none(x)    (!pmd_val(x))
-#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#define pmd_present(x) (pmd_val(x))
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
-#define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define        pmd_bad(x)      (pmd_val(x) & ~PAGE_MASK)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 #define pte_page(x)    phys_to_page(pte_val(x)&PTE_PHYS_MASK)
@@ -212,28 +396,52 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-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_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_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_not_present(pte_t pte){ return !(pte_val(pte) & _PAGE_PRESENT); }
-
-static inline pte_t pte_rdprotect(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
-static inline pte_t pte_mkclean(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return 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_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; }
-#ifdef CONFIG_HUGETLB_PAGE
-static inline pte_t pte_mkhuge(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+#define pte_not_present(pte)   (!(pte_val(pte) & _PAGE_PRESENT))
+#define pte_dirty(pte)         (pte_val(pte) & _PAGE_DIRTY)
+#define pte_young(pte)         (pte_val(pte) & _PAGE_ACCESSED)
+#define pte_file(pte)          (pte_val(pte) & _PAGE_FILE)
+
+#ifdef CONFIG_X2TLB
+#define pte_read(pte)          ((pte).pte_high & _PAGE_EXT_USER_READ)
+#define pte_exec(pte)          ((pte).pte_high & _PAGE_EXT_USER_EXEC)
+#define pte_write(pte)         ((pte).pte_high & _PAGE_EXT_USER_WRITE)
+#else
+#define pte_read(pte)          (pte_val(pte) & _PAGE_USER)
+#define pte_exec(pte)          (pte_val(pte) & _PAGE_USER)
+#define pte_write(pte)         (pte_val(pte) & _PAGE_RW)
 #endif
 
+#define PTE_BIT_FUNC(h,fn,op) \
+static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; }
+
+#ifdef CONFIG_X2TLB
+/*
+ * We cheat a bit in the SH-X2 TLB case. As the permission bits are
+ * individually toggled (and user permissions are entirely decoupled from
+ * kernel permissions), we attempt to couple them a bit more sanely here.
+ */
+PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ);
+PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ);
+PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
+PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
+PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC);
+PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC);
+PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
+#else
+PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER);
+PTE_BIT_FUNC(low, mkread, |= _PAGE_USER);
+PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW);
+PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW);
+PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER);
+PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER);
+PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE);
+#endif
+
+PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY);
+PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY);
+PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED);
+PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
+
 /*
  * Macro and implementation to make a page protection as uncachable.
  */
@@ -258,13 +466,14 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
 #define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
-
-#define pmd_page_vaddr(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+{
+       set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) |
+                           pgprot_val(newprot)));
+       return pte;
+}
 
-#define pmd_page(pmd) \
-       (phys_to_page(pmd_val(pmd)))
+#define pmd_page_vaddr(pmd)    pmd_val(pmd)
+#define pmd_page(pmd)          (virt_to_page(pmd_val(pmd)))
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
@@ -283,8 +492,15 @@ 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)
 
+#ifdef CONFIG_X2TLB
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \
+              &(e), (e).pte_high, (e).pte_low)
+#else
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#endif
+
 #define pgd_ERROR(e) \
        printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
@@ -337,6 +553,9 @@ extern unsigned int kobjsize(const void *objp);
 extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
 #endif
 
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern void paging_init(void);
+
 #include <asm-generic/pgtable.h>
 
 #endif /* !__ASSEMBLY__ */
index 45bb74e..6f1dd7c 100644 (file)
  */
 enum cpu_type {
        /* SH-2 types */
-       CPU_SH7604,
+       CPU_SH7604, CPU_SH7619,
+
+       /* SH-2A types */
+       CPU_SH7206,
 
        /* SH-3 types */
        CPU_SH7705, CPU_SH7706, CPU_SH7707,
@@ -47,7 +50,10 @@ enum cpu_type {
        /* 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,
+
+       /* SH-4A types */
        CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
+       CPU_SH7785,
 
        /* Unknown subtype */
        CPU_SH_NONE
@@ -130,12 +136,11 @@ union sh_fpu_union {
 };
 
 struct thread_struct {
+       /* Saved registers when thread is descheduled */
        unsigned long sp;
        unsigned long pc;
 
-       unsigned long trap_no, error_code;
-       unsigned long address;
-       /* Hardware debugging registers may come here */
+       /* Hardware debugging registers */
        unsigned long ubc_pc;
 
        /* floating point info */
@@ -150,12 +155,7 @@ typedef struct {
 extern int ubc_usercnt;
 
 #define INIT_THREAD  {                                         \
-       sizeof(init_stack) + (long) &init_stack, /* sp */       \
-       0,                                       /* pc */       \
-       0, 0,                                                   \
-       0,                                                      \
-       0,                                                      \
-       {{{0,}},}                               /* fpu state */ \
+       .sp = sizeof(init_stack) + (long) &init_stack,          \
 }
 
 /*
@@ -259,8 +259,8 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
                struct pt_regs *regs);
 extern unsigned long get_wchan(struct task_struct *p);
 
-#define KSTK_EIP(tsk)  ((tsk)->thread.pc)
-#define KSTK_ESP(tsk)  ((tsk)->thread.sp)
+#define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
 
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
diff --git a/include/asm-sh/push-switch.h b/include/asm-sh/push-switch.h
new file mode 100644 (file)
index 0000000..dfc6bad
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_SH_PUSH_SWITCH_H
+#define __ASM_SH_PUSH_SWITCH_H
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+struct push_switch {
+       /* switch state */
+       unsigned int            state:1;
+       /* debounce timer */
+       struct timer_list       debounce;
+       /* workqueue */
+       struct work_struct      work;
+};
+
+struct push_switch_platform_info {
+       /* IRQ handler */
+       irqreturn_t             (*irq_handler)(int irq, void *data);
+       /* Special IRQ flags */
+       unsigned int            irq_flags;
+       /* Bit location of switch */
+       unsigned int            bit;
+       /* Symbolic switch name */
+       const char              *name;
+};
+
+#endif /* __ASM_SH_PUSH_SWITCH_H */
index 9d2aea5..4931ba8 100644 (file)
@@ -25,11 +25,21 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
        spinlock_t              wait_lock;
        struct list_head        wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map      dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
        { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-         LIST_HEAD_INIT((name).wait_list) }
+         LIST_HEAD_INIT((name).wait_list) \
+         __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name)            \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
@@ -39,6 +49,16 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+                        struct lock_class_key *key);
+
+#define init_rwsem(sem)                                \
+do {                                           \
+       static struct lock_class_key __key;     \
+                                               \
+       __init_rwsem((sem), #sem, &__key);      \
+} while (0)
+
 static inline void init_rwsem(struct rw_semaphore *sem)
 {
        sem->count = RWSEM_UNLOCKED_VALUE;
@@ -141,6 +161,11 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
                rwsem_downgrade_wake(sem);
 }
 
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+       __down_write(sem);
+}
+
 /*
  * implement exchange and add functionality
  */
diff --git a/include/asm-sh/se7206.h b/include/asm-sh/se7206.h
new file mode 100644 (file)
index 0000000..698eb80
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_SH_SE7206_H
+#define __ASM_SH_SE7206_H
+
+#define PA_SMSC                0x30000000
+#define PA_MRSHPC      0x34000000
+#define PA_LED         0x31400000
+
+void init_se7206_IRQ(void);
+
+#define __IO_PREFIX    se7206
+#include <asm/io_generic.h>
+
+#endif /* __ASM_SH_SE7206_H */
index 34ca8a7..1583c6b 100644 (file)
@@ -1,10 +1,12 @@
-#ifdef __KERNEL__
 #ifndef _SH_SETUP_H
 #define _SH_SETUP_H
 
 #define COMMAND_LINE_SIZE 256
 
+#ifdef __KERNEL__
+
 int setup_early_printk(char *);
 
-#endif /* _SH_SETUP_H */
 #endif /* __KERNEL__ */
+
+#endif /* _SH_SETUP_H */
index 3340126..b1e42e7 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
+#include <linux/irqflags.h>
 #include <asm/types.h>
 
 /*
@@ -131,103 +132,6 @@ static inline unsigned long tas(volatile int *m)
 
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 
-/* Interrupt Control */
-#ifdef CONFIG_CPU_HAS_SR_RB
-static inline void local_irq_enable(void)
-{
-       unsigned long __dummy0, __dummy1;
-
-       __asm__ __volatile__("stc       sr, %0\n\t"
-                            "and       %1, %0\n\t"
-                            "stc       r6_bank, %1\n\t"
-                            "or        %1, %0\n\t"
-                            "ldc       %0, sr"
-                            : "=&r" (__dummy0), "=r" (__dummy1)
-                            : "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)
-{
-       unsigned long __dummy;
-       __asm__ __volatile__("stc       sr, %0\n\t"
-                            "or        #0xf0, %0\n\t"
-                            "ldc       %0, sr"
-                            : "=&z" (__dummy)
-                            : /* no inputs */
-                            : "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" )
-
-#define irqs_disabled()                        \
-({                                     \
-       unsigned long flags;            \
-       local_save_flags(flags);        \
-       (flags != 0);                   \
-})
-
-static inline unsigned long local_irq_save(void)
-{
-       unsigned long flags, __dummy;
-
-       __asm__ __volatile__("stc       sr, %1\n\t"
-                            "mov       %1, %0\n\t"
-                            "or        #0xf0, %0\n\t"
-                            "ldc       %0, sr\n\t"
-                            "mov       %1, %0\n\t"
-                            "and       #0xf0, %0"
-                            : "=&z" (flags), "=&r" (__dummy)
-                            :/**/
-                            : "memory" );
-       return flags;
-}
-
-#define local_irq_restore(x) do {                      \
-       if ((x & 0x000000f0) != 0x000000f0)             \
-               local_irq_enable();                     \
-} while (0)
-
 /*
  * Jump to P2 area.
  * When handling TLB or caches, we need to do it from P2 area.
@@ -264,9 +168,6 @@ do {                                                        \
                : "=&r" (__dummy));                     \
 } while (0)
 
-/* For spinlocks etc */
-#define local_irq_save(x)      x = local_irq_save()
-
 static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 {
        unsigned long flags, retval;
index 4f9822a..f1b7b46 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 3ebc3f9..0c01dc5 100644 (file)
@@ -90,13 +90,7 @@ static inline struct thread_info *current_thread_info(void)
 #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
-
-#endif
+#endif /* __ASSEMBLY__ */
 
 /*
  * thread information flags
index 5df842b..17b5e76 100644 (file)
@@ -18,11 +18,32 @@ struct sys_timer {
 
        struct sys_device       dev;
        struct sys_timer_ops    *ops;
+
+#ifdef CONFIG_NO_IDLE_HZ
+       struct dyn_tick_timer   *dyn_tick;
+#endif
 };
 
+#ifdef CONFIG_NO_IDLE_HZ
+#define DYN_TICK_ENABLED       (1 << 1)
+
+struct dyn_tick_timer {
+       spinlock_t      lock;
+       unsigned int    state;                  /* Current state */
+       int             (*enable)(void);        /* Enables dynamic tick */
+       int             (*disable)(void);       /* Disables dynamic tick */
+       void            (*reprogram)(unsigned long); /* Reprograms the timer */
+       int             (*handler)(int, void *);
+};
+
+void timer_dyn_reprogram(void);
+#else
+#define timer_dyn_reprogram()  do { } while (0)
+#endif
+
 #define TICK_SIZE (tick_nsec / 1000)
 
-extern struct sys_timer tmu_timer;
+extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
 extern struct sys_timer *sys_timer;
 
 #ifndef CONFIG_GENERIC_TIME
index 270a4f4..03f3583 100644 (file)
@@ -1,9 +1,8 @@
 /*
  * Platform defintions for Titan
  */
-
-#ifndef _ASM_SH_TITAN_TITAN_H
-#define _ASM_SH_TITAN_TITAN_H
+#ifndef _ASM_SH_TITAN_H
+#define _ASM_SH_TITAN_H
 
 #define __IO_PREFIX titan
 #include <asm/io_generic.h>
 #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
+#endif /* __ASM_SH_TITAN_H */
index 1c2abde..f982073 100644 (file)
 
 #ifdef __KERNEL__
 
-#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)(-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); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-register long __sc0 __asm__ ("r3") = __NR_##name; \
-__asm__ __volatile__ ("trapa   #0x10" \
-       : "=z" (__sc0) \
-       : "0" (__sc0) \
-       : "memory" ); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-register long __sc0 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-__asm__ __volatile__ ("trapa   #0x11" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4) \
-       : "memory"); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-register long __sc0 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-register long __sc5 __asm__ ("r5") = (long) arg2; \
-__asm__ __volatile__ ("trapa   #0x12" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5) \
-       : "memory"); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-register long __sc0 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-register long __sc5 __asm__ ("r5") = (long) arg2; \
-register long __sc6 __asm__ ("r6") = (long) arg3; \
-__asm__ __volatile__ ("trapa   #0x13" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) \
-       : "memory"); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-register long __sc0 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-register long __sc5 __asm__ ("r5") = (long) arg2; \
-register long __sc6 __asm__ ("r6") = (long) arg3; \
-register long __sc7 __asm__ ("r7") = (long) arg4; \
-__asm__ __volatile__ ("trapa   #0x14" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6),  \
-         "r" (__sc7) \
-       : "memory" ); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
-{ \
-register long __sc3 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-register long __sc5 __asm__ ("r5") = (long) arg2; \
-register long __sc6 __asm__ ("r6") = (long) arg3; \
-register long __sc7 __asm__ ("r7") = (long) arg4; \
-register long __sc0 __asm__ ("r0") = (long) arg5; \
-__asm__ __volatile__ ("trapa   #0x15" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7),  \
-         "r" (__sc3) \
-       : "memory" ); \
-__syscall_return(type,__sc0); \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
-{ \
-register long __sc3 __asm__ ("r3") = __NR_##name; \
-register long __sc4 __asm__ ("r4") = (long) arg1; \
-register long __sc5 __asm__ ("r5") = (long) arg2; \
-register long __sc6 __asm__ ("r6") = (long) arg3; \
-register long __sc7 __asm__ ("r7") = (long) arg4; \
-register long __sc0 __asm__ ("r0") = (long) arg5; \
-register long __sc1 __asm__ ("r1") = (long) arg6; \
-__asm__ __volatile__ ("trapa   #0x16" \
-       : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7),  \
-         "r" (__sc3), "r" (__sc1) \
-       : "memory" ); \
-__syscall_return(type,__sc0); \
-}
-
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 68e27a8..5efe906 100644 (file)
@@ -35,7 +35,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
        consistent_free(NULL, size, vaddr, dma_handle);
 }
 
-static inline void dma_cache_sync(void *vaddr, size_t size,
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                                  enum dma_data_direction dir)
 {
        dma_cache_wback_inv((unsigned long)vaddr, size);
index ebd42eb..5b07b14 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ASM_SH64_SETUP_H
 #define __ASM_SH64_SETUP_H
 
+#define COMMAND_LINE_SIZE 256
+
+#ifdef __KERNEL__
+
 #define PARAM ((unsigned char *)empty_zero_page)
 #define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
 #define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
@@ -12,5 +16,7 @@
 #define COMMAND_LINE ((char *) (PARAM+256))
 #define COMMAND_LINE_SIZE 256
 
+#endif  /*  __KERNEL__  */
+
 #endif /* __ASM_SH64_SETUP_H */
 
index ee7828b..1f38a7a 100644 (file)
 #ifdef __KERNEL__ 
 
 #define NR_syscalls 321
-#include <linux/err.h>
-
-/* user-visible error numbers are in the range -1 - -MAX_ERRNO:
- * see <asm-sh64/errno.h> */
-
-#define __syscall_return(type, res) \
-do { \
-       /* Note: when returning from kernel the return value is in r9       \
-       **       This prevents conflicts between return value and arg1      \
-       **       when dispatching signal handler, in other words makes      \
-       **       life easier in the system call epilogue (see entry.S)      \
-       */                                                                  \
-        register unsigned long __sr2 __asm__ ("r2") = res;                 \
-       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {          \
-               errno = -(res);                                             \
-               __sr2 = -1;                                                 \
-       } \
-       return (type) (__sr2);                                              \
-} while (0)
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x10 << 16) | __NR_##name); \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "()"                      \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0) );                                                    \
-__syscall_return(type,__sc0);                                              \
-}
-
-       /*
-        * The apparent spurious "dummy" assembler comment is *needed*,
-        * as without it, the compiler treats the arg<n> variables
-        * as no longer live just before the asm. The compiler can
-        * then optimize the storage into any registers it wishes.
-        * The additional dummy statement forces the compiler to put
-        * the arguments into the correct registers before the TRAPA.
-        */
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x11 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2)"                    \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2));                                        \
-__asm__ __volatile__ ("!dummy  %0 %1"                                      \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2));                                        \
-__syscall_return(type,__sc0);                                              \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x12 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2,%3)"                 \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3) );                          \
-__asm__ __volatile__ ("!dummy  %0 %1 %2"                                   \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3) );                          \
-__syscall_return(type,__sc0);                                              \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2;        \
-register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2,%3,%4)"              \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );             \
-__asm__ __volatile__ ("!dummy  %0 %1 %2 %3"                                \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );             \
-__syscall_return(type,__sc0);                                              \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x14 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2;        \
-register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3;        \
-register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2,%3,%4,%5)"           \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\
-__asm__ __volatile__ ("!dummy  %0 %1 %2 %3 %4"                             \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\
-__syscall_return(type,__sc0);                                              \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x15 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2;        \
-register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3;        \
-register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4;        \
-register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2,%3,%4,%5,%6)"        \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
-         "r" (__sc6));                                                     \
-__asm__ __volatile__ ("!dummy  %0 %1 %2 %3 %4 %5"                          \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
-         "r" (__sc6));                                                     \
-__syscall_return(type,__sc0);                                              \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
-{ \
-register unsigned long __sc0 __asm__ ("r9") = ((0x16 << 16) | __NR_##name); \
-register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1;        \
-register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2;        \
-register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3;        \
-register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4;        \
-register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5;        \
-register unsigned long __sc7 __asm__ ("r7") = (unsigned long) arg6;        \
-__asm__ __volatile__ ("trapa   %1 !\t\t\t" #name "(%2,%3,%4,%5,%6,%7)"     \
-       : "=r" (__sc0)                                                      \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
-         "r" (__sc6), "r" (__sc7));                                        \
-__asm__ __volatile__ ("!dummy  %0 %1 %2 %3 %4 %5 %6"                       \
-       :                                                                   \
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
-         "r" (__sc6), "r" (__sc7));                                        \
-__syscall_return(type,__sc0);                                              \
-}
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 1794d71..5eb00a1 100644 (file)
@@ -31,6 +31,18 @@ struct termios {
 #endif
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       cc_t _x_cc[2];                  /* We need them to hold vmin/vtime */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR    0
 #define VQUIT    1
index f7827fa..d5b2f80 100644 (file)
  *          find a free slot in the 0-302 range.
  */
 
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res)\
-                     : "r" (__g1) \
-                     : "o0", "cc"); \
-if (__res < -255 || __res >= 0) \
-    return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__g1) \
-                     : "cc"); \
-if (__res < -255 || __res >= 0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__g1) \
-                     : "cc"); \
-if (__res < -255 || __res >= 0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
-                     : "cc"); \
-if (__res < -255 || __res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
-                     : "cc"); \
-if (__res < -255 || __res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-} 
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-register long __o4 __asm__ ("o4") = (long)(arg5); \
-__asm__ __volatile__ ("t 0x10\n\t" \
-                     "bcc 1f\n\t" \
-                     "mov %%o0, %0\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "1:\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
-                     : "cc"); \
-if (__res < -255 || __res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
index 27c46fb..2f858a2 100644 (file)
@@ -181,7 +181,7 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t siz
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline int
 dma_get_cache_alignment(void)
@@ -210,7 +210,7 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 }
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        /* could define this in terms of the dma_cache ... operations,
index 27f6597..93e5a06 100644 (file)
@@ -152,9 +152,9 @@ extern void dvma_init(struct sbus_bus *);
 #define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
 
 /* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs)    (((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
-#define DMA_WRITE_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
+#define DMA_ERROR_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
+#define DMA_WRITE_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
 #define DMA_OFF(__regs)                \
 do {   u32 tmp = sbus_readl((__regs) + DMA_CSR); \
        tmp &= ~DMA_ENABLE; \
index 7392fc4..876312f 100644 (file)
@@ -45,7 +45,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
                oparg = 1 << oparg;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -67,7 +67,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
diff --git a/include/asm-sparc64/irqflags.h b/include/asm-sparc64/irqflags.h
new file mode 100644 (file)
index 0000000..024fc54
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sparc64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__(
+               "rdpr   %%pil, %0"
+               : "=r" (flags)
+       );
+
+       return flags;
+}
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       __asm__ __volatile__(
+               "wrpr   %0, %%pil"
+               : /* no output */
+               : "r" (flags)
+               : "memory"
+       );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__(
+               "wrpr   15, %%pil"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory"
+       );
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__(
+               "wrpr   0, %%pil"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory"
+       );
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags > 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * For spinlocks, etc:
+ */
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_disable();
+
+       return flags;
+}
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
index c9f5c34..becc38f 100644 (file)
@@ -13,7 +13,11 @@ typedef u32 kprobe_opcode_t;
 #define JPROBE_ENTRY(pentry)   (kprobe_opcode_t *)pentry
 #define arch_remove_kprobe(p)  do {} while (0)
 #define  ARCH_INACTIVE_KPROBE_COUNT 0
-#define flush_insn_slot(p)     do { } while (0)
+
+#define flush_insn_slot(p)             \
+do {   flushi(&(p)->ainsn.insn[0]);    \
+       flushi(&(p)->ainsn.insn[1]);    \
+} while (0)
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
@@ -23,7 +27,7 @@ struct arch_specific_insn {
 
 struct prev_kprobe {
        struct kprobe *kp;
-       unsigned int status;
+       unsigned long status;
        unsigned long orig_tnpc;
        unsigned long orig_tstate_pil;
 };
@@ -33,10 +37,7 @@ struct kprobe_ctlblk {
        unsigned long kprobe_status;
        unsigned long kprobe_orig_tnpc;
        unsigned long kprobe_orig_tstate_pil;
-       long *jprobe_saved_esp;
        struct pt_regs jprobe_saved_regs;
-       struct pt_regs *jprobe_saved_regs_location;
-       struct sparc_stackf jprobe_saved_stack;
        struct prev_kprobe prev_kprobe;
 };
 
index 010f9cd..5891ff7 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/page.h>
 
 /* Page table allocation/freeing. */
-extern kmem_cache_t *pgtable_cache;
+extern struct kmem_cache *pgtable_cache;
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
index cef5e82..1294b7c 100644 (file)
@@ -23,20 +23,33 @@ struct rw_semaphore {
        signed int count;
        spinlock_t              wait_lock;
        struct list_head        wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map      dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
+{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
+  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name) \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
 
-static __inline__ void init_rwsem(struct rw_semaphore *sem)
-{
-       sem->count = RWSEM_UNLOCKED_VALUE;
-       spin_lock_init(&sem->wait_lock);
-       INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+                        struct lock_class_key *key);
+
+#define init_rwsem(sem)                                                \
+do {                                                           \
+       static struct lock_class_key __key;                     \
+                                                               \
+       __init_rwsem((sem), #sem, &__key);                      \
+} while (0)
 
 extern void __down_read(struct rw_semaphore *sem);
 extern int __down_read_trylock(struct rw_semaphore *sem);
@@ -46,6 +59,11 @@ extern void __up_read(struct rw_semaphore *sem);
 extern void __up_write(struct rw_semaphore *sem);
 extern void __downgrade_write(struct rw_semaphore *sem);
 
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+       __down_write(sem);
+}
+
 static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
 {
        return atomic_add_return(delta, (atomic_t *)(&sem->count));
index a8b7432..32281ac 100644 (file)
@@ -7,6 +7,9 @@
 #include <asm/visasm.h>
 
 #ifndef __ASSEMBLY__
+
+#include <linux/irqflags.h>
+
 /*
  * Sparc (general) CPU types
  */
@@ -72,52 +75,6 @@ do { __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
 
 #endif
 
-#define setipl(__new_ipl) \
-       __asm__ __volatile__("wrpr      %0, %%pil"  : : "r" (__new_ipl) : "memory")
-
-#define local_irq_disable() \
-       __asm__ __volatile__("wrpr      15, %%pil" : : : "memory")
-
-#define local_irq_enable() \
-       __asm__ __volatile__("wrpr      0, %%pil" : : : "memory")
-
-#define getipl() \
-({ unsigned long retval; __asm__ __volatile__("rdpr    %%pil, %0" : "=r" (retval)); retval; })
-
-#define swap_pil(__new_pil) \
-({     unsigned long retval; \
-       __asm__ __volatile__("rdpr      %%pil, %0\n\t" \
-                            "wrpr      %1, %%pil" \
-                            : "=&r" (retval) \
-                            : "r" (__new_pil) \
-                            : "memory"); \
-       retval; \
-})
-
-#define read_pil_and_cli() \
-({     unsigned long retval; \
-       __asm__ __volatile__("rdpr      %%pil, %0\n\t" \
-                            "wrpr      15, %%pil" \
-                            : "=r" (retval) \
-                            : : "memory"); \
-       retval; \
-})
-
-#define local_save_flags(flags)                ((flags) = getipl())
-#define local_irq_save(flags)          ((flags) = read_pil_and_cli())
-#define local_irq_restore(flags)               setipl((flags))
-
-/* On sparc64 IRQ flags are the PIL register.  A value of zero
- * means all interrupt levels are enabled, any other value means
- * only IRQ levels greater than that value will be received.
- * Consequently this means that the lowest IRQ level is one.
- */
-#define irqs_disabled()                \
-({     unsigned long flags;    \
-       local_save_flags(flags);\
-       (flags > 0);            \
-})
-
 #define nop()          __asm__ __volatile__ ("nop")
 
 #define read_barrier_depends()         do { } while(0)
index b077152..705cd44 100644 (file)
@@ -33,6 +33,18 @@ struct termios {
 #endif
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       cc_t _x_cc[2];                  /* We need them to hold vmin/vtime */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR    0
 #define VQUIT    1
index f235260..c2a16e1 100644 (file)
 #endif
 #define BREAKPOINT_TRAP TRAP(breakpoint_trap)
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#define TRAP_IRQ(routine, level)                       \
+       rdpr    %pil, %g2;                              \
+       wrpr    %g0, 15, %pil;                          \
+       sethi   %hi(1f-4), %g7;                         \
+       ba,pt   %xcc, etrap_irq;                        \
+        or     %g7, %lo(1f-4), %g7;                    \
+       nop;                                            \
+       nop;                                            \
+       nop;                                            \
+       .subsection     2;                              \
+1:     call    trace_hardirqs_off;                     \
+        nop;                                           \
+       mov     level, %o0;                             \
+       call    routine;                                \
+        add    %sp, PTREGS_OFF, %o1;                   \
+       ba,a,pt %xcc, rtrap_irq;                        \
+       .previous;
+
+#define TICK_SMP_IRQ                                   \
+       rdpr    %pil, %g2;                              \
+       wrpr    %g0, 15, %pil;                          \
+       sethi   %hi(1f-4), %g7;                         \
+       ba,pt   %xcc, etrap_irq;                        \
+        or     %g7, %lo(1f-4), %g7;                    \
+       nop;                                            \
+       nop;                                            \
+       nop;                                            \
+       .subsection     2;                              \
+1:     call    trace_hardirqs_off;                     \
+        nop;                                           \
+       call    smp_percpu_timer_interrupt;             \
+        add    %sp, PTREGS_OFF, %o0;                   \
+       ba,a,pt %xcc, rtrap_irq;                        \
+       .previous;
+
+#else
+
 #define TRAP_IRQ(routine, level)                       \
        rdpr    %pil, %g2;                              \
        wrpr    %g0, 15, %pil;                          \
-       b,pt    %xcc, etrap_irq;                        \
+       ba,pt   %xcc, etrap_irq;                        \
         rd     %pc, %g7;                               \
        mov     level, %o0;                             \
        call    routine;                                \
        rdpr    %pil, %g2;                              \
        wrpr    %g0, 15, %pil;                          \
        sethi   %hi(109f), %g7;                         \
-       b,pt    %xcc, etrap_irq;                        \
+       ba,pt   %xcc, etrap_irq;                        \
 109:    or     %g7, %lo(109b), %g7;                    \
        call    smp_percpu_timer_interrupt;             \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,a,pt %xcc, rtrap_irq;
 
+#endif
+
 #define TRAP_IVEC TRAP_NOSAVE(do_ivec)
 
 #define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
index 63669da..4704753 100644 (file)
  *          find a free slot in the 0-302 range.
  */
 
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res)\
-                     : "r" (__g1) \
-                     : "o0", "cc"); \
-if (__res >= 0) \
-    return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__g1) \
-                     : "cc"); \
-if (__res >= 0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__g1) \
-                     : "cc"); \
-if (__res >= 0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
-                     : "cc"); \
-if (__res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
-                     : "cc"); \
-if (__res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-} 
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##name; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-register long __o4 __asm__ ("o4") = (long)(arg5); \
-__asm__ __volatile__ ("t 0x6d\n\t" \
-                     "sub %%g0, %%o0, %0\n\t" \
-                     "movcc %%xcc, %%o0, %0\n\t" \
-                     : "=r" (__res), "=&r" (__o0) \
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
-                     : "cc"); \
-if (__res>=0) \
-       return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
 /* sysconf options, for SunOS compatibility */
 #define   _SC_ARG_MAX             1
 #define   _SC_CHILD_MAX           2
index 1e22fa2..3357c5e 100644 (file)
@@ -1,4 +1,6 @@
 #ifndef __UM_BUG_H
 #define __UM_BUG_H
-#include <asm-generic/bug.h>
+
+#include <asm/arch/bug.h>
+
 #endif
index babd298..f0ee4fb 100644 (file)
@@ -94,7 +94,7 @@ dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(d) (1)
+#define dma_is_consistent(d, h) (1)
 
 static inline int
 dma_get_cache_alignment(void)
@@ -112,7 +112,7 @@ dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
 }
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        BUG();
index 1bf096d..88687c1 100644 (file)
@@ -46,8 +46,6 @@ extern void
 init_irq_handlers (int base_irq, int num, int interval,
                   struct hw_interrupt_type *irq_type);
 
-typedef void (*irq_handler_t)(int irq, void *data, struct pt_regs *regs);
-
 /* Handle interrupt IRQ.  REGS are the registers at the time of ther
    interrupt.  */
 extern unsigned int handle_irq (int irq, struct pt_regs *regs);
index 212d4e2..f3b4330 100644 (file)
@@ -17,6 +17,17 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
index 737401e..2241ed4 100644 (file)
 #define __NR_gettid            201
 #define __NR_tkill             202
 
-
-/* Syscall protocol:
-   Syscall number in r12, args in r6-r9, r13-r14
-   Return value in r10
-   Trap 0 for `short' syscalls, where all the args can fit in function
-   call argument registers, and trap 1 when there are additional args in
-   r13-r14.  */
-
-#define SYSCALL_NUM    "r12"
-#define SYSCALL_ARG0   "r6"
-#define SYSCALL_ARG1   "r7"
-#define SYSCALL_ARG2   "r8"
-#define SYSCALL_ARG3   "r9"
-#define SYSCALL_ARG4   "r13"
-#define SYSCALL_ARG5   "r14"
-#define SYSCALL_RET    "r10"
-
-#define SYSCALL_SHORT_TRAP     "0"
-#define SYSCALL_LONG_TRAP      "1"
-
-/* Registers clobbered by any syscall.  This _doesn't_ include the syscall
-   number (r12) or the `extended arg' registers (r13, r14), even though
-   they are actually clobbered too (this is because gcc's `asm' statement
-   doesn't allow a clobber to be used as an input or output).  */
-#define SYSCALL_CLOBBERS       "r1", "r5", "r11", "r15", "r16", \
-                               "r17", "r18", "r19"
-
-/* Registers clobbered by a `short' syscall.  This includes all clobbers
-   except the syscall number (r12).  */
-#define SYSCALL_SHORT_CLOBBERS SYSCALL_CLOBBERS, "r13", "r14"
-
 #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 - -MAX_ERRNO:      \
-            see <asm-v850/errno.h> */                                        \
-         if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO), 0)) { \
-                 errno = -(res);                                             \
-                 res = -1;                                                   \
-         }                                                                   \
-         return (type) (res);                                                \
-  } while (0)
-
-
-#define _syscall0(type, name)                                                \
-type name (void)                                                             \
-{                                                                            \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP                           \
-                       : "=r" (__ret), "=r" (__syscall)                      \
-                       : "1" (__syscall)                                     \
-                       : SYSCALL_SHORT_CLOBBERS);                            \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define _syscall1(type, name, atype, a)                                              \
-type name (atype a)                                                          \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP                           \
-                       : "=r" (__ret), "=r" (__syscall)                      \
-                       : "1" (__syscall), "r" (__a)                          \
-                       : SYSCALL_SHORT_CLOBBERS);                            \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define _syscall2(type, name, atype, a, btype, b)                            \
-type name (atype a, btype b)                                                 \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register btype __b __asm__ (SYSCALL_ARG1) = b;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP                           \
-                       : "=r" (__ret), "=r" (__syscall)                      \
-                       : "1" (__syscall), "r" (__a), "r" (__b)               \
-                       : SYSCALL_SHORT_CLOBBERS);                            \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define _syscall3(type, name, atype, a, btype, b, ctype, c)                  \
-type name (atype a, btype b, ctype c)                                        \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register btype __b __asm__ (SYSCALL_ARG1) = b;                             \
-  register ctype __c __asm__ (SYSCALL_ARG2) = c;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP                           \
-                       : "=r" (__ret), "=r" (__syscall)                      \
-                       : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)    \
-                       : SYSCALL_SHORT_CLOBBERS);                            \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d)        \
-type name (atype a, btype b, ctype c, dtype d)                               \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register btype __b __asm__ (SYSCALL_ARG1) = b;                             \
-  register ctype __c __asm__ (SYSCALL_ARG2) = c;                             \
-  register dtype __d __asm__ (SYSCALL_ARG3) = d;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP                           \
-                       : "=r" (__ret), "=r" (__syscall)                      \
-                       : "1" (__syscall),                                    \
-                       "r" (__a), "r" (__b), "r" (__c), "r" (__d)            \
-                       : SYSCALL_SHORT_CLOBBERS);                            \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype,e)\
-type name (atype a, btype b, ctype c, dtype d, etype e)                              \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register btype __b __asm__ (SYSCALL_ARG1) = b;                             \
-  register ctype __c __asm__ (SYSCALL_ARG2) = c;                             \
-  register dtype __d __asm__ (SYSCALL_ARG3) = d;                             \
-  register etype __e __asm__ (SYSCALL_ARG4) = e;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP                            \
-                       : "=r" (__ret), "=r" (__syscall), "=r" (__e)          \
-                       : "1" (__syscall),                                    \
-                       "r" (__a), "r" (__b), "r" (__c), "r" (__d), "2" (__e) \
-                       : SYSCALL_CLOBBERS);                                  \
-  __syscall_return (type, __ret);                                            \
-}
-
-#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f)                              \
-  __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP                            \
-                       : "=r" (ret), "=r" (syscall),                         \
-                       "=r" (e), "=r" (f)                                    \
-                       : "1" (syscall),                                      \
-                       "r" (a), "r" (b), "r" (c), "r" (d),                   \
-                       "2" (e), "3" (f)                                      \
-                       : SYSCALL_CLOBBERS);
-
-#define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \
-type name (atype a, btype b, ctype c, dtype d, etype e, ftype f)             \
-{                                                                            \
-  register atype __a __asm__ (SYSCALL_ARG0) = a;                             \
-  register btype __b __asm__ (SYSCALL_ARG1) = b;                             \
-  register ctype __c __asm__ (SYSCALL_ARG2) = c;                             \
-  register dtype __d __asm__ (SYSCALL_ARG3) = d;                             \
-  register etype __e __asm__ (SYSCALL_ARG4) = e;                             \
-  register etype __f __asm__ (SYSCALL_ARG5) = f;                             \
-  register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;              \
-  register unsigned long __ret __asm__ (SYSCALL_RET);                        \
-  __SYSCALL6_TRAP(__syscall, __ret, __a, __b, __c, __d, __e, __f);           \
-  __syscall_return (type, __ret);                                            \
-}
-               
-
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
index 1ee9b07..ebd7117 100644 (file)
@@ -6,13 +6,11 @@ ALTARCHDEF := defined __i386__
 
 header-y += boot.h
 header-y += bootsetup.h
-header-y += cpufeature.h
 header-y += debugreg.h
 header-y += ldt.h
 header-y += msr.h
 header-y += prctl.h
 header-y += ptrace-abi.h
-header-y += setup.h
 header-y += sigcontext32.h
 header-y += ucontext.h
 header-y += vsyscall32.h
index a584826..a6657b4 100644 (file)
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <linux/stddef.h>
 #include <asm/cpufeature.h>
 
 struct alt_instr {
@@ -133,4 +134,15 @@ static inline void alternatives_smp_switch(int smp) {}
 #define LOCK_PREFIX ""
 #endif
 
+struct paravirt_patch;
+#ifdef CONFIG_PARAVIRT
+void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
+#else
+static inline void
+apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
+{}
+#define __start_parainstructions NULL
+#define __stop_parainstructions NULL
+#endif
+
 #endif /* _X86_64_ALTERNATIVE_H */
index 007e88d..706ca4b 100644 (file)
@@ -21,7 +21,7 @@
  * on us. We need to use _exactly_ the address the user gave us,
  * not some alias that contains the same information.
  */
-typedef struct { volatile int counter; } atomic_t;
+typedef struct { int counter; } atomic_t;
 
 #define ATOMIC_INIT(i) { (i) }
 
@@ -189,9 +189,9 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
 {
        int __i = i;
        __asm__ __volatile__(
-               LOCK_PREFIX "xaddl %0, %1;"
-               :"=r"(i)
-               :"m"(v->counter), "0"(i));
+               LOCK_PREFIX "xaddl %0, %1"
+               :"+r" (i), "+m" (v->counter)
+               : : "memory");
        return i + __i;
 }
 
index 80ac1fe..6826064 100644 (file)
@@ -1,30 +1,30 @@
 #ifndef __ASM_X8664_BUG_H
 #define __ASM_X8664_BUG_H 1
 
-#include <linux/stringify.h>
-
-/*
- * Tell the user there is some problem.  The exception handler decodes 
- * this frame.
- */
-struct bug_frame {
-       unsigned char ud2[2];
-       unsigned char push;
-       signed int filename;
-       unsigned char ret;
-       unsigned short line;
-} __attribute__((packed));
-
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
-/* We turn the bug frame into valid instructions to not confuse
-   the disassembler. Thanks to Jan Beulich & Suresh Siddha
-   for nice instruction selection.
-   The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
-#define BUG()                                                          \
-       asm volatile(                                                   \
-       "ud2 ; pushq $%c1 ; ret $%c0" ::                                \
-                    "i"(__LINE__), "i" (__FILE__))
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile("1:\tud2\n"                                \
+                            ".pushsection __bug_table,\"a\"\n"         \
+                            "2:\t.quad 1b, %c0\n"                      \
+                            "\t.word %c1, 0\n"                         \
+                            "\t.org 2b+%c2\n"                          \
+                            ".popsection"                              \
+                            : : "i" (__FILE__), "i" (__LINE__),        \
+                               "i" (sizeof(struct bug_entry)));        \
+               for(;;) ;                                               \
+       } while(0)
+#else
+#define BUG()                                                          \
+       do {                                                            \
+               asm volatile("ud2");                                    \
+               for(;;) ;                                               \
+       } while(0)
+#endif
+
 void out_of_line_bug(void);
 #else
 static inline void out_of_line_bug(void) { }
index 6b93f5a..7ee9006 100644 (file)
@@ -51,6 +51,8 @@ struct iommu_table {
 #define TCE_TABLE_SIZE_4M              6
 #define TCE_TABLE_SIZE_8M              7
 
+extern int use_calgary;
+
 #ifdef CONFIG_CALGARY_IOMMU
 extern int calgary_iommu_init(void);
 extern void detect_calgary(void);
index ee792fa..0b3c686 100644 (file)
@@ -29,7 +29,7 @@
 #define X86_FEATURE_PSE36      (0*32+17) /* 36-bit PSEs */
 #define X86_FEATURE_PN         (0*32+18) /* Processor serial number */
 #define X86_FEATURE_CLFLSH     (0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DTES       (0*32+21) /* Debug Trace Store */
+#define X86_FEATURE_DS         (0*32+21) /* Debug Store */
 #define X86_FEATURE_ACPI       (0*32+22) /* ACPI via MSR */
 #define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
 #define X86_FEATURE_FXSR       (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
@@ -68,6 +68,8 @@
 #define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
 #define X86_FEATURE_UP         (3*32+8) /* SMP kernel running on UP */
 #define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS       (3*32+10) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS                (3*32+11) /* Branch Trace Store */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define cpu_has_cyrix_arr      0
 #define cpu_has_centaur_mcr    0
 #define cpu_has_clflush               boot_cpu_has(X86_FEATURE_CLFLSH)
+#define cpu_has_ds            boot_cpu_has(X86_FEATURE_DS)
+#define cpu_has_pebs          boot_cpu_has(X86_FEATURE_PEBS)
+#define cpu_has_bts           boot_cpu_has(X86_FEATURE_BTS)
 
 #endif /* __ASM_X8664_CPUFEATURE_H */
index 65f64ac..c2669f1 100644 (file)
@@ -7,18 +7,21 @@
  * Delay routines calling functions in arch/x86_64/lib/delay.c
  */
  
+/* Undefined functions to get compile-time errors */
 extern void __bad_udelay(void);
 extern void __bad_ndelay(void);
 
 extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
 extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
+/* 0x10c7 is 2**32 / 1000000 (rounded up) */
 #define udelay(n) (__builtin_constant_p(n) ? \
-       ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
+       ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
        __udelay(n))
 
+/* 0x5 is 2**32 / 1000000000 (rounded up) */
 #define ndelay(n) (__builtin_constant_p(n) ? \
        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
        __ndelay(n))
index eb7723a..913d6ac 100644 (file)
@@ -9,64 +9,13 @@
 
 #include <linux/string.h>
 #include <linux/smp.h>
+#include <asm/desc_defs.h>
 
 #include <asm/segment.h>
 #include <asm/mmu.h>
 
-// 8 byte segment descriptor
-struct desc_struct { 
-       u16 limit0;
-       u16 base0;
-       unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
-       unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
-} __attribute__((packed)); 
-
-struct n_desc_struct { 
-       unsigned int a,b;
-};     
-
 extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
 
-enum { 
-       GATE_INTERRUPT = 0xE, 
-       GATE_TRAP = 0xF,        
-       GATE_CALL = 0xC,
-};     
-
-// 16byte gate
-struct gate_struct {          
-       u16 offset_low;
-       u16 segment; 
-       unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
-       u16 offset_middle;
-       u32 offset_high;
-       u32 zero1; 
-} __attribute__((packed));
-
-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF) 
-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
-
-enum { 
-       DESC_TSS = 0x9,
-       DESC_LDT = 0x2,
-}; 
-
-// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc { 
-       u16 limit0;
-       u16 base0;
-       unsigned base1 : 8, type : 5, dpl : 2, p : 1;
-       unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
-       u32 base3;
-       u32 zero1; 
-} __attribute__((packed)); 
-
-struct desc_ptr {
-       unsigned short size;
-       unsigned long address;
-} __attribute__((packed)) ;
-
 #define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
 #define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
 #define clear_LDT()  asm volatile("lldt %w0"::"r" (0))
diff --git a/include/asm-x86_64/desc_defs.h b/include/asm-x86_64/desc_defs.h
new file mode 100644 (file)
index 0000000..0890040
--- /dev/null
@@ -0,0 +1,69 @@
+/* Written 2000 by Andi Kleen */
+#ifndef __ARCH_DESC_DEFS_H
+#define __ARCH_DESC_DEFS_H
+
+/*
+ * Segment descriptor structure definitions, usable from both x86_64 and i386
+ * archs.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+// 8 byte segment descriptor
+struct desc_struct {
+       u16 limit0;
+       u16 base0;
+       unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
+       unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
+} __attribute__((packed));
+
+struct n_desc_struct {
+       unsigned int a,b;
+};
+
+enum {
+       GATE_INTERRUPT = 0xE,
+       GATE_TRAP = 0xF,
+       GATE_CALL = 0xC,
+};
+
+// 16byte gate
+struct gate_struct {
+       u16 offset_low;
+       u16 segment;
+       unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
+       u16 offset_middle;
+       u32 offset_high;
+       u32 zero1;
+} __attribute__((packed));
+
+#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
+#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
+#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+
+enum {
+       DESC_TSS = 0x9,
+       DESC_LDT = 0x2,
+};
+
+// LDT or TSS descriptor in the GDT. 16 bytes.
+struct ldttss_desc {
+       u16 limit0;
+       u16 base0;
+       unsigned base1 : 8, type : 5, dpl : 2, p : 1;
+       unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
+       u32 base3;
+       u32 zero1;
+} __attribute__((packed));
+
+struct desc_ptr {
+       unsigned short size;
+       unsigned long address;
+} __attribute__((packed)) ;
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
index 10174b1..be9ec68 100644 (file)
@@ -180,12 +180,13 @@ static inline int dma_get_cache_alignment(void)
        return boot_cpu_data.x86_clflush_size;
 }
 
-#define dma_is_consistent(h) 1
+#define dma_is_consistent(d, h) 1
 
 extern int dma_set_mask(struct device *dev, u64 mask);
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+       enum dma_data_direction dir)
 {
        flush_write_buffers();
 }
index 9804bf0..5cdfb08 100644 (file)
@@ -55,7 +55,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -78,7 +78,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
index a0e9a4b..b80f4bb 100644 (file)
@@ -30,6 +30,6 @@ struct genapic {
 };
 
 
-extern struct genapic *genapic;
+extern struct genapic *genapic, *genapic_force, apic_flat;
 
 #endif
index 62caf8b..3fc0b15 100644 (file)
 #define TIOCSBRK       0x5427  /* BSD compatibility */
 #define TIOCCBRK       0x5428  /* BSD compatibility */
 #define TIOCGSID       0x5429  /* Return the session ID of FD */
+#define TCGETS2                _IOR('T',0x2A, struct termios2)
+#define TCSETS2                _IOW('T',0x2B, struct termios2)
+#define TCSETSW2       _IOW('T',0x2C, struct termios2)
+#define TCSETSF2       _IOW('T',0x2D, struct termios2)
 #define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
 
index 37e1941..952783d 100644 (file)
@@ -169,8 +169,8 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #define MSR_LSTAR 0xc0000082           /* long mode SYSCALL target */
 #define MSR_CSTAR 0xc0000083           /* compatibility mode SYSCALL target */
 #define MSR_SYSCALL_MASK 0xc0000084    /* EFLAGS mask for syscall */
-#define MSR_FS_BASE 0xc0000100         /* 64bit GS base */
-#define MSR_GS_BASE 0xc0000101         /* 64bit FS base */
+#define MSR_FS_BASE 0xc0000100         /* 64bit FS base */
+#define MSR_GS_BASE 0xc0000101         /* 64bit GS base */
 #define MSR_KERNEL_GS_BASE  0xc0000102 /* SwapGS GS shadow (or USER_GS from kernel) */ 
 /* EFER bits: */ 
 #define _EFER_SCE 0  /* SYSCALL/SYSRET */
@@ -210,6 +210,10 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #define MSR_IA32_LASTINTFROMIP     0x1dd
 #define MSR_IA32_LASTINTTOIP       0x1de
 
+#define MSR_IA32_PEBS_ENABLE           0x3f1
+#define MSR_IA32_DS_AREA               0x600
+#define MSR_IA32_PERF_CAPABILITIES     0x345
+
 #define MSR_MTRRfix64K_00000   0x250
 #define MSR_MTRRfix16K_80000   0x258
 #define MSR_MTRRfix16K_A0000   0x259
@@ -407,4 +411,13 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #define MSR_P4_U2L_ESCR0               0x3b0
 #define MSR_P4_U2L_ESCR1               0x3b1
 
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0       0x309
+#define MSR_CORE_PERF_FIXED_CTR1       0x30a
+#define MSR_CORE_PERF_FIXED_CTR2       0x30b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x38d
+#define MSR_CORE_PERF_GLOBAL_STATUS    0x38e
+#define MSR_CORE_PERF_GLOBAL_CTRL      0x38f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x390
+
 #endif
index f367d40..72375e7 100644 (file)
@@ -77,4 +77,7 @@ extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
 
 extern int unknown_nmi_panic;
 
+void __trigger_all_cpu_backtrace(void);
+#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+
 #endif /* ASM_NMI_H */
index eba9cb4..6823fa4 100644 (file)
@@ -10,6 +10,7 @@ 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);
+extern void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val);
 
 extern int early_pci_allowed(void);
 
index 0555c1c..59901c6 100644 (file)
@@ -221,20 +221,19 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 #define __S110 PAGE_SHARED_EXEC
 #define __S111 PAGE_SHARED_EXEC
 
-static inline unsigned long pgd_bad(pgd_t pgd) 
-{ 
-       unsigned long val = pgd_val(pgd);
-       val &= ~PTE_MASK; 
-       val &= ~(_PAGE_USER | _PAGE_DIRTY); 
-       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);      
-} 
+static inline unsigned long pgd_bad(pgd_t pgd)
+{
+       return pgd_val(pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
+}
 
 static inline unsigned long pud_bad(pud_t pud)
 {
-       unsigned long val = pud_val(pud);
-       val &= ~PTE_MASK;
-       val &= ~(_PAGE_USER | _PAGE_DIRTY);
-       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);
+       return pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
+}
+
+static inline unsigned long pmd_bad(pmd_t pmd)
+{
+       return pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
 }
 
 #define pte_none(x)    (!pte_val(x))
@@ -347,7 +346,6 @@ static inline int pmd_large(pmd_t pte) {
 #define pmd_none(x)    (!pmd_val(x))
 #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
-#define        pmd_bad(x)      ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE )
 #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
 #define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
 
index cef17e0..76552d7 100644 (file)
@@ -475,6 +475,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
                : :"a" (eax), "c" (ecx));
 }
 
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+       /* "mwait %eax,%ecx;" */
+       asm volatile(
+               "sti; .byte 0x0f,0x01,0xc9;"
+               : :"a" (eax), "c" (ecx));
+}
+
 extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
 
 #define stack_current() \
index e72cfcd..6d324b8 100644 (file)
@@ -61,7 +61,6 @@ extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
 extern unsigned long numa_free_all_bootmem(void);
 
 extern void reserve_bootmem_generic(unsigned long phys, unsigned len);
-extern void free_bootmem_generic(unsigned long phys, unsigned len);
 
 extern void load_gs_index(unsigned gs);
 
@@ -88,6 +87,7 @@ extern void syscall32_cpu_init(void);
 extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);
 
 extern void early_quirks(void);
+extern void quirk_intel_irqbalance(void);
 extern void check_efer(void);
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
diff --git a/include/asm-x86_64/rio.h b/include/asm-x86_64/rio.h
new file mode 100644 (file)
index 0000000..c7350f6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Derived from include/asm-i386/mach-summit/mach_mpparse.h
+ *          and include/asm-i386/mach-default/bios_ebda.h
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ */
+
+#ifndef __ASM_RIO_H
+#define __ASM_RIO_H
+
+#define RIO_TABLE_VERSION      3
+
+struct rio_table_hdr {
+       u8 version;      /* Version number of this data structure  */
+       u8 num_scal_dev; /* # of Scalability devices               */
+       u8 num_rio_dev;  /* # of RIO I/O devices                   */
+} __attribute__((packed));
+
+struct scal_detail {
+       u8 node_id;      /* Scalability Node ID                    */
+       u32 CBAR;        /* Address of 1MB register space          */
+       u8 port0node;    /* Node ID port connected to: 0xFF=None   */
+       u8 port0port;    /* Port num port connected to: 0,1,2, or  */
+                        /* 0xFF=None                              */
+       u8 port1node;    /* Node ID port connected to: 0xFF = None */
+       u8 port1port;    /* Port num port connected to: 0,1,2, or  */
+                        /* 0xFF=None                              */
+       u8 port2node;    /* Node ID port connected to: 0xFF = None */
+       u8 port2port;    /* Port num port connected to: 0,1,2, or  */
+                        /* 0xFF=None                              */
+       u8 chassis_num;  /* 1 based Chassis number (1 = boot node) */
+} __attribute__((packed));
+
+struct rio_detail {
+       u8 node_id;      /* RIO Node ID                            */
+       u32 BBAR;        /* Address of 1MB register space          */
+       u8 type;         /* Type of device                         */
+       u8 owner_id;     /* Node ID of Hurricane that owns this    */
+                        /* node                                   */
+       u8 port0node;    /* Node ID port connected to: 0xFF=None   */
+       u8 port0port;    /* Port num port connected to: 0,1,2, or  */
+                        /* 0xFF=None                              */
+       u8 port1node;    /* Node ID port connected to: 0xFF=None   */
+       u8 port1port;    /* Port num port connected to: 0,1,2, or  */
+                        /* 0xFF=None                              */
+       u8 first_slot;   /* Lowest slot number below this Calgary  */
+       u8 status;       /* Bit 0 = 1 : the XAPIC is used          */
+                        /*       = 0 : the XAPIC is not used, ie: */
+                        /*            ints fwded to another XAPIC */
+                        /*           Bits1:7 Reserved             */
+       u8 WP_index;     /* instance index - lower ones have       */
+                        /*     lower slot numbers/PCI bus numbers */
+       u8 chassis_num;  /* 1 based Chassis number                 */
+} __attribute__((packed));
+
+enum {
+       HURR_SCALABILTY = 0,  /* Hurricane Scalability info */
+       HURR_RIOIB      = 2,  /* Hurricane RIOIB info       */
+       COMPAT_CALGARY  = 4,  /* Compatibility Calgary      */
+       ALT_CALGARY     = 5,  /* Second Planar Calgary      */
+};
+
+/*
+ * there is a real-mode segmented pointer pointing to the
+ * 4K EBDA area at 0x40E.
+ */
+static inline unsigned long get_bios_ebda(void)
+{
+       unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
+       address <<= 4;
+       return address;
+}
+
+#endif /* __ASM_RIO_H */
index d6b7c05..e17b9ec 100644 (file)
@@ -82,11 +82,6 @@ extern u8 x86_cpu_to_apicid[NR_CPUS];        /* physical ID */
 extern u8 x86_cpu_to_log_apicid[NR_CPUS];
 extern u8 bios_cpu_apicid[];
 
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
-{
-       return cpus_addr(cpumask)[0];
-}
-
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
        if (mps_cpu < NR_CPUS)
@@ -118,13 +113,6 @@ static __inline int logical_smp_processor_id(void)
 #define cpu_physical_id(cpu)           x86_cpu_to_apicid[cpu]
 #else
 #define cpu_physical_id(cpu)           boot_cpu_id
-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 05ef097..88bf981 100644 (file)
@@ -36,7 +36,34 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
                "2:\t" : "=m" (lock->slock) : : "memory");
 }
 
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+/*
+ * Same as __raw_spin_lock, but reenable interrupts during spinning.
+ */
+#ifndef CONFIG_PROVE_LOCKING
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+       asm volatile(
+               "\n1:\t"
+               LOCK_PREFIX " ; decl %0\n\t"
+               "jns 5f\n"
+               "testl $0x200, %1\n\t"  /* interrupts were disabled? */
+               "jz 4f\n\t"
+               "sti\n"
+               "3:\t"
+               "rep;nop\n\t"
+               "cmpl $0, %0\n\t"
+               "jle 3b\n\t"
+               "cli\n\t"
+               "jmp 1b\n"
+               "4:\t"
+               "rep;nop\n\t"
+               "cmpl $0, %0\n\t"
+               "jg 1b\n\t"
+               "jmp 4b\n"
+               "5:\n\t"
+               : "+m" (lock->slock) : "r" ((unsigned)flags) : "memory");
+}
+#endif
 
 static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
index 59efe84..4da9345 100644 (file)
@@ -6,13 +6,13 @@
 #endif
 
 typedef struct {
-       volatile unsigned int slock;
+       unsigned int slock;
 } raw_spinlock_t;
 
 #define __RAW_SPIN_LOCK_UNLOCKED       { 1 }
 
 typedef struct {
-       volatile unsigned int lock;
+       unsigned int lock;
 } raw_rwlock_t;
 
 #define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
index 5eb9799..6f0b545 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_STACKTRACE_H
 #define _ASM_STACKTRACE_H 1
 
+extern int kstack_depth_to_print;
+
 /* Generic stack tracer with callbacks */
 
 struct stacktrace_ops {
index bd95094..6cfc3bb 100644 (file)
@@ -17,6 +17,28 @@ struct termios {
        cc_t c_cc[NCCS];                /* control characters */
 };
 
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
 /* c_cc characters */
 #define VINTR 0
 #define VQUIT 1
@@ -118,6 +140,7 @@ struct termios {
 #define HUPCL  0002000
 #define CLOCAL 0004000
 #define CBAUDEX 0010000
+#define           BOTHER 0010000               /* non standard rate */
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -133,10 +156,12 @@ struct termios {
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD   002003600000  /* input baud rate (not used) */
+#define CIBAUD   002003600000  /* input baud rate */
 #define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
 
+#define IBSHIFT          8             /* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG   0000001
 #define ICANON 0000002
index 041a91f..443b225 100644 (file)
@@ -98,8 +98,10 @@ struct termio {
        copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif /* __KERNEL__ */
 
index 5c8f492..2facec5 100644 (file)
@@ -47,6 +47,7 @@ extern int __node_distance(int, int);
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_FORK       \
                                | SD_BALANCE_EXEC       \
+                               | SD_SERIALIZE          \
                                | SD_WAKE_BALANCE,      \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
index 777288e..c5f596e 100644 (file)
@@ -622,25 +622,7 @@ __SYSCALL(__NR_move_pages, sys_move_pages)
 
 #define __NR_syscall_max __NR_move_pages
 
-#ifdef __KERNEL__
-#include <linux/err.h>
-#endif
-
 #ifndef __NO_STUBS
-
-/* 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)(-MAX_ERRNO)) { \
-               errno = -(res); \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
 #define __ARCH_WANT_SYS_ALARM
@@ -664,87 +646,6 @@ do { \
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_TIME
 
-#define __syscall "syscall"
-
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name) : __syscall_clobber ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)) : __syscall_clobber ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)) : __syscall_clobber ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \
-                 "d" ((long)(arg3)) : __syscall_clobber); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-__asm__ volatile ("movq %5,%%r10 ;" __syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \
-         "d" ((long)(arg3)),"g" ((long)(arg4)) : __syscall_clobber,"r10" ); \
-__syscall_return(type,__res); \
-} 
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \
-         "d" ((long)(arg3)),"g" ((long)(arg4)),"g" ((long)(arg5)) : \
-       __syscall_clobber,"r8","r10" ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-         type5,arg5,type6,arg6) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
-{ \
-long __res; \
-__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; movq %7,%%r9 ; " __syscall \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \
-         "d" ((long)(arg3)), "g" ((long)(arg4)), "g" ((long)(arg5)), \
-         "g" ((long)(arg6)) : \
-       __syscall_clobber,"r8","r10","r9" ); \
-__syscall_return(type,__res); \
-}
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
index 2e7ff10..2f6349e 100644 (file)
@@ -87,14 +87,10 @@ extern int arch_unwind_init_running(struct unwind_frame_info *,
 
 static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 {
-#if 0 /* This can only work when selector register saves/restores
-         are properly annotated (and tracked in UNW_REGISTER_INFO). */
-       return user_mode(&info->regs);
-#else
-       return (long)info->regs.rip >= 0
+       return user_mode(&info->regs)
+              || (long)info->regs.rip >= 0
               || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
               || (long)info->regs.rsp >= 0;
-#endif
 }
 
 #else
index 01d1c17..05cb8dd 100644 (file)
@@ -10,6 +10,7 @@ enum vsyscall_num {
 #define VSYSCALL_START (-10UL << 20)
 #define VSYSCALL_SIZE 1024
 #define VSYSCALL_END (-2UL << 20)
+#define VSYSCALL_MAPPED_PAGES 1
 #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
 
 #ifdef __KERNEL__
diff --git a/include/asm-xtensa/asmmacro.h b/include/asm-xtensa/asmmacro.h
new file mode 100644 (file)
index 0000000..76915ca
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * include/asm-xtensa/asmmacro.h
+ *
+ * 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) 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ASMMACRO_H
+#define _XTENSA_ASMMACRO_H
+
+#include <asm/variant/core.h>
+
+/*
+ * Some little helpers for loops. Use zero-overhead-loops
+ * where applicable and if supported by the processor.
+ *
+ * __loopi ar, at, size, inc
+ *         ar  register initialized with the start address
+ *        at   scratch register used by macro
+ *        size size immediate value
+ *        inc  increment
+ *
+ * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
+ *        ar   register initialized with the start address
+ *        as   register initialized with the size
+ *        at   scratch register use by macro
+ *        inc_log2     increment [in log2]
+ *        mask_log2    mask [in log2]
+ *        cond         true condition (used in loop'cond')
+ *        ncond        false condition (used in b'ncond')
+ *
+ * __loop  as
+ *        restart loop. 'as' register must not have been modified!
+ *
+ * __endla ar, at, incr
+ *        ar   start address (modified)
+ *        as   scratch register used by macro
+ *        inc  increment
+ */
+
+/*
+ * loop for given size as immediate
+ */
+
+       .macro  __loopi ar, at, size, incr
+
+#if XCHAL_HAVE_LOOPS
+               movi    \at, ((\size + \incr - 1) / (\incr))
+               loop    \at, 99f
+#else
+               addi    \at, \ar, \size
+               98:
+#endif
+
+       .endm
+
+/*
+ * loop for given size in register
+ */
+
+       .macro  __loops ar, as, at, incr_log2, mask_log2, cond, ncond
+
+#if XCHAL_HAVE_LOOPS
+               .ifgt \incr_log2 - 1
+                       addi    \at, \as, (1 << \incr_log2) - 1
+                       .ifnc \mask_log2,
+                               extui   \at, \at, \incr_log2, \mask_log2
+                       .else
+                               srli    \at, \at, \incr_log2
+                       .endif
+               .endif
+               loop\cond       \at, 99f
+#else
+               .ifnc \mask_log2,
+                       extui   \at, \as, \incr_log2, \mask_log2
+               .else
+                       .ifnc \ncond,
+                               srli    \at, \as, \incr_log2
+                       .endif
+               .endif
+               .ifnc \ncond,
+                       b\ncond \at, 99f
+
+               .endif
+               .ifnc \mask_log2,
+                       slli    \at, \at, \incr_log2
+                       add     \at, \ar, \at
+               .else
+                       add     \at, \ar, \as
+               .endif
+#endif
+               98:
+
+       .endm
+
+/*
+ * loop from ar to ax
+ */
+
+       .macro  __loopt ar, as, at, incr_log2
+
+#if XCHAL_HAVE_LOOPS
+               sub     \at, \as, \ar
+               .ifgt   \incr_log2 - 1
+                       addi    \at, \at, (1 << \incr_log2) - 1
+                       srli    \at, \at, \incr_log2
+               .endif
+               loop    \at, 99f
+#else
+               98:
+#endif
+
+       .endm
+
+/*
+ * restart loop. registers must be unchanged
+ */
+
+       .macro  __loop  as
+
+#if XCHAL_HAVE_LOOPS
+               loop    \as, 99f
+#else
+               98:
+#endif
+
+       .endm
+
+/*
+ * end of loop with no increment of the address.
+ */
+
+       .macro  __endl  ar, as
+#if !XCHAL_HAVE_LOOPS
+               bltu    \ar, \as, 98b
+#endif
+               99:
+       .endm
+
+/*
+ * end of loop with increment of the address.
+ */
+
+       .macro  __endla ar, as, incr
+               addi    \ar, \ar, \incr
+               __endl  \ar \as
+       .endm
+
+
+#endif /* _XTENSA_ASMMACRO_H */
index 5670365..3e52d72 100644 (file)
 #ifndef _XTENSA_BUG_H
 #define _XTENSA_BUG_H
 
-#include <linux/stringify.h>
-
-#define ILL    __asm__ __volatile__ (".byte 0,0,0\n")
-
-#ifdef CONFIG_KALLSYMS
-# define BUG() do {                                                    \
-       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);           \
-       ILL;                                                            \
-} while (0)
-#else
-# define BUG() do {                                                    \
-       printk("kernel BUG!\n");                                        \
-       ILL;                                                            \
-} while (0)
-#endif
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) do {  BUG(); } while (0)
-#define WARN_ON(condition) do {                                                   \
-  if (unlikely((condition)!=0)) {                                         \
-    printk ("Warning in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-      dump_stack();                                                       \
-  }                                                                       \
-} while (0)
+#include <asm-generic/bug.h>
 
 #endif /* _XTENSA_BUG_H */
index 0b15525..0f540a5 100644 (file)
 #ifndef _XTENSA_BYTEORDER_H
 #define _XTENSA_BYTEORDER_H
 
-#include <asm/processor.h>
 #include <asm/types.h>
 
-static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
 {
     __u32 res;
     /* instruction sequence from Xtensa ISA release 2/2000 */
@@ -29,7 +28,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
     return res;
 }
 
-static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
 {
     /* Given that 'short' values are signed (i.e., can be negative),
      * we cannot assume that the upper 16-bits of the register are
index 1e79c0e..1c4a78f 100644 (file)
@@ -4,7 +4,6 @@
  * 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.
- * 2 of the License, or (at your option) any later version.
  *
  * (C) 2001 - 2005 Tensilica Inc.
  */
 #ifndef _XTENSA_CACHE_H
 #define _XTENSA_CACHE_H
 
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
-#if XCHAL_ICACHE_SIZE > 0
-# if (XCHAL_ICACHE_SIZE % (XCHAL_ICACHE_LINESIZE*XCHAL_ICACHE_WAYS*4)) != 0
-#  error cache configuration outside expected/supported range!
-# endif
-#endif
+#define L1_CACHE_SHIFT XCHAL_DCACHE_LINEWIDTH
+#define L1_CACHE_BYTES XCHAL_DCACHE_LINESIZE
+#define SMP_CACHE_BYTES        L1_CACHE_BYTES
 
-#if XCHAL_DCACHE_SIZE > 0
-# if (XCHAL_DCACHE_SIZE % (XCHAL_DCACHE_LINESIZE*XCHAL_DCACHE_WAYS*4)) != 0
-#  error cache configuration outside expected/supported range!
-# endif
-#endif
+#define DCACHE_WAY_SIZE        (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS)
+#define ICACHE_WAY_SIZE        (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS)
 
-#define L1_CACHE_SHIFT         XCHAL_CACHE_LINEWIDTH_MAX
-#define L1_CACHE_BYTES         XCHAL_CACHE_LINESIZE_MAX
 
 #endif /* _XTENSA_CACHE_H */
diff --git a/include/asm-xtensa/cacheasm.h b/include/asm-xtensa/cacheasm.h
new file mode 100644 (file)
index 0000000..2c20a58
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * include/asm-xtensa/cacheasm.h
+ *
+ * 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) 2006 Tensilica Inc.
+ */
+
+#include <asm/cache.h>
+#include <asm/asmmacro.h>
+#include <linux/stringify.h>
+
+/*
+ * Define cache functions as macros here so that they can be used
+ * by the kernel and boot loader. We should consider moving them to a
+ * library that can be linked by both.
+ *
+ * Locking
+ *
+ *   ___unlock_dcache_all
+ *   ___unlock_icache_all
+ *
+ * Flush and invaldating
+ *
+ *   ___flush_invalidate_dcache_{all|range|page}
+ *   ___flush_dcache_{all|range|page}
+ *   ___invalidate_dcache_{all|range|page}
+ *   ___invalidate_icache_{all|range|page}
+ *
+ */
+
+       .macro  __loop_cache_all ar at insn size line_width
+
+       movi    \ar, 0
+
+       __loopi \ar, \at, \size, (4 << (\line_width))
+       \insn   \ar, 0 << (\line_width)
+       \insn   \ar, 1 << (\line_width)
+       \insn   \ar, 2 << (\line_width)
+       \insn   \ar, 3 << (\line_width)
+       __endla \ar, \at, 4 << (\line_width)
+
+       .endm
+
+
+       .macro  __loop_cache_range ar as at insn line_width
+
+       extui   \at, \ar, 0, \line_width
+       add     \as, \as, \at
+
+       __loops \ar, \as, \at, \line_width
+       \insn   \ar, 0
+       __endla \ar, \at, (1 << (\line_width))
+
+       .endm
+
+
+       .macro  __loop_cache_page ar at insn line_width
+
+       __loopi \ar, \at, PAGE_SIZE, 4 << (\line_width)
+       \insn   \ar, 0 << (\line_width)
+       \insn   \ar, 1 << (\line_width)
+       \insn   \ar, 2 << (\line_width)
+       \insn   \ar, 3 << (\line_width)
+       __endla \ar, \at, 4 << (\line_width)
+
+       .endm
+
+
+#if XCHAL_DCACHE_LINE_LOCKABLE
+
+       .macro  ___unlock_dcache_all ar at
+
+       __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+#endif
+
+#if XCHAL_ICACHE_LINE_LOCKABLE
+
+       .macro  ___unlock_icache_all ar at
+
+       __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH
+
+       .endm
+#endif
+
+       .macro  ___flush_invalidate_dcache_all ar at
+
+       __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___flush_dcache_all ar at
+
+       __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_dcache_all ar at
+
+       __loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \
+                        XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_icache_all ar at
+
+       __loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \
+                        XCHAL_ICACHE_LINEWIDTH
+
+       .endm
+
+
+
+       .macro  ___flush_invalidate_dcache_range ar as at
+
+       __loop_cache_range \ar \as \at dhwbi XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___flush_dcache_range ar as at
+
+       __loop_cache_range \ar \as \at dhwb XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_dcache_range ar as at
+
+       __loop_cache_range \ar \as \at dhi XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_icache_range ar as at
+
+       __loop_cache_range \ar \as \at ihi XCHAL_ICACHE_LINEWIDTH
+
+       .endm
+
+
+
+       .macro  ___flush_invalidate_dcache_page ar as
+
+       __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro ___flush_dcache_page ar as
+
+       __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_dcache_page ar as
+
+       __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH
+
+       .endm
+
+
+       .macro  ___invalidate_icache_page ar as
+
+       __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
+
+       .endm
+
index 44a36e0..337765b 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * (C) 2001 - 2005 Tensilica Inc.
+ * (C) 2001 - 2006 Tensilica Inc.
  */
 
 #ifndef _XTENSA_CACHEFLUSH_H
index 5435aff..23534c6 100644 (file)
@@ -12,7 +12,7 @@
 #define _XTENSA_CHECKSUM_H
 
 #include <linux/in6.h>
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
 /*
  * computes the checksum of a memory block at buff, length len,
index 5093034..bd09ec0 100644 (file)
 #ifndef _XTENSA_COPROCESSOR_H
 #define _XTENSA_COPROCESSOR_H
 
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
+#include <asm/variant/tie.h>
+
+#if !XCHAL_HAVE_CP
+
+#define XTENSA_CP_EXTRA_OFFSET         0
+#define XTENSA_CP_EXTRA_ALIGN  1       /* must be a power of 2 */
+#define XTENSA_CP_EXTRA_SIZE   0
+
+#else
 
 #define XTOFS(last_start,last_size,align) \
        ((last_start+last_size+align-1) & -align)
@@ -67,4 +76,6 @@ extern void save_coprocessor_registers(void*, int);
 # endif
 #endif
 
+#endif
+
 #endif /* _XTENSA_COPROCESSOR_H */
index c39c91d..82b03b3 100644 (file)
@@ -170,10 +170,10 @@ dma_get_cache_alignment(void)
        return L1_CACHE_BYTES;
 }
 
-#define dma_is_consistent(d)   (1)
+#define dma_is_consistent(d, h)        (1)
 
 static inline void
-dma_cache_sync(void *vaddr, size_t size,
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction)
 {
        consistent_sync(vaddr, size, direction);
index db2633f..e30f3ab 100644 (file)
@@ -12,7 +12,6 @@
 #define _XTENSA_DMA_H
 
 #include <asm/io.h>            /* need byte IO */
-#include <xtensa/config/core.h>
 
 /*
  * This is only to be defined if we have PC-like DMA.
@@ -44,7 +43,9 @@
  *     enters another area, and virt_to_phys() may not return
  *     the value desired).
  */
-#define MAX_DMA_ADDRESS                (PAGE_OFFSET + XCHAL_KSEG_CACHED_SIZE - 1)
+
+#define MAX_DMA_ADDRESS                (PAGE_OFFSET + XCHAL_KIO_SIZE - 1)
+
 
 /* Reserve and release a DMA channel */
 extern int request_dma(unsigned int dmanr, const char * device_id);
index de06674..f0f9fd8 100644 (file)
@@ -13,9 +13,8 @@
 #ifndef _XTENSA_ELF_H
 #define _XTENSA_ELF_H
 
+#include <asm/variant/core.h>
 #include <asm/ptrace.h>
-#include <asm/coprocessor.h>
-#include <xtensa/config/core.h>
 
 /* Xtensa processor ELF architecture-magic number */
 
@@ -118,11 +117,15 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
  * using memcpy().  But we do allow space for such alignment,
  * to allow optimizations of layout and copying.
  */
-
+#if 0
 #define TOTAL_FPREGS_SIZE                                              \
        (4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
 #define ELF_NFPREG                                                     \
        ((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
+#else
+#define TOTAL_FPREGS_SIZE      0
+#define ELF_NFPREG             0
+#endif
 
 typedef unsigned int elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
index ec066ae..0609fc6 100644 (file)
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_APPEND       0x0008
-#define O_SYNC         0x0010
-#define O_NONBLOCK     0x0080
-#define O_CREAT         0x0100 /* not fcntl */
-#define O_EXCL         0x0400  /* not fcntl */
-#define O_NOCTTY       0x0800  /* not fcntl */
-#define FASYNC         0x1000  /* fcntl, for BSD compatibility */
-#define O_LARGEFILE    0x2000  /* allow large file opens - currently ignored */
-#define O_DIRECT       0x8000  /* direct disk access hint - currently ignored*/
-#define O_NOATIME      0x100000
-
-#define F_GETLK                14
-#define F_GETLK64       15
+#define O_ACCMODE         0003
+#define O_RDONLY            00
+#define O_WRONLY            01
+#define O_RDWR              02
+#define O_CREAT                   0100 /* not fcntl */
+#define O_EXCL            0200 /* not fcntl */
+#define O_NOCTTY          0400 /* not fcntl */
+#define O_TRUNC                  01000 /* not fcntl */
+#define O_APPEND         02000
+#define O_NONBLOCK       04000
+#define O_NDELAY       O_NONBLOCK
+#define O_SYNC          010000
+#define FASYNC          020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT        040000 /* direct disk access hint */
+#define O_LARGEFILE    0100000
+#define O_DIRECTORY    0200000 /* must be a directory */
+#define O_NOFOLLOW     0400000 /* don't follow links */
+#define O_NOATIME      01000000
+
+#define F_DUPFD                0       /* dup */
+#define F_GETFD                1       /* get close_on_exec */
+#define F_SETFD                2       /* set/clear close_on_exec */
+#define F_GETFL                3       /* get file->f_flags */
+#define F_SETFL                4       /* set file->f_flags */
+#define F_GETLK                5
 #define F_SETLK                6
 #define F_SETLKW       7
-#define F_SETLK64       16
-#define F_SETLKW64      17
 
-#define F_SETOWN       24      /*  for sockets. */
-#define F_GETOWN       23      /*  for sockets. */
+#define F_SETOWN       8       /*  for sockets. */
+#define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
+
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC     1       /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK                0
+#define F_WRLCK                1
+#define F_UNLCK                2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK                4       /* or 3 */
+#define F_SHLCK                8       /* or 4 */
 
-typedef struct flock {
+/* for leases */
+#define F_INPROGRESS   16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH                1       /* shared lock */
+#define LOCK_EX                2       /* exclusive lock */
+#define LOCK_NB                4       /* or'd with one of the above to prevent
+                                  blocking */
+#define LOCK_UN                8       /* remove lock */
+
+#define LOCK_MAND      32      /* This is a mandatory flock */
+#define LOCK_READ      64      /* ... Which allows concurrent read operations */
+#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
+#define LOCK_RW                192     /* ... Which allows concurrent read & write ops */
+
+struct flock {
        short l_type;
        short l_whence;
-       __kernel_off_t l_start;
-       __kernel_off_t l_len;
-       long  l_sysid;
-       __kernel_pid_t l_pid;
-       long  pad[4];
-} flock_t;
+       off_t l_start;
+       off_t l_len;
+       pid_t l_pid;
+};
 
 struct flock64 {
        short  l_type;
        short  l_whence;
-       __kernel_off_t l_start;
-       __kernel_off_t l_len;
+       loff_t l_start;
+       loff_t l_len;
        pid_t  l_pid;
 };
 
-#define HAVE_ARCH_STRUCT_FLOCK
-#define HAVE_ARCH_STRUCT_FLOCK64
-
-#include <asm-generic/fcntl.h>
+#define F_LINUX_SPECIFIC_BASE  1024
 
 #endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/fixmap.h b/include/asm-xtensa/fixmap.h
deleted file mode 100644 (file)
index 4423b8a..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * include/asm-xtensa/fixmap.h
- *
- * 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 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_FIXMAP_H
-#define _XTENSA_FIXMAP_H
-
-#include <asm/processor.h>
-
-#ifdef CONFIG_MMU
-
-/*
- * Here we define all the compile-time virtual addresses.
- */
-
-#if XCHAL_SEG_MAPPABLE_VADDR != 0
-# error "Current port requires virtual user space starting at 0"
-#endif
-#if XCHAL_SEG_MAPPABLE_SIZE < 0x80000000
-# error "Current port requires at least 0x8000000 bytes for user space"
-#endif
-
-/* Verify instruction/data ram/rom and xlmi don't overlay vmalloc space. */
-
-#define __IN_VMALLOC(addr)                                             \
-       (((addr) >= VMALLOC_START) && ((addr) < VMALLOC_END))
-#define __SPAN_VMALLOC(start,end)                                      \
-       (((start) < VMALLOC_START) && ((end) >= VMALLOC_END))
-#define INSIDE_VMALLOC(start,end)                                      \
-       (__IN_VMALLOC((start)) || __IN_VMALLOC(end) || __SPAN_VMALLOC((start),(end)))
-
-#if XCHAL_NUM_INSTROM
-# if XCHAL_NUM_INSTROM == 1
-#  if INSIDE_VMALLOC(XCHAL_INSTROM0_VADDR,XCHAL_INSTROM0_VADDR+XCHAL_INSTROM0_SIZE)
-#   error vmalloc range conflicts with instrom0
-#  endif
-# endif
-# if XCHAL_NUM_INSTROM == 2
-#  if INSIDE_VMALLOC(XCHAL_INSTROM1_VADDR,XCHAL_INSTROM1_VADDR+XCHAL_INSTROM1_SIZE)
-#   error vmalloc range conflicts with instrom1
-#  endif
-# endif
-#endif
-
-#if XCHAL_NUM_INSTRAM
-# if XCHAL_NUM_INSTRAM == 1
-#  if INSIDE_VMALLOC(XCHAL_INSTRAM0_VADDR,XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE)
-#   error vmalloc range conflicts with instram0
-#  endif
-# endif
-# if XCHAL_NUM_INSTRAM == 2
-#  if INSIDE_VMALLOC(XCHAL_INSTRAM1_VADDR,XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE)
-#   error vmalloc range conflicts with instram1
-#  endif
-# endif
-#endif
-
-#if XCHAL_NUM_DATAROM
-# if XCHAL_NUM_DATAROM == 1
-#  if INSIDE_VMALLOC(XCHAL_DATAROM0_VADDR,XCHAL_DATAROM0_VADDR+XCHAL_DATAROM0_SIZE)
-#   error vmalloc range conflicts with datarom0
-#  endif
-# endif
-# if XCHAL_NUM_DATAROM == 2
-#  if INSIDE_VMALLOC(XCHAL_DATAROM1_VADDR,XCHAL_DATAROM1_VADDR+XCHAL_DATAROM1_SIZE)
-#   error vmalloc range conflicts with datarom1
-#  endif
-# endif
-#endif
-
-#if XCHAL_NUM_DATARAM
-# if XCHAL_NUM_DATARAM == 1
-#  if INSIDE_VMALLOC(XCHAL_DATARAM0_VADDR,XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE)
-#   error vmalloc range conflicts with dataram0
-#  endif
-# endif
-# if XCHAL_NUM_DATARAM == 2
-#  if INSIDE_VMALLOC(XCHAL_DATARAM1_VADDR,XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE)
-#   error vmalloc range conflicts with dataram1
-#  endif
-# endif
-#endif
-
-#if XCHAL_NUM_XLMI
-# if XCHAL_NUM_XLMI == 1
-#  if INSIDE_VMALLOC(XCHAL_XLMI0_VADDR,XCHAL_XLMI0_VADDR+XCHAL_XLMI0_SIZE)
-#   error vmalloc range conflicts with xlmi0
-#  endif
-# endif
-# if XCHAL_NUM_XLMI == 2
-#  if INSIDE_VMALLOC(XCHAL_XLMI1_VADDR,XCHAL_XLMI1_VADDR+XCHAL_XLMI1_SIZE)
-#   error vmalloc range conflicts with xlmi1
-#  endif
-# endif
-#endif
-
-#if (XCHAL_NUM_INSTROM > 2) || \
-    (XCHAL_NUM_INSTRAM > 2) || \
-    (XCHAL_NUM_DATARAM > 2) || \
-    (XCHAL_NUM_DATAROM > 2) || \
-    (XCHAL_NUM_XLMI    > 2)
-# error Insufficient checks on vmalloc above for more than 2 devices
-#endif
-
-/*
- * USER_VM_SIZE does not necessarily equal TASK_SIZE.  We bumped
- * TASK_SIZE down to 0x4000000 to simplify the handling of windowed
- * call instructions (currently limited to a range of 1 GByte).  User
- * tasks may very well reclaim the VM space from 0x40000000 to
- * 0x7fffffff in the future, so we do not want the kernel becoming
- * accustomed to having any of its stuff (e.g., page tables) in this
- * region.  This VM region is no-man's land for now.
- */
-
-#define USER_VM_START          XCHAL_SEG_MAPPABLE_VADDR
-#define USER_VM_SIZE           0x80000000
-
-/*  Size of page table:  */
-
-#define PGTABLE_SIZE_BITS      (32 - XCHAL_MMU_MIN_PTE_PAGE_SIZE + 2)
-#define PGTABLE_SIZE           (1L << PGTABLE_SIZE_BITS)
-
-/*  All kernel-mappable space:  */
-
-#define KERNEL_ALLMAP_START    (USER_VM_START + USER_VM_SIZE)
-#define KERNEL_ALLMAP_SIZE     (XCHAL_SEG_MAPPABLE_SIZE - KERNEL_ALLMAP_START)
-
-/*  Carve out page table at start of kernel-mappable area:  */
-
-#if KERNEL_ALLMAP_SIZE < PGTABLE_SIZE
-#error "Gimme some space for page table!"
-#endif
-#define PGTABLE_START          KERNEL_ALLMAP_START
-
-/*  Remaining kernel-mappable space:  */
-
-#define KERNEL_MAPPED_START    (KERNEL_ALLMAP_START + PGTABLE_SIZE)
-#define KERNEL_MAPPED_SIZE     (KERNEL_ALLMAP_SIZE - PGTABLE_SIZE)
-
-#if KERNEL_MAPPED_SIZE < 0x01000000    /* 16 MB is arbitrary for now */
-# error "Shouldn't the kernel have at least *some* mappable space?"
-#endif
-
-#define MAX_LOW_MEMORY         XCHAL_KSEG_CACHED_SIZE
-
-#endif
-
-/*
- *  Some constants used elsewhere, but perhaps only in Xtensa header
- *  files, so maybe we can get rid of some and access compile-time HAL
- *  directly...
- *
- *  Note:  We assume that system RAM is located at the very start of the
- *        kernel segments !!
- */
-#define KERNEL_VM_LOW           XCHAL_KSEG_CACHED_VADDR
-#define KERNEL_VM_HIGH          XCHAL_KSEG_BYPASS_VADDR
-#define KERNEL_SPACE            XCHAL_KSEG_CACHED_VADDR
-
-/*
- * Returns the physical/virtual addresses of the kernel space
- * (works with the cached kernel segment only, which is the
- *  one normally used for kernel operation).
- */
-
-/*                     PHYSICAL        BYPASS          CACHED
- *
- *  bypass vaddr       bypass paddr    *               cached vaddr
- *  cached vaddr       cached paddr    bypass vaddr    *
- *  bypass paddr       *               bypass vaddr    cached vaddr
- *  cached paddr       *               bypass vaddr    cached vaddr
- *  other              *               *               *
- */
-
-#define PHYSADDR(a)                                                          \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR                                   \
-  && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
-    (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_PADDR :       \
-    ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR                                \
-     && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
-        (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_PADDR :   \
-       (unsigned)(a))
-
-#define BYPASS_ADDR(a)                                                       \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR                                   \
-  && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
-    (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_VADDR :       \
-    ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR                                \
-     && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
-        (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_BYPASS_VADDR :   \
-        ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR                            \
-         && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_CACHED_SIZE)?  \
-            (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_BYPASS_VADDR:  \
-           (unsigned)(a))
-
-#define CACHED_ADDR(a)                                                       \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR                                   \
-  && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
-    (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_CACHED_VADDR :       \
-    ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR                                \
-     && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
-        (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_VADDR :   \
-        ((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR                            \
-         && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_BYPASS_SIZE) ? \
-            (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_CACHED_VADDR : \
-           (unsigned)(a))
-
-#define PHYSADDR_IO(a)                                                       \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR                                    \
-  && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ?       \
-    (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_PADDR :        \
-    ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR                                 \
-     && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ?     \
-        (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_PADDR :     \
-       (unsigned)(a))
-
-#define BYPASS_ADDR_IO(a)                                                    \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR                                    \
-  && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ?       \
-    (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_VADDR :        \
-    ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR                                 \
-     && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ?     \
-        (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_BYPASS_VADDR :     \
-        ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR                             \
-         && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
-            (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_BYPASS_VADDR : \
-           (unsigned)(a))
-
-#define CACHED_ADDR_IO(a)                                                    \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR                                    \
-  && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ?       \
-    (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_CACHED_VADDR :        \
-    ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR                                 \
-     && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ?     \
-        (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_VADDR :     \
-        ((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR                             \
-         && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
-            (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_CACHED_VADDR : \
-           (unsigned)(a))
-
-#endif /* _XTENSA_ADDRSPACE_H */
-
-
-
-
-
index 556e5ee..31ffc3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-xtensa/io.h
+ * include/asm-xtensa/io.h
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
 #include <asm/byteorder.h>
 
 #include <linux/types.h>
-#include <asm/fixmap.h>
-
-#define _IO_BASE 0
 
+#define XCHAL_KIO_CACHED_VADDR 0xf0000000
+#define XCHAL_KIO_BYPASS_VADDR 0xf8000000
+#define XCHAL_KIO_PADDR                0xf0000000
+#define XCHAL_KIO_SIZE         0x08000000
 
 /*
  * swap functions to change byte order from little-endian to big-endian and
@@ -42,40 +43,43 @@ static inline unsigned int _swapl (unsigned int v)
 
 static inline unsigned long virt_to_phys(volatile void * address)
 {
-       return PHYSADDR((unsigned long)address);
+       return __pa(address);
 }
 
 static inline void * phys_to_virt(unsigned long address)
 {
-       return (void*) CACHED_ADDR(address);
+       return __va(address);
 }
 
 /*
- * IO bus memory addresses are also 1:1 with the physical address
+ * virt_to_bus and bus_to_virt are deprecated.
  */
 
-static inline unsigned long virt_to_bus(volatile void * address)
-{
-       return PHYSADDR((unsigned long)address);
-}
-
-static inline void * bus_to_virt (unsigned long address)
-{
-       return (void *) CACHED_ADDR(address);
-}
+#define virt_to_bus(x) virt_to_phys(x)
+#define bus_to_virt(x) phys_to_virt(x)
 
 /*
- * Change "struct page" to physical address.
+ * Return the virtual (cached) address for the specified bus memory.
+ * Note that we currently don't support any address outside the KIO segment.
  */
 
 static inline void *ioremap(unsigned long offset, unsigned long size)
 {
-        return (void *) CACHED_ADDR_IO(offset);
+       if (offset >= XCHAL_KIO_PADDR
+           && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+               return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR);
+
+       else
+               BUG();
 }
 
 static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
 {
-        return (void *) BYPASS_ADDR_IO(offset);
+       if (offset >= XCHAL_KIO_PADDR
+           && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+               return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR);
+       else
+               BUG();
 }
 
 static inline void iounmap(void *addr)
@@ -121,9 +125,6 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
           *(__force volatile __u32 *)(addr) = b;
 }
 
-
-
-
 /* These are the definitions for the x86 IO instructions
  * inb/inw/inl/outb/outw/outl, the "string" versions
  * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
@@ -131,11 +132,11 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
  * The macros don't do byte-swapping.
  */
 
-#define inb(port)              readb((u8 *)((port)+_IO_BASE))
-#define outb(val, port)                writeb((val),(u8 *)((unsigned long)(port)+_IO_BASE))
-#define inw(port)              readw((u16 *)((port)+_IO_BASE))
-#define outw(val, port)                writew((val),(u16 *)((unsigned long)(port)+_IO_BASE))
-#define inl(port)              readl((u32 *)((port)+_IO_BASE))
+#define inb(port)              readb((u8 *)((port)))
+#define outb(val, port)                writeb((val),(u8 *)((unsigned long)(port)))
+#define inw(port)              readw((u16 *)((port)))
+#define outw(val, port)                writew((val),(u16 *)((unsigned long)(port)))
+#define inl(port)              readl((u32 *)((port)))
 #define outl(val, port)                writel((val),(u32 *)((unsigned long)(port)))
 
 #define inb_p(port)            inb((port))
@@ -180,14 +181,13 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
 
 
 /*
- *  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- *   * access
- *    */
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem access
+ */
 #define xlate_dev_mem_ptr(p)    __va(p)
 
 /*
- *  * Convert a virtual cached pointer to an uncached pointer
- *   */
+ * Convert a virtual cached pointer to an uncached pointer
+ */
 #define xlate_dev_kmem_ptr(p)   p
 
 
index 049fde7..fc73b7f 100644 (file)
@@ -12,8 +12,7 @@
 #define _XTENSA_IRQ_H
 
 #include <asm/platform/hardware.h>
-
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
 #ifndef PLATFORM_NR_IRQS
 # define PLATFORM_NR_IRQS 0
@@ -27,10 +26,5 @@ static __inline__ int irq_canonicalize(int irq)
 }
 
 struct irqaction;
-#if 0 // FIXME
-extern void disable_irq_nosync(unsigned int);
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-#endif
 
 #endif /* _XTENSA_IRQ_H */
diff --git a/include/asm-xtensa/irq_regs.h b/include/asm-xtensa/irq_regs.h
new file mode 100644 (file)
index 0000000..3dd9c0b
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
index af683a7..f14851f 100644 (file)
 #include <linux/stringify.h>
 
 #include <asm/pgtable.h>
-#include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-/*
- * Linux was ported to Xtensa assuming all auto-refill ways in set 0
- * had the same properties (a very likely assumption).  Multiple sets
- * of auto-refill ways will still work properly, but not as optimally
- * as the Xtensa designer may have assumed.
- *
- * We make this case a hard #error, killing the kernel build, to alert
- * the developer to this condition (which is more likely an error).
- * You super-duper clever developers can change it to a warning or
- * remove it altogether if you think you know what you're doing.  :)
- */
+#define XCHAL_MMU_ASID_BITS    8
 
 #if (XCHAL_HAVE_TLBS != 1)
 # error "Linux must have an MMU!"
 #endif
 
-#if ((XCHAL_ITLB_ARF_WAYS == 0) || (XCHAL_DTLB_ARF_WAYS == 0))
-# error "MMU must have auto-refill ways"
-#endif
-
-#if ((XCHAL_ITLB_ARF_SETS != 1) || (XCHAL_DTLB_ARF_SETS != 1))
-# error Linux may not use all auto-refill ways as efficiently as you think
-#endif
-
-#if (XCHAL_MMU_MAX_PTE_PAGE_SIZE != XCHAL_MMU_MIN_PTE_PAGE_SIZE)
-# error Only one page size allowed!
-#endif
-
 extern unsigned long asid_cache;
-extern pgd_t *current_pgd;
-
-/*
- * Define the number of entries per auto-refill way in set 0 of both I and D
- * TLBs.  We deal only with set 0 here (an assumption further explained in
- * assertions.h).  Also, define the total number of ARF entries in both TLBs.
- */
-
-#define ITLB_ENTRIES_PER_ARF_WAY  (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES))
-#define DTLB_ENTRIES_PER_ARF_WAY  (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES))
-
-#define ITLB_ENTRIES                                                   \
-       (ITLB_ENTRIES_PER_ARF_WAY * (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,WAYS)))
-#define DTLB_ENTRIES                                                   \
-       (DTLB_ENTRIES_PER_ARF_WAY * (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,WAYS)))
-
-
-/*
- * SMALLEST_NTLB_ENTRIES is the smaller of ITLB_ENTRIES and DTLB_ENTRIES.
- * In practice, they are probably equal.  This macro simplifies function
- * flush_tlb_range().
- */
-
-#if (DTLB_ENTRIES < ITLB_ENTRIES)
-# define SMALLEST_NTLB_ENTRIES  DTLB_ENTRIES
-#else
-# define SMALLEST_NTLB_ENTRIES  ITLB_ENTRIES
-#endif
-
-
-/*
- * asid_cache tracks only the ASID[USER_RING] field of the RASID special
- * register, which is the current user-task asid allocation value.
- * mm->context has the same meaning.  When it comes time to write the
- * asid_cache or mm->context values to the RASID special register, we first
- * shift the value left by 8, then insert the value.
- * ASID[0] always contains the kernel's asid value, and we reserve three
- * other asid values that we never assign to user tasks.
- */
-
-#define ASID_INC       0x1
-#define ASID_MASK      ((1 << XCHAL_MMU_ASID_BITS) - 1)
-
-/*
- * XCHAL_MMU_ASID_INVALID is a configurable Xtensa processor constant
- * indicating invalid address space.  XCHAL_MMU_ASID_KERNEL is a configurable
- * Xtensa processor constant indicating the kernel address space.  They can
- * be arbitrary values.
- *
- * We identify three more unique, reserved ASID values to use in the unused
- * ring positions.  No other user process will be assigned these reserved
- * ASID values.
- *
- * For example, given that
- *
- *     XCHAL_MMU_ASID_INVALID == 0
- *     XCHAL_MMU_ASID_KERNEL  == 1
- *
- * the following maze of #if statements would generate
- *
- *     ASID_RESERVED_1        == 2
- *     ASID_RESERVED_2        == 3
- *     ASID_RESERVED_3        == 4
- *     ASID_FIRST_NONRESERVED == 5
- */
-
-#if (XCHAL_MMU_ASID_INVALID != XCHAL_MMU_ASID_KERNEL + 1)
-# define ASID_RESERVED_1         ((XCHAL_MMU_ASID_KERNEL + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_1         ((XCHAL_MMU_ASID_KERNEL + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_1 + 1)
-# define ASID_RESERVED_2         ((ASID_RESERVED_1 + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_2         ((ASID_RESERVED_1 + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_2 + 1)
-# define ASID_RESERVED_3         ((ASID_RESERVED_2 + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_3         ((ASID_RESERVED_2 + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_3 + 1)
-# define ASID_FIRST_NONRESERVED  ((ASID_RESERVED_3 + 1) & ASID_MASK)
-#else
-# define ASID_FIRST_NONRESERVED  ((ASID_RESERVED_3 + 2) & ASID_MASK)
-#endif
-
-#define ASID_ALL_RESERVED ( ((ASID_RESERVED_1) << 24) + \
-                            ((ASID_RESERVED_2) << 16) + \
-                            ((ASID_RESERVED_3) <<  8) + \
-                            ((XCHAL_MMU_ASID_KERNEL))   )
-
 
 /*
  * NO_CONTEXT is the invalid ASID value that we don't ever assign to
- * any user or kernel context.  NO_CONTEXT is a better mnemonic than
- * XCHAL_MMU_ASID_INVALID, so we use it in code instead.
- */
-
-#define NO_CONTEXT   XCHAL_MMU_ASID_INVALID
-
-#if (KERNEL_RING != 0)
-# error The KERNEL_RING really should be zero.
-#endif
-
-#if (USER_RING >= XCHAL_MMU_RINGS)
-# error USER_RING cannot be greater than the highest numbered ring.
-#endif
-
-#if (USER_RING == KERNEL_RING)
-# error The user and kernel rings really should not be equal.
-#endif
-
-#if (USER_RING == 1)
-#define ASID_INSERT(x) ( ((ASID_RESERVED_1)   << 24) + \
-                         ((ASID_RESERVED_2)   << 16) + \
-                         (((x) & (ASID_MASK)) <<  8) + \
-                         ((XCHAL_MMU_ASID_KERNEL))   )
-
-#elif (USER_RING == 2)
-#define ASID_INSERT(x) ( ((ASID_RESERVED_1)   << 24) + \
-                         (((x) & (ASID_MASK)) << 16) + \
-                         ((ASID_RESERVED_2)   <<  8) + \
-                         ((XCHAL_MMU_ASID_KERNEL))   )
-
-#elif (USER_RING == 3)
-#define ASID_INSERT(x) ( (((x) & (ASID_MASK)) << 24) + \
-                        ((ASID_RESERVED_1)   << 16) + \
-                         ((ASID_RESERVED_2)   <<  8) + \
-                         ((XCHAL_MMU_ASID_KERNEL))   )
-
-#else
-#error Goofy value for USER_RING
-
-#endif /* USER_RING == 1 */
-
-
-/*
- *  All unused by hardware upper bits will be considered
- *  as a software asid extension.
+ * any user or kernel context.
+ *
+ * 0 invalid
+ * 1 kernel
+ * 2 reserved
+ * 3 reserved
+ * 4...255 available
  */
 
-#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
-#define ASID_FIRST_VERSION                                             \
-       ((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
+#define NO_CONTEXT     0
+#define ASID_USER_FIRST        4
+#define ASID_MASK      ((1 << XCHAL_MMU_ASID_BITS) - 1)
+#define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8))
 
 static inline void set_rasid_register (unsigned long val)
 {
@@ -207,67 +52,28 @@ static inline void set_rasid_register (unsigned long val)
 static inline unsigned long get_rasid_register (void)
 {
        unsigned long tmp;
-       __asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
+       __asm__ __volatile__ (" rsr %0,"__stringify(RASID)"\n\t" : "=a" (tmp));
        return tmp;
 }
 
-
-#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
-
 static inline void
-get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+__get_new_mmu_context(struct mm_struct *mm)
 {
        extern void flush_tlb_all(void);
-       if (! ((asid += ASID_INC) & ASID_MASK) ) {
+       if (! (++asid_cache & ASID_MASK) ) {
                flush_tlb_all(); /* start new asid cycle */
-               if (!asid)      /* fix version if needed */
-                       asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
-               asid += ASID_FIRST_NONRESERVED;
+               asid_cache += ASID_USER_FIRST;
        }
-       mm->context = asid_cache = asid;
-}
-
-#else
-#warning ASID_{INVALID,KERNEL} values impose non-optimal get_new_mmu_context implementation
-
-/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
-   really the best, but if you insist... */
-
-static inline int validate_asid (unsigned long asid)
-{
-       switch (asid) {
-       case XCHAL_MMU_ASID_INVALID:
-       case XCHAL_MMU_ASID_KERNEL:
-       case ASID_RESERVED_1:
-       case ASID_RESERVED_2:
-       case ASID_RESERVED_3:
-               return 0; /* can't use these values as ASIDs */
-       }
-       return 1; /* valid */
+       mm->context = asid_cache;
 }
 
 static inline void
-get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+__load_mmu_context(struct mm_struct *mm)
 {
-       extern void flush_tlb_all(void);
-       while (1) {
-               asid += ASID_INC;
-               if ( ! (asid & ASID_MASK) ) {
-                       flush_tlb_all(); /* start new asid cycle */
-                       if (!asid)      /* fix version if needed */
-                               asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
-                       asid += ASID_FIRST_NONRESERVED;
-                       break; /* no need to validate here */
-               }
-               if (validate_asid (asid & ASID_MASK))
-                       break;
-       }
-       mm->context = asid_cache = asid;
+       set_rasid_register(ASID_INSERT(mm->context));
+       invalidate_page_directory();
 }
 
-#endif
-
-
 /*
  * Initialize the context related info for a new mm_struct
  * instance.
@@ -280,6 +86,20 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
        return 0;
 }
 
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static inline void
+activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+       /* Unconditionally get a new ASID.  */
+
+       __get_new_mmu_context(next);
+       __load_mmu_context(next);
+}
+
+
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                              struct task_struct *tsk)
 {
@@ -287,11 +107,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
        /* Check if our ASID is of an older version and thus invalid */
 
-       if ((next->context ^ asid) & ASID_VERSION_MASK)
-               get_new_mmu_context(next, asid);
+       if (next->context == NO_CONTEXT || ((next->context^asid) & ~ASID_MASK))
+               __get_new_mmu_context(next);
 
-       set_rasid_register (ASID_INSERT(next->context));
-       invalidate_page_directory();
+       __load_mmu_context(next);
 }
 
 #define deactivate_mm(tsk, mm) do { } while(0)
@@ -302,20 +121,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
  */
 static inline void destroy_context(struct mm_struct *mm)
 {
-       /* Nothing to do. */
-}
-
-/*
- * After we have set current->mm to a new value, this activates
- * the context for the new mm so we see the new mappings.
- */
-static inline void
-activate_mm(struct mm_struct *prev, struct mm_struct *next)
-{
-       /* Unconditionally get a new ASID.  */
-
-       get_new_mmu_context(next, asid_cache);
-       set_rasid_register (ASID_INSERT(next->context));
        invalidate_page_directory();
 }
 
index 40f4c6c..c631d00 100644 (file)
 
 #include <asm/processor.h>
 
+#define XCHAL_KSEG_CACHED_VADDR 0xd0000000
+#define XCHAL_KSEG_BYPASS_VADDR 0xd8000000
+#define XCHAL_KSEG_PADDR        0x00000000
+#define XCHAL_KSEG_SIZE         0x08000000
+
 /*
  * PAGE_SHIFT determines the page size
  * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
  */
 
-#define PAGE_SHIFT             XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SHIFT             12
 #define PAGE_SIZE              (1 << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
 
-#define DCACHE_WAY_SIZE                (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
 #define PAGE_OFFSET            XCHAL_KSEG_CACHED_VADDR
+#define MAX_MEM_PFN             XCHAL_KSEG_SIZE
+#define PGTABLE_START           0x80000000
 
 #ifdef __ASSEMBLY__
 
index c0eec82..6f28139 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _XTENSA_PARAM_H
 #define _XTENSA_PARAM_H
 
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
 #ifdef __KERNEL__
 # define HZ            100             /* internal timer frequency */
index b431893..2d4b5db 100644 (file)
 #include <asm-generic/pgtable-nopmd.h>
 #include <asm/page.h>
 
-/* Assertions. */
-
-#ifdef CONFIG_MMU
-
-
-#if (XCHAL_MMU_RINGS < 2)
-# error Linux build assumes at least 2 ring levels.
-#endif
-
-#if (XCHAL_MMU_CA_BITS != 4)
-# error We assume exactly four bits for CA.
-#endif
-
-#if (XCHAL_MMU_SR_BITS != 0)
-# error We have no room for SR bits.
-#endif
-
-/*
- * Use the first min-wired way for mapping page-table pages.
- * Page coloring requires a second min-wired way.
- */
-
-#if (XCHAL_DTLB_MINWIRED_SETS == 0)
-# error Need a min-wired way for mapping page-table pages
-#endif
-
-#define DTLB_WAY_PGTABLE XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAY)
-
-#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
-# if XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAYS) >= 2
-#  define DTLB_WAY_DCACHE_ALIAS0 (DTLB_WAY_PGTABLE + 1)
-#  define DTLB_WAY_DCACHE_ALIAS1 (DTLB_WAY_PGTABLE + 2)
-# else
-#  error Page coloring requires its own wired dtlb way!
-# endif
-#endif
-
-#endif /* CONFIG_MMU */
-
 /*
  * We only use two ring levels, user and kernel space.
  */
@@ -97,7 +58,7 @@
 #define PGD_ORDER              0
 #define PMD_ORDER              0
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
-#define FIRST_USER_ADDRESS      XCHAL_SEG_MAPPABLE_VADDR
+#define FIRST_USER_ADDRESS      0
 #define FIRST_USER_PGD_NR      (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
 
 /* virtual memory area. We keep a distance to other memory regions to be
index 22240f0..6930c12 100644 (file)
  * This file contains the default configuration of ISS.
  */
 
-#ifndef __ASM_XTENSA_ISS_HARDWARE
-#define __ASM_XTENSA_ISS_HARDWARE
+#ifndef _XTENSA_PLATFORM_ISS_HARDWARE_H
+#define _XTENSA_PLATFORM_ISS_HARDWARE_H
 
 /*
  * Memory configuration.
  */
 
-#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
-#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
+#define PLATFORM_DEFAULT_MEM_START     0x00000000
+#define PLATFORM_DEFAULT_MEM_SIZE      0x08000000
 
 /*
  * Interrupt configuration.
  */
 
-#endif /* __ASM_XTENSA_ISS_HARDWARE */
+#endif /* _XTENSA_PLATFORM_ISS_HARDWARE_H */
diff --git a/include/asm-xtensa/platform-iss/simcall.h b/include/asm-xtensa/platform-iss/simcall.h
new file mode 100644 (file)
index 0000000..6acb572
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * include/asm-xtensa/platform-iss/hardware.h
+ *
+ * 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 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H
+#define _XTENSA_PLATFORM_ISS_SIMCALL_H
+
+
+/*
+ *  System call like services offered by the simulator host.
+ */
+
+#define SYS_nop                0       /* unused */
+#define SYS_exit       1       /*x*/
+#define SYS_fork       2
+#define SYS_read       3       /*x*/
+#define SYS_write      4       /*x*/
+#define SYS_open       5       /*x*/
+#define SYS_close      6       /*x*/
+#define SYS_rename     7       /*x 38 - waitpid */
+#define SYS_creat      8       /*x*/
+#define SYS_link       9       /*x (not implemented on WIN32) */
+#define SYS_unlink     10      /*x*/
+#define SYS_execv      11      /* n/a - execve */
+#define SYS_execve     12      /* 11 - chdir */
+#define SYS_pipe       13      /* 42 - time */
+#define SYS_stat       14      /* 106 - mknod */
+#define SYS_chmod      15
+#define SYS_chown      16      /* 202 - lchown */
+#define SYS_utime      17      /* 30 - break */
+#define SYS_wait       18      /* n/a - oldstat */
+#define SYS_lseek      19      /*x*/
+#define SYS_getpid     20
+#define SYS_isatty     21      /* n/a - mount */
+#define SYS_fstat      22      /* 108 - oldumount */
+#define SYS_time       23      /* 13 - setuid */
+#define SYS_gettimeofday 24    /*x 78 - getuid (not implemented on WIN32) */
+#define SYS_times      25      /*X 43 - stime (Xtensa-specific implementation) */
+#define SYS_socket      26
+#define SYS_sendto      27
+#define SYS_recvfrom    28
+#define SYS_select_one  29      /* not compitible select, one file descriptor at the time */
+#define SYS_bind        30
+#define SYS_ioctl      31
+
+/*
+ * SYS_select_one specifiers
+ */
+
+#define  XTISS_SELECT_ONE_READ    1
+#define  XTISS_SELECT_ONE_WRITE   2
+#define  XTISS_SELECT_ONE_EXCEPT  3
+
+
+#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */
+
index 2c816b0..3470b44 100644 (file)
@@ -21,7 +21,7 @@
 
 typedef unsigned long  __kernel_ino_t;
 typedef unsigned int   __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
+typedef unsigned long  __kernel_nlink_t;
 typedef long           __kernel_off_t;
 typedef int            __kernel_pid_t;
 typedef unsigned short __kernel_ipc_pid_t;
index 8b96e77..4feb9f7 100644 (file)
 #ifndef _XTENSA_PROCESSOR_H
 #define _XTENSA_PROCESSOR_H
 
-#ifdef __ASSEMBLY__
-#define _ASMLANGUAGE
-#endif
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/tie.h>
-#include <xtensa/config/system.h>
+#include <asm/variant/core.h>
+#include <asm/coprocessor.h>
 
 #include <linux/compiler.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/coprocessor.h>
+#include <asm/regs.h>
 
 /* Assertions. */
 
 #if (XCHAL_HAVE_WINDOWED != 1)
-#error Linux requires the Xtensa Windowed Registers Option.
+# error Linux requires the Xtensa Windowed Registers Option.
 #endif
 
 /*
@@ -145,11 +139,11 @@ struct thread_struct {
  * Note: We set-up ps as if we did a call4 to the new pc.
  *       set_thread_state in signal.c depends on it.
  */
-#define USER_PS_VALUE ( (1 << XCHAL_PS_WOE_SHIFT) + \
-                        (1 << XCHAL_PS_CALLINC_SHIFT) + \
-                        (USER_RING << XCHAL_PS_RING_SHIFT) + \
-                        (1 << XCHAL_PS_PROGSTACK_SHIFT) + \
-                        (1 << XCHAL_PS_EXCM_SHIFT) )
+#define USER_PS_VALUE ((1 << PS_WOE_BIT) |                             \
+                       (1 << PS_CALLINC_SHIFT) |                       \
+                       (USER_RING << PS_RING_SHIFT) |                  \
+                       (1 << PS_UM_BIT) |                              \
+                       (1 << PS_EXCM_BIT))
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
index a5ac71a..1b7fe36 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _XTENSA_PTRACE_H
 #define _XTENSA_PTRACE_H
 
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
 
 /*
  * Kernel stack
diff --git a/include/asm-xtensa/regs.h b/include/asm-xtensa/regs.h
new file mode 100644 (file)
index 0000000..c913d25
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006 Tensilica, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _XTENSA_REGS_H
+#define _XTENSA_REGS_H
+
+/*  Special registers.  */
+
+#define LBEG           0
+#define LEND           1
+#define LCOUNT         2
+#define SAR            3
+#define BR             4
+#define SCOMPARE1      12
+#define ACCHI          16
+#define ACCLO          17
+#define MR             32
+#define WINDOWBASE     72
+#define WINDOWSTART    73
+#define PTEVADDR       83
+#define RASID          90
+#define ITLBCFG                91
+#define DTLBCFG                92
+#define IBREAKENABLE   96
+#define DDR            104
+#define IBREAKA                128
+#define DBREAKA                144
+#define DBREAKC                160
+#define EPC            176
+#define EPC_1          177
+#define DEPC           192
+#define EPS            192
+#define EPS_1          193
+#define EXCSAVE                208
+#define EXCSAVE_1      209
+#define INTERRUPT      226
+#define INTENABLE      228
+#define PS             230
+#define THREADPTR      231
+#define EXCCAUSE       232
+#define DEBUGCAUSE     233
+#define CCOUNT         234
+#define PRID           235
+#define ICOUNT         236
+#define ICOUNTLEVEL    237
+#define EXCVADDR       238
+#define CCOMPARE       240
+#define MISC           244
+
+/*  Special names for read-only and write-only interrupt registers.  */
+
+#define INTREAD                226
+#define INTSET         226
+#define INTCLEAR       227
+
+/*  EXCCAUSE register fields  */
+
+#define EXCCAUSE_EXCCAUSE_SHIFT        0
+#define EXCCAUSE_EXCCAUSE_MASK 0x3F
+
+#define EXCCAUSE_ILLEGAL_INSTRUCTION           0
+#define EXCCAUSE_SYSTEM_CALL                   1
+#define EXCCAUSE_INSTRUCTION_FETCH_ERROR       2
+#define EXCCAUSE_LOAD_STORE_ERROR              3
+#define EXCCAUSE_LEVEL1_INTERRUPT              4
+#define EXCCAUSE_ALLOCA                                5
+#define EXCCAUSE_INTEGER_DIVIDE_BY_ZERO                6
+#define EXCCAUSE_SPECULATION                   7
+#define EXCCAUSE_PRIVILEGED                    8
+#define EXCCAUSE_UNALIGNED                     9
+#define EXCCAUSE_ITLB_MISS                     16
+#define EXCCAUSE_ITLB_MULTIHIT                 17
+#define EXCCAUSE_ITLB_PRIVILEGE                        18
+#define EXCCAUSE_ITLB_SIZE_RESTRICTION         19
+#define EXCCAUSE_FETCH_CACHE_ATTRIBUTE         20
+#define EXCCAUSE_DTLB_MISS                     24
+#define EXCCAUSE_DTLB_MULTIHIT                 25
+#define EXCCAUSE_DTLB_PRIVILEGE                        26
+#define EXCCAUSE_DTLB_SIZE_RESTRICTION         27
+#define EXCCAUSE_LOAD_CACHE_ATTRIBUTE          28
+#define EXCCAUSE_STORE_CACHE_ATTRIBUTE         29
+#define EXCCAUSE_FLOATING_POINT                        40
+
+/*  PS register fields.  */
+
+#define PS_WOE_BIT             18
+#define PS_CALLINC_SHIFT       16
+#define PS_CALLINC_MASK                0x00030000
+#define PS_OWB_SHIFT           8
+#define PS_OWB_MASK            0x00000F00
+#define PS_RING_SHIFT          6
+#define PS_RING_MASK           0x000000C0
+#define PS_UM_BIT              5
+#define PS_EXCM_BIT            4
+#define PS_INTLEVEL_SHIFT      0
+#define PS_INTLEVEL_MASK       0x0000000F
+
+/*  DBREAKCn register fields.  */
+
+#define DBREAKC_MASK_BIT               0
+#define DBREAKC_MASK_MASK              0x0000003F
+#define DBREAKC_LOAD_BIT               30
+#define DBREAKC_LOAD_MASK              0x40000000
+#define DBREAKC_STOR_BIT               31
+#define DBREAKC_STOR_MASK              0x80000000
+
+/*  DEBUGCAUSE register fields.  */
+
+#define DEBUGCAUSE_DEBUGINT_BIT                5       /* External debug interrupt */
+#define DEBUGCAUSE_BREAKN_BIT          4       /* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_BIT           3       /* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_BIT          2       /* DBREAK match */
+#define DEBUGCAUSE_IBREAK_BIT          1       /* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_BIT          0       /* ICOUNT would incr. to zero */
+
+#endif /* _XTENSA_SPECREG_H */
+
index 2d26c47..c158704 100644 (file)
@@ -25,7 +25,7 @@
 
 struct semid64_ds {
        struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-#if XCHAL_HAVE_LE
+#ifdef __XTENSA_EL__
        __kernel_time_t sem_otime;              /* last semop time */
        unsigned long   __unused1;
        __kernel_time_t sem_ctime;              /* last change time */
index a30b81a..ad4b012 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef _XTENSA_SHMBUF_H
 #define _XTENSA_SHMBUF_H
 
+#if defined (__XTENSA_EL__)
 struct shmid64_ds {
        struct ipc64_perm       shm_perm;       /* operation perms */
        size_t                  shm_segsz;      /* size of segment (bytes) */
@@ -34,6 +35,26 @@ struct shmid64_ds {
        unsigned long           __unused4;
        unsigned long           __unused5;
 };
+#elif defined (__XTENSA_EB__)
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+#else
+# error endian order not defined
+#endif
+
 
 struct shminfo64 {
        unsigned long   shmmax;
index 2f4662f..149f4bc 100644 (file)
 
 #include <linux/types.h>
 
-struct __old_kernel_stat {
-       unsigned short st_dev;
-       unsigned short st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_atime;
-       unsigned long  st_mtime;
-       unsigned long  st_ctime;
-};
-
 #define STAT_HAVE_NSEC 1
 
 struct stat {
-       unsigned short st_dev;
-       unsigned short __pad1;
-       unsigned long st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned short __pad2;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  st_atime_nsec;
-       unsigned long  st_mtime;
-       unsigned long  st_mtime_nsec;
-       unsigned long  st_ctime;
-       unsigned long  st_ctime_nsec;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
+       unsigned long   st_dev;
+       ino_t           st_ino;
+       mode_t          st_mode;
+       nlink_t         st_nlink;
+       uid_t           st_uid;
+       gid_t           st_gid;
+       unsigned int    st_rdev;
+       off_t           st_size;
+       unsigned long   st_blksize;
+       unsigned long   st_blocks;
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+       unsigned long   __unused4;
+       unsigned long   __unused5;
 };
 
-/* This matches struct stat64 in glibc-2.2.3. */
+/* This matches struct stat64 in glibc-2.3 */
 
 struct stat64  {
-#ifdef __XTENSA_EL__
-       unsigned short  st_dev;         /* Device */
-       unsigned char   __pad0[10];
-#else
-       unsigned char   __pad0[6];
-       unsigned short  st_dev;
-       unsigned char   __pad1[2];
-#endif
-
-#define STAT64_HAS_BROKEN_ST_INO       1
-       unsigned long __st_ino;         /* 32bit file serial number. */
-
+       unsigned long long st_dev;      /* Device */
+       unsigned long long st_ino;      /* File serial number */
        unsigned int  st_mode;          /* File mode. */
        unsigned int  st_nlink;         /* Link count. */
        unsigned int  st_uid;           /* User ID of the file's owner. */
        unsigned int  st_gid;           /* Group ID of the file's group. */
-
-#ifdef __XTENSA_EL__
-       unsigned short  st_rdev;        /* Device number, if device. */
-       unsigned char   __pad3[10];
-#else
-       unsigned char   __pad2[6];
-       unsigned short  st_rdev;
-       unsigned char   __pad3[2];
-#endif
-
-       long long int  st_size;         /* Size of file, in bytes. */
-       long int st_blksize;            /* Optimal block size for I/O. */
-
-#ifdef __XTENSA_EL__
-       unsigned long  st_blocks;       /* Number 512-byte blocks allocated. */
-       unsigned long  __pad4;
+       unsigned long long st_rdev;     /* Device number, if device. */
+       long long st_size;              /* Size of file, in bytes. */
+       long st_blksize;                /* Optimal block size for I/O. */
+       unsigned long __unused2;
+#ifdef __XTENSA_EB__
+       unsigned long __unused3;
+       long st_blocks;                 /* Number 512-byte blocks allocated. */
 #else
-       unsigned long  __pad4;
-       unsigned long  st_blocks;
+       long st_blocks;                 /* Number 512-byte blocks allocated. */
+       unsigned long __unused3;
 #endif
-
-       unsigned long  __pad5;
-       long int st_atime;              /* Time of last access. */
-       unsigned long  st_atime_nsec;
-       long int st_mtime;              /* Time of last modification. */
-       unsigned long  st_mtime_nsec;
-       long int  st_ctime;             /* Time of last status change. */
-       unsigned long  st_ctime_nsec;
-       unsigned long long int st_ino;  /* File serial number. */
+       long st_atime;                  /* Time of last access. */
+       unsigned long st_atime_nsec;
+       long st_mtime;                  /* Time of last modification. */
+       unsigned long st_mtime_nsec;
+       long st_ctime;                  /* Time of last status change. */
+       unsigned long st_ctime_nsec;
+       unsigned long __unused4;
+       unsigned long __unused5;
 };
 
 #endif /* _XTENSA_STAT_H */
diff --git a/include/asm-xtensa/syscall.h b/include/asm-xtensa/syscall.h
new file mode 100644 (file)
index 0000000..6cb0d42
--- /dev/null
@@ -0,0 +1,20 @@
+struct pt_regs;
+struct sigaction;
+asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
+asmlinkage long xtensa_pipe(int __user *);
+asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long,
+                            unsigned long, unsigned long, unsigned long);
+asmlinkage long xtensa_ptrace(long, long, long, long);
+asmlinkage long xtensa_sigreturn(struct pt_regs*);
+asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
+asmlinkage long xtensa_sigsuspend(struct pt_regs*);
+asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*);
+asmlinkage long xtensa_sigaction(int, const struct old_sigaction*,
+                                struct old_sigaction*);
+asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
+asmlinkage long sys_rt_sigaction(int,
+                                const struct sigaction __user *,
+                                struct sigaction __user *,
+                                size_t);
+asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg);
index 932bda9..4aaed7f 100644 (file)
@@ -213,7 +213,7 @@ static inline void spill_registers(void)
        unsigned int a0, ps;
 
        __asm__ __volatile__ (
-               "movi   a14," __stringify (PS_EXCM_MASK) " | 1\n\t"
+               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
                "mov    a12, a0\n\t"
                "rsr    a13," __stringify(SAR) "\n\t"
                "xsr    a14," __stringify(PS) "\n\t"
index c7b705e..28c7985 100644 (file)
 #include <asm/processor.h>
 #include <linux/stringify.h>
 
-#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
+#define _INTLEVEL(x)   XCHAL_INT ## x ## _LEVEL
+#define INTLEVEL(x)    _INTLEVEL(x)
+
+#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) == 1
 # define LINUX_TIMER     0
-#elif XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
+# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
+#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) == 1
 # define LINUX_TIMER     1
-#elif XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
+# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
+#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) == 1
 # define LINUX_TIMER     2
+# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT
 #else
 # error "Bad timer number for Linux configurations!"
 #endif
 
-#define LINUX_TIMER_INT         XCHAL_TIMER_INTERRUPT(LINUX_TIMER)
 #define LINUX_TIMER_MASK        (1L << LINUX_TIMER_INT)
 
 #define CLOCK_TICK_RATE        1193180 /* (everyone is using this value) */
@@ -60,8 +65,8 @@ extern cycles_t cacheflush_time;
 
 #define WSR_CCOUNT(r)    __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r))
 #define RSR_CCOUNT(r)    __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r))
-#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) :: "a"(r))
-#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) : "=a"(r))
+#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r))
 
 static inline unsigned long get_ccount (void)
 {
index 43f6ec8..7c637b3 100644 (file)
 #ifndef _XTENSA_TLBFLUSH_H
 #define _XTENSA_TLBFLUSH_H
 
-#define DEBUG_TLB
-
 #ifdef __KERNEL__
 
-#include <asm/processor.h>
 #include <linux/stringify.h>
+#include <asm/processor.h>
+
+#define DTLB_WAY_PGD   7
+
+#define ITLB_ARF_WAYS  4
+#define DTLB_ARF_WAYS  4
+
+#define ITLB_HIT_BIT   3
+#define DTLB_HIT_BIT   4
+
+#ifndef __ASSEMBLY__
 
 /* TLB flushing:
  *
@@ -46,11 +54,6 @@ static inline void flush_tlb_pgtables(struct mm_struct *mm,
 
 /* TLB operations. */
 
-#define ITLB_WAYS_LOG2      XCHAL_ITLB_WAY_BITS
-#define DTLB_WAYS_LOG2      XCHAL_DTLB_WAY_BITS
-#define ITLB_PROBE_SUCCESS  (1 << ITLB_WAYS_LOG2)
-#define DTLB_PROBE_SUCCESS  (1 << DTLB_WAYS_LOG2)
-
 static inline unsigned long itlb_probe(unsigned long addr)
 {
        unsigned long tmp;
@@ -131,29 +134,30 @@ static inline void write_itlb_entry (pte_t entry, int way)
 
 static inline void invalidate_page_directory (void)
 {
-       invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
+       invalidate_dtlb_entry (DTLB_WAY_PGD);
+       invalidate_dtlb_entry (DTLB_WAY_PGD+1);
+       invalidate_dtlb_entry (DTLB_WAY_PGD+2);
 }
 
 static inline void invalidate_itlb_mapping (unsigned address)
 {
        unsigned long tlb_entry;
-       while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
-               invalidate_itlb_entry (tlb_entry);
+       if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0)
+               invalidate_itlb_entry(tlb_entry);
 }
 
 static inline void invalidate_dtlb_mapping (unsigned address)
 {
        unsigned long tlb_entry;
-       while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
-               invalidate_dtlb_entry (tlb_entry);
+       if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0)
+               invalidate_dtlb_entry(tlb_entry);
 }
 
 #define check_pgt_cache()      do { } while (0)
 
 
-#ifdef DEBUG_TLB
-
-/* DO NOT USE THESE FUNCTIONS.  These instructions aren't part of the Xtensa
+/*
+ * DO NOT USE THESE FUNCTIONS.  These instructions aren't part of the Xtensa
  * ISA and exist only for test purposes..
  * You may find it helpful for MMU debugging, however.
  *
@@ -193,8 +197,6 @@ static inline unsigned long read_itlb_translation (int way)
        return tmp;
 }
 
-#endif /* DEBUG_TLB */
-
-
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
-#endif /* _XTENSA_PGALLOC_H */
+#endif /* _XTENSA_TLBFLUSH_H */
index 411f810..8a7fb69 100644 (file)
 #ifndef _XTENSA_UNISTD_H
 #define _XTENSA_UNISTD_H
 
-#define __NR_spill               0
-#define __NR_exit                1
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-#define __NR_break              17
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_ptrace             26
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_ioperm            101
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_iopl              110
-#define __NR_vhangup           111
-#define __NR_idle              112
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_modify_ldt                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_cacheflush         147
-#define __NR_cachectl           148
-#define __NR_sysxtensa          149
-#define __NR_sysdummy           150
-#define __NR_getsid            151
-#define __NR_fdatasync         152
-#define __NR__sysctl           153
-#define __NR_mlock             154
-#define __NR_munlock           155
-#define __NR_mlockall          156
-#define __NR_munlockall                157
-#define __NR_sched_setparam            158
-#define __NR_sched_getparam            159
-#define __NR_sched_setscheduler                160
-#define __NR_sched_getscheduler                161
-#define __NR_sched_yield               162
-#define __NR_sched_get_priority_max    163
-#define __NR_sched_get_priority_min    164
-#define __NR_sched_rr_get_interval     165
-#define __NR_nanosleep         166
-#define __NR_mremap            167
-#define __NR_accept             168
-#define __NR_bind               169
-#define __NR_connect            170
-#define __NR_getpeername        171
-#define __NR_getsockname        172
-#define __NR_getsockopt         173
-#define __NR_listen             174
-#define __NR_recv               175
-#define __NR_recvfrom           176
-#define __NR_recvmsg            177
-#define __NR_send               178
-#define __NR_sendmsg            179
-#define __NR_sendto             180
-#define __NR_setsockopt         181
-#define __NR_shutdown           182
-#define __NR_socket             183
-#define __NR_socketpair         184
-#define __NR_setresuid         185
-#define __NR_getresuid         186
-#define __NR_query_module      187
-#define __NR_poll              188
-#define __NR_nfsservctl                189
-#define __NR_setresgid         190
-#define __NR_getresgid         191
-#define __NR_prctl              192
-#define __NR_rt_sigreturn      193
-#define __NR_rt_sigaction      194
-#define __NR_rt_sigprocmask    195
-#define __NR_rt_sigpending     196
-#define __NR_rt_sigtimedwait   197
-#define __NR_rt_sigqueueinfo   198
-#define __NR_rt_sigsuspend     199
-#define __NR_pread             200
-#define __NR_pwrite            201
-#define __NR_chown             202
-#define __NR_getcwd            203
-#define __NR_capget            204
-#define __NR_capset            205
-#define __NR_sigaltstack       206
-#define __NR_sendfile          207
-#define __NR_mmap2             210
-#define __NR_truncate64                211
-#define __NR_ftruncate64       212
-#define __NR_stat64            213
-#define __NR_lstat64           214
-#define __NR_fstat64           215
-#define __NR_pivot_root                216
-#define __NR_mincore           217
-#define __NR_madvise           218
-#define __NR_getdents64                219
-
-/* Keep this last; should always equal the last valid call number. */
-#define __NR_Linux_syscalls     220
-
-/* user-visible error numbers are in the range -1 - -125: see
- * <asm-xtensa/errno.h> */
-
-#define SYSXTENSA_RESERVED        0    /* don't use this */
-#define SYSXTENSA_ATOMIC_SET      1    /* set variable */
-#define SYSXTENSA_ATOMIC_EXG_ADD   2   /* exchange memory and add */
-#define SYSXTENSA_ATOMIC_ADD      3    /* add to memory */
-#define SYSXTENSA_ATOMIC_CMP_SWP   4   /* compare and swap */
-
-#define SYSXTENSA_COUNT                   5    /* count of syscall0 functions*/
+#ifndef __SYSCALL
+# define __SYSCALL(nr,func,nargs)
+#endif
 
-#ifdef __KERNEL__
-#include <linux/linkage.h>
+#define __NR_spill                               0
+__SYSCALL(  0, sys_ni_syscall, 0)
+#define __NR_xtensa                              1
+__SYSCALL(  1, sys_ni_syscall, 0)
+#define __NR_available4                                  2
+__SYSCALL(  2, sys_ni_syscall, 0)
+#define __NR_available5                                  3
+__SYSCALL(  3, sys_ni_syscall, 0)
+#define __NR_available6                                  4
+__SYSCALL(  4, sys_ni_syscall, 0)
+#define __NR_available7                                  5
+__SYSCALL(  5, sys_ni_syscall, 0)
+#define __NR_available8                                  6
+__SYSCALL(  6, sys_ni_syscall, 0)
+#define __NR_available9                                  7
+__SYSCALL(  7, sys_ni_syscall, 0)
 
-#define __syscall_return(type, res) return ((type)(res))
+/* File Operations */
 
-/* Tensilica's xt-xcc compiler is much more agressive at code
- * optimization than gcc.  Multiple __asm__ statements are
- * insufficient for xt-xcc because subsequent optimization passes
- * (beyond the front-end that knows of __asm__ statements and other
- * such GNU Extensions to C) can modify the register selection for
- * containment of C variables.
- *
- * xt-xcc cannot modify the contents of a single __asm__ statement, so
- * we create single-asm versions of the syscall macros that are
- * suitable and optimal for both xt-xcc and gcc.
- *
- * Linux takes system-call arguments in registers.  The following
- * design is optimized for user-land apps (e.g., glibc) which
- * typically have a function wrapper around the "syscall" assembly
- * instruction.  It satisfies the Xtensa ABI while minizing argument
- * shifting.
- *
- * The Xtensa ABI and software conventions require the system-call
- * number in a2.  If an argument exists in a2, we move it to the next
- * available register.  Note that for improved efficiency, we do NOT
- * shift all parameters down one register to maintain the original
- * order.
- *
- * At best case (zero arguments), we just write the syscall number to
- * a2.  At worst case (1 to 6 arguments), we move the argument in a2
- * to the next available register, then write the syscall number to
- * a2.
- *
- * For clarity, the following truth table enumerates all possibilities.
+#define __NR_open                                8
+__SYSCALL(  8, sys_open, 3)
+#define __NR_close                               9
+__SYSCALL(  9, sys_close, 1)
+#define __NR_dup                                10
+__SYSCALL( 10, sys_dup, 1)
+#define __NR_dup2                               11
+__SYSCALL( 11, sys_dup2, 2)
+#define __NR_read                               12
+__SYSCALL( 12, sys_read, 3)
+#define __NR_write                              13
+__SYSCALL( 13, sys_write, 3)
+#define __NR_select                             14
+__SYSCALL( 14, sys_select, 5)
+#define __NR_lseek                              15
+__SYSCALL( 15, sys_lseek, 3)
+#define __NR_poll                               16
+__SYSCALL( 16, sys_poll, 3)
+#define __NR__llseek                            17
+__SYSCALL( 17, sys_llseek, 5)
+#define __NR_epoll_wait                         18
+__SYSCALL( 18, sys_epoll_wait, 4)
+#define __NR_epoll_ctl                                  19
+__SYSCALL( 19, sys_epoll_ctl, 4)
+#define __NR_epoll_create                       20
+__SYSCALL( 20, sys_epoll_create, 1)
+#define __NR_creat                              21
+__SYSCALL( 21, sys_creat, 2)
+#define __NR_truncate                           22
+__SYSCALL( 22, sys_truncate, 2)
+#define __NR_ftruncate                                  23
+__SYSCALL( 23, sys_ftruncate, 2)
+#define __NR_readv                              24
+__SYSCALL( 24, sys_readv, 3)
+#define __NR_writev                             25
+__SYSCALL( 25, sys_writev, 3)
+#define __NR_fsync                              26
+__SYSCALL( 26, sys_fsync, 1)
+#define __NR_fdatasync                                  27
+__SYSCALL( 27, sys_fdatasync, 1)
+#define __NR_truncate64                         28
+__SYSCALL( 28, sys_truncate64, 2)
+#define __NR_ftruncate64                        29
+__SYSCALL( 29, sys_ftruncate64, 2)
+#define __NR_pread64                            30
+__SYSCALL( 30, sys_pread64, 6)
+#define __NR_pwrite64                           31
+__SYSCALL( 31, sys_pwrite64, 6)
+
+#define __NR_link                               32
+__SYSCALL( 32, sys_link, 2)
+#define __NR_rename                             33
+__SYSCALL( 33, sys_rename, 2)
+#define __NR_symlink                            34
+__SYSCALL( 34, sys_symlink, 2)
+#define __NR_readlink                           35
+__SYSCALL( 35, sys_readlink, 3)
+#define __NR_mknod                              36
+__SYSCALL( 36, sys_mknod, 3)
+#define __NR_pipe                               37
+__SYSCALL( 37, xtensa_pipe, 1)
+#define __NR_unlink                             38
+__SYSCALL( 38, sys_unlink, 1)
+#define __NR_rmdir                              39
+__SYSCALL( 39, sys_rmdir, 1)
+
+#define __NR_mkdir                              40
+__SYSCALL( 40, sys_mkdir, 2)
+#define __NR_chdir                              41
+__SYSCALL( 41, sys_chdir, 1)
+#define __NR_fchdir                             42
+__SYSCALL( 42, sys_fchdir, 1)
+#define __NR_getcwd                             43
+__SYSCALL( 43, sys_getcwd, 2)
+
+#define __NR_chmod                              44
+__SYSCALL( 44, sys_chmod, 2)
+#define __NR_chown                              45
+__SYSCALL( 45, sys_chown, 3)
+#define __NR_stat                               46
+__SYSCALL( 46, sys_newstat, 2)
+#define __NR_stat64                             47
+__SYSCALL( 47, sys_stat64, 2)
+
+#define __NR_lchown                             48
+__SYSCALL( 48, sys_lchown, 3)
+#define __NR_lstat                              49
+__SYSCALL( 49, sys_newlstat, 2)
+#define __NR_lstat64                            50
+__SYSCALL( 50, sys_lstat64, 2)
+#define __NR_available51                        51
+__SYSCALL( 51, sys_ni_syscall, 0)
+
+#define __NR_fchmod                             52
+__SYSCALL( 52, sys_fchmod, 2)
+#define __NR_fchown                             53
+__SYSCALL( 53, sys_fchown, 3)
+#define __NR_fstat                              54
+__SYSCALL( 54, sys_newfstat, 2)
+#define __NR_fstat64                            55
+__SYSCALL( 55, sys_fstat64, 2)
+
+#define __NR_flock                              56
+__SYSCALL( 56, sys_flock, 2)
+#define __NR_access                             57
+__SYSCALL( 57, sys_access, 2)
+#define __NR_umask                              58
+__SYSCALL( 58, sys_umask, 1)
+#define __NR_getdents                           59
+__SYSCALL( 59, sys_getdents, 3)
+#define __NR_getdents64                         60
+__SYSCALL( 60, sys_getdents64, 3)
+#define __NR_fcntl64                            61
+__SYSCALL( 61, sys_fcntl64, 3)
+#define __NR_available62                        62
+__SYSCALL( 62, sys_ni_syscall, 0)
+#define __NR_fadvise64_64                       63
+__SYSCALL( 63, sys_fadvise64_64, 6)
+#define __NR_utime                              64     /* glibc 2.3.3 ?? */
+__SYSCALL( 64, sys_utime, 2)
+#define __NR_utimes                             65
+__SYSCALL( 65, sys_utimes, 2)
+#define __NR_ioctl                              66
+__SYSCALL( 66, sys_ioctl, 3)
+#define __NR_fcntl                              67
+__SYSCALL( 67, sys_fcntl, 3)
+
+#define __NR_setxattr                           68
+__SYSCALL( 68, sys_setxattr, 5)
+#define __NR_getxattr                           69
+__SYSCALL( 69, sys_getxattr, 4)
+#define __NR_listxattr                                  70
+__SYSCALL( 70, sys_listxattr, 3)
+#define __NR_removexattr                        71
+__SYSCALL( 71, sys_removexattr, 2)
+#define __NR_lsetxattr                                  72
+__SYSCALL( 72, sys_lsetxattr, 5)
+#define __NR_lgetxattr                                  73
+__SYSCALL( 73, sys_lgetxattr, 4)
+#define __NR_llistxattr                         74
+__SYSCALL( 74, sys_llistxattr, 3)
+#define __NR_lremovexattr                       75
+__SYSCALL( 75, sys_lremovexattr, 2)
+#define __NR_fsetxattr                                  76
+__SYSCALL( 76, sys_fsetxattr, 5)
+#define __NR_fgetxattr                                  77
+__SYSCALL( 77, sys_fgetxattr, 4)
+#define __NR_flistxattr                         78
+__SYSCALL( 78, sys_flistxattr, 3)
+#define __NR_fremovexattr                       79
+__SYSCALL( 79, sys_fremovexattr, 2)
+
+/* File Map / Shared Memory Operations */
+
+#define __NR_mmap2                              80
+__SYSCALL( 80, xtensa_mmap2, 6)
+#define __NR_munmap                             81
+__SYSCALL( 81, sys_munmap, 2)
+#define __NR_mprotect                           82
+__SYSCALL( 82, sys_mprotect, 3)
+#define __NR_brk                                83
+__SYSCALL( 83, sys_brk, 1)
+#define __NR_mlock                              84
+__SYSCALL( 84, sys_mlock, 2)
+#define __NR_munlock                            85
+__SYSCALL( 85, sys_munlock, 2)
+#define __NR_mlockall                           86
+__SYSCALL( 86, sys_mlockall, 1)
+#define __NR_munlockall                         87
+__SYSCALL( 87, sys_munlockall, 0)
+#define __NR_mremap                             88
+__SYSCALL( 88, sys_mremap, 4)
+#define __NR_msync                              89
+__SYSCALL( 89, sys_msync, 3)
+#define __NR_mincore                            90
+__SYSCALL( 90, sys_mincore, 3)
+#define __NR_madvise                            91
+__SYSCALL( 91, sys_madvise, 3)
+#define __NR_shmget                             92
+__SYSCALL( 92, sys_shmget, 4)
+#define __NR_shmat                              93
+__SYSCALL( 93, xtensa_shmat, 4)
+#define __NR_shmctl                             94
+__SYSCALL( 94, sys_shmctl, 4)
+#define __NR_shmdt                              95
+__SYSCALL( 95, sys_shmdt, 4)
+
+/* Socket Operations */
+
+#define __NR_socket                             96
+__SYSCALL( 96, sys_socket, 3)
+#define __NR_setsockopt                         97
+__SYSCALL( 97, sys_setsockopt, 5)
+#define __NR_getsockopt                         98
+__SYSCALL( 98, sys_getsockopt, 5)
+#define __NR_shutdown                           99
+__SYSCALL( 99, sys_shutdown, 2)
+
+#define __NR_bind                              100
+__SYSCALL(100, sys_bind, 3)
+#define __NR_connect                           101
+__SYSCALL(101, sys_connect, 3)
+#define __NR_listen                            102
+__SYSCALL(102, sys_listen, 2)
+#define __NR_accept                            103
+__SYSCALL(103, sys_accept, 3)
+
+#define __NR_getsockname                       104
+__SYSCALL(104, sys_getsockname, 3)
+#define __NR_getpeername                       105
+__SYSCALL(105, sys_getpeername, 3)
+#define __NR_sendmsg                           106
+__SYSCALL(106, sys_sendmsg, 3)
+#define __NR_recvmsg                           107
+__SYSCALL(107, sys_recvmsg, 3)
+#define __NR_send                              108
+__SYSCALL(108, sys_send, 4)
+#define __NR_recv                              109
+__SYSCALL(109, sys_recv, 4)
+#define __NR_sendto                            110
+__SYSCALL(110, sys_sendto, 6)
+#define __NR_recvfrom                          111
+__SYSCALL(111, sys_recvfrom, 6)
+
+#define __NR_socketpair                        112
+__SYSCALL(112, sys_socketpair, 4)
+#define __NR_sendfile                          113
+__SYSCALL(113, sys_sendfile, 4)
+#define __NR_sendfile64                        114
+__SYSCALL(114, sys_sendfile64, 4)
+#define __NR_available115                      115
+__SYSCALL(115, sys_ni_syscall, 0)
+
+/* Process Operations */
+
+#define __NR_clone                             116
+__SYSCALL(116, xtensa_clone, 5)
+#define __NR_execve                            117
+__SYSCALL(117, xtensa_execve, 3)
+#define __NR_exit                              118
+__SYSCALL(118, sys_exit, 1)
+#define __NR_exit_group                        119
+__SYSCALL(119, sys_exit_group, 1)
+#define __NR_getpid                            120
+__SYSCALL(120, sys_getpid, 0)
+#define __NR_wait4                             121
+__SYSCALL(121, sys_wait4, 4)
+#define __NR_waitid                            122
+__SYSCALL(122, sys_waitid, 5)
+#define __NR_kill                              123
+__SYSCALL(123, sys_kill, 2)
+#define __NR_tkill                             124
+__SYSCALL(124, sys_tkill, 2)
+#define __NR_tgkill                            125
+__SYSCALL(125, sys_tgkill, 3)
+#define __NR_set_tid_address                   126
+__SYSCALL(126, sys_set_tid_address, 1)
+#define __NR_gettid                            127
+__SYSCALL(127, sys_gettid, 0)
+#define __NR_setsid                            128
+__SYSCALL(128, sys_setsid, 0)
+#define __NR_getsid                            129
+__SYSCALL(129, sys_getsid, 1)
+#define __NR_prctl                             130
+__SYSCALL(130, sys_prctl, 5)
+#define __NR_personality                       131
+__SYSCALL(131, sys_personality, 1)
+#define __NR_getpriority                       132
+__SYSCALL(132, sys_getpriority, 2)
+#define __NR_setpriority                       133
+__SYSCALL(133, sys_setpriority, 3)
+#define __NR_setitimer                                 134
+__SYSCALL(134, sys_setitimer, 3)
+#define __NR_getitimer                                 135
+__SYSCALL(135, sys_getitimer, 2)
+#define __NR_setuid                            136
+__SYSCALL(136, sys_setuid, 1)
+#define __NR_getuid                            137
+__SYSCALL(137, sys_getuid, 0)
+#define __NR_setgid                            138
+__SYSCALL(138, sys_setgid, 1)
+#define __NR_getgid                            139
+__SYSCALL(139, sys_getgid, 0)
+#define __NR_geteuid                           140
+__SYSCALL(140, sys_geteuid, 0)
+#define __NR_getegid                           141
+__SYSCALL(141, sys_getegid, 0)
+#define __NR_setreuid                          142
+__SYSCALL(142, sys_setreuid, 2)
+#define __NR_setregid                          143
+__SYSCALL(143, sys_setregid, 2)
+#define __NR_setresuid                                 144
+__SYSCALL(144, sys_setresuid, 3)
+#define __NR_getresuid                                 145
+__SYSCALL(145, sys_getresuid, 3)
+#define __NR_setresgid                                 146
+__SYSCALL(146, sys_setresgid, 3)
+#define __NR_getresgid                                 147
+__SYSCALL(147, sys_getresgid, 3)
+#define __NR_setpgid                           148
+__SYSCALL(148, sys_setpgid, 2)
+#define __NR_getpgid                           149
+__SYSCALL(149, sys_getpgid, 1)
+#define __NR_getppid                           150
+__SYSCALL(150, sys_getppid, 0)
+#define __NR_available151                      151
+__SYSCALL(151, sys_ni_syscall, 0)
+
+#define __NR_reserved152                       152     /* set_thread_area */
+__SYSCALL(152, sys_ni_syscall, 0)
+#define __NR_reserved153                       153     /* get_thread_area */
+__SYSCALL(153, sys_ni_syscall, 0)
+#define __NR_times                             154
+__SYSCALL(154, sys_times, 1)
+#define __NR_acct                              155
+__SYSCALL(155, sys_acct, 1)
+#define __NR_sched_setaffinity                         156
+__SYSCALL(156, sys_sched_setaffinity, 3)
+#define __NR_sched_getaffinity                         157
+__SYSCALL(157, sys_sched_getaffinity, 3)
+#define __NR_capget                            158
+__SYSCALL(158, sys_capget, 2)
+#define __NR_capset                            159
+__SYSCALL(159, sys_capset, 2)
+#define __NR_ptrace                            160
+__SYSCALL(160, sys_ptrace, 4)
+#define __NR_semtimedop                                161
+__SYSCALL(161, sys_semtimedop, 5)
+#define __NR_semget                            162
+__SYSCALL(162, sys_semget, 4)
+#define __NR_semop                             163
+__SYSCALL(163, sys_semop, 4)
+#define __NR_semctl                            164
+__SYSCALL(164, sys_semctl, 4)
+#define __NR_available165                      165
+__SYSCALL(165, sys_ni_syscall, 0)
+#define __NR_msgget                            166
+__SYSCALL(166, sys_msgget, 4)
+#define __NR_msgsnd                            167
+__SYSCALL(167, sys_msgsnd, 4)
+#define __NR_msgrcv                            168
+__SYSCALL(168, sys_msgrcv, 4)
+#define __NR_msgctl                            169
+__SYSCALL(169, sys_msgctl, 4)
+#define __NR_available170                      170
+__SYSCALL(170, sys_ni_syscall, 0)
+#define __NR_available171                      171
+__SYSCALL(171, sys_ni_syscall, 0)
+
+/* File System */
+
+#define __NR_mount                             172
+__SYSCALL(172, sys_mount, 5)
+#define __NR_swapon                            173
+__SYSCALL(173, sys_swapon, 2)
+#define __NR_chroot                            174
+__SYSCALL(174, sys_chroot, 1)
+#define __NR_pivot_root                        175
+__SYSCALL(175, sys_pivot_root, 2)
+#define __NR_umount                            176
+__SYSCALL(176, sys_umount, 2)
+#define __NR_swapoff                           177
+__SYSCALL(177, sys_swapoff, 1)
+#define __NR_sync                              178
+__SYSCALL(178, sys_sync, 0)
+#define __NR_available179                      179
+__SYSCALL(179, sys_ni_syscall, 0)
+#define __NR_setfsuid                          180
+__SYSCALL(180, sys_setfsuid, 1)
+#define __NR_setfsgid                          181
+__SYSCALL(181, sys_setfsgid, 1)
+#define __NR_sysfs                             182
+__SYSCALL(182, sys_sysfs, 3)
+#define __NR_ustat                             183
+__SYSCALL(183, sys_ustat, 2)
+#define __NR_statfs                            184
+__SYSCALL(184, sys_statfs, 2)
+#define __NR_fstatfs                           185
+__SYSCALL(185, sys_fstatfs, 2)
+#define __NR_statfs64                          186
+__SYSCALL(186, sys_statfs64, 3)
+#define __NR_fstatfs64                                 187
+__SYSCALL(187, sys_fstatfs64, 3)
+
+/* System */
+
+#define __NR_setrlimit                                 188
+__SYSCALL(188, sys_setrlimit, 2)
+#define __NR_getrlimit                                 189
+__SYSCALL(189, sys_getrlimit, 2)
+#define __NR_getrusage                                 190
+__SYSCALL(190, sys_getrusage, 2)
+#define __NR_futex                             191
+__SYSCALL(191, sys_futex, 5)
+#define __NR_gettimeofday                      192
+__SYSCALL(192, sys_gettimeofday, 2)
+#define __NR_settimeofday                      193
+__SYSCALL(193, sys_settimeofday, 2)
+#define __NR_adjtimex                          194
+__SYSCALL(194, sys_adjtimex, 1)
+#define __NR_nanosleep                         195
+__SYSCALL(195, sys_nanosleep, 2)
+#define __NR_getgroups                                 196
+__SYSCALL(196, sys_getgroups, 2)
+#define __NR_setgroups                                 197
+__SYSCALL(197, sys_setgroups, 2)
+#define __NR_sethostname                       198
+__SYSCALL(198, sys_sethostname, 2)
+#define __NR_setdomainname                     199
+__SYSCALL(199, sys_setdomainname, 2)
+#define __NR_syslog                            200
+__SYSCALL(200, sys_syslog, 3)
+#define __NR_vhangup                           201
+__SYSCALL(201, sys_vhangup, 0)
+#define __NR_uselib                            202
+__SYSCALL(202, sys_uselib, 1)
+#define __NR_reboot                            203
+__SYSCALL(203, sys_reboot, 3)
+#define __NR_quotactl                          204
+__SYSCALL(204, sys_quotactl, 4)
+#define __NR_nfsservctl                        205
+__SYSCALL(205, sys_nfsservctl, 3)
+#define __NR__sysctl                           206
+__SYSCALL(206, sys_sysctl, 1)
+#define __NR_bdflush                           207
+__SYSCALL(207, sys_bdflush, 2)
+#define __NR_uname                             208
+__SYSCALL(208, sys_newuname, 1)
+#define __NR_sysinfo                           209
+__SYSCALL(209, sys_sysinfo, 1)
+#define __NR_init_module                       210
+__SYSCALL(210, sys_init_module, 2)
+#define __NR_delete_module                     211
+__SYSCALL(211, sys_delete_module, 1)
+
+#define __NR_sched_setparam                    212
+__SYSCALL(212, sys_sched_setparam, 2)
+#define __NR_sched_getparam                    213
+__SYSCALL(213, sys_sched_getparam, 2)
+#define __NR_sched_setscheduler                214
+__SYSCALL(214, sys_sched_setscheduler, 3)
+#define __NR_sched_getscheduler                215
+__SYSCALL(215, sys_sched_getscheduler, 1)
+#define __NR_sched_get_priority_max            216
+__SYSCALL(216, sys_sched_get_priority_max, 1)
+#define __NR_sched_get_priority_min            217
+__SYSCALL(217, sys_sched_get_priority_min, 1)
+#define __NR_sched_rr_get_interval             218
+__SYSCALL(218, sys_sched_rr_get_interval, 2)
+#define __NR_sched_yield                       219
+__SYSCALL(219, sys_sched_yield, 0)
+#define __NR_sigreturn                         222
+__SYSCALL(222, xtensa_sigreturn, 0)
+
+/* Signal Handling */
+
+#define __NR_restart_syscall                   223
+__SYSCALL(223, sys_restart_syscall, 0)
+#define __NR_sigaltstack                       224
+__SYSCALL(224, xtensa_sigaltstack, 2)
+#define __NR_rt_sigreturn                      225
+__SYSCALL(225, xtensa_rt_sigreturn, 1)
+#define __NR_rt_sigaction                      226
+__SYSCALL(226, sys_rt_sigaction, 4)
+#define __NR_rt_sigprocmask                    227
+__SYSCALL(227, sys_rt_sigprocmask, 4)
+#define __NR_rt_sigpending                     228
+__SYSCALL(228, sys_rt_sigpending, 2)
+#define __NR_rt_sigtimedwait                   229
+__SYSCALL(229, sys_rt_sigtimedwait, 4)
+#define __NR_rt_sigqueueinfo                   230
+__SYSCALL(230, sys_rt_sigqueueinfo, 3)
+#define __NR_rt_sigsuspend                     231
+__SYSCALL(231, xtensa_rt_sigsuspend, 2)
+
+/* Message */
+
+#define __NR_mq_open                           232
+__SYSCALL(232, sys_mq_open, 4)
+#define __NR_mq_unlink                                 233
+__SYSCALL(233, sys_mq_unlink, 1)
+#define __NR_mq_timedsend                      234
+__SYSCALL(234, sys_mq_timedsend, 5)
+#define __NR_mq_timedreceive                   235
+__SYSCALL(235, sys_mq_timedreceive, 5)
+#define __NR_mq_notify                                 236
+__SYSCALL(236, sys_mq_notify, 2)
+#define __NR_mq_getsetattr                     237
+__SYSCALL(237, sys_mq_getsetattr, 3)
+#define __NR_available238                      238
+__SYSCALL(238, sys_ni_syscall, 0)
+
+/* IO */
+
+#define __NR_io_setup                          239
+__SYSCALL(239, sys_io_setup, 2)
+#define __NR_io_destroy                        240
+__SYSCALL(240, sys_io_destroy, 1)
+#define __NR_io_submit                                 241
+__SYSCALL(241, sys_io_submit, 3)
+#define __NR_io_getevents                      242
+__SYSCALL(242, sys_io_getevents, 5)
+#define __NR_io_cancel                                 243
+__SYSCALL(243, sys_io_cancel, 3)
+#define __NR_clock_settime                     244
+__SYSCALL(244, sys_clock_settime, 2)
+#define __NR_clock_gettime                     245
+__SYSCALL(245, sys_clock_gettime, 2)
+#define __NR_clock_getres                      246
+__SYSCALL(246, sys_clock_getres, 2)
+#define __NR_clock_nanosleep                   247
+__SYSCALL(247, sys_clock_nanosleep, 4)
+
+/* Timer */
+
+#define __NR_timer_create                      248
+__SYSCALL(248, sys_timer_create, 3)
+#define __NR_timer_delete                      249
+__SYSCALL(249, sys_timer_delete, 1)
+#define __NR_timer_settime                     250
+__SYSCALL(250, sys_timer_settime, 4)
+#define __NR_timer_gettime                     251
+__SYSCALL(251, sys_timer_gettime, 2)
+#define __NR_timer_getoverrun                  252
+__SYSCALL(252, sys_timer_getoverrun, 1)
+
+/* System */
+
+#define __NR_reserved244                       253
+__SYSCALL(253, sys_ni_syscall, 0)
+#define __NR_lookup_dcookie                    254
+__SYSCALL(254, sys_lookup_dcookie, 4)
+#define __NR_available255                      255
+__SYSCALL(255, sys_ni_syscall, 0)
+#define __NR_add_key                           256
+__SYSCALL(256, sys_add_key, 5)
+#define __NR_request_key                       257
+__SYSCALL(257, sys_request_key, 5)
+#define __NR_keyctl                            258
+__SYSCALL(258, sys_keyctl, 5)
+#define __NR_available259                      259
+__SYSCALL(259, sys_ni_syscall, 0)
+
+#define __NR_syscall_count                     261
+
+/*
+ * sysxtensa syscall handler
  *
- * arguments   syscall number  arg0, arg1, arg2, arg3, arg4, arg5
- * ---------   --------------  ----------------------------------
- *     0             a2
- *     1             a2        a3
- *     2             a2        a4,   a3
- *     3             a2        a5,   a3,   a4
- *     4             a2        a6,   a3,   a4,   a5
- *     5             a2        a7,   a3,   a4,   a5,   a6
- *     6             a2        a8,   a3,   a4,   a5,   a6,   a7
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ *        a2            a6                   a3    a4      a5
  */
 
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name) \
-       : "a2" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall1(type,name,type0,arg0) \
-type name(type0 arg0) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a3, %2 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0) \
-       : "a2", "a3" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall2(type,name,type0,arg0,type1,arg1) \
-type name(type0 arg0,type1 arg1) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a4, %2 \n" \
-       "  mov   a3, %3 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0), "a" (arg1) \
-       : "a2", "a3", "a4" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall3(type,name,type0,arg0,type1,arg1,type2,arg2) \
-type name(type0 arg0,type1 arg1,type2 arg2) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a5, %2 \n" \
-       "  mov   a4, %4 \n" \
-       "  mov   a3, %3 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2) \
-       : "a2", "a3", "a4", "a5" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-#define _syscall4(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3) \
-type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a6, %2 \n" \
-       "  mov   a5, %5 \n" \
-       "  mov   a4, %4 \n" \
-       "  mov   a3, %3 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), "a" (arg3) \
-       : "a2", "a3", "a4", "a5", "a6" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-/* Note that we save and restore the a7 frame pointer.
- * Including a7 in the clobber list doesn't do what you'd expect.
- */
-#define _syscall5(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a9, a7 \n" \
-       "  mov   a7, %2 \n" \
-       "  mov   a6, %6 \n" \
-       "  mov   a5, %5 \n" \
-       "  mov   a4, %4 \n" \
-       "  mov   a3, %3 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   a7, a9 \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
-                             "a" (arg3), "a" (arg4) \
-       : "a2", "a3", "a4", "a5", "a6", "a9" \
-       ); \
-__syscall_return(type,__res); \
-}
-
-/* Note that we save and restore the a7 frame pointer.
- * Including a7 in the clobber list doesn't do what you'd expect.
- */
-#define _syscall6(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-__asm__ __volatile__ ( \
-       "  mov   a9, a7 \n" \
-       "  mov   a8, %2 \n" \
-       "  mov   a7, %7 \n" \
-       "  mov   a6, %6 \n" \
-       "  mov   a5, %5 \n" \
-       "  mov   a4, %4 \n" \
-       "  mov   a3, %3 \n" \
-       "  movi  a2, %1 \n" \
-       "  syscall      \n" \
-       "  mov   a7, a9 \n" \
-       "  mov   %0, a2 \n" \
-       : "=a" (__res) \
-       : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
-                             "a" (arg3), "a" (arg4), "a" (arg5)  \
-       : "a2", "a3", "a4", "a5", "a6", "a8", "a9" \
-       ); \
-__syscall_return(type,__res); \
-}
+#define SYS_XTENSA_RESERVED               0     /* don't use this */
+#define SYS_XTENSA_ATOMIC_SET             1     /* set variable */
+#define SYS_XTENSA_ATOMIC_EXG_ADD         2     /* exchange memory and add */
+#define SYS_XTENSA_ATOMIC_ADD             3     /* add to memory */
+#define SYS_XTENSA_ATOMIC_CMP_SWP         4     /* compare and swap */
+
+#define SYS_XTENSA_COUNT                  5     /* count */
+
+#ifdef __KERNEL__
 
 /*
  * "Conditional" syscalls
@@ -414,6 +611,9 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif /* __KERNEL__ */
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+
+#endif /* __KERNEL__ */
 
 #endif /* _XTENSA_UNISTD_H */
+
diff --git a/include/asm-xtensa/variant-fsf/core.h b/include/asm-xtensa/variant-fsf/core.h
new file mode 100644 (file)
index 0000000..2f33760
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Xtensa processor core configuration 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.
+ *
+ * Copyright (C) 1999-2006 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CORE_H
+#define _XTENSA_CORE_H
+
+
+/****************************************************************************
+           Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+                               ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE                  1       /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED            1       /* windowed registers option */
+#define XCHAL_NUM_AREGS                        64      /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2           6       /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE     3       /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG               1       /* debug option */
+#define XCHAL_HAVE_DENSITY             1       /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS               1       /* zero-overhead loops */
+#define XCHAL_HAVE_NSA                 1       /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX              0       /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT                        0       /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS              0       /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16               0       /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32               0       /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH          0       /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_L32R                        1       /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS   1       /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16             0       /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX                        1       /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES       0       /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES  0       /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12          1       /* (obsolete option) */
+#define XCHAL_HAVE_ABS                 1       /* ABS instruction */
+/*#define XCHAL_HAVE_POPC              0*/     /* POPC instruction */
+/*#define XCHAL_HAVE_CRC               0*/     /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC                0       /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I              0       /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION         0       /* speculation */
+#define XCHAL_HAVE_FULL_RESET          1       /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS             1       /* */
+#define XCHAL_NUM_MISC_REGS            2       /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER          0       /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID                        1       /* processor ID register */
+#define XCHAL_HAVE_THREADPTR           1       /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS            0       /* boolean registers */
+#define XCHAL_HAVE_CP                  0       /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG                        0       /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16               0       /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005       0       /* vector floating-point pkg */
+#define XCHAL_HAVE_FP                  0       /* floating point pkg */
+#define XCHAL_HAVE_VECTRA1             0       /* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX            0       /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFI2               0       /* HiFi2 Audio Engine pkg */
+
+
+/*----------------------------------------------------------------------
+                               MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES  4       /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH         4       /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH               4       /* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1       /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION        1       /* unaligned stores cause exc.*/
+
+#define XCHAL_CORE_ID                  "fsf"   /* alphanum core name
+                                                  (CoreID) set in the Xtensa
+                                                  Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID          0x00006700      /* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0             0xC103C3FF      /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1             0x0C006700      /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME          "LX2.0.0"       /* full version name */
+#define XCHAL_HW_VERSION_MAJOR         2200    /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR         0       /* minor ver# of targeted hw */
+#define XTHAL_HW_REL_LX2               1
+#define XTHAL_HW_REL_LX2_0             1
+#define XTHAL_HW_REL_LX2_0_0           1
+#define XCHAL_HW_CONFIGID_RELIABLE     1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR     2200    /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR     0       /* minor v of earliest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR     2200    /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR     0       /* minor v of latest tgt hw */
+
+
+/*----------------------------------------------------------------------
+                               CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE          16      /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE          16      /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH         4       /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH         4       /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE              8192    /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE              8192    /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK      0       /* writeback feature */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+                               CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF                 1       /* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH          8
+#define XCHAL_DCACHE_SETWIDTH          8
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS              2
+#define XCHAL_DCACHE_WAYS              2
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE     0
+#define XCHAL_DCACHE_LINE_LOCKABLE     0
+#define XCHAL_ICACHE_ECC_PARITY                0
+#define XCHAL_DCACHE_ECC_PARITY                0
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS                  4
+
+
+/*----------------------------------------------------------------------
+                       INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM              0       /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM              0       /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM              0       /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM              0       /* number of core data RAMs */
+#define XCHAL_NUM_URAM                 0       /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI                 0       /* number of core XLMI ports */
+
+
+/*----------------------------------------------------------------------
+                       INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS          1       /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS  1       /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI                 0       /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT              1       /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS               3       /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS           17      /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2      5       /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS                10      /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS            4       /* number of interrupt levels
+                                                  (not including level zero) */
+#define XCHAL_EXCM_LEVEL               1       /* level masked by PS.EXCM */
+       /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK           0x000064F9
+#define XCHAL_INTLEVEL2_MASK           0x00008902
+#define XCHAL_INTLEVEL3_MASK           0x00011204
+#define XCHAL_INTLEVEL4_MASK           0x00000000
+#define XCHAL_INTLEVEL5_MASK           0x00000000
+#define XCHAL_INTLEVEL6_MASK           0x00000000
+#define XCHAL_INTLEVEL7_MASK           0x00000000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK  0x000064F9
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK  0x0000EDFB
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK  0x0001FFFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK  0x0001FFFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK  0x0001FFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK  0x0001FFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK  0x0001FFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL               1
+#define XCHAL_INT1_LEVEL               2
+#define XCHAL_INT2_LEVEL               3
+#define XCHAL_INT3_LEVEL               1
+#define XCHAL_INT4_LEVEL               1
+#define XCHAL_INT5_LEVEL               1
+#define XCHAL_INT6_LEVEL               1
+#define XCHAL_INT7_LEVEL               1
+#define XCHAL_INT8_LEVEL               2
+#define XCHAL_INT9_LEVEL               3
+#define XCHAL_INT10_LEVEL              1
+#define XCHAL_INT11_LEVEL              2
+#define XCHAL_INT12_LEVEL              3
+#define XCHAL_INT13_LEVEL              1
+#define XCHAL_INT14_LEVEL              1
+#define XCHAL_INT15_LEVEL              2
+#define XCHAL_INT16_LEVEL              3
+#define XCHAL_DEBUGLEVEL               4       /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT    0       /* OCD external db interrupt */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT7_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT8_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT9_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT10_TYPE       XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE       XTHAL_INTTYPE_TIMER
+#define XCHAL_INT12_TYPE       XTHAL_INTTYPE_TIMER
+#define XCHAL_INT13_TYPE       XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT14_TYPE       XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT15_TYPE       XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT16_TYPE       XTHAL_INTTYPE_SOFTWARE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED        0xFFFE0000
+#define XCHAL_INTTYPE_MASK_SOFTWARE    0x0001E000
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL        0x0000007F
+#define XCHAL_INTTYPE_MASK_TIMER       0x00001C00
+#define XCHAL_INTTYPE_MASK_NMI         0x00000000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT         10      /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT         11      /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT         12      /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT         XTHAL_TIMER_UNCONFIGURED
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+/*  (There are many interrupts each at level(s) 1, 2, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM              0       /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM              1       /* (intlevel 2) */
+#define XCHAL_EXTINT2_NUM              2       /* (intlevel 3) */
+#define XCHAL_EXTINT3_NUM              3       /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM              4       /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM              5       /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM              6       /* (intlevel 1) */
+#define XCHAL_EXTINT7_NUM              7       /* (intlevel 1) */
+#define XCHAL_EXTINT8_NUM              8       /* (intlevel 2) */
+#define XCHAL_EXTINT9_NUM              9       /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+                       EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION              2       /* Xtensa Exception Architecture
+                                                  number: 1 == XEA1 (old)
+                                                          2 == XEA2 (new)
+                                                          0 == XEAX (extern) */
+#define XCHAL_HAVE_XEA1                        0       /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2                        1       /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX                        0       /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS          1       /* exception option */
+#define XCHAL_HAVE_MEM_ECC_PARITY      0       /* local memory ECC/parity */
+
+#define XCHAL_RESET_VECTOR_VADDR       0xFE000020
+#define XCHAL_RESET_VECTOR_PADDR       0xFE000020
+#define XCHAL_USER_VECTOR_VADDR                0xD0000220
+#define XCHAL_USER_VECTOR_PADDR                0x00000220
+#define XCHAL_KERNEL_VECTOR_VADDR      0xD0000200
+#define XCHAL_KERNEL_VECTOR_PADDR      0x00000200
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR   0xD0000290
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR   0x00000290
+#define XCHAL_WINDOW_VECTORS_VADDR     0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR     0x00000000
+#define XCHAL_INTLEVEL2_VECTOR_VADDR   0xD0000240
+#define XCHAL_INTLEVEL2_VECTOR_PADDR   0x00000240
+#define XCHAL_INTLEVEL3_VECTOR_VADDR   0xD0000250
+#define XCHAL_INTLEVEL3_VECTOR_PADDR   0x00000250
+#define XCHAL_INTLEVEL4_VECTOR_VADDR   0xFE000520
+#define XCHAL_INTLEVEL4_VECTOR_PADDR   0xFE000520
+#define XCHAL_DEBUG_VECTOR_VADDR       XCHAL_INTLEVEL4_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR       XCHAL_INTLEVEL4_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+                               DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD                 1       /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK               2       /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK               2       /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY       1       /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+                               MMU
+  ----------------------------------------------------------------------*/
+
+/*  See <xtensa/config/core-matmap.h> header file for more details.  */
+
+#define XCHAL_HAVE_TLBS                        1       /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY                0       /* one way maps I+D 4GB vaddr */
+#define XCHAL_HAVE_IDENTITY_MAP                0       /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR           0       /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR     0       /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR       0       /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU             1       /* full MMU (with page table
+                                                  [autorefill] and protection)
+                                                  usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2    2       /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2    2       /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS            8       /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS                        4       /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS            2       /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/include/asm-xtensa/variant-fsf/tie.h b/include/asm-xtensa/variant-fsf/tie.h
new file mode 100644 (file)
index 0000000..a73c716
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Xtensa processor core configuration 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.
+ *
+ * Copyright (C) 1999-2006 Tensilica Inc.
+ */
+
+#ifndef XTENSA_TIE_H
+#define XTENSA_TIE_H
+
+/*----------------------------------------------------------------------
+                       COPROCESSORS and EXTRA STATE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_CP_NUM                   0       /* number of coprocessors */
+#define XCHAL_CP_MASK                  0x00
+
+#endif /*XTENSA_CONFIG_TIE_H*/
+
diff --git a/include/asm-xtensa/xtensa/cacheasm.h b/include/asm-xtensa/xtensa/cacheasm.h
deleted file mode 100644 (file)
index 0cdbb0b..0000000
+++ /dev/null
@@ -1,708 +0,0 @@
-#ifndef XTENSA_CACHEASM_H
-#define XTENSA_CACHEASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
- * related definitions that depend on CORE configuration.
- *
- * 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) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/coreasm.h>
-
-
-/*
- *  This header file defines assembler macros of the form:
- *     <x>cache_<func>
- *  where <x> is 'i' or 'd' for instruction and data caches,
- *  and <func> indicates the function of the macro.
- *
- *  The following functions <func> are defined,
- *  and apply only to the specified cache (I or D):
- *
- *  reset
- *     Resets the cache.
- *
- *  sync
- *     Makes sure any previous cache instructions have been completed;
- *     ie. makes sure any previous cache control operations
- *     have had full effect and been synchronized to memory.
- *     Eg. any invalidate completed [so as not to generate a hit],
- *     any writebacks or other pipelined writes written to memory, etc.
- *
- *  invalidate_line            (single cache line)
- *  invalidate_region          (specified memory range)
- *  invalidate_all             (entire cache)
- *     Invalidates all cache entries that cache
- *     data from the specified memory range.
- *     NOTE: locked entries are not invalidated.
- *
- *  writeback_line             (single cache line)
- *  writeback_region           (specified memory range)
- *  writeback_all              (entire cache)
- *     Writes back to memory all dirty cache entries
- *     that cache data from the specified memory range,
- *     and marks these entries as clean.
- *     NOTE: on some future implementations, this might
- *             also invalidate.
- *     NOTE: locked entries are written back, but never invalidated.
- *     NOTE: instruction caches never implement writeback.
- *
- *  writeback_inv_line         (single cache line)
- *  writeback_inv_region       (specified memory range)
- *  writeback_inv_all          (entire cache)
- *     Writes back to memory all dirty cache entries
- *     that cache data from the specified memory range,
- *     and invalidates these entries (including all clean
- *     cache entries that cache data from that range).
- *     NOTE: locked entries are written back but not invalidated.
- *     NOTE: instruction caches never implement writeback.
- *
- *  lock_line                  (single cache line)
- *  lock_region                        (specified memory range)
- *     Prefetch and lock the specified memory range into cache.
- *     NOTE:  if any part of the specified memory range cannot
- *     be locked, a ??? exception occurs.  These macros don't
- *     do anything special (yet anyway) to handle this situation.
- *
- *  unlock_line                        (single cache line)
- *  unlock_region              (specified memory range)
- *  unlock_all                 (entire cache)
- *     Unlock cache entries that cache the specified memory range.
- *     Entries not already locked are unaffected.
- */
-
-
-
-/***************************   GENERIC -- ALL CACHES   ***************************/
-
-
-/*
- *  The following macros assume the following cache size/parameter limits
- *  in the current Xtensa core implementation:
- *     cache size:     1024 bytes minimum
- *     line size:      16 - 64 bytes
- *     way count:      1 - 4
- *
- *  Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
- *  Hence the assumption that each loop can execute four cache instructions.
- *
- *  Correspondingly, the offset range of instructions is assumed able to cover
- *  four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
- *  both hit and indexed cache instructions.  Ie. these offsets are all
- *  valid:  0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
- *  This is true of all original cache instructions
- *  (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
- *  of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
- *  This is also true of subsequent cache instructions
- *  (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
- *  of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
- *
- *  (Maximum cache size, currently 32k, doesn't affect the following macros.
- *  Cache ways > MMU min page size cause aliasing but that's another matter.)
- */
-
-
-
-/*
- *  Macro to apply an 'indexed' cache instruction to the entire cache.
- *
- *  Parameters:
- *     cainst          instruction/ that takes an address register parameter
- *                     and an offset parameter (in range 0 .. 3*linesize).
- *     size            size of cache in bytes
- *     linesize        size of cache line in bytes
- *     assoc_or1       number of associativities (ways/sets) in cache
- *                     if all sets affected by cainst,
- *                     or 1 if only one set (or not all sets) of the cache
- *                     is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
- *     aa, ab          unique address registers (temporaries)
- */
-
-       .macro  cache_index_all         cainst, size, linesize, assoc_or1, aa, ab
-
-       //  Sanity-check on cache parameters:
-       .ifne   (\size % (\linesize * \assoc_or1 * 4))
-       .err    //  cache configuration outside expected/supported range!
-       .endif
-
-       //  \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
-       movi    \aa, (\size / (\linesize * \assoc_or1 * 4))
-       // Possible improvement: need only loop if \aa > 1 ;
-       // however that particular condition is highly unlikely.
-       movi    \ab, 0          // to iterate over cache
-       floop           \aa, cachex\@
-       \cainst         \ab, 0*\linesize
-       \cainst         \ab, 1*\linesize
-       \cainst         \ab, 2*\linesize
-       \cainst         \ab, 3*\linesize
-       addi            \ab, \ab, 4*\linesize   // move to next line
-       floopend        \aa, cachex\@
-
-       .endm
-
-
-/*
- *  Macro to apply a 'hit' cache instruction to a memory region,
- *  ie. to any cache entries that cache a specified portion (region) of memory.
- *  Takes care of the unaligned cases, ie. may apply to one
- *  more cache line than $asize / lineSize if $aaddr is not aligned.
- *
- *
- *  Parameters are:
- *     cainst  instruction/macro that takes an address register parameter
- *             and an offset parameter (currently always zero)
- *             and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
- *     linesize_log2   log2(size of cache line in bytes)
- *     addr    register containing start address of region (clobbered)
- *     asize   register containing size of the region in bytes (clobbered)
- *     askew   unique register used as temporary
- *
- * !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
- */
-
-       .macro  cache_hit_region        cainst, linesize_log2, addr, asize, askew
-
-       //  Make \asize the number of iterations:
-       extui   \askew, \addr, 0, \linesize_log2        // get unalignment amount of \addr
-       add     \asize, \asize, \askew                  // ... and add it to \asize
-       addi    \asize, \asize, (1 << \linesize_log2) - 1       // round up!
-       srli    \asize, \asize, \linesize_log2
-
-       //  Iterate over region:
-       floopnez        \asize, cacheh\@
-       \cainst         \addr, 0
-       addi            \addr, \addr, (1 << \linesize_log2)     // move to next line
-       floopend        \asize, cacheh\@
-
-       .endm
-
-
-
-
-
-/***************************   INSTRUCTION CACHE   ***************************/
-
-
-/*
- *  Reset/initialize the instruction cache by simply invalidating it:
- *  (need to unlock first also, if cache locking implemented):
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  icache_reset    aa, ab
-       icache_unlock_all       \aa, \ab
-       icache_invalidate_all   \aa, \ab
-       .endm
-
-
-/*
- * Synchronize after an instruction cache operation,
- * to be sure everything is in sync with memory as to be
- * expected following any previous instruction cache control operations.
- *
- * Parameters are:
- *     ar      an address register (temporary) (currently unused, but may be used in future)
- */
-       .macro  icache_sync     ar
-#if XCHAL_ICACHE_SIZE > 0
-       isync
-#endif
-       .endm
-
-
-
-/*
- *  Invalidate a single line of the instruction cache.
- *  Parameters are:
- *     ar      address register that contains (virtual) address to invalidate
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  (optional) offset to add to \ar to compute effective address to invalidate
- *             (note: some number of lsbits are ignored)
- */
-       .macro  icache_invalidate_line  ar, offset
-#if XCHAL_ICACHE_SIZE > 0
-       ihi     \ar, \offset            // invalidate icache line
-       /*
-        *  NOTE:  in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
-        *  'ihi' doesn't work, so it had been replaced with 'iii'
-        *  (which would just invalidate more than it should,
-        *  which should be okay other than the performance hit
-        *  because cache locking did not exist in that version,
-        *  unless user somehow relies on something being cached).
-        *  [WHAT VERSION IS IT!!?!?
-        *  IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
-        *
-        *      iii     \ar, \offset
-        */
-       icache_sync     \ar
-#endif
-       .endm
-
-
-
-
-/*
- *  Invalidate instruction  cache entries that cache a specified portion of memory.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  icache_invalidate_region        astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0
-       //  Instruction cache region invalidation:
-       cache_hit_region        ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
-       icache_sync     \ac
-       //  End of instruction cache region invalidation
-#endif
-       .endm
-
-
-
-/*
- *  Invalidate entire instruction cache.
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  icache_invalidate_all   aa, ab
-#if XCHAL_ICACHE_SIZE > 0
-       //  Instruction cache invalidation:
-       cache_index_all         iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
-       icache_sync     \aa
-       //  End of instruction cache invalidation
-#endif
-       .endm
-
-
-
-/*
- *  Lock (prefetch & lock) a single line of the instruction cache.
- *
- *  Parameters are:
- *     ar      address register that contains (virtual) address to lock
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to lock
- *             (note: some number of lsbits are ignored)
- */
-       .macro  icache_lock_line        ar, offset
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
-       ipfl    \ar, \offset    /* prefetch and lock icache line */
-       icache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Lock (prefetch & lock) a specified portion of memory into the instruction cache.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  icache_lock_region      astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
-       //  Instruction cache region lock:
-       cache_hit_region        ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
-       icache_sync     \ac
-       //  End of instruction cache region lock
-#endif
-       .endm
-
-
-
-/*
- *  Unlock a single line of the instruction cache.
- *
- *  Parameters are:
- *     ar      address register that contains (virtual) address to unlock
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to unlock
- *             (note: some number of lsbits are ignored)
- */
-       .macro  icache_unlock_line      ar, offset
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
-       ihu     \ar, \offset    /* unlock icache line */
-       icache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Unlock a specified portion of memory from the instruction cache.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  icache_unlock_region    astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
-       //  Instruction cache region unlock:
-       cache_hit_region        ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
-       icache_sync     \ac
-       //  End of instruction cache region unlock
-#endif
-       .endm
-
-
-
-/*
- *  Unlock entire instruction cache.
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  icache_unlock_all       aa, ab
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
-       //  Instruction cache unlock:
-       cache_index_all         iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
-       icache_sync     \aa
-       //  End of instruction cache unlock
-#endif
-       .endm
-
-
-
-
-
-/***************************   DATA CACHE   ***************************/
-
-
-
-/*
- *  Reset/initialize the data cache by simply invalidating it
- *  (need to unlock first also, if cache locking implemented):
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  dcache_reset    aa, ab
-       dcache_unlock_all       \aa, \ab
-       dcache_invalidate_all   \aa, \ab
-       .endm
-
-
-
-
-/*
- * Synchronize after a data cache operation,
- * to be sure everything is in sync with memory as to be
- * expected following any previous data cache control operations.
- *
- * Parameters are:
- *     ar      an address register (temporary) (currently unused, but may be used in future)
- */
-       .macro  dcache_sync     ar
-#if XCHAL_DCACHE_SIZE > 0
-       //  This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
-       //memw          // synchronize data cache changes relative to subsequent memory accesses
-       //isync         // be conservative and ISYNC as well (just to be sure)
-
-       dsync
-#endif
-       .endm
-
-
-
-/*
- * Synchronize after a data store operation,
- * to be sure the stored data is completely off the processor
- * (and assuming there is no buffering outside the processor,
- *  that the data is in memory).  This may be required to
- * ensure that the processor's write buffers are emptied.
- * A MEMW followed by a read guarantees this, by definition.
- * We also try to make sure the read itself completes.
- *
- * Parameters are:
- *     ar      an address register (temporary)
- */
-       .macro  write_sync      ar
-       memw                    // ensure previous memory accesses are complete prior to subsequent memory accesses
-       l32i    \ar, sp, 0      // completing this read ensures any previous write has completed, because of MEMW
-       //slot
-       add     \ar, \ar, \ar   // use the result of the read to help ensure the read completes (in future architectures)
-       .endm
-
-
-/*
- *  Invalidate a single line of the data cache.
- *  Parameters are:
- *     ar      address register that contains (virtual) address to invalidate
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  (optional) offset to add to \ar to compute effective address to invalidate
- *             (note: some number of lsbits are ignored)
- */
-       .macro  dcache_invalidate_line  ar, offset
-#if XCHAL_DCACHE_SIZE > 0
-       dhi     \ar, \offset
-       dcache_sync     \ar
-#endif
-       .endm
-
-
-
-
-
-/*
- *  Invalidate data cache entries that cache a specified portion of memory.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  dcache_invalidate_region        astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0
-       //  Data cache region invalidation:
-       cache_hit_region        dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
-       dcache_sync     \ac
-       //  End of data cache region invalidation
-#endif
-       .endm
-
-
-
-#if 0
-/*
- *  This is a work-around for a bug in SiChip1 (???).
- *  There should be a proper mechanism for not outputting
- *  these instructions when not needed.
- *  To enable work-around, uncomment this and replace 'dii'
- *  with 'dii_s1' everywhere, eg. in dcache_invalidate_all
- *  macro below.
- */
-       .macro  dii_s1  ar, offset
-       dii     \ar, \offset
-       or      \ar, \ar, \ar
-       or      \ar, \ar, \ar
-       or      \ar, \ar, \ar
-       or      \ar, \ar, \ar
-       .endm
-#endif
-
-
-/*
- *  Invalidate entire data cache.
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  dcache_invalidate_all   aa, ab
-#if XCHAL_DCACHE_SIZE > 0
-       //  Data cache invalidation:
-       cache_index_all         dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
-       dcache_sync     \aa
-       //  End of data cache invalidation
-#endif
-       .endm
-
-
-
-/*
- *  Writeback a single line of the data cache.
- *  Parameters are:
- *     ar      address register that contains (virtual) address to writeback
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to writeback
- *             (note: some number of lsbits are ignored)
- */
-       .macro  dcache_writeback_line   ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
-       dhwb    \ar, \offset
-       dcache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Writeback dirty data cache entries that cache a specified portion of memory.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  dcache_writeback_region         astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
-       //  Data cache region writeback:
-       cache_hit_region        dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
-       dcache_sync     \ac
-       //  End of data cache region writeback
-#endif
-       .endm
-
-
-
-/*
- *  Writeback entire data cache.
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  dcache_writeback_all    aa, ab
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
-       //  Data cache writeback:
-       cache_index_all         diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
-       dcache_sync     \aa
-       //  End of data cache writeback
-#endif
-       .endm
-
-
-
-/*
- *  Writeback and invalidate a single line of the data cache.
- *  Parameters are:
- *     ar      address register that contains (virtual) address to writeback and invalidate
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to writeback and invalidate
- *             (note: some number of lsbits are ignored)
- */
-       .macro  dcache_writeback_inv_line       ar, offset
-#if XCHAL_DCACHE_SIZE > 0
-       dhwbi   \ar, \offset    /* writeback and invalidate dcache line */
-       dcache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Writeback and invalidate data cache entries that cache a specified portion of memory.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  dcache_writeback_inv_region     astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0
-       //  Data cache region writeback and invalidate:
-       cache_hit_region        dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
-       dcache_sync     \ac
-       //  End of data cache region writeback and invalidate
-#endif
-       .endm
-
-
-
-/*
- *  Writeback and invalidate entire data cache.
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  dcache_writeback_inv_all        aa, ab
-#if XCHAL_DCACHE_SIZE > 0
-       //  Data cache writeback and invalidate:
-#if XCHAL_DCACHE_IS_WRITEBACK
-       cache_index_all         diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
-       dcache_sync     \aa
-#else /*writeback*/
-       //  Data cache does not support writeback, so just invalidate: */
-       dcache_invalidate_all   \aa, \ab
-#endif /*writeback*/
-       //  End of data cache writeback and invalidate
-#endif
-       .endm
-
-
-
-
-/*
- *  Lock (prefetch & lock) a single line of the data cache.
- *
- *  Parameters are:
- *     ar      address register that contains (virtual) address to lock
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to lock
- *             (note: some number of lsbits are ignored)
- */
-       .macro  dcache_lock_line        ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
-       dpfl    \ar, \offset    /* prefetch and lock dcache line */
-       dcache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Lock (prefetch & lock) a specified portion of memory into the data cache.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  dcache_lock_region      astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
-       //  Data cache region lock:
-       cache_hit_region        dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
-       dcache_sync     \ac
-       //  End of data cache region lock
-#endif
-       .endm
-
-
-
-/*
- *  Unlock a single line of the data cache.
- *
- *  Parameters are:
- *     ar      address register that contains (virtual) address to unlock
- *             (may get clobbered in a future implementation, but not currently)
- *     offset  offset to add to \ar to compute effective address to unlock
- *             (note: some number of lsbits are ignored)
- */
-       .macro  dcache_unlock_line      ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
-       dhu     \ar, \offset    /* unlock dcache line */
-       dcache_sync     \ar
-#endif
-       .endm
-
-
-
-/*
- *  Unlock a specified portion of memory from the data cache.
- *  Parameters are:
- *     astart  start address (register gets clobbered)
- *     asize   size of the region in bytes (register gets clobbered)
- *     ac      unique register used as temporary
- */
-       .macro  dcache_unlock_region    astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
-       //  Data cache region unlock:
-       cache_hit_region        dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
-       dcache_sync     \ac
-       //  End of data cache region unlock
-#endif
-       .endm
-
-
-
-/*
- *  Unlock entire data cache.
- *
- *  Parameters:
- *     aa, ab          unique address registers (temporaries)
- */
-       .macro  dcache_unlock_all       aa, ab
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
-       //  Data cache unlock:
-       cache_index_all         diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
-       dcache_sync     \aa
-       //  End of data cache unlock
-#endif
-       .endm
-
-
-#endif /*XTENSA_CACHEASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/cacheattrasm.h b/include/asm-xtensa/xtensa/cacheattrasm.h
deleted file mode 100644 (file)
index 1c3e117..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-#ifndef XTENSA_CACHEATTRASM_H
-#define XTENSA_CACHEATTRASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific
- * CACHEATTR register related definitions that depend on CORE
- * configuration.
- *
- * 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) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/coreasm.h>
-
-
-/*
- *  This header file defines assembler macros of the form:
- *     <x>cacheattr_<func>
- *  where:
- *     <x> is 'i', 'd' or absent for instruction, data
- *             or both caches; and
- *     <func> indicates the function of the macro.
- *
- *  The following functions are defined:
- *
- *  icacheattr_get
- *     Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
- *
- *  dcacheattr_get
- *     Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
- *     (Note:  for configs with a real CACHEATTR register, the
- *      above two macros are identical.)
- *
- *  cacheattr_set
- *     Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
- *     Works even when changing one's own code's attributes.
- *
- *  icacheattr_is_enabled  label
- *     Branches to \label if I-cache appears to have been enabled
- *     (eg. if CACHEATTR contains a cache-enabled attribute).
- *     (clobbers a2-a5,SAR)
- *
- *  dcacheattr_is_enabled  label
- *     Branches to \label if D-cache appears to have been enabled
- *     (eg. if CACHEATTR contains a cache-enabled attribute).
- *     (clobbers a2-a5,SAR)
- *
- *  cacheattr_is_enabled  label
- *     Branches to \label if either I-cache or D-cache appears to have been enabled
- *     (eg. if CACHEATTR contains a cache-enabled attribute).
- *     (clobbers a2-a5,SAR)
- *
- *  The following macros are only defined under certain conditions:
- *
- *  icacheattr_set     (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
- *     Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
- *
- *  dcacheattr_set     (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
- *     Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
- */
-
-
-
-/***************************   GENERIC -- ALL CACHES   ***************************/
-
-/*
- *  _cacheattr_get
- *
- *  (Internal macro.)
- *  Returns value of CACHEATTR register (or closest equivalent) in a2.
- *
- *  Entry:
- *     (none)
- *  Exit:
- *     a2      value read from CACHEATTR
- *     a3-a5   clobbered (temporaries)
- */
-       .macro  _cacheattr_get  tlb
-#if XCHAL_HAVE_CACHEATTR
-       rsr     a2, CACHEATTR
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       //  We have a config that "mimics" CACHEATTR using a simplified
-       //  "MMU" composed of a single statically-mapped way.
-       //  DTLB and ITLB are independent, so there's no single
-       //  cache attribute that can describe both.  So for now
-       //  just return the DTLB state.
-       movi    a5, 0xE0000000
-       movi    a2, 0
-       movi    a3, 0
-1:     add     a3, a3, a5      // next segment
-       r&tlb&1 a4, a3          // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
-       dsync   // interlock???
-       slli    a2, a2, 4
-       extui   a4, a4, 0, 4    // extract CA
-       or      a2, a2, a4
-       bnez    a3, 1b
-#else
-       //  This macro isn't applicable to arbitrary MMU configurations.
-       //  Just return zero.
-       movi    a2, 0
-#endif
-       .endm
-
-       .macro  icacheattr_get
-       _cacheattr_get  itlb
-       .endm
-
-       .macro  dcacheattr_get
-       _cacheattr_get  dtlb
-       .endm
-
-
-#define XCHAL_CACHEATTR_ALL_BYPASS     0x22222222      /* default (powerup/reset) value of CACHEATTR, all BYPASS
-                                                          mode (ie. disabled/bypassed caches) */
-
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-
-#define XCHAL_FCA_ENAMASK      0x001A  /* bitmap of fetch attributes that require enabled icache */
-#define XCHAL_LCA_ENAMASK      0x0003  /* bitmap of load  attributes that require enabled dcache */
-#define XCHAL_SCA_ENAMASK      0x0003  /* bitmap of store attributes that require enabled dcache */
-#define XCHAL_LSCA_ENAMASK     (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK)   /* l/s attrs requiring enabled dcache */
-#define XCHAL_ALLCA_ENAMASK    (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK)  /* all attrs requiring enabled caches */
-
-/*
- *  _cacheattr_is_enabled
- *
- *  (Internal macro.)
- *  Branches to \label if CACHEATTR in a2 indicates an enabled
- *  cache, using mask in a3.
- *
- *  Parameters:
- *     label   where to branch to if cache is enabled
- *  Entry:
- *     a2      contains CACHEATTR value used to determine whether
- *             caches are enabled
- *     a3      16-bit constant where each bit correspond to
- *             one of the 16 possible CA values (in a CACHEATTR mask);
- *             CA values that indicate the cache is enabled
- *             have their corresponding bit set in this mask
- *             (eg. use XCHAL_xCA_ENAMASK , above)
- *  Exit:
- *     a2,a4,a5        clobbered
- *     SAR             clobbered
- */
-       .macro  _cacheattr_is_enabled   label
-       movi    a4, 8           // loop 8 times
-.Lcaife\@:
-       extui   a5, a2, 0, 4    // get CA nibble
-       ssr     a5              // index into mask according to CA...
-       srl     a5, a3          // ...and get CA's mask bit in a5 bit 0
-       bbsi.l  a5, 0, \label   // if CA indicates cache enabled, jump to label
-       srli    a2, a2, 4       // next nibble
-       addi    a4, a4, -1
-       bnez    a4, .Lcaife\@   // loop for each nibble
-       .endm
-
-#else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
-       .macro  _cacheattr_is_enabled   label
-       j       \label          // macro not applicable, assume caches always enabled
-       .endm
-#endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
-
-
-
-/*
- *  icacheattr_is_enabled
- *
- *  Branches to \label if I-cache is enabled.
- *
- *  Parameters:
- *     label   where to branch to if icache is enabled
- *  Entry:
- *     (none)
- *  Exit:
- *     a2-a5, SAR      clobbered (temporaries)
- */
-       .macro  icacheattr_is_enabled   label
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       icacheattr_get
-       movi    a3, XCHAL_FCA_ENAMASK
-#endif
-       _cacheattr_is_enabled   \label
-       .endm
-
-/*
- *  dcacheattr_is_enabled
- *
- *  Branches to \label if D-cache is enabled.
- *
- *  Parameters:
- *     label   where to branch to if dcache is enabled
- *  Entry:
- *     (none)
- *  Exit:
- *     a2-a5, SAR      clobbered (temporaries)
- */
-       .macro  dcacheattr_is_enabled   label
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       dcacheattr_get
-       movi    a3, XCHAL_LSCA_ENAMASK
-#endif
-       _cacheattr_is_enabled   \label
-       .endm
-
-/*
- *  cacheattr_is_enabled
- *
- *  Branches to \label if either I-cache or D-cache is enabled.
- *
- *  Parameters:
- *     label   where to branch to if a cache is enabled
- *  Entry:
- *     (none)
- *  Exit:
- *     a2-a5, SAR      clobbered (temporaries)
- */
-       .macro  cacheattr_is_enabled    label
-#if XCHAL_HAVE_CACHEATTR
-       rsr     a2, CACHEATTR
-       movi    a3, XCHAL_ALLCA_ENAMASK
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       icacheattr_get
-       movi    a3, XCHAL_FCA_ENAMASK
-       _cacheattr_is_enabled   \label
-       dcacheattr_get
-       movi    a3, XCHAL_LSCA_ENAMASK
-#endif
-       _cacheattr_is_enabled   \label
-       .endm
-
-
-
-/*
- *  The ISA does not have a defined way to change the
- *  instruction cache attributes of the running code,
- *  ie. of the memory area that encloses the current PC.
- *  However, each micro-architecture (or class of
- *  configurations within a micro-architecture)
- *  provides a way to deal with this issue.
- *
- *  Here are a few macros used to implement the relevant
- *  approach taken.
- */
-
-#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       //  We have a config that "mimics" CACHEATTR using a simplified
-       //  "MMU" composed of a single statically-mapped way.
-
-/*
- *  icacheattr_set
- *
- *  Entry:
- *     a2              cacheattr value to set
- *  Exit:
- *     a2              unchanged
- *     a3-a8           clobbered (temporaries)
- */
-       .macro  icacheattr_set
-
-       movi    a5, 0xE0000000  // mask of upper 3 bits
-       movi    a6, 3f          // PC where ITLB is set
-       movi    a3, 0           // start at region 0 (0 .. 7)
-       and     a6, a6, a5      // upper 3 bits of local PC area
-       mov     a7, a2          // copy a2 so it doesn't get clobbered
-       j       3f
-
-# if XCHAL_HAVE_XLT_CACHEATTR
-       //  Can do translations, use generic method:
-1:     sub     a6, a3, a5      // address of some other segment
-       ritlb1  a8, a6          // save its PPN+CA
-       dsync   // interlock??
-       witlb   a4, a6          // make it translate to this code area
-       movi    a6, 5f          // where to jump into it
-       isync
-       sub     a6, a6, a5      // adjust jump address within that other segment
-       jx      a6
-
-       //  Note that in the following code snippet, which runs at a different virtual
-       //  address than it is assembled for, we avoid using literals (eg. via movi/l32r)
-       //  just in case literals end up in a different 512 MB segment, and we avoid
-       //  instructions that rely on the current PC being what is expected.
-       //
-       .align  4
-       _j      6f              // this is at label '5' minus 4 bytes
-       .align  4
-5:     witlb   a4, a3          // we're in other segment, now can write previous segment's CA
-       isync
-       add     a6, a6, a5      // back to previous segment
-       addi    a6, a6, -4      // next jump label
-       jx      a6
-
-6:     sub     a6, a3, a5      // address of some other segment
-       witlb   a8, a6          // restore PPN+CA of other segment
-       mov     a6, a3          // restore a6
-       isync
-# else /* XCHAL_HAVE_XLT_CACHEATTR */
-       //  Use micro-architecture specific method.
-       //  The following 4-instruction sequence is aligned such that
-       //  it all fits within a single I-cache line.  Sixteen byte
-       //  alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
-       //  actually causes problems because that can be greater than
-       //  the alignment of the reset vector, where this macro is often
-       //  invoked, which would cause the linker to align the reset
-       //  vector code away from the reset vector!!).
-       .align  16 /*XCHAL_ICACHE_LINESIZE*/
-1:     _witlb  a4, a3          // write wired PTE (CA, no PPN) of 512MB segment to ITLB
-       _isync
-       nop
-       nop
-# endif /* XCHAL_HAVE_XLT_CACHEATTR */
-       beq     a3, a5, 4f      // done?
-
-       //  Note that in the WITLB loop, we don't do any load/stores
-       //  (may not be an issue here, but it is important in the DTLB case).
-2:     srli    a7, a7, 4       // next CA
-       sub     a3, a3, a5      // next segment (add 0x20000000)
-3:
-# if XCHAL_HAVE_XLT_CACHEATTR  /* if have translation, preserve it */
-       ritlb1  a8, a3          // get current PPN+CA of segment
-       dsync   // interlock???
-       extui   a4, a7, 0, 4    // extract CA to set
-       srli    a8, a8, 4       // clear CA but keep PPN ...
-       slli    a8, a8, 4       // ...
-       add     a4, a4, a8      // combine new CA with PPN to preserve
-# else
-       extui   a4, a7, 0, 4    // extract CA
-# endif
-       beq     a3, a6, 1b      // current PC's region? if so, do it in a safe way
-       witlb   a4, a3          // write wired PTE (CA [+PPN]) of 512MB segment to ITLB
-       bne     a3, a5, 2b
-       isync                   // make sure all ifetch changes take effect
-4:
-       .endm   // icacheattr_set
-
-
-/*
- *  dcacheattr_set
- *
- *  Entry:
- *     a2              cacheattr value to set
- *  Exit:
- *     a2              unchanged
- *     a3-a8           clobbered (temporaries)
- */
-
-       .macro  dcacheattr_set
-
-       movi    a5, 0xE0000000  // mask of upper 3 bits
-       movi    a3, 0           // start at region 0 (0 .. 7)
-       mov     a7, a2          // copy a2 so it doesn't get clobbered
-       j       3f
-       //  Note that in the WDTLB loop, we don't do any load/stores
-       //  (including implicit l32r via movi) because it isn't safe.
-2:     srli    a7, a7, 4       // next CA
-       sub     a3, a3, a5      // next segment (add 0x20000000)
-3:
-# if XCHAL_HAVE_XLT_CACHEATTR  /* if have translation, preserve it */
-       rdtlb1  a8, a3          // get current PPN+CA of segment
-       dsync   // interlock???
-       extui   a4, a7, 0, 4    // extract CA to set
-       srli    a8, a8, 4       // clear CA but keep PPN ...
-       slli    a8, a8, 4       // ...
-       add     a4, a4, a8      // combine new CA with PPN to preserve
-# else
-       extui   a4, a7, 0, 4    // extract CA to set
-# endif
-       wdtlb   a4, a3          // write wired PTE (CA [+PPN]) of 512MB segment to DTLB
-       bne     a3, a5, 2b
-       dsync                   // make sure all data path changes take effect
-       .endm   // dcacheattr_set
-
-#endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
-
-
-
-/*
- *  cacheattr_set
- *
- *  Macro that sets the current CACHEATTR safely
- *  (both i and d) according to the current contents of a2.
- *  It works even when changing the cache attributes of
- *  the currently running code.
- *
- *  Entry:
- *     a2              cacheattr value to set
- *  Exit:
- *     a2              unchanged
- *     a3-a8           clobbered (temporaries)
- */
-       .macro  cacheattr_set
-
-#if XCHAL_HAVE_CACHEATTR
-# if XCHAL_ICACHE_LINESIZE < 4
-       //  No i-cache, so can always safely write to CACHEATTR:
-       wsr     a2, CACHEATTR
-# else
-       //  The Athens micro-architecture, when using the old
-       //  exception architecture option (ie. with the CACHEATTR register)
-       //  allows changing the cache attributes of the running code
-       //  using the following exact sequence aligned to be within
-       //  an instruction cache line.  (NOTE: using XCHAL_ICACHE_LINESIZE
-       //  alignment actually causes problems because that can be greater
-       //  than the alignment of the reset vector, where this macro is often
-       //  invoked, which would cause the linker to align the reset
-       //  vector code away from the reset vector!!).
-       j       1f
-       .align  16 /*XCHAL_ICACHE_LINESIZE*/    // align to within an I-cache line
-1:     _wsr    a2, CACHEATTR
-       _isync
-       nop
-       nop
-# endif
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-       //  DTLB and ITLB are independent, but to keep semantics
-       //  of this macro we simply write to both.
-       icacheattr_set
-       dcacheattr_set
-#else
-       //  This macro isn't applicable to arbitrary MMU configurations.
-       //  Do nothing in this case.
-#endif
-       .endm
-
-
-#endif /*XTENSA_CACHEATTRASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/core.h b/include/asm-xtensa/xtensa/config-linux_be/core.h
deleted file mode 100644 (file)
index d54fe5e..0000000
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
- * xtensa/config/core.h -- HAL definitions that are dependent on CORE configuration
- *
- *  This header file is sometimes referred to as the "compile-time HAL" or CHAL.
- *  It was generated for a specific Xtensa processor configuration.
- *
- *  Source for configuration-independent binaries (which link in a
- *  configuration-specific HAL library) must NEVER include this file.
- *  It is perfectly normal, however, for the HAL source itself to include this file.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- */
-
-
-#ifndef XTENSA_CONFIG_CORE_H
-#define XTENSA_CONFIG_CORE_H
-
-#include <xtensa/hal.h>
-
-
-/*----------------------------------------------------------------------
-                               GENERAL
-  ----------------------------------------------------------------------*/
-
-/*
- *  Separators for macros that expand into arrays.
- *  These can be predefined by files that #include this one,
- *  when different separators are required.
- */
-/*  Element separator for macros that expand into 1-dimensional arrays:  */
-#ifndef XCHAL_SEP
-#define XCHAL_SEP                      ,
-#endif
-/*  Array separator for macros that expand into 2-dimensional arrays:  */
-#ifndef XCHAL_SEP2
-#define XCHAL_SEP2                     },{
-#endif
-
-
-/*----------------------------------------------------------------------
-                               ENDIANNESS
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_BE                  1
-#define XCHAL_HAVE_LE                  0
-#define XCHAL_MEMORY_ORDER             XTHAL_BIGENDIAN
-
-
-/*----------------------------------------------------------------------
-                               REGISTER WINDOWS
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_WINDOWED            1       /* 1 if windowed registers option configured, 0 otherwise */
-#define XCHAL_NUM_AREGS                        64      /* number of physical address regs */
-#define XCHAL_NUM_AREGS_LOG2           6       /* log2(XCHAL_NUM_AREGS) */
-
-
-/*----------------------------------------------------------------------
-                               ADDRESS ALIGNMENT
-  ----------------------------------------------------------------------*/
-
-/*  These apply to a selected set of core load and store instructions only (see ISA):  */
-#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1       /* 1 if unaligned loads cause an exception, 0 otherwise */
-#define XCHAL_UNALIGNED_STORE_EXCEPTION        1       /* 1 if unaligned stores cause an exception, 0 otherwise */
-
-
-/*----------------------------------------------------------------------
-                               INTERRUPTS
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_INTERRUPTS          1       /* 1 if interrupt option configured, 0 otherwise */
-#define XCHAL_HAVE_HIGHPRI_INTERRUPTS  1       /* 1 if high-priority interrupt option configured, 0 otherwise */
-#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS        XCHAL_HAVE_HIGHPRI_INTERRUPTS
-#define XCHAL_HAVE_NMI                 0       /* 1 if NMI option configured, 0 otherwise */
-#define XCHAL_NUM_INTERRUPTS           17      /* number of interrupts */
-#define XCHAL_NUM_INTERRUPTS_LOG2      5       /* number of bits to hold an interrupt number: roundup(log2(number of interrupts)) */
-#define XCHAL_NUM_EXTINTERRUPTS                10      /* number of external interrupts */
-#define XCHAL_NUM_INTLEVELS            4       /* number of interrupt levels (not including level zero!) */
-#define XCHAL_NUM_LOWPRI_LEVELS                1                       /* number of low-priority interrupt levels (always 1) */
-#define XCHAL_FIRST_HIGHPRI_LEVEL      (XCHAL_NUM_LOWPRI_LEVELS+1)     /* level of first high-priority interrupt (always 2) */
-#define XCHAL_EXCM_LEVEL               1                       /* level of interrupts masked by PS.EXCM (XEA2 only; always 1 in T10xx);
-                                                                  for XEA1, where there is no PS.EXCM, this is always 1;
-                                                                  interrupts at levels FIRST_HIGHPRI <= n <= EXCM_LEVEL, if any,
-                                                                  are termed "medium priority" interrupts (post T10xx only) */
-/*  Note:  1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15  */
-
-/*  Masks of interrupts at each interrupt level:  */
-#define XCHAL_INTLEVEL0_MASK           0x00000000
-#define XCHAL_INTLEVEL1_MASK           0x000064F9
-#define XCHAL_INTLEVEL2_MASK           0x00008902
-#define XCHAL_INTLEVEL3_MASK           0x00011204
-#define XCHAL_INTLEVEL4_MASK           0x00000000
-#define XCHAL_INTLEVEL5_MASK           0x00000000
-#define XCHAL_INTLEVEL6_MASK           0x00000000
-#define XCHAL_INTLEVEL7_MASK           0x00000000
-#define XCHAL_INTLEVEL8_MASK           0x00000000
-#define XCHAL_INTLEVEL9_MASK           0x00000000
-#define XCHAL_INTLEVEL10_MASK          0x00000000
-#define XCHAL_INTLEVEL11_MASK          0x00000000
-#define XCHAL_INTLEVEL12_MASK          0x00000000
-#define XCHAL_INTLEVEL13_MASK          0x00000000
-#define XCHAL_INTLEVEL14_MASK          0x00000000
-#define XCHAL_INTLEVEL15_MASK          0x00000000
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_INTLEVEL_MASKS           0x00000000      XCHAL_SEP \
-                                       0x000064F9      XCHAL_SEP \
-                                       0x00008902      XCHAL_SEP \
-                                       0x00011204      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000      XCHAL_SEP \
-                                       0x00000000
-
-/*  Masks of interrupts at each range 1..n of interrupt levels:  */
-#define XCHAL_INTLEVEL0_ANDBELOW_MASK  0x00000000
-#define XCHAL_INTLEVEL1_ANDBELOW_MASK  0x000064F9
-#define XCHAL_INTLEVEL2_ANDBELOW_MASK  0x0000EDFB
-#define XCHAL_INTLEVEL3_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL4_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL5_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL6_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL7_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL8_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL9_ANDBELOW_MASK  0x0001FFFF
-#define XCHAL_INTLEVEL10_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL11_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL12_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL13_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL14_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL15_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_LOWPRI_MASK              XCHAL_INTLEVEL1_ANDBELOW_MASK   /* mask of all low-priority interrupts */
-#define XCHAL_EXCM_MASK                        XCHAL_INTLEVEL1_ANDBELOW_MASK   /* mask of all interrupts masked by PS.EXCM (or CEXCM) */
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_INTLEVEL_ANDBELOW_MASKS  0x00000000      XCHAL_SEP \
-                                       0x000064F9      XCHAL_SEP \
-                                       0x0000EDFB      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF      XCHAL_SEP \
-                                       0x0001FFFF
-
-/*  Interrupt numbers for each interrupt level at which only one interrupt was configured:  */
-/*#define XCHAL_INTLEVEL1_NUM          ...more than one interrupt at this level...*/
-/*#define XCHAL_INTLEVEL2_NUM          ...more than one interrupt at this level...*/
-/*#define XCHAL_INTLEVEL3_NUM          ...more than one interrupt at this level...*/
-
-/*  Level of each interrupt:  */
-#define XCHAL_INT0_LEVEL               1
-#define XCHAL_INT1_LEVEL               2
-#define XCHAL_INT2_LEVEL               3
-#define XCHAL_INT3_LEVEL               1
-#define XCHAL_INT4_LEVEL               1
-#define XCHAL_INT5_LEVEL               1
-#define XCHAL_INT6_LEVEL               1
-#define XCHAL_INT7_LEVEL               1
-#define XCHAL_INT8_LEVEL               2
-#define XCHAL_INT9_LEVEL               3
-#define XCHAL_INT10_LEVEL              1
-#define XCHAL_INT11_LEVEL              2
-#define XCHAL_INT12_LEVEL              3
-#define XCHAL_INT13_LEVEL              1
-#define XCHAL_INT14_LEVEL              1
-#define XCHAL_INT15_LEVEL              2
-#define XCHAL_INT16_LEVEL              3
-#define XCHAL_INT17_LEVEL              0
-#define XCHAL_INT18_LEVEL              0
-#define XCHAL_INT19_LEVEL              0
-#define XCHAL_INT20_LEVEL              0
-#define XCHAL_INT21_LEVEL              0
-#define XCHAL_INT22_LEVEL              0
-#define XCHAL_INT23_LEVEL              0
-#define XCHAL_INT24_LEVEL              0
-#define XCHAL_INT25_LEVEL              0
-#define XCHAL_INT26_LEVEL              0
-#define XCHAL_INT27_LEVEL              0
-#define XCHAL_INT28_LEVEL              0
-#define XCHAL_INT29_LEVEL              0
-#define XCHAL_INT30_LEVEL              0
-#define XCHAL_INT31_LEVEL              0
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_INT_LEVELS               1       XCHAL_SEP \
-                                       2       XCHAL_SEP \
-                                       3       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       2       XCHAL_SEP \
-                                       3       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       2       XCHAL_SEP \
-                                       3       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       1       XCHAL_SEP \
-                                       2       XCHAL_SEP \
-                                       3       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0       XCHAL_SEP \
-                                       0
-
-/*  Type of each interrupt:  */
-#define XCHAL_INT0_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT1_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT2_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT3_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT4_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT5_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT6_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT7_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT8_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT9_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT10_TYPE       XTHAL_INTTYPE_TIMER
-#define XCHAL_INT11_TYPE       XTHAL_INTTYPE_TIMER
-#define XCHAL_INT12_TYPE       XTHAL_INTTYPE_TIMER
-#define XCHAL_INT13_TYPE       XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT14_TYPE       XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT15_TYPE       XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT16_TYPE       XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT17_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT18_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT19_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT20_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT21_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT22_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT23_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT24_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT25_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT26_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT27_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT28_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT29_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT30_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT31_TYPE       XTHAL_INTTYPE_UNCONFIGURED
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_INT_TYPES                XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_LEVEL      XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_EDGE       XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_EDGE       XCHAL_SEP \
-                               XTHAL_INTTYPE_EXTERN_EDGE       XCHAL_SEP \
-                               XTHAL_INTTYPE_TIMER             XCHAL_SEP \
-                               XTHAL_INTTYPE_TIMER             XCHAL_SEP \
-                               XTHAL_INTTYPE_TIMER             XCHAL_SEP \
-                               XTHAL_INTTYPE_SOFTWARE          XCHAL_SEP \
-                               XTHAL_INTTYPE_SOFTWARE          XCHAL_SEP \
-                               XTHAL_INTTYPE_SOFTWARE          XCHAL_SEP \
-                               XTHAL_INTTYPE_SOFTWARE          XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED      XCHAL_SEP \
-                               XTHAL_INTTYPE_UNCONFIGURED
-
-/*  Masks of interrupts for each type of interrupt:  */
-#define XCHAL_INTTYPE_MASK_UNCONFIGURED        0xFFFE0000
-#define XCHAL_INTTYPE_MASK_SOFTWARE    0x0001E000
-#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
-#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL        0x0000007F
-#define XCHAL_INTTYPE_MASK_TIMER       0x00001C00
-#define XCHAL_INTTYPE_MASK_NMI         0x00000000
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_INTTYPE_MASKS            0xFFFE0000      XCHAL_SEP \
-                                       0x0001E000      XCHAL_SEP \
-                                       0x00000380      XCHAL_SEP \
-                                       0x0000007F      XCHAL_SEP \
-                                       0x00001C00      XCHAL_SEP \
-                                       0x00000000
-
-/*  Interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned  */
-#define XCHAL_TIMER0_INTERRUPT 10
-#define XCHAL_TIMER1_INTERRUPT 11
-#define XCHAL_TIMER2_INTERRUPT 12
-#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
-/*  As an array of entries (eg. for C constant arrays):  */
-#define XCHAL_TIMER_INTERRUPTS 10      XCHAL_SEP \
-                               11      XCHAL_SEP \
-                               12      XCHAL_SEP \
-                               XTHAL_TIMER_UNCONFIGURED
-
-/*  Indexing macros:  */
-#define _XCHAL_INTLEVEL_MASK(n)                XCHAL_INTLEVEL ## n ## _MASK
-#define XCHAL_INTLEVEL_MASK(n)         _XCHAL_INTLEVEL_MASK(n)         /* n = 0 .. 15 */
-#define _XCHAL_INTLEVEL_ANDBELOWMASK(n)        XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK
-#define XCHAL_INTLEVEL_ANDBELOW_MASK(n)        _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */
-#define _XCHAL_INT_LEVEL(n)            XCHAL_INT ## n ## _LEVEL
-#define XCHAL_INT_LEVEL(n)             _XCHAL_INT_LEVEL(n)             /* n = 0 .. 31 */
-#define _XCHAL_INT_TYPE(n)             XCHAL_INT ## n ## _TYPE
-#define XCHAL_INT_TYPE(n)              _XCHAL_INT_TYPE(n)              /* n = 0 .. 31 */
-#define _XCHAL_TIMER_INTERRUPT(n)      XCHAL_TIMER ## n ## _INTERRUPT
-#define XCHAL_TIMER_INTERRUPT(n)       _XCHAL_TIMER_INTERRUPT(n)       /* n = 0 .. 3 */
-
-
-
-/*
- *  External interrupt vectors/levels.
- *  These macros describe how Xtensa processor interrupt numbers
- *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
- *  map to external BInterrupt<n> pins, for those interrupts
- *  configured as external (level-triggered, edge-triggered, or NMI).
- *  See the Xtensa processor databook for more details.
- */
-
-/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
-#define XCHAL_EXTINT0_NUM              0       /* (intlevel 1) */
-#define XCHAL_EXTINT1_NUM              1       /* (intlevel 2) */
-#define XCHAL_EXTINT2_NUM              2       /* (intlevel 3) */
-#define XCHAL_EXTINT3_NUM              3       /* (intlevel 1) */
-#define XCHAL_EXTINT4_NUM              4       /* (intlevel 1) */
-#define XCHAL_EXTINT5_NUM              5       /* (intlevel 1) */
-#define XCHAL_EXTINT6_NUM              6       /* (intlevel 1) */
-#define XCHAL_EXTINT7_NUM              7       /* (intlevel 1) */
-#define XCHAL_EXTINT8_NUM              8       /* (intlevel 2) */
-#define XCHAL_EXTINT9_NUM              9       /* (intlevel 3) */
-
-/*  Corresponding interrupt masks:  */
-#define XCHAL_EXTINT0_MASK             0x00000001
-#define XCHAL_EXTINT1_MASK             0x00000002
-#define XCHAL_EXTINT2_MASK             0x00000004
-#define XCHAL_EXTINT3_MASK             0x00000008
-#define XCHAL_EXTINT4_MASK             0x00000010
-#define XCHAL_EXTINT5_MASK             0x00000020
-#define XCHAL_EXTINT6_MASK             0x00000040
-#define XCHAL_EXTINT7_MASK             0x00000080
-#define XCHAL_EXTINT8_MASK             0x00000100
-#define XCHAL_EXTINT9_MASK             0x00000200
-
-/*  Core config interrupt levels mapped to each external interrupt:  */
-#define XCHAL_EXTINT0_LEVEL            1       /* (int number 0) */
-#define XCHAL_EXTINT1_LEVEL            2       /* (int number 1) */
-#define XCHAL_EXTINT2_LEVEL            3       /* (int number 2) */
-#define XCHAL_EXTINT3_LEVEL            1       /* (int number 3) */
-#define XCHAL_EXTINT4_LEVEL            1       /* (int number 4) */
-#define XCHAL_EXTINT5_LEVEL            1       /* (int number 5) */
-#define XCHAL_EXTINT6_LEVEL            1       /* (int number 6) */
-#define XCHAL_EXTINT7_LEVEL            1       /* (int number 7) */
-#define XCHAL_EXTINT8_LEVEL            2       /* (int number 8) */
-#define XCHAL_EXTINT9_LEVEL            3       /* (int number 9) */
-
-
-/*----------------------------------------------------------------------
-                       EXCEPTIONS and VECTORS
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_EXCEPTIONS          1       /* 1 if exception option configured, 0 otherwise */
-
-#define XCHAL_XEA_VERSION              2       /* Xtensa Exception Architecture number: 1 for XEA1 (old), 2 for XEA2 (new) */
-#define XCHAL_HAVE_XEA1                        0       /* 1 if XEA1, 0 otherwise */
-#define XCHAL_HAVE_XEA2                        1       /* 1 if XEA2, 0 otherwise */
-/*  For backward compatibility ONLY -- DO NOT USE (will be removed in future release):  */
-#define XCHAL_HAVE_OLD_EXC_ARCH                XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */
-#define XCHAL_HAVE_EXCM                        XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */
-
-#define XCHAL_RESET_VECTOR_VADDR       0xFE000020
-#define XCHAL_RESET_VECTOR_PADDR       0xFE000020
-#define XCHAL_USER_VECTOR_VADDR                0xD0000220
-#define XCHAL_PROGRAMEXC_VECTOR_VADDR  XCHAL_USER_VECTOR_VADDR         /* for backward compatibility */
-#define XCHAL_USEREXC_VECTOR_VADDR     XCHAL_USER_VECTOR_VADDR         /* for backward compatibility */
-#define XCHAL_USER_VECTOR_PADDR                0x00000220
-#define XCHAL_PROGRAMEXC_VECTOR_PADDR  XCHAL_USER_VECTOR_PADDR         /* for backward compatibility */
-#define XCHAL_USEREXC_VECTOR_PADDR     XCHAL_USER_VECTOR_PADDR         /* for backward compatibility */
-#define XCHAL_KERNEL_VECTOR_VADDR      0xD0000200
-#define XCHAL_STACKEDEXC_VECTOR_VADDR  XCHAL_KERNEL_VECTOR_VADDR       /* for backward compatibility */
-#define XCHAL_KERNELEXC_VECTOR_VADDR   XCHAL_KERNEL_VECTOR_VADDR       /* for backward compatibility */
-#define XCHAL_KERNEL_VECTOR_PADDR      0x00000200
-#define XCHAL_STACKEDEXC_VECTOR_PADDR  XCHAL_KERNEL_VECTOR_PADDR       /* for backward compatibility */
-#define XCHAL_KERNELEXC_VECTOR_PADDR   XCHAL_KERNEL_VECTOR_PADDR       /* for backward compatibility */
-#define XCHAL_DOUBLEEXC_VECTOR_VADDR   0xD0000290
-#define XCHAL_DOUBLEEXC_VECTOR_PADDR   0x00000290
-#define XCHAL_WINDOW_VECTORS_VADDR     0xD0000000
-#define XCHAL_WINDOW_VECTORS_PADDR     0x00000000
-#define XCHAL_INTLEVEL2_VECTOR_VADDR   0xD0000240
-#define XCHAL_INTLEVEL2_VECTOR_PADDR   0x00000240
-#define XCHAL_INTLEVEL3_VECTOR_VADDR   0xD0000250
-#define XCHAL_INTLEVEL3_VECTOR_PADDR   0x00000250
-#define XCHAL_INTLEVEL4_VECTOR_VADDR   0xFE000520
-#define XCHAL_INTLEVEL4_VECTOR_PADDR   0xFE000520
-#define XCHAL_DEBUG_VECTOR_VADDR       XCHAL_INTLEVEL4_VECTOR_VADDR
-#define XCHAL_DEBUG_VECTOR_PADDR       XCHAL_INTLEVEL4_VECTOR_PADDR
-
-/*  Indexing macros:  */
-#define _XCHAL_INTLEVEL_VECTOR_VADDR(n)                XCHAL_INTLEVEL ## n ## _VECTOR_VADDR
-#define XCHAL_INTLEVEL_VECTOR_VADDR(n)         _XCHAL_INTLEVEL_VECTOR_VADDR(n)         /* n = 0 .. 15 */
-
-/*
- *  General Exception Causes
- *  (values of EXCCAUSE special register set by general exceptions,
- *   which vector to the user, kernel, or double-exception vectors):
- */
-#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION             0       /* Illegal Instruction (IllegalInstruction) */
-#define XCHAL_EXCCAUSE_SYSTEM_CALL                     1       /* System Call (SystemCall) */
-#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR         2       /* Instruction Fetch Error (InstructionFetchError) */
-#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR                        3       /* Load Store Error (LoadStoreError) */
-#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT                        4       /* Level 1 Interrupt (Level1Interrupt) */
-#define XCHAL_EXCCAUSE_ALLOCA                          5       /* Stack Extension Assist (Alloca) */
-#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO          6       /* Integer Divide by Zero (IntegerDivideByZero) */
-#define XCHAL_EXCCAUSE_SPECULATION                     7       /* Speculation (Speculation) */
-#define XCHAL_EXCCAUSE_PRIVILEGED                      8       /* Privileged Instruction (Privileged) */
-#define XCHAL_EXCCAUSE_UNALIGNED                       9       /* Unaligned Load Store (Unaligned) */
-#define XCHAL_EXCCAUSE_ITLB_MISS                       16      /* ITlb Miss Exception (ITlbMiss) */
-#define XCHAL_EXCCAUSE_ITLB_MULTIHIT                   17      /* ITlb Mutltihit Exception (ITlbMultihit) */
-#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE                  18      /* ITlb Privilege Exception (ITlbPrivilege) */
-#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION           19      /* ITlb Size Restriction Exception (ITlbSizeRestriction) */
-#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE           20      /* Fetch Cache Attribute Exception (FetchCacheAttribute) */
-#define XCHAL_EXCCAUSE_DTLB_MISS                       24      /* DTlb Miss Exception (DTlbMiss) */
-#define XCHAL_EXCCAUSE_DTLB_MULTIHIT                   25      /* DTlb Multihit Exception (DTlbMultihit) */
-#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE                  26      /* DTlb Privilege Exception (DTlbPrivilege) */
-#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION           27      /* DTlb Size Restriction Exception (DTlbSizeRestriction) */
-#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE            28      /* Load Cache Attribute Exception (LoadCacheAttribute) */
-#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE           29      /* Store Cache Attribute Exception (StoreCacheAttribute) */
-#define XCHAL_EXCCAUSE_FLOATING_POINT                  40      /* Floating Point Exception (FloatingPoint) */
-
-
-
-/*----------------------------------------------------------------------
-                               TIMERS
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_CCOUNT              1       /* 1 if have CCOUNT, 0 otherwise */
-/*#define XCHAL_HAVE_TIMERS            XCHAL_HAVE_CCOUNT*/
-#define XCHAL_NUM_TIMERS               3       /* number of CCOMPAREn regs */
-
-
-
-/*----------------------------------------------------------------------
-                               DEBUG
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_DEBUG               1       /* 1 if debug option configured, 0 otherwise */
-#define XCHAL_HAVE_OCD                 1       /* 1 if OnChipDebug option configured, 0 otherwise */
-#define XCHAL_NUM_IBREAK               2       /* number of IBREAKn regs */
-#define XCHAL_NUM_DBREAK               2       /* number of DBREAKn regs */
-#define XCHAL_DEBUGLEVEL               4       /* debug interrupt level */
-/*DebugExternalInterrupt               0               0|1*/
-/*DebugUseDIRArray                     0               0|1*/
-
-
-
-
-/*----------------------------------------------------------------------
-                       COPROCESSORS and EXTRA STATE
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_CP                  0       /* 1 if coprocessor option configured (CPENABLE present) */
-#define XCHAL_CP_MAXCFG                        0       /* max allowed cp id plus one (per cfg) */
-
-#include <xtensa/config/tie.h>
-
-
-
-
-/*----------------------------------------------------------------------
-                       INTERNAL I/D RAM/ROMs and XLMI
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_NUM_INSTROM              0       /* number of core instruction ROMs configured */
-#define XCHAL_NUM_INSTRAM              0       /* number of core instruction RAMs configured */
-#define XCHAL_NUM_DATAROM              0       /* number of core data ROMs configured */
-#define XCHAL_NUM_DATARAM              0       /* number of core data RAMs configured */
-#define XCHAL_NUM_XLMI                 0       /* number of core XLMI ports configured */
-#define  XCHAL_NUM_IROM                        XCHAL_NUM_INSTROM       /* (DEPRECATED) */
-#define  XCHAL_NUM_IRAM                        XCHAL_NUM_INSTRAM       /* (DEPRECATED) */
-#define  XCHAL_NUM_DROM                        XCHAL_NUM_DATAROM       /* (DEPRECATED) */
-#define  XCHAL_NUM_DRAM                        XCHAL_NUM_DATARAM       /* (DEPRECATED) */
-
-
-
-/*----------------------------------------------------------------------
-                               CACHE
-  ----------------------------------------------------------------------*/
-
-/*  Size of the cache lines in log2(bytes):  */
-#define XCHAL_ICACHE_LINEWIDTH         4
-#define XCHAL_DCACHE_LINEWIDTH         4
-/*  Size of the cache lines in bytes:  */
-#define XCHAL_ICACHE_LINESIZE          16
-#define XCHAL_DCACHE_LINESIZE          16
-/*  Max for both I-cache and D-cache (used for general alignment):  */
-#define XCHAL_CACHE_LINEWIDTH_MAX      4
-#define XCHAL_CACHE_LINESIZE_MAX       16
-
-/*  Number of cache sets in log2(lines per way):  */
-#define XCHAL_ICACHE_SETWIDTH          8
-#define XCHAL_DCACHE_SETWIDTH          8
-/*  Max for both I-cache and D-cache (used for general cache-coherency page alignment):  */
-#define XCHAL_CACHE_SETWIDTH_MAX       8
-#define XCHAL_CACHE_SETSIZE_MAX                256
-
-/*  Cache set associativity (number of ways):  */
-#define XCHAL_ICACHE_WAYS              2
-#define XCHAL_DCACHE_WAYS              2
-
-/*  Size of the caches in bytes (ways * 2^(linewidth + setwidth)):  */
-#define XCHAL_ICACHE_SIZE              8192
-#define XCHAL_DCACHE_SIZE              8192
-
-/*  Cache features:  */
-#define XCHAL_DCACHE_IS_WRITEBACK      0
-/*  Whether cache locking feature is available:  */
-#define XCHAL_ICACHE_LINE_LOCKABLE     0
-#define XCHAL_DCACHE_LINE_LOCKABLE     0
-
-/*  Number of (encoded) cache attribute bits:  */
-#define XCHAL_CA_BITS                  4       /* number of bits needed to hold cache attribute encoding */
-/*  (The number of access mode bits (decoded cache attribute bits) is defined by the architecture; see xtensa/hal.h?)  */
-
-
-/*  Cache Attribute encodings -- lists of access modes for each cache attribute:  */
-#define XCHAL_FCA_LIST         XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_BYPASS        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_BYPASS        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_CACHED        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_CACHED        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_CACHED        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_CACHED        XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_FAM_EXCEPTION
-#define XCHAL_LCA_LIST         XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_BYPASSG       XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_BYPASSG       XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_CACHED        XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_CACHED        XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_NACACHED      XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_NACACHED      XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_ISOLATE       XCHAL_SEP \
-                               XTHAL_LAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_LAM_CACHED
-#define XCHAL_SCA_LIST         XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_BYPASS        XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_WRITETHRU     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_WRITETHRU     XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_ISOLATE       XCHAL_SEP \
-                               XTHAL_SAM_EXCEPTION     XCHAL_SEP \
-                               XTHAL_SAM_WRITETHRU
-
-/*  Test:
-       read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
-       read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
-       all:       0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
-       fault:     0 + 2 + 4 + 6 + 8 + 10 + 12 + 14
-       r/w/x cached:
-       r/w/x dcached:
-       I-bypass:  1 + 3
-
-       load guard bit set: 1 + 3
-       load guard bit clr: 0 + 2 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
-       hit-cache r/w/x: 7 + 11
-
-       fams: 5
-       fams: 0 / 6 / 18 / 1 / 2
-       fams: Bypass / Isolate / Cached / Exception / NACached
-
-        MMU okay:  yes
-*/
-
-
-/*----------------------------------------------------------------------
-                               MMU
-  ----------------------------------------------------------------------*/
-
-/*
- *  General notes on MMU parameters.
- *
- *  Terminology:
- *     ASID = address-space ID (acts as an "extension" of virtual addresses)
- *     VPN  = virtual page number
- *     PPN  = physical page number
- *     CA   = encoded cache attribute (access modes)
- *     TLB  = translation look-aside buffer (term is stretched somewhat here)
- *     I    = instruction (fetch accesses)
- *     D    = data (load and store accesses)
- *     way  = each TLB (ITLB and DTLB) consists of a number of "ways"
- *             that simultaneously match the virtual address of an access;
- *             a TLB successfully translates a virtual address if exactly
- *             one way matches the vaddr; if none match, it is a miss;
- *             if multiple match, one gets a "multihit" exception;
- *             each way can be independently configured in terms of number of
- *             entries, page sizes, which fields are writable or constant, etc.
- *     set  = group of contiguous ways with exactly identical parameters
- *     ARF  = auto-refill; hardware services a 1st-level miss by loading a PTE
- *             from the page table and storing it in one of the auto-refill ways;
- *             if this PTE load also misses, a miss exception is posted for s/w.
- *     min-wired = a "min-wired" way can be used to map a single (minimum-sized)
- *             page arbitrarily under program control; it has a single entry,
- *             is non-auto-refill (some other way(s) must be auto-refill),
- *             all its fields (VPN, PPN, ASID, CA) are all writable, and it
- *             supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current
- *             restriction is that this be the only page size it supports).
- *
- *  TLB way entries are virtually indexed.
- *  TLB ways that support multiple page sizes:
- *     - must have all writable VPN and PPN fields;
- *     - can only use one page size at any given time (eg. setup at startup),
- *       selected by the respective ITLBCFG or DTLBCFG special register,
- *       whose bits n*4+3 .. n*4 index the list of page sizes for way n
- *       (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n);
- *       this list may be sparse for auto-refill ways because auto-refill
- *       ways have independent lists of supported page sizes sharing a
- *       common encoding with PTE entries; the encoding is the index into
- *       this list; unsupported sizes for a given way are zero in the list;
- *       selecting unsupported sizes results in undefined hardware behaviour;
- *     - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition).
- */
-
-#define XCHAL_HAVE_CACHEATTR           0       /* 1 if CACHEATTR register present, 0 if TLBs present instead */
-#define XCHAL_HAVE_TLBS                        1       /* 1 if TLBs present, 0 if CACHEATTR present instead */
-#define XCHAL_HAVE_MMU                 XCHAL_HAVE_TLBS /* (DEPRECATED; use XCHAL_HAVE_TLBS instead; will be removed in future release) */
-#define XCHAL_HAVE_SPANNING_WAY                0       /* 1 if single way maps entire virtual address space in I+D */
-#define XCHAL_HAVE_IDENTITY_MAP                0       /* 1 if virtual addr == physical addr always, 0 otherwise */
-#define XCHAL_HAVE_MIMIC_CACHEATTR     0       /* 1 if have MMU that mimics a CACHEATTR config (CaMMU) */
-#define XCHAL_HAVE_XLT_CACHEATTR       0       /* 1 if have MMU that mimics a CACHEATTR config, but with translation (CaXltMMU) */
-
-#define XCHAL_MMU_ASID_BITS            8       /* number of bits in ASIDs (address space IDs) */
-#define XCHAL_MMU_ASID_INVALID         0       /* ASID value indicating invalid address space */
-#define XCHAL_MMU_ASID_KERNEL          1       /* ASID value indicating kernel (ring 0) address space */
-#define XCHAL_MMU_RINGS                        4       /* number of rings supported (1..4) */
-#define XCHAL_MMU_RING_BITS            2       /* number of bits needed to hold ring number */
-#define XCHAL_MMU_SR_BITS              0       /* number of size-restriction bits supported */
-#define XCHAL_MMU_CA_BITS              4       /* number of bits needed to hold cache attribute encoding */
-#define XCHAL_MMU_MAX_PTE_PAGE_SIZE    12      /* max page size in a PTE structure (log2) */
-#define XCHAL_MMU_MIN_PTE_PAGE_SIZE    12      /* min page size in a PTE structure (log2) */
-
-
-/***  Instruction TLB:  ***/
-
-#define XCHAL_ITLB_WAY_BITS            3       /* number of bits holding the ways */
-#define XCHAL_ITLB_WAYS                        7       /* number of ways (n-way set-associative TLB) */
-#define XCHAL_ITLB_ARF_WAYS            4       /* number of auto-refill ways */
-#define XCHAL_ITLB_SETS                        4       /* number of sets (groups of ways with identical settings) */
-
-/*  Way set to which each way belongs:  */
-#define XCHAL_ITLB_WAY0_SET            0
-#define XCHAL_ITLB_WAY1_SET            0
-#define XCHAL_ITLB_WAY2_SET            0
-#define XCHAL_ITLB_WAY3_SET            0
-#define XCHAL_ITLB_WAY4_SET            1
-#define XCHAL_ITLB_WAY5_SET            2
-#define XCHAL_ITLB_WAY6_SET            3
-
-/*  Ways sets that are used by hardware auto-refill (ARF):  */
-#define XCHAL_ITLB_ARF_SETS            1       /* number of auto-refill sets */
-#define XCHAL_ITLB_ARF_SET0            0       /* index of n'th auto-refill set */
-
-/*  Way sets that are "min-wired" (see terminology comment above):  */
-#define XCHAL_ITLB_MINWIRED_SETS       0       /* number of "min-wired" sets */
-
-
-/*  ITLB way set 0 (group of ways 0 thru 3):  */
-#define XCHAL_ITLB_SET0_WAY                    0       /* index of first way in this way set */
-#define XCHAL_ITLB_SET0_WAYS                   4       /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET0_ENTRIES_LOG2           2       /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET0_ENTRIES                        4       /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET0_ARF                    1       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET0_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET0_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN                12      /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX                12      /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST       12      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET0_ASID_CONSTMASK         0       /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_VPN_CONSTMASK          0       /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_PPN_CONSTMASK          0       /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_CA_CONSTMASK           0       /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/*  ITLB way set 1 (group of ways 4 thru 4):  */
-#define XCHAL_ITLB_SET1_WAY                    4       /* index of first way in this way set */
-#define XCHAL_ITLB_SET1_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET1_ENTRIES_LOG2           2       /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET1_ENTRIES                        4       /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET1_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET1_PAGESIZES              4       /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET1_PAGESZ_BITS            2       /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN                20      /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX                26      /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST       20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26       /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET1_ASID_CONSTMASK         0       /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_VPN_CONSTMASK          0       /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_PPN_CONSTMASK          0       /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_CA_CONSTMASK           0       /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/*  ITLB way set 2 (group of ways 5 thru 5):  */
-#define XCHAL_ITLB_SET2_WAY                    5       /* index of first way in this way set */
-#define XCHAL_ITLB_SET2_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET2_ENTRIES_LOG2           1       /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET2_ENTRIES                        2       /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET2_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET2_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET2_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN                27      /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX                27      /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST       27      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET2_ASID_CONSTMASK         0xFF    /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_VPN_CONSTMASK          0xF0000000      /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_PPN_CONSTMASK          0xF8000000      /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_CA_CONSTMASK           0x0000000F      /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/*  Constant ASID values for each entry of ITLB way set 2 (because ASID_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET2_E0_ASID_CONST          0x01
-#define XCHAL_ITLB_SET2_E1_ASID_CONST          0x01
-/*  Constant VPN values for each entry of ITLB way set 2 (because VPN_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET2_E0_VPN_CONST           0xD0000000
-#define XCHAL_ITLB_SET2_E1_VPN_CONST           0xD8000000
-/*  Constant PPN values for each entry of ITLB way set 2 (because PPN_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET2_E0_PPN_CONST           0x00000000
-#define XCHAL_ITLB_SET2_E1_PPN_CONST           0x00000000
-/*  Constant CA values for each entry of ITLB way set 2 (because CA_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET2_E0_CA_CONST            0x07
-#define XCHAL_ITLB_SET2_E1_CA_CONST            0x03
-
-/*  ITLB way set 3 (group of ways 6 thru 6):  */
-#define XCHAL_ITLB_SET3_WAY                    6       /* index of first way in this way set */
-#define XCHAL_ITLB_SET3_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET3_ENTRIES_LOG2           1       /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET3_ENTRIES                        2       /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET3_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET3_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET3_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN                28      /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX                28      /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST       28      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET3_ASID_CONSTMASK         0xFF    /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_VPN_CONSTMASK          0xE0000000      /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_PPN_CONSTMASK          0xF0000000      /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_CA_CONSTMASK           0x0000000F      /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/*  Constant ASID values for each entry of ITLB way set 3 (because ASID_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET3_E0_ASID_CONST          0x01
-#define XCHAL_ITLB_SET3_E1_ASID_CONST          0x01
-/*  Constant VPN values for each entry of ITLB way set 3 (because VPN_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET3_E0_VPN_CONST           0xE0000000
-#define XCHAL_ITLB_SET3_E1_VPN_CONST           0xF0000000
-/*  Constant PPN values for each entry of ITLB way set 3 (because PPN_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET3_E0_PPN_CONST           0xF0000000
-#define XCHAL_ITLB_SET3_E1_PPN_CONST           0xF0000000
-/*  Constant CA values for each entry of ITLB way set 3 (because CA_CONSTMASK is non-zero):  */
-#define XCHAL_ITLB_SET3_E0_CA_CONST            0x07
-#define XCHAL_ITLB_SET3_E1_CA_CONST            0x03
-
-/*  Indexing macros:  */
-#define _XCHAL_ITLB_SET(n,_what)       XCHAL_ITLB_SET ## n ## _what
-#define XCHAL_ITLB_SET(n,what)         _XCHAL_ITLB_SET(n, _ ## what )
-#define _XCHAL_ITLB_SET_E(n,i,_what)   XCHAL_ITLB_SET ## n ## _E ## i ## _what
-#define XCHAL_ITLB_SET_E(n,i,what)     _XCHAL_ITLB_SET_E(n,i, _ ## what )
-/*
- *  Example use:  XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES)
- *     to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
- */
-
-
-/***  Data TLB:  ***/
-
-#define XCHAL_DTLB_WAY_BITS            4       /* number of bits holding the ways */
-#define XCHAL_DTLB_WAYS                        10      /* number of ways (n-way set-associative TLB) */
-#define XCHAL_DTLB_ARF_WAYS            4       /* number of auto-refill ways */
-#define XCHAL_DTLB_SETS                        5       /* number of sets (groups of ways with identical settings) */
-
-/*  Way set to which each way belongs:  */
-#define XCHAL_DTLB_WAY0_SET            0
-#define XCHAL_DTLB_WAY1_SET            0
-#define XCHAL_DTLB_WAY2_SET            0
-#define XCHAL_DTLB_WAY3_SET            0
-#define XCHAL_DTLB_WAY4_SET            1
-#define XCHAL_DTLB_WAY5_SET            2
-#define XCHAL_DTLB_WAY6_SET            3
-#define XCHAL_DTLB_WAY7_SET            4
-#define XCHAL_DTLB_WAY8_SET            4
-#define XCHAL_DTLB_WAY9_SET            4
-
-/*  Ways sets that are used by hardware auto-refill (ARF):  */
-#define XCHAL_DTLB_ARF_SETS            1       /* number of auto-refill sets */
-#define XCHAL_DTLB_ARF_SET0            0       /* index of n'th auto-refill set */
-
-/*  Way sets that are "min-wired" (see terminology comment above):  */
-#define XCHAL_DTLB_MINWIRED_SETS       1       /* number of "min-wired" sets */
-#define XCHAL_DTLB_MINWIRED_SET0       4       /* index of n'th "min-wired" set */
-
-
-/*  DTLB way set 0 (group of ways 0 thru 3):  */
-#define XCHAL_DTLB_SET0_WAY                    0       /* index of first way in this way set */
-#define XCHAL_DTLB_SET0_WAYS                   4       /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET0_ENTRIES_LOG2           2       /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET0_ENTRIES                        4       /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET0_ARF                    1       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET0_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET0_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN                12      /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX                12      /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST       12      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET0_ASID_CONSTMASK         0       /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_VPN_CONSTMASK          0       /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_PPN_CONSTMASK          0       /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_CA_CONSTMASK           0       /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/*  DTLB way set 1 (group of ways 4 thru 4):  */
-#define XCHAL_DTLB_SET1_WAY                    4       /* index of first way in this way set */
-#define XCHAL_DTLB_SET1_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET1_ENTRIES_LOG2           2       /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET1_ENTRIES                        4       /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET1_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET1_PAGESIZES              4       /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET1_PAGESZ_BITS            2       /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN                20      /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX                26      /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST       20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26       /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET1_ASID_CONSTMASK         0       /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_VPN_CONSTMASK          0       /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_PPN_CONSTMASK          0       /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_CA_CONSTMASK           0       /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/*  DTLB way set 2 (group of ways 5 thru 5):  */
-#define XCHAL_DTLB_SET2_WAY                    5       /* index of first way in this way set */
-#define XCHAL_DTLB_SET2_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET2_ENTRIES_LOG2           1       /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET2_ENTRIES                        2       /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET2_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET2_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET2_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN                27      /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX                27      /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST       27      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET2_ASID_CONSTMASK         0xFF    /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_VPN_CONSTMASK          0xF0000000      /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_PPN_CONSTMASK          0xF8000000      /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_CA_CONSTMASK           0x0000000F      /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/*  Constant ASID values for each entry of DTLB way set 2 (because ASID_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET2_E0_ASID_CONST          0x01
-#define XCHAL_DTLB_SET2_E1_ASID_CONST          0x01
-/*  Constant VPN values for each entry of DTLB way set 2 (because VPN_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET2_E0_VPN_CONST           0xD0000000
-#define XCHAL_DTLB_SET2_E1_VPN_CONST           0xD8000000
-/*  Constant PPN values for each entry of DTLB way set 2 (because PPN_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET2_E0_PPN_CONST           0x00000000
-#define XCHAL_DTLB_SET2_E1_PPN_CONST           0x00000000
-/*  Constant CA values for each entry of DTLB way set 2 (because CA_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET2_E0_CA_CONST            0x07
-#define XCHAL_DTLB_SET2_E1_CA_CONST            0x03
-
-/*  DTLB way set 3 (group of ways 6 thru 6):  */
-#define XCHAL_DTLB_SET3_WAY                    6       /* index of first way in this way set */
-#define XCHAL_DTLB_SET3_WAYS                   1       /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET3_ENTRIES_LOG2           1       /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET3_ENTRIES                        2       /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET3_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET3_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET3_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN                28      /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX                28      /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST       28      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET3_ASID_CONSTMASK         0xFF    /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_VPN_CONSTMASK          0xE0000000      /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_PPN_CONSTMASK          0xF0000000      /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_CA_CONSTMASK           0x0000000F      /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/*  Constant ASID values for each entry of DTLB way set 3 (because ASID_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET3_E0_ASID_CONST          0x01
-#define XCHAL_DTLB_SET3_E1_ASID_CONST          0x01
-/*  Constant VPN values for each entry of DTLB way set 3 (because VPN_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET3_E0_VPN_CONST           0xE0000000
-#define XCHAL_DTLB_SET3_E1_VPN_CONST           0xF0000000
-/*  Constant PPN values for each entry of DTLB way set 3 (because PPN_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET3_E0_PPN_CONST           0xF0000000
-#define XCHAL_DTLB_SET3_E1_PPN_CONST           0xF0000000
-/*  Constant CA values for each entry of DTLB way set 3 (because CA_CONSTMASK is non-zero):  */
-#define XCHAL_DTLB_SET3_E0_CA_CONST            0x07
-#define XCHAL_DTLB_SET3_E1_CA_CONST            0x03
-
-/*  DTLB way set 4 (group of ways 7 thru 9):  */
-#define XCHAL_DTLB_SET4_WAY                    7       /* index of first way in this way set */
-#define XCHAL_DTLB_SET4_WAYS                   3       /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET4_ENTRIES_LOG2           0       /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET4_ENTRIES                        1       /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET4_ARF                    0       /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET4_PAGESIZES              1       /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET4_PAGESZ_BITS            0       /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN                12      /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX                12      /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST       12      /* list of log2(page size)s, separated by XCHAL_SEP;
-                                                          2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET4_ASID_CONSTMASK         0       /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_VPN_CONSTMASK          0       /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_PPN_CONSTMASK          0       /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_CA_CONSTMASK           0       /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_ASID_RESET             0       /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_VPN_RESET              0       /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_PPN_RESET              0       /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_CA_RESET               0       /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/*  Indexing macros:  */
-#define _XCHAL_DTLB_SET(n,_what)       XCHAL_DTLB_SET ## n ## _what
-#define XCHAL_DTLB_SET(n,what)         _XCHAL_DTLB_SET(n, _ ## what )
-#define _XCHAL_DTLB_SET_E(n,i,_what)   XCHAL_DTLB_SET ## n ## _E ## i ## _what
-#define XCHAL_DTLB_SET_E(n,i,what)     _XCHAL_DTLB_SET_E(n,i, _ ## what )
-/*
- *  Example use:  XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES)
- *     to get the value of XCHAL_DTLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
- */
-
-
-/*
- *  Determine whether we have a full MMU (with Page Table and Protection)
- *  usable for an MMU-based OS:
- */
-#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2
-# define XCHAL_HAVE_PTP_MMU            1       /* have full MMU (with page table [autorefill] and protection) */
-#else
-# define XCHAL_HAVE_PTP_MMU            0       /* don't have full MMU */
-#endif
-
-/*
- *  For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings:
- */
-#if XCHAL_HAVE_PTP_MMU
-#define XCHAL_KSEG_CACHED_VADDR                0xD0000000      /* virt.addr of kernel RAM cached static map */
-#define XCHAL_KSEG_CACHED_PADDR                0x00000000      /* phys.addr of kseg_cached */
-#define XCHAL_KSEG_CACHED_SIZE         0x08000000      /* size in bytes of kseg_cached (assumed power of 2!!!) */
-#define XCHAL_KSEG_BYPASS_VADDR                0xD8000000      /* virt.addr of kernel RAM bypass (uncached) static map */
-#define XCHAL_KSEG_BYPASS_PADDR                0x00000000      /* phys.addr of kseg_bypass */
-#define XCHAL_KSEG_BYPASS_SIZE         0x08000000      /* size in bytes of kseg_bypass (assumed power of 2!!!) */
-
-#define XCHAL_KIO_CACHED_VADDR         0xE0000000      /* virt.addr of kernel I/O cached static map */
-#define XCHAL_KIO_CACHED_PADDR         0xF0000000      /* phys.addr of kio_cached */
-#define XCHAL_KIO_CACHED_SIZE          0x10000000      /* size in bytes of kio_cached (assumed power of 2!!!) */
-#define XCHAL_KIO_BYPASS_VADDR         0xF0000000      /* virt.addr of kernel I/O bypass (uncached) static map */
-#define XCHAL_KIO_BYPASS_PADDR         0xF0000000      /* phys.addr of kio_bypass */
-#define XCHAL_KIO_BYPASS_SIZE          0x10000000      /* size in bytes of kio_bypass (assumed power of 2!!!) */
-
-#define XCHAL_SEG_MAPPABLE_VADDR       0x00000000      /* start of largest non-static-mapped virtual addr area */
-#define XCHAL_SEG_MAPPABLE_SIZE                0xD0000000      /* size in bytes of  "  */
-/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size.  */
-#endif
-
-
-/*----------------------------------------------------------------------
-                               MISC
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_NUM_WRITEBUFFER_ENTRIES  4       /* number of write buffer entries */
-
-#define XCHAL_CORE_ID                  "linux_be"      /* configuration's alphanumeric core identifier
-                                                          (CoreID) set in the Xtensa Processor Generator */
-
-#define XCHAL_BUILD_UNIQUE_ID          0x00003256      /* software build-unique ID (22-bit) */
-
-/*  These definitions describe the hardware targeted by this software:  */
-#define XCHAL_HW_CONFIGID0             0xC103D1FF      /* config ID reg 0 value (upper 32 of 64 bits) */
-#define XCHAL_HW_CONFIGID1             0x00803256      /* config ID reg 1 value (lower 32 of 64 bits) */
-#define XCHAL_CONFIGID0                        XCHAL_HW_CONFIGID0      /* for backward compatibility only -- don't use! */
-#define XCHAL_CONFIGID1                        XCHAL_HW_CONFIGID1      /* for backward compatibility only -- don't use! */
-#define XCHAL_HW_RELEASE_MAJOR         1050    /* major release of targeted hardware */
-#define XCHAL_HW_RELEASE_MINOR         1       /* minor release of targeted hardware */
-#define XCHAL_HW_RELEASE_NAME          "T1050.1"       /* full release name of targeted hardware */
-#define XTHAL_HW_REL_T1050     1
-#define XTHAL_HW_REL_T1050_1   1
-#define XCHAL_HW_CONFIGID_RELIABLE     1
-
-
-/*
- *  Miscellaneous special register fields:
- */
-
-
-/*  DBREAKC (special register number 160):  */
-#define XCHAL_DBREAKC_VALIDMASK        0xC000003F      /* bits of DBREAKC that are defined */
-/*  MASK field:  */
-#define XCHAL_DBREAKC_MASK_BITS        6               /* number of bits in MASK field */
-#define XCHAL_DBREAKC_MASK_NUM         64              /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_MASK_SHIFT       0               /* position of MASK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_MASK_MASK        0x0000003F      /* mask of bits in MASK field of DBREAKC */
-/*  LOADBREAK field:  */
-#define XCHAL_DBREAKC_LOADBREAK_BITS   1               /* number of bits in LOADBREAK field */
-#define XCHAL_DBREAKC_LOADBREAK_NUM    2               /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_LOADBREAK_SHIFT  30              /* position of LOADBREAK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_LOADBREAK_MASK   0x40000000      /* mask of bits in LOADBREAK field of DBREAKC */
-/*  STOREBREAK field:  */
-#define XCHAL_DBREAKC_STOREBREAK_BITS  1               /* number of bits in STOREBREAK field */
-#define XCHAL_DBREAKC_STOREBREAK_NUM   2               /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31              /* position of STOREBREAK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_STOREBREAK_MASK  0x80000000      /* mask of bits in STOREBREAK field of DBREAKC */
-
-/*  PS (special register number 230):  */
-#define XCHAL_PS_VALIDMASK     0x00070FFF      /* bits of PS that are defined */
-/*  INTLEVEL field:  */
-#define XCHAL_PS_INTLEVEL_BITS         4               /* number of bits in INTLEVEL field */
-#define XCHAL_PS_INTLEVEL_NUM          16              /* max number of possible causes (2^bits) */
-#define XCHAL_PS_INTLEVEL_SHIFT        0               /* position of INTLEVEL bits in PS, starting from lsbit */
-#define XCHAL_PS_INTLEVEL_MASK         0x0000000F      /* mask of bits in INTLEVEL field of PS */
-/*  EXCM field:  */
-#define XCHAL_PS_EXCM_BITS     1               /* number of bits in EXCM field */
-#define XCHAL_PS_EXCM_NUM      2               /* max number of possible causes (2^bits) */
-#define XCHAL_PS_EXCM_SHIFT    4               /* position of EXCM bits in PS, starting from lsbit */
-#define XCHAL_PS_EXCM_MASK     0x00000010      /* mask of bits in EXCM field of PS */
-/*  PROGSTACK field:  */
-#define XCHAL_PS_PROGSTACK_BITS        1               /* number of bits in PROGSTACK field */
-#define XCHAL_PS_PROGSTACK_NUM         2               /* max number of possible causes (2^bits) */
-#define XCHAL_PS_PROGSTACK_SHIFT       5               /* position of PROGSTACK bits in PS, starting from lsbit */
-#define XCHAL_PS_PROGSTACK_MASK        0x00000020      /* mask of bits in PROGSTACK field of PS */
-/*  RING field:  */
-#define XCHAL_PS_RING_BITS     2               /* number of bits in RING field */
-#define XCHAL_PS_RING_NUM      4               /* max number of possible causes (2^bits) */
-#define XCHAL_PS_RING_SHIFT    6               /* position of RING bits in PS, starting from lsbit */
-#define XCHAL_PS_RING_MASK     0x000000C0      /* mask of bits in RING field of PS */
-/*  OWB field:  */
-#define XCHAL_PS_OWB_BITS      4               /* number of bits in OWB field */
-#define XCHAL_PS_OWB_NUM       16              /* max number of possible causes (2^bits) */
-#define XCHAL_PS_OWB_SHIFT     8               /* position of OWB bits in PS, starting from lsbit */
-#define XCHAL_PS_OWB_MASK      0x00000F00      /* mask of bits in OWB field of PS */
-/*  CALLINC field:  */
-#define XCHAL_PS_CALLINC_BITS  2               /* number of bits in CALLINC field */
-#define XCHAL_PS_CALLINC_NUM   4               /* max number of possible causes (2^bits) */
-#define XCHAL_PS_CALLINC_SHIFT 16              /* position of CALLINC bits in PS, starting from lsbit */
-#define XCHAL_PS_CALLINC_MASK  0x00030000      /* mask of bits in CALLINC field of PS */
-/*  WOE field:  */
-#define XCHAL_PS_WOE_BITS      1               /* number of bits in WOE field */
-#define XCHAL_PS_WOE_NUM       2               /* max number of possible causes (2^bits) */
-#define XCHAL_PS_WOE_SHIFT     18              /* position of WOE bits in PS, starting from lsbit */
-#define XCHAL_PS_WOE_MASK      0x00040000      /* mask of bits in WOE field of PS */
-
-/*  EXCCAUSE (special register number 232):  */
-#define XCHAL_EXCCAUSE_VALIDMASK       0x0000003F      /* bits of EXCCAUSE that are defined */
-/*  EXCCAUSE field:  */
-#define XCHAL_EXCCAUSE_BITS            6               /* number of bits in EXCCAUSE register */
-#define XCHAL_EXCCAUSE_NUM             64              /* max number of possible causes (2^bits) */
-#define XCHAL_EXCCAUSE_SHIFT           0               /* position of EXCCAUSE bits in register, starting from lsbit */
-#define XCHAL_EXCCAUSE_MASK            0x0000003F      /* mask of bits in EXCCAUSE register */
-
-/*  DEBUGCAUSE (special register number 233):  */
-#define XCHAL_DEBUGCAUSE_VALIDMASK     0x0000003F      /* bits of DEBUGCAUSE that are defined */
-/*  ICOUNT field:  */
-#define XCHAL_DEBUGCAUSE_ICOUNT_BITS   1               /* number of bits in ICOUNT field */
-#define XCHAL_DEBUGCAUSE_ICOUNT_NUM    2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT  0               /* position of ICOUNT bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_ICOUNT_MASK   0x00000001      /* mask of bits in ICOUNT field of DEBUGCAUSE */
-/*  IBREAK field:  */
-#define XCHAL_DEBUGCAUSE_IBREAK_BITS   1               /* number of bits in IBREAK field */
-#define XCHAL_DEBUGCAUSE_IBREAK_NUM    2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT  1               /* position of IBREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_IBREAK_MASK   0x00000002      /* mask of bits in IBREAK field of DEBUGCAUSE */
-/*  DBREAK field:  */
-#define XCHAL_DEBUGCAUSE_DBREAK_BITS   1               /* number of bits in DBREAK field */
-#define XCHAL_DEBUGCAUSE_DBREAK_NUM    2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT  2               /* position of DBREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_DBREAK_MASK   0x00000004      /* mask of bits in DBREAK field of DEBUGCAUSE */
-/*  BREAK field:  */
-#define XCHAL_DEBUGCAUSE_BREAK_BITS    1               /* number of bits in BREAK field */
-#define XCHAL_DEBUGCAUSE_BREAK_NUM     2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_BREAK_SHIFT   3               /* position of BREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_BREAK_MASK    0x00000008      /* mask of bits in BREAK field of DEBUGCAUSE */
-/*  BREAKN field:  */
-#define XCHAL_DEBUGCAUSE_BREAKN_BITS   1               /* number of bits in BREAKN field */
-#define XCHAL_DEBUGCAUSE_BREAKN_NUM    2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT  4               /* position of BREAKN bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_BREAKN_MASK   0x00000010      /* mask of bits in BREAKN field of DEBUGCAUSE */
-/*  DEBUGINT field:  */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS         1               /* number of bits in DEBUGINT field */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM          2               /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT        5               /* position of DEBUGINT bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK         0x00000020      /* mask of bits in DEBUGINT field of DEBUGCAUSE */
-
-
-
-/*----------------------------------------------------------------------
-                               ISA
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_DENSITY             1       /* 1 if density option configured, 0 otherwise */
-#define XCHAL_HAVE_LOOPS               1       /* 1 if zero-overhead loops option configured, 0 otherwise */
-/*  Misc instructions:  */
-#define XCHAL_HAVE_NSA                 0       /* 1 if NSA/NSAU instructions option configured, 0 otherwise */
-#define XCHAL_HAVE_MINMAX              0       /* 1 if MIN/MAX instructions option configured, 0 otherwise */
-#define XCHAL_HAVE_SEXT                        0       /* 1 if sign-extend instruction option configured, 0 otherwise */
-#define XCHAL_HAVE_CLAMPS              0       /* 1 if CLAMPS instruction option configured, 0 otherwise */
-#define XCHAL_HAVE_MAC16               0       /* 1 if MAC16 option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL16               0       /* 1 if 16-bit integer multiply option configured, 0 otherwise */
-/*#define XCHAL_HAVE_POPC              0*/     /* 1 if CRC instruction option configured, 0 otherwise */
-/*#define XCHAL_HAVE_CRC               0*/     /* 1 if POPC instruction option configured, 0 otherwise */
-
-#define XCHAL_HAVE_SPECULATION         0       /* 1 if speculation option configured, 0 otherwise */
-/*#define XCHAL_HAVE_MP_SYNC           0*/     /* 1 if multiprocessor sync. option configured, 0 otherwise */
-#define XCHAL_HAVE_PRID                        0       /* 1 if processor ID register configured, 0 otherwise */
-
-#define XCHAL_NUM_MISC_REGS            2       /* number of miscellaneous registers (0..4) */
-
-/*  These relate a bit more to TIE:  */
-#define XCHAL_HAVE_BOOLEANS            0       /* 1 if booleans option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32               0       /* 1 if 32-bit integer multiply option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32_HIGH          0       /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
-#define XCHAL_HAVE_FP                  0       /* 1 if floating point option configured, 0 otherwise */
-
-
-/*----------------------------------------------------------------------
-                               DERIVED
-  ----------------------------------------------------------------------*/
-
-#if XCHAL_HAVE_BE
-#define XCHAL_INST_ILLN                        0xD60F          /* 2-byte illegal instruction, msb-first */
-#define XCHAL_INST_ILLN_BYTE0          0xD6            /* 2-byte illegal instruction, 1st byte */
-#define XCHAL_INST_ILLN_BYTE1          0x0F            /* 2-byte illegal instruction, 2nd byte */
-#else
-#define XCHAL_INST_ILLN                        0xF06D          /* 2-byte illegal instruction, lsb-first */
-#define XCHAL_INST_ILLN_BYTE0          0x6D            /* 2-byte illegal instruction, 1st byte */
-#define XCHAL_INST_ILLN_BYTE1          0xF0            /* 2-byte illegal instruction, 2nd byte */
-#endif
-/*  Belongs in xtensa/hal.h:  */
-#define XTHAL_INST_ILL                 0x000000        /* 3-byte illegal instruction */
-
-
-/*
- *  Because information as to exactly which hardware release is targeted
- *  by a given software build is not always available, compile-time HAL
- *  Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE):
- */
-#ifndef XCHAL_HW_RELEASE_MAJOR
-# define XCHAL_HW_CONFIGID_RELIABLE    0
-#endif
-#if XCHAL_HW_CONFIGID_RELIABLE
-# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor)     (XTHAL_REL_LE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor)     (XTHAL_REL_GE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_AT(major,minor)              (XTHAL_REL_EQ( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_MAJOR_AT(major)              ((XCHAL_HW_RELEASE_MAJOR == (major)) ? 1 : 0)
-#else
-# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor)     ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \
-                                                       : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \
-                                                       : XTHAL_MAYBE )
-# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor)     ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \
-                                                       : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \
-                                                       : XTHAL_MAYBE )
-# define XCHAL_HW_RELEASE_AT(major,minor)              ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \
-                                                          ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE)
-# define XCHAL_HW_RELEASE_MAJOR_AT(major)              XCHAL_HW_RELEASE_AT(major,0)
-#endif
-
-/*
- *  Specific errata:
- */
-
-/*
- *  Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1;
- *  relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled):
- */
-#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \
-                                        (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \
-                                         || XCHAL_HW_RELEASE_AT(1050,0)))
-
-
-
-#endif /*XTENSA_CONFIG_CORE_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/defs.h b/include/asm-xtensa/xtensa/config-linux_be/defs.h
deleted file mode 100644 (file)
index f7c58b2..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Definitions for Xtensa instructions, types, and protos. */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- */
-
-/* Do not modify. This is automatically generated.*/
-
-#ifndef _XTENSA_BASE_HEADER
-#define _XTENSA_BASE_HEADER
-
-#ifdef __XTENSA__
-#if defined(__GNUC__) && !defined(__XCC__)
-
-#define L8UI_ASM(arr, ars, imm) { \
-  __asm__ volatile("l8ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L8UI(ars, imm) \
-({ \
-  unsigned char _arr; \
-  const unsigned char *_ars = ars; \
-  L8UI_ASM(_arr, _ars, imm); \
-  _arr; \
-})
-
-#define L16UI_ASM(arr, ars, imm) { \
-  __asm__ volatile("l16ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L16UI(ars, imm) \
-({ \
-  unsigned short _arr; \
-  const unsigned short *_ars = ars; \
-  L16UI_ASM(_arr, _ars, imm); \
-  _arr; \
-})
-
-#define L16SI_ASM(arr, ars, imm) {\
-  __asm__ volatile("l16si %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L16SI(ars, imm) \
-({ \
-  signed short _arr; \
-  const signed short *_ars = ars; \
-  L16SI_ASM(_arr, _ars, imm); \
-  _arr; \
-})
-
-#define L32I_ASM(arr, ars, imm) { \
-  __asm__ volatile("l32i %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L32I(ars, imm) \
-({ \
-  unsigned _arr; \
-  const unsigned *_ars = ars; \
-  L32I_ASM(_arr, _ars, imm); \
-  _arr; \
-})
-
-#define S8I_ASM(arr, ars, imm) {\
-  __asm__ volatile("s8i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S8I(arr, ars, imm) \
-({ \
-  signed char _arr = arr; \
-  const signed char *_ars = ars; \
-  S8I_ASM(_arr, _ars, imm); \
-})
-
-#define S16I_ASM(arr, ars, imm) {\
-  __asm__ volatile("s16i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S16I(arr, ars, imm) \
-({ \
-  signed short _arr = arr; \
-  const signed short *_ars = ars; \
-  S16I_ASM(_arr, _ars, imm); \
-})
-
-#define S32I_ASM(arr, ars, imm) { \
-  __asm__ volatile("s32i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S32I(arr, ars, imm) \
-({ \
-  signed int _arr = arr; \
-  const signed int *_ars = ars; \
-  S32I_ASM(_arr, _ars, imm); \
-})
-
-#define ADDI_ASM(art, ars, imm) {\
-   __asm__ ("addi %0, %1, %2" : "=a" (art) : "a" (ars), "i" (imm)); \
-}
-
-#define XT_ADDI(ars, imm) \
-({ \
-   unsigned _art; \
-   unsigned _ars = ars; \
-   ADDI_ASM(_art, _ars, imm); \
-   _art; \
-})
-
-#define ABS_ASM(arr, art) {\
-   __asm__ ("abs %0, %1" : "=a" (arr) : "a" (art)); \
-}
-
-#define XT_ABS(art) \
-({ \
-   unsigned _arr; \
-   signed _art = art; \
-   ABS_ASM(_arr, _art); \
-   _arr; \
-})
-
-/* Note: In the following macros that reference SAR, the magic "state"
-   register is used to capture the dependency on SAR.  This is because
-   SAR is a 5-bit register and thus there are no C types that can be
-   used to represent it.  It doesn't appear that the SAR register is
-   even relevant to GCC, but it is marked as "clobbered" just in
-   case.  */
-
-#define SRC_ASM(arr, ars, art) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("src %0, %1, %2" \
-           : "=a" (arr) : "a" (ars), "a" (art), "t" (_xt_sar)); \
-}
-
-#define XT_SRC(ars, art) \
-({ \
-   unsigned _arr; \
-   unsigned _ars = ars; \
-   unsigned _art = art; \
-   SRC_ASM(_arr, _ars, _art); \
-   _arr; \
-})
-
-#define SSR_ASM(ars) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("ssr %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSR(ars) \
-({ \
-   unsigned _ars = ars; \
-   SSR_ASM(_ars); \
-})
-
-#define SSL_ASM(ars) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("ssl %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSL(ars) \
-({ \
-   unsigned _ars = ars; \
-   SSL_ASM(_ars); \
-})
-
-#define SSA8B_ASM(ars) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("ssa8b %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSA8B(ars) \
-({ \
-   unsigned _ars = ars; \
-   SSA8B_ASM(_ars); \
-})
-
-#define SSA8L_ASM(ars) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("ssa8l %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSA8L(ars) \
-({ \
-   unsigned _ars = ars; \
-   SSA8L_ASM(_ars); \
-})
-
-#define SSAI_ASM(imm) {\
-   register int _xt_sar __asm__ ("state"); \
-   __asm__ ("ssai %1" : "=t" (_xt_sar) : "i" (imm) : "sar"); \
-}
-
-#define XT_SSAI(imm) \
-({ \
-   SSAI_ASM(imm); \
-})
-
-
-
-
-
-
-
-
-#endif /* __GNUC__ && !__XCC__ */
-
-#ifdef __XCC__
-
-/* Core load/store instructions */
-extern unsigned char _TIE_L8UI(const unsigned char * ars, immediate imm);
-extern unsigned short _TIE_L16UI(const unsigned short * ars, immediate imm);
-extern signed short _TIE_L16SI(const signed short * ars, immediate imm);
-extern unsigned _TIE_L32I(const unsigned * ars, immediate imm);
-extern void _TIE_S8I(unsigned char arr, unsigned char * ars, immediate imm);
-extern void _TIE_S16I(unsigned short arr, unsigned short * ars, immediate imm);
-extern void _TIE_S32I(unsigned arr, unsigned * ars, immediate imm);
-
-#define XT_L8UI  _TIE_L8UI
-#define XT_L16UI _TIE_L16UI
-#define XT_L16SI _TIE_L16SI
-#define XT_L32I  _TIE_L32I
-#define XT_S8I   _TIE_S8I
-#define XT_S16I  _TIE_S16I
-#define XT_S32I  _TIE_S32I
-
-/* Add-immediate instruction */
-extern unsigned _TIE_ADDI(unsigned ars, immediate imm);
-#define XT_ADDI  _TIE_ADDI
-
-/* Absolute value instruction */
-extern unsigned _TIE_ABS(int art);
-#define XT_ABS _TIE_ABS
-
-/* funnel shift instructions */
-extern unsigned _TIE_SRC(unsigned ars, unsigned art);
-#define XT_SRC _TIE_SRC
-extern void _TIE_SSR(unsigned ars);
-#define XT_SSR _TIE_SSR
-extern void _TIE_SSL(unsigned ars);
-#define XT_SSL _TIE_SSL
-extern void _TIE_SSA8B(unsigned ars);
-#define XT_SSA8B _TIE_SSA8B
-extern void _TIE_SSA8L(unsigned ars);
-#define XT_SSA8L _TIE_SSA8L
-extern void _TIE_SSAI(immediate imm);
-#define XT_SSAI _TIE_SSAI
-
-
-#endif /* __XCC__ */
-
-#endif /* __XTENSA__ */
-#endif /* !_XTENSA_BASE_HEADER */
diff --git a/include/asm-xtensa/xtensa/config-linux_be/specreg.h b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
deleted file mode 100644 (file)
index fa4106a..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Xtensa Special Register symbolic names
- */
-
-/* $Id: specreg.h,v 1.2 2003/03/07 19:15:18 joetaylor Exp $ */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- */
-
-#ifndef XTENSA_SPECREG_H
-#define XTENSA_SPECREG_H
-
-/*  Include these special register bitfield definitions, for historical reasons:  */
-#include <xtensa/corebits.h>
-
-
-/*  Special registers:  */
-#define LBEG           0
-#define LEND           1
-#define LCOUNT         2
-#define SAR            3
-#define WINDOWBASE     72
-#define WINDOWSTART    73
-#define PTEVADDR       83
-#define RASID          90
-#define ITLBCFG                91
-#define DTLBCFG                92
-#define IBREAKENABLE   96
-#define DDR            104
-#define IBREAKA_0      128
-#define IBREAKA_1      129
-#define DBREAKA_0      144
-#define DBREAKA_1      145
-#define DBREAKC_0      160
-#define DBREAKC_1      161
-#define EPC_1          177
-#define EPC_2          178
-#define EPC_3          179
-#define EPC_4          180
-#define DEPC           192
-#define EPS_2          194
-#define EPS_3          195
-#define EPS_4          196
-#define EXCSAVE_1      209
-#define EXCSAVE_2      210
-#define EXCSAVE_3      211
-#define EXCSAVE_4      212
-#define INTERRUPT      226
-#define INTENABLE      228
-#define PS             230
-#define EXCCAUSE       232
-#define DEBUGCAUSE     233
-#define CCOUNT         234
-#define ICOUNT         236
-#define ICOUNTLEVEL    237
-#define EXCVADDR       238
-#define CCOMPARE_0     240
-#define CCOMPARE_1     241
-#define CCOMPARE_2     242
-#define MISC_REG_0     244
-#define MISC_REG_1     245
-
-/*  Special cases (bases of special register series):  */
-#define IBREAKA                128
-#define DBREAKA                144
-#define DBREAKC                160
-#define EPC            176
-#define EPS            192
-#define EXCSAVE                208
-#define CCOMPARE       240
-
-/*  Special names for read-only and write-only interrupt registers:  */
-#define INTREAD                226
-#define INTSET         226
-#define INTCLEAR       227
-
-#endif /* XTENSA_SPECREG_H */
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/system.h b/include/asm-xtensa/xtensa/config-linux_be/system.h
deleted file mode 100644 (file)
index cf9d4d3..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration
- *
- *  NOTE: The location and contents of this file are highly subject to change.
- *
- *  Source for configuration-independent binaries (which link in a
- *  configuration-specific HAL library) must NEVER include this file.
- *  The HAL itself has historically included this file in some instances,
- *  but this is not appropriate either, because the HAL is meant to be
- *  core-specific but system independent.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- */
-
-
-#ifndef XTENSA_CONFIG_SYSTEM_H
-#define XTENSA_CONFIG_SYSTEM_H
-
-/*#include <xtensa/hal.h>*/
-
-
-
-/*----------------------------------------------------------------------
-                               DEVICE ADDRESSES
-  ----------------------------------------------------------------------*/
-
-/*
- *  Strange place to find these, but the configuration GUI
- *  allows moving these around to account for various core
- *  configurations.  Specific boards (and their BSP software)
- *  will have specific meanings for these components.
- */
-
-/*  I/O Block areas:  */
-#define XSHAL_IOBLOCK_CACHED_VADDR     0xE0000000
-#define XSHAL_IOBLOCK_CACHED_PADDR     0xF0000000
-#define XSHAL_IOBLOCK_CACHED_SIZE      0x0E000000
-
-#define XSHAL_IOBLOCK_BYPASS_VADDR     0xF0000000
-#define XSHAL_IOBLOCK_BYPASS_PADDR     0xF0000000
-#define XSHAL_IOBLOCK_BYPASS_SIZE      0x0E000000
-
-/*  System ROM:  */
-#define XSHAL_ROM_VADDR                0xEE000000
-#define XSHAL_ROM_PADDR                0xFE000000
-#define XSHAL_ROM_SIZE         0x00400000
-/*  Largest available area (free of vectors):  */
-#define XSHAL_ROM_AVAIL_VADDR  0xEE00052C
-#define XSHAL_ROM_AVAIL_VSIZE  0x003FFAD4
-
-/*  System RAM:  */
-#define XSHAL_RAM_VADDR                0xD0000000
-#define XSHAL_RAM_PADDR                0x00000000
-#define XSHAL_RAM_VSIZE                0x08000000
-#define XSHAL_RAM_PSIZE                0x10000000
-#define XSHAL_RAM_SIZE         XSHAL_RAM_PSIZE
-/*  Largest available area (free of vectors):  */
-#define XSHAL_RAM_AVAIL_VADDR  0xD0000370
-#define XSHAL_RAM_AVAIL_VSIZE  0x07FFFC90
-
-/*
- *  Shadow system RAM (same device as system RAM, at different address).
- *  (Emulation boards need this for the SONIC Ethernet driver
- *   when data caches are configured for writeback mode.)
- *  NOTE: on full MMU configs, this points to the BYPASS virtual address
- *  of system RAM, ie. is the same as XSHAL_RAM_* except that virtual
- *  addresses are viewed through the BYPASS static map rather than
- *  the CACHED static map.
- */
-#define XSHAL_RAM_BYPASS_VADDR         0xD8000000
-#define XSHAL_RAM_BYPASS_PADDR         0x00000000
-#define XSHAL_RAM_BYPASS_PSIZE         0x08000000
-
-/*  Alternate system RAM (different device than system RAM):  */
-#define XSHAL_ALTRAM_VADDR             0xCEE00000
-#define XSHAL_ALTRAM_PADDR             0xC0000000
-#define XSHAL_ALTRAM_SIZE              0x00200000
-
-
-/*----------------------------------------------------------------------
- *                     DEVICE-ADDRESS DEPENDENT...
- *
- *  Values written to CACHEATTR special register (or its equivalent)
- *  to enable and disable caches in various modes.
- *----------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------
-                       BACKWARD COMPATIBILITY ...
-  ----------------------------------------------------------------------*/
-
-/*
- *  NOTE:  the following two macros are DEPRECATED.  Use the latter
- *  board-specific macros instead, which are specially tuned for the
- *  particular target environments' memory maps.
- */
-#define XSHAL_CACHEATTR_BYPASS         XSHAL_XT2000_CACHEATTR_BYPASS   /* disable caches in bypass mode */
-#define XSHAL_CACHEATTR_DEFAULT                XSHAL_XT2000_CACHEATTR_DEFAULT  /* default setting to enable caches (no writeback!) */
-
-/*----------------------------------------------------------------------
-                       ISS (Instruction Set Simulator) SPECIFIC ...
-  ----------------------------------------------------------------------*/
-
-#define XSHAL_ISS_CACHEATTR_WRITEBACK  0x1122222F      /* enable caches in write-back mode */
-#define XSHAL_ISS_CACHEATTR_WRITEALLOC 0x1122222F      /* enable caches in write-allocate mode */
-#define XSHAL_ISS_CACHEATTR_WRITETHRU  0x1122222F      /* enable caches in write-through mode */
-#define XSHAL_ISS_CACHEATTR_BYPASS     0x2222222F      /* disable caches in bypass mode */
-#define XSHAL_ISS_CACHEATTR_DEFAULT    XSHAL_ISS_CACHEATTR_WRITEBACK   /* default setting to enable caches */
-
-/*  For Coware only:  */
-#define XSHAL_COWARE_CACHEATTR_WRITEBACK       0x11222222      /* enable caches in write-back mode */
-#define XSHAL_COWARE_CACHEATTR_WRITEALLOC      0x11222222      /* enable caches in write-allocate mode */
-#define XSHAL_COWARE_CACHEATTR_WRITETHRU       0x11222222      /* enable caches in write-through mode */
-#define XSHAL_COWARE_CACHEATTR_BYPASS          0x22222222      /* disable caches in bypass mode */
-#define XSHAL_COWARE_CACHEATTR_DEFAULT         XSHAL_COWARE_CACHEATTR_WRITEBACK        /* default setting to enable caches */
-
-/*  For BFM and other purposes:  */
-#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK     0x11222222      /* enable caches without any invalid regions */
-#define XSHAL_ALLVALID_CACHEATTR_DEFAULT       XSHAL_ALLVALID_CACHEATTR_WRITEBACK      /* default setting for caches without any invalid regions */
-
-#define XSHAL_ISS_PIPE_REGIONS 0
-#define XSHAL_ISS_SDRAM_REGIONS        0
-
-
-/*----------------------------------------------------------------------
-                       XT2000 BOARD SPECIFIC ...
-  ----------------------------------------------------------------------*/
-
-#define XSHAL_XT2000_CACHEATTR_WRITEBACK       0x22FFFFFF      /* enable caches in write-back mode */
-#define XSHAL_XT2000_CACHEATTR_WRITEALLOC      0x22FFFFFF      /* enable caches in write-allocate mode */
-#define XSHAL_XT2000_CACHEATTR_WRITETHRU       0x22FFFFFF      /* enable caches in write-through mode */
-#define XSHAL_XT2000_CACHEATTR_BYPASS          0x22FFFFFF      /* disable caches in bypass mode */
-#define XSHAL_XT2000_CACHEATTR_DEFAULT         XSHAL_XT2000_CACHEATTR_WRITEBACK        /* default setting to enable caches */
-
-#define XSHAL_XT2000_PIPE_REGIONS      0x00001000      /* BusInt pipeline regions */
-#define XSHAL_XT2000_SDRAM_REGIONS     0x00000005      /* BusInt SDRAM regions */
-
-
-/*----------------------------------------------------------------------
-                               VECTOR SIZES
-  ----------------------------------------------------------------------*/
-
-/*
- *  Sizes allocated to vectors by the system (memory map) configuration.
- *  These sizes are constrained by core configuration (eg. one vector's
- *  code cannot overflow into another vector) but are dependent on the
- *  system or board (or LSP) memory map configuration.
- *
- *  Whether or not each vector happens to be in a system ROM is also
- *  a system configuration matter, sometimes useful, included here also:
- */
-#define XSHAL_RESET_VECTOR_SIZE        0x000004E0
-#define XSHAL_RESET_VECTOR_ISROM       1
-#define XSHAL_USER_VECTOR_SIZE 0x0000001C
-#define XSHAL_USER_VECTOR_ISROM        0
-#define XSHAL_PROGRAMEXC_VECTOR_SIZE   XSHAL_USER_VECTOR_SIZE  /* for backward compatibility */
-#define XSHAL_USEREXC_VECTOR_SIZE      XSHAL_USER_VECTOR_SIZE  /* for backward compatibility */
-#define XSHAL_KERNEL_VECTOR_SIZE       0x0000001C
-#define XSHAL_KERNEL_VECTOR_ISROM      0
-#define XSHAL_STACKEDEXC_VECTOR_SIZE   XSHAL_KERNEL_VECTOR_SIZE        /* for backward compatibility */
-#define XSHAL_KERNELEXC_VECTOR_SIZE    XSHAL_KERNEL_VECTOR_SIZE        /* for backward compatibility */
-#define XSHAL_DOUBLEEXC_VECTOR_SIZE    0x000000E0
-#define XSHAL_DOUBLEEXC_VECTOR_ISROM   0
-#define XSHAL_WINDOW_VECTORS_SIZE      0x00000180
-#define XSHAL_WINDOW_VECTORS_ISROM     0
-#define XSHAL_INTLEVEL2_VECTOR_SIZE    0x0000000C
-#define XSHAL_INTLEVEL2_VECTOR_ISROM   0
-#define XSHAL_INTLEVEL3_VECTOR_SIZE    0x0000000C
-#define XSHAL_INTLEVEL3_VECTOR_ISROM   0
-#define XSHAL_INTLEVEL4_VECTOR_SIZE    0x0000000C
-#define XSHAL_INTLEVEL4_VECTOR_ISROM   1
-#define XSHAL_DEBUG_VECTOR_SIZE                XSHAL_INTLEVEL4_VECTOR_SIZE
-#define XSHAL_DEBUG_VECTOR_ISROM       XSHAL_INTLEVEL4_VECTOR_ISROM
-
-
-#endif /*XTENSA_CONFIG_SYSTEM_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/tie.h b/include/asm-xtensa/xtensa/config-linux_be/tie.h
deleted file mode 100644 (file)
index 3c2e514..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * xtensa/config/tie.h -- HAL definitions that are dependent on CORE and TIE configuration
- *
- *  This header file is sometimes referred to as the "compile-time HAL" or CHAL.
- *  It was generated for a specific Xtensa processor configuration,
- *  and furthermore for a specific set of TIE source files that extend
- *  basic core functionality.
- *
- *  Source for configuration-independent binaries (which link in a
- *  configuration-specific HAL library) must NEVER include this file.
- *  It is perfectly normal, however, for the HAL source itself to include this file.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- */
-
-
-#ifndef XTENSA_CONFIG_TIE_H
-#define XTENSA_CONFIG_TIE_H
-
-#include <xtensa/hal.h>
-
-
-/*----------------------------------------------------------------------
-                               GENERAL
-  ----------------------------------------------------------------------*/
-
-/*
- *  Separators for macros that expand into arrays.
- *  These can be predefined by files that #include this one,
- *  when different separators are required.
- */
-/*  Element separator for macros that expand into 1-dimensional arrays:  */
-#ifndef XCHAL_SEP
-#define XCHAL_SEP                      ,
-#endif
-/*  Array separator for macros that expand into 2-dimensional arrays:  */
-#ifndef XCHAL_SEP2
-#define XCHAL_SEP2                     },{
-#endif
-
-
-
-
-
-
-/*----------------------------------------------------------------------
-                       COPROCESSORS and EXTRA STATE
-  ----------------------------------------------------------------------*/
-
-#define XCHAL_CP_NUM                   0       /* number of coprocessors */
-#define XCHAL_CP_MAX                   0       /* max coprocessor id plus one (0 if none) */
-#define XCHAL_CP_MASK                  0x00    /* bitmask of coprocessors by id */
-
-/*  Space for coprocessors' state save areas:  */
-#define XCHAL_CP0_SA_SIZE              0
-#define XCHAL_CP1_SA_SIZE              0
-#define XCHAL_CP2_SA_SIZE              0
-#define XCHAL_CP3_SA_SIZE              0
-#define XCHAL_CP4_SA_SIZE              0
-#define XCHAL_CP5_SA_SIZE              0
-#define XCHAL_CP6_SA_SIZE              0
-#define XCHAL_CP7_SA_SIZE              0
-/*  Minimum required alignments of CP state save areas:  */
-#define XCHAL_CP0_SA_ALIGN             1
-#define XCHAL_CP1_SA_ALIGN             1
-#define XCHAL_CP2_SA_ALIGN             1
-#define XCHAL_CP3_SA_ALIGN             1
-#define XCHAL_CP4_SA_ALIGN             1
-#define XCHAL_CP5_SA_ALIGN             1
-#define XCHAL_CP6_SA_ALIGN             1
-#define XCHAL_CP7_SA_ALIGN             1
-
-/*  Indexing macros:  */
-#define _XCHAL_CP_SA_SIZE(n)           XCHAL_CP ## n ## _SA_SIZE
-#define XCHAL_CP_SA_SIZE(n)            _XCHAL_CP_SA_SIZE(n)    /* n = 0 .. 7 */
-#define _XCHAL_CP_SA_ALIGN(n)          XCHAL_CP ## n ## _SA_ALIGN
-#define XCHAL_CP_SA_ALIGN(n)           _XCHAL_CP_SA_ALIGN(n)   /* n = 0 .. 7 */
-
-
-/*  Space for "extra" state (user special registers and non-cp TIE) save area:  */
-#define XCHAL_EXTRA_SA_SIZE            0
-#define XCHAL_EXTRA_SA_ALIGN           1
-
-/*  Total save area size (extra + all coprocessors)  */
-/*  (not useful until xthal_{save,restore}_all_extra() is implemented,  */
-/*   but included for Tor2 beta; doesn't account for alignment!):  */
-#define XCHAL_CPEXTRA_SA_SIZE_TOR2     0       /* Tor2Beta temporary definition -- do not use */
-
-/*  Combined required alignment for all CP and EXTRA state save areas  */
-/*  (does not include required alignment for any base config registers):  */
-#define XCHAL_CPEXTRA_SA_ALIGN         1
-
-/* ... */
-
-
-#ifdef _ASMLANGUAGE
-/*
- *  Assembly-language specific definitions (assembly macros, etc.).
- */
-#include <xtensa/config/specreg.h>
-
-/********************
- *  Macros to save and restore the non-coprocessor TIE portion of EXTRA state.
- */
-
-/* (none) */
-
-
-/********************
- *  Macros to create functions that save and restore all EXTRA (non-coprocessor) state
- *  (does not include zero-overhead loop registers and non-optional registers).
- */
-
-       /*
-        *  Macro that expands to the body of a function that
-        *  stores the extra (non-coprocessor) optional/custom state.
-        *      Entry:  a2 = ptr to save area in which to save extra state
-        *      Exit:   any register a2-a15 (?) may have been clobbered.
-        */
-       .macro  xchal_extra_store_funcbody
-       .endm
-
-
-       /*
-        *  Macro that expands to the body of a function that
-        *  loads the extra (non-coprocessor) optional/custom state.
-        *      Entry:  a2 = ptr to save area from which to restore extra state
-        *      Exit:   any register a2-a15 (?) may have been clobbered.
-        */
-       .macro  xchal_extra_load_funcbody
-       .endm
-
-
-/********************
- *  Macros to save and restore the state of each TIE coprocessor.
- */
-
-
-
-/********************
- *  Macros to create functions that save and restore the state of *any* TIE coprocessor.
- */
-
-       /*
-        *  Macro that expands to the body of a function
-        *  that stores the selected coprocessor's state (registers etc).
-        *      Entry:  a2 = ptr to save area in which to save cp state
-        *              a3 = coprocessor number
-        *      Exit:   any register a2-a15 (?) may have been clobbered.
-        */
-       .macro  xchal_cpi_store_funcbody
-       .endm
-
-
-       /*
-        *  Macro that expands to the body of a function
-        *  that loads the selected coprocessor's state (registers etc).
-        *      Entry:  a2 = ptr to save area from which to restore cp state
-        *              a3 = coprocessor number
-        *      Exit:   any register a2-a15 (?) may have been clobbered.
-        */
-       .macro  xchal_cpi_load_funcbody
-       .endm
-
-#endif /*_ASMLANGUAGE*/
-
-
-/*
- *  Contents of save areas in terms of libdb register numbers.
- *  NOTE:  CONTENTS_LIBDB_{UREG,REGF} macros are not defined in this file;
- *  it is up to the user of this header file to define these macros
- *  usefully before each expansion of the CONTENTS_LIBDB macros.
- *  (Fields rsv[123] are reserved for future additions; they are currently
- *   set to zero but may be set to some useful values in the future.)
- *
- *     CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, bitmask, rsv2, rsv3)
- *     CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, bitmask, rsv2, rsv3)
- *     CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, numentries, contentsize, regname_base, regfile_name, rsv2, rsv3)
- */
-
-#define XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM      0
-#define XCHAL_EXTRA_SA_CONTENTS_LIBDB  /* empty */
-
-#define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP0_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP1_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP2_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP3_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP4_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP5_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP6_SA_CONTENTS_LIBDB    /* empty */
-
-#define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM        0
-#define XCHAL_CP7_SA_CONTENTS_LIBDB    /* empty */
-
-
-
-
-
-
-/*----------------------------------------------------------------------
-                               MISC
-  ----------------------------------------------------------------------*/
-
-#if 0  /* is there something equivalent for user TIE? */
-#define XCHAL_CORE_ID                  "linux_be"      /* configuration's alphanumeric core identifier
-                                                          (CoreID) set in the Xtensa Processor Generator */
-
-#define XCHAL_BUILD_UNIQUE_ID          0x00003256      /* software build-unique ID (22-bit) */
-
-/*  These definitions describe the hardware targeted by this software:  */
-#define XCHAL_HW_CONFIGID0             0xC103D1FF      /* config ID reg 0 value (upper 32 of 64 bits) */
-#define XCHAL_HW_CONFIGID1             0x00803256      /* config ID reg 1 value (lower 32 of 64 bits) */
-#define XCHAL_CONFIGID0                        XCHAL_HW_CONFIGID0      /* for backward compatibility only -- don't use! */
-#define XCHAL_CONFIGID1                        XCHAL_HW_CONFIGID1      /* for backward compatibility only -- don't use! */
-#define XCHAL_HW_RELEASE_MAJOR         1050    /* major release of targeted hardware */
-#define XCHAL_HW_RELEASE_MINOR         1       /* minor release of targeted hardware */
-#define XCHAL_HW_RELEASE_NAME          "T1050.1"       /* full release name of targeted hardware */
-#define XTHAL_HW_REL_T1050     1
-#define XTHAL_HW_REL_T1050_1   1
-#define XCHAL_HW_CONFIGID_RELIABLE     1
-#endif /*0*/
-
-
-
-/*----------------------------------------------------------------------
-                               ISA
-  ----------------------------------------------------------------------*/
-
-#if 0  /* these probably don't belong here, but are related to or implemented using TIE */
-#define XCHAL_HAVE_BOOLEANS            0       /* 1 if booleans option configured, 0 otherwise */
-/*  Misc instructions:  */
-#define XCHAL_HAVE_MUL32               0       /* 1 if 32-bit integer multiply option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32_HIGH          0       /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
-
-#define XCHAL_HAVE_FP                  0       /* 1 if floating point option configured, 0 otherwise */
-#endif /*0*/
-
-
-#endif /*XTENSA_CONFIG_TIE_H*/
-
diff --git a/include/asm-xtensa/xtensa/coreasm.h b/include/asm-xtensa/xtensa/coreasm.h
deleted file mode 100644 (file)
index a8cfb54..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-#ifndef XTENSA_COREASM_H
-#define XTENSA_COREASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
- * definitions that depend on CORE configuration.
- *
- * Source for configuration-independent binaries (which link in a
- * configuration-specific HAL library) must NEVER include this file.
- * It is perfectly normal, however, for the HAL itself to include this
- * file.
- *
- * This file must NOT include xtensa/config/system.h.  Any assembler
- * header file that depends on system information should likely go in
- * a new systemasm.h (or sysasm.h) header file.
- *
- *  NOTE: macro beqi32 is NOT configuration-dependent, and is placed
- *        here til we will have configuration-independent header file.
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/specreg.h>
-
-/*
- *  Assembly-language specific definitions (assembly macros, etc.).
- */
-
-/*----------------------------------------------------------------------
- *  find_ms_setbit
- *
- *  This macro finds the most significant bit that is set in <as>
- *  and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
- *  The index counts starting at zero for the lsbit, so the return
- *  value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
- *
- *  Parameters:
- *     <ad>    destination address register (any register)
- *     <as>    source address register
- *     <at>    temporary address register (must be different than <as>)
- *     <base>  constant value added to result (usually 0 or 1)
- *  On entry:
- *     <ad> = undefined if different than <as>
- *     <as> = value whose most significant set bit is to be found
- *     <at> = undefined
- *     no other registers are used by this macro.
- *  On exit:
- *     <ad> = <base> + index of msbit set in original <as>,
- *          = <base> - 1 if original <as> was zero.
- *     <as> clobbered (if not <ad>)
- *     <at> clobbered (if not <ad>)
- *  Example:
- *     find_ms_setbit a0, a4, a0, 0            -- return in a0 index of msbit set in a4
- */
-
-       .macro  find_ms_setbit ad, as, at, base
-#if XCHAL_HAVE_NSA
-       movi    \at, 31+\base
-       nsau    \as, \as        // get index of \as, numbered from msbit (32 if absent)
-       sub     \ad, \at, \as   // get numbering from lsbit (0..31, -1 if absent)
-#else /* XCHAL_HAVE_NSA */
-       movi    \at, \base      // start with result of 0 (point to lsbit of 32)
-
-       beqz    \as, 2f         // special case for zero argument: return -1
-       bltui   \as, 0x10000, 1f        // is it one of the 16 lsbits? (if so, check lower 16 bits)
-       addi    \at, \at, 16    // no, increment result to upper 16 bits (of 32)
-       //srli  \as, \as, 16    // check upper half (shift right 16 bits)
-       extui   \as, \as, 16, 16        // check upper half (shift right 16 bits)
-1:     bltui   \as, 0x100, 1f  // is it one of the 8 lsbits? (if so, check lower 8 bits)
-       addi    \at, \at, 8     // no, increment result to upper 8 bits (of 16)
-       srli    \as, \as, 8     // shift right to check upper 8 bits
-1:     bltui   \as, 0x10, 1f   // is it one of the 4 lsbits? (if so, check lower 4 bits)
-       addi    \at, \at, 4     // no, increment result to upper 4 bits (of 8)
-       srli    \as, \as, 4     // shift right 4 bits to check upper half
-1:     bltui   \as, 0x4, 1f    // is it one of the 2 lsbits? (if so, check lower 2 bits)
-       addi    \at, \at, 2     // no, increment result to upper 2 bits (of 4)
-       srli    \as, \as, 2     // shift right 2 bits to check upper half
-1:     bltui   \as, 0x2, 1f    // is it the lsbit?
-       addi    \at, \at, 2     // no, increment result to upper bit (of 2)
-2:     addi    \at, \at, -1    // (from just above: add 1;  from beqz: return -1)
-       //srli  \as, \as, 1
-1:                             // done! \at contains index of msbit set (or -1 if none set)
-       .if     0x\ad - 0x\at   // destination different than \at ? (works because regs are a0-a15)
-       mov     \ad, \at        // then move result to \ad
-       .endif
-#endif /* XCHAL_HAVE_NSA */
-       .endm   // find_ms_setbit
-
-/*----------------------------------------------------------------------
- *  find_ls_setbit
- *
- *  This macro finds the least significant bit that is set in <as>,
- *  and return its index in <ad>.
- *  Usage is the same as for the find_ms_setbit macro.
- *  Example:
- *     find_ls_setbit a0, a4, a0, 0    -- return in a0 index of lsbit set in a4
- */
-
-       .macro  find_ls_setbit ad, as, at, base
-       neg     \at, \as        // keep only the least-significant bit that is set...
-       and     \as, \at, \as   // ... in \as
-       find_ms_setbit  \ad, \as, \at, \base
-       .endm   // find_ls_setbit
-
-/*----------------------------------------------------------------------
- *  find_ls_one
- *
- *  Same as find_ls_setbit with base zero.
- *  Source (as) and destination (ad) registers must be different.
- *  Provided for backward compatibility.
- */
-
-       .macro  find_ls_one ad, as
-       find_ls_setbit  \ad, \as, \ad, 0
-       .endm   // find_ls_one
-
-/*----------------------------------------------------------------------
- *  floop, floopnez, floopgtz, floopend
- *
- *  These macros are used for fast inner loops that
- *  work whether or not the Loops options is configured.
- *  If the Loops option is configured, they simply use
- *  the zero-overhead LOOP instructions; otherwise
- *  they use explicit decrement and branch instructions.
- *
- *  They are used in pairs, with floop, floopnez or floopgtz
- *  at the beginning of the loop, and floopend at the end.
- *
- *  Each pair of loop macro calls must be given the loop count
- *  address register and a unique label for that loop.
- *
- *  Example:
- *
- *     movi     a3, 16     // loop 16 times
- *     floop    a3, myloop1
- *     :
- *     bnez     a7, end1       // exit loop if a7 != 0
- *     :
- *     floopend a3, myloop1
- *  end1:
- *
- *  Like the LOOP instructions, these macros cannot be
- *  nested, must include at least one instruction,
- *  cannot call functions inside the loop, etc.
- *  The loop can be exited by jumping to the instruction
- *  following floopend (or elsewhere outside the loop),
- *  or continued by jumping to a NOP instruction placed
- *  immediately before floopend.
- *
- *  Unlike LOOP instructions, the register passed to floop*
- *  cannot be used inside the loop, because it is used as
- *  the loop counter if the Loops option is not configured.
- *  And its value is undefined after exiting the loop.
- *  And because the loop counter register is active inside
- *  the loop, you can't easily use this construct to loop
- *  across a register file using ROTW as you might with LOOP
- *  instructions, unless you copy the loop register along.
- */
-
-       /*  Named label version of the macros:  */
-
-       .macro  floop           ar, endlabel
-       floop_          \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
-       .endm
-
-       .macro  floopnez        ar, endlabel
-       floopnez_       \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
-       .endm
-
-       .macro  floopgtz        ar, endlabel
-       floopgtz_       \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
-       .endm
-
-       .macro  floopend        ar, endlabel
-       floopend_       \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
-       .endm
-
-       /*  Numbered local label version of the macros:  */
-#if 0 /*UNTESTED*/
-       .macro  floop89         ar
-       floop_          \ar, 8, 9f
-       .endm
-
-       .macro  floopnez89      ar
-       floopnez_       \ar, 8, 9f
-       .endm
-
-       .macro  floopgtz89      ar
-       floopgtz_       \ar, 8, 9f
-       .endm
-
-       .macro  floopend89      ar
-       floopend_       \ar, 8b, 9
-       .endm
-#endif /*0*/
-
-       /*  Underlying version of the macros:  */
-
-       .macro  floop_  ar, startlabel, endlabelref
-       .ifdef  _infloop_
-       .if     _infloop_
-       .err    // Error: floop cannot be nested
-       .endif
-       .endif
-       .set    _infloop_, 1
-#if XCHAL_HAVE_LOOPS
-       loop    \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
-\startlabel:
-       addi    \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
-       .endm   // floop_
-
-       .macro  floopnez_       ar, startlabel, endlabelref
-       .ifdef  _infloop_
-       .if     _infloop_
-       .err    // Error: floopnez cannot be nested
-       .endif
-       .endif
-       .set    _infloop_, 1
-#if XCHAL_HAVE_LOOPS
-       loopnez \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
-       beqz    \ar, \endlabelref
-\startlabel:
-       addi    \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
-       .endm   // floopnez_
-
-       .macro  floopgtz_       ar, startlabel, endlabelref
-       .ifdef  _infloop_
-       .if     _infloop_
-       .err    // Error: floopgtz cannot be nested
-       .endif
-       .endif
-       .set    _infloop_, 1
-#if XCHAL_HAVE_LOOPS
-       loopgtz \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
-       bltz    \ar, \endlabelref
-       beqz    \ar, \endlabelref
-\startlabel:
-       addi    \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
-       .endm   // floopgtz_
-
-
-       .macro  floopend_       ar, startlabelref, endlabel
-       .ifndef _infloop_
-       .err    // Error: floopend without matching floopXXX
-       .endif
-       .ifeq   _infloop_
-       .err    // Error: floopend without matching floopXXX
-       .endif
-       .set    _infloop_, 0
-#if ! XCHAL_HAVE_LOOPS
-       bnez    \ar, \startlabelref
-#endif /* XCHAL_HAVE_LOOPS */
-\endlabel:
-       .endm   // floopend_
-
-/*----------------------------------------------------------------------
- *  crsil  --  conditional RSIL (read/set interrupt level)
- *
- *  Executes the RSIL instruction if it exists, else just reads PS.
- *  The RSIL instruction does not exist in the new exception architecture
- *  if the interrupt option is not selected.
- */
-
-       .macro  crsil   ar, newlevel
-#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
-       rsil    \ar, \newlevel
-#else
-       rsr     \ar, PS
-#endif
-       .endm   // crsil
-
-/*----------------------------------------------------------------------
- *  window_spill{4,8,12}
- *
- *  These macros spill callers' register windows to the stack.
- *  They work for both privileged and non-privileged tasks.
- *  Must be called from a windowed ABI context, eg. within
- *  a windowed ABI function (ie. valid stack frame, window
- *  exceptions enabled, not in exception mode, etc).
- *
- *  This macro requires a single invocation of the window_spill_common
- *  macro in the same assembly unit and section.
- *
- *  Note that using window_spill{4,8,12} macros is more efficient
- *  than calling a function implemented using window_spill_function,
- *  because the latter needs extra code to figure out the size of
- *  the call to the spilling function.
- *
- *  Example usage:
- *
- *             .text
- *             .align  4
- *             .global some_function
- *             .type   some_function,@function
- *     some_function:
- *             entry   a1, 16
- *             :
- *             :
- *
- *             window_spill4   // spill windows of some_function's callers; preserves a0..a3 only;
- *                             // to use window_spill{8,12} in this example function we'd have
- *                             // to increase space allocated by the entry instruction, because
- *                             // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
- *                             // for call8/window_spill8 or call12/window_spill12 respectively.
- *             :
- *
- *             retw
- *
- *             window_spill_common     // instantiates code used by window_spill4
- *
- *
- *  On entry:
- *     none (if window_spill4)
- *     stack frame has enough space allocated for call8 (if window_spill8)
- *     stack frame has enough space allocated for call12 (if window_spill12)
- *  On exit:
- *      a4..a15 clobbered (if window_spill4)
- *      a8..a15 clobbered (if window_spill8)
- *     a12..a15 clobbered (if window_spill12)
- *     no caller windows are in live registers
- */
-
-       .macro  window_spill4
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
-       movi    a15, 0                  // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
-       call4   .L__wdwspill_assist28   // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
-       call4   .L__wdwspill_assist60   // call deep enough to clear out any live callers
-# endif
-#endif
-       .endm   // window_spill4
-
-       .macro  window_spill8
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
-       movi    a15, 0                  // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
-       call8   .L__wdwspill_assist24   // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
-       call8   .L__wdwspill_assist56   // call deep enough to clear out any live callers
-# endif
-#endif
-       .endm   // window_spill8
-
-       .macro  window_spill12
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
-       movi    a15, 0                  // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
-       call12  .L__wdwspill_assist20   // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
-       call12  .L__wdwspill_assist52   // call deep enough to clear out any live callers
-# endif
-#endif
-       .endm   // window_spill12
-
-/*----------------------------------------------------------------------
- *  window_spill_function
- *
- *  This macro outputs a function that will spill its caller's callers'
- *  register windows to the stack.  Eg. it could be used to implement
- *  a version of xthal_window_spill() that works in non-privileged tasks.
- *  This works for both privileged and non-privileged tasks.
- *
- *  Typical usage:
- *
- *             .text
- *             .align  4
- *             .global my_spill_function
- *             .type   my_spill_function,@function
- *     my_spill_function:
- *             window_spill_function
- *
- *  On entry to resulting function:
- *     none
- *  On exit from resulting function:
- *     none (no caller windows are in live registers)
- */
-
-       .macro  window_spill_function
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 32
-       entry   sp, 48
-       bbci.l  a0, 31, 1f              // branch if called with call4
-       bbsi.l  a0, 30, 2f              // branch if called with call12
-       call8   .L__wdwspill_assist16   // called with call8, only need another 8
-       retw
-1:     call12  .L__wdwspill_assist16   // called with call4, only need another 12
-       retw
-2:     call4   .L__wdwspill_assist16   // called with call12, only need another 4
-       retw
-# elif XCHAL_NUM_AREGS == 64
-       entry   sp, 48
-       bbci.l  a0, 31, 1f              // branch if called with call4
-       bbsi.l  a0, 30, 2f              // branch if called with call12
-       call4   .L__wdwspill_assist52   // called with call8, only need a call4
-       retw
-1:     call8   .L__wdwspill_assist52   // called with call4, only need a call8
-       retw
-2:     call12  .L__wdwspill_assist40   // called with call12, can skip a call12
-       retw
-# elif XCHAL_NUM_AREGS == 16
-       entry   sp, 16
-       bbci.l  a0, 31, 1f      // branch if called with call4
-       bbsi.l  a0, 30, 2f      // branch if called with call12
-       movi    a7, 0           // called with call8
-       retw
-1:     movi    a11, 0          // called with call4
-2:     retw                    // if called with call12, everything already spilled
-
-//     movi    a15, 0          // trick to spill all but the direct caller
-//     j       1f
-//     //  The entry instruction is magical in the assembler (gets auto-aligned)
-//     //  so we have to jump to it to avoid falling through the padding.
-//     //  We need entry/retw to know where to return.
-//1:   entry   sp, 16
-//     retw
-# else
-#  error "unrecognized address register file size"
-# endif
-#endif /* XCHAL_HAVE_WINDOWED */
-       window_spill_common
-       .endm   // window_spill_function
-
-/*----------------------------------------------------------------------
- *  window_spill_common
- *
- *  Common code used by any number of invocations of the window_spill##
- *  and window_spill_function macros.
- *
- *  Must be instantiated exactly once within a given assembly unit,
- *  within call/j range of and same section as window_spill##
- *  macro invocations for that assembly unit.
- *  (Is automatically instantiated by the window_spill_function macro.)
- */
-
-       .macro  window_spill_common
-#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
-       .ifndef .L__wdwspill_defined
-# if XCHAL_NUM_AREGS >= 64
-.L__wdwspill_assist60:
-       entry   sp, 32
-       call8   .L__wdwspill_assist52
-       retw
-.L__wdwspill_assist56:
-       entry   sp, 16
-       call4   .L__wdwspill_assist52
-       retw
-.L__wdwspill_assist52:
-       entry   sp, 48
-       call12  .L__wdwspill_assist40
-       retw
-.L__wdwspill_assist40:
-       entry   sp, 48
-       call12  .L__wdwspill_assist28
-       retw
-# endif
-.L__wdwspill_assist28:
-       entry   sp, 48
-       call12  .L__wdwspill_assist16
-       retw
-.L__wdwspill_assist24:
-       entry   sp, 32
-       call8   .L__wdwspill_assist16
-       retw
-.L__wdwspill_assist20:
-       entry   sp, 16
-       call4   .L__wdwspill_assist16
-       retw
-.L__wdwspill_assist16:
-       entry   sp, 16
-       movi    a15, 0
-       retw
-       .set    .L__wdwspill_defined, 1
-       .endif
-#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
-       .endm   // window_spill_common
-
-/*----------------------------------------------------------------------
- *  beqi32
- *
- *  macro implements version of beqi for arbitrary 32-bit immidiate value
- *
- *     beqi32 ax, ay, imm32, label
- *
- *  Compares value in register ax with imm32 value and jumps to label if
- *  equal. Clobberes register ay if needed
- *
- */
-   .macro beqi32       ax, ay, imm, label
-    .ifeq ((\imm-1) & ~7)      // 1..8 ?
-               beqi    \ax, \imm, \label
-    .else
-      .ifeq (\imm+1)           // -1 ?
-               beqi    \ax, \imm, \label
-      .else
-        .ifeq (\imm)           // 0 ?
-               beqz    \ax, \label
-        .else
-               //  We could also handle immediates 10,12,16,32,64,128,256
-               //  but it would be a long macro...
-               movi    \ay, \imm
-               beq     \ax, \ay, \label
-        .endif
-      .endif
-    .endif
-   .endm // beqi32
-
-#endif /*XTENSA_COREASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/corebits.h b/include/asm-xtensa/xtensa/corebits.h
deleted file mode 100644 (file)
index e578ade..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef XTENSA_COREBITS_H
-#define XTENSA_COREBITS_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * xtensa/corebits.h - Xtensa Special Register field positions and masks.
- *
- * (In previous releases, these were defined in specreg.h, a generated file.
- *  This file is not generated, i.e. it is processor configuration independent.)
- */
-
-
-/*  EXCCAUSE register fields:  */
-#define EXCCAUSE_EXCCAUSE_SHIFT        0
-#define EXCCAUSE_EXCCAUSE_MASK 0x3F
-/*  Exception causes (mostly incomplete!):  */
-#define EXCCAUSE_ILLEGAL               0
-#define EXCCAUSE_SYSCALL               1
-#define EXCCAUSE_IFETCHERROR           2
-#define EXCCAUSE_LOADSTOREERROR                3
-#define EXCCAUSE_LEVEL1INTERRUPT       4
-#define EXCCAUSE_ALLOCA                        5
-
-/*  PS register fields:  */
-#define PS_WOE_SHIFT           18
-#define PS_WOE_MASK            0x00040000
-#define PS_WOE                 PS_WOE_MASK
-#define PS_CALLINC_SHIFT       16
-#define PS_CALLINC_MASK                0x00030000
-#define PS_CALLINC(n)          (((n)&3)<<PS_CALLINC_SHIFT)     /* n = 0..3 */
-#define PS_OWB_SHIFT           8
-#define PS_OWB_MASK            0x00000F00
-#define PS_OWB(n)              (((n)&15)<<PS_OWB_SHIFT)        /* n = 0..15 (or 0..7) */
-#define PS_RING_SHIFT          6
-#define PS_RING_MASK           0x000000C0
-#define PS_RING(n)             (((n)&3)<<PS_RING_SHIFT)        /* n = 0..3 */
-#define PS_UM_SHIFT            5
-#define PS_UM_MASK             0x00000020
-#define PS_UM                  PS_UM_MASK
-#define PS_EXCM_SHIFT          4
-#define PS_EXCM_MASK           0x00000010
-#define PS_EXCM                        PS_EXCM_MASK
-#define PS_INTLEVEL_SHIFT      0
-#define PS_INTLEVEL_MASK       0x0000000F
-#define PS_INTLEVEL(n)         ((n)&PS_INTLEVEL_MASK)          /* n = 0..15 */
-/*  Backward compatibility (deprecated):  */
-#define PS_PROGSTACK_SHIFT     PS_UM_SHIFT
-#define PS_PROGSTACK_MASK      PS_UM_MASK
-#define PS_PROG_SHIFT          PS_UM_SHIFT
-#define PS_PROG_MASK           PS_UM_MASK
-#define PS_PROG                        PS_UM
-
-/*  DBREAKCn register fields:  */
-#define DBREAKC_MASK_SHIFT             0
-#define DBREAKC_MASK_MASK              0x0000003F
-#define DBREAKC_LOADBREAK_SHIFT                30
-#define DBREAKC_LOADBREAK_MASK         0x40000000
-#define DBREAKC_STOREBREAK_SHIFT       31
-#define DBREAKC_STOREBREAK_MASK                0x80000000
-
-/*  DEBUGCAUSE register fields:  */
-#define DEBUGCAUSE_DEBUGINT_SHIFT      5
-#define DEBUGCAUSE_DEBUGINT_MASK       0x20    /* debug interrupt */
-#define DEBUGCAUSE_BREAKN_SHIFT                4
-#define DEBUGCAUSE_BREAKN_MASK         0x10    /* BREAK.N instruction */
-#define DEBUGCAUSE_BREAK_SHIFT         3
-#define DEBUGCAUSE_BREAK_MASK          0x08    /* BREAK instruction */
-#define DEBUGCAUSE_DBREAK_SHIFT                2
-#define DEBUGCAUSE_DBREAK_MASK         0x04    /* DBREAK match */
-#define DEBUGCAUSE_IBREAK_SHIFT                1
-#define DEBUGCAUSE_IBREAK_MASK         0x02    /* IBREAK match */
-#define DEBUGCAUSE_ICOUNT_SHIFT                0
-#define DEBUGCAUSE_ICOUNT_MASK         0x01    /* ICOUNT would increment to zero */
-
-#endif /*XTENSA_COREBITS_H*/
-
diff --git a/include/asm-xtensa/xtensa/hal.h b/include/asm-xtensa/xtensa/hal.h
deleted file mode 100644 (file)
index d104725..0000000
+++ /dev/null
@@ -1,822 +0,0 @@
-#ifndef XTENSA_HAL_H
-#define XTENSA_HAL_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/hal.h -- contains a definition of the
- * Core HAL interface.
- *
- * All definitions in this header file are independent of any specific
- * Xtensa processor configuration.  Thus an OS or other software can
- * include this header file and be compiled into configuration-
- * independent objects that can be distributed and eventually linked
- * to the HAL library (libhal.a) to create a configuration-specific
- * final executable.
- *
- * Certain definitions, however, are release-specific -- such as the
- * XTHAL_RELEASE_xxx macros (or additions made in later releases).
- *
- * 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) 2002 Tensilica Inc.
- */
-
-
-/*----------------------------------------------------------------------
-                        Constant Definitions
-                       (shared with assembly)
-  ----------------------------------------------------------------------*/
-
-/*  Software release information (not configuration-specific!):  */
-#define XTHAL_RELEASE_MAJOR    1050
-#define XTHAL_RELEASE_MINOR    0
-#define XTHAL_RELEASE_NAME     "T1050.0-2002-08-06-eng0"
-#define XTHAL_RELEASE_INTERNAL "2002-08-06-eng0"
-#define XTHAL_REL_T1050        1
-#define XTHAL_REL_T1050_0      1
-#define XTHAL_REL_T1050_0_2002 1
-#define XTHAL_REL_T1050_0_2002_08      1
-#define XTHAL_REL_T1050_0_2002_08_06   1
-#define XTHAL_REL_T1050_0_2002_08_06_ENG0      1
-
-/*  HAL version numbers (these names are for backward compatibility):  */
-#define XTHAL_MAJOR_REV                XTHAL_RELEASE_MAJOR
-#define XTHAL_MINOR_REV                XTHAL_RELEASE_MINOR
-/*
- *  A bit of software release history on values of XTHAL_{MAJOR,MINOR}_REV:
- *
- *     Release         MAJOR   MINOR           Comment
- *     =======         =====   =====           =======
- *     T1015.n         n/a     n/a             (HAL not yet available)
- *     T1020.{0,1,2}   0       1               (HAL beta)
- *     T1020.{3,4}     0       2               First release.
- *     T1020.n (n>4)   0       2 or >3         (TBD)
- *     T1030.0         0       1               (HAL beta)
- *     T1030.{1,2}     0       3               Equivalent to first release.
- *     T1030.n (n>=3)  0       >= 3            (TBD)
- *     T1040.n         1040    n               Full CHAL available from T1040.2
- *     T1050.n         1050    n               Current release.
- *
- *
- *  Note:  there is a distinction between the software release with
- *  which something is compiled (accessible using XTHAL_RELEASE_* macros)
- *  and the software release with which the HAL library was compiled
- *  (accessible using Xthal_release_* global variables).  This
- *  distinction is particularly relevant for vendors that distribute
- *  configuration-independent binaries (eg. an OS), where their customer
- *  might link it with a HAL of a different Xtensa software release.
- *  In this case, it may be appropriate for the OS to verify at run-time
- *  whether XTHAL_RELEASE_* and Xthal_release_* are compatible.
- *  [Guidelines as to which release is compatible with which are not
- *  currently provided explicitly, but might be inferred from reading
- *  OSKit documentation for all releases -- compatibility is also highly
- *  dependent on which HAL features are used.  Each release is usually
- *  backward compatible, with very few exceptions if any.]
- *
- *  Notes:
- *     Tornado 2.0 supported in T1020.3+, T1030.1+, and T1040.{0,1} only.
- *     Tornado 2.0.2 supported in T1040.2+, and T1050.
- *     Compile-time HAL port of NucleusPlus supported by T1040.2+ and T1050.
- */
-
-
-/*
- *  Architectural limits, independent of configuration.
- *  Note that these are ISA-defined limits, not micro-architecture implementation
- *  limits enforced by the Xtensa Processor Generator (which may be stricter than
- *  these below).
- */
-#define XTHAL_MAX_CPS          8       /* max number of coprocessors (0..7) */
-#define XTHAL_MAX_INTERRUPTS   32      /* max number of interrupts (0..31) */
-#define XTHAL_MAX_INTLEVELS    16      /* max number of interrupt levels (0..15) */
-                                       /* (as of T1040, implementation limit is 7: 0..6) */
-#define XTHAL_MAX_TIMERS       4       /* max number of timers (CCOMPARE0..CCOMPARE3) */
-                                       /* (as of T1040, implementation limit is 3: 0..2) */
-
-/*  Misc:  */
-#define XTHAL_LITTLEENDIAN             0
-#define XTHAL_BIGENDIAN                        1
-
-
-/*  Interrupt types:  */
-#define XTHAL_INTTYPE_UNCONFIGURED     0
-#define XTHAL_INTTYPE_SOFTWARE         1
-#define XTHAL_INTTYPE_EXTERN_EDGE      2
-#define XTHAL_INTTYPE_EXTERN_LEVEL     3
-#define XTHAL_INTTYPE_TIMER            4
-#define XTHAL_INTTYPE_NMI              5
-#define XTHAL_MAX_INTTYPES             6       /* number of interrupt types */
-
-/*  Timer related:  */
-#define XTHAL_TIMER_UNCONFIGURED       -1      /* Xthal_timer_interrupt[] value for non-existent timers */
-#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED        /* (for backwards compatibility only) */
-
-
-/*  Access Mode bits (tentative):  */  /* bit abbr unit short_name       PPC equ - Description */
-#define XTHAL_AMB_EXCEPTION    0       /* 001 E EX fls: EXception        none    - generate exception on any access (aka "illegal") */
-#define XTHAL_AMB_HITCACHE     1       /* 002 C CH fls: use Cache on Hit ~(I CI) - use cache on hit -- way from tag match [or H HC, or U UC] (ISA: same, except for Isolate case) */
-#define XTHAL_AMB_ALLOCATE     2       /* 004 A AL fl?: ALlocate         none    - refill cache on miss -- way from LRU [or F FI fill] (ISA: Read/Write Miss Refill) */
-#define XTHAL_AMB_WRITETHRU    3       /* 008 W WT --s: WriteThrough     W WT    - store immediately to memory (ISA: same) */
-#define XTHAL_AMB_ISOLATE      4       /* 010 I IS fls: ISolate          none    - use cache regardless of hit-vs-miss -- way from vaddr (ISA: use-cache-on-miss+hit) */
-#define XTHAL_AMB_GUARD                5       /* 020 G GU ?l?: GUard            G *     - non-speculative; spec/replay refs not permitted */
-#if 0
-#define XTHAL_AMB_ORDERED      x       /* 000 O OR fls: ORdered          G *     - mem accesses cannot be out of order */
-#define XTHAL_AMB_FUSEWRITES   x       /* 000 F FW --s: FuseWrites       none    - allow combining/merging multiple writes (to same datapath data unit) into one (implied by writeback) */
-#define XTHAL_AMB_COHERENT     x       /* 000 M MC fl?: Mem/MP Coherent  M       - on reads, other CPUs/bus-masters may need to supply data */
-#define XTHAL_AMB_TRUSTED      x       /* 000 T TR ?l?: TRusted          none    - memory will not bus error (if it does, handle as fatal imprecise interrupt) */
-#define XTHAL_AMB_PREFETCH     x       /* 000 P PR fl?: PRefetch         none    - on refill, read line+1 into prefetch buffers */
-#define XTHAL_AMB_STREAM       x       /* 000 S ST ???: STreaming        none    - access one of N stream buffers */
-#endif /*0*/
-
-#define XTHAL_AM_EXCEPTION     (1<<XTHAL_AMB_EXCEPTION)
-#define XTHAL_AM_HITCACHE      (1<<XTHAL_AMB_HITCACHE)
-#define XTHAL_AM_ALLOCATE      (1<<XTHAL_AMB_ALLOCATE)
-#define XTHAL_AM_WRITETHRU     (1<<XTHAL_AMB_WRITETHRU)
-#define XTHAL_AM_ISOLATE       (1<<XTHAL_AMB_ISOLATE)
-#define XTHAL_AM_GUARD         (1<<XTHAL_AMB_GUARD)
-#if 0
-#define XTHAL_AM_ORDERED       (1<<XTHAL_AMB_ORDERED)
-#define XTHAL_AM_FUSEWRITES    (1<<XTHAL_AMB_FUSEWRITES)
-#define XTHAL_AM_COHERENT      (1<<XTHAL_AMB_COHERENT)
-#define XTHAL_AM_TRUSTED       (1<<XTHAL_AMB_TRUSTED)
-#define XTHAL_AM_PREFETCH      (1<<XTHAL_AMB_PREFETCH)
-#define XTHAL_AM_STREAM                (1<<XTHAL_AMB_STREAM)
-#endif /*0*/
-
-/*
- *  Allowed Access Modes (bit combinations).
- *
- *  Columns are:
- *  "FOGIWACE"
- *     Access mode bits (see XTHAL_AMB_xxx above).
- *     <letter> = bit is set
- *     '-'      = bit is clear
- *     '.'      = bit is irrelevant / don't care, as follows:
- *                     E=1 makes all others irrelevant
- *                     W,F relevant only for stores
- *  "2345"
- *     Indicates which Xtensa releases support the corresponding
- *     access mode.  Releases for each character column are:
- *             2 = prior to T1020.2:   T1015 (V1.5), T1020.0, T1020.1
- *             3 = T1020.2 and later:  T1020.2+, T1030
- *             4 = T1040
- *             5 = T1050 (maybe)
- *     And the character column contents are:
- *             <number> = support by release(s)
- *             "." = unsupported by release(s)
- *             "?" = support unknown
- */
-                                       /* FOGIWACE 2345 */
-/*  For instruction fetch:  */
-#define XTHAL_FAM_EXCEPTION    0x001   /* .......E 2345 exception */
-#define XTHAL_FAM_ISOLATE      0x012   /* .--I.-C- .... isolate */
-#define XTHAL_FAM_BYPASS       0x000   /* .---.--- 2345 bypass */
-#define XTHAL_FAM_NACACHED     0x002   /* .---.-C- .... cached no-allocate (frozen) */
-#define XTHAL_FAM_CACHED       0x006   /* .---.AC- 2345 cached */
-/*  For data load:  */
-#define XTHAL_LAM_EXCEPTION    0x001   /* .......E 2345 exception */
-#define XTHAL_LAM_ISOLATE      0x012   /* .--I.-C- 2345 isolate */
-#define XTHAL_LAM_BYPASS       0x000   /* .O--.--- 2... bypass speculative */
-#define XTHAL_LAM_BYPASSG      0x020   /* .OG-.--- .345 bypass guarded */
-#define XTHAL_LAM_NACACHED     0x002   /* .O--.-C- 2... cached no-allocate speculative */
-#define XTHAL_LAM_NACACHEDG    0x022   /* .OG-.-C- .345 cached no-allocate guarded */
-#define XTHAL_LAM_CACHED       0x006   /* .---.AC- 2345 cached speculative */
-#define XTHAL_LAM_CACHEDG      0x026   /* .?G-.AC- .... cached guarded */
-/*  For data store:  */
-#define XTHAL_SAM_EXCEPTION    0x001   /* .......E 2345 exception */
-#define XTHAL_SAM_ISOLATE      0x032   /* .-GI--C- 2345 isolate */
-#define XTHAL_SAM_BYPASS       0x028   /* -OG-W--- 2345 bypass */
-/*efine XTHAL_SAM_BYPASSF      0x028*/ /* F-G-W--- ...? bypass write-combined */
-#define XTHAL_SAM_WRITETHRU    0x02A   /* -OG-W-C- 234? writethrough */
-/*efine XTHAL_SAM_WRITETHRUF   0x02A*/ /* F-G-W-C- ...5 writethrough write-combined */
-#define XTHAL_SAM_WRITEALLOC   0x02E   /* -OG-WAC- ...? writethrough-allocate */
-/*efine XTHAL_SAM_WRITEALLOCF  0x02E*/ /* F-G-WAC- ...? writethrough-allocate write-combined */
-#define XTHAL_SAM_WRITEBACK    0x026   /* F-G--AC- ...5 writeback */
-
-#if 0
-/*
-    Cache attribute encoding for CACHEATTR (per ISA):
-    (Note:  if this differs from ISA Ref Manual, ISA has precedence)
-
-       Inst-fetches    Loads           Stores
-       -------------   ------------    -------------
-0x0    FCA_EXCEPTION  ?LCA_NACACHED_G* SCA_WRITETHRU   "uncached"
-0x1    FCA_CACHED      LCA_CACHED      SCA_WRITETHRU   cached
-0x2    FCA_BYPASS      LCA_BYPASS_G*   SCA_BYPASS      bypass
-0x3    FCA_CACHED      LCA_CACHED      SCA_WRITEALLOCF write-allocate
-                    or LCA_EXCEPTION   SCA_EXCEPTION   (if unimplemented)
-0x4    FCA_CACHED      LCA_CACHED      SCA_WRITEBACK   write-back
-                    or LCA_EXCEPTION   SCA_EXCEPTION   (if unimplemented)
-0x5..D FCA_EXCEPTION   LCA_EXCEPTION   SCA_EXCEPTION   (reserved)
-0xE    FCA_EXCEPTION   LCA_ISOLATE     SCA_ISOLATE     isolate
-0xF    FCA_EXCEPTION   LCA_EXCEPTION   SCA_EXCEPTION   illegal
-     *  Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G)
-*/
-#endif /*0*/
-
-
-#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*----------------------------------------------------------------------
-                            HAL
-  ----------------------------------------------------------------------*/
-
-/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */
-extern const unsigned int Xthal_rev_no;
-
-
-/*----------------------------------------------------------------------
-                       Processor State
-  ----------------------------------------------------------------------*/
-/* save & restore the extra processor state */
-extern void xthal_save_extra(void *base);
-extern void xthal_restore_extra(void *base);
-
-extern void xthal_save_cpregs(void *base, int);
-extern void xthal_restore_cpregs(void *base, int);
-
-/*extern void xthal_save_all_extra(void *base);*/
-/*extern void xthal_restore_all_extra(void *base);*/
-
-/* space for processor state */
-extern const unsigned int Xthal_extra_size;
-extern const unsigned int Xthal_extra_align;
-/* space for TIE register files */
-extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS];
-extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS];
-
-/* total of space for the processor state (for Tor2) */
-extern const unsigned int Xthal_all_extra_size;
-extern const unsigned int Xthal_all_extra_align;
-
-/* initialize the extra processor */
-/*extern void xthal_init_extra(void);*/
-/* initialize the TIE coprocessor */
-/*extern void xthal_init_cp(int);*/
-
-/* initialize the extra processor */
-extern void xthal_init_mem_extra(void *);
-/* initialize the TIE coprocessor */
-extern void xthal_init_mem_cp(void *, int);
-
-/* validate & invalidate the TIE register file */
-extern void xthal_validate_cp(int);
-extern void xthal_invalidate_cp(int);
-
-/* the number of TIE coprocessors contiguous from zero (for Tor2) */
-extern const unsigned int Xthal_num_coprocessors;
-
-/* actual number of coprocessors */
-extern const unsigned char Xthal_cp_num;
-/* index of highest numbered coprocessor, plus one */
-extern const unsigned char Xthal_cp_max;
-/* index of highest allowed coprocessor number, per cfg, plus one */
-/*extern const unsigned char Xthal_cp_maxcfg;*/
-/* bitmask of which coprocessors are present */
-extern const unsigned int  Xthal_cp_mask;
-
-/* read and write cpenable register */
-extern void xthal_set_cpenable(unsigned);
-extern unsigned xthal_get_cpenable(void);
-
-/* read & write extra state register */
-/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/
-/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/
-
-/* read & write a TIE coprocessor register */
-/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/
-/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/
-
-/* return coprocessor number based on register */
-/*extern int xthal_which_cp(unsigned reg);*/
-
-/*----------------------------------------------------------------------
-                               Interrupts
-  ----------------------------------------------------------------------*/
-
-/* the number of interrupt levels */
-extern const unsigned char Xthal_num_intlevels;
-/* the number of interrupts */
-extern const unsigned char Xthal_num_interrupts;
-
-/* mask for level of interrupts */
-extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS];
-/* mask for level 0 to N interrupts */
-extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS];
-
-/* level of each interrupt */
-extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS];
-
-/* type per interrupt */
-extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS];
-
-/* masks of each type of interrupt */
-extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES];
-
-/* interrupt numbers assigned to each timer interrupt */
-extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS];
-
-/***  Virtual interrupt prioritization:  ***/
-
-/*  Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities:  */
-extern unsigned        xthal_vpri_to_intlevel(unsigned vpri);
-extern unsigned        xthal_intlevel_to_vpri(unsigned intlevel);
-
-/*  Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints:  */
-extern unsigned        xthal_int_enable(unsigned);
-extern unsigned        xthal_int_disable(unsigned);
-
-/*  Set/get virtual priority of an interrupt:  */
-extern int     xthal_set_int_vpri(int intnum, int vpri);
-extern int     xthal_get_int_vpri(int intnum);
-
-/*  Set/get interrupt lockout level for exclusive access to virtual priority data structures:  */
-extern void    xthal_set_vpri_locklevel(unsigned intlevel);
-extern unsigned        xthal_get_vpri_locklevel(void);
-
-/*  Set/get current virtual interrupt priority:  */
-extern unsigned        xthal_set_vpri(unsigned vpri);
-extern unsigned        xthal_get_vpri(unsigned vpri);
-extern unsigned        xthal_set_vpri_intlevel(unsigned intlevel);
-extern unsigned        xthal_set_vpri_lock(void);
-
-
-
-/*----------------------------------------------------------------------
-                       Generic Interrupt Trampolining Support
-  ----------------------------------------------------------------------*/
-
-typedef void (XtHalVoidFunc)(void);
-
-/*
- *  Bitmask of interrupts currently trampolining down:
- */
-extern unsigned Xthal_tram_pending;
-
-/*
- *  Bitmask of which interrupts currently trampolining down
- *  synchronously are actually enabled; this bitmask is necessary
- *  because INTENABLE cannot hold that state (sync-trampolining
- *  interrupts must be kept disabled while trampolining);
- *  in the current implementation, any bit set here is not set
- *  in INTENABLE, and vice-versa; once a sync-trampoline is
- *  handled (at level one), its enable bit must be moved from
- *  here to INTENABLE:
- */
-extern unsigned Xthal_tram_enabled;
-
-/*
- *  Bitmask of interrupts configured for sync trampolining:
- */
-extern unsigned Xthal_tram_sync;
-
-
-/*  Trampoline support functions:  */
-extern unsigned  xthal_tram_pending_to_service( void );
-extern void      xthal_tram_done( unsigned serviced_mask );
-extern int       xthal_tram_set_sync( int intnum, int sync );
-extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn );
-
-/*  INTENABLE,INTREAD,INTSET,INTCLEAR register access functions:  */
-extern unsigned  xthal_get_intenable( void );
-extern void      xthal_set_intenable( unsigned );
-extern unsigned  xthal_get_intread( void );
-extern void      xthal_set_intset( unsigned );
-extern void      xthal_set_intclear( unsigned );
-
-
-/*----------------------------------------------------------------------
-                               Register Windows
-  ----------------------------------------------------------------------*/
-
-/* number of registers in register window */
-extern const unsigned int  Xthal_num_aregs;
-extern const unsigned char Xthal_num_aregs_log2;
-
-/*  This spill any live register windows (other than the caller's):  */
-extern void      xthal_window_spill( void );
-
-
-/*----------------------------------------------------------------------
-                               Cache
-  ----------------------------------------------------------------------*/
-
-/* size of the cache lines in log2(bytes) */
-extern const unsigned char Xthal_icache_linewidth;
-extern const unsigned char Xthal_dcache_linewidth;
-/* size of the cache lines in bytes */
-extern const unsigned short Xthal_icache_linesize;
-extern const unsigned short Xthal_dcache_linesize;
-/* number of cache sets in log2(lines per way) */
-extern const unsigned char Xthal_icache_setwidth;
-extern const unsigned char Xthal_dcache_setwidth;
-/* cache set associativity (number of ways) */
-extern const unsigned int  Xthal_icache_ways;
-extern const unsigned int  Xthal_dcache_ways;
-/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */
-extern const unsigned int  Xthal_icache_size;
-extern const unsigned int  Xthal_dcache_size;
-/* cache features */
-extern const unsigned char Xthal_dcache_is_writeback;
-extern const unsigned char Xthal_icache_line_lockable;
-extern const unsigned char Xthal_dcache_line_lockable;
-
-/* cache attribute register control (used by other HAL routines) */
-extern unsigned xthal_get_cacheattr( void );
-extern unsigned xthal_get_icacheattr( void );
-extern unsigned xthal_get_dcacheattr( void );
-extern void     xthal_set_cacheattr( unsigned );
-extern void     xthal_set_icacheattr( unsigned );
-extern void     xthal_set_dcacheattr( unsigned );
-
-/* initialize cache support (must be called once at startup, before all other cache calls) */
-/*extern void xthal_cache_startinit( void );*/
-/* reset caches */
-/*extern void xthal_icache_reset( void );*/
-/*extern void xthal_dcache_reset( void );*/
-/* enable caches */
-extern void xthal_icache_enable( void );       /* DEPRECATED */
-extern void xthal_dcache_enable( void );       /* DEPRECATED */
-/* disable caches */
-extern void xthal_icache_disable( void );      /* DEPRECATED */
-extern void xthal_dcache_disable( void );      /* DEPRECATED */
-
-/* invalidate the caches */
-extern void xthal_icache_all_invalidate( void );
-extern void xthal_dcache_all_invalidate( void );
-extern void xthal_icache_region_invalidate( void *addr, unsigned size );
-extern void xthal_dcache_region_invalidate( void *addr, unsigned size );
-extern void xthal_icache_line_invalidate(void *addr);
-extern void xthal_dcache_line_invalidate(void *addr);
-/* write dirty data back */
-extern void xthal_dcache_all_writeback( void );
-extern void xthal_dcache_region_writeback( void *addr, unsigned size );
-extern void xthal_dcache_line_writeback(void *addr);
-/* write dirty data back and invalidate */
-extern void xthal_dcache_all_writeback_inv( void );
-extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size );
-extern void xthal_dcache_line_writeback_inv(void *addr);
-/* prefetch and lock specified memory range into cache */
-extern void xthal_icache_region_lock( void *addr, unsigned size );
-extern void xthal_dcache_region_lock( void *addr, unsigned size );
-extern void xthal_icache_line_lock(void *addr);
-extern void xthal_dcache_line_lock(void *addr);
-/* unlock from cache */
-extern void xthal_icache_all_unlock( void );
-extern void xthal_dcache_all_unlock( void );
-extern void xthal_icache_region_unlock( void *addr, unsigned size );
-extern void xthal_dcache_region_unlock( void *addr, unsigned size );
-extern void xthal_icache_line_unlock(void *addr);
-extern void xthal_dcache_line_unlock(void *addr);
-
-
-/* sync icache and memory */
-extern void xthal_icache_sync( void );
-/* sync dcache and memory */
-extern void xthal_dcache_sync( void );
-
-/*----------------------------------------------------------------------
-                               Debug
-  ----------------------------------------------------------------------*/
-
-/*  1 if debug option configured, 0 if not:  */
-extern const int Xthal_debug_configured;
-
-/*  Number of instruction and data break registers:  */
-extern const int Xthal_num_ibreak;
-extern const int Xthal_num_dbreak;
-
-/*  Set (plant) and remove software breakpoint, both synchronizing cache:  */
-extern unsigned int xthal_set_soft_break(void *addr);
-extern void         xthal_remove_soft_break(void *addr, unsigned int);
-
-
-/*----------------------------------------------------------------------
-                               Disassembler
-  ----------------------------------------------------------------------*/
-
-/*  Max expected size of the return buffer for a disassembled instruction (hint only):  */
-#define XTHAL_DISASM_BUFSIZE   80
-
-/*  Disassembly option bits for selecting what to return:  */
-#define XTHAL_DISASM_OPT_ADDR  0x0001  /* display address */
-#define XTHAL_DISASM_OPT_OPHEX 0x0002  /* display opcode bytes in hex */
-#define XTHAL_DISASM_OPT_OPCODE        0x0004  /* display opcode name (mnemonic) */
-#define XTHAL_DISASM_OPT_PARMS 0x0008  /* display parameters */
-#define XTHAL_DISASM_OPT_ALL   0x0FFF  /* display everything */
-
-/* routine to get a string for the disassembled instruction */
-extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr,
-                      char *buffer, unsigned buflen, unsigned options );
-
-/* routine to get the size of the next instruction. Returns 0 for
-   illegal instruction */
-extern int xthal_disassemble_size( unsigned char *instr_buf );
-
-
-/*----------------------------------------------------------------------
-                               Core Counter
-  ----------------------------------------------------------------------*/
-
-/* counter info */
-extern const unsigned char Xthal_have_ccount;  /* set if CCOUNT register present */
-extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */
-
-/* get CCOUNT register (if not present return 0) */
-extern unsigned xthal_get_ccount(void);
-
-/* set and get CCOMPAREn registers (if not present, get returns 0) */
-extern void     xthal_set_ccompare(int, unsigned);
-extern unsigned xthal_get_ccompare(int);
-
-
-/*----------------------------------------------------------------------
-                       Instruction/Data RAM/ROM Access
-  ----------------------------------------------------------------------*/
-
-extern void* xthal_memcpy(void *dst, const void *src, unsigned len);
-extern void* xthal_bcopy(const void *src, void *dst, unsigned len);
-
-/*----------------------------------------------------------------------
-                           MP Synchronization
-  ----------------------------------------------------------------------*/
-extern int      xthal_compare_and_set( int *addr, int test_val, int compare_val );
-extern unsigned xthal_get_prid( void );
-
-/*extern const char  Xthal_have_s32c1i;*/
-extern const unsigned char Xthal_have_prid;
-
-
-/*----------------------------------------------------------------------
-                             Miscellaneous
-  ----------------------------------------------------------------------*/
-
-extern const unsigned int  Xthal_release_major;
-extern const unsigned int  Xthal_release_minor;
-extern const char * const  Xthal_release_name;
-extern const char * const  Xthal_release_internal;
-
-extern const unsigned char Xthal_memory_order;
-extern const unsigned char Xthal_have_windowed;
-extern const unsigned char Xthal_have_density;
-extern const unsigned char Xthal_have_booleans;
-extern const unsigned char Xthal_have_loops;
-extern const unsigned char Xthal_have_nsa;
-extern const unsigned char Xthal_have_minmax;
-extern const unsigned char Xthal_have_sext;
-extern const unsigned char Xthal_have_clamps;
-extern const unsigned char Xthal_have_mac16;
-extern const unsigned char Xthal_have_mul16;
-extern const unsigned char Xthal_have_fp;
-extern const unsigned char Xthal_have_speculation;
-extern const unsigned char Xthal_have_exceptions;
-extern const unsigned char Xthal_xea_version;
-extern const unsigned char Xthal_have_interrupts;
-extern const unsigned char Xthal_have_highlevel_interrupts;
-extern const unsigned char Xthal_have_nmi;
-
-extern const unsigned short Xthal_num_writebuffer_entries;
-
-extern const unsigned int  Xthal_build_unique_id;
-/*  Release info for hardware targeted by software upgrades:  */
-extern const unsigned int  Xthal_hw_configid0;
-extern const unsigned int  Xthal_hw_configid1;
-extern const unsigned int  Xthal_hw_release_major;
-extern const unsigned int  Xthal_hw_release_minor;
-extern const char * const  Xthal_hw_release_name;
-extern const char * const  Xthal_hw_release_internal;
-
-
-/*  Internal memories...  */
-
-extern const unsigned char Xthal_num_instrom;
-extern const unsigned char Xthal_num_instram;
-extern const unsigned char Xthal_num_datarom;
-extern const unsigned char Xthal_num_dataram;
-extern const unsigned char Xthal_num_xlmi;
-extern const unsigned int  Xthal_instrom_vaddr[1];
-extern const unsigned int  Xthal_instrom_paddr[1];
-extern const unsigned int  Xthal_instrom_size [1];
-extern const unsigned int  Xthal_instram_vaddr[1];
-extern const unsigned int  Xthal_instram_paddr[1];
-extern const unsigned int  Xthal_instram_size [1];
-extern const unsigned int  Xthal_datarom_vaddr[1];
-extern const unsigned int  Xthal_datarom_paddr[1];
-extern const unsigned int  Xthal_datarom_size [1];
-extern const unsigned int  Xthal_dataram_vaddr[1];
-extern const unsigned int  Xthal_dataram_paddr[1];
-extern const unsigned int  Xthal_dataram_size [1];
-extern const unsigned int  Xthal_xlmi_vaddr[1];
-extern const unsigned int  Xthal_xlmi_paddr[1];
-extern const unsigned int  Xthal_xlmi_size [1];
-
-
-
-/*----------------------------------------------------------------------
-                         Memory Management Unit
-  ----------------------------------------------------------------------*/
-
-extern const unsigned char Xthal_have_spanning_way;
-extern const unsigned char Xthal_have_identity_map;
-extern const unsigned char Xthal_have_mimic_cacheattr;
-extern const unsigned char Xthal_have_xlt_cacheattr;
-extern const unsigned char Xthal_have_cacheattr;
-extern const unsigned char Xthal_have_tlbs;
-
-extern const unsigned char Xthal_mmu_asid_bits;                /* 0 .. 8 */
-extern const unsigned char Xthal_mmu_asid_kernel;
-extern const unsigned char Xthal_mmu_rings;            /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */
-extern const unsigned char Xthal_mmu_ring_bits;
-extern const unsigned char Xthal_mmu_sr_bits;
-extern const unsigned char Xthal_mmu_ca_bits;
-extern const unsigned int  Xthal_mmu_max_pte_page_size;
-extern const unsigned int  Xthal_mmu_min_pte_page_size;
-
-extern const unsigned char Xthal_itlb_way_bits;
-extern const unsigned char Xthal_itlb_ways;
-extern const unsigned char Xthal_itlb_arf_ways;
-extern const unsigned char Xthal_dtlb_way_bits;
-extern const unsigned char Xthal_dtlb_ways;
-extern const unsigned char Xthal_dtlb_arf_ways;
-
-/*  Convert between virtual and physical addresses (through static maps only):  */
-/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/
-extern int  xthal_static_v2p( unsigned vaddr, unsigned *paddrp );
-extern int  xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached );
-
-#if 0
-/*******************   EXPERIMENTAL AND TENTATIVE ONLY   ********************/
-
-#define XTHAL_MMU_PAGESZ_COUNT_MAX     8       /* maximum number of different page sizes */
-extern const char      Xthal_mmu_pagesz_count;         /* 0 .. 8               number of different page sizes configured */
-
-/*  Note:  the following table doesn't necessarily have page sizes in increasing order: */
-extern const char      Xthal_mmu_pagesz_log2[XTHAL_MMU_PAGESZ_COUNT_MAX];      /* 10 .. 28 (0 past count) */
-
-/*  Sorted (increasing) table of page sizes, that indexes into the above table: */
-extern const char      Xthal_mmu_pagesz_sorted[XTHAL_MMU_PAGESZ_COUNT_MAX];    /* 0 .. 7 (0 past count) */
-
-/*u32  Xthal_virtual_exceptions;*/     /* bitmask of which exceptions execute in virtual mode... */
-
-extern const char      Xthal_mmu_pte_pagesz_log2_min;  /* ?? minimum page size in PTEs */
-extern const char      Xthal_mmu_pte_pagesz_log2_max;  /* ?? maximum page size in PTEs */
-
-/*  Cache Attribute Bits Implemented by the Cache (part of the cache abstraction) */
-extern const char      Xthal_icache_fca_bits_implemented;      /* ITLB/UTLB only! */
-extern const char      Xthal_dcache_lca_bits_implemented;      /* DTLB/UTLB only! */
-extern const char      Xthal_dcache_sca_bits_implemented;      /* DTLB/UTLB only! */
-
-/*  Per TLB Parameters (Instruction, Data, Unified)  */
-struct XtHalMmuTlb     Xthal_itlb;     /* description of MMU I-TLB generic features */
-struct XtHalMmuTlb     Xthal_dtlb;     /* description of MMU D-TLB generic features */
-struct XtHalMmuTlb     Xthal_utlb;     /* description of MMU U-TLB generic features */
-
-#define XTHAL_MMU_WAYS_MAX     8       /* maximum number of ways (associativities) for each TLB */
-
-/*  Structure for common information described for each possible TLB (instruction, data and unified): */
-typedef struct XtHalMmuTlb {
-    u8         va_bits;                /* 32           (number of virtual address bits) */
-    u8         pa_bits;                /* 32           (number of physical address bits) */
-    bool       tlb_va_indexed;         /* 1    (set if TLB is indexed by virtual address) */
-    bool       tlb_va_tagged;          /* 0    (set if TLB is tagged by virtual address) */
-    bool       cache_va_indexed;       /* 1    (set if cache is indexed by virtual address) */
-    bool       cache_va_tagged;        /* 0    (set if cache is tagged by virtual address) */
-    /*bool     (whether page tables are traversed in vaddr sorted order, paddr sorted order, ...) */
-    /*u8       (set of available page attribute bits, other than cache attribute bits defined above) */
-    /*u32      (various masks for pages, MMU table/TLB entries, etc.) */
-    u8         way_count;              /* 0 .. 8       (number of ways, a.k.a. associativities, for this TLB) */
-    XtHalMmuTlbWay *   ways[XTHAL_MMU_WAYS_MAX];       /* pointers to per-way parms for each way */
-} XtHalMmuTlb;
-
-/*  Per TLB Way (Per Associativity) Parameters  */
-typedef struct XtHalMmuTlbWay {
-     u32       index_count_log2;       /* 0 .. 4 */
-     u32       pagesz_mask;            /* 0 .. 2^pagesz_count - 1      (each bit corresponds to a size */
-                                       /*              defined in the Xthal_mmu_pagesz_log2[] table) */
-     u32       vpn_const_mask;
-     u32       vpn_const_value;
-     u64       ppn_const_mask;         /* future may support pa_bits > 32 */
-     u64       ppn_const_value;
-     u32       ppn_id_mask;            /* paddr bits taken directly from vaddr */
-     bool      backgnd_match;          /* 0 or 1 */
-     /*  These are defined in terms of the XTHAL_CACHE_xxx bits: */
-     u8        fca_const_mask;         /* ITLB/UTLB only! */
-     u8        fca_const_value;        /* ITLB/UTLB only! */
-     u8        lca_const_mask;         /* DTLB/UTLB only! */
-     u8        lca_const_value;        /* DTLB/UTLB only! */
-     u8        sca_const_mask;         /* DTLB/UTLB only! */
-     u8        sca_const_value;        /* DTLB/UTLB only! */
-     /*  These define an encoding that map 5 bits in TLB and PTE entries to */
-     /*  8 bits (FCA, ITLB), 16 bits (LCA+SCA, DTLB) or 24 bits (FCA+LCA+SCA, UTLB): */
-     /*  (they may be moved to struct XtHalMmuTlb) */
-     u8                ca_bits;                /* number of bits in TLB/PTE entries for cache attributes */
-     u32 *     ca_map;                 /* pointer to array of 2^ca_bits entries of FCA+LCA+SCA bits */
-} XtHalMmuTlbWay;
-
-/*
- *  The way to determine whether protection support is present in core
- *  is to [look at Xthal_mmu_rings ???].
- *  Give info on memory requirements for MMU tables and other in-memory
- *  data structures (globally, per task, base and per page, etc.) - whatever bounds can be calculated.
- */
-
-
-/*  Default vectors:  */
-xthal_immu_fetch_miss_vector
-xthal_dmmu_load_miss_vector
-xthal_dmmu_store_miss_vector
-
-/*  Functions called when a fault is detected:  */
-typedef void (XtHalMmuFaultFunc)( unsigned vaddr, ...context... );
-/*  Or, */
-/*     a? = vaddr */
-/*     a? = context... */
-/*     PS.xxx = xxx */
-XtHalMMuFaultFunc *Xthal_immu_fetch_fault_func;
-XtHalMMuFaultFunc *Xthal_dmmu_load_fault_func;
-XtHalMMuFaultFunc *Xthal_dmmu_store_fault_func;
-
-/*  Default Handlers:  */
-/*  The user and/or kernel exception handlers may jump to these handlers to handle the relevant exceptions,
- *  according to the value of EXCCAUSE.  The exact register state on entry to these handlers is TBD.  */
-/*  When multiple TLB entries match (hit) on the same access:  */
-xthal_immu_fetch_multihit_handler
-xthal_dmmu_load_multihit_handler
-xthal_dmmu_store_multihit_handler
-/*  Protection violations according to cache attributes, and other cache attribute mismatches:  */
-xthal_immu_fetch_attr_handler
-xthal_dmmu_load_attr_handler
-xthal_dmmu_store_attr_handler
-/*  Protection violations due to insufficient ring level:  */
-xthal_immu_fetch_priv_handler
-xthal_dmmu_load_priv_handler
-xthal_dmmu_store_priv_handler
-/*  Alignment exception handlers (if supported by the particular Xtensa MMU configuration):  */
-xthal_dmmu_load_align_handler
-xthal_dmmu_store_align_handler
-
-/*  Or, alternatively, the OS user and/or kernel exception handlers may simply jump to the
- *  following entry points which will handle any values of EXCCAUSE not handled by the OS:  */
-xthal_user_exc_default_handler
-xthal_kernel_exc_default_handler
-
-#endif /*0*/
-
-#ifdef INCLUDE_DEPRECATED_HAL_CODE
-extern const unsigned char Xthal_have_old_exc_arch;
-extern const unsigned char Xthal_have_mmu;
-extern const unsigned int  Xthal_num_regs;
-extern const unsigned char Xthal_num_iroms;
-extern const unsigned char Xthal_num_irams;
-extern const unsigned char Xthal_num_droms;
-extern const unsigned char Xthal_num_drams;
-extern const unsigned int  Xthal_configid0;
-extern const unsigned int  Xthal_configid1;
-#endif
-
-#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
-#define XTHAL_24_BIT_BREAK             0x80000000
-#define XTHAL_16_BIT_BREAK             0x40000000
-extern const unsigned short    Xthal_ill_inst_16[16];
-#define XTHAL_DEST_REG         0xf0000000      /* Mask for destination register */
-#define XTHAL_DEST_REG_INST    0x08000000      /* Branch address is in register */
-#define XTHAL_DEST_REL_INST    0x04000000      /* Branch address is relative */
-#define XTHAL_RFW_INST         0x00000800
-#define XTHAL_RFUE_INST                0x00000400
-#define XTHAL_RFI_INST         0x00000200
-#define XTHAL_RFE_INST         0x00000100
-#define XTHAL_RET_INST         0x00000080
-#define XTHAL_BREAK_INST       0x00000040
-#define XTHAL_SYSCALL_INST     0x00000020
-#define XTHAL_LOOP_END         0x00000010      /* Not set by xthal_inst_type */
-#define XTHAL_JUMP_INST                0x00000008      /* Call or jump instruction */
-#define XTHAL_BRANCH_INST      0x00000004      /* Branch instruction */
-#define XTHAL_24_BIT_INST      0x00000002
-#define XTHAL_16_BIT_INST   0x00000001
-typedef struct xthal_state {
-    unsigned   pc;
-    unsigned   ar[16];
-    unsigned   lbeg;
-    unsigned   lend;
-    unsigned   lcount;
-    unsigned   extra_ptr;
-    unsigned   cpregs_ptr[XTHAL_MAX_CPS];
-} XTHAL_STATE;
-extern unsigned int xthal_inst_type(void *addr);
-extern unsigned int xthal_branch_addr(void *addr);
-extern unsigned int xthal_get_npc(XTHAL_STATE *user_state);
-#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /*!__ASSEMBLY__ */
-
-#endif /*XTENSA_HAL_H*/
-
diff --git a/include/asm-xtensa/xtensa/simcall.h b/include/asm-xtensa/xtensa/simcall.h
deleted file mode 100644 (file)
index a2b8689..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#ifndef SIMCALL_INCLUDED
-#define SIMCALL_INCLUDED
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/simcall.h  -  Simulator call numbers
- *
- * 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) 2002 Tensilica Inc.
- */
-
-
-/*
- *  System call like services offered by the simulator host.
- *  These are modeled after the Linux 2.4 kernel system calls
- *  for Xtensa processors.  However not all system calls and
- *  not all functionality of a given system call are implemented,
- *  or necessarily have well defined or equivalent semantics in
- *  the context of a simulation (as opposed to a Unix kernel).
- *
- *  These services behave largely as if they had been invoked
- *  as a task in the simulator host's operating system
- *  (eg. files accessed are those of the simulator host).
- *  However, these SIMCALLs model a virtual operating system
- *  so that various definitions, bit assignments etc
- *  (eg. open mode bits, errno values, etc) are independent
- *  of the host operating system used to run the simulation.
- *  Rather these definitions are specific to the Xtensa ISS.
- *  This way Xtensa ISA code written to use these SIMCALLs
- *  can (in principle) be simulated on any host.
- *
- *  Up to 6 parameters are passed in registers a3 to a8
- *  (note the 6th parameter isn't passed on the stack,
- *   unlike windowed function calling conventions).
- *  The return value is in a2.  A negative value in the
- *  range -4096 to -1 indicates a negated error code to be
- *  reported in errno with a return value of -1, otherwise
- *  the value in a2 is returned as is.
- */
-
-/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */
-
-#define SYS_nop                0       /* n/a - setup; used to flush register windows */
-#define SYS_exit       1       /*x*/
-#define SYS_fork       2
-#define SYS_read       3       /*x*/
-#define SYS_write      4       /*x*/
-#define SYS_open       5       /*x*/
-#define SYS_close      6       /*x*/
-#define SYS_rename     7       /*x 38 - waitpid */
-#define SYS_creat      8       /*x*/
-#define SYS_link       9       /*x (not implemented on WIN32) */
-#define SYS_unlink     10      /*x*/
-#define SYS_execv      11      /* n/a - execve */
-#define SYS_execve     12      /* 11 - chdir */
-#define SYS_pipe       13      /* 42 - time */
-#define SYS_stat       14      /* 106 - mknod */
-#define SYS_chmod      15
-#define SYS_chown      16      /* 202 - lchown */
-#define SYS_utime      17      /* 30 - break */
-#define SYS_wait       18      /* n/a - oldstat */
-#define SYS_lseek      19      /*x*/
-#define SYS_getpid     20
-#define SYS_isatty     21      /* n/a - mount */
-#define SYS_fstat      22      /* 108 - oldumount */
-#define SYS_time       23      /* 13 - setuid */
-#define SYS_gettimeofday 24    /*x 78 - getuid (not implemented on WIN32) */
-#define SYS_times      25      /*X 43 - stime (Xtensa-specific implementation) */
-#define SYS_socket      26
-#define SYS_sendto      27
-#define SYS_recvfrom    28
-#define SYS_select_one  29      /* not compitible select, one file descriptor at the time */
-#define SYS_bind        30
-#define SYS_ioctl      31
-
-/*
- *  Other...
- */
-#define SYS_iss_argc      1000 /* returns value of argc */
-#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */
-#define SYS_iss_set_argv  1002 /* saves argv & arg strings at given addr */
-
-/*
- * SIMCALLs for the ferret memory debugger. All are invoked by
- * libferret.a ...  ( Xtensa/Target-Libs/ferret )
- */
-#define SYS_ferret           1010
-#define SYS_malloc           1011
-#define SYS_free             1012
-#define SYS_more_heap        1013
-#define SYS_no_heap          1014
-
-
-/*
- *  Extra SIMCALLs for GDB:
- */
-#define SYS_gdb_break         -1       /* invoked by XTOS on user exceptions if EPC points
-                                          to a break.n/break, regardless of cause! */
-#define SYS_xmon_out          -2       /* invoked by XMON: ... */
-#define SYS_xmon_in           -3       /* invoked by XMON: ... */
-#define SYS_xmon_flush        -4       /* invoked by XMON: ... */
-#define SYS_gdb_abort         -5       /* invoked by XTOS in _xtos_panic() */
-#define SYS_gdb_illegal_inst  -6       /* invoked by XTOS for illegal instructions (too deeply) */
-#define SYS_xmon_init         -7       /* invoked by XMON: ... */
-#define SYS_gdb_enter_sktloop -8       /* invoked by XTOS on debug exceptions */
-
-/*
- *  SIMCALLs for vxWorks xtiss BSP:
- */
-#define SYS_setup_ppp_pipes   -83
-#define SYS_log_msg           -84
-
-/*
- *  Test SIMCALLs:
- */
-#define SYS_test_write_state  -100
-#define SYS_test_read_state   -101
-
-/*
- * SYS_select_one specifiers
- */
-#define  XTISS_SELECT_ONE_READ    1
-#define  XTISS_SELECT_ONE_WRITE   2
-#define  XTISS_SELECT_ONE_EXCEPT  3
-
-#endif /* !SIMCALL_INCLUDED */
diff --git a/include/asm-xtensa/xtensa/xt2000-uart.h b/include/asm-xtensa/xtensa/xt2000-uart.h
deleted file mode 100644 (file)
index 0154460..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef _uart_h_included_
-#define _uart_h_included_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/xt2000-uart.h -- NatSemi PC16552D DUART
- * definitions
- *
- * 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) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/xt2000.h>
-
-
-/* 16550 UART DEVICE REGISTERS
-   The XT2000 board aligns each register to a 32-bit word but the UART device only uses
-   one byte of the word, which is the least-significant byte regardless of the
-   endianness of the core (ie. byte offset 0 for little-endian and 3 for big-endian).
-   So if using word accesses then endianness doesn't matter.
-   The macros provided here do that.
-*/
-struct uart_dev_s {
-  union {
-    unsigned int rxb;  /* DLAB=0: receive buffer, read-only */
-    unsigned int txb;  /* DLAB=0: transmit buffer, write-only */
-    unsigned int dll;  /* DLAB=1: divisor, least-significant byte latch (was write-only?) */
-  } w0;
-  union {
-    unsigned int ier;  /* DLAB=0: interrupt-enable register (was write-only?) */
-    unsigned int dlm;  /* DLAB=1: divisor, most-significant byte latch (was write-only?) */
-  } w1;
-
-  union {
-    unsigned int isr;  /* DLAB=0: interrupt status register, read-only */
-    unsigned int fcr;  /* DLAB=0: FIFO control register, write-only */
-    unsigned int afr;  /* DLAB=1: alternate function register */
-  } w2;
-
-  unsigned int lcr;    /* line control-register, write-only */
-  unsigned int mcr;    /* modem control-regsiter, write-only */
-  unsigned int lsr;    /* line status register, read-only */
-  unsigned int msr;    /* modem status register, read-only */
-  unsigned int scr;    /* scratch regsiter, read/write */
-};
-
-#define _RXB(u) ((u)->w0.rxb)
-#define _TXB(u) ((u)->w0.txb)
-#define _DLL(u) ((u)->w0.dll)
-#define _IER(u) ((u)->w1.ier)
-#define _DLM(u) ((u)->w1.dlm)
-#define _ISR(u) ((u)->w2.isr)
-#define _FCR(u) ((u)->w2.fcr)
-#define _AFR(u) ((u)->w2.afr)
-#define _LCR(u) ((u)->lcr)
-#define _MCR(u) ((u)->mcr)
-#define _LSR(u) ((u)->lsr)
-#define _MSR(u) ((u)->msr)
-#define _SCR(u) ((u)->scr)
-
-typedef volatile struct uart_dev_s uart_dev_t;
-
-/* IER bits */
-#define RCVR_DATA_REG_INTENABLE 0x01
-#define XMIT_HOLD_REG_INTENABLE    0x02
-#define RCVR_STATUS_INTENABLE   0x04
-#define MODEM_STATUS_INTENABLE     0x08
-
-/* FCR bits */
-#define _FIFO_ENABLE      0x01
-#define RCVR_FIFO_RESET  0x02
-#define XMIT_FIFO_RESET  0x04
-#define DMA_MODE_SELECT  0x08
-#define RCVR_TRIGGER_LSB 0x40
-#define RCVR_TRIGGER_MSB 0x80
-
-/* AFR bits */
-#define AFR_CONC_WRITE 0x01
-#define AFR_BAUDOUT_SEL        0x02
-#define AFR_RXRDY_SEL  0x04
-
-/* ISR bits */
-#define INT_STATUS(r)   ((r)&1)
-#define INT_PRIORITY(r) (((r)>>1)&0x7)
-
-/* LCR bits */
-#define WORD_LENGTH(n)  (((n)-5)&0x3)
-#define STOP_BIT_ENABLE 0x04
-#define PARITY_ENABLE   0x08
-#define EVEN_PARITY     0x10
-#define FORCE_PARITY    0x20
-#define XMIT_BREAK      0x40
-#define DLAB_ENABLE     0x80
-
-/* MCR bits */
-#define _DTR 0x01
-#define _RTS 0x02
-#define _OP1 0x04
-#define _OP2 0x08
-#define LOOP_BACK 0x10
-
-/* LSR Bits */
-#define RCVR_DATA_READY 0x01
-#define OVERRUN_ERROR   0x02
-#define PARITY_ERROR    0x04
-#define FRAMING_ERROR   0x08
-#define BREAK_INTERRUPT 0x10
-#define XMIT_HOLD_EMPTY 0x20
-#define XMIT_EMPTY      0x40
-#define FIFO_ERROR      0x80
-#define RCVR_READY(u)   (_LSR(u)&RCVR_DATA_READY)
-#define XMIT_READY(u)   (_LSR(u)&XMIT_HOLD_EMPTY)
-
-/* MSR bits */
-#define _RDR       0x01
-#define DELTA_DSR 0x02
-#define DELTA_RI  0x04
-#define DELTA_CD  0x08
-#define _CTS       0x10
-#define _DSR       0x20
-#define _RI        0x40
-#define _CD        0x80
-
-/* prototypes */
-void uart_init( uart_dev_t *u, int bitrate );
-void uart_out( uart_dev_t *u, char c );
-void uart_puts( uart_dev_t *u, char *s );
-char uart_in( uart_dev_t *u );
-void uart_enable_rcvr_int( uart_dev_t *u );
-void uart_disable_rcvr_int( uart_dev_t *u );
-
-#ifdef DUART16552_1_VADDR
-/*  DUART present.  */
-#define DUART_1_BASE   (*(uart_dev_t*)DUART16552_1_VADDR)
-#define DUART_2_BASE   (*(uart_dev_t*)DUART16552_2_VADDR)
-#define UART1_PUTS(s)  uart_puts( &DUART_1_BASE, s )
-#define UART2_PUTS(s)  uart_puts( &DUART_2_BASE, s )
-#else
-/*  DUART not configured, use dummy placeholders to allow compiles to work.  */
-#define DUART_1_BASE   (*(uart_dev_t*)0)
-#define DUART_2_BASE   (*(uart_dev_t*)0)
-#define UART1_PUTS(s)
-#define UART2_PUTS(s)
-#endif
-
-/*  Compute 16-bit divisor for baudrate generator, with rounding:  */
-#define DUART_DIVISOR(crystal,speed)   (((crystal)/16 + (speed)/2)/(speed))
-
-#endif /*_uart_h_included_*/
-
diff --git a/include/asm-xtensa/xtensa/xt2000.h b/include/asm-xtensa/xtensa/xt2000.h
deleted file mode 100644 (file)
index 703a450..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-#ifndef _INC_XT2000_H_
-#define _INC_XT2000_H_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/xt2000.h - Definitions specific to the
- * Tensilica XT2000 Emulation 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.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/system.h>
-
-
-/*
- *  Default assignment of XT2000 devices to external interrupts.
- */
-
-/*  Ethernet interrupt:  */
-#ifdef XCHAL_EXTINT3_NUM
-#define SONIC83934_INTNUM      XCHAL_EXTINT3_NUM
-#define SONIC83934_INTLEVEL    XCHAL_EXTINT3_LEVEL
-#define SONIC83934_INTMASK     XCHAL_EXTINT3_MASK
-#else
-#define SONIC83934_INTMASK     0
-#endif
-
-/*  DUART channel 1 interrupt (P1 - console):  */
-#ifdef XCHAL_EXTINT4_NUM
-#define DUART16552_1_INTNUM    XCHAL_EXTINT4_NUM
-#define DUART16552_1_INTLEVEL  XCHAL_EXTINT4_LEVEL
-#define DUART16552_1_INTMASK   XCHAL_EXTINT4_MASK
-#else
-#define DUART16552_1_INTMASK   0
-#endif
-
-/*  DUART channel 2 interrupt (P2 - 2nd serial port):  */
-#ifdef XCHAL_EXTINT5_NUM
-#define DUART16552_2_INTNUM    XCHAL_EXTINT5_NUM
-#define DUART16552_2_INTLEVEL  XCHAL_EXTINT5_LEVEL
-#define DUART16552_2_INTMASK   XCHAL_EXTINT5_MASK
-#else
-#define DUART16552_2_INTMASK   0
-#endif
-
-/*  FPGA-combined PCI/etc interrupts:  */
-#ifdef XCHAL_EXTINT6_NUM
-#define XT2000_FPGAPCI_INTNUM  XCHAL_EXTINT6_NUM
-#define XT2000_FPGAPCI_INTLEVEL        XCHAL_EXTINT6_LEVEL
-#define XT2000_FPGAPCI_INTMASK XCHAL_EXTINT6_MASK
-#else
-#define XT2000_FPGAPCI_INTMASK 0
-#endif
-
-
-
-/*
- *  Device addresses.
- *
- *  Note:  for endianness-independence, use 32-bit loads and stores for all
- *  register accesses to Ethernet, DUART and LED devices.  Undefined bits
- *  may need to be masked out if needed when reading if the actual register
- *  size is smaller than 32 bits.
- *
- *  Note:  XT2000 bus byte lanes are defined in terms of msbyte and lsbyte
- *  relative to the processor.  So 32-bit registers are accessed consistently
- *  from both big and little endian processors.  However, this means byte
- *  sequences are not consistent between big and little endian processors.
- *  This is fine for RAM, and for ROM if ROM is created for a specific
- *  processor (and thus has correct byte sequences).  However this may be
- *  unexpected for Flash, which might contain a file-system that one wants
- *  to use for multiple processor configurations (eg. the Flash might contain
- *  the Ethernet card's address, endianness-independent application data, etc).
- *  That is, byte sequences written in Flash by a core of a given endianness
- *  will be byte-swapped when seen by a core of the other endianness.
- *  Someone implementing an endianness-independent Flash file system will
- *  likely handle this byte-swapping issue in the Flash driver software.
- */
-
-#define DUART16552_XTAL_FREQ   18432000        /* crystal frequency in Hz */
-#define XTBOARD_FLASH_MAXSIZE  0x4000000       /* 64 MB (max; depends on what is socketed!) */
-#define XTBOARD_EPROM_MAXSIZE  0x0400000       /* 4 MB (max; depends on what is socketed!) */
-#define XTBOARD_EEPROM_MAXSIZE 0x0080000       /* 512 kB (max; depends on what is socketed!) */
-#define XTBOARD_ASRAM_SIZE     0x0100000       /* 1 MB */
-#define XTBOARD_PCI_MEM_SIZE   0x8000000       /* 128 MB (allocated) */
-#define XTBOARD_PCI_IO_SIZE    0x1000000       /* 16 MB (allocated) */
-
-#ifdef XSHAL_IOBLOCK_BYPASS_PADDR
-/*  PCI memory space:  */
-# define XTBOARD_PCI_MEM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0000000)
-/*  Socketed Flash (eg. 2 x 16-bit devices):  */
-# define XTBOARD_FLASH_PADDR   (XSHAL_IOBLOCK_BYPASS_PADDR+0x8000000)
-/*  PCI I/O space:  */
-# define XTBOARD_PCI_IO_PADDR  (XSHAL_IOBLOCK_BYPASS_PADDR+0xC000000)
-/*  V3 PCI interface chip register/config space:  */
-# define XTBOARD_V3PCI_PADDR   (XSHAL_IOBLOCK_BYPASS_PADDR+0xD000000)
-/*  Bus Interface registers:  */
-# define XTBOARD_BUSINT_PADDR  (XSHAL_IOBLOCK_BYPASS_PADDR+0xD010000)
-/*  FPGA registers:  */
-# define XT2000_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD020000)
-/*  SONIC SN83934 Ethernet controller/transceiver:  */
-# define SONIC83934_PADDR      (XSHAL_IOBLOCK_BYPASS_PADDR+0xD030000)
-/*  8-character bitmapped LED display:  */
-# define XTBOARD_LED_PADDR     (XSHAL_IOBLOCK_BYPASS_PADDR+0xD040000)
-/*  National-Semi PC16552D DUART:  */
-# define DUART16552_1_PADDR    (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050020)  /* channel 1 (P1 - console) */
-# define DUART16552_2_PADDR    (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050000)  /* channel 2 (P2) */
-/*  Asynchronous Static RAM:  */
-# define XTBOARD_ASRAM_PADDR   (XSHAL_IOBLOCK_BYPASS_PADDR+0xD400000)
-/*  8-bit EEPROM:  */
-# define XTBOARD_EEPROM_PADDR  (XSHAL_IOBLOCK_BYPASS_PADDR+0xD600000)
-/*  2 x 16-bit EPROMs:  */
-# define XTBOARD_EPROM_PADDR   (XSHAL_IOBLOCK_BYPASS_PADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */
-
-/*  These devices might be accessed cached:  */
-#ifdef XSHAL_IOBLOCK_CACHED_PADDR
-# define XTBOARD_PCI_MEM_CACHED_PADDR  (XSHAL_IOBLOCK_CACHED_PADDR+0x0000000)
-# define XTBOARD_FLASH_CACHED_PADDR    (XSHAL_IOBLOCK_CACHED_PADDR+0x8000000)
-# define XTBOARD_ASRAM_CACHED_PADDR    (XSHAL_IOBLOCK_CACHED_PADDR+0xD400000)
-# define XTBOARD_EEPROM_CACHED_PADDR   (XSHAL_IOBLOCK_CACHED_PADDR+0xD600000)
-# define XTBOARD_EPROM_CACHED_PADDR    (XSHAL_IOBLOCK_CACHED_PADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_CACHED_PADDR */
-
-
-/***  Same thing over again, this time with virtual addresses:  ***/
-
-#ifdef XSHAL_IOBLOCK_BYPASS_VADDR
-/*  PCI memory space:  */
-# define XTBOARD_PCI_MEM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0000000)
-/*  Socketed Flash (eg. 2 x 16-bit devices):  */
-# define XTBOARD_FLASH_VADDR   (XSHAL_IOBLOCK_BYPASS_VADDR+0x8000000)
-/*  PCI I/O space:  */
-# define XTBOARD_PCI_IO_VADDR  (XSHAL_IOBLOCK_BYPASS_VADDR+0xC000000)
-/*  V3 PCI interface chip register/config space:  */
-# define XTBOARD_V3PCI_VADDR   (XSHAL_IOBLOCK_BYPASS_VADDR+0xD000000)
-/*  Bus Interface registers:  */
-# define XTBOARD_BUSINT_VADDR  (XSHAL_IOBLOCK_BYPASS_VADDR+0xD010000)
-/*  FPGA registers:  */
-# define XT2000_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD020000)
-/*  SONIC SN83934 Ethernet controller/transceiver:  */
-# define SONIC83934_VADDR      (XSHAL_IOBLOCK_BYPASS_VADDR+0xD030000)
-/*  8-character bitmapped LED display:  */
-# define XTBOARD_LED_VADDR     (XSHAL_IOBLOCK_BYPASS_VADDR+0xD040000)
-/*  National-Semi PC16552D DUART:  */
-# define DUART16552_1_VADDR    (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050020)  /* channel 1 (P1 - console) */
-# define DUART16552_2_VADDR    (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050000)  /* channel 2 (P2) */
-/*  Asynchronous Static RAM:  */
-# define XTBOARD_ASRAM_VADDR   (XSHAL_IOBLOCK_BYPASS_VADDR+0xD400000)
-/*  8-bit EEPROM:  */
-# define XTBOARD_EEPROM_VADDR  (XSHAL_IOBLOCK_BYPASS_VADDR+0xD600000)
-/*  2 x 16-bit EPROMs:  */
-# define XTBOARD_EPROM_VADDR   (XSHAL_IOBLOCK_BYPASS_VADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */
-
-/*  These devices might be accessed cached:  */
-#ifdef XSHAL_IOBLOCK_CACHED_VADDR
-# define XTBOARD_PCI_MEM_CACHED_VADDR  (XSHAL_IOBLOCK_CACHED_VADDR+0x0000000)
-# define XTBOARD_FLASH_CACHED_VADDR    (XSHAL_IOBLOCK_CACHED_VADDR+0x8000000)
-# define XTBOARD_ASRAM_CACHED_VADDR    (XSHAL_IOBLOCK_CACHED_VADDR+0xD400000)
-# define XTBOARD_EEPROM_CACHED_VADDR   (XSHAL_IOBLOCK_CACHED_VADDR+0xD600000)
-# define XTBOARD_EPROM_CACHED_VADDR    (XSHAL_IOBLOCK_CACHED_VADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_CACHED_VADDR */
-
-
-/*  System ROM:  */
-#define XTBOARD_ROM_SIZE               XSHAL_ROM_SIZE
-#ifdef XSHAL_ROM_VADDR
-#define XTBOARD_ROM_VADDR              XSHAL_ROM_VADDR
-#endif
-#ifdef XSHAL_ROM_PADDR
-#define XTBOARD_ROM_PADDR              XSHAL_ROM_PADDR
-#endif
-
-/*  System RAM:  */
-#define XTBOARD_RAM_SIZE               XSHAL_RAM_SIZE
-#ifdef XSHAL_RAM_VADDR
-#define XTBOARD_RAM_VADDR              XSHAL_RAM_VADDR
-#endif
-#ifdef XSHAL_RAM_PADDR
-#define XTBOARD_RAM_PADDR              XSHAL_RAM_PADDR
-#endif
-#define XTBOARD_RAM_BYPASS_VADDR       XSHAL_RAM_BYPASS_VADDR
-#define XTBOARD_RAM_BYPASS_PADDR       XSHAL_RAM_BYPASS_PADDR
-
-
-
-/*
- *  Things that depend on device addresses.
- */
-
-
-#define XTBOARD_CACHEATTR_WRITEBACK    XSHAL_XT2000_CACHEATTR_WRITEBACK
-#define XTBOARD_CACHEATTR_WRITEALLOC   XSHAL_XT2000_CACHEATTR_WRITEALLOC
-#define XTBOARD_CACHEATTR_WRITETHRU    XSHAL_XT2000_CACHEATTR_WRITETHRU
-#define XTBOARD_CACHEATTR_BYPASS       XSHAL_XT2000_CACHEATTR_BYPASS
-#define XTBOARD_CACHEATTR_DEFAULT      XSHAL_XT2000_CACHEATTR_DEFAULT
-
-#define XTBOARD_BUSINT_PIPE_REGIONS    XSHAL_XT2000_PIPE_REGIONS
-#define XTBOARD_BUSINT_SDRAM_REGIONS   XSHAL_XT2000_SDRAM_REGIONS
-
-
-
-/*
- *  BusLogic (FPGA) registers.
- *  All these registers are normally accessed using 32-bit loads/stores.
- */
-
-/*  Register offsets:  */
-#define XT2000_DATECD_OFS      0x00    /* date code (read-only) */
-#define XT2000_STSREG_OFS      0x04    /* status (read-only) */
-#define XT2000_SYSLED_OFS      0x08    /* system LED */
-#define XT2000_WRPROT_OFS      0x0C    /* write protect */
-#define XT2000_SWRST_OFS       0x10    /* software reset */
-#define XT2000_SYSRST_OFS      0x14    /* system (peripherals) reset */
-#define XT2000_IMASK_OFS       0x18    /* interrupt mask */
-#define XT2000_ISTAT_OFS       0x1C    /* interrupt status */
-#define XT2000_V3CFG_OFS       0x20    /* V3 config (V320 PCI) */
-
-/*  Physical register addresses:  */
-#ifdef XT2000_FPGAREGS_PADDR
-#define XT2000_DATECD_PADDR    (XT2000_FPGAREGS_PADDR+XT2000_DATECD_OFS)
-#define XT2000_STSREG_PADDR    (XT2000_FPGAREGS_PADDR+XT2000_STSREG_OFS)
-#define XT2000_SYSLED_PADDR    (XT2000_FPGAREGS_PADDR+XT2000_SYSLED_OFS)
-#define XT2000_WRPROT_PADDR    (XT2000_FPGAREGS_PADDR+XT2000_WRPROT_OFS)
-#define XT2000_SWRST_PADDR     (XT2000_FPGAREGS_PADDR+XT2000_SWRST_OFS)
-#define XT2000_SYSRST_PADDR    (XT2000_FPGAREGS_PADDR+XT2000_SYSRST_OFS)
-#define XT2000_IMASK_PADDR     (XT2000_FPGAREGS_PADDR+XT2000_IMASK_OFS)
-#define XT2000_ISTAT_PADDR     (XT2000_FPGAREGS_PADDR+XT2000_ISTAT_OFS)
-#define XT2000_V3CFG_PADDR     (XT2000_FPGAREGS_PADDR+XT2000_V3CFG_OFS)
-#endif
-
-/*  Virtual register addresses:  */
-#ifdef XT2000_FPGAREGS_VADDR
-#define XT2000_DATECD_VADDR    (XT2000_FPGAREGS_VADDR+XT2000_DATECD_OFS)
-#define XT2000_STSREG_VADDR    (XT2000_FPGAREGS_VADDR+XT2000_STSREG_OFS)
-#define XT2000_SYSLED_VADDR    (XT2000_FPGAREGS_VADDR+XT2000_SYSLED_OFS)
-#define XT2000_WRPROT_VADDR    (XT2000_FPGAREGS_VADDR+XT2000_WRPROT_OFS)
-#define XT2000_SWRST_VADDR     (XT2000_FPGAREGS_VADDR+XT2000_SWRST_OFS)
-#define XT2000_SYSRST_VADDR    (XT2000_FPGAREGS_VADDR+XT2000_SYSRST_OFS)
-#define XT2000_IMASK_VADDR     (XT2000_FPGAREGS_VADDR+XT2000_IMASK_OFS)
-#define XT2000_ISTAT_VADDR     (XT2000_FPGAREGS_VADDR+XT2000_ISTAT_OFS)
-#define XT2000_V3CFG_VADDR     (XT2000_FPGAREGS_VADDR+XT2000_V3CFG_OFS)
-/*  Register access (for C code):  */
-#define XT2000_DATECD_REG      (*(volatile unsigned*) XT2000_DATECD_VADDR)
-#define XT2000_STSREG_REG      (*(volatile unsigned*) XT2000_STSREG_VADDR)
-#define XT2000_SYSLED_REG      (*(volatile unsigned*) XT2000_SYSLED_VADDR)
-#define XT2000_WRPROT_REG      (*(volatile unsigned*) XT2000_WRPROT_VADDR)
-#define XT2000_SWRST_REG       (*(volatile unsigned*) XT2000_SWRST_VADDR)
-#define XT2000_SYSRST_REG      (*(volatile unsigned*) XT2000_SYSRST_VADDR)
-#define XT2000_IMASK_REG       (*(volatile unsigned*) XT2000_IMASK_VADDR)
-#define XT2000_ISTAT_REG       (*(volatile unsigned*) XT2000_ISTAT_VADDR)
-#define XT2000_V3CFG_REG       (*(volatile unsigned*) XT2000_V3CFG_VADDR)
-#endif
-
-/*  DATECD (date code) bit fields:  */
-
-/*  BCD-coded month (01..12):  */
-#define XT2000_DATECD_MONTH_SHIFT      24
-#define XT2000_DATECD_MONTH_BITS       8
-#define XT2000_DATECD_MONTH_MASK       0xFF000000
-/*  BCD-coded day (01..31):  */
-#define XT2000_DATECD_DAY_SHIFT                16
-#define XT2000_DATECD_DAY_BITS         8
-#define XT2000_DATECD_DAY_MASK         0x00FF0000
-/*  BCD-coded year (2001..9999):  */
-#define XT2000_DATECD_YEAR_SHIFT       0
-#define XT2000_DATECD_YEAR_BITS                16
-#define XT2000_DATECD_YEAR_MASK                0x0000FFFF
-
-/*  STSREG (status) bit fields:  */
-
-/*  Switch SW3 setting bit fields (0=off/up, 1=on/down):  */
-#define XT2000_STSREG_SW3_SHIFT                0
-#define XT2000_STSREG_SW3_BITS         4
-#define XT2000_STSREG_SW3_MASK         0x0000000F
-/*  Boot-select bits of switch SW3:  */
-#define XT2000_STSREG_BOOTSEL_SHIFT    0
-#define XT2000_STSREG_BOOTSEL_BITS     2
-#define XT2000_STSREG_BOOTSEL_MASK     0x00000003
-/*  Boot-select values:  */
-#define XT2000_STSREG_BOOTSEL_FLASH    0
-#define XT2000_STSREG_BOOTSEL_EPROM16  1
-#define XT2000_STSREG_BOOTSEL_PROM8    2
-#define XT2000_STSREG_BOOTSEL_ASRAM    3
-/*  User-defined bits of switch SW3:  */
-#define XT2000_STSREG_SW3_2_SHIFT      2
-#define XT2000_STSREG_SW3_2_MASK       0x00000004
-#define XT2000_STSREG_SW3_3_SHIFT      3
-#define XT2000_STSREG_SW3_3_MASK       0x00000008
-
-/*  SYSLED (system LED) bit fields:  */
-
-/*  LED control bit (0=off, 1=on):  */
-#define XT2000_SYSLED_LEDON_SHIFT      0
-#define XT2000_SYSLED_LEDON_MASK       0x00000001
-
-/*  WRPROT (write protect) bit fields (0=writable, 1=write-protected [default]):  */
-
-/*  Flash write protect:  */
-#define XT2000_WRPROT_FLWP_SHIFT       0
-#define XT2000_WRPROT_FLWP_MASK                0x00000001
-/*  Reserved but present write protect bits:  */
-#define XT2000_WRPROT_WRP_SHIFT                1
-#define XT2000_WRPROT_WRP_BITS         7
-#define XT2000_WRPROT_WRP_MASK         0x000000FE
-
-/*  SWRST (software reset; allows s/w to generate power-on equivalent reset):  */
-
-/*  Software reset bits:  */
-#define XT2000_SWRST_SWR_SHIFT         0
-#define XT2000_SWRST_SWR_BITS          16
-#define XT2000_SWRST_SWR_MASK          0x0000FFFF
-/*  Software reset value -- writing this value resets the board:  */
-#define XT2000_SWRST_RESETVALUE                0x0000DEAD
-
-/*  SYSRST (system reset; controls reset of individual peripherals):  */
-
-/*  All-device reset:  */
-#define XT2000_SYSRST_ALL_SHIFT                0
-#define XT2000_SYSRST_ALL_BITS         4
-#define XT2000_SYSRST_ALL_MASK         0x0000000F
-/*  HDSP-2534 LED display reset (1=reset, 0=nothing):  */
-#define XT2000_SYSRST_LED_SHIFT                0
-#define XT2000_SYSRST_LED_MASK         0x00000001
-/*  Sonic DP83934 Ethernet controller reset (1=reset, 0=nothing):  */
-#define XT2000_SYSRST_SONIC_SHIFT      1
-#define XT2000_SYSRST_SONIC_MASK       0x00000002
-/*  DP16552 DUART reset (1=reset, 0=nothing):  */
-#define XT2000_SYSRST_DUART_SHIFT      2
-#define XT2000_SYSRST_DUART_MASK       0x00000004
-/*  V3 V320 PCI bridge controller reset (1=reset, 0=nothing):  */
-#define XT2000_SYSRST_V3_SHIFT         3
-#define XT2000_SYSRST_V3_MASK          0x00000008
-
-/*  IMASK (interrupt mask; 0=disable, 1=enable):  */
-/*  ISTAT (interrupt status; 0=inactive, 1=pending):  */
-
-/*  PCI INTP interrupt:  */
-#define XT2000_INTMUX_PCI_INTP_SHIFT   2
-#define XT2000_INTMUX_PCI_INTP_MASK    0x00000004
-/*  PCI INTS interrupt:  */
-#define XT2000_INTMUX_PCI_INTS_SHIFT   3
-#define XT2000_INTMUX_PCI_INTS_MASK    0x00000008
-/*  PCI INTD interrupt:  */
-#define XT2000_INTMUX_PCI_INTD_SHIFT   4
-#define XT2000_INTMUX_PCI_INTD_MASK    0x00000010
-/*  V320 PCI controller interrupt:  */
-#define XT2000_INTMUX_V3_SHIFT         5
-#define XT2000_INTMUX_V3_MASK          0x00000020
-/*  PCI ENUM interrupt:  */
-#define XT2000_INTMUX_PCI_ENUM_SHIFT   6
-#define XT2000_INTMUX_PCI_ENUM_MASK    0x00000040
-/*  PCI DEG interrupt:  */
-#define XT2000_INTMUX_PCI_DEG_SHIFT    7
-#define XT2000_INTMUX_PCI_DEG_MASK     0x00000080
-
-/*  V3CFG (V3 config, V320 PCI controller):  */
-
-/*  V3 address control (0=pass-thru, 1=V3 address bits 31:28 set to 4'b0001 [default]):  */
-#define XT2000_V3CFG_V3ADC_SHIFT       0
-#define XT2000_V3CFG_V3ADC_MASK                0x00000001
-
-/* I2C Devices */
-
-#define        XT2000_I2C_RTC_ID               0x68
-#define        XT2000_I2C_NVRAM0_ID            0x56    /* 1st 256 byte block */
-#define        XT2000_I2C_NVRAM1_ID            0x57    /* 2nd 256 byte block */
-
-/*  NVRAM Board Info structure:  */
-
-#define XT2000_NVRAM_SIZE              512
-
-#define XT2000_NVRAM_BINFO_START       0x100
-#define XT2000_NVRAM_BINFO_SIZE                0x20
-#define XT2000_NVRAM_BINFO_VERSION     0x10    /* version 1.0 */
-#if 0
-#define XT2000_NVRAM_BINFO_VERSION_OFFSET      0x00
-#define XT2000_NVRAM_BINFO_VERSION_SIZE                        0x1
-#define XT2000_NVRAM_BINFO_ETH_ADDR_OFFSET     0x02
-#define XT2000_NVRAM_BINFO_ETH_ADDR_SIZE               0x6
-#define XT2000_NVRAM_BINFO_SN_OFFSET           0x10
-#define XT2000_NVRAM_BINFO_SN_SIZE                     0xE
-#define        XT2000_NVRAM_BINFO_CRC_OFFSET           0x1E
-#define        XT2000_NVRAM_BINFO_CRC_SIZE                     0x2
-#endif /*0*/
-
-#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
-typedef struct xt2000_nvram_binfo {
-    unsigned char      version;
-    unsigned char      reserved1;
-    unsigned char      eth_addr[6];
-    unsigned char      reserved8[8];
-    unsigned char      serialno[14];
-    unsigned char      crc[2];         /* 16-bit CRC */
-} xt2000_nvram_binfo;
-#endif /*!__ASSEMBLY__ && !_NOCLANGUAGE*/
-
-
-#endif /*_INC_XT2000_H_*/
-
diff --git a/include/asm-xtensa/xtensa/xtboard.h b/include/asm-xtensa/xtensa/xtboard.h
deleted file mode 100644 (file)
index 22469c1..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef _xtboard_h_included_
-#define _xtboard_h_included_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- *  xtboard.h  --  Routines for getting useful information from the 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.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/xt2000.h>
-
-#define        XTBOARD_RTC_ERROR       -1
-#define        XTBOARD_RTC_STOPPED     -2
-
-
-/*  xt2000-i2cdev.c:  */
-typedef void XtboardDelayFunc( unsigned );
-extern XtboardDelayFunc* xtboard_set_nsdelay_func( XtboardDelayFunc *delay_fn );
-extern int xtboard_i2c_read (unsigned id, unsigned char *buf, unsigned addr, unsigned size);
-extern int xtboard_i2c_write(unsigned id, unsigned char *buf, unsigned addr, unsigned size);
-extern int xtboard_i2c_wait_nvram_ack(unsigned id, unsigned swtimer);
-
-/*  xtboard.c:  */
-extern int xtboard_nvram_read (unsigned addr, unsigned len, unsigned char *buf);
-extern int xtboard_nvram_write(unsigned addr, unsigned len, unsigned char *buf);
-extern int xtboard_nvram_binfo_read (xt2000_nvram_binfo *buf);
-extern int xtboard_nvram_binfo_write(xt2000_nvram_binfo *buf);
-extern int xtboard_nvram_binfo_valid(xt2000_nvram_binfo *buf);
-extern int xtboard_ethermac_get(unsigned char *buf);
-extern int xtboard_ethermac_set(unsigned char *buf);
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_rtc_time
-/
-/ Description:  Get time stored in real-time clock.
-/
-/ Returns: time in seconds stored in real-time clock.
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_get_rtc_time(void);
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_set_rtc_time
-/
-/ Description:  Set time stored in real-time clock.
-/
-/ Parameters:  time -- time in seconds to store to real-time clock
-/
-/ Returns: 0 on success, xtboard_i2c_write() error code otherwise.
-/-**----------------------------------------------------------------------------*/
-
-extern int xtboard_set_rtc_time(unsigned time);
-
-
-/*  xtfreq.c:  */
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_measure_sys_clk
-/
-/ Description:  Get frequency of system clock.
-/
-/ Parameters:  none
-/
-/ Returns: frequency of system clock.
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_measure_sys_clk(void);
-
-
-#if 0  /* old stuff from xtboard.c: */
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_nvram valid
-/
-/ Description:  Determines if data in NVRAM is valid.
-/
-/ Parameters:  delay -- 10us delay function
-/
-/ Returns: 1 if NVRAM is valid, 0 otherwise
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_nvram_valid(void (*delay)( void ));
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_nvram_contents
-/
-/ Description:  Returns contents of NVRAM.
-/
-/ Parameters:  buf -- buffer to NVRAM contents.
-/              delay -- 10us delay function
-/
-/ Returns: 1 if NVRAM is valid, 0 otherwise
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_get_nvram_contents(unsigned char *buf, void (*delay)( void ));
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_ether_addr
-/
-/ Description:  Returns ethernet address of board.
-/
-/ Parameters:  buf -- buffer to store ethernet address
-/              delay -- 10us delay function
-/
-/ Returns: nothing.
-/-**----------------------------------------------------------------------------*/
-
-extern void xtboard_get_ether_addr(unsigned char *buf, void (*delay)( void ));
-
-#endif /*0*/
-
-
-#endif /*_xtboard_h_included_*/
-
diff --git a/include/crypto/b128ops.h b/include/crypto/b128ops.h
new file mode 100644 (file)
index 0000000..0b8e6bc
--- /dev/null
@@ -0,0 +1,80 @@
+/* b128ops.h - common 128-bit block operations
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * 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.
+ */
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 13/06/2006
+*/
+
+#ifndef _CRYPTO_B128OPS_H
+#define _CRYPTO_B128OPS_H
+
+#include <linux/types.h>
+
+typedef struct {
+       u64 a, b;
+} u128;
+
+typedef struct {
+       __be64 a, b;
+} be128;
+
+typedef struct {
+       __le64 b, a;
+} le128;
+
+static inline void u128_xor(u128 *r, const u128 *p, const u128 *q)
+{
+       r->a = p->a ^ q->a;
+       r->b = p->b ^ q->b;
+}
+
+static inline void be128_xor(be128 *r, const be128 *p, const be128 *q)
+{
+       u128_xor((u128 *)r, (u128 *)p, (u128 *)q);
+}
+
+static inline void le128_xor(le128 *r, const le128 *p, const le128 *q)
+{
+       u128_xor((u128 *)r, (u128 *)p, (u128 *)q);
+}
+
+#endif /* _CRYPTO_B128OPS_H */
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
new file mode 100644 (file)
index 0000000..4fd3152
--- /dev/null
@@ -0,0 +1,198 @@
+/* gf128mul.h - GF(2^128) multiplication functions
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * 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.
+ */
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 31/01/2006
+
+ An implementation of field multiplication in Galois Field GF(128)
+*/
+
+#ifndef _CRYPTO_GF128MUL_H
+#define _CRYPTO_GF128MUL_H
+
+#include <crypto/b128ops.h>
+#include <linux/slab.h>
+
+/* Comment by Rik:
+ *
+ * For some background on GF(2^128) see for example: http://-
+ * csrc.nist.gov/CryptoToolkit/modes/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * The elements of GF(2^128) := GF(2)[X]/(X^128-X^7-X^2-X^1-1) can
+ * be mapped to computer memory in a variety of ways. Let's examine
+ * three common cases.
+ *
+ * Take a look at the 16 binary octets below in memory order. The msb's
+ * are left and the lsb's are right. char b[16] is an array and b[0] is
+ * the first octet.
+ *
+ * 80000000 00000000 00000000 00000000 .... 00000000 00000000 00000000
+ *   b[0]     b[1]     b[2]     b[3]          b[13]    b[14]    b[15]
+ *
+ * Every bit is a coefficient of some power of X. We can store the bits
+ * in every byte in little-endian order and the bytes themselves also in
+ * little endian order. I will call this lle (little-little-endian).
+ * The above buffer represents the polynomial 1, and X^7+X^2+X^1+1 looks
+ * like 11100001 00000000 .... 00000000 = { 0xE1, 0x00, }.
+ * This format was originally implemented in gf128mul and is used
+ * in GCM (Galois/Counter mode) and in ABL (Arbitrary Block Length).
+ *
+ * Another convention says: store the bits in bigendian order and the
+ * bytes also. This is bbe (big-big-endian). Now the buffer above
+ * represents X^127. X^7+X^2+X^1+1 looks like 00000000 .... 10000111,
+ * b[15] = 0x87 and the rest is 0. LRW uses this convention and bbe
+ * is partly implemented.
+ *
+ * Both of the above formats are easy to implement on big-endian
+ * machines.
+ *
+ * EME (which is patent encumbered) uses the ble format (bits are stored
+ * in big endian order and the bytes in little endian). The above buffer
+ * represents X^7 in this case and the primitive polynomial is b[0] = 0x87.
+ *
+ * The common machine word-size is smaller than 128 bits, so to make
+ * an efficient implementation we must split into machine word sizes.
+ * This file uses one 32bit for the moment. Machine endianness comes into
+ * play. The lle format in relation to machine endianness is discussed
+ * below by the original author of gf128mul Dr Brian Gladman.
+ *
+ * Let's look at the bbe and ble format on a little endian machine.
+ *
+ * bbe on a little endian machine u32 x[4]:
+ *
+ *  MS            x[0]           LS  MS            x[1]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  103..96 111.104 119.112 127.120  71...64 79...72 87...80 95...88
+ *
+ *  MS            x[2]           LS  MS            x[3]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  39...32 47...40 55...48 63...56  07...00 15...08 23...16 31...24
+ *
+ * ble on a little endian machine
+ *
+ *  MS            x[0]           LS  MS            x[1]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  31...24 23...16 15...08 07...00  63...56 55...48 47...40 39...32
+ *
+ *  MS            x[2]           LS  MS            x[3]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  95...88 87...80 79...72 71...64  127.120 199.112 111.104 103..96
+ *
+ * Multiplications in GF(2^128) are mostly bit-shifts, so you see why
+ * ble (and lbe also) are easier to implement on a little-endian
+ * machine than on a big-endian machine. The converse holds for bbe
+ * and lle.
+ *
+ * Note: to have good alignment, it seems to me that it is sufficient
+ * to keep elements of GF(2^128) in type u64[2]. On 32-bit wordsize
+ * machines this will automatically aligned to wordsize and on a 64-bit
+ * machine also.
+ */
+/*     Multiply a GF128 field element by x. Field elements are held in arrays
+    of bytes in which field bits 8n..8n + 7 are held in byte[n], with lower
+    indexed bits placed in the more numerically significant bit positions
+    within bytes.
+
+    On little endian machines the bit indexes translate into the bit
+    positions within four 32-bit words in the following way
+
+    MS            x[0]           LS  MS            x[1]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    24...31 16...23 08...15 00...07  56...63 48...55 40...47 32...39
+
+    MS            x[2]           LS  MS            x[3]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    88...95 80...87 72...79 64...71  120.127 112.119 104.111 96..103
+
+    On big endian machines the bit indexes translate into the bit
+    positions within four 32-bit words in the following way
+
+    MS            x[0]           LS  MS            x[1]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    00...07 08...15 16...23 24...31  32...39 40...47 48...55 56...63
+
+    MS            x[2]           LS  MS            x[3]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    64...71 72...79 80...87 88...95  96..103 104.111 112.119 120.127
+*/
+
+/*     A slow generic version of gf_mul, implemented for lle and bbe
+ *     It multiplies a and b and puts the result in a */
+void gf128mul_lle(be128 *a, const be128 *b);
+
+void gf128mul_bbe(be128 *a, const be128 *b);
+
+
+/* 4k table optimization */
+
+struct gf128mul_4k {
+       be128 t[256];
+};
+
+struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g);
+struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g);
+void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t);
+void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t);
+
+static inline void gf128mul_free_4k(struct gf128mul_4k *t)
+{
+       kfree(t);
+}
+
+
+/* 64k table optimization, implemented for lle and bbe */
+
+struct gf128mul_64k {
+       struct gf128mul_4k *t[16];
+};
+
+/* first initialize with the constant factor with which you
+ * want to multiply and then call gf128_64k_lle with the other
+ * factor in the first argument, the table in the second and a
+ * scratch register in the third. Afterwards *a = *r. */
+struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g);
+struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g);
+void gf128mul_free_64k(struct gf128mul_64k *t);
+void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t);
+void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t);
+
+#endif /* _CRYPTO_GF128MUL_H */
index ff43312..a1b04d8 100644 (file)
@@ -61,7 +61,6 @@ header-y += fd.h
 header-y += fdreg.h
 header-y += fib_rules.h
 header-y += fuse.h
-header-y += futex.h
 header-y += genetlink.h
 header-y += gen_stats.h
 header-y += gigaset_dev.h
@@ -203,6 +202,7 @@ unifdef-y += fb.h
 unifdef-y += fcntl.h
 unifdef-y += filter.h
 unifdef-y += flat.h
+unifdef-y += futex.h
 unifdef-y += fs.h
 unifdef-y += gameport.h
 unifdef-y += generic_serial.h
@@ -221,6 +221,7 @@ unifdef-y += if_bridge.h
 unifdef-y += if_ec.h
 unifdef-y += if_eql.h
 unifdef-y += if_ether.h
+unifdef-y += if_fddi.h
 unifdef-y += if_frad.h
 unifdef-y += if_ltalk.h
 unifdef-y += if_pppox.h
@@ -282,6 +283,7 @@ unifdef-y += nvram.h
 unifdef-y += parport.h
 unifdef-y += patchkey.h
 unifdef-y += pci.h
+unifdef-y += personality.h
 unifdef-y += pktcdvd.h
 unifdef-y += pmu.h
 unifdef-y += poll.h
@@ -337,6 +339,7 @@ unifdef-y += videodev.h
 unifdef-y += wait.h
 unifdef-y += wanrouter.h
 unifdef-y += watchdog.h
+unifdef-y += wireless.h
 unifdef-y += xfrm.h
 
 objhdr-y += version.h
index 0d71c00..3372ec6 100644 (file)
@@ -111,7 +111,6 @@ struct kiocb {
        size_t                  ki_nbytes;      /* copy of iocb->aio_nbytes */
        char                    __user *ki_buf; /* remaining iocb->aio_buf */
        size_t                  ki_left;        /* remaining bytes */
-       long                    ki_retried;     /* just for testing */
        struct iovec            ki_inline_vec;  /* inline vector */
        struct iovec            *ki_iovec;
        unsigned long           ki_nr_segs;
@@ -194,7 +193,7 @@ struct kioctx {
 
        struct aio_ring_info    ring_info;
 
-       struct work_struct      wq;
+       struct delayed_work     wq;
 };
 
 /* prototypes */
@@ -238,7 +237,6 @@ do {                                                                        \
 } while (0)
 
 #define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
-#define is_retried_kiocb(iocb) ((iocb)->ki_retried > 1)
 
 #include <linux/aio_abi.h>
 
index b2ca666..0e07db6 100644 (file)
 #define AUDIT_MAC_CIPSOV4_DEL  1408    /* NetLabel: del CIPSOv4 DOI entry */
 #define AUDIT_MAC_MAP_ADD      1409    /* NetLabel: add LSM domain mapping */
 #define AUDIT_MAC_MAP_DEL      1410    /* NetLabel: del LSM domain mapping */
+#define AUDIT_MAC_IPSEC_ADDSA  1411    /* Add a XFRM state */
+#define AUDIT_MAC_IPSEC_DELSA  1412    /* Delete a XFRM state */
+#define AUDIT_MAC_IPSEC_ADDSPD 1413    /* Add a XFRM policy */
+#define AUDIT_MAC_IPSEC_DELSPD 1414    /* Delete a XFRM policy */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
@@ -377,6 +381,7 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
+extern void audit_log_task_context(struct audit_buffer *ab);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 extern int audit_bprm(struct linux_binprm *bprm);
@@ -449,6 +454,7 @@ extern int audit_n_rules;
 #define audit_inode_update(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
+#define audit_log_task_context(b) do { ; } while (0)
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h
new file mode 100644 (file)
index 0000000..05e540d
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _LINUX_BITREV_H
+#define _LINUX_BITREV_H
+
+#include <linux/types.h>
+
+extern u8 const byte_rev_table[256];
+
+static inline u8 bitrev8(u8 byte)
+{
+       return byte_rev_table[byte];
+}
+
+extern u32 bitrev32(u32 in);
+
+#endif /* _LINUX_BITREV_H */
index e1c7286..ea330d7 100644 (file)
@@ -342,7 +342,6 @@ typedef void (unplug_fn) (request_queue_t *);
 
 struct bio_vec;
 typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
-typedef void (activity_fn) (void *data, int rw);
 typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
 typedef void (prepare_flush_fn) (request_queue_t *, struct request *);
 typedef void (softirq_done_fn)(struct request *);
@@ -384,7 +383,6 @@ struct request_queue
        prep_rq_fn              *prep_rq_fn;
        unplug_fn               *unplug_fn;
        merge_bvec_fn           *merge_bvec_fn;
-       activity_fn             *activity_fn;
        issue_flush_fn          *issue_flush_fn;
        prepare_flush_fn        *prepare_flush_fn;
        softirq_done_fn         *softirq_done_fn;
@@ -411,8 +409,6 @@ struct request_queue
         */
        void                    *queuedata;
 
-       void                    *activity_data;
-
        /*
         * queue needs bounce pages for pages above this limit
         */
@@ -677,7 +673,6 @@ extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(request_queue_t *q);
 extern void blk_run_queue(request_queue_t *);
 extern void blk_start_queueing(request_queue_t *);
-extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
 extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
 extern int blk_rq_unmap_user(struct request *);
 extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
index 31e9abb..2275f27 100644 (file)
@@ -119,8 +119,7 @@ extern void *alloc_large_system_hash(const char *tablename,
                                     unsigned int *_hash_mask,
                                     unsigned long limit);
 
-#define HASH_HIGHMEM   0x00000001      /* Consider highmem? */
-#define HASH_EARLY     0x00000002      /* Allocating during early boot? */
+#define HASH_EARLY     0x00000001      /* Allocating during early boot? */
 
 /* Only NUMA needs hash distribution.
  * IA64 is known to have sufficient vmalloc space.
diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h
new file mode 100644 (file)
index 0000000..777dbf6
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LINUX_BH_H
+#define _LINUX_BH_H
+
+extern void local_bh_disable(void);
+extern void __local_bh_enable(void);
+extern void _local_bh_enable(void);
+extern void local_bh_enable(void);
+extern void local_bh_enable_ip(unsigned long ip);
+
+#endif /* _LINUX_BH_H */
diff --git a/include/linux/bug.h b/include/linux/bug.h
new file mode 100644 (file)
index 0000000..42aa0a5
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _LINUX_BUG_H
+#define _LINUX_BUG_H
+
+#include <linux/module.h>
+#include <asm/bug.h>
+
+enum bug_trap_type {
+       BUG_TRAP_TYPE_NONE = 0,
+       BUG_TRAP_TYPE_WARN = 1,
+       BUG_TRAP_TYPE_BUG = 2,
+};
+
+#ifdef CONFIG_GENERIC_BUG
+#include <asm-generic/bug.h>
+
+static inline int is_warning_bug(const struct bug_entry *bug)
+{
+       return bug->flags & BUGFLAG_WARNING;
+}
+
+const struct bug_entry *find_bug(unsigned long bugaddr);
+
+enum bug_trap_type report_bug(unsigned long bug_addr);
+
+int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
+                        struct module *);
+void module_bug_cleanup(struct module *);
+
+/* These are defined by the architecture */
+int is_valid_bugaddr(unsigned long addr);
+
+#else  /* !CONFIG_GENERIC_BUG */
+
+static inline enum bug_trap_type report_bug(unsigned long bug_addr)
+{
+       return BUG_TRAP_TYPE_BUG;
+}
+static inline int  module_bug_finalize(const Elf_Ehdr *hdr,
+                                       const Elf_Shdr *sechdrs,
+                                       struct module *mod)
+{
+       return 0;
+}
+static inline void module_bug_cleanup(struct module *mod) {}
+
+#endif /* CONFIG_GENERIC_BUG */
+#endif /* _LINUX_BUG_H */
diff --git a/include/linux/carta_random32.h b/include/linux/carta_random32.h
deleted file mode 100644 (file)
index f6f3bd9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Fast, simple, yet decent quality random number generator based on
- * a paper by David G. Carta ("Two Fast Implementations of the
- * `Minimal Standard' Random Number Generator," Communications of the
- * ACM, January, 1990).
- *
- * Copyright (c) 2002-2006 Hewlett-Packard Development Company, L.P.
- *     Contributed by Stephane Eranian <eranian@hpl.hp.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307 USA
- */
-#ifndef _LINUX_CARTA_RANDOM32_H_
-#define _LINUX_CARTA_RANDOM32_H_
-
-u64 carta_random32(u64 seed);
-
-#endif /* _LINUX_CARTA_RANDOM32_H_ */
index 6e27f42..cb57c30 100644 (file)
@@ -80,7 +80,7 @@ typedef __u32 DriverVer_type;
 #define HWORD __u16
 #define DWORD __u32
 
-#define CISS_MAX_LUN   16      
+#define CISS_MAX_LUN   1024
 
 #define LEVEL2LUN   1   // index into Target(x) structure, due to byte swapping
 #define LEVEL3LUN   0
index ee5f53f..f309b00 100644 (file)
@@ -2,6 +2,10 @@
 #define _LINUX_CDEV_H
 #ifdef __KERNEL__
 
+#include <linux/kobject.h>
+#include <linux/kdev_t.h>
+#include <linux/list.h>
+
 struct cdev {
        struct kobject kobj;
        struct module *owner;
index d852024..1622d23 100644 (file)
@@ -159,7 +159,7 @@ static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles)
  * Unless you're the timekeeping code, you should not be using this!
  */
 static inline void clocksource_calculate_interval(struct clocksource *c,
-                                               unsigned long length_nsec)
+                                                 unsigned long length_nsec)
 {
        u64 tmp;
 
index 4c02119..3ea1cd5 100644 (file)
@@ -133,7 +133,7 @@ struct cn_callback_data {
 struct cn_callback_entry {
        struct list_head callback_entry;
        struct cn_callback *cb;
-       struct work_struct work;
+       struct delayed_work work;
        struct cn_queue_dev *pdev;
 
        struct cn_callback_id id;
@@ -170,7 +170,7 @@ void cn_queue_free_dev(struct cn_queue_dev *dev);
 
 int cn_cb_equal(struct cb_id *, struct cb_id *);
 
-void cn_queue_wrapper(void *data);
+void cn_queue_wrapper(struct work_struct *work);
 
 extern int cn_already_initialized;
 
index f02d71b..bfb5202 100644 (file)
 #include <linux/compiler.h>
 #include <linux/cpumask.h>
 #include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 struct cpu {
        int node_id;            /* The node which contains the CPU */
-       int no_control;         /* Should the sysfs control file be created? */
+       int hotpluggable;       /* creates sysfs control file if hotpluggable */
        struct sys_device sysdev;
 };
 
@@ -74,6 +75,17 @@ extern struct sysdev_class cpu_sysdev_class;
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* Stop CPUs going up and down. */
+
+static inline void cpuhotplug_mutex_lock(struct mutex *cpu_hp_mutex)
+{
+       mutex_lock(cpu_hp_mutex);
+}
+
+static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
+{
+       mutex_unlock(cpu_hp_mutex);
+}
+
 extern void lock_cpu_hotplug(void);
 extern void unlock_cpu_hotplug(void);
 #define hotcpu_notifier(fn, pri) {                             \
@@ -85,17 +97,24 @@ extern void unlock_cpu_hotplug(void);
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
 int cpu_down(unsigned int cpu);
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
-#else
+
+#else          /* CONFIG_HOTPLUG_CPU */
+
+static inline void cpuhotplug_mutex_lock(struct mutex *cpu_hp_mutex)
+{ }
+static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
+{ }
+
 #define lock_cpu_hotplug()     do { } while (0)
 #define unlock_cpu_hotplug()   do { } while (0)
 #define lock_cpu_hotplug_interruptible() 0
-#define hotcpu_notifier(fn, pri)       do { } while (0)
-#define register_hotcpu_notifier(nb)   do { } while (0)
-#define unregister_hotcpu_notifier(nb) do { } while (0)
+#define hotcpu_notifier(fn, pri)       do { (void)(fn); } while (0)
+#define register_hotcpu_notifier(nb)   do { (void)(nb); } while (0)
+#define unregister_hotcpu_notifier(nb) do { (void)(nb); } while (0)
 
 /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
 static inline int cpu_is_offline(int cpu) { return 0; }
-#endif
+#endif         /* CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_SUSPEND_SMP
 extern int disable_nonboot_cpus(void);
index 4d8adf6..8821e1f 100644 (file)
@@ -23,6 +23,7 @@ extern void cpuset_fork(struct task_struct *p);
 extern void cpuset_exit(struct task_struct *p);
 extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
 extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
+#define cpuset_current_mems_allowed (current->mems_allowed)
 void cpuset_init_current_mems_allowed(void);
 void cpuset_update_task_memory_state(void);
 #define cpuset_nodes_subset_current_mems_allowed(nodes) \
@@ -45,7 +46,7 @@ extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
 extern int cpuset_memory_pressure_enabled;
 extern void __cpuset_memory_pressure_bump(void);
 
-extern struct file_operations proc_cpuset_operations;
+extern const struct file_operations proc_cpuset_operations;
 extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
 
 extern void cpuset_lock(void);
@@ -83,6 +84,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
        return node_possible_map;
 }
 
+#define cpuset_current_mems_allowed (node_online_map)
 static inline void cpuset_init_current_mems_allowed(void) {}
 static inline void cpuset_update_task_memory_state(void) {}
 #define cpuset_nodes_subset_current_mems_allowed(nodes) (1)
index 56c0645..e20dd1f 100644 (file)
@@ -6,10 +6,10 @@
 #define _LINUX_CRC32_H
 
 #include <linux/types.h>
+#include <linux/bitrev.h>
 
 extern u32  crc32_le(u32 crc, unsigned char const *p, size_t len);
 extern u32  crc32_be(u32 crc, unsigned char const *p, size_t len);
-extern u32  bitreverse(u32 in);
 
 #define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)data, length)
 
@@ -21,7 +21,7 @@ extern u32  bitreverse(u32 in);
  * is in bit nr 0], thus it must be reversed before use. Except for
  * nics that bit swap the result internally...
  */
-#define ether_crc(length, data)    bitreverse(crc32_le(~0, data, length))
+#define ether_crc(length, data)    bitrev32(crc32_le(~0, data, length))
 #define ether_crc_le(length, data) crc32_le(~0, data, length)
 
 #endif /* _LINUX_CRC32_H */
index 6485e97..4aa9046 100644 (file)
@@ -241,12 +241,8 @@ int crypto_unregister_alg(struct crypto_alg *alg);
  * Algorithm query interface.
  */
 #ifdef CONFIG_CRYPTO
-int crypto_alg_available(const char *name, u32 flags)
-       __deprecated_for_modules;
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 #else
-static int crypto_alg_available(const char *name, u32 flags)
-       __deprecated_for_modules;
 static inline int crypto_alg_available(const char *name, u32 flags)
 {
        return 0;
@@ -707,16 +703,6 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
                                                dst, src);
 }
 
-void crypto_digest_init(struct crypto_tfm *tfm) __deprecated_for_modules;
-void crypto_digest_update(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg)
-       __deprecated_for_modules;
-void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
-       __deprecated_for_modules;
-void crypto_digest_digest(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg, u8 *out)
-       __deprecated_for_modules;
-
 static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm)
 {
        return (struct crypto_hash *)tfm;
@@ -729,14 +715,6 @@ static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm)
        return __crypto_hash_cast(tfm);
 }
 
-static int crypto_digest_setkey(struct crypto_tfm *tfm, const u8 *key,
-                               unsigned int keylen) __deprecated;
-static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
-                                       const u8 *key, unsigned int keylen)
-{
-       return tfm->crt_hash.setkey(crypto_hash_cast(tfm), key, keylen);
-}
-
 static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name,
                                                    u32 type, u32 mask)
 {
index ed6cc89..1cb054b 100644 (file)
@@ -176,20 +176,20 @@ enum {
 };
 
 /* DCCP features (RFC 4340 section 6.4) */
- enum {
-       DCCPF_RESERVED = 0,
-       DCCPF_CCID = 1,
+enum {
+       DCCPF_RESERVED = 0,
+       DCCPF_CCID = 1,
        DCCPF_SHORT_SEQNOS = 2,         /* XXX: not yet implemented */
-       DCCPF_SEQUENCE_WINDOW = 3,
+       DCCPF_SEQUENCE_WINDOW = 3,
        DCCPF_ECN_INCAPABLE = 4,        /* XXX: not yet implemented */
-       DCCPF_ACK_RATIO = 5,
-       DCCPF_SEND_ACK_VECTOR = 6,
-       DCCPF_SEND_NDP_COUNT = 7,
+       DCCPF_ACK_RATIO = 5,
+       DCCPF_SEND_ACK_VECTOR = 6,
+       DCCPF_SEND_NDP_COUNT = 7,
        DCCPF_MIN_CSUM_COVER = 8,
        DCCPF_DATA_CHECKSUM = 9,        /* XXX: not yet implemented */
-       /* 10-127 reserved */
-       DCCPF_MIN_CCID_SPECIFIC = 128,
-       DCCPF_MAX_CCID_SPECIFIC = 255,
+       /* 10-127 reserved */
+       DCCPF_MIN_CCID_SPECIFIC = 128,
+       DCCPF_MAX_CCID_SPECIFIC = 255,
 };
 
 /* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
@@ -427,7 +427,7 @@ struct dccp_service_list {
 };
 
 #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
-#define DCCP_SERVICE_CODE_IS_ABSENT             0
+#define DCCP_SERVICE_CODE_IS_ABSENT            0
 
 static inline int dccp_list_has_service(const struct dccp_service_list *sl,
                                        const __be32 service)
@@ -436,7 +436,7 @@ static inline int dccp_list_has_service(const struct dccp_service_list *sl,
                u32 i = sl->dccpsl_nr;
                while (i--)
                        if (sl->dccpsl_list[i] == service)
-                               return 1; 
+                               return 1;
        }
        return 0;
 }
@@ -511,7 +511,7 @@ struct dccp_sock {
        __u8                            dccps_hc_tx_insert_options:1;
        struct timer_list               dccps_xmit_timer;
 };
+
 static inline struct dccp_sock *dccp_sk(const struct sock *sk)
 {
        return (struct dccp_sock *)sk;
index 952bee7..a1c10b0 100644 (file)
@@ -24,7 +24,7 @@ extern int debug_locks_off(void);
        int __ret = 0;                                                  \
                                                                        \
        if (unlikely(c)) {                                              \
-               if (debug_locks_off())                                  \
+               if (debug_locks_silent || debug_locks_off())            \
                        WARN_ON(1);                                     \
                __ret = 1;                                              \
        }                                                               \
index 561e2a7..55d1ca5 100644 (file)
@@ -30,7 +30,7 @@
 #ifdef CONFIG_TASK_DELAY_ACCT
 
 extern int delayacct_on;       /* Delay accounting turned on/off */
-extern kmem_cache_t *delayacct_cache;
+extern struct kmem_cache *delayacct_cache;
 extern void delayacct_init(void);
 extern void __delayacct_tsk_init(struct task_struct *);
 extern void __delayacct_tsk_exit(struct task_struct *);
index 03ef41c..499f537 100644 (file)
@@ -39,7 +39,8 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti);
  * The map function must return:
  * < 0: error
  * = 0: The target will handle the io by resubmitting it later
- * > 0: simple remap complete
+ * = 1: simple remap complete
+ * = 2: The target wants to push back the io
  */
 typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
                          union map_info *map_context);
@@ -50,6 +51,7 @@ typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
  * 0   : ended successfully
  * 1   : for some reason the io has still not completed (eg,
  *       multipath target might want to requeue a failed io).
+ * 2   : The target wants to push back the io
  */
 typedef int (*dm_endio_fn) (struct dm_target *ti,
                            struct bio *bio, int error,
@@ -173,7 +175,7 @@ void *dm_get_mdptr(struct mapped_device *md);
 /*
  * A device can still be used while suspended, but I/O is deferred.
  */
-int dm_suspend(struct mapped_device *md, int with_lockfs);
+int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
 int dm_resume(struct mapped_device *md);
 
 /*
@@ -188,6 +190,7 @@ int dm_wait_event(struct mapped_device *md, int event_nr);
 const char *dm_device_name(struct mapped_device *md);
 struct gendisk *dm_disk(struct mapped_device *md);
 int dm_suspended(struct mapped_device *md);
+int dm_noflush_suspending(struct dm_target *ti);
 
 /*
  * Geometry functions.
index 583a341..49ab53c 100644 (file)
@@ -371,6 +371,9 @@ struct device {
                                           core doesn't touch it */
        struct dev_pm_info      power;
 
+#ifdef CONFIG_NUMA
+       int             numa_node;      /* NUMA node this device is close to */
+#endif
        u64             *dma_mask;      /* dma mask (if dma'able device) */
        u64             coherent_dma_mask;/* Like dma_mask, but for
                                             alloc_coherent mappings as
@@ -394,6 +397,25 @@ struct device {
        void    (*release)(struct device * dev);
 };
 
+#ifdef CONFIG_NUMA
+static inline int dev_to_node(struct device *dev)
+{
+       return dev->numa_node;
+}
+static inline void set_dev_node(struct device *dev, int node)
+{
+       dev->numa_node = node;
+}
+#else
+static inline int dev_to_node(struct device *dev)
+{
+       return -1;
+}
+static inline void set_dev_node(struct device *dev, int node)
+{
+}
+#endif
+
 static inline void *
 dev_get_drvdata (struct device *dev)
 {
index 8853fc4..b934861 100644 (file)
@@ -285,9 +285,9 @@ typedef char ioctl_struct[308];
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       10
+#define DM_VERSION_MINOR       11
 #define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2006-09-14)"
+#define DM_VERSION_EXTRA       "-ioctl (2006-10-12)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
@@ -323,4 +323,9 @@ typedef char ioctl_struct[308];
  */
 #define DM_SKIP_LOCKFS_FLAG    (1 << 10) /* In */
 
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG                (1 << 11) /* In */
+
 #endif                         /* _LINUX_DM_IOCTL_H */
index 66d621d..df1c918 100644 (file)
@@ -300,8 +300,9 @@ extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
 extern int __init efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
                                        struct resource *data_resource);
-extern unsigned long __init efi_get_time(void);
+extern unsigned long efi_get_time(void);
 extern int __init efi_set_rtc_mmss(unsigned long nowtime);
+extern int is_available_memory(efi_memory_desc_t * md);
 extern struct efi_memory_map memmap;
 
 /**
index 743d5c8..60713e6 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/elf-em.h>
 #include <asm/elf.h>
 
+struct file;
+
 #ifndef elf_read_implies_exec
   /* Executables for which elf_read_implies_exec() returns TRUE will
      have the READ_IMPLIES_EXEC personality flag set automatically.
@@ -358,6 +360,7 @@ extern Elf32_Dyn _DYNAMIC [];
 #define elfhdr         elf32_hdr
 #define elf_phdr       elf32_phdr
 #define elf_note       elf32_note
+#define elf_addr_t     Elf32_Off
 
 #else
 
@@ -365,6 +368,7 @@ extern Elf64_Dyn _DYNAMIC [];
 #define elfhdr         elf64_hdr
 #define elf_phdr       elf64_phdr
 #define elf_note       elf64_note
+#define elf_addr_t     Elf64_Off
 
 #endif
 
index ce0e610..8c43b13 100644 (file)
@@ -109,74 +109,32 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode);
  * been done yet.
  */
 
-void ext3_journal_abort_handle(const char *caller, const char *err_fn,
-               struct buffer_head *bh, handle_t *handle, int err);
-
-static inline int
-__ext3_journal_get_undo_access(const char *where, handle_t *handle,
-                               struct buffer_head *bh)
+static inline void ext3_journal_release_buffer(handle_t *handle,
+                                               struct buffer_head *bh)
 {
-       int err = journal_get_undo_access(handle, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
+       journal_release_buffer(handle, bh);
 }
 
-static inline int
-__ext3_journal_get_write_access(const char *where, handle_t *handle,
-                               struct buffer_head *bh)
-{
-       int err = journal_get_write_access(handle, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+void ext3_journal_abort_handle(const char *caller, const char *err_fn,
+               struct buffer_head *bh, handle_t *handle, int err);
 
-static inline void
-ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
-{
-       journal_release_buffer(handle, bh);
-}
+int __ext3_journal_get_undo_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext3_journal_forget(const char *where, handle_t *handle, struct buffer_head *bh)
-{
-       int err = journal_forget(handle, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext3_journal_get_write_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext3_journal_revoke(const char *where, handle_t *handle,
-                     unsigned long blocknr, struct buffer_head *bh)
-{
-       int err = journal_revoke(handle, blocknr, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext3_journal_forget(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext3_journal_get_create_access(const char *where,
-                                handle_t *handle, struct buffer_head *bh)
-{
-       int err = journal_get_create_access(handle, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext3_journal_revoke(const char *where, handle_t *handle,
+                               unsigned long blocknr, struct buffer_head *bh);
 
-static inline int
-__ext3_journal_dirty_metadata(const char *where,
-                             handle_t *handle, struct buffer_head *bh)
-{
-       int err = journal_dirty_metadata(handle, bh);
-       if (err)
-               ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext3_journal_get_create_access(const char *where,
+                               handle_t *handle, struct buffer_head *bh);
 
+int __ext3_journal_dirty_metadata(const char *where,
+                               handle_t *handle, struct buffer_head *bh);
 
 #define ext3_journal_get_undo_access(handle, bh) \
        __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
index 72dd631..d716e63 100644 (file)
@@ -114,74 +114,32 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
  * been done yet.
  */
 
-void ext4_journal_abort_handle(const char *caller, const char *err_fn,
-               struct buffer_head *bh, handle_t *handle, int err);
-
-static inline int
-__ext4_journal_get_undo_access(const char *where, handle_t *handle,
-                               struct buffer_head *bh)
+static inline void ext4_journal_release_buffer(handle_t *handle,
+                                               struct buffer_head *bh)
 {
-       int err = jbd2_journal_get_undo_access(handle, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
+       jbd2_journal_release_buffer(handle, bh);
 }
 
-static inline int
-__ext4_journal_get_write_access(const char *where, handle_t *handle,
-                               struct buffer_head *bh)
-{
-       int err = jbd2_journal_get_write_access(handle, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+               struct buffer_head *bh, handle_t *handle, int err);
 
-static inline void
-ext4_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
-{
-       jbd2_journal_release_buffer(handle, bh);
-}
+int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext4_journal_forget(const char *where, handle_t *handle, struct buffer_head *bh)
-{
-       int err = jbd2_journal_forget(handle, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext4_journal_revoke(const char *where, handle_t *handle,
-                     ext4_fsblk_t blocknr, struct buffer_head *bh)
-{
-       int err = jbd2_journal_revoke(handle, blocknr, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext4_journal_forget(const char *where, handle_t *handle,
+                               struct buffer_head *bh);
 
-static inline int
-__ext4_journal_get_create_access(const char *where,
-                                handle_t *handle, struct buffer_head *bh)
-{
-       int err = jbd2_journal_get_create_access(handle, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext4_journal_revoke(const char *where, handle_t *handle,
+                               ext4_fsblk_t blocknr, struct buffer_head *bh);
 
-static inline int
-__ext4_journal_dirty_metadata(const char *where,
-                             handle_t *handle, struct buffer_head *bh)
-{
-       int err = jbd2_journal_dirty_metadata(handle, bh);
-       if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-       return err;
-}
+int __ext4_journal_get_create_access(const char *where,
+                               handle_t *handle, struct buffer_head *bh);
 
+int __ext4_journal_dirty_metadata(const char *where,
+                               handle_t *handle, struct buffer_head *bh);
 
 #define ext4_journal_get_undo_access(handle, bh) \
        __ext4_journal_get_undo_access(__FUNCTION__, (handle), (bh))
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
new file mode 100644 (file)
index 0000000..32368c4
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef _LINUX_FAULT_INJECT_H
+#define _LINUX_FAULT_INJECT_H
+
+#ifdef CONFIG_FAULT_INJECTION
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <asm/atomic.h>
+
+/*
+ * For explanation of the elements of this struct, see
+ * Documentation/fault-injection/fault-injection.txt
+ */
+struct fault_attr {
+       unsigned long probability;
+       unsigned long interval;
+       atomic_t times;
+       atomic_t space;
+       unsigned long verbose;
+       u32 task_filter;
+       unsigned long stacktrace_depth;
+       unsigned long require_start;
+       unsigned long require_end;
+       unsigned long reject_start;
+       unsigned long reject_end;
+
+       unsigned long count;
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+       struct {
+               struct dentry *dir;
+
+               struct dentry *probability_file;
+               struct dentry *interval_file;
+               struct dentry *times_file;
+               struct dentry *space_file;
+               struct dentry *verbose_file;
+               struct dentry *task_filter_file;
+               struct dentry *stacktrace_depth_file;
+               struct dentry *require_start_file;
+               struct dentry *require_end_file;
+               struct dentry *reject_start_file;
+               struct dentry *reject_end_file;
+       } dentries;
+
+#endif
+};
+
+#define FAULT_ATTR_INITIALIZER {                               \
+               .interval = 1,                                  \
+               .times = ATOMIC_INIT(1),                        \
+               .require_end = ULONG_MAX,                       \
+               .stacktrace_depth = 32,                         \
+               .verbose = 2,                                   \
+       }
+
+#define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
+int setup_fault_attr(struct fault_attr *attr, char *str);
+void should_fail_srandom(unsigned long entropy);
+bool should_fail(struct fault_attr *attr, ssize_t size);
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+int init_fault_attr_dentries(struct fault_attr *attr, const char *name);
+void cleanup_fault_attr_dentries(struct fault_attr *attr);
+
+#else /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+static inline int init_fault_attr_dentries(struct fault_attr *attr,
+                                         const char *name)
+{
+       return -ENODEV;
+}
+
+static inline void cleanup_fault_attr_dentries(struct fault_attr *attr)
+{
+}
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#endif /* CONFIG_FAULT_INJECTION */
+
+#endif /* _LINUX_FAULT_INJECT_H */
index fa23e06..6fe56aa 100644 (file)
@@ -970,11 +970,11 @@ extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
 extern void fb_dealloc_cmap(struct fb_cmap *cmap);
-extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to);
-extern int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to);
+extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
+extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);
 extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *fb_info);
 extern int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *fb_info);
-extern struct fb_cmap *fb_default_cmap(int len);
+extern const struct fb_cmap *fb_default_cmap(int len);
 extern void fb_invert_cmaps(void);
 
 struct fb_videomode {
index 74183e6..edca361 100644 (file)
@@ -26,19 +26,12 @@ struct embedded_fd_set {
        unsigned long fds_bits[1];
 };
 
-/*
- * More than this number of fds: we use a separately allocated fd_set
- */
-#define EMBEDDED_FD_SET_SIZE (BITS_PER_BYTE * sizeof(struct embedded_fd_set))
-
 struct fdtable {
        unsigned int max_fds;
-       int max_fdset;
        struct file ** fd;      /* current fd array */
        fd_set *close_on_exec;
        fd_set *open_fds;
        struct rcu_head rcu;
-       struct files_struct *free_files;
        struct fdtable *next;
 };
 
@@ -64,6 +57,8 @@ struct files_struct {
 
 #define files_fdtable(files) (rcu_dereference((files)->fdt))
 
+extern struct kmem_cache *filp_cachep;
+
 extern void FASTCALL(__fput(struct file *));
 extern void FASTCALL(fput(struct file *));
 
@@ -81,14 +76,8 @@ extern int get_unused_fd(void);
 extern void FASTCALL(put_unused_fd(unsigned int fd));
 struct kmem_cache;
 
-extern struct file ** alloc_fd_array(int);
-extern void free_fd_array(struct file **, int);
-
-extern fd_set *alloc_fdset(int);
-extern void free_fdset(fd_set *, int);
-
 extern int expand_files(struct files_struct *, int nr);
-extern void free_fdtable(struct fdtable *fdt);
+extern void free_fdtable_rcu(struct rcu_head *rcu);
 extern void __init files_defer_init(void);
 
 static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
@@ -114,4 +103,6 @@ struct files_struct *get_files_struct(struct task_struct *);
 void FASTCALL(put_files_struct(struct files_struct *fs));
 void reset_files_struct(struct task_struct *, struct files_struct *);
 
+extern struct kmem_cache *files_cachep;
+
 #endif /* __LINUX_FILE_H */
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
new file mode 100644 (file)
index 0000000..3930630
--- /dev/null
@@ -0,0 +1,89 @@
+/* Freezer declarations */
+
+#include <linux/sched.h>
+
+#ifdef CONFIG_PM
+/*
+ * Check if a process has been frozen
+ */
+static inline int frozen(struct task_struct *p)
+{
+       return p->flags & PF_FROZEN;
+}
+
+/*
+ * Check if there is a request to freeze a process
+ */
+static inline int freezing(struct task_struct *p)
+{
+       return p->flags & PF_FREEZE;
+}
+
+/*
+ * Request that a process be frozen
+ * FIXME: SMP problem. We may not modify other process' flags!
+ */
+static inline void freeze(struct task_struct *p)
+{
+       p->flags |= PF_FREEZE;
+}
+
+/*
+ * Sometimes we may need to cancel the previous 'freeze' request
+ */
+static inline void do_not_freeze(struct task_struct *p)
+{
+       p->flags &= ~PF_FREEZE;
+}
+
+/*
+ * Wake up a frozen process
+ */
+static inline int thaw_process(struct task_struct *p)
+{
+       if (frozen(p)) {
+               p->flags &= ~PF_FROZEN;
+               wake_up_process(p);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * freezing is complete, mark process as frozen
+ */
+static inline void frozen_process(struct task_struct *p)
+{
+       p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+}
+
+extern void refrigerator(void);
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+
+static inline int try_to_freeze(void)
+{
+       if (freezing(current)) {
+               refrigerator();
+               return 1;
+       } else
+               return 0;
+}
+
+extern void thaw_some_processes(int all);
+
+#else
+static inline int frozen(struct task_struct *p) { return 0; }
+static inline int freezing(struct task_struct *p) { return 0; }
+static inline void freeze(struct task_struct *p) { BUG(); }
+static inline int thaw_process(struct task_struct *p) { return 1; }
+static inline void frozen_process(struct task_struct *p) { BUG(); }
+
+static inline void refrigerator(void) {}
+static inline int freeze_processes(void) { BUG(); return 0; }
+static inline void thaw_processes(void) {}
+
+static inline int try_to_freeze(void) { return 0; }
+
+
+#endif
index cac7b1e..adce6e1 100644 (file)
@@ -269,6 +269,7 @@ extern int dir_notify_enable;
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/dcache.h>
+#include <linux/namei.h>
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/kobject.h>
@@ -481,21 +482,6 @@ struct block_device {
        unsigned long           bd_private;
 };
 
-/*
- * bdev->bd_mutex nesting subclasses for the lock validator:
- *
- * 0: normal
- * 1: 'whole'
- * 2: 'partition'
- */
-enum bdev_bd_mutex_lock_class
-{
-       BD_MUTEX_NORMAL,
-       BD_MUTEX_WHOLE,
-       BD_MUTEX_PARTITION
-};
-
-
 /*
  * Radix-tree tags, for tagging dirty and writeback pages within the pagecache
  * radix trees
@@ -543,19 +529,22 @@ struct inode {
        struct list_head        i_dentry;
        unsigned long           i_ino;
        atomic_t                i_count;
-       umode_t                 i_mode;
        unsigned int            i_nlink;
        uid_t                   i_uid;
        gid_t                   i_gid;
        dev_t                   i_rdev;
+       unsigned long           i_version;
        loff_t                  i_size;
+#ifdef __NEED_I_SIZE_ORDERED
+       seqcount_t              i_size_seqcount;
+#endif
        struct timespec         i_atime;
        struct timespec         i_mtime;
        struct timespec         i_ctime;
        unsigned int            i_blkbits;
-       unsigned long           i_version;
        blkcnt_t                i_blocks;
        unsigned short          i_bytes;
+       umode_t                 i_mode;
        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
        struct mutex            i_mutex;
        struct rw_semaphore     i_alloc_sem;
@@ -598,9 +587,6 @@ struct inode {
        void                    *i_security;
 #endif
        void                    *i_private; /* fs or device private pointer */
-#ifdef __NEED_I_SIZE_ORDERED
-       seqcount_t              i_size_seqcount;
-#endif
 };
 
 /*
@@ -636,7 +622,7 @@ extern void inode_double_unlock(struct inode *inode1, struct inode *inode2);
  * cmpxchg8b without the need of the lock prefix). For SMP compiles
  * and 64bit archs it makes no difference if preempt is enabled or not.
  */
-static inline loff_t i_size_read(struct inode *inode)
+static inline loff_t i_size_read(const struct inode *inode)
 {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
        loff_t i_size;
@@ -679,12 +665,12 @@ static inline void i_size_write(struct inode *inode, loff_t i_size)
 #endif
 }
 
-static inline unsigned iminor(struct inode *inode)
+static inline unsigned iminor(const struct inode *inode)
 {
        return MINOR(inode->i_rdev);
 }
 
-static inline unsigned imajor(struct inode *inode)
+static inline unsigned imajor(const struct inode *inode)
 {
        return MAJOR(inode->i_rdev);
 }
@@ -726,8 +712,9 @@ struct file {
                struct list_head        fu_list;
                struct rcu_head         fu_rcuhead;
        } f_u;
-       struct dentry           *f_dentry;
-       struct vfsmount         *f_vfsmnt;
+       struct path             f_path;
+#define f_dentry       f_path.dentry
+#define f_vfsmnt       f_path.mnt
        const struct file_operations    *f_op;
        atomic_t                f_count;
        unsigned int            f_flags;
@@ -1239,7 +1226,7 @@ extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
 static inline void file_accessed(struct file *file)
 {
        if (!(file->f_flags & O_NOATIME))
-               touch_atime(file->f_vfsmnt, file->f_dentry);
+               touch_atime(file->f_path.mnt, file->f_path.dentry);
 }
 
 int sync_inode(struct inode *inode, struct writeback_control *wbc);
@@ -1481,7 +1468,9 @@ extern char * getname(const char __user *);
 extern void __init vfs_caches_init_early(void);
 extern void __init vfs_caches_init(unsigned long);
 
-#define __getname()    kmem_cache_alloc(names_cachep, SLAB_KERNEL)
+extern struct kmem_cache *names_cachep;
+
+#define __getname()    kmem_cache_alloc(names_cachep, GFP_KERNEL)
 #define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
 #ifndef CONFIG_AUDITSYSCALL
 #define putname(name)   __putname(name)
@@ -1497,7 +1486,6 @@ extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern struct block_device *open_by_devnum(dev_t, unsigned);
-extern struct block_device *open_partition_by_devnum(dev_t, unsigned);
 extern const struct address_space_operations def_blk_aops;
 #else
 static inline void bd_forget(struct inode *inode) {}
@@ -1515,7 +1503,6 @@ extern int blkdev_driver_ioctl(struct inode *inode, struct file *file,
 extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
 extern int blkdev_get(struct block_device *, mode_t, unsigned);
 extern int blkdev_put(struct block_device *);
-extern int blkdev_put_partition(struct block_device *);
 extern int bd_claim(struct block_device *, void *);
 extern void bd_release(struct block_device *);
 #ifdef CONFIG_SYSFS
@@ -1630,7 +1617,7 @@ static inline void put_write_access(struct inode * inode)
 static inline void allow_write_access(struct file *file)
 {
        if (file)
-               atomic_inc(&file->f_dentry->d_inode->i_writecount);
+               atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
 }
 extern int do_pipe(int *);
 extern struct file *create_read_pipe(struct file *f);
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
new file mode 100644 (file)
index 0000000..bb516ce
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _LINUX_FS_STACK_H
+#define _LINUX_FS_STACK_H
+
+/* This file defines generic functions used primarily by stackable
+ * filesystems; none of these functions require i_mutex to be held.
+ */
+
+#include <linux/fs.h>
+
+/* externs for fs/stack.c */
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+                               int (*get_nlinks)(struct inode *));
+
+extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+
+/* inlines */
+static inline void fsstack_copy_attr_atime(struct inode *dest,
+                                          const struct inode *src)
+{
+       dest->i_atime = src->i_atime;
+}
+
+static inline void fsstack_copy_attr_times(struct inode *dest,
+                                          const struct inode *src)
+{
+       dest->i_atime = src->i_atime;
+       dest->i_mtime = src->i_mtime;
+       dest->i_ctime = src->i_ctime;
+}
+
+#endif /* _LINUX_FS_STACK_H */
index c623d12..11a36ce 100644 (file)
@@ -18,6 +18,8 @@ struct fs_struct {
        .umask          = 0022, \
 }
 
+extern struct kmem_cache *fs_cachep;
+
 extern void exit_fs(struct task_struct *);
 extern void set_fs_altroot(void);
 extern void set_fs_root(struct fs_struct *, struct vfsmount *, struct dentry *);
index 3da29e2..abb64c4 100644 (file)
@@ -19,6 +19,7 @@
 #define _FSL_DEVICE_H_
 
 #include <linux/types.h>
+#include <linux/phy.h>
 
 /*
  * Some conventions on how we handle peripherals on Freescale chips
index d4f219f..dfc4e4f 100644 (file)
@@ -164,7 +164,7 @@ static inline void fsnotify_open(struct dentry *dentry)
  */
 static inline void fsnotify_close(struct file *file)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        const char *name = dentry->d_name.name;
        mode_t mode = file->f_mode;
index 9fc48a6..534744e 100644 (file)
@@ -15,7 +15,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 7
+#define FUSE_KERNEL_MINOR_VERSION 8
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -92,6 +92,11 @@ struct fuse_file_lock {
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
 
+/**
+ * Release flags
+ */
+#define FUSE_RELEASE_FLUSH     (1 << 0)
+
 enum fuse_opcode {
        FUSE_LOOKUP        = 1,
        FUSE_FORGET        = 2,  /* no reply */
@@ -127,6 +132,8 @@ enum fuse_opcode {
        FUSE_ACCESS        = 34,
        FUSE_CREATE        = 35,
        FUSE_INTERRUPT     = 36,
+       FUSE_BMAP          = 37,
+       FUSE_DESTROY       = 38,
 };
 
 /* The read buffer is required to be at least 8k, but may be much larger */
@@ -205,12 +212,13 @@ struct fuse_open_out {
 struct fuse_release_in {
        __u64   fh;
        __u32   flags;
-       __u32   padding;
+       __u32   release_flags;
+       __u64   lock_owner;
 };
 
 struct fuse_flush_in {
        __u64   fh;
-       __u32   flush_flags;
+       __u32   unused;
        __u32   padding;
        __u64   lock_owner;
 };
@@ -296,6 +304,16 @@ struct fuse_interrupt_in {
        __u64   unique;
 };
 
+struct fuse_bmap_in {
+       __u64   block;
+       __u32   blocksize;
+       __u32   padding;
+};
+
+struct fuse_bmap_out {
+       __u64   block;
+};
+
 struct fuse_in_header {
        __u32   len;
        __u32   opcode;
index d097b5b..3f153b4 100644 (file)
@@ -93,6 +93,7 @@ struct robust_list_head {
  */
 #define ROBUST_LIST_LIMIT      2048
 
+#ifdef __KERNEL__
 long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
              u32 __user *uaddr2, u32 val2, u32 val3);
 
@@ -110,6 +111,7 @@ static inline void exit_pi_state_list(struct task_struct *curr)
 {
 }
 #endif
+#endif /* __KERNEL__ */
 
 #define FUTEX_OP_SET           0       /* *(int *)UADDR2 = OPARG; */
 #define FUTEX_OP_ADD           1       /* *(int *)UADDR2 += OPARG; */
index e253845..5412da2 100644 (file)
@@ -91,7 +91,7 @@ void gs_hangup(struct tty_struct *tty);
 int  gs_block_til_ready(void *port, struct file *filp);
 void gs_close(struct tty_struct *tty, struct file *filp);
 void gs_set_termios (struct tty_struct * tty, 
-                     struct termios * old_termios);
+                     struct ktermios * old_termios);
 int  gs_init_port(struct gs_port *port);
 int  gs_setserial(struct gs_port *port, struct serial_struct __user *sp);
 int  gs_getserial(struct gs_port *port, struct serial_struct __user *sp);
index 9049dc6..f7a9377 100644 (file)
@@ -17,6 +17,9 @@ struct genlmsghdr {
 #define GENL_HDRLEN    NLMSG_ALIGN(sizeof(struct genlmsghdr))
 
 #define GENL_ADMIN_PERM                0x01
+#define GENL_CMD_CAP_DO                0x02
+#define GENL_CMD_CAP_DUMP      0x04
+#define GENL_CMD_CAP_HASPOL    0x08
 
 /*
  * List of reserved static generic netlink identifiers:
@@ -58,9 +61,6 @@ enum {
        CTRL_ATTR_OP_UNSPEC,
        CTRL_ATTR_OP_ID,
        CTRL_ATTR_OP_FLAGS,
-       CTRL_ATTR_OP_POLICY,
-       CTRL_ATTR_OP_DOIT,
-       CTRL_ATTR_OP_DUMPIT,
        __CTRL_ATTR_OP_MAX,
 };
 
index 41f276f..0a022b2 100644 (file)
@@ -83,6 +83,9 @@ struct hd_struct {
        struct kobject *holder_dir;
        unsigned ios[2], sectors[2];    /* READs and WRITEs */
        int policy, partno;
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+       int make_it_fail;
+#endif
 };
 
 #define GENHD_FL_REMOVABLE                     1
@@ -90,6 +93,7 @@ struct hd_struct {
 #define GENHD_FL_CD                            8
 #define GENHD_FL_UP                            16
 #define GENHD_FL_SUPPRESS_PARTITION_INFO       32
+#define GENHD_FL_FAIL                          64
 
 struct disk_stats {
        unsigned long sectors[2];       /* READs and WRITEs */
index bf2b6bc..00c314a 100644 (file)
@@ -116,6 +116,9 @@ static inline enum zone_type gfp_zone(gfp_t flags)
 #ifndef HAVE_ARCH_FREE_PAGE
 static inline void arch_free_page(struct page *page, int order) { }
 #endif
+#ifndef HAVE_ARCH_ALLOC_PAGE
+static inline void arch_alloc_page(struct page *page, int order) { }
+#endif
 
 extern struct page *
 FASTCALL(__alloc_pages(gfp_t, unsigned int, struct zonelist *));
index a7ae7c1..8b7e4c1 100644 (file)
@@ -54,8 +54,13 @@ struct gfs2_inum {
        __be64 no_addr;
 };
 
-static inline int gfs2_inum_equal(const struct gfs2_inum *ino1,
-                                 const struct gfs2_inum *ino2)
+struct gfs2_inum_host {
+       __u64 no_formal_ino;
+       __u64 no_addr;
+};
+
+static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1,
+                                 const struct gfs2_inum_host *ino2)
 {
        return ino1->no_formal_ino == ino2->no_formal_ino &&
               ino1->no_addr == ino2->no_addr;
@@ -89,6 +94,12 @@ struct gfs2_meta_header {
        __be32 __pad1;          /* Was incarnation number in gfs1 */
 };
 
+struct gfs2_meta_header_host {
+       __u32 mh_magic;
+       __u32 mh_type;
+       __u32 mh_format;
+};
+
 /*
  * super-block structure
  *
@@ -128,6 +139,23 @@ struct gfs2_sb {
        /* In gfs1, quota and license dinodes followed */
 };
 
+struct gfs2_sb_host {
+       struct gfs2_meta_header_host sb_header;
+
+       __u32 sb_fs_format;
+       __u32 sb_multihost_format;
+
+       __u32 sb_bsize;
+       __u32 sb_bsize_shift;
+
+       struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */
+       struct gfs2_inum_host sb_root_dir;
+
+       char sb_lockproto[GFS2_LOCKNAME_LEN];
+       char sb_locktable[GFS2_LOCKNAME_LEN];
+       /* In gfs1, quota and license dinodes followed */
+};
+
 /*
  * resource index structure
  */
@@ -145,6 +173,14 @@ struct gfs2_rindex {
        __u8 ri_reserved[64];
 };
 
+struct gfs2_rindex_host {
+       __u64 ri_addr;  /* grp block disk address */
+       __u64 ri_data0; /* first data location */
+       __u32 ri_length;        /* length of rgrp header in fs blocks */
+       __u32 ri_data;  /* num of data blocks in rgrp */
+       __u32 ri_bitbytes;      /* number of bytes in data bitmaps */
+};
+
 /*
  * resource group header structure
  */
@@ -176,6 +212,13 @@ struct gfs2_rgrp {
        __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
 };
 
+struct gfs2_rgrp_host {
+       __u32 rg_flags;
+       __u32 rg_free;
+       __u32 rg_dinodes;
+       __u64 rg_igeneration;
+};
+
 /*
  * quota structure
  */
@@ -187,6 +230,12 @@ struct gfs2_quota {
        __u8 qu_reserved[64];
 };
 
+struct gfs2_quota_host {
+       __u64 qu_limit;
+       __u64 qu_warn;
+       __u64 qu_value;
+};
+
 /*
  * dinode structure
  */
@@ -270,6 +319,27 @@ struct gfs2_dinode {
        __u8 di_reserved[56];
 };
 
+struct gfs2_dinode_host {
+       __u64 di_size;  /* number of bytes in file */
+       __u64 di_blocks;        /* number of blocks in file */
+
+       /* This section varies from gfs1. Padding added to align with
+         * remainder of dinode
+        */
+       __u64 di_goal_meta;     /* rgrp to alloc from next */
+       __u64 di_goal_data;     /* data block goal */
+       __u64 di_generation;    /* generation number for NFS */
+
+       __u32 di_flags; /* GFS2_DIF_... */
+       __u16 di_height;        /* height of metadata */
+
+       /* These only apply to directories  */
+       __u16 di_depth; /* Number of bits in the table */
+       __u32 di_entries;       /* The number of entries in the directory */
+
+       __u64 di_eattr; /* extended attribute block number */
+};
+
 /*
  * directory structure - many of these per directory file
  */
@@ -344,6 +414,16 @@ struct gfs2_log_header {
        __be32 lh_hash;
 };
 
+struct gfs2_log_header_host {
+       struct gfs2_meta_header_host lh_header;
+
+       __u64 lh_sequence;      /* Sequence number of this transaction */
+       __u32 lh_flags; /* GFS2_LOG_HEAD_... */
+       __u32 lh_tail;          /* Block number of log tail */
+       __u32 lh_blkno;
+       __u32 lh_hash;
+};
+
 /*
  * Log type descriptor
  */
@@ -384,6 +464,11 @@ struct gfs2_inum_range {
        __be64 ir_length;
 };
 
+struct gfs2_inum_range_host {
+       __u64 ir_start;
+       __u64 ir_length;
+};
+
 /*
  * Statfs change
  * Describes an change to the pool of free and allocated
@@ -396,6 +481,12 @@ struct gfs2_statfs_change {
        __be64 sc_dinodes;
 };
 
+struct gfs2_statfs_change_host {
+       __u64 sc_total;
+       __u64 sc_free;
+       __u64 sc_dinodes;
+};
+
 /*
  * Quota change
  * Describes an allocation change for a particular
@@ -410,33 +501,38 @@ struct gfs2_quota_change {
        __be32 qc_id;
 };
 
+struct gfs2_quota_change_host {
+       __u64 qc_change;
+       __u32 qc_flags; /* GFS2_QCF_... */
+       __u32 qc_id;
+};
+
 #ifdef __KERNEL__
 /* Translation functions */
 
-extern void gfs2_inum_in(struct gfs2_inum *no, const void *buf);
-extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf);
-extern void gfs2_sb_in(struct gfs2_sb *sb, const void *buf);
-extern void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf);
-extern void gfs2_rindex_out(const struct gfs2_rindex *ri, void *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf);
-extern void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf);
-extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf);
-extern void gfs2_quota_out(const struct gfs2_quota *qu, void *buf);
-extern void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf);
-extern void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf);
+extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf);
+extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf);
+extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf);
+extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf);
+extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf);
+extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf);
+extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf);
+extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf);
+struct gfs2_inode;
+extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
 extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);
 extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf);
-extern void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf);
-extern void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf);
-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf);
+extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf);
+extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf);
+extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf);
+extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf);
+extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf);
+extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf);
 
 /* Printing functions */
 
-extern void gfs2_rindex_print(const struct gfs2_rindex *ri);
-extern void gfs2_dinode_print(const struct gfs2_dinode *di);
+extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri);
+extern void gfs2_dinode_print(const struct gfs2_inode *ip);
 
 #endif /* __KERNEL__ */
 
similarity index 86%
rename from drivers/usb/input/hid.h
rename to include/linux/hid.h
index 2a9bf07..770120a 100644 (file)
@@ -6,6 +6,7 @@
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2006 Jiri Kosina
  */
 
 /*
@@ -33,6 +34,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/input.h>
 
 /*
  * USB HID (Human Interface Device) interface class code
@@ -260,7 +262,8 @@ struct hid_item {
 #define HID_QUIRK_POWERBOOK_HAS_FN             0x00001000
 #define HID_QUIRK_POWERBOOK_FN_ON              0x00002000
 #define HID_QUIRK_INVERT_HWHEEL                        0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD       0x00008000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
+#define HID_QUIRK_BAD_RELATIVE_KEYS            0x00010000
 
 /*
  * This is the global environment of the parser. This information is
@@ -400,42 +403,14 @@ struct hid_device {                                                       /* device report descriptor */
        unsigned collection_size;                                       /* Number of allocated hid_collections */
        unsigned maxcollection;                                         /* Number of parsed collections */
        unsigned maxapplication;                                        /* Number of applications */
+       unsigned short bus;                                             /* BUS ID */
+       unsigned short vendor;                                          /* Vendor ID */
+       unsigned short product;                                         /* Product ID */
        unsigned version;                                               /* HID version */
        unsigned country;                                               /* HID country */
        struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-       struct usb_device *dev;                                         /* USB device */
-       struct usb_interface *intf;                                     /* USB interface */
-       int ifnum;                                                      /* USB interface number */
-
-       unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
-       struct timer_list io_retry;                                     /* Retry timer */
-       unsigned long stop_retry;                                       /* Time to give up, in jiffies */
-       unsigned int retry_delay;                                       /* Delay length in ms */
-       struct work_struct reset_work;                                  /* Task context for resets */
-
-       unsigned int bufsize;                                           /* URB buffer size */
-
-       struct urb *urbin;                                              /* Input URB */
-       char *inbuf;                                                    /* Input buffer */
-       dma_addr_t inbuf_dma;                                           /* Input buffer dma */
-       spinlock_t inlock;                                              /* Input fifo spinlock */
-
-       struct urb *urbctrl;                                            /* Control URB */
-       struct usb_ctrlrequest *cr;                                     /* Control request struct */
-       dma_addr_t cr_dma;                                              /* Control request struct dma */
-       struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];            /* Control fifo */
-       unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
-       char *ctrlbuf;                                                  /* Control buffer */
-       dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
-       spinlock_t ctrllock;                                            /* Control fifo spinlock */
-
-       struct urb *urbout;                                             /* Output URB */
-       struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
-       unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
-       char *outbuf;                                                   /* Output buffer */
-       dma_addr_t outbuf_dma;                                          /* Output buffer dma */
-       spinlock_t outlock;                                             /* Output fifo spinlock */
+       struct device *dev;                                             /* device */
 
        unsigned claimed;                                               /* Claimed by hidinput, hiddev? */
        unsigned quirks;                                                /* Various quirks the device can pull on us */
@@ -451,7 +426,19 @@ struct hid_device {                                                        /* device report descriptor */
        char phys[64];                                                  /* Device physical location */
        char uniq[64];                                                  /* Device unique identifier (serial #) */
 
+       void *driver_data;
+
+       /* device-specific function pointers */
+       int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
+       int (*hidinput_open) (struct input_dev *);
+       void (*hidinput_close) (struct input_dev *);
+
+       /* hiddev event handler */
+       void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
+                                 struct hid_usage *, __s32);
+       void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+       unsigned int  pb_fnmode;
        unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
        unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
 #endif
@@ -495,31 +482,23 @@ struct hid_descriptor {
 #define resolv_event(a,b)      do { } while (0)
 #endif
 
-#endif
-
-#ifdef CONFIG_USB_HIDINPUT
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
+
+/* HID core API */
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *);
 extern void hidinput_disconnect(struct hid_device *);
-#else
-#define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
-static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { }
-static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
-static inline void hidinput_disconnect(struct hid_device *hid) { }
-#endif
 
-int hid_open(struct hid_device *);
-void hid_close(struct hid_device *);
 int hid_set_field(struct hid_field *, unsigned, __s32);
-void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
-void hid_init_reports(struct hid_device *hid);
-int hid_wait_io(struct hid_device* hid);
-
+int hid_input_report(struct hid_device *, int type, u8 *, int, int);
+int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
+void hid_output_report(struct hid_report *report, __u8 *data);
+void hid_free_device(struct hid_device *device);
+struct hid_device *hid_parse_report(__u8 *start, unsigned size);
 
 #ifdef CONFIG_HID_FF
 int hid_ff_init(struct hid_device *hid);
@@ -536,4 +515,14 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
 #else
 static inline int hid_ff_init(struct hid_device *hid) { return -1; }
 #endif
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+               __FILE__ , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+               __FILE__ , ## arg)
+#endif
 
index fd7d12d..3d8768b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
 
@@ -41,9 +42,10 @@ static inline void *kmap(struct page *page)
 
 #define kunmap(page) do { (void) (page); } while (0)
 
-#define kmap_atomic(page, idx)         page_address(page)
-#define kunmap_atomic(addr, idx)       do { } while (0)
-#define kmap_atomic_pfn(pfn, idx)      page_address(pfn_to_page(pfn))
+#define kmap_atomic(page, idx) \
+       ({ pagefault_disable(); page_address(page); })
+#define kunmap_atomic(addr, idx)       do { pagefault_enable(); } while (0)
+#define kmap_atomic_pfn(pfn, idx)      kmap_atomic(pfn_to_page(pfn), (idx))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
 #endif
 
index ace64e5..a60995a 100644 (file)
@@ -35,6 +35,7 @@ extern int sysctl_hugetlb_shm_group;
 
 pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep);
 struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
                              int write);
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
index 0a8f750..0f4cf34 100644 (file)
 #define I2C_DRIVERID_ASB100 1043
 #define I2C_DRIVERID_FSCHER 1046
 #define I2C_DRIVERID_W83L785TS 1047
+#define I2C_DRIVERID_OV7670 1048       /* Omnivision 7670 camera */
 
 /*
  * ---- Adapter types ----------------------------------------------------
 #define I2C_HW_SMBUS_OV518     0x04000f /* OV518(+) USB 1.1 webcam ICs */
 #define I2C_HW_SMBUS_OV519     0x040010 /* OV519 USB 1.1 webcam IC */
 #define I2C_HW_SMBUS_OVFX2     0x040011 /* Cypress/OmniVision FX2 webcam */
+#define I2C_HW_SMBUS_CAFE      0x040012 /* Marvell 88ALP01 "CAFE" cam  */
 
 /* --- ISA pseudo-adapter                                              */
 #define I2C_HW_ISA             0x050000
index 5f3eaf8..41dcdfe 100644 (file)
@@ -1,29 +1,6 @@
 #ifndef _LINUX_I2C_ALGO_PXA_H
 #define _LINUX_I2C_ALGO_PXA_H
 
-struct i2c_eeprom_emu_watcher {
-       void (*write)(void *, unsigned int addr, unsigned char newval);
-};
-
-struct i2c_eeprom_emu_watch {
-       struct list_head node;
-       unsigned int start;
-       unsigned int end;
-       struct i2c_eeprom_emu_watcher *ops;
-       void *data;
-};
-
-#define I2C_EEPROM_EMU_SIZE (256)
-
-struct i2c_eeprom_emu {
-       unsigned int size;
-       unsigned int ptr;
-       unsigned int seen_start;
-       struct list_head watch;
-
-       unsigned char bytes[I2C_EEPROM_EMU_SIZE];
-};
-
 typedef enum i2c_slave_event_e {
        I2C_SLAVE_EVENT_START_READ,
        I2C_SLAVE_EVENT_START_WRITE,
@@ -37,12 +14,4 @@ struct i2c_slave_client {
        void (*write)(void *ptr, unsigned int val);
 };
 
-extern int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *, void *data,
-                                    unsigned int addr, unsigned int size,
-                                    struct i2c_eeprom_emu_watcher *);
-
-extern void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *, void *data, struct i2c_eeprom_emu_watcher *watcher);
-
-extern struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void);
-
 #endif /* _LINUX_I2C_ALGO_PXA_H */
index c115e9e..52f53e2 100644 (file)
@@ -461,7 +461,7 @@ struct i2o_driver {
        int (*reply) (struct i2o_controller *, u32, struct i2o_message *);
 
        /* Event handler */
-       void (*event) (struct i2o_event *);
+       work_func_t event;
 
        struct workqueue_struct *event_queue;   /* Event queue */
 
@@ -490,7 +490,7 @@ struct i2o_dma {
  */
 struct i2o_pool {
        char *name;
-       kmem_cache_t *slab;
+       struct kmem_cache *slab;
        mempool_t *mempool;
 };
 
@@ -986,7 +986,8 @@ extern void i2o_driver_unregister(struct i2o_driver *);
 
 /**
  *     i2o_driver_notify_controller_add - Send notification of added controller
- *                                        to a single I2O driver
+ *     @drv: I2O driver
+ *     @c: I2O controller
  *
  *     Send notification of added controller to a single registered driver.
  */
@@ -998,8 +999,9 @@ static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv,
 };
 
 /**
- *     i2o_driver_notify_controller_remove - Send notification of removed
- *                                           controller to a single I2O driver
+ *     i2o_driver_notify_controller_remove - Send notification of removed controller
+ *     @drv: I2O driver
+ *     @c: I2O controller
  *
  *     Send notification of removed controller to a single registered driver.
  */
@@ -1011,8 +1013,9 @@ static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv,
 };
 
 /**
- *     i2o_driver_notify_device_add - Send notification of added device to a
- *                                    single I2O driver
+ *     i2o_driver_notify_device_add - Send notification of added device
+ *     @drv: I2O driver
+ *     @i2o_dev: the added i2o_device
  *
  *     Send notification of added device to a single registered driver.
  */
@@ -1025,7 +1028,8 @@ static inline void i2o_driver_notify_device_add(struct i2o_driver *drv,
 
 /**
  *     i2o_driver_notify_device_remove - Send notification of removed device
- *                                       to a single I2O driver
+ *     @drv: I2O driver
+ *     @i2o_dev: the added i2o_device
  *
  *     Send notification of removed device to a single registered driver.
  */
@@ -1148,7 +1152,7 @@ static inline void i2o_msg_post(struct i2o_controller *c,
 /**
  *     i2o_msg_post_wait - Post and wait a message and wait until return
  *     @c: controller
- *     @m: message to post
+ *     @msg: message to post
  *     @timeout: time in seconds to wait
  *
  *     This API allows an OSM to post a message and then be told whether or
index 9c20502..e26a039 100644 (file)
@@ -796,6 +796,7 @@ typedef struct hwif_s {
        unsigned        sg_mapped  : 1; /* sg_table and sg_nents are ready */
        unsigned        no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
        unsigned        err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
+       unsigned        atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */
 
        struct device   gendev;
        struct completion gendev_rel_comp; /* To deal with device release() */
@@ -803,8 +804,6 @@ typedef struct hwif_s {
        void            *hwif_data;     /* extra hwif data */
 
        unsigned dma;
-
-       void (*led_act)(void *data, int rw);
 } ____cacheline_internodealigned_in_smp ide_hwif_t;
 
 /*
index dbe8f61..d557e4c 100644 (file)
@@ -52,4 +52,10 @@ struct ifa_cacheinfo
        __u32   tstamp; /* updated timestamp, hundredths of seconds */
 };
 
+/* backwards compatibility for userspace */
+#ifndef __KERNEL__
+#define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
+
 #endif
index e963a07..35ed3b5 100644 (file)
@@ -82,6 +82,12 @@ enum
 
 #define IFLA_MAX (__IFLA_MAX - 1)
 
+/* backwards compatibility for userspace */
+#ifndef __KERNEL__
+#define IFLA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
+#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+#endif
+
 /* ifi_flags.
 
    IFF_* flags.
index 5eb5d24..5a593a1 100644 (file)
@@ -111,6 +111,7 @@ extern void setup_arch(char **);
 #define subsys_initcall_sync(fn)       __define_initcall("4s",fn,4s)
 #define fs_initcall(fn)                        __define_initcall("5",fn,5)
 #define fs_initcall_sync(fn)           __define_initcall("5s",fn,5s)
+#define rootfs_initcall(fn)            __define_initcall("rootfs",fn,rootfs)
 #define device_initcall(fn)            __define_initcall("6",fn,6)
 #define device_initcall_sync(fn)       __define_initcall("6s",fn,6s)
 #define late_initcall(fn)              __define_initcall("7",fn,7)
index 33c5daa..b531515 100644 (file)
@@ -7,16 +7,15 @@
 #include <linux/utsname.h>
 #include <linux/lockdep.h>
 #include <linux/ipc.h>
+#include <linux/pid_namespace.h>
 
 #define INIT_FDTABLE \
 {                                                      \
        .max_fds        = NR_OPEN_DEFAULT,              \
-       .max_fdset      = EMBEDDED_FD_SET_SIZE,         \
        .fd             = &init_files.fd_array[0],      \
        .close_on_exec  = (fd_set *)&init_files.close_on_exec_init, \
        .open_fds       = (fd_set *)&init_files.open_fds_init,  \
        .rcu            = RCU_HEAD_INIT,                \
-       .free_files     = NULL,                         \
        .next           = NULL,                         \
 }
 
        .cpu_vm_mask    = CPU_MASK_ALL,                         \
 }
 
-#define INIT_SIGNALS(sig) {    \
-       .count          = ATOMIC_INIT(1),               \
+#define INIT_SIGNALS(sig) {                                            \
+       .count          = ATOMIC_INIT(1),                               \
        .wait_chldexit  = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
-       .shared_pending = {                             \
+       .shared_pending = {                                             \
                .list = LIST_HEAD_INIT(sig.shared_pending.list),        \
-               .signal =  {{0}}}, \
+               .signal =  {{0}}},                                      \
        .posix_timers    = LIST_HEAD_INIT(sig.posix_timers),            \
        .cpu_timers     = INIT_CPU_TIMERS(sig.cpu_timers),              \
        .rlim           = INIT_RLIMITS,                                 \
        .pgrp           = 1,                                            \
-       .session        = 1,                                            \
+       .tty_old_pgrp   = 0,                                            \
+       { .__session      = 1},                                         \
 }
 
 extern struct nsproxy init_nsproxy;
 #define INIT_NSPROXY(nsproxy) {                                                \
+       .pid_ns         = &init_pid_ns,                                 \
        .count          = ATOMIC_INIT(1),                               \
-       .nslock         = SPIN_LOCK_UNLOCKED,                           \
+       .nslock         = __SPIN_LOCK_UNLOCKED(nsproxy.nslock),         \
+       .id             = 0,                                            \
        .uts_ns         = &init_uts_ns,                                 \
-       .namespace      = NULL,                                         \
+       .mnt_ns         = NULL,                                         \
        INIT_IPC_NS(ipc_ns)                                             \
 }
 
index c38507b..4e61158 100644 (file)
@@ -663,7 +663,7 @@ struct input_absinfo {
 #define BUS_GSC                        0x1A
 
 /*
- * Values describing the status of an effect
+ * Values describing the status of a force-feedback effect
  */
 #define FF_STATUS_STOPPED      0x00
 #define FF_STATUS_PLAYING      0x01
@@ -680,7 +680,7 @@ struct input_absinfo {
  */
 
 /**
- * struct ff_replay - defines scheduling of the effect
+ * struct ff_replay - defines scheduling of the force-feedback effect
  * @length: duration of the effect
  * @delay: delay before effect should start playing
  */
@@ -690,7 +690,7 @@ struct ff_replay {
 };
 
 /**
- * struct ff_trigger - defines what triggers the effect
+ * struct ff_trigger - defines what triggers the force-feedback effect
  * @button: number of the button triggering the effect
  * @interval: controls how soon the effect can be re-triggered
  */
@@ -700,7 +700,7 @@ struct ff_trigger {
 };
 
 /**
- * struct ff_envelope - generic effect envelope
+ * struct ff_envelope - generic force-feedback effect envelope
  * @attack_length: duration of the attack (ms)
  * @attack_level: level at the beginning of the attack
  * @fade_length: duration of fade (ms)
@@ -719,7 +719,7 @@ struct ff_envelope {
 };
 
 /**
- * struct ff_constant_effect - defines parameters of a constant effect
+ * struct ff_constant_effect - defines parameters of a constant force-feedback effect
  * @level: strength of the effect; may be negative
  * @envelope: envelope data
  */
@@ -729,7 +729,7 @@ struct ff_constant_effect {
 };
 
 /**
- * struct ff_ramp_effect - defines parameters of a ramp effect
+ * struct ff_ramp_effect - defines parameters of a ramp force-feedback effect
  * @start_level: beginning strength of the effect; may be negative
  * @end_level: final strength of the effect; may be negative
  * @envelope: envelope data
@@ -741,7 +741,7 @@ struct ff_ramp_effect {
 };
 
 /**
- * struct ff_condition_effect - defines a spring or friction effect
+ * struct ff_condition_effect - defines a spring or friction force-feedback effect
  * @right_saturation: maximum level when joystick moved all way to the right
  * @left_saturation: same for the left side
  * @right_coeff: controls how fast the force grows when the joystick moves
@@ -762,7 +762,7 @@ struct ff_condition_effect {
 };
 
 /**
- * struct ff_periodic_effect - defines parameters of a periodic effect
+ * struct ff_periodic_effect - defines parameters of a periodic force-feedback effect
  * @waveform: kind of the effect (wave)
  * @period: period of the wave (ms)
  * @magnitude: peak value
@@ -793,7 +793,7 @@ struct ff_periodic_effect {
 };
 
 /**
- * struct ff_rumble_effect - defines parameters of a periodic effect
+ * struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
  * @strong_magnitude: magnitude of the heavy motor
  * @weak_magnitude: magnitude of the light one
  *
index 5b83e7b..e36e86c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/hardirq.h>
 #include <linux/sched.h>
 #include <linux/irqflags.h>
+#include <linux/bottom_half.h>
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -217,12 +218,6 @@ static inline void __deprecated save_and_cli(unsigned long *x)
 #define save_and_cli(x)        save_and_cli(&x)
 #endif /* CONFIG_SMP */
 
-extern void local_bh_disable(void);
-extern void __local_bh_enable(void);
-extern void _local_bh_enable(void);
-extern void local_bh_enable(void);
-extern void local_bh_enable_ip(unsigned long ip);
-
 /* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
    frequency threaded job scheduling. For almost all the purposes
    tasklets are more than enough. F.e. all serial device BHs et
@@ -236,7 +231,8 @@ enum
        NET_TX_SOFTIRQ,
        NET_RX_SOFTIRQ,
        BLOCK_SOFTIRQ,
-       TASKLET_SOFTIRQ
+       TASKLET_SOFTIRQ,
+       SCHED_SOFTIRQ,
 };
 
 /* softirq mask and active fields moved to irq_cpustat_t in
index 796ca00..7a9db39 100644 (file)
@@ -208,6 +208,15 @@ struct kernel_ipmi_msg
    code as the first byte of the incoming data, unlike a response. */
 
 
+/*
+ * Modes for ipmi_set_maint_mode() and the userland IOCTL.  The AUTO
+ * setting is the default and means it will be set on certain
+ * commands.  Hard setting it on and off will override automatic
+ * operation.
+ */
+#define IPMI_MAINTENANCE_MODE_AUTO     0
+#define IPMI_MAINTENANCE_MODE_OFF      1
+#define IPMI_MAINTENANCE_MODE_ON       2
 
 #ifdef __KERNEL__
 
@@ -373,6 +382,35 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
                            unsigned char cmd,
                            unsigned int  chans);
 
+/*
+ * Go into a mode where the driver will not autonomously attempt to do
+ * things with the interface.  It will still respond to attentions and
+ * interrupts, and it will expect that commands will complete.  It
+ * will not automatcially check for flags, events, or things of that
+ * nature.
+ *
+ * This is primarily used for firmware upgrades.  The idea is that
+ * when you go into firmware upgrade mode, you do this operation
+ * and the driver will not attempt to do anything but what you tell
+ * it or what the BMC asks for.
+ *
+ * Note that if you send a command that resets the BMC, the driver
+ * will still expect a response from that command.  So the BMC should
+ * reset itself *after* the response is sent.  Resetting before the
+ * response is just silly.
+ *
+ * If in auto maintenance mode, the driver will automatically go into
+ * maintenance mode for 30 seconds if it sees a cold reset, a warm
+ * reset, or a firmware NetFN.  This means that code that uses only
+ * firmware NetFN commands to do upgrades will work automatically
+ * without change, assuming it sends a message every 30 seconds or
+ * less.
+ *
+ * See the IPMI_MAINTENANCE_MODE_xxx defines for what the mode means.
+ */
+int ipmi_get_maintenance_mode(ipmi_user_t user);
+int ipmi_set_maintenance_mode(ipmi_user_t user, int mode);
+
 /*
  * Allow run-to-completion mode to be set for the interface of
  * a specific user.
@@ -656,4 +694,11 @@ struct ipmi_timing_parms
 #define IPMICTL_GET_TIMING_PARMS_CMD   _IOR(IPMI_IOC_MAGIC, 23, \
                                             struct ipmi_timing_parms)
 
+/*
+ * Set the maintenance mode.  See ipmi_set_maintenance_mode() above
+ * for a description of what this does.
+ */
+#define IPMICTL_GET_MAINTENANCE_MODE_CMD       _IOR(IPMI_IOC_MAGIC, 30, int)
+#define IPMICTL_SET_MAINTENANCE_MODE_CMD       _IOW(IPMI_IOC_MAGIC, 31, int)
+
 #endif /* __LINUX_IPMI_H */
index 4d04d8b..b56a158 100644 (file)
@@ -46,6 +46,8 @@
 #define IPMI_NETFN_APP_REQUEST                 0x06
 #define IPMI_NETFN_APP_RESPONSE                        0x07
 #define IPMI_GET_DEVICE_ID_CMD         0x01
+#define IPMI_COLD_RESET_CMD            0x02
+#define IPMI_WARM_RESET_CMD            0x03
 #define IPMI_CLEAR_MSG_FLAGS_CMD       0x30
 #define IPMI_GET_DEVICE_GUID_CMD       0x08
 #define IPMI_GET_MSG_FLAGS_CMD         0x31
 #define IPMI_NETFN_STORAGE_RESPONSE            0x0b
 #define IPMI_ADD_SEL_ENTRY_CMD         0x44
 
+#define IPMI_NETFN_FIRMWARE_REQUEST            0x08
+#define IPMI_NETFN_FIRMWARE_RESPONSE           0x09
+
 /* The default slave address */
 #define IPMI_BMC_SLAVE_ADDR    0x20
 
 /* The BT interface on high-end HP systems supports up to 255 bytes in
  * one transfer.  Its "virtual" BMC supports some commands that are longer
  * than 128 bytes.  Use the full 256, plus NetFn/LUN, Cmd, cCode, plus
- * some overhead.  It would be nice to base this on the "BT Capabilities"
- * but that's too hard to propagate to the rest of the driver. */
+ * some overhead; it's not worth the effort to dynamically size this based
+ * on the results of the "Get BT Capabilities" command. */
 #define IPMI_MAX_MSG_LENGTH    272     /* multiple of 16 */
 
 #define IPMI_CC_NO_ERROR               0x00
 #define IPMI_NODE_BUSY_ERR             0xc0
 #define IPMI_INVALID_COMMAND_ERR       0xc1
+#define IPMI_TIMEOUT_ERR               0xc3
 #define IPMI_ERR_MSG_TRUNCATED         0xc6
+#define IPMI_REQ_LEN_INVALID_ERR       0xc7
+#define IPMI_REQ_LEN_EXCEEDED_ERR      0xc8
+#define IPMI_NOT_IN_MY_STATE_ERR       0xd5    /* IPMI 2.0 */
 #define IPMI_LOST_ARBITRATION_ERR      0x81
 #define IPMI_BUS_ERR                   0x82
 #define IPMI_NAK_ON_WRITE_ERR          0x83
index 6d9c7e4..c063310 100644 (file)
@@ -115,6 +115,13 @@ struct ipmi_smi_handlers
           poll for operations during things like crash dumps. */
        void (*poll)(void *send_info);
 
+       /* Enable/disable firmware maintenance mode.  Note that this
+          is *not* the modes defined, this is simply an on/off
+          setting.  The message handler does the mode handling.  Note
+          that this is called from interupt context, so it cannot
+          block. */
+       void (*set_maintenance_mode)(void *send_info, int enable);
+
        /* Tell the handler that we are using it/not using it.  The
           message handler get the modules that this handler belongs
           to; this function lets the SMI claim any modules that it
@@ -173,6 +180,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                      void                     *send_info,
                      struct ipmi_device_id    *device_id,
                      struct device            *dev,
+                     const char               *sysfs_name,
                      unsigned char            slave_addr);
 
 /*
index 6299114..3c7875b 100644 (file)
@@ -511,8 +511,8 @@ typedef struct modem_info {
 #endif
   struct tty_struct    *tty;            /* Pointer to corresponding tty   */
   atemu                 emu;             /* AT-emulator data               */
-  struct termios       normal_termios;  /* For saving termios structs     */
-  struct termios       callout_termios;
+  struct ktermios      normal_termios;  /* For saving termios structs     */
+  struct ktermios      callout_termios;
   wait_queue_head_t    open_wait, close_wait;
   struct semaphore      write_sem;
   spinlock_t           readlock;
@@ -525,8 +525,8 @@ typedef struct _isdn_modem {
   int                refcount;                         /* Number of opens        */
   struct tty_driver  *tty_modem;                       /* tty-device             */
   struct tty_struct  *modem_table[ISDN_MAX_CHANNELS];  /* ?? copied from Orig    */
-  struct termios     *modem_termios[ISDN_MAX_CHANNELS];
-  struct termios     *modem_termios_locked[ISDN_MAX_CHANNELS];
+  struct ktermios     *modem_termios[ISDN_MAX_CHANNELS];
+  struct ktermios     *modem_termios_locked[ISDN_MAX_CHANNELS];
   modem_info         info[ISDN_MAX_CHANNELS];     /* Private data           */
 } isdn_modem_t;
 
index b55e2a0..106a5e8 100644 (file)
  *     communication with the slave board will always be on a per port
  *     basis.
  */
-typedef struct {
+struct stliport {
        unsigned long           magic;
-       int                     portnr;
-       int                     panelnr;
-       int                     brdnr;
+       unsigned int            portnr;
+       unsigned int            panelnr;
+       unsigned int            brdnr;
        unsigned long           state;
-       int                     devnr;
+       unsigned int            devnr;
        int                     flags;
        int                     baud_base;
        int                     custom_divisor;
@@ -72,7 +72,7 @@ typedef struct {
        wait_queue_head_t       close_wait;
        wait_queue_head_t       raw_wait;
        struct work_struct      tqhangup;
-       asysigs_t               asig;
+       struct asysigs          asig;
        unsigned long           addr;
        unsigned long           rxoffset;
        unsigned long           txoffset;
@@ -83,31 +83,31 @@ typedef struct {
        unsigned char           reqbit;
        unsigned char           portidx;
        unsigned char           portbit;
-} stliport_t;
+};
 
 /*
  *     Use a structure of function pointers to do board level operations.
  *     These include, enable/disable, paging shared memory, interrupting, etc.
  */
-typedef struct stlibrd {
+struct stlibrd {
        unsigned long   magic;
-       int             brdnr;
-       int             brdtype;
-       int             state;
-       int             nrpanels;
-       int             nrports;
-       int             nrdevs;
+       unsigned int    brdnr;
+       unsigned int    brdtype;
+       unsigned int    state;
+       unsigned int    nrpanels;
+       unsigned int    nrports;
+       unsigned int    nrdevs;
        unsigned int    iobase;
        int             iosize;
        unsigned long   memaddr;
        void            __iomem *membase;
-       int             memsize;
+       unsigned long   memsize;
        int             pagesize;
        int             hostoffset;
        int             slaveoffset;
        int             bitsize;
        int             enabval;
-       int             panels[STL_MAXPANELS];
+       unsigned int    panels[STL_MAXPANELS];
        int             panelids[STL_MAXPANELS];
        void            (*init)(struct stlibrd *brdp);
        void            (*enable)(struct stlibrd *brdp);
@@ -116,8 +116,8 @@ typedef struct stlibrd {
        void            __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
        void            (*intr)(struct stlibrd *brdp);
        void            (*reset)(struct stlibrd *brdp);
-       stliport_t      *ports[STL_MAXPORTS];
-} stlibrd_t;
+       struct stliport *ports[STL_MAXPORTS];
+};
 
 
 /*
index fe89444..4527375 100644 (file)
@@ -839,7 +839,6 @@ struct journal_s
  */
 
 /* Filing buffers */
-extern void __journal_temp_unlink_buffer(struct journal_head *jh);
 extern void journal_unfile_buffer(journal_t *, struct journal_head *);
 extern void __journal_unfile_buffer(struct journal_head *);
 extern void __journal_refile_buffer(struct journal_head *);
@@ -949,7 +948,7 @@ void journal_put_journal_head(struct journal_head *jh);
 /*
  * handle management
  */
-extern kmem_cache_t *jbd_handle_cache;
+extern struct kmem_cache *jbd_handle_cache;
 
 static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags)
 {
index ddb1287..0e0fedd 100644 (file)
@@ -848,7 +848,6 @@ struct journal_s
  */
 
 /* Filing buffers */
-extern void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
 extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *);
 extern void __jbd2_journal_unfile_buffer(struct journal_head *);
 extern void __jbd2_journal_refile_buffer(struct journal_head *);
@@ -958,7 +957,7 @@ void jbd2_journal_put_journal_head(struct journal_head *jh);
 /*
  * handle management
  */
-extern kmem_cache_t *jbd2_handle_cache;
+extern struct kmem_cache *jbd2_handle_cache;
 
 static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags)
 {
index efe0ee4..06c58c4 100644 (file)
@@ -158,7 +158,7 @@ static inline void con_schedule_flip(struct tty_struct *t)
        if (t->buf.tail != NULL)
                t->buf.tail->commit = t->buf.tail->used;
        spin_unlock_irqrestore(&t->buf.lock, flags);
-       schedule_work(&t->buf.work);
+       schedule_delayed_work(&t->buf.work, 0);
 }
 
 #endif
index 6738283..b0c4a05 100644 (file)
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/bitops.h>
+#include <linux/log2.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
-extern const char linux_banner[];
-
 #define INT_MAX                ((int)(~0U>>1))
 #define INT_MIN                (-INT_MAX - 1)
 #define UINT_MAX       (~0U)
@@ -157,20 +156,6 @@ static inline int printk(const char *s, ...) { return 0; }
 
 unsigned long int_sqrt(unsigned long);
 
-static inline int __attribute_pure__ long_log2(unsigned long x)
-{
-       int r = 0;
-       for (x >>= 1; x > 0; x >>= 1)
-               r++;
-       return r;
-}
-
-static inline unsigned long
-__attribute_const__ roundup_pow_of_two(unsigned long x)
-{
-       return 1UL << fls_long(x - 1);
-}
-
 extern int printk_ratelimit(void);
 extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
index a4ede62..d02425c 100644 (file)
@@ -105,9 +105,14 @@ extern struct page *kimage_alloc_control_pages(struct kimage *image,
                                                unsigned int order);
 extern void crash_kexec(struct pt_regs *);
 int kexec_should_crash(struct task_struct *);
+void crash_save_cpu(struct pt_regs *regs, int cpu);
 extern struct kimage *kexec_image;
 extern struct kimage *kexec_crash_image;
 
+#ifndef kexec_flush_icache_page
+#define kexec_flush_icache_page(page)
+#endif
+
 #define KEXEC_ON_CRASH  0x00000001
 #define KEXEC_ARCH_MASK 0xffff0000
 
@@ -133,6 +138,7 @@ extern struct resource crashk_res;
 typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
 extern note_buf_t *crash_notes;
 
+
 #else /* !CONFIG_KEXEC */
 struct pt_regs;
 struct task_struct;
index ac4c055..769be39 100644 (file)
@@ -165,7 +165,7 @@ extern void arch_disarm_kprobe(struct kprobe *p);
 extern int arch_init_kprobes(void);
 extern void show_registers(struct pt_regs *regs);
 extern kprobe_opcode_t *get_insn_slot(void);
-extern void free_insn_slot(kprobe_opcode_t *slot);
+extern void free_insn_slot(kprobe_opcode_t *slot, int dirty);
 extern void kprobes_inc_nmissed_count(struct kprobe *p);
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
index 84eeecd..611f17f 100644 (file)
@@ -248,9 +248,9 @@ static inline struct timeval ktime_to_timeval(const ktime_t kt)
  *
  * Returns the scalar nanoseconds representation of kt
  */
-static inline u64 ktime_to_ns(const ktime_t kt)
+static inline s64 ktime_to_ns(const ktime_t kt)
 {
-       return (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
+       return (s64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
 }
 
 #endif
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
new file mode 100644 (file)
index 0000000..5bb2c3c
--- /dev/null
@@ -0,0 +1,227 @@
+#ifndef __LINUX_KVM_H
+#define __LINUX_KVM_H
+
+/*
+ * Userspace interface for /dev/kvm - kernel based virtual machine
+ *
+ * Note: this interface is considered experimental and may change without
+ *       notice.
+ */
+
+#include <asm/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * Architectural interrupt line count, and the size of the bitmap needed
+ * to hold them.
+ */
+#define KVM_NR_INTERRUPTS 256
+#define KVM_IRQ_BITMAP_SIZE_BYTES    ((KVM_NR_INTERRUPTS + 7) / 8)
+#define KVM_IRQ_BITMAP_SIZE(type)    (KVM_IRQ_BITMAP_SIZE_BYTES / sizeof(type))
+
+
+/* for KVM_CREATE_MEMORY_REGION */
+struct kvm_memory_region {
+       __u32 slot;
+       __u32 flags;
+       __u64 guest_phys_addr;
+       __u64 memory_size; /* bytes */
+};
+
+/* for kvm_memory_region::flags */
+#define KVM_MEM_LOG_DIRTY_PAGES  1UL
+
+
+#define KVM_EXIT_TYPE_FAIL_ENTRY 1
+#define KVM_EXIT_TYPE_VM_EXIT    2
+
+enum kvm_exit_reason {
+       KVM_EXIT_UNKNOWN          = 0,
+       KVM_EXIT_EXCEPTION        = 1,
+       KVM_EXIT_IO               = 2,
+       KVM_EXIT_CPUID            = 3,
+       KVM_EXIT_DEBUG            = 4,
+       KVM_EXIT_HLT              = 5,
+       KVM_EXIT_MMIO             = 6,
+};
+
+/* for KVM_RUN */
+struct kvm_run {
+       /* in */
+       __u32 vcpu;
+       __u32 emulated;  /* skip current instruction */
+       __u32 mmio_completed; /* mmio request completed */
+
+       /* out */
+       __u32 exit_type;
+       __u32 exit_reason;
+       __u32 instruction_length;
+       union {
+               /* KVM_EXIT_UNKNOWN */
+               struct {
+                       __u32 hardware_exit_reason;
+               } hw;
+               /* KVM_EXIT_EXCEPTION */
+               struct {
+                       __u32 exception;
+                       __u32 error_code;
+               } ex;
+               /* KVM_EXIT_IO */
+               struct {
+#define KVM_EXIT_IO_IN  0
+#define KVM_EXIT_IO_OUT 1
+                       __u8 direction;
+                       __u8 size; /* bytes */
+                       __u8 string;
+                       __u8 string_down;
+                       __u8 rep;
+                       __u8 pad;
+                       __u16 port;
+                       __u64 count;
+                       union {
+                               __u64 address;
+                               __u32 value;
+                       };
+               } io;
+               struct {
+               } debug;
+               /* KVM_EXIT_MMIO */
+               struct {
+                       __u64 phys_addr;
+                       __u8  data[8];
+                       __u32 len;
+                       __u8  is_write;
+               } mmio;
+       };
+};
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+       /* in */
+       __u32 vcpu;
+       __u32 padding;
+
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 rax, rbx, rcx, rdx;
+       __u64 rsi, rdi, rsp, rbp;
+       __u64 r8,  r9,  r10, r11;
+       __u64 r12, r13, r14, r15;
+       __u64 rip, rflags;
+};
+
+struct kvm_segment {
+       __u64 base;
+       __u32 limit;
+       __u16 selector;
+       __u8  type;
+       __u8  present, dpl, db, s, l, g, avl;
+       __u8  unusable;
+       __u8  padding;
+};
+
+struct kvm_dtable {
+       __u64 base;
+       __u16 limit;
+       __u16 padding[3];
+};
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+       /* in */
+       __u32 vcpu;
+       __u32 padding;
+
+       /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+       struct kvm_segment cs, ds, es, fs, gs, ss;
+       struct kvm_segment tr, ldt;
+       struct kvm_dtable gdt, idt;
+       __u64 cr0, cr2, cr3, cr4, cr8;
+       __u64 efer;
+       __u64 apic_base;
+       __u64 interrupt_bitmap[KVM_IRQ_BITMAP_SIZE(__u64)];
+};
+
+struct kvm_msr_entry {
+       __u32 index;
+       __u32 reserved;
+       __u64 data;
+};
+
+/* for KVM_GET_MSRS and KVM_SET_MSRS */
+struct kvm_msrs {
+       __u32 vcpu;
+       __u32 nmsrs; /* number of msrs in entries */
+
+       struct kvm_msr_entry entries[0];
+};
+
+/* for KVM_GET_MSR_INDEX_LIST */
+struct kvm_msr_list {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 indices[0];
+};
+
+/* for KVM_TRANSLATE */
+struct kvm_translation {
+       /* in */
+       __u64 linear_address;
+       __u32 vcpu;
+       __u32 padding;
+
+       /* out */
+       __u64 physical_address;
+       __u8  valid;
+       __u8  writeable;
+       __u8  usermode;
+};
+
+/* for KVM_INTERRUPT */
+struct kvm_interrupt {
+       /* in */
+       __u32 vcpu;
+       __u32 irq;
+};
+
+struct kvm_breakpoint {
+       __u32 enabled;
+       __u32 padding;
+       __u64 address;
+};
+
+/* for KVM_DEBUG_GUEST */
+struct kvm_debug_guest {
+       /* int */
+       __u32 vcpu;
+       __u32 enabled;
+       struct kvm_breakpoint breakpoints[4];
+       __u32 singlestep;
+};
+
+/* for KVM_GET_DIRTY_LOG */
+struct kvm_dirty_log {
+       __u32 slot;
+       __u32 padding;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding;
+       };
+};
+
+#define KVMIO 0xAE
+
+#define KVM_RUN                   _IOWR(KVMIO, 2, struct kvm_run)
+#define KVM_GET_REGS              _IOWR(KVMIO, 3, struct kvm_regs)
+#define KVM_SET_REGS              _IOW(KVMIO, 4, struct kvm_regs)
+#define KVM_GET_SREGS             _IOWR(KVMIO, 5, struct kvm_sregs)
+#define KVM_SET_SREGS             _IOW(KVMIO, 6, struct kvm_sregs)
+#define KVM_TRANSLATE             _IOWR(KVMIO, 7, struct kvm_translation)
+#define KVM_INTERRUPT             _IOW(KVMIO, 8, struct kvm_interrupt)
+#define KVM_DEBUG_GUEST           _IOW(KVMIO, 9, struct kvm_debug_guest)
+#define KVM_SET_MEMORY_REGION     _IOW(KVMIO, 10, struct kvm_memory_region)
+#define KVM_CREATE_VCPU           _IOW(KVMIO, 11, int /* vcpu_slot */)
+#define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 12, struct kvm_dirty_log)
+#define KVM_GET_MSRS              _IOWR(KVMIO, 13, struct kvm_msrs)
+#define KVM_SET_MSRS              _IOWR(KVMIO, 14, struct kvm_msrs)
+#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 15, struct kvm_msr_list)
+
+#endif
index 202283b..ab27548 100644 (file)
@@ -575,8 +575,9 @@ struct ata_port {
        struct ata_host         *host;
        struct device           *dev;
 
-       struct work_struct      port_task;
-       struct work_struct      hotplug_task;
+       void                    *port_task_data;
+       struct delayed_work     port_task;
+       struct delayed_work     hotplug_task;
        struct work_struct      scsi_rescan_task;
 
        unsigned int            hsm_task_state;
@@ -755,7 +756,7 @@ extern void ata_host_resume(struct ata_host *host);
 extern int ata_ratelimit(void);
 extern int ata_busy_sleep(struct ata_port *ap,
                          unsigned long timeout_pat, unsigned long timeout);
-extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
+extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
                                void *data, unsigned long delay);
 extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
                             unsigned long interval_msec,
index 862d973..0c962b8 100644 (file)
@@ -164,14 +164,12 @@ void                nlmclnt_next_cookie(struct nlm_cookie *);
  */
 struct nlm_host * nlmclnt_lookup_host(const struct sockaddr_in *, int, int, const char *, int);
 struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *, const char *, int);
-struct nlm_host * nlm_lookup_host(int server, const struct sockaddr_in *, int, int, const char *, int);
 struct rpc_clnt * nlm_bind_host(struct nlm_host *);
 void             nlm_rebind_host(struct nlm_host *);
 struct nlm_host * nlm_get_host(struct nlm_host *);
 void             nlm_release_host(struct nlm_host *);
 void             nlm_shutdown_hosts(void);
 extern void      nlm_host_rebooted(const struct sockaddr_in *, const char *, int, u32);
-struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int);
 void             nsm_release(struct nsm_handle *);
 
 
@@ -208,7 +206,7 @@ void                  nlmsvc_invalidate_all(void);
 static __inline__ struct inode *
 nlmsvc_file_inode(struct nlm_file *file)
 {
-       return file->f_file->f_dentry->d_inode;
+       return file->f_file->f_path.dentry->d_inode;
 }
 
 /*
index 819f08f..498bfbd 100644 (file)
@@ -193,7 +193,6 @@ extern void lockdep_free_key_range(void *start, unsigned long size);
 
 extern void lockdep_off(void);
 extern void lockdep_on(void);
-extern int lockdep_internal(void);
 
 /*
  * These methods are used by specific locking variants (spinlocks,
@@ -243,6 +242,8 @@ extern void lock_release(struct lockdep_map *lock, int nested,
 
 # define INIT_LOCKDEP                          .lockdep_recursion = 0,
 
+#define lockdep_depth(tsk)     ((tsk)->lockdep_depth)
+
 #else /* !LOCKDEP */
 
 static inline void lockdep_off(void)
@@ -253,11 +254,6 @@ static inline void lockdep_on(void)
 {
 }
 
-static inline int lockdep_internal(void)
-{
-       return 0;
-}
-
 # define lock_acquire(l, s, t, r, c, i)                do { } while (0)
 # define lock_release(l, n, i)                 do { } while (0)
 # define lockdep_init()                                do { } while (0)
@@ -277,6 +273,9 @@ static inline int lockdep_internal(void)
  * The class key takes no space if lockdep is disabled:
  */
 struct lock_class_key { };
+
+#define lockdep_depth(tsk)     (0)
+
 #endif /* !LOCKDEP */
 
 #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
diff --git a/include/linux/log2.h b/include/linux/log2.h
new file mode 100644 (file)
index 0000000..d02e1a5
--- /dev/null
@@ -0,0 +1,157 @@
+/* Integer base 2 logarithm calculation
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_LOG2_H
+#define _LINUX_LOG2_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+/*
+ * deal with unrepresentable constant logarithms
+ */
+extern __attribute__((const, noreturn))
+int ____ilog2_NaN(void);
+
+/*
+ * non-constant log of base 2 calculators
+ * - the arch may override these in asm/bitops.h if they can be implemented
+ *   more efficiently than using fls() and fls64()
+ * - the arch is not required to handle n==0 if implementing the fallback
+ */
+#ifndef CONFIG_ARCH_HAS_ILOG2_U32
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+       return fls(n) - 1;
+}
+#endif
+
+#ifndef CONFIG_ARCH_HAS_ILOG2_U64
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+       return fls64(n) - 1;
+}
+#endif
+
+/*
+ * round up to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __roundup_pow_of_two(unsigned long n)
+{
+       return 1UL << fls_long(n - 1);
+}
+
+/**
+ * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
+ * @n - parameter
+ *
+ * constant-capable log of base 2 calculation
+ * - this can be used to initialise global variables from constant data, hence
+ *   the massive ternary operator construction
+ *
+ * selects the appropriately-sized optimised version depending on sizeof(n)
+ */
+#define ilog2(n)                               \
+(                                              \
+       __builtin_constant_p(n) ? (             \
+               (n) < 1 ? ____ilog2_NaN() :     \
+               (n) & (1ULL << 63) ? 63 :       \
+               (n) & (1ULL << 62) ? 62 :       \
+               (n) & (1ULL << 61) ? 61 :       \
+               (n) & (1ULL << 60) ? 60 :       \
+               (n) & (1ULL << 59) ? 59 :       \
+               (n) & (1ULL << 58) ? 58 :       \
+               (n) & (1ULL << 57) ? 57 :       \
+               (n) & (1ULL << 56) ? 56 :       \
+               (n) & (1ULL << 55) ? 55 :       \
+               (n) & (1ULL << 54) ? 54 :       \
+               (n) & (1ULL << 53) ? 53 :       \
+               (n) & (1ULL << 52) ? 52 :       \
+               (n) & (1ULL << 51) ? 51 :       \
+               (n) & (1ULL << 50) ? 50 :       \
+               (n) & (1ULL << 49) ? 49 :       \
+               (n) & (1ULL << 48) ? 48 :       \
+               (n) & (1ULL << 47) ? 47 :       \
+               (n) & (1ULL << 46) ? 46 :       \
+               (n) & (1ULL << 45) ? 45 :       \
+               (n) & (1ULL << 44) ? 44 :       \
+               (n) & (1ULL << 43) ? 43 :       \
+               (n) & (1ULL << 42) ? 42 :       \
+               (n) & (1ULL << 41) ? 41 :       \
+               (n) & (1ULL << 40) ? 40 :       \
+               (n) & (1ULL << 39) ? 39 :       \
+               (n) & (1ULL << 38) ? 38 :       \
+               (n) & (1ULL << 37) ? 37 :       \
+               (n) & (1ULL << 36) ? 36 :       \
+               (n) & (1ULL << 35) ? 35 :       \
+               (n) & (1ULL << 34) ? 34 :       \
+               (n) & (1ULL << 33) ? 33 :       \
+               (n) & (1ULL << 32) ? 32 :       \
+               (n) & (1ULL << 31) ? 31 :       \
+               (n) & (1ULL << 30) ? 30 :       \
+               (n) & (1ULL << 29) ? 29 :       \
+               (n) & (1ULL << 28) ? 28 :       \
+               (n) & (1ULL << 27) ? 27 :       \
+               (n) & (1ULL << 26) ? 26 :       \
+               (n) & (1ULL << 25) ? 25 :       \
+               (n) & (1ULL << 24) ? 24 :       \
+               (n) & (1ULL << 23) ? 23 :       \
+               (n) & (1ULL << 22) ? 22 :       \
+               (n) & (1ULL << 21) ? 21 :       \
+               (n) & (1ULL << 20) ? 20 :       \
+               (n) & (1ULL << 19) ? 19 :       \
+               (n) & (1ULL << 18) ? 18 :       \
+               (n) & (1ULL << 17) ? 17 :       \
+               (n) & (1ULL << 16) ? 16 :       \
+               (n) & (1ULL << 15) ? 15 :       \
+               (n) & (1ULL << 14) ? 14 :       \
+               (n) & (1ULL << 13) ? 13 :       \
+               (n) & (1ULL << 12) ? 12 :       \
+               (n) & (1ULL << 11) ? 11 :       \
+               (n) & (1ULL << 10) ? 10 :       \
+               (n) & (1ULL <<  9) ?  9 :       \
+               (n) & (1ULL <<  8) ?  8 :       \
+               (n) & (1ULL <<  7) ?  7 :       \
+               (n) & (1ULL <<  6) ?  6 :       \
+               (n) & (1ULL <<  5) ?  5 :       \
+               (n) & (1ULL <<  4) ?  4 :       \
+               (n) & (1ULL <<  3) ?  3 :       \
+               (n) & (1ULL <<  2) ?  2 :       \
+               (n) & (1ULL <<  1) ?  1 :       \
+               (n) & (1ULL <<  0) ?  0 :       \
+               ____ilog2_NaN()                 \
+                                  ) :          \
+       (sizeof(n) <= 4) ?                      \
+       __ilog2_u32(n) :                        \
+       __ilog2_u64(n)                          \
+ )
+
+/**
+ * roundup_pow_of_two - round the given value up to nearest power of two
+ * @n - parameter
+ *
+ * round the given balue up to the nearest power of two
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define roundup_pow_of_two(n)                  \
+(                                              \
+       __builtin_constant_p(n) ? (             \
+               (n == 1) ? 0 :                  \
+               (1UL << (ilog2((n) - 1) + 1))   \
+                                  ) :          \
+       __roundup_pow_of_two(n)                 \
+ )
+
+#endif /* _LINUX_LOG2_H */
index d538de9..a17b147 100644 (file)
@@ -114,6 +114,8 @@ struct vm_area_struct {
 #endif
 };
 
+extern struct kmem_cache *vm_area_cachep;
+
 /*
  * This struct defines the per-mm list of VMAs for uClinux. If CONFIG_MMU is
  * disabled, then there's a single shared list of VMAs maintained by the
@@ -293,6 +295,24 @@ void put_pages_list(struct list_head *pages);
 
 void split_page(struct page *page, unsigned int order);
 
+/*
+ * Compound pages have a destructor function.  Provide a
+ * prototype for that function and accessor functions.
+ * These are _only_ valid on the head of a PG_compound page.
+ */
+typedef void compound_page_dtor(struct page *);
+
+static inline void set_compound_page_dtor(struct page *page,
+                                               compound_page_dtor *dtor)
+{
+       page[1].lru.next = (void *)dtor;
+}
+
+static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
+{
+       return (compound_page_dtor *)page[1].lru.next;
+}
+
 /*
  * Multiple processes may "see" the same page. E.g. for untouched
  * mappings of /dev/null, all processes see the same page full of
@@ -396,7 +416,9 @@ void split_page(struct page *page, unsigned int order);
  * We are going to use the flags for the page to node mapping if its in
  * there.  This includes the case where there is no node, so it is implicit.
  */
-#define FLAGS_HAS_NODE         (NODES_WIDTH > 0 || NODES_SHIFT == 0)
+#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
+#define NODE_NOT_IN_PAGE_FLAGS
+#endif
 
 #ifndef PFN_SECTION_SHIFT
 #define PFN_SECTION_SHIFT 0
@@ -411,13 +433,18 @@ void split_page(struct page *page, unsigned int order);
 #define NODES_PGSHIFT          (NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT          (ZONES_PGOFF * (ZONES_WIDTH != 0))
 
-/* NODE:ZONE or SECTION:ZONE is used to lookup the zone from a page. */
-#if FLAGS_HAS_NODE
-#define ZONETABLE_SHIFT                (NODES_SHIFT + ZONES_SHIFT)
+/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */
+#ifdef NODE_NOT_IN_PAGEFLAGS
+#define ZONEID_SHIFT           (SECTIONS_SHIFT + ZONES_SHIFT)
+#else
+#define ZONEID_SHIFT           (NODES_SHIFT + ZONES_SHIFT)
+#endif
+
+#if ZONES_WIDTH > 0
+#define ZONEID_PGSHIFT         ZONES_PGSHIFT
 #else
-#define ZONETABLE_SHIFT                (SECTIONS_SHIFT + ZONES_SHIFT)
+#define ZONEID_PGSHIFT         NODES_PGOFF
 #endif
-#define ZONETABLE_PGSHIFT      ZONES_PGSHIFT
 
 #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
 #error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
@@ -426,26 +453,28 @@ void split_page(struct page *page, unsigned int order);
 #define ZONES_MASK             ((1UL << ZONES_WIDTH) - 1)
 #define NODES_MASK             ((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK          ((1UL << SECTIONS_WIDTH) - 1)
-#define ZONETABLE_MASK         ((1UL << ZONETABLE_SHIFT) - 1)
+#define ZONEID_MASK            ((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type page_zonenum(struct page *page)
 {
        return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
 }
 
-struct zone;
-extern struct zone *zone_table[];
-
+/*
+ * The identification function is only used by the buddy allocator for
+ * determining if two pages could be buddies. We are not really
+ * identifying a zone since we could be using a the section number
+ * id if we have not node id available in page flags.
+ * We guarantee only that it will return the same value for two
+ * combinable pages in a zone.
+ */
 static inline int page_zone_id(struct page *page)
 {
-       return (page->flags >> ZONETABLE_PGSHIFT) & ZONETABLE_MASK;
-}
-static inline struct zone *page_zone(struct page *page)
-{
-       return zone_table[page_zone_id(page)];
+       BUILD_BUG_ON(ZONEID_PGSHIFT == 0 && ZONEID_MASK);
+       return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
 }
 
-static inline unsigned long zone_to_nid(struct zone *zone)
+static inline int zone_to_nid(struct zone *zone)
 {
 #ifdef CONFIG_NUMA
        return zone->node;
@@ -454,13 +483,20 @@ static inline unsigned long zone_to_nid(struct zone *zone)
 #endif
 }
 
-static inline unsigned long page_to_nid(struct page *page)
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+extern int page_to_nid(struct page *page);
+#else
+static inline int page_to_nid(struct page *page)
+{
+       return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
+}
+#endif
+
+static inline struct zone *page_zone(struct page *page)
 {
-       if (FLAGS_HAS_NODE)
-               return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
-       else
-               return zone_to_nid(page_zone(page));
+       return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
 }
+
 static inline unsigned long page_to_section(struct page *page)
 {
        return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
@@ -477,6 +513,7 @@ static inline void set_page_node(struct page *page, unsigned long node)
        page->flags &= ~(NODES_MASK << NODES_PGSHIFT);
        page->flags |= (node & NODES_MASK) << NODES_PGSHIFT;
 }
+
 static inline void set_page_section(struct page *page, unsigned long section)
 {
        page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
@@ -947,8 +984,6 @@ extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
-extern void zonetable_add(struct zone *zone, int nid, enum zone_type zid,
-                                       unsigned long pfn, unsigned long size);
 
 #ifdef CONFIG_NUMA
 extern void setup_per_cpu_pageset(void);
index 528e7d3..c15ae19 100644 (file)
@@ -110,7 +110,7 @@ struct mmc_host {
        struct mmc_card         *card_busy;     /* the MMC card claiming host */
        struct mmc_card         *card_selected; /* the selected MMC card */
 
-       struct work_struct      detect;
+       struct delayed_work     detect;
 
        unsigned long           private[0] ____cacheline_aligned;
 };
index e06683e..e339a73 100644 (file)
@@ -278,7 +278,7 @@ struct zone {
        /*
         * rarely used fields:
         */
-       char                    *name;
+       const char              *name;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -288,19 +288,94 @@ struct zone {
  */
 #define DEF_PRIORITY 12
 
+/* Maximum number of zones on a zonelist */
+#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
+
+#ifdef CONFIG_NUMA
+/*
+ * We cache key information from each zonelist for smaller cache
+ * footprint when scanning for free pages in get_page_from_freelist().
+ *
+ * 1) The BITMAP fullzones tracks which zones in a zonelist have come
+ *    up short of free memory since the last time (last_fullzone_zap)
+ *    we zero'd fullzones.
+ * 2) The array z_to_n[] maps each zone in the zonelist to its node
+ *    id, so that we can efficiently evaluate whether that node is
+ *    set in the current tasks mems_allowed.
+ *
+ * Both fullzones and z_to_n[] are one-to-one with the zonelist,
+ * indexed by a zones offset in the zonelist zones[] array.
+ *
+ * The get_page_from_freelist() routine does two scans.  During the
+ * first scan, we skip zones whose corresponding bit in 'fullzones'
+ * is set or whose corresponding node in current->mems_allowed (which
+ * comes from cpusets) is not set.  During the second scan, we bypass
+ * this zonelist_cache, to ensure we look methodically at each zone.
+ *
+ * Once per second, we zero out (zap) fullzones, forcing us to
+ * reconsider nodes that might have regained more free memory.
+ * The field last_full_zap is the time we last zapped fullzones.
+ *
+ * This mechanism reduces the amount of time we waste repeatedly
+ * reexaming zones for free memory when they just came up low on
+ * memory momentarilly ago.
+ *
+ * The zonelist_cache struct members logically belong in struct
+ * zonelist.  However, the mempolicy zonelists constructed for
+ * MPOL_BIND are intentionally variable length (and usually much
+ * shorter).  A general purpose mechanism for handling structs with
+ * multiple variable length members is more mechanism than we want
+ * here.  We resort to some special case hackery instead.
+ *
+ * The MPOL_BIND zonelists don't need this zonelist_cache (in good
+ * part because they are shorter), so we put the fixed length stuff
+ * at the front of the zonelist struct, ending in a variable length
+ * zones[], as is needed by MPOL_BIND.
+ *
+ * Then we put the optional zonelist cache on the end of the zonelist
+ * struct.  This optional stuff is found by a 'zlcache_ptr' pointer in
+ * the fixed length portion at the front of the struct.  This pointer
+ * both enables us to find the zonelist cache, and in the case of
+ * MPOL_BIND zonelists, (which will just set the zlcache_ptr to NULL)
+ * to know that the zonelist cache is not there.
+ *
+ * The end result is that struct zonelists come in two flavors:
+ *  1) The full, fixed length version, shown below, and
+ *  2) The custom zonelists for MPOL_BIND.
+ * The custom MPOL_BIND zonelists have a NULL zlcache_ptr and no zlcache.
+ *
+ * Even though there may be multiple CPU cores on a node modifying
+ * fullzones or last_full_zap in the same zonelist_cache at the same
+ * time, we don't lock it.  This is just hint data - if it is wrong now
+ * and then, the allocator will still function, perhaps a bit slower.
+ */
+
+
+struct zonelist_cache {
+       unsigned short z_to_n[MAX_ZONES_PER_ZONELIST];          /* zone->nid */
+       DECLARE_BITMAP(fullzones, MAX_ZONES_PER_ZONELIST);      /* zone full? */
+       unsigned long last_full_zap;            /* when last zap'd (jiffies) */
+};
+#else
+struct zonelist_cache;
+#endif
+
 /*
  * One allocation request operates on a zonelist. A zonelist
  * is a list of zones, the first one is the 'goal' of the
  * allocation, the other zones are fallback zones, in decreasing
  * priority.
  *
- * Right now a zonelist takes up less than a cacheline. We never
- * modify it apart from boot-up, and only a few indices are used,
- * so despite the zonelist table being relatively big, the cache
- * footprint of this construct is very small.
+ * If zlcache_ptr is not NULL, then it is just the address of zlcache,
+ * as explained above.  If zlcache_ptr is NULL, there is no zlcache.
  */
+
 struct zonelist {
-       struct zone *zones[MAX_NUMNODES * MAX_NR_ZONES + 1]; // NULL delimited
+       struct zonelist_cache *zlcache_ptr;                  // NULL or &zlcache
+       struct zone *zones[MAX_ZONES_PER_ZONELIST + 1];      // NULL delimited
+#ifdef CONFIG_NUMA
+       struct zonelist_cache zlcache;                       // optional ...
+#endif
 };
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
new file mode 100644 (file)
index 0000000..4af0b1f
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+#ifdef __KERNEL__
+
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+
+struct mnt_namespace {
+       atomic_t                count;
+       struct vfsmount *       root;
+       struct list_head        list;
+       wait_queue_head_t poll;
+       int event;
+};
+
+extern int copy_mnt_ns(int, struct task_struct *);
+extern void __put_mnt_ns(struct mnt_namespace *ns);
+extern struct mnt_namespace *dup_mnt_ns(struct task_struct *,
+               struct fs_struct *);
+
+static inline void put_mnt_ns(struct mnt_namespace *ns)
+{
+       if (atomic_dec_and_lock(&ns->count, &vfsmount_lock))
+               /* releases vfsmount_lock */
+               __put_mnt_ns(ns);
+}
+
+static inline void exit_mnt_ns(struct task_struct *p)
+{
+       struct mnt_namespace *ns = p->nsproxy->mnt_ns;
+       if (ns)
+               put_mnt_ns(ns);
+}
+
+static inline void get_mnt_ns(struct mnt_namespace *ns)
+{
+       atomic_inc(&ns->count);
+}
+
+#endif
+#endif
index d33df24..10f771a 100644 (file)
@@ -319,6 +319,13 @@ struct module
 
        unsigned int taints;    /* same bits as kernel:tainted */
 
+#ifdef CONFIG_GENERIC_BUG
+       /* Support for BUG */
+       struct list_head bug_list;
+       struct bug_entry *bug_table;
+       unsigned num_bugs;
+#endif
+
 #ifdef CONFIG_MODULE_UNLOAD
        /* Reference counts */
        struct module_ref ref[NR_CPUS];
index 7c0c2c1..4a189da 100644 (file)
@@ -63,6 +63,9 @@ struct kparam_array
    not there, read bits mean it's readable, write bits mean it's
    writable. */
 #define __module_param_call(prefix, name, set, get, arg, perm)         \
+       /* Default value instead of permissions? */                     \
+       static int __param_perm_check_##name __attribute__((unused)) =  \
+       BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)); \
        static char __param_str_##name[] = prefix #name;                \
        static struct kernel_param const __param_##name                 \
        __attribute_used__                                              \
index 403d1a9..e357dc8 100644 (file)
@@ -20,7 +20,7 @@
 struct super_block;
 struct vfsmount;
 struct dentry;
-struct namespace;
+struct mnt_namespace;
 
 #define MNT_NOSUID     0x01
 #define MNT_NODEV      0x02
@@ -52,7 +52,7 @@ struct vfsmount {
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */
-       struct namespace *mnt_namespace; /* containing namespace */
+       struct mnt_namespace *mnt_ns;   /* containing namespace */
        int mnt_pinned;
 };
 
index acc7c17..f1b6074 100644 (file)
@@ -92,6 +92,12 @@ struct msg_queue {
        struct list_head q_senders;
 };
 
+/* Helper routines for sys_msgsnd and sys_msgrcv */
+extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
+                       size_t msgsz, int msgflg);
+extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
+                       size_t msgsz, long msgtyp, int msgflg);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_MSG_H */
index 27c48da..a7544af 100644 (file)
@@ -94,7 +94,7 @@ do {                                                  \
 
 #define __MUTEX_INITIALIZER(lockname) \
                { .count = ATOMIC_INIT(1) \
-               , .wait_lock = SPIN_LOCK_UNLOCKED \
+               , .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \
                , .wait_list = LIST_HEAD_INIT(lockname.wait_list) \
                __DEBUG_MUTEX_INITIALIZER(lockname) \
                __DEP_MAP_MUTEX_INITIALIZER(lockname) }
@@ -125,8 +125,10 @@ extern int fastcall mutex_lock_interruptible(struct mutex *lock);
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
+extern int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass);
 #else
 # define mutex_lock_nested(lock, subclass) mutex_lock(lock)
+# define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock)
 #endif
 
 /*
index f5f1960..d39a5a6 100644 (file)
@@ -29,6 +29,11 @@ struct nameidata {
        } intent;
 };
 
+struct path {
+       struct vfsmount *mnt;
+       struct dentry *dentry;
+};
+
 /*
  * Type of the last component on LOOKUP_PARENT
  */
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
deleted file mode 100644 (file)
index d137009..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _NAMESPACE_H_
-#define _NAMESPACE_H_
-#ifdef __KERNEL__
-
-#include <linux/mount.h>
-#include <linux/sched.h>
-#include <linux/nsproxy.h>
-
-struct namespace {
-       atomic_t                count;
-       struct vfsmount *       root;
-       struct list_head        list;
-       wait_queue_head_t poll;
-       int event;
-};
-
-extern int copy_namespace(int, struct task_struct *);
-extern void __put_namespace(struct namespace *namespace);
-extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *);
-
-static inline void put_namespace(struct namespace *namespace)
-{
-       if (atomic_dec_and_lock(&namespace->count, &vfsmount_lock))
-               /* releases vfsmount_lock */
-               __put_namespace(namespace);
-}
-
-static inline void exit_namespace(struct task_struct *p)
-{
-       struct namespace *namespace = p->nsproxy->namespace;
-       if (namespace) {
-               put_namespace(namespace);
-       }
-}
-
-static inline void get_namespace(struct namespace *namespace)
-{
-       atomic_inc(&namespace->count);
-}
-
-#endif
-#endif
index d6b6dc0..0f3e693 100644 (file)
@@ -64,6 +64,7 @@ struct nbd_device {
        struct gendisk *disk;
        int blksize;
        u64 bytesize;
+       pid_t pid; /* pid of nbd-client, if attached */
 };
 
 #endif
index b089d95..a503052 100644 (file)
@@ -127,10 +127,10 @@ struct ncp_server {
        } unexpected_packet;
 };
 
-extern void ncp_tcp_rcv_proc(void *server);
-extern void ncp_tcp_tx_proc(void *server);
-extern void ncpdgram_rcv_proc(void *server);
-extern void ncpdgram_timeout_proc(void *server);
+extern void ncp_tcp_rcv_proc(struct work_struct *work);
+extern void ncp_tcp_tx_proc(struct work_struct *work);
+extern void ncpdgram_rcv_proc(struct work_struct *work);
+extern void ncpdgram_timeout_proc(struct work_struct *work);
 extern void ncpdgram_timeout_call(unsigned long server);
 extern void ncp_tcp_data_ready(struct sock* sk, int len);
 extern void ncp_tcp_write_space(struct sock* sk);
index c57088f..6be767c 100644 (file)
@@ -193,13 +193,20 @@ struct hh_cache
 {
        struct hh_cache *hh_next;       /* Next entry                        */
        atomic_t        hh_refcnt;      /* number of users                   */
-       __be16          hh_type;        /* protocol identifier, f.e ETH_P_IP
+/*
+ * We want hh_output, hh_len, hh_lock and hh_data be a in a separate
+ * cache line on SMP.
+ * They are mostly read, but hh_refcnt may be changed quite frequently,
+ * incurring cache line ping pongs.
+ */
+       __be16          hh_type ____cacheline_aligned_in_smp;
+                                       /* protocol identifier, f.e ETH_P_IP
                                          *  NOTE:  For VLANs, this will be the
                                          *  encapuslated type. --BLG
                                          */
        u16             hh_len;         /* length of header */
        int             (*hh_output)(struct sk_buff *skb);
-       rwlock_t        hh_lock;
+       seqlock_t       hh_lock;
 
        /* cached hardware header; allow for machine alignment needs.        */
 #define HH_DATA_MOD    16
index fb049ec..9d8144a 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _NF_CONNTRACK_PPTP_H
 #define _NF_CONNTRACK_PPTP_H
 
+#include <linux/netfilter/nf_conntrack_common.h>
+
 /* state of the control session */
 enum pptp_ctrlsess_state {
        PPTP_SESSION_NONE,                      /* no session present */
@@ -295,7 +297,6 @@ union pptp_ctrl_union {
 /* crap needed for nf_conntrack_compat.h */
 struct nf_conn;
 struct nf_conntrack_expect;
-enum ip_conntrack_info;
 
 extern int
 (*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
index 2cc9867..29930b7 100644 (file)
@@ -32,7 +32,7 @@ struct netpoll_info {
        struct netpoll *rx_np; /* netpoll that registered an rx_hook */
        struct sk_buff_head arp_tx; /* list of arp requests to reply to */
        struct sk_buff_head txq;
-       struct work_struct tx_work;
+       struct delayed_work tx_work;
 };
 
 void netpoll_poll(struct netpoll *np);
index 625ffea..0496306 100644 (file)
@@ -33,6 +33,7 @@
 #define FLUSH_HIGHPRI          16      /* high priority memory reclaim flush */
 #define FLUSH_NOCOMMIT         32      /* Don't send the NFSv3/v4 COMMIT */
 #define FLUSH_INVALIDATE       64      /* Invalidate the page cache */
+#define FLUSH_NOWRITEPAGE      128     /* Don't call writepage() */
 
 #ifdef __KERNEL__
 
@@ -427,19 +428,21 @@ extern int  nfs_flush_incompatible(struct file *file, struct page *page);
 extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
 extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
 extern void nfs_writedata_release(void *);
-
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-struct nfs_write_data *nfs_commit_alloc(void);
-void nfs_commit_free(struct nfs_write_data *p);
-#endif
+extern int nfs_set_page_dirty(struct page *);
 
 /*
  * Try to write back everything synchronously (but check the
  * return value!)
  */
-extern int  nfs_sync_inode_wait(struct inode *, unsigned long, unsigned int, int);
+extern long nfs_sync_mapping_wait(struct address_space *, struct writeback_control *, int);
+extern int nfs_sync_mapping_range(struct address_space *, loff_t, loff_t, int);
+extern int nfs_wb_all(struct inode *inode);
+extern int nfs_wb_page(struct inode *inode, struct page* page);
+extern int nfs_wb_page_priority(struct inode *inode, struct page* page, int how);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 extern int  nfs_commit_inode(struct inode *, int);
+extern struct nfs_write_data *nfs_commit_alloc(void);
+extern void nfs_commit_free(struct nfs_write_data *wdata);
 extern void nfs_commit_release(void *wdata);
 #else
 static inline int
@@ -455,28 +458,6 @@ nfs_have_writebacks(struct inode *inode)
        return NFS_I(inode)->npages != 0;
 }
 
-static inline int
-nfs_wb_all(struct inode *inode)
-{
-       int error = nfs_sync_inode_wait(inode, 0, 0, 0);
-       return (error < 0) ? error : 0;
-}
-
-/*
- * Write back all requests on one page - we do this before reading it.
- */
-static inline int nfs_wb_page_priority(struct inode *inode, struct page* page, int how)
-{
-       int error = nfs_sync_inode_wait(inode, page->index, 1,
-                       how | FLUSH_STABLE);
-       return (error < 0) ? error : 0;
-}
-
-static inline int nfs_wb_page(struct inode *inode, struct page* page)
-{
-       return nfs_wb_page_priority(inode, page, 0);
-}
-
 /*
  * Allocate nfs_write_data structures
  */
index 7ccfc7e..95796e6 100644 (file)
@@ -51,7 +51,7 @@ struct nfs_client {
 
        unsigned long           cl_lease_time;
        unsigned long           cl_last_renewal;
-       struct work_struct      cl_renewd;
+       struct delayed_work     cl_renewd;
 
        struct rpc_wait_queue   cl_rpcwaitq;
 
index 1f7bd28..2e555d4 100644 (file)
@@ -30,6 +30,8 @@
 #define PG_BUSY                        0
 #define PG_NEED_COMMIT         1
 #define PG_NEED_RESCHED                2
+#define PG_NEED_FLUSH          3
+#define PG_FLUSHING            4
 
 struct nfs_inode;
 struct nfs_page {
@@ -60,8 +62,9 @@ extern        void nfs_clear_request(struct nfs_page *req);
 extern void nfs_release_request(struct nfs_page *req);
 
 
-extern  int nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
-                               unsigned long idx_start, unsigned int npages);
+extern long nfs_scan_dirty(struct address_space *mapping,
+                               struct writeback_control *wbc,
+                               struct list_head *dst);
 extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
                          unsigned long idx_start, unsigned int npages);
 extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
index 768c1ad..9ee9da5 100644 (file)
@@ -785,8 +785,6 @@ struct nfs_rpc_ops {
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);
        int     (*read)    (struct nfs_read_data *);
-       int     (*write)   (struct nfs_write_data *);
-       int     (*commit)  (struct nfs_write_data *);
        int     (*create)  (struct inode *, struct dentry *,
                            struct iattr *, int, struct nameidata *);
        int     (*remove)  (struct inode *, struct qstr *);
index e16904e..acb4ed1 100644 (file)
  * disables interrupts for a long time. This call is stateless.
  */
 #ifdef ARCH_HAS_NMI_WATCHDOG
+#include <asm/nmi.h>
 extern void touch_nmi_watchdog(void);
 #else
 # define touch_nmi_watchdog() touch_softlockup_watchdog()
 #endif
 
+#ifndef trigger_all_cpu_backtrace
+#define trigger_all_cpu_backtrace() do { } while (0)
+#endif
+
 #endif
index 971d1c6..fdfb0e4 100644 (file)
@@ -4,9 +4,10 @@
 #include <linux/spinlock.h>
 #include <linux/sched.h>
 
-struct namespace;
+struct mnt_namespace;
 struct uts_namespace;
 struct ipc_namespace;
+struct pid_namespace;
 
 /*
  * A structure to contain pointers to all per-process
@@ -23,9 +24,11 @@ struct ipc_namespace;
 struct nsproxy {
        atomic_t count;
        spinlock_t nslock;
+       unsigned long id;
        struct uts_namespace *uts_ns;
        struct ipc_namespace *ipc_ns;
-       struct namespace *namespace;
+       struct mnt_namespace *mnt_ns;
+       struct pid_namespace *pid_ns;
 };
 extern struct nsproxy init_nsproxy;
 
index c09da1e..51180db 100644 (file)
 #define PCI_DEVICE_ID_NS_CS5535_IDE    0x002d
 #define PCI_DEVICE_ID_NS_CS5535_AUDIO  0x002e
 #define PCI_DEVICE_ID_NS_CS5535_USB    0x002f
-#define PCI_DEVICE_ID_NS_CS5535_VIDEO  0x0030
+#define PCI_DEVICE_ID_NS_GX_VIDEO      0x0030
 #define PCI_DEVICE_ID_NS_SATURN                0x0035
 #define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
 #define PCI_DEVICE_ID_NS_SCx200_SMI    0x0501
 #define PCI_DEVICE_ID_NS_SC1100_XBUS   0x0515
 #define PCI_DEVICE_ID_NS_87410         0xd001
 
-#define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE  0x0028
-#define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE   0x002b
+#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE  0x0028
 
 #define PCI_VENDOR_ID_TSENG            0x100c
 #define PCI_DEVICE_ID_TSENG_W32P_2     0x3202
 #define PCI_DEVICE_ID_MOXA_C104                0x1040
 #define PCI_DEVICE_ID_MOXA_CP104U      0x1041
 #define PCI_DEVICE_ID_MOXA_CP104JU     0x1042
+#define PCI_DEVICE_ID_MOXA_CP104EL     0x1043
 #define PCI_DEVICE_ID_MOXA_CT114       0x1140
 #define PCI_DEVICE_ID_MOXA_CP114       0x1141
 #define PCI_DEVICE_ID_MOXA_CP118U      0x1180
+#define PCI_DEVICE_ID_MOXA_CP118EL     0x1181
 #define PCI_DEVICE_ID_MOXA_CP132       0x1320
 #define PCI_DEVICE_ID_MOXA_CP132U      0x1321
 #define PCI_DEVICE_ID_MOXA_CP134U      0x1340
 #define PCI_DEVICE_ID_MOXA_C168                0x1680
 #define PCI_DEVICE_ID_MOXA_CP168U      0x1681
+#define PCI_DEVICE_ID_MOXA_CP168EL     0x1682
 
 #define PCI_VENDOR_ID_CCD              0x1397
 #define PCI_DEVICE_ID_CCD_2BD0         0x2bd0
 #define PCI_DEVICE_ID_OXSEMI_16PCI95N  0x9511
 #define PCI_DEVICE_ID_OXSEMI_16PCI954PP        0x9513
 #define PCI_DEVICE_ID_OXSEMI_16PCI952  0x9521
+#define PCI_DEVICE_ID_OXSEMI_16PCI952PP        0x9523
 
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 
 #define PCI_DEVICE_ID_TIGON3_5750M     0x167c
 #define PCI_DEVICE_ID_TIGON3_5751M     0x167d
 #define PCI_DEVICE_ID_TIGON3_5751F     0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F     0x167f
 #define PCI_DEVICE_ID_TIGON3_5787M     0x1693
 #define PCI_DEVICE_ID_TIGON3_5782      0x1696
 #define PCI_DEVICE_ID_TIGON3_5786      0x169a
 #define PCI_DEVICE_ID_FARSITE_TE1       0x1610
 #define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
 
+#define PCI_VENDOR_ID_ARIMA            0x161f
+
 #define PCI_VENDOR_ID_SIBYTE           0x166d
 #define PCI_DEVICE_ID_BCM1250_PCI      0x0001
 #define PCI_DEVICE_ID_BCM1250_HT       0x0002
index 0f0b880..265bafa 100644 (file)
@@ -285,6 +285,7 @@ struct sadb_x_sec_ctx {
 #define SADB_X_AALG_SHA2_384HMAC       6
 #define SADB_X_AALG_SHA2_512HMAC       7
 #define SADB_X_AALG_RIPEMD160HMAC      8
+#define SADB_X_AALG_AES_XCBC_MAC       9
 #define SADB_X_AALG_NULL               251     /* kame */
 #define SADB_AALG_MAX                  251
 
index 2c0007d..4dec047 100644 (file)
@@ -35,8 +35,9 @@ enum pid_type
  *
  * Holding a reference to struct pid solves both of these problems.
  * It is small so holding a reference does not consume a lot of
- * resources, and since a new struct pid is allocated when the numeric
- * pid value is reused we don't mistakenly refer to new processes.
+ * resources, and since a new struct pid is allocated when the numeric pid
+ * value is reused (when pids wrap around) we don't mistakenly refer to new
+ * processes.
  */
 
 struct pid
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
new file mode 100644 (file)
index 0000000..d2a9d41
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _LINUX_PID_NS_H
+#define _LINUX_PID_NS_H
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
+#include <linux/kref.h>
+
+struct pidmap {
+       atomic_t nr_free;
+       void *page;
+};
+
+#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
+
+struct pid_namespace {
+       struct kref kref;
+       struct pidmap pidmap[PIDMAP_ENTRIES];
+       int last_pid;
+       struct task_struct *child_reaper;
+};
+
+extern struct pid_namespace init_pid_ns;
+
+static inline void get_pid_ns(struct pid_namespace *ns)
+{
+       kref_get(&ns->kref);
+}
+
+extern int copy_pid_ns(int flags, struct task_struct *tsk);
+extern void free_pid_ns(struct kref *kref);
+
+static inline void put_pid_ns(struct pid_namespace *ns)
+{
+       kref_put(&ns->kref, free_pid_ns);
+}
+
+static inline struct task_struct *child_reaper(struct task_struct *tsk)
+{
+       return tsk->nsproxy->pid_ns->child_reaper;
+}
+
+#endif /* _LINUX_PID_NS_H */
index 8a94c71..5ea4f05 100644 (file)
@@ -111,6 +111,13 @@ struct pkt_ctrl_command {
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/cdrom.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+/* default bio write queue congestion marks */
+#define PKT_WRITE_CONGESTION_ON    10000
+#define PKT_WRITE_CONGESTION_OFF   9000
+
 
 struct packet_settings
 {
@@ -241,6 +248,14 @@ struct packet_stacked_data
 };
 #define PSD_POOL_SIZE          64
 
+struct pktcdvd_kobj
+{
+       struct kobject          kobj;
+       struct pktcdvd_device   *pd;
+};
+#define to_pktcdvdkobj(_k) \
+  ((struct pktcdvd_kobj*)container_of(_k,struct pktcdvd_kobj,kobj))
+
 struct pktcdvd_device
 {
        struct block_device     *bdev;          /* dev attached */
@@ -271,6 +286,16 @@ struct pktcdvd_device
 
        struct packet_iosched   iosched;
        struct gendisk          *disk;
+
+       int                     write_congestion_off;
+       int                     write_congestion_on;
+
+       struct class_device     *clsdev;        /* sysfs pktcdvd[0-7] class dev */
+       struct pktcdvd_kobj     *kobj_stat;     /* sysfs pktcdvd[0-7]/stat/     */
+       struct pktcdvd_kobj     *kobj_wqueue;   /* sysfs pktcdvd[0-7]/write_queue/ */
+
+       struct dentry           *dfs_d_root;    /* debugfs: devname directory */
+       struct dentry           *dfs_f_info;    /* debugfs: info file */
 };
 
 #endif /* __KERNEL__ */
index acce53f..5670b34 100644 (file)
@@ -6,10 +6,15 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
+#include <linux/cache.h>
+
 #include <asm/errno.h>
 
+extern int prof_on __read_mostly;
+
 #define CPU_PROFILING  1
 #define SCHED_PROFILING        2
+#define SLEEP_PROFILING        3
 
 struct proc_dir_entry;
 struct pt_regs;
@@ -18,7 +23,24 @@ struct notifier_block;
 /* init basic kernel profiler */
 void __init profile_init(void);
 void profile_tick(int);
-void profile_hit(int, void *);
+
+/*
+ * Add multiple profiler hits to a given address:
+ */
+void profile_hits(int, void *ip, unsigned int nr_hits);
+
+/*
+ * Single profiler hit:
+ */
+static inline void profile_hit(int type, void *ip)
+{
+       /*
+        * Speedup for the common (no profiling enabled) case:
+        */
+       if (unlikely(prof_on == type))
+               profile_hits(type, ip, 1);
+}
+
 #ifdef CONFIG_PROC_FS
 void create_prof_cpu_mask(struct proc_dir_entry *);
 #else
diff --git a/include/linux/pspace.h b/include/linux/pspace.h
deleted file mode 100644 (file)
index 91d48b8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _LINUX_PSPACE_H
-#define _LINUX_PSPACE_H
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/threads.h>
-#include <linux/pid.h>
-
-struct pidmap {
-       atomic_t nr_free;
-       void *page;
-};
-
-#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
-
-struct pspace {
-       struct pidmap pidmap[PIDMAP_ENTRIES];
-       int last_pid;
-};
-
-extern struct pspace init_pspace;
-
-#endif /* _LINUX_PSPACE_H */
index 5110201..90c23f6 100644 (file)
@@ -37,6 +37,9 @@ extern int dquot_release(struct dquot *dquot);
 extern int dquot_commit_info(struct super_block *sb, int type);
 extern int dquot_mark_dquot_dirty(struct dquot *dquot);
 
+int remove_inode_dquot_ref(struct inode *inode, int type,
+                          struct list_head *tofree_head);
+
 extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
 extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
                int format_id, int type);
index cbfa115..0deb842 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
+ * Copyright (C) 2006 Nick Piggin
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 
 #include <linux/preempt.h>
 #include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/rcupdate.h>
+
+/*
+ * A direct pointer (root->rnode pointing directly to a data item,
+ * rather than another radix_tree_node) is signalled by the low bit
+ * set in the root->rnode pointer.
+ *
+ * In this case root->height is also NULL, but the direct pointer tests are
+ * needed for RCU lookups when root->height is unreliable.
+ */
+#define RADIX_TREE_DIRECT_PTR  1
+
+static inline void *radix_tree_ptr_to_direct(void *ptr)
+{
+       return (void *)((unsigned long)ptr | RADIX_TREE_DIRECT_PTR);
+}
+
+static inline void *radix_tree_direct_to_ptr(void *ptr)
+{
+       return (void *)((unsigned long)ptr & ~RADIX_TREE_DIRECT_PTR);
+}
+
+static inline int radix_tree_is_direct_ptr(void *ptr)
+{
+       return (int)((unsigned long)ptr & RADIX_TREE_DIRECT_PTR);
+}
+
+/*** radix-tree API starts here ***/
 
 #define RADIX_TREE_MAX_TAGS 2
 
@@ -47,6 +77,77 @@ do {                                                                 \
        (root)->rnode = NULL;                                           \
 } while (0)
 
+/**
+ * Radix-tree synchronization
+ *
+ * The radix-tree API requires that users provide all synchronisation (with
+ * specific exceptions, noted below).
+ *
+ * Synchronization of access to the data items being stored in the tree, and
+ * management of their lifetimes must be completely managed by API users.
+ *
+ * For API usage, in general,
+ * - any function _modifying_ the the tree or tags (inserting or deleting
+ *   items, setting or clearing tags must exclude other modifications, and
+ *   exclude any functions reading the tree.
+ * - any function _reading_ the the tree or tags (looking up items or tags,
+ *   gang lookups) must exclude modifications to the tree, but may occur
+ *   concurrently with other readers.
+ *
+ * The notable exceptions to this rule are the following functions:
+ * radix_tree_lookup
+ * radix_tree_tag_get
+ * radix_tree_gang_lookup
+ * radix_tree_gang_lookup_tag
+ * radix_tree_tagged
+ *
+ * The first 4 functions are able to be called locklessly, using RCU. The
+ * caller must ensure calls to these functions are made within rcu_read_lock()
+ * regions. Other readers (lock-free or otherwise) and modifications may be
+ * running concurrently.
+ *
+ * It is still required that the caller manage the synchronization and lifetimes
+ * of the items. So if RCU lock-free lookups are used, typically this would mean
+ * that the items have their own locks, or are amenable to lock-free access; and
+ * that the items are freed by RCU (or only freed after having been deleted from
+ * the radix tree *and* a synchronize_rcu() grace period).
+ *
+ * (Note, rcu_assign_pointer and rcu_dereference are not needed to control
+ * access to data items when inserting into or looking up from the radix tree)
+ *
+ * radix_tree_tagged is able to be called without locking or RCU.
+ */
+
+/**
+ * radix_tree_deref_slot       - dereference a slot
+ * @pslot:     pointer to slot, returned by radix_tree_lookup_slot
+ * Returns:    item that was stored in that slot with any direct pointer flag
+ *             removed.
+ *
+ * For use with radix_tree_lookup_slot().  Caller must hold tree at least read
+ * locked across slot lookup and dereference.  More likely, will be used with
+ * radix_tree_replace_slot(), as well, so caller will hold tree write locked.
+ */
+static inline void *radix_tree_deref_slot(void **pslot)
+{
+       return radix_tree_direct_to_ptr(*pslot);
+}
+/**
+ * radix_tree_replace_slot     - replace item in a slot
+ * @pslot:     pointer to slot, returned by radix_tree_lookup_slot
+ * @item:      new item to store in the slot.
+ *
+ * For use with radix_tree_lookup_slot().  Caller must hold tree write locked
+ * across slot lookup and replacement.
+ */
+static inline void radix_tree_replace_slot(void **pslot, void *item)
+{
+       BUG_ON(radix_tree_is_direct_ptr(item));
+       rcu_assign_pointer(*pslot,
+               (void *)((unsigned long)item |
+                       ((unsigned long)*pslot & RADIX_TREE_DIRECT_PTR)));
+}
+
 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
index f13299a..d8286db 100644 (file)
@@ -227,7 +227,10 @@ struct raid5_private_data {
        struct list_head        handle_list; /* stripes needing handling */
        struct list_head        delayed_list; /* stripes that have plugged requests */
        struct list_head        bitmap_list; /* stripes delaying awaiting bitmap update */
+       struct bio              *retry_read_aligned; /* currently retrying aligned bios   */
+       struct bio              *retry_read_aligned_list; /* aligned bios retry list  */
        atomic_t                preread_active_stripes; /* stripes with scheduled io */
+       atomic_t                active_aligned_reads;
 
        atomic_t                reshape_stripes; /* stripes with pending writes for reshape */
        /* unfortunately we need two cache names as we temporarily have
@@ -235,7 +238,7 @@ struct raid5_private_data {
         */
        int                     active_name;
        char                    cache_name[2][20];
-       kmem_cache_t            *slab_cache; /* for allocating stripes */
+       struct kmem_cache               *slab_cache; /* for allocating stripes */
 
        int                     seq_flush, seq_write;
        int                     quiesce;
index 7bc6bfb..c3fc6ca 100644 (file)
@@ -739,7 +739,7 @@ struct block_head {
 #define PUT_B_FREE_SPACE(p_s_bh,val)  do { set_blkh_free_space(B_BLK_HEAD(p_s_bh),val); } while (0)
 
 /* Get right delimiting key. -- little endian */
-#define B_PRIGHT_DELIM_KEY(p_s_bh)   (&(blk_right_delim_key(B_BLK_HEAD(p_s_bh))
+#define B_PRIGHT_DELIM_KEY(p_s_bh)   (&(blk_right_delim_key(B_BLK_HEAD(p_s_bh))))
 
 /* Does the buffer contain a disk leaf. */
 #define B_IS_ITEMS_LEVEL(p_s_bh)     (B_LEVEL(p_s_bh) == DISK_LEAF_NODE_LEVEL)
@@ -1159,7 +1159,7 @@ znodes are the way! */
 #define PATH_READA     0x1     /* do read ahead */
 #define PATH_READA_BACK 0x2    /* read backwards */
 
-struct path {
+struct treepath {
        int path_length;        /* Length of the array above.   */
        int reada;
        struct path_element path_elements[EXTENDED_MAX_HEIGHT]; /* Array of the path elements.  */
@@ -1169,7 +1169,7 @@ struct path {
 #define pos_in_item(path) ((path)->pos_in_item)
 
 #define INITIALIZE_PATH(var) \
-struct path var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
+struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
 
 /* Get path element by path and path position. */
 #define PATH_OFFSET_PELEMENT(p_s_path,n_offset)  ((p_s_path)->path_elements +(n_offset))
@@ -1327,7 +1327,7 @@ struct tree_balance {
        int need_balance_dirty;
        struct super_block *tb_sb;
        struct reiserfs_transaction_handle *transaction_handle;
-       struct path *tb_path;
+       struct treepath *tb_path;
        struct buffer_head *L[MAX_HEIGHT];      /* array of left neighbors of nodes in the path */
        struct buffer_head *R[MAX_HEIGHT];      /* array of right neighbors of nodes in the path */
        struct buffer_head *FL[MAX_HEIGHT];     /* array of fathers of the left  neighbors      */
@@ -1793,41 +1793,41 @@ static inline void copy_key(struct reiserfs_key *to,
        memcpy(to, from, KEY_SIZE);
 }
 
-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path);
-const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
+int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path);
+const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
                                    const struct super_block *p_s_sb);
 int search_by_key(struct super_block *, const struct cpu_key *,
-                 struct path *, int);
+                 struct treepath *, int);
 #define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL)
 int search_for_position_by_key(struct super_block *p_s_sb,
                               const struct cpu_key *p_s_cpu_key,
-                              struct path *p_s_search_path);
+                              struct treepath *p_s_search_path);
 extern void decrement_bcount(struct buffer_head *p_s_bh);
-void decrement_counters_in_path(struct path *p_s_search_path);
-void pathrelse(struct path *p_s_search_path);
-int reiserfs_check_path(struct path *p);
-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path);
+void decrement_counters_in_path(struct treepath *p_s_search_path);
+void pathrelse(struct treepath *p_s_search_path);
+int reiserfs_check_path(struct treepath *p);
+void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path);
 
 int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
-                        struct path *path,
+                        struct treepath *path,
                         const struct cpu_key *key,
                         struct item_head *ih,
                         struct inode *inode, const char *body);
 
 int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th,
-                            struct path *path,
+                            struct treepath *path,
                             const struct cpu_key *key,
                             struct inode *inode,
                             const char *body, int paste_size);
 
 int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
-                          struct path *path,
+                          struct treepath *path,
                           struct cpu_key *key,
                           struct inode *inode,
                           struct page *page, loff_t new_file_size);
 
 int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
-                        struct path *path,
+                        struct treepath *path,
                         const struct cpu_key *key,
                         struct inode *inode, struct buffer_head *p_s_un_bh);
 
@@ -1858,7 +1858,7 @@ void padd_item(char *item, int total_length, int length);
 #define GET_BLOCK_NO_DANGLE   16       /* don't leave any transactions running */
 
 int restart_transaction(struct reiserfs_transaction_handle *th,
-                       struct inode *inode, struct path *path);
+                       struct inode *inode, struct treepath *path);
 void reiserfs_read_locked_inode(struct inode *inode,
                                struct reiserfs_iget_args *args);
 int reiserfs_find_actor(struct inode *inode, void *p);
@@ -1905,7 +1905,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr);
 /* namei.c */
 void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
 int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
-                       struct path *path, struct reiserfs_dir_entry *de);
+                       struct treepath *path, struct reiserfs_dir_entry *de);
 struct dentry *reiserfs_get_parent(struct dentry *);
 /* procfs.c */
 
@@ -1956,9 +1956,9 @@ extern const struct file_operations reiserfs_dir_operations;
 
 /* tail_conversion.c */
 int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
-                   struct path *, struct buffer_head *, loff_t);
+                   struct treepath *, struct buffer_head *, loff_t);
 int indirect2direct(struct reiserfs_transaction_handle *, struct inode *,
-                   struct page *, struct path *, const struct cpu_key *,
+                   struct page *, struct treepath *, const struct cpu_key *,
                    loff_t, char *);
 void reiserfs_unmap_buffer(struct buffer_head *);
 
@@ -2045,7 +2045,7 @@ struct __reiserfs_blocknr_hint {
        struct inode *inode;    /* inode passed to allocator, if we allocate unf. nodes */
        long block;             /* file offset, in blocks */
        struct in_core_key key;
-       struct path *path;      /* search path, used by allocator to deternine search_start by
+       struct treepath *path;  /* search path, used by allocator to deternine search_start by
                                 * various ways */
        struct reiserfs_transaction_handle *th; /* transaction handle is needed to log super blocks and
                                                 * bitmap blocks changes  */
@@ -2101,7 +2101,7 @@ static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
 static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
                                            *th, struct inode *inode,
                                            b_blocknr_t * new_blocknrs,
-                                           struct path *path, long block)
+                                           struct treepath *path, long block)
 {
        reiserfs_blocknr_hint_t hint = {
                .th = th,
@@ -2118,7 +2118,7 @@ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
 static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
                                             *th, struct inode *inode,
                                             b_blocknr_t * new_blocknrs,
-                                            struct path *path, long block)
+                                            struct treepath *path, long block)
 {
        reiserfs_blocknr_hint_t hint = {
                .th = th,
index 62a7169..3a28742 100644 (file)
@@ -249,7 +249,8 @@ struct reiserfs_journal {
        int j_errno;
 
        /* when flushing ordered buffers, throttle new ordered writers */
-       struct work_struct j_work;
+       struct delayed_work j_work;
+       struct super_block *j_work_sb;
        atomic_t j_async_throttle;
 };
 
index 24accb4..c6a48bf 100644 (file)
@@ -38,7 +38,7 @@ struct rchan_buf
        size_t subbufs_consumed;        /* count of sub-buffers consumed */
        struct rchan *chan;             /* associated channel */
        wait_queue_head_t read_wait;    /* reader wait queue */
-       struct work_struct wake_readers; /* reader wake-up work struct */
+       struct delayed_work wake_readers; /* reader wake-up work struct */
        struct dentry *dentry;          /* channel file dentry */
        struct kref kref;               /* channel buffer refcount */
        struct page **page_array;       /* array of current buffer pages */
@@ -274,7 +274,7 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf,
 /*
  * exported relay file operations, kernel/relay.c
  */
-extern struct file_operations relay_file_operations;
+extern const struct file_operations relay_file_operations;
 
 #endif /* _LINUX_RELAY_H */
 
index db2c1df..36f8503 100644 (file)
@@ -30,11 +30,11 @@ struct anon_vma {
 
 #ifdef CONFIG_MMU
 
-extern kmem_cache_t *anon_vma_cachep;
+extern struct kmem_cache *anon_vma_cachep;
 
 static inline struct anon_vma *anon_vma_alloc(void)
 {
-       return kmem_cache_alloc(anon_vma_cachep, SLAB_KERNEL);
+       return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
 }
 
 static inline void anon_vma_free(struct anon_vma *anon_vma)
index 09ff4c3..5e22d45 100644 (file)
@@ -106,6 +106,7 @@ extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year
 extern int rtc_valid_tm(struct rtc_time *tm);
 extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
 extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+extern void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm);
 
 #include <linux/device.h>
 #include <linux/seq_file.h>
index 5d41dee..b0090e9 100644 (file)
@@ -63,7 +63,7 @@ struct hrtimer_sleeper;
 #endif
 
 #define __RT_MUTEX_INITIALIZER(mutexname) \
-       { .wait_lock = SPIN_LOCK_UNLOCKED \
+       { .wait_lock = __SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
        , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \
        , .owner = NULL \
        __DEBUG_RT_MUTEX_INITIALIZER(mutexname)}
index 493297a..4a629ea 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/netlink.h>
 #include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
 
 /****
  *             Routing/neighbour discovery messages.
index ae1fcad..813cee1 100644 (file)
@@ -44,7 +44,8 @@ struct rw_semaphore {
 #endif
 
 #define __RWSEM_INITIALIZER(name) \
-{ 0, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
+{ 0, __SPIN_LOCK_UNLOCKED(name.wait_lock), LIST_HEAD_INIT((name).wait_list) \
+  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name) \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
index eafe4a7..ea92e5c 100644 (file)
@@ -82,6 +82,7 @@ struct sched_param {
 #include <linux/resource.h>
 #include <linux/timer.h>
 #include <linux/hrtimer.h>
+#include <linux/task_io_accounting.h>
 
 #include <asm/processor.h>
 
@@ -194,7 +195,16 @@ extern void init_idle(struct task_struct *idle, int cpu);
 
 extern cpumask_t nohz_cpu_mask;
 
-extern void show_state(void);
+/*
+ * Only dump TASK_* tasks. (-1 for all tasks)
+ */
+extern void show_state_filter(unsigned long state_filter);
+
+static inline void show_state(void)
+{
+       show_state_filter(-1);
+}
+
 extern void show_regs(struct pt_regs *);
 
 /*
@@ -338,15 +348,23 @@ struct mm_struct {
 
        unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
 
-       unsigned dumpable:2;
        cpumask_t cpu_vm_mask;
 
        /* Architecture-specific MM context */
        mm_context_t context;
 
-       /* Token based thrashing protection. */
-       unsigned long swap_token_time;
-       char recent_pagein;
+       /* Swap token stuff */
+       /*
+        * Last value of global fault stamp as seen by this process.
+        * In other words, this value gives an indication of how long
+        * it has been since this task got the token.
+        * Look at mm/thrash.c
+        */
+       unsigned int faultstamp;
+       unsigned int token_priority;
+       unsigned int last_interval;
+
+       unsigned char dumpable:2;
 
        /* coredumping support */
        int core_waiters;
@@ -419,7 +437,12 @@ struct signal_struct {
        /* job control IDs */
        pid_t pgrp;
        pid_t tty_old_pgrp;
-       pid_t session;
+
+       union {
+               pid_t session __deprecated;
+               pid_t __session;
+       };
+
        /* boolean value for session group leader */
        int leader;
 
@@ -556,7 +579,7 @@ struct sched_info {
 #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
 
 #ifdef CONFIG_SCHEDSTATS
-extern struct file_operations proc_schedstat_operations;
+extern const struct file_operations proc_schedstat_operations;
 #endif /* CONFIG_SCHEDSTATS */
 
 #ifdef CONFIG_TASK_DELAY_ACCT
@@ -625,6 +648,7 @@ enum idle_type
 #define SD_SHARE_CPUPOWER      128     /* Domain members share cpu power */
 #define SD_POWERSAVINGS_BALANCE        256     /* Balance for power savings */
 #define SD_SHARE_PKG_RESOURCES 512     /* Domain members share cpu pkg resources */
+#define SD_SERIALIZE           1024    /* Only a single load balancing instance */
 
 #define BALANCE_FOR_MC_POWER   \
        (sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
@@ -991,6 +1015,7 @@ struct task_struct {
        wait_queue_t *io_wait;
 /* i/o counters(bytes read/written, #syscalls */
        u64 rchar, wchar, syscr, syscw;
+       struct task_io_accounting ioac;
 #if defined(CONFIG_TASK_XACCT)
        u64 acct_rss_mem1;      /* accumulated rss usage */
        u64 acct_vm_mem1;       /* accumulated virtual memory usage */
@@ -1023,6 +1048,9 @@ struct task_struct {
 #ifdef CONFIG_TASK_DELAY_ACCT
        struct task_delay_info *delays;
 #endif
+#ifdef CONFIG_FAULT_INJECTION
+       int make_it_fail;
+#endif
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
@@ -1030,6 +1058,21 @@ static inline pid_t process_group(struct task_struct *tsk)
        return tsk->signal->pgrp;
 }
 
+static inline pid_t signal_session(struct signal_struct *sig)
+{
+       return sig->__session;
+}
+
+static inline pid_t process_session(struct task_struct *tsk)
+{
+       return signal_session(tsk->signal);
+}
+
+static inline void set_signal_session(struct signal_struct *sig, pid_t session)
+{
+       sig->__session = session;
+}
+
 static inline struct pid *task_pid(struct task_struct *task)
 {
        return task->pids[PIDTYPE_PID].pid;
@@ -1223,7 +1266,6 @@ extern struct   mm_struct init_mm;
 
 #define find_task_by_pid(nr)   find_task_by_pid_type(PIDTYPE_PID, nr)
 extern struct task_struct *find_task_by_pid_type(int type, int pid);
-extern void set_special_pids(pid_t session, pid_t pgrp);
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
 /* per-UID process charging. */
@@ -1288,7 +1330,6 @@ extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
 extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
 extern int kill_pg_info(int, struct siginfo *, pid_t);
-extern int kill_proc_info(int, struct siginfo *, pid_t);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
@@ -1365,7 +1406,6 @@ extern NORET_TYPE void do_group_exit(int);
 extern void daemonize(const char *, ...);
 extern int allow_signal(int);
 extern int disallow_signal(int);
-extern struct task_struct *child_reaper;
 
 extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *);
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
@@ -1610,87 +1650,6 @@ extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls);
 
 extern void normalize_rt_tasks(void);
 
-#ifdef CONFIG_PM
-/*
- * Check if a process has been frozen
- */
-static inline int frozen(struct task_struct *p)
-{
-       return p->flags & PF_FROZEN;
-}
-
-/*
- * Check if there is a request to freeze a process
- */
-static inline int freezing(struct task_struct *p)
-{
-       return p->flags & PF_FREEZE;
-}
-
-/*
- * Request that a process be frozen
- * FIXME: SMP problem. We may not modify other process' flags!
- */
-static inline void freeze(struct task_struct *p)
-{
-       p->flags |= PF_FREEZE;
-}
-
-/*
- * Sometimes we may need to cancel the previous 'freeze' request
- */
-static inline void do_not_freeze(struct task_struct *p)
-{
-       p->flags &= ~PF_FREEZE;
-}
-
-/*
- * Wake up a frozen process
- */
-static inline int thaw_process(struct task_struct *p)
-{
-       if (frozen(p)) {
-               p->flags &= ~PF_FROZEN;
-               wake_up_process(p);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
-{
-       p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
-}
-
-extern void refrigerator(void);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
-static inline int try_to_freeze(void)
-{
-       if (freezing(current)) {
-               refrigerator();
-               return 1;
-       } else
-               return 0;
-}
-#else
-static inline int frozen(struct task_struct *p) { return 0; }
-static inline int freezing(struct task_struct *p) { return 0; }
-static inline void freeze(struct task_struct *p) { BUG(); }
-static inline int thaw_process(struct task_struct *p) { return 1; }
-static inline void frozen_process(struct task_struct *p) { BUG(); }
-
-static inline void refrigerator(void) {}
-static inline int freeze_processes(void) { BUG(); return 0; }
-static inline void thaw_processes(void) {}
-
-static inline int try_to_freeze(void) { return 0; }
-
-#endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
 #endif
index 2925e66..b02308e 100644 (file)
@@ -42,7 +42,8 @@ struct screen_info {
        u16 pages;              /* 0x32 */
        u16 vesa_attributes;    /* 0x34 */
        u32 capabilities;       /* 0x36 */
-                               /* 0x3a -- 0x3f reserved for future expansion */
+                               /* 0x3a -- 0x3b reserved for future expansion */
+                               /* 0x3c -- 0x3f micro stack for relocatable kernels */
 };
 
 extern struct screen_info screen_info;
index b95f6eb..3e3cccb 100644 (file)
@@ -20,7 +20,7 @@ struct seq_file {
        loff_t index;
        loff_t version;
        struct mutex lock;
-       struct seq_operations *op;
+       const struct seq_operations *op;
        void *private;
 };
 
@@ -31,7 +31,7 @@ struct seq_operations {
        int (*show) (struct seq_file *m, void *v);
 };
 
-int seq_open(struct file *, struct seq_operations *);
+int seq_open(struct file *, const struct seq_operations *);
 ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
 loff_t seq_lseek(struct file *, loff_t, int);
 int seq_release(struct inode *, struct file *);
index 8e96814..71310d8 100644 (file)
@@ -41,6 +41,7 @@ enum {
        PLAT8250_DEV_FOURPORT,
        PLAT8250_DEV_ACCENT,
        PLAT8250_DEV_BOCA,
+       PLAT8250_DEV_EXAR_ST16C554,
        PLAT8250_DEV_HUB6,
        PLAT8250_DEV_MCA,
        PLAT8250_DEV_AU1X00,
index 463ab95..cf23813 100644 (file)
 
 #define PORT_S3C2412   73
 
+/* Xilinx uartlite */
+#define PORT_UARTLITE  74
 
 #ifdef __KERNEL__
 
@@ -164,8 +166,8 @@ struct uart_ops {
        void            (*break_ctl)(struct uart_port *, int ctl);
        int             (*startup)(struct uart_port *);
        void            (*shutdown)(struct uart_port *);
-       void            (*set_termios)(struct uart_port *, struct termios *new,
-                                      struct termios *old);
+       void            (*set_termios)(struct uart_port *, struct ktermios *new,
+                                      struct ktermios *old);
        void            (*pm)(struct uart_port *, unsigned int state,
                              unsigned int oldstate);
        int             (*set_wake)(struct uart_port *, unsigned int state);
@@ -359,8 +361,8 @@ void uart_write_wakeup(struct uart_port *port);
  */
 void uart_update_timeout(struct uart_port *port, unsigned int cflag,
                         unsigned int baud);
-unsigned int uart_get_baud_rate(struct uart_port *port, struct termios *termios,
-                               struct termios *old, unsigned int min,
+unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+                               struct ktermios *old, unsigned int min,
                                unsigned int max);
 unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
 
index b99c5ca..0f478a8 100644 (file)
@@ -85,18 +85,8 @@ static inline void serio_register_port(struct serio *serio)
 
 void serio_unregister_port(struct serio *serio);
 void serio_unregister_child_port(struct serio *serio);
-void __serio_unregister_port_delayed(struct serio *serio, struct module *owner);
-static inline void serio_unregister_port_delayed(struct serio *serio)
-{
-       __serio_unregister_port_delayed(serio, THIS_MODULE);
-}
-
-void __serio_register_driver(struct serio_driver *drv, struct module *owner);
-static inline void serio_register_driver(struct serio_driver *drv)
-{
-       __serio_register_driver(drv, THIS_MODULE);
-}
 
+int serio_register_driver(struct serio_driver *drv);
 void serio_unregister_driver(struct serio_driver *drv);
 
 static inline int serio_write(struct serio *serio, unsigned char data)
index 117135e..1474905 100644 (file)
@@ -241,6 +241,8 @@ extern int sigprocmask(int, sigset_t *, sigset_t *);
 struct pt_regs;
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 
+extern struct kmem_cache *sighand_cachep;
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SIGNAL_H */
index a05a5f7..4ff3940 100644 (file)
@@ -332,20 +332,20 @@ struct sk_buff {
 extern void kfree_skb(struct sk_buff *skb);
 extern void           __kfree_skb(struct sk_buff *skb);
 extern struct sk_buff *__alloc_skb(unsigned int size,
-                                  gfp_t priority, int fclone);
+                                  gfp_t priority, int fclone, int node);
 static inline struct sk_buff *alloc_skb(unsigned int size,
                                        gfp_t priority)
 {
-       return __alloc_skb(size, priority, 0);
+       return __alloc_skb(size, priority, 0, -1);
 }
 
 static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
                                               gfp_t priority)
 {
-       return __alloc_skb(size, priority, 1);
+       return __alloc_skb(size, priority, 1, -1);
 }
 
-extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
+extern struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
                                            unsigned int size,
                                            gfp_t priority);
 extern void           kfree_skbmem(struct sk_buff *skb);
index c4947b8..2271886 100644 (file)
@@ -7,27 +7,17 @@
 #ifndef _LINUX_SLAB_H
 #define        _LINUX_SLAB_H
 
-#if    defined(__KERNEL__)
+#ifdef __KERNEL__
 
-typedef struct kmem_cache kmem_cache_t;
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <asm/page.h>          /* kmalloc_sizes.h needs PAGE_SIZE */
+#include <asm/cache.h>         /* kmalloc_sizes.h needs L1_CACHE_BYTES */
+#include <linux/compiler.h>
 
-#include       <linux/gfp.h>
-#include       <linux/init.h>
-#include       <linux/types.h>
-#include       <asm/page.h>            /* kmalloc_sizes.h needs PAGE_SIZE */
-#include       <asm/cache.h>           /* kmalloc_sizes.h needs L1_CACHE_BYTES */
-
-/* flags for kmem_cache_alloc() */
-#define        SLAB_NOFS               GFP_NOFS
-#define        SLAB_NOIO               GFP_NOIO
-#define        SLAB_ATOMIC             GFP_ATOMIC
-#define        SLAB_USER               GFP_USER
-#define        SLAB_KERNEL             GFP_KERNEL
-#define        SLAB_DMA                GFP_DMA
-
-#define SLAB_LEVEL_MASK                GFP_LEVEL_MASK
-
-#define        SLAB_NO_GROW            __GFP_NO_GROW   /* don't grow a cache */
+/* kmem_cache_t exists for legacy reasons and is not used by code in mm */
+typedef struct kmem_cache kmem_cache_t __deprecated;
 
 /* flags to pass to kmem_cache_create().
  * The first 3 are only valid when the allocator as been build
@@ -57,22 +47,23 @@ typedef struct kmem_cache kmem_cache_t;
 /* prototypes */
 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 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 struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+                       unsigned long,
+                       void (*)(void *, struct kmem_cache *, unsigned long),
+                       void (*)(void *, struct kmem_cache *, unsigned long));
+extern void kmem_cache_destroy(struct kmem_cache *);
+extern int kmem_cache_shrink(struct kmem_cache *);
+extern void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
 extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-extern void kmem_cache_free(kmem_cache_t *, void *);
-extern unsigned int kmem_cache_size(kmem_cache_t *);
-extern const char *kmem_cache_name(kmem_cache_t *);
+extern void kmem_cache_free(struct kmem_cache *, void *);
+extern unsigned int kmem_cache_size(struct kmem_cache *);
+extern const char *kmem_cache_name(struct kmem_cache *);
 
 /* Size description struct for general caches. */
 struct cache_sizes {
-       size_t           cs_size;
-       kmem_cache_t    *cs_cachep;
-       kmem_cache_t    *cs_dmacachep;
+       size_t                  cs_size;
+       struct kmem_cache       *cs_cachep;
+       struct kmem_cache       *cs_dmacachep;
 };
 extern struct cache_sizes malloc_sizes[];
 
@@ -211,7 +202,7 @@ extern unsigned int ksize(const void *);
 extern int slab_is_available(void);
 
 #ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node);
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
 
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
@@ -236,8 +227,27 @@ found:
        }
        return __kmalloc_node(size, flags, node);
 }
+
+/*
+ * kmalloc_node_track_caller is a special version of kmalloc_node that
+ * records the calling function of the routine calling it for slab leak
+ * tracking instead of just the calling function (confusing, eh?).
+ * It's useful when the call to kmalloc_node comes from a widely-used
+ * standard allocator where we care about the real place the memory
+ * allocation request comes from.
+ */
+#ifndef CONFIG_DEBUG_SLAB
+#define kmalloc_node_track_caller(size, flags, node) \
+       __kmalloc_node(size, flags, node)
 #else
-static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int node)
+extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
+#define kmalloc_node_track_caller(size, flags, node) \
+       __kmalloc_node_track_caller(size, flags, node, \
+                       __builtin_return_address(0))
+#endif
+#else /* CONFIG_NUMA */
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+                                       gfp_t flags, int node)
 {
        return kmem_cache_alloc(cachep, flags);
 }
@@ -245,10 +255,13 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
        return kmalloc(size, flags);
 }
+
+#define kmalloc_node_track_caller(size, flags, node) \
+       kmalloc_track_caller(size, flags)
 #endif
 
 extern int FASTCALL(kmem_cache_reap(int));
-extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr));
+extern int FASTCALL(kmem_ptr_validate(struct kmem_cache *cachep, void *ptr));
 
 #else /* CONFIG_SLOB */
 
@@ -283,16 +296,9 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 #define kzalloc(s, f) __kzalloc(s, f)
 #define kmalloc_track_caller kmalloc
 
-#endif /* CONFIG_SLOB */
+#define kmalloc_node_track_caller kmalloc_node
 
-/* System wide caches */
-extern kmem_cache_t    *vm_area_cachep;
-extern kmem_cache_t    *names_cachep;
-extern kmem_cache_t    *files_cachep;
-extern kmem_cache_t    *filp_cachep;
-extern kmem_cache_t    *fs_cachep;
-extern kmem_cache_t    *sighand_cachep;
-extern kmem_cache_t    *bio_cachep;
+#endif /* CONFIG_SLOB */
 
 #endif /* __KERNEL__ */
 
index 5164998..7ba23ec 100644 (file)
@@ -99,6 +99,13 @@ static inline int up_smp_call_function(void)
 static inline void smp_send_reschedule(int cpu) { }
 #define num_booting_cpus()                     1
 #define smp_prepare_boot_cpu()                 do {} while (0)
+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 /* !SMP */
 
index 8451052..94b767d 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/thread_info.h>
 #include <linux/kernel.h>
 #include <linux/stringify.h>
+#include <linux/bottom_half.h>
 
 #include <asm/system.h>
 
index 13a37f1..4a0a329 100644 (file)
  *     protection - since "write" code only needs to change the head, and
  *     interrupt code only needs to change the tail.
  */
-typedef struct {
+struct stlrq {
        char    *buf;
        char    *head;
        char    *tail;
-} stlrq_t;
+};
 
 /*
  *     Port, panel and board structures to hold status info about each.
@@ -67,14 +67,14 @@ typedef struct {
  *     is associated with, this makes it (fairly) easy to get back to the
  *     board/panel info for a port.
  */
-typedef struct stlport {
+struct stlport {
        unsigned long           magic;
-       int                     portnr;
-       int                     panelnr;
-       int                     brdnr;
+       unsigned int            portnr;
+       unsigned int            panelnr;
+       unsigned int            brdnr;
        int                     ioaddr;
        int                     uartaddr;
-       int                     pagenr;
+       unsigned int            pagenr;
        long                    istate;
        int                     flags;
        int                     baud_base;
@@ -97,31 +97,31 @@ typedef struct stlport {
        wait_queue_head_t       close_wait;
        struct work_struct      tqueue;
        comstats_t              stats;
-       stlrq_t                 tx;
-} stlport_t;
+       struct stlrq            tx;
+};
 
-typedef struct stlpanel {
+struct stlpanel {
        unsigned long   magic;
-       int             panelnr;
-       int             brdnr;
-       int             pagenr;
-       int             nrports;
+       unsigned int    panelnr;
+       unsigned int    brdnr;
+       unsigned int    pagenr;
+       unsigned int    nrports;
        int             iobase;
        void            *uartp;
        void            (*isr)(struct stlpanel *panelp, unsigned int iobase);
        unsigned int    hwid;
        unsigned int    ackmask;
-       stlport_t       *ports[STL_PORTSPERPANEL];
-} stlpanel_t;
+       struct stlport  *ports[STL_PORTSPERPANEL];
+};
 
-typedef struct stlbrd {
+struct stlbrd {
        unsigned long   magic;
-       int             brdnr;
-       int             brdtype;
-       int             state;
-       int             nrpanels;
-       int             nrports;
-       int             nrbnks;
+       unsigned int    brdnr;
+       unsigned int    brdtype;
+       unsigned int    state;
+       unsigned int    nrpanels;
+       unsigned int    nrports;
+       unsigned int    nrbnks;
        int             irq;
        int             irqtype;
        int             (*isr)(struct stlbrd *brdp);
@@ -136,9 +136,9 @@ typedef struct stlbrd {
        unsigned long   clk;
        unsigned int    bnkpageaddr[STL_MAXBANKS];
        unsigned int    bnkstataddr[STL_MAXBANKS];
-       stlpanel_t      *bnk2panel[STL_MAXBANKS];
-       stlpanel_t      *panels[STL_MAXPANELS];
-} stlbrd_t;
+       struct stlpanel *bnk2panel[STL_MAXBANKS];
+       struct stlpanel *panels[STL_MAXPANELS];
+};
 
 
 /*
diff --git a/include/linux/start_kernel.h b/include/linux/start_kernel.h
new file mode 100644 (file)
index 0000000..d3e5f27
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LINUX_START_KERNEL_H
+#define _LINUX_START_KERNEL_H
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+/* Define the prototype for start_kernel here, rather than cluttering
+   up something else. */
+
+extern asmlinkage void __init start_kernel(void);
+
+#endif /* _LINUX_START_KERNEL_H */
index 97b62e9..2db2fbf 100644 (file)
@@ -90,8 +90,6 @@ struct gss_cred {
 #define gc_flags               gc_base.cr_flags
 #define gc_expire              gc_base.cr_expire
 
-void print_hexl(u32 *p, u_int length, u_int offset);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
 
index f6d1d64..a1be89d 100644 (file)
@@ -53,6 +53,7 @@ struct rpc_clnt {
        struct dentry *         cl_dentry;      /* inode */
        struct rpc_clnt *       cl_parent;      /* Points to parent of clones */
        struct rpc_rtt          cl_rtt_default;
+       struct rpc_program *    cl_program;
        char                    cl_inline_name[32];
 };
 
index e4729aa..60fce3c 100644 (file)
@@ -62,12 +62,6 @@ extern unsigned int          nlm_debug;
 # define RPC_IFDEBUG(x)
 #endif
 
-#ifdef RPC_PROFILE
-# define pprintk(args...)      printk(## args)
-#else
-# define pprintk(args...)      do ; while (0)
-#endif
-
 /*
  * Sysctl interface for RPC debugging
  */
index e30ba20..5a4b1e0 100644 (file)
 
 struct krb5_ctx {
        int                     initiate; /* 1 = initiating, 0 = accepting */
-       int                     seed_init;
-       unsigned char           seed[16];
-       int                     signalg;
-       int                     sealalg;
        struct crypto_blkcipher *enc;
        struct crypto_blkcipher *seq;
        s32                     endtime;
@@ -117,7 +113,7 @@ enum seal_alg {
 #define ENCTYPE_UNKNOWN         0x01ff
 
 s32
-make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body,
                   int body_offset, struct xdr_netobj *cksum);
 
 u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
index 2cf3fbb..e3e6a34 100644 (file)
 #include <linux/sunrpc/gss_asn1.h>
 
 struct spkm3_ctx {
-       struct xdr_netobj       ctx_id; /* per message context id */
-       int                     qop;         /* negotiated qop */
+       struct xdr_netobj       ctx_id;  /* per message context id */
+       int                     endtime; /* endtime of the context */
        struct xdr_netobj       mech_used;
        unsigned int            ret_flags ;
-       unsigned int            req_flags ;
-       struct xdr_netobj       share_key;
-       int                     conf_alg;
-       struct crypto_blkcipher *derived_conf_key;
-       int                     intg_alg;
-       struct crypto_blkcipher *derived_integ_key;
-       int                     keyestb_alg;   /* alg used to get share_key */
-       int                     owf_alg;   /* one way function */
+       struct xdr_netobj       conf_alg;
+       struct xdr_netobj       derived_conf_key;
+       struct xdr_netobj       intg_alg;
+       struct xdr_netobj       derived_integ_key;
 };
 
-/* from openssl/objects.h */
-/* XXX need SEAL_ALG_NONE */
-#define NID_md5                4
-#define NID_dhKeyAgreement     28 
-#define NID_des_cbc            31 
-#define NID_sha1               64
-#define NID_cast5_cbc          108
+/* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */
+extern const struct xdr_netobj hmac_md5_oid;
+extern const struct xdr_netobj cast5_cbc_oid;
 
 /* SPKM InnerContext Token types */
 
@@ -46,11 +38,13 @@ u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_ne
 u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
 
 #define CKSUMTYPE_RSA_MD5            0x0007
+#define CKSUMTYPE_HMAC_MD5           0x0008
 
-s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-                   int body_offset, struct xdr_netobj *cksum);
+s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+               unsigned int hdrlen, struct xdr_buf *body,
+               unsigned int body_offset, struct xdr_netobj *cksum);
 void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
-int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, 
+int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen,
                    int explen);
 void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
                    unsigned char *ctxhdr, int elen, int zbit);
index a2eb9b4..4a68125 100644 (file)
@@ -30,7 +30,7 @@ struct rpc_inode {
 #define RPC_PIPE_WAIT_FOR_OPEN 1
        int flags;
        struct rpc_pipe_ops *ops;
-       struct work_struct queue_timeout;
+       struct delayed_work queue_timeout;
 };
 
 static inline struct rpc_inode *
index f399c13..97c7616 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/timer.h>
 #include <linux/sunrpc/types.h>
+#include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
@@ -85,6 +86,7 @@ struct rpc_task {
        union {
                struct work_struct      tk_work;        /* Async task work queue */
                struct rpc_wait         tk_wait;        /* RPC wait */
+               struct rcu_head         tk_rcu;         /* for task deletion */
        } u;
 
        unsigned short          tk_timeouts;    /* maj timeouts */
@@ -178,13 +180,6 @@ struct rpc_call_ops {
        } while (0)
 
 #define RPC_IS_ACTIVATED(t)    (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
-#define rpc_set_active(t)      (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
-#define rpc_clear_active(t)    \
-       do { \
-               smp_mb__before_clear_bit(); \
-               clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \
-               smp_mb__after_clear_bit(); \
-       } while(0)
 
 /*
  * Task priorities.
@@ -222,7 +217,7 @@ struct rpc_wait_queue {
 
 #ifndef RPC_DEBUG
 # define RPC_WAITQ_INIT(var,qname) { \
-               .lock = SPIN_LOCK_UNLOCKED, \
+               .lock = __SPIN_LOCK_UNLOCKED(var.lock), \
                .tasks = { \
                        [0] = LIST_HEAD_INIT(var.tasks[0]), \
                        [1] = LIST_HEAD_INIT(var.tasks[1]), \
@@ -231,7 +226,7 @@ struct rpc_wait_queue {
        }
 #else
 # define RPC_WAITQ_INIT(var,qname) { \
-               .lock = SPIN_LOCK_UNLOCKED, \
+               .lock = __SPIN_LOCK_UNLOCKED(var.lock), \
                .tasks = { \
                        [0] = LIST_HEAD_INIT(var.tasks[0]), \
                        [1] = LIST_HEAD_INIT(var.tasks[1]), \
@@ -254,8 +249,10 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
 void           rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
                                int flags, const struct rpc_call_ops *ops,
                                void *data);
+void           rpc_put_task(struct rpc_task *);
 void           rpc_release_task(struct rpc_task *);
 void           rpc_exit_task(struct rpc_task *);
+void           rpc_release_calldata(const struct rpc_call_ops *, void *);
 void           rpc_killall_tasks(struct rpc_clnt *);
 int            rpc_execute(struct rpc_task *);
 void           rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
index 9a527c3..9e340fa 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/uio.h>
 #include <asm/byteorder.h>
+#include <linux/scatterlist.h>
 
 /*
  * Buffer adjustment
@@ -139,29 +140,30 @@ xdr_adjust_iovec(struct kvec *iov, __be32 *p)
  */
 extern void xdr_shift_buf(struct xdr_buf *, size_t);
 extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
-extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, int, int);
-extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, int);
-extern int read_bytes_from_xdr_buf(struct xdr_buf *, int, void *, int);
-extern int write_bytes_to_xdr_buf(struct xdr_buf *, int, void *, int);
+extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int);
+extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int);
+extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
+extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
 
 /*
  * Helper structure for copying from an sk_buff.
  */
-typedef struct {
+struct xdr_skb_reader {
        struct sk_buff  *skb;
        unsigned int    offset;
        size_t          count;
        __wsum          csum;
-} skb_reader_t;
+};
 
-typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
+typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len);
 
+size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len);
 extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
 extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
-               skb_reader_t *, skb_read_actor_t);
+               struct xdr_skb_reader *, xdr_skb_read_actor);
 
-extern int xdr_encode_word(struct xdr_buf *, int, u32);
-extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
+extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32);
+extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *);
 
 struct xdr_array2_desc;
 typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
@@ -196,6 +198,7 @@ extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32
 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
+extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
 
 #endif /* __KERNEL__ */
 
index 60394fb..f780e72 100644 (file)
@@ -106,7 +106,6 @@ struct rpc_rqst {
 
 struct rpc_xprt_ops {
        void            (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
-       char *          (*print_addr)(struct rpc_xprt *xprt, enum rpc_display_format_t format);
        int             (*reserve_xprt)(struct rpc_task *task);
        void            (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
        void            (*rpcbind)(struct rpc_task *task);
@@ -126,8 +125,6 @@ struct rpc_xprt_ops {
 struct rpc_xprt {
        struct kref             kref;           /* Reference count */
        struct rpc_xprt_ops *   ops;            /* transport methods */
-       struct socket *         sock;           /* BSD socket layer */
-       struct sock *           inet;           /* INET layer */
 
        struct rpc_timeout      timeout;        /* timeout parms */
        struct sockaddr_storage addr;           /* server address */
@@ -137,9 +134,6 @@ struct rpc_xprt {
        unsigned long           cong;           /* current congestion */
        unsigned long           cwnd;           /* congestion window */
 
-       size_t                  rcvsize,        /* transport rcv buffer size */
-                               sndsize;        /* transport send buffer size */
-
        size_t                  max_payload;    /* largest RPC payload size,
                                                   in bytes */
        unsigned int            tsh_size;       /* size of transport specific
@@ -157,28 +151,12 @@ struct rpc_xprt {
        unsigned char           shutdown   : 1, /* being shut down */
                                resvport   : 1; /* use a reserved port */
 
-       /*
-        * XID
-        */
-       __u32                   xid;            /* Next XID value to use */
-
-       /*
-        * State of TCP reply receive stuff
-        */
-       __be32                  tcp_recm,       /* Fragment header */
-                               tcp_xid;        /* Current XID */
-       u32                     tcp_reclen,     /* fragment length */
-                               tcp_offset;     /* fragment offset */
-       unsigned long           tcp_copied,     /* copied to request */
-                               tcp_flags;
        /*
         * Connection of transports
         */
        unsigned long           connect_timeout,
                                bind_timeout,
                                reestablish_timeout;
-       struct work_struct      connect_worker;
-       unsigned short          port;
 
        /*
         * Disconnection of idle transports
@@ -193,8 +171,8 @@ struct rpc_xprt {
         */
        spinlock_t              transport_lock; /* lock transport info */
        spinlock_t              reserve_lock;   /* lock slot table */
+       u32                     xid;            /* Next XID value to use */
        struct rpc_task *       snd_task;       /* Task blocked in send */
-
        struct list_head        recv;
 
        struct {
@@ -210,18 +188,9 @@ struct rpc_xprt {
                                        bklog_u;        /* backlog queue utilization */
        } stat;
 
-       void                    (*old_data_ready)(struct sock *, int);
-       void                    (*old_state_change)(struct sock *);
-       void                    (*old_write_space)(struct sock *);
-
        char *                  address_strings[RPC_DISPLAY_MAX];
 };
 
-#define XPRT_LAST_FRAG         (1 << 0)
-#define XPRT_COPY_RECM         (1 << 1)
-#define XPRT_COPY_XID          (1 << 2)
-#define XPRT_COPY_DATA         (1 << 3)
-
 #ifdef __KERNEL__
 
 /*
@@ -270,8 +239,8 @@ void                        xprt_disconnect(struct rpc_xprt *xprt);
 /*
  * Socket transport setup operations
  */
-int                    xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
-int                    xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+struct rpc_xprt *      xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
+struct rpc_xprt *      xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
 
 /*
  * Reserved bit positions in xprt->state
index b1237f1..bf99bd4 100644 (file)
@@ -9,10 +9,13 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 
-/* page backup entry */
+/* struct pbe is used for creating lists of pages that should be restored
+ * atomically during the resume from disk, because the page frames they have
+ * occupied before the suspend are in use.
+ */
 struct pbe {
-       unsigned long address;          /* address of the copy */
-       unsigned long orig_address;     /* original address of page */
+       void *address;          /* address of the copy */
+       void *orig_address;     /* original address of a page */
        struct pbe *next;
 };
 
index e7c36ba..add51ce 100644 (file)
@@ -218,8 +218,6 @@ extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *);
 /* linux/mm/page_io.c */
 extern int swap_readpage(struct file *, struct page *);
 extern int swap_writepage(struct page *page, struct writeback_control *wbc);
-extern int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page,
-                               struct bio **bio_chain);
 extern int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err);
 
 /* linux/mm/swap_state.c */
@@ -247,9 +245,10 @@ extern int swap_duplicate(swp_entry_t);
 extern int valid_swaphandles(swp_entry_t, unsigned long *);
 extern void swap_free(swp_entry_t);
 extern void free_swap_and_cache(swp_entry_t);
-extern int swap_type_of(dev_t);
+extern int swap_type_of(dev_t, sector_t);
 extern unsigned int count_swap_pages(int, int);
 extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t);
+extern sector_t swapdev_block(int, pgoff_t);
 extern struct swap_info_struct *get_swap_info_struct(unsigned);
 extern int can_share_swap_page(struct page *);
 extern int remove_exclusive_swap_page(struct page *);
@@ -259,7 +258,6 @@ extern spinlock_t swap_lock;
 
 /* linux/mm/thrash.c */
 extern struct mm_struct * swap_token_mm;
-extern unsigned long swap_token_default_timeout;
 extern void grab_swap_token(void);
 extern void __put_swap_token(struct mm_struct *);
 
index 94316a9..6d8846e 100644 (file)
@@ -918,8 +918,7 @@ typedef struct ctl_table ctl_table;
 
 typedef int ctl_handler (ctl_table *table, int __user *name, int nlen,
                         void __user *oldval, size_t __user *oldlenp,
-                        void __user *newval, size_t newlen, 
-                        void **context);
+                        void __user *newval, size_t newlen);
 
 typedef int proc_handler (ctl_table *ctl, int write, struct file * filp,
                          void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -950,7 +949,7 @@ extern int do_sysctl (int __user *name, int nlen,
 extern int do_sysctl_strategy (ctl_table *table, 
                               int __user *name, int nlen,
                               void __user *oldval, size_t __user *oldlenp,
-                              void __user *newval, size_t newlen, void ** context);
+                              void __user *newval, size_t newlen);
 
 extern ctl_handler sysctl_string;
 extern ctl_handler sysctl_intvec;
diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h
new file mode 100644 (file)
index 0000000..44d00e9
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * task_io_accounting: a structure which is used for recording a single task's
+ * IO statistics.
+ *
+ * Don't include this header file directly - it is designed to be dragged in via
+ * sched.h.
+ *
+ * Blame akpm@osdl.org for all this.
+ */
+
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+struct task_io_accounting {
+       /*
+        * The number of bytes which this task has caused to be read from
+        * storage.
+        */
+       u64 read_bytes;
+
+       /*
+        * The number of bytes which this task has caused, or shall cause to be
+        * written to disk.
+        */
+       u64 write_bytes;
+
+       /*
+        * A task can cause "negative" IO too.  If this task truncates some
+        * dirty pagecache, some IO which another task has been accounted for
+        * (in its write_bytes) will not be happening.  We _could_ just
+        * subtract that from the truncating task's write_bytes, but there is
+        * information loss in doing that.
+        */
+       u64 cancelled_write_bytes;
+};
+#else
+struct task_io_accounting {
+};
+#endif
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
new file mode 100644 (file)
index 0000000..df2a319
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Task I/O accounting operations
+ */
+#ifndef __TASK_IO_ACCOUNTING_OPS_INCLUDED
+#define __TASK_IO_ACCOUNTING_OPS_INCLUDED
+
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+static inline void task_io_account_read(size_t bytes)
+{
+       current->ioac.read_bytes += bytes;
+}
+
+static inline void task_io_account_write(size_t bytes)
+{
+       current->ioac.write_bytes += bytes;
+}
+
+static inline void task_io_account_cancelled_write(size_t bytes)
+{
+       current->ioac.cancelled_write_bytes += bytes;
+}
+
+static inline void task_io_accounting_init(struct task_struct *tsk)
+{
+       memset(&tsk->ioac, 0, sizeof(tsk->ioac));
+}
+
+#else
+
+static inline void task_io_account_read(size_t bytes)
+{
+}
+
+static inline void task_io_account_write(size_t bytes)
+{
+}
+
+static inline void task_io_account_cancelled_write(size_t bytes)
+{
+}
+
+static inline void task_io_accounting_init(struct task_struct *tsk)
+{
+}
+
+#endif         /* CONFIG_TASK_IO_ACCOUNTING */
+#endif         /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */
index 4524880..3fced47 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 
-#define TASKSTATS_VERSION      2
+#define TASKSTATS_VERSION      3
 #define TS_COMM_LEN            32      /* should be >= TASK_COMM_LEN
                                         * in linux/sched.h */
 
@@ -115,31 +115,37 @@ struct taskstats {
        __u64   ac_majflt;              /* Major Page Fault Count */
        /* Basic Accounting Fields end */
 
-       /* Extended accounting fields start */
+       /* Extended accounting fields start */
        /* Accumulated RSS usage in duration of a task, in MBytes-usecs.
         * The current rss usage is added to this counter every time
         * a tick is charged to a task's system time. So, at the end we
         * will have memory usage multiplied by system time. Thus an
         * average usage per system time unit can be calculated.
         */
-       __u64   coremem;                /* accumulated RSS usage in MB-usec */
+       __u64   coremem;                /* accumulated RSS usage in MB-usec */
        /* Accumulated virtual memory usage in duration of a task.
         * Same as acct_rss_mem1 above except that we keep track of VM usage.
         */
-       __u64   virtmem;                /* accumulated VM  usage in MB-usec */
+       __u64   virtmem;                /* accumulated VM  usage in MB-usec */
 
        /* High watermark of RSS and virtual memory usage in duration of
         * a task, in KBytes.
         */
-       __u64   hiwater_rss;            /* High-watermark of RSS usage, in KB */
-       __u64   hiwater_vm;             /* High-water VM usage, in KB */
+       __u64   hiwater_rss;            /* High-watermark of RSS usage, in KB */
+       __u64   hiwater_vm;             /* High-water VM usage, in KB */
 
        /* The following four fields are I/O statistics of a task. */
-       __u64   read_char;              /* bytes read */
-       __u64   write_char;             /* bytes written */
-       __u64   read_syscalls;          /* read syscalls */
-       __u64   write_syscalls;         /* write syscalls */
-       /* Extended accounting fields end */
+       __u64   read_char;              /* bytes read */
+       __u64   write_char;             /* bytes written */
+       __u64   read_syscalls;          /* read syscalls */
+       __u64   write_syscalls;         /* write syscalls */
+       /* Extended accounting fields end */
+
+#define TASKSTATS_HAS_IO_ACCOUNTING
+       /* Per-task storage I/O accounting starts */
+       __u64   read_bytes;             /* bytes of read I/O */
+       __u64   write_bytes;            /* bytes of write I/O */
+       __u64   cancelled_write_bytes;  /* bytes of cancelled write I/O */
 };
 
 
index 6562a20..7e9680f 100644 (file)
 #include <net/genetlink.h>
 
 #ifdef CONFIG_TASKSTATS
-extern kmem_cache_t *taskstats_cache;
+extern struct kmem_cache *taskstats_cache;
 extern struct mutex taskstats_exit_mutex;
 
-static inline void taskstats_exit_free(struct taskstats *tidstats)
-{
-       if (tidstats)
-               kmem_cache_free(taskstats_cache, tidstats);
-}
-
 static inline void taskstats_tgid_init(struct signal_struct *sig)
 {
        sig->stats = NULL;
 }
 
-static inline void taskstats_tgid_alloc(struct task_struct *tsk)
-{
-       struct signal_struct *sig = tsk->signal;
-       struct taskstats *stats;
-
-       if (sig->stats != NULL)
-               return;
-
-       /* No problem if kmem_cache_zalloc() fails */
-       stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL);
-
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (!sig->stats) {
-               sig->stats = stats;
-               stats = NULL;
-       }
-       spin_unlock_irq(&tsk->sighand->siglock);
-
-       if (stats)
-               kmem_cache_free(taskstats_cache, stats);
-}
-
 static inline void taskstats_tgid_free(struct signal_struct *sig)
 {
        if (sig->stats)
                kmem_cache_free(taskstats_cache, sig->stats);
 }
 
-extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
-extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
+extern void taskstats_exit(struct task_struct *, int group_dead);
 extern void taskstats_init_early(void);
 #else
-static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
-{}
-static inline void taskstats_exit_free(struct taskstats *ptidstats)
-{}
-static inline void taskstats_exit_send(struct task_struct *tsk,
-                                      struct taskstats *tidstats,
-                                      int group_dead, unsigned int cpu)
+static inline void taskstats_exit(struct task_struct *tsk, int group_dead)
 {}
 static inline void taskstats_tgid_init(struct signal_struct *sig)
 {}
-static inline void taskstats_tgid_alloc(struct task_struct *tsk)
-{}
 static inline void taskstats_tgid_free(struct signal_struct *sig)
 {}
 static inline void taskstats_init_early(void)
index 31a9b25..8a8462b 100644 (file)
@@ -37,10 +37,14 @@ struct tfrc_rx_info {
  *     @tfrctx_p:      current loss event rate (5.4)
  *     @tfrctx_rto:    estimate of RTO, equals 4*RTT (4.3)
  *     @tfrctx_ipi:    inter-packet interval (4.6)
+ *
+ *  Note: X and X_recv are both maintained in units of 64 * bytes/second. This
+ *        enables a finer resolution of sending rates and avoids problems with
+ *        integer arithmetic; u32 is not sufficient as scaling consumes 6 bits.
  */
 struct tfrc_tx_info {
-       __u32 tfrctx_x;
-       __u32 tfrctx_x_recv;
+       __u64 tfrctx_x;
+       __u64 tfrctx_x_recv;
        __u32 tfrctx_x_calc;
        __u32 tfrctx_rtt;
        __u32 tfrctx_p;
index c982304..eeef664 100644 (file)
@@ -98,4 +98,10 @@ extern void run_local_timers(void);
 struct hrtimer;
 extern int it_real_fn(struct hrtimer *);
 
+unsigned long __round_jiffies(unsigned long j, int cpu);
+unsigned long __round_jiffies_relative(unsigned long j, int cpu);
+unsigned long round_jiffies(unsigned long j);
+unsigned long round_jiffies_relative(unsigned long j);
+
+
 #endif
index da508d1..6c5a6e6 100644 (file)
@@ -93,7 +93,7 @@
        .groups                 = NULL,                 \
        .min_interval           = 1,                    \
        .max_interval           = 2,                    \
-       .busy_factor            = 8,                    \
+       .busy_factor            = 64,                   \
        .imbalance_pct          = 110,                  \
        .cache_nice_tries       = 0,                    \
        .per_cpu_gain           = 25,                   \
        .wake_idx               = 0, /* unused */       \
        .forkexec_idx           = 0, /* unused */       \
        .per_cpu_gain           = 100,                  \
-       .flags                  = SD_LOAD_BALANCE,      \
+       .flags                  = SD_LOAD_BALANCE       \
+                               | SD_SERIALIZE, \
        .last_balance           = jiffies,              \
        .balance_interval       = 64,                   \
        .nr_balance_failed      = 0,                    \
index 65321f9..65cbcf2 100644 (file)
@@ -53,7 +53,7 @@ struct tty_buffer {
 };
 
 struct tty_bufhead {
-       struct work_struct              work;
+       struct delayed_work work;
        struct semaphore pty_sem;
        spinlock_t lock;
        struct tty_buffer *head;        /* Queue head */
@@ -175,7 +175,7 @@ struct tty_struct {
        int index;
        struct tty_ldisc ldisc;
        struct mutex termios_mutex;
-       struct termios *termios, *termios_locked;
+       struct ktermios *termios, *termios_locked;
        char name[64];
        int pgrp;
        int session;
@@ -258,7 +258,7 @@ struct tty_struct {
 
 extern void tty_write_flush(struct tty_struct *);
 
-extern struct termios tty_std_termios;
+extern struct ktermios tty_std_termios;
 
 extern int kmsg_redirect;
 
@@ -293,8 +293,9 @@ extern int tty_hung_up_p(struct file * filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
-extern int tty_get_baud_rate(struct tty_struct *tty);
-extern int tty_termios_baud_rate(struct termios *termios);
+extern speed_t tty_get_baud_rate(struct tty_struct *tty);
+extern speed_t tty_termios_baud_rate(struct ktermios *termios);
+extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
 
 extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
 extern void tty_ldisc_deref(struct tty_ldisc *);
@@ -309,6 +310,12 @@ extern void tty_ldisc_flush(struct tty_struct *tty);
 extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                     unsigned long arg);
 
+extern dev_t tty_devnum(struct tty_struct *tty);
+extern void proc_clear_tty(struct task_struct *p);
+extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+extern struct tty_struct *get_current_tty(void);
+
 extern struct mutex tty_mutex;
 
 /* n_tty.c */
@@ -335,10 +342,5 @@ extern void console_print(const char *);
 extern int vt_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg);
 
-static inline dev_t tty_devnum(struct tty_struct *tty)
-{
-       return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
-}
-
 #endif /* __KERNEL__ */
 #endif
index 5c8473b..659487e 100644 (file)
@@ -53,7 +53,7 @@
  *     device-specific ioctl's.  If the ioctl number passed in cmd
  *     is not recognized by the driver, it should return ENOIOCTLCMD.
  * 
- * void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  *     This routine allows the tty driver to be notified when
  *     device's termios settings have changed.  Note that a
@@ -132,7 +132,7 @@ struct tty_operations {
        int  (*chars_in_buffer)(struct tty_struct *tty);
        int  (*ioctl)(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg);
-       void (*set_termios)(struct tty_struct *tty, struct termios * old);
+       void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        void (*throttle)(struct tty_struct * tty);
        void (*unthrottle)(struct tty_struct * tty);
        void (*stop)(struct tty_struct *tty);
@@ -165,7 +165,7 @@ struct tty_driver {
        int     num;            /* number of devices allocated */
        short   type;           /* type of tty driver */
        short   subtype;        /* subtype of tty driver */
-       struct termios init_termios; /* Initial termios */
+       struct ktermios init_termios; /* Initial termios */
        int     flags;          /* tty driver flags */
        int     refcount;       /* for loadable tty drivers */
        struct proc_dir_entry *proc_entry; /* /proc fs entry */
@@ -175,8 +175,8 @@ struct tty_driver {
         * Pointer to the tty data structures
         */
        struct tty_struct **ttys;
-       struct termios **termios;
-       struct termios **termios_locked;
+       struct ktermios **termios;
+       struct ktermios **termios_locked;
        void *driver_state;     /* only used for the PTY driver */
        
        /*
@@ -193,7 +193,7 @@ struct tty_driver {
        int  (*chars_in_buffer)(struct tty_struct *tty);
        int  (*ioctl)(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg);
-       void (*set_termios)(struct tty_struct *tty, struct termios * old);
+       void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        void (*throttle)(struct tty_struct * tty);
        void (*unthrottle)(struct tty_struct * tty);
        void (*stop)(struct tty_struct *tty);
index 83c6e6c..d75932e 100644 (file)
@@ -59,7 +59,7 @@
  *     low-level driver can "grab" an ioctl request before the line
  *     discpline has a chance to see it.
  * 
- * void        (*set_termios)(struct tty_struct *tty, struct termios * old);
+ * void        (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  *     This function notifies the line discpline that a change has
  *     been made to the termios structure.
@@ -118,7 +118,7 @@ struct tty_ldisc {
                         const unsigned char * buf, size_t nr); 
        int     (*ioctl)(struct tty_struct * tty, struct file * file,
                         unsigned int cmd, unsigned long arg);
-       void    (*set_termios)(struct tty_struct *tty, struct termios * old);
+       void    (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        unsigned int (*poll)(struct tty_struct *, struct file *,
                             struct poll_table_struct *);
        int     (*hangup)(struct tty_struct *tty);
index a48d7f1..975c963 100644 (file)
@@ -1,8 +1,43 @@
 #ifndef __LINUX_UACCESS_H__
 #define __LINUX_UACCESS_H__
 
+#include <linux/preempt.h>
 #include <asm/uaccess.h>
 
+/*
+ * These routines enable/disable the pagefault handler in that
+ * it will not take any locks and go straight to the fixup table.
+ *
+ * They have great resemblance to the preempt_disable/enable calls
+ * and in fact they are identical; this is because currently there is
+ * no other way to make the pagefault handlers do this. So we do
+ * disable preemption but we don't necessarily care about that.
+ */
+static inline void pagefault_disable(void)
+{
+       inc_preempt_count();
+       /*
+        * make sure to have issued the store before a pagefault
+        * can hit.
+        */
+       barrier();
+}
+
+static inline void pagefault_enable(void)
+{
+       /*
+        * make sure to issue those last loads/stores before enabling
+        * the pagefault handler again.
+        */
+       barrier();
+       dec_preempt_count();
+       /*
+        * make sure we do..
+        */
+       barrier();
+       preempt_check_resched();
+}
+
 #ifndef ARCH_HAS_NOCACHE_UACCESS
 
 static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
@@ -30,14 +65,22 @@ static inline unsigned long __copy_from_user_nocache(void *to,
  * 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.
+ * This must be a macro because __get_user() needs to know the types of the
+ * args.
+ *
+ * We don't include enough header files to be able to do the set_fs().  We
+ * require that the probe_kernel_address() caller will do that.
  */
 #define probe_kernel_address(addr, retval)             \
        ({                                              \
                long ret;                               \
+               mm_segment_t old_fs = get_fs();         \
                                                        \
-               inc_preempt_count();                    \
-               ret = __get_user(retval, addr);         \
-               dec_preempt_count();                    \
+               set_fs(KERNEL_DS);                      \
+               pagefault_disable();                    \
+               ret = __get_user(retval, (__force typeof(retval) __user *)(addr));              \
+               pagefault_enable();                     \
+               set_fs(old_fs);                         \
                ret;                                    \
        })
 
index 0cd73ed..aab5b1b 100644 (file)
@@ -388,7 +388,7 @@ struct usb_device {
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
 #ifdef CONFIG_PM
-       struct work_struct autosuspend; /* for delayed autosuspends */
+       struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
 
        unsigned auto_pm:1;             /* autosuspend/resume in progress */
index 91b3ea2..10f99e5 100644 (file)
@@ -218,7 +218,7 @@ struct usb_serial_driver {
        int  (*write)           (struct usb_serial_port *port, const unsigned char *buf, int count);
        int  (*write_room)      (struct usb_serial_port *port);
        int  (*ioctl)           (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-       void (*set_termios)     (struct usb_serial_port *port, struct termios * old);
+       void (*set_termios)     (struct usb_serial_port *port, struct ktermios * old);
        void (*break_ctl)       (struct usb_serial_port *port, int break_state);
        int  (*chars_in_buffer) (struct usb_serial_port *port);
        void (*throttle)        (struct usb_serial_port *port);
index df5c465..5cb380a 100644 (file)
@@ -244,6 +244,7 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V') /* 16  YUV 4:2:2     */
 #define V4L2_PIX_FMT_HI240   v4l2_fourcc('H','I','2','4') /*  8  8-bit color   */
 #define V4L2_PIX_FMT_HM12    v4l2_fourcc('H','M','1','2') /*  8  YUV 4:2:0 16x16 macroblocks */
+#define V4L2_PIX_FMT_RGB444  v4l2_fourcc('R','4','4','4') /* 16  xxxxrrrr ggggbbbb */
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
index 9bca353..edef8d5 100644 (file)
 
 struct workqueue_struct;
 
+struct work_struct;
+typedef void (*work_func_t)(struct work_struct *work);
+
 struct work_struct {
-       unsigned long pending;
+       /* the first word is the work queue pointer and the flags rolled into
+        * one */
+       unsigned long management;
+#define WORK_STRUCT_PENDING 0          /* T if work item pending execution */
+#define WORK_STRUCT_NOAUTOREL 1                /* F if work item automatically released on exec */
+#define WORK_STRUCT_FLAG_MASK (3UL)
+#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
        struct list_head entry;
-       void (*func)(void *);
-       void *data;
-       void *wq_data;
+       work_func_t func;
+};
+
+struct delayed_work {
+       struct work_struct work;
        struct timer_list timer;
 };
 
@@ -24,77 +35,160 @@ struct execute_work {
        struct work_struct work;
 };
 
-#define __WORK_INITIALIZER(n, f, d) {                          \
+#define __WORK_INITIALIZER(n, f) {                             \
+       .management = 0,                                        \
+        .entry = { &(n).entry, &(n).entry },                   \
+       .func = (f),                                            \
+       }
+
+#define __WORK_INITIALIZER_NAR(n, f) {                         \
+       .management = (1 << WORK_STRUCT_NOAUTOREL),             \
         .entry = { &(n).entry, &(n).entry },                   \
        .func = (f),                                            \
-       .data = (d),                                            \
+       }
+
+#define __DELAYED_WORK_INITIALIZER(n, f) {                     \
+       .work = __WORK_INITIALIZER((n).work, (f)),              \
+       .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
+       }
+
+#define __DELAYED_WORK_INITIALIZER_NAR(n, f) {                 \
+       .work = __WORK_INITIALIZER_NAR((n).work, (f)),          \
        .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
        }
 
-#define DECLARE_WORK(n, f, d)                                  \
-       struct work_struct n = __WORK_INITIALIZER(n, f, d)
+#define DECLARE_WORK(n, f)                                     \
+       struct work_struct n = __WORK_INITIALIZER(n, f)
+
+#define DECLARE_WORK_NAR(n, f)                                 \
+       struct work_struct n = __WORK_INITIALIZER_NAR(n, f)
+
+#define DECLARE_DELAYED_WORK(n, f)                             \
+       struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)
+
+#define DECLARE_DELAYED_WORK_NAR(n, f)                 \
+       struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f)
 
 /*
- * initialize a work-struct's func and data pointers:
+ * initialize a work item's function pointer
  */
-#define PREPARE_WORK(_work, _func, _data)                      \
+#define PREPARE_WORK(_work, _func)                             \
        do {                                                    \
-               (_work)->func = _func;                          \
-               (_work)->data = _data;                          \
+               (_work)->func = (_func);                        \
        } while (0)
 
+#define PREPARE_DELAYED_WORK(_work, _func)                     \
+       PREPARE_WORK(&(_work)->work, (_func))
+
 /*
- * initialize all of a work-struct:
+ * initialize all of a work item in one go
  */
-#define INIT_WORK(_work, _func, _data)                         \
+#define INIT_WORK(_work, _func)                                        \
        do {                                                    \
+               (_work)->management = 0;                        \
                INIT_LIST_HEAD(&(_work)->entry);                \
-               (_work)->pending = 0;                           \
-               PREPARE_WORK((_work), (_func), (_data));        \
+               PREPARE_WORK((_work), (_func));                 \
+       } while (0)
+
+#define INIT_WORK_NAR(_work, _func)                                    \
+       do {                                                            \
+               (_work)->management = (1 << WORK_STRUCT_NOAUTOREL);     \
+               INIT_LIST_HEAD(&(_work)->entry);                        \
+               PREPARE_WORK((_work), (_func));                         \
+       } while (0)
+
+#define INIT_DELAYED_WORK(_work, _func)                                \
+       do {                                                    \
+               INIT_WORK(&(_work)->work, (_func));             \
+               init_timer(&(_work)->timer);                    \
+       } while (0)
+
+#define INIT_DELAYED_WORK_NAR(_work, _func)                    \
+       do {                                                    \
+               INIT_WORK_NAR(&(_work)->work, (_func));         \
                init_timer(&(_work)->timer);                    \
        } while (0)
 
+/**
+ * work_pending - Find out whether a work item is currently pending
+ * @work: The work item in question
+ */
+#define work_pending(work) \
+       test_bit(WORK_STRUCT_PENDING, &(work)->management)
+
+/**
+ * delayed_work_pending - Find out whether a delayable work item is currently
+ * pending
+ * @work: The work item in question
+ */
+#define delayed_work_pending(work) \
+       test_bit(WORK_STRUCT_PENDING, &(work)->work.management)
+
+/**
+ * work_release - Release a work item under execution
+ * @work: The work item to release
+ *
+ * This is used to release a work item that has been initialised with automatic
+ * release mode disabled (WORK_STRUCT_NOAUTOREL is set).  This gives the work
+ * function the opportunity to grab auxiliary data from the container of the
+ * work_struct before clearing the pending bit as the work_struct may be
+ * subject to deallocation the moment the pending bit is cleared.
+ *
+ * In such a case, this should be called in the work function after it has
+ * fetched any data it may require from the containter of the work_struct.
+ * After this function has been called, the work_struct may be scheduled for
+ * further execution or it may be deallocated unless other precautions are
+ * taken.
+ *
+ * This should also be used to release a delayed work item.
+ */
+#define work_release(work) \
+       clear_bit(WORK_STRUCT_PENDING, &(work)->management)
+
+
 extern struct workqueue_struct *__create_workqueue(const char *name,
-                                                   int singlethread);
-#define create_workqueue(name) __create_workqueue((name), 0)
-#define create_singlethread_workqueue(name) __create_workqueue((name), 1)
+                                                   int singlethread,
+                                                   int freezeable);
+#define create_workqueue(name) __create_workqueue((name), 0, 0)
+#define create_freezeable_workqueue(name) __create_workqueue((name), 0, 1)
+#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
 extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work));
-extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay));
+extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay));
 extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
-       struct work_struct *work, unsigned long delay);
+       struct delayed_work *work, unsigned long delay);
 extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
-extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
+extern int FASTCALL(run_scheduled_work(struct work_struct *work));
+extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay));
 
-extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay);
-extern int schedule_on_each_cpu(void (*func)(void *info), void *info);
+extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay);
+extern int schedule_on_each_cpu(work_func_t func);
 extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
 
 extern void init_workqueues(void);
-void cancel_rearming_delayed_work(struct work_struct *work);
+void cancel_rearming_delayed_work(struct delayed_work *work);
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *,
-                                      struct work_struct *);
-int execute_in_process_context(void (*fn)(void *), void *,
-                              struct execute_work *);
+                                      struct delayed_work *);
+int execute_in_process_context(work_func_t fn, struct execute_work *);
 
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
  * function may still be running on return from cancel_delayed_work().  Run
  * flush_scheduled_work() to wait on it.
  */
-static inline int cancel_delayed_work(struct work_struct *work)
+static inline int cancel_delayed_work(struct delayed_work *work)
 {
        int ret;
 
        ret = del_timer_sync(&work->timer);
        if (ret)
-               clear_bit(0, &work->pending);
+               clear_bit(WORK_STRUCT_PENDING, &work->work.management);
        return ret;
 }
 
index 088ba81..9529ea1 100644 (file)
@@ -357,7 +357,7 @@ struct xfrm_user_report {
 #define XFRMGRP_EXPIRE         2
 #define XFRMGRP_SA             4
 #define XFRMGRP_POLICY         8
-#define XFRMGRP_REPORT         0x10
+#define XFRMGRP_REPORT         0x20
 #endif
 
 enum xfrm_nlgroups {
index 8f58406..2b25f5c 100644 (file)
@@ -92,6 +92,7 @@ extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
 
 #endif
 
index fee579f..796bcf1 100644 (file)
@@ -42,10 +42,6 @@ extern unsigned int saa7146_debug;
 #define DEB_INT(x)  if (0!=(DEBUG_VARIABLE&0x20)) { DEBUG_PROLOG; printk x; } /* interrupt debug messages */
 #define DEB_CAP(x)  if (0!=(DEBUG_VARIABLE&0x40)) { DEBUG_PROLOG; printk x; } /* capture debug messages */
 
-#define SAA7146_IER_DISABLE(x,y) \
-       saa7146_write(x, IER, saa7146_read(x, IER) & ~(y));
-#define SAA7146_IER_ENABLE(x,y) \
-       saa7146_write(x, IER, saa7146_read(x, IER) | (y));
 #define SAA7146_ISR_CLEAR(x,y) \
        saa7146_write(x, ISR, (y));
 
@@ -441,4 +437,20 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
 #define SAA7146_I2C_BUS_BIT_RATE_80    (0x200)
 #define SAA7146_I2C_BUS_BIT_RATE_60    (0x300)
 
+static inline void SAA7146_IER_DISABLE(struct saa7146_dev *x, unsigned y)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&x->int_slock, flags);
+       saa7146_write(x, IER, saa7146_read(x, IER) & ~y);
+       spin_unlock_irqrestore(&x->int_slock, flags);
+}
+
+static inline void SAA7146_IER_ENABLE(struct saa7146_dev *x, unsigned y)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&x->int_slock, flags);
+       saa7146_write(x, IER, saa7146_read(x, IER) | y);
+       spin_unlock_irqrestore(&x->int_slock, flags);
+}
+
 #endif
index 37dad07..e5ad3fc 100644 (file)
@@ -50,6 +50,10 @@ struct tuner_params {
           sensitivity. If this setting is 1, then set PORT2 to 1 to
           get proper FM reception. */
        unsigned int port2_fm_high_sensitivity:1;
+       /* Some Philips tuners use tda9887 cGainNormal to select the FM radio
+          sensitivity. If this setting is 1, e register will use cGainNormal
+          instead of cGainLow. */
+       unsigned int fm_gain_normal:1;
        /* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners
           use Intercarrier mode. If this setting is 1, then the tuner
           needs to be set to intercarrier mode. */
index 3116e75..99acf84 100644 (file)
@@ -145,6 +145,7 @@ extern int tuner_debug;
 #define TDA9887_DEEMPHASIS_75          (3<<16)
 #define TDA9887_AUTOMUTE               (1<<18)
 #define TDA9887_GATING_18              (1<<19)
+#define TDA9887_GAIN_NORMAL            (1<<20)
 
 #ifdef __KERNEL__
 
index e9fc1a7..5660ea2 100644 (file)
@@ -3,7 +3,7 @@
 
 struct tveeprom {
        u32 has_radio;
-       u32 has_ir;     /* 0: no IR, 1: IR present, 2: unknown */
+       u32 has_ir;     /* bit 0: IR receiver present, bit 1: IR transmitter (blaster) present. -1 == unknown */
        u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */
 
        u32 tuner_type;
index aecc946..91b1992 100644 (file)
@@ -144,6 +144,9 @@ enum v4l2_chip_ident {
        V4L2_IDENT_CX25841 = 241,
        V4L2_IDENT_CX25842 = 242,
        V4L2_IDENT_CX25843 = 243,
+
+       /* OmniVision sensors - range 250-299 */
+       V4L2_IDENT_OV7670 = 250,
 };
 
 /* audio ioctls */
@@ -251,4 +254,8 @@ struct v4l2_crystal_freq {
    If the frequency is not supported, then -EINVAL is returned. */
 #define VIDIOC_INT_S_CRYSTAL_FREQ      _IOW ('d', 113, struct v4l2_crystal_freq)
 
+/* Initialize the sensor registors to some sort of reasonable
+   default values. */
+#define VIDIOC_INT_INIT                        _IOW ('d', 114, u32)
+
 #endif /* V4L2_COMMON_H_ */
index 6a11d77..fb96472 100644 (file)
@@ -43,6 +43,7 @@
 
 /*  Video standard functions  */
 extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern char *v4l2_norm_to_name(v4l2_std_id id);
 extern int v4l2_video_std_construct(struct v4l2_standard *vs,
                                    int id, char *name);
 
@@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
  *     This version moves redundant code from video device code to
  *     the common handler
  */
-struct v4l2_tvnorm {
-       char          *name;
-       v4l2_std_id   id;
-
-       void          *priv_data;
-};
 
 struct video_device
 {
@@ -104,9 +99,8 @@ struct video_device
        int debug;      /* Activates debug level*/
 
        /* Video standard vars */
-       int tvnormsize; /* Size of tvnorm array */
-       v4l2_std_id current_norm; /* Current tvnorm */
-       struct v4l2_tvnorm *tvnorms;
+       v4l2_std_id tvnorms;            /* Supported tv norms */
+       v4l2_std_id current_norm;       /* Current tvnorm */
 
        /* callbacks */
        void (*release)(struct video_device *vfd);
@@ -211,7 +205,7 @@ struct video_device
                /* Standard handling
                        G_STD and ENUMSTD are handled by videodev.c
                 */
-       int (*vidioc_s_std)    (struct file *file, void *fh, v4l2_std_id a);
+       int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
        int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
 
                /* Input handling */
index 69374cd..14b72d8 100644 (file)
@@ -282,15 +282,19 @@ extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
 extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
 
 /* ax25_addr.c */
-extern ax25_address null_ax25_address;
-extern char *ax2asc(char *buf, ax25_address *);
-extern void asc2ax(ax25_address *addr, char *callsign);
-extern int  ax25cmp(ax25_address *, ax25_address *);
-extern int  ax25digicmp(ax25_digi *, ax25_digi *);
-extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *);
-extern int  ax25_addr_build(unsigned char *, ax25_address *, ax25_address *, ax25_digi *, int, int);
-extern int  ax25_addr_size(ax25_digi *);
-extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
+extern const ax25_address ax25_bcast;
+extern const ax25_address ax25_defaddr;
+extern const ax25_address null_ax25_address;
+extern char *ax2asc(char *buf, const ax25_address *);
+extern void asc2ax(ax25_address *addr, const char *callsign);
+extern int ax25cmp(const ax25_address *, const ax25_address *);
+extern int ax25digicmp(const ax25_digi *, const ax25_digi *);
+extern const unsigned char *ax25_addr_parse(const unsigned char *, int,
+       ax25_address *, ax25_address *, ax25_digi *, int *, int *);
+extern int  ax25_addr_build(unsigned char *, const ax25_address *,
+       const ax25_address *, const ax25_digi *, int, int);
+extern int  ax25_addr_size(const ax25_digi *);
+extern void ax25_digi_invert(const ax25_digi *, ax25_digi *);
 
 /* ax25_dev.c */
 extern ax25_dev *ax25_dev_list;
index e156e38..62b7e75 100644 (file)
@@ -98,7 +98,7 @@ struct dst_ops
        int                     entry_size;
 
        atomic_t                entries;
-       kmem_cache_t            *kmem_cachep;
+       struct kmem_cache               *kmem_cachep;
 };
 
 #ifdef __KERNEL__
index 617b672..8911927 100644 (file)
@@ -108,8 +108,8 @@ struct ieee80211softmac_assoc_info {
        /* Scan retries remaining */
        int scan_retry;
 
-       struct work_struct work;
-       struct work_struct timeout;
+       struct delayed_work work;
+       struct delayed_work timeout;
 };
 
 struct ieee80211softmac_bss_info {
index a9eb2ea..34cc76e 100644 (file)
@@ -125,7 +125,7 @@ struct inet_hashinfo {
        rwlock_t                        lhash_lock ____cacheline_aligned;
        atomic_t                        lhash_users;
        wait_queue_head_t               lhash_wait;
-       kmem_cache_t                    *bind_bucket_cachep;
+       struct kmem_cache                       *bind_bucket_cachep;
 };
 
 static inline struct inet_ehash_bucket *inet_ehash_bucket(
@@ -136,10 +136,10 @@ static inline struct inet_ehash_bucket *inet_ehash_bucket(
 }
 
 extern struct inet_bind_bucket *
-                   inet_bind_bucket_create(kmem_cache_t *cachep,
+                   inet_bind_bucket_create(struct kmem_cache *cachep,
                                            struct inet_bind_hashbucket *head,
                                            const unsigned short snum);
-extern void inet_bind_bucket_destroy(kmem_cache_t *cachep,
+extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
                                     struct inet_bind_bucket *tb);
 
 static inline int inet_bhashfn(const __u16 lport, const int bhash_size)
index 5f48748..f7be1ac 100644 (file)
@@ -84,7 +84,7 @@ struct inet_timewait_death_row {
 };
 
 extern void inet_twdr_hangman(unsigned long data);
-extern void inet_twdr_twkill_work(void *data);
+extern void inet_twdr_twkill_work(struct work_struct *work);
 extern void inet_twdr_twcal_tick(unsigned long data);
 
 #if (BITS_PER_LONG == 64)
index 83cb9ac..053f02b 100644 (file)
@@ -376,8 +376,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
                         size_t *lenp, loff_t *ppos);
 int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
                                  void __user *oldval, size_t __user *oldlenp,
-                                 void __user *newval, size_t newlen, 
-                                 void **context);
+                                 void __user *newval, size_t newlen);
 #ifdef CONFIG_PROC_FS
 extern int ip_misc_proc_init(void);
 #endif
index 87699cb..8dabdd6 100644 (file)
@@ -126,7 +126,7 @@ extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
 extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
                            unsigned int cmd, unsigned long arg);
 extern void ircomm_tty_set_termios(struct tty_struct *tty, 
-                                  struct termios *old_termios);
+                                  struct ktermios *old_termios);
 extern hashbin_t *ircomm_tty;
 
 #endif
index 492deda..1720539 100644 (file)
@@ -28,6 +28,8 @@
 void irlan_check_command_param(struct irlan_cb *self, char *param, 
                               char *value);
 void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+#ifdef CONFIG_PROC_FS
 void irlan_print_filter(struct seq_file *seq, int filter_type);
+#endif
 
 #endif /* IRLAN_FILTER_H */
index c8aacbd..3725b93 100644 (file)
@@ -160,7 +160,7 @@ struct neigh_table
        atomic_t                entries;
        rwlock_t                lock;
        unsigned long           last_rand;
-       kmem_cache_t            *kmem_cachep;
+       struct kmem_cache               *kmem_cachep;
        struct neigh_statistics *stats;
        struct neighbour        **hash_buckets;
        unsigned int            hash_mask;
@@ -309,6 +309,24 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
        return 0;
 }
 
+static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
+{
+       unsigned seq;
+       int hh_len;
+
+       do {
+               int hh_alen;
+
+               seq = read_seqbegin(&hh->hh_lock);
+               hh_len = hh->hh_len;
+               hh_alen = HH_DATA_ALIGN(hh_len);
+               memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
+       } while (read_seqretry(&hh->hh_lock, seq));
+
+       skb_push(skb, hh_len);
+       return hh->hh_output(skb);
+}
+
 static inline struct neighbour *
 __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
 {
index cef3136..41bcc9e 100644 (file)
@@ -7,7 +7,7 @@
 #include <net/netfilter/nf_conntrack.h>
 
 extern struct list_head nf_conntrack_expect_list;
-extern kmem_cache_t *nf_conntrack_expect_cachep;
+extern struct kmem_cache *nf_conntrack_expect_cachep;
 extern struct file_operations exp_file_ops;
 
 struct nf_conntrack_expect
index e37baaf..7aed02c 100644 (file)
@@ -29,7 +29,7 @@ struct proto;
 struct request_sock_ops {
        int             family;
        int             obj_size;
-       kmem_cache_t    *slab;
+       struct kmem_cache       *slab;
        int             (*rtx_syn_ack)(struct sock *sk,
                                       struct request_sock *req,
                                       struct dst_entry *dst);
@@ -60,7 +60,7 @@ struct request_sock {
 
 static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops)
 {
-       struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC);
+       struct request_sock *req = kmem_cache_alloc(ops->slab, GFP_ATOMIC);
 
        if (req != NULL)
                req->rsk_ops = ops;
index 215461f..c818f87 100644 (file)
@@ -368,7 +368,7 @@ static inline void sctp_sysctl_register(void) { return; }
 static inline void sctp_sysctl_unregister(void) { return; }
 static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context) {
+               void __user *newval, size_t newlen) {
        return -ENOSYS;
 }
 #endif
index f8cbe40..c089f93 100644 (file)
@@ -1030,7 +1030,7 @@ void sctp_inq_init(struct sctp_inq *);
 void sctp_inq_free(struct sctp_inq *);
 void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
 struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
-void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
+void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t);
 
 /* This is the structure we use to hold outbound chunks.  You push
  * chunks in and they automatically pop out the other end as bundled
index fe3a33f..03684e7 100644 (file)
@@ -571,7 +571,7 @@ struct proto {
        int                     *sysctl_rmem;
        int                     max_header;
 
-       kmem_cache_t            *slab;
+       struct kmem_cache               *slab;
        unsigned int            obj_size;
 
        atomic_t                *orphan_count;
@@ -746,6 +746,25 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size)
  */
 #define sock_owned_by_user(sk) ((sk)->sk_lock.owner)
 
+/*
+ * Macro so as to not evaluate some arguments when
+ * lockdep is not enabled.
+ *
+ * Mark both the sk_lock and the sk_lock.slock as a
+ * per-address-family lock class.
+ */
+#define sock_lock_init_class_and_name(sk, sname, skey, name, key)      \
+do {                                                                   \
+       sk->sk_lock.owner = NULL;                                       \
+       init_waitqueue_head(&sk->sk_lock.wq);                           \
+       spin_lock_init(&(sk)->sk_lock.slock);                           \
+       debug_check_no_locks_freed((void *)&(sk)->sk_lock,              \
+                       sizeof((sk)->sk_lock));                         \
+       lockdep_set_class_and_name(&(sk)->sk_lock.slock,                \
+                       (skey), (sname));                               \
+       lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0);     \
+} while (0)
+
 extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass));
 
 static inline void lock_sock(struct sock *sk)
index d7a306e..1e1ee32 100644 (file)
@@ -15,7 +15,7 @@
 #include <net/sock.h>
 
 struct timewait_sock_ops {
-       kmem_cache_t    *twsk_slab;
+       struct kmem_cache       *twsk_slab;
        unsigned int    twsk_obj_size;
        int             (*twsk_unique)(struct sock *sk,
                                       struct sock *sktw, void *twp);
index 15ec19d..e476541 100644 (file)
@@ -392,6 +392,20 @@ extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
 
+/* Audit Information */
+struct xfrm_audit
+{
+       uid_t   loginuid;
+       u32     secid;
+};
+
+#ifdef CONFIG_AUDITSYSCALL
+extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
+                   struct xfrm_policy *xp, struct xfrm_state *x);
+#else
+#define xfrm_audit_log(a,s,t,r,p,x) do { ; } while (0)
+#endif /* CONFIG_AUDITSYSCALL */
+
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
 {
        if (likely(policy != NULL))
@@ -906,7 +920,7 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s
 #endif
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto);
+extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
@@ -959,13 +973,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                                          struct xfrm_selector *sel,
                                          struct xfrm_sec_ctx *ctx, int delete);
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
-void xfrm_policy_flush(u8 type);
+void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
-                                 xfrm_address_t *daddr, xfrm_address_t *saddr, 
+struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
+                                 xfrm_address_t *daddr, xfrm_address_t *saddr,
                                  int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type);
+extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
                          struct flowi *fl, int family, int strict);
index 44b2f82..0c775fc 100644 (file)
@@ -201,9 +201,14 @@ struct domain_device {
         void *lldd_dev;
 };
 
+struct sas_discovery_event {
+       struct work_struct work;
+       struct asd_sas_port *port;
+};
+
 struct sas_discovery {
        spinlock_t disc_event_lock;
-       struct work_struct disc_work[DISC_NUM_EVENTS];
+       struct sas_discovery_event disc_work[DISC_NUM_EVENTS];
        unsigned long    pending;
        u8     fanout_sas_addr[8];
        u8     eeds_a[8];
@@ -249,14 +254,19 @@ struct asd_sas_port {
        void *lldd_port;          /* not touched by the sas class code */
 };
 
+struct asd_sas_event {
+       struct work_struct work;
+       struct asd_sas_phy *phy;
+};
+
 /* The phy pretty much is controlled by the LLDD.
  * The class only reads those fields.
  */
 struct asd_sas_phy {
 /* private: */
        /* protected by ha->event_lock */
-       struct work_struct   port_events[PORT_NUM_EVENTS];
-       struct work_struct   phy_events[PHY_NUM_EVENTS];
+       struct asd_sas_event   port_events[PORT_NUM_EVENTS];
+       struct asd_sas_event   phy_events[PHY_NUM_EVENTS];
 
        unsigned long port_events_pending;
        unsigned long phy_events_pending;
@@ -308,10 +318,15 @@ struct scsi_core {
        int               queue_thread_kill;
 };
 
+struct sas_ha_event {
+       struct work_struct work;
+       struct sas_ha_struct *ha;
+};
+
 struct sas_ha_struct {
 /* private: */
        spinlock_t       event_lock;
-       struct work_struct ha_events[HA_NUM_EVENTS];
+       struct sas_ha_event ha_events[HA_NUM_EVENTS];
        unsigned long    pending;
 
        struct scsi_core core;
@@ -542,7 +557,7 @@ struct sas_task {
 
 static inline struct sas_task *sas_alloc_task(gfp_t flags)
 {
-       extern kmem_cache_t *sas_task_cache;
+       extern struct kmem_cache *sas_task_cache;
        struct sas_task *task = kmem_cache_alloc(sas_task_cache, flags);
 
        if (task) {
@@ -560,7 +575,7 @@ static inline struct sas_task *sas_alloc_task(gfp_t flags)
 static inline void sas_free_task(struct sas_task *task)
 {
        if (task) {
-               extern kmem_cache_t *sas_task_cache;
+               extern struct kmem_cache *sas_task_cache;
                BUG_ON(!list_empty(&task->list));
                kmem_cache_free(sas_task_cache, task);
        }
@@ -631,6 +646,6 @@ void sas_unregister_dev(struct domain_device *);
 
 void sas_init_dev(struct domain_device *);
 
-void sas_task_abort(struct sas_task *task);
+void sas_task_abort(struct work_struct *);
 
 #endif /* _SASLIB_H_ */
index fd35232..798f7c7 100644 (file)
@@ -206,9 +206,9 @@ struct fc_rport {   /* aka fc_starget_attrs */
        u8 flags;
        struct list_head peers;
        struct device dev;
-       struct work_struct dev_loss_work;
+       struct delayed_work dev_loss_work;
        struct work_struct scan_work;
-       struct work_struct fail_io_work;
+       struct delayed_work fail_io_work;
        struct work_struct stgt_delete_work;
        struct work_struct rport_delete_work;
 } __attribute__((aligned(sizeof(unsigned long))));
index 4b95c89..d5c218d 100644 (file)
@@ -176,7 +176,7 @@ struct iscsi_cls_session {
 
        /* recovery fields */
        int recovery_tmo;
-       struct work_struct recovery_work;
+       struct delayed_work recovery_work;
 
        int target_id;
 
index 4c43521..3372039 100644 (file)
@@ -511,7 +511,7 @@ struct snd_ac97 {
 #ifdef CONFIG_SND_AC97_POWER_SAVE
        unsigned int power_up;  /* power states */
        struct workqueue_struct *power_workq;
-       struct work_struct power_work;
+       struct delayed_work power_work;
 #endif
        struct device dev;
 };
index 11702aa..2ee0616 100644 (file)
@@ -182,7 +182,7 @@ struct ak4114 {
        unsigned char rcs0;
        unsigned char rcs1;
        struct workqueue_struct *workqueue;
-       struct work_struct work;
+       struct delayed_work work;
        void *change_callback_private;
        void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
 };
index 3bde0f5..20b9002 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __MBX_FB_H
 #define __MBX_FB_H
 
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
 struct mbxfb_val {
        unsigned int    defval;
        unsigned int    min;
@@ -25,4 +28,32 @@ struct mbxfb_platform_data {
                int (*remove)(struct fb_info *fb);
 };
 
+/* planar */
+#define MBXFB_FMT_YUV12                0
+
+/* packed */
+#define MBXFB_FMT_UY0VY1       1
+#define MBXFB_FMT_VY0UY1       2
+#define MBXFB_FMT_Y0UY1V       3
+#define MBXFB_FMT_Y0VY1U       4
+struct mbxfb_overlaySetup {
+       __u32 enable;
+       __u32 x, y;
+       __u32 width, height;
+       __u32 alpha;
+       __u32 fmt;
+       __u32 mem_offset;
+       __u32 scaled_width;
+       __u32 scaled_height;
+
+       /* Filled by the driver */
+       __u32 U_offset;
+       __u32 V_offset;
+
+       __u16 Y_stride;
+       __u16 UV_stride;
+};
+
+#define MBXFB_IOCX_OVERLAY     _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup)
+
 #endif /* __MBX_FB_H */
index ac02137..94c7d2d 100644 (file)
 #define PM3FBDestReadModeOr                                    0xac98
        #define PM3FBDestReadMode_ReadDisable                   0<<0
        #define PM3FBDestReadMode_ReadEnable                    1<<0
-       #define PM3FBDestReadMode_StripePitch(sp)       (((sp)&0x7)<<2
-       #define PM3FBDestReadMode_StripeHeight(sh)      (((sh)&0x7)<<7
+       #define PM3FBDestReadMode_StripePitch(sp)       (((sp)&0x7)<<2)
+       #define PM3FBDestReadMode_StripeHeight(sh)      (((sh)&0x7)<<7)
        #define PM3FBDestReadMode_Enable0                       1<<8
        #define PM3FBDestReadMode_Enable1                       1<<9
        #define PM3FBDestReadMode_Enable2                       1<<10
        #define PM3FBDestReadMode_Enable3                       1<<11
-       #define PM3FBDestReadMode_Layout0(l)            (((l)&0x3)<<12
-       #define PM3FBDestReadMode_Layout1(l)            (((l)&0x3)<<14
-       #define PM3FBDestReadMode_Layout2(l)            (((l)&0x3)<<16
-       #define PM3FBDestReadMode_Layout3(l)            (((l)&0x3)<<18
+       #define PM3FBDestReadMode_Layout0(l)            (((l)&0x3)<<12)
+       #define PM3FBDestReadMode_Layout1(l)            (((l)&0x3)<<14)
+       #define PM3FBDestReadMode_Layout2(l)            (((l)&0x3)<<16)
+       #define PM3FBDestReadMode_Layout3(l)            (((l)&0x3)<<18)
        #define PM3FBDestReadMode_Origin0                       1<<20
        #define PM3FBDestReadMode_Origin1                       1<<21
        #define PM3FBDestReadMode_Origin2                       1<<22
 #define PM3FBSourceReadModeOr                                  0xaca8
        #define PM3FBSourceReadMode_ReadDisable                 (0<<0)
        #define PM3FBSourceReadMode_ReadEnable                  (1<<0)
-       #define PM3FBSourceReadMode_StripePitch(sp)     (((sp)&0x7)<<2
-       #define PM3FBSourceReadMode_StripeHeight(sh)    (((sh)&0x7)<<7
-       #define PM3FBSourceReadMode_Layout(l)           (((l)&0x3)<<8
+       #define PM3FBSourceReadMode_StripePitch(sp)     (((sp)&0x7)<<2)
+       #define PM3FBSourceReadMode_StripeHeight(sh)    (((sh)&0x7)<<7)
+       #define PM3FBSourceReadMode_Layout(l)           (((l)&0x3)<<8)
        #define PM3FBSourceReadMode_Origin                      1<<10
        #define PM3FBSourceReadMode_Blocking                    1<<11
        #define PM3FBSourceReadMode_UserTexelCoord              1<<13
        #define PM3FBSourceReadMode_WrapXEnable                 1<<14
        #define PM3FBSourceReadMode_WrapYEnable                 1<<15
-       #define PM3FBSourceReadMode_WrapX(w)            (((w)&0xf)<<16
-       #define PM3FBSourceReadMode_WrapY(w)            (((w)&0xf)<<20
+       #define PM3FBSourceReadMode_WrapX(w)            (((w)&0xf)<<16)
+       #define PM3FBSourceReadMode_WrapY(w)            (((w)&0xf)<<20)
        #define PM3FBSourceReadMode_ExternalSourceData          1<<24
 #define PM3FBWriteBufferAddr0                                   0xb000
 #define PM3FBWriteBufferAddr1                                   0xb008
 #define PM3Window                                              0x8980
        #define PM3Window_ForceLBUpdate                         1<<3
        #define PM3Window_LBUpdateSource                        1<<4
-       #define PM3Window_FrameCount(c)                         (((c)&0xff)<<9
+       #define PM3Window_FrameCount(c)                         (((c)&0xff)<<9)
        #define PM3Window_StencilFCP                            1<<17
        #define PM3Window_DepthFCP                              1<<18
        #define PM3Window_OverrideWriteFiltering                1<<19
index 14d4846..9edf103 100644 (file)
@@ -304,6 +304,15 @@ config TASK_XACCT
 
          Say N if unsure.
 
+config TASK_IO_ACCOUNTING
+       bool "Enable per-task storage I/O accounting (EXPERIMENTAL)"
+       depends on TASK_XACCT
+       help
+         Collect information on the number of bytes of storage I/O which this
+         task has caused.
+
+         Say N if unsure.
+
 config SYSCTL
        bool
 
index 633a268..d6c764d 100644 (file)
@@ -15,6 +15,7 @@ clean-files := ../include/linux/compile.h
 
 # dependencies on generated files need to be listed explicitly
 
+$(obj)/main.o: include/linux/compile.h
 $(obj)/version.o: include/linux/compile.h
 
 # compile.h changes depending on hostname, generation number, etc,
index 919a80c..2cfd7cb 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/romfs_fs.h>
 #include <linux/initrd.h>
 #include <linux/sched.h>
+#include <linux/freezer.h>
 
 #include "do_mounts.h"
 
index d28c109..4fa0f79 100644 (file)
@@ -182,6 +182,10 @@ static int __init do_collect(void)
 
 static int __init do_header(void)
 {
+       if (memcmp(collected, "070707", 6)==0) {
+               error("incorrect cpio method used: use -H newc option");
+               return 1;
+       }
        if (memcmp(collected, "070701", 6)) {
                error("no cpio magic");
                return 1;
@@ -522,7 +526,7 @@ static void __init free_initrd(void)
 
 #endif
 
-void __init populate_rootfs(void)
+static int __init populate_rootfs(void)
 {
        char *err = unpack_to_rootfs(__initramfs_start,
                         __initramfs_end - __initramfs_start, 0);
@@ -540,7 +544,7 @@ void __init populate_rootfs(void)
                        unpack_to_rootfs((char *)initrd_start,
                                initrd_end - initrd_start, 0);
                        free_initrd();
-                       return;
+                       return 0;
                }
                printk("it isn't (%s); looks like an initrd\n", err);
                fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
@@ -561,4 +565,6 @@ void __init populate_rootfs(void)
 #endif
        }
 #endif
+       return 0;
 }
+rootfs_initcall(populate_rootfs);
index 36f608a..e3f0bb2 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/percpu.h>
 #include <linux/kmod.h>
 #include <linux/kernel_stat.h>
+#include <linux/start_kernel.h>
 #include <linux/security.h>
 #include <linux/workqueue.h>
 #include <linux/profile.h>
@@ -49,6 +50,9 @@
 #include <linux/buffer_head.h>
 #include <linux/debug_locks.h>
 #include <linux/lockdep.h>
+#include <linux/utsrelease.h>
+#include <linux/pid_namespace.h>
+#include <linux/compile.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
 #error Sorry, your GCC is too old. It builds incorrect kernels.
 #endif
 
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0
+#warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
+#endif
+
 static int init(void *);
 
 extern void init_IRQ(void);
@@ -86,7 +94,6 @@ extern void pidmap_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
-extern void populate_rootfs(void);
 extern void driver_init(void);
 extern void prepare_namespace(void);
 #ifdef CONFIG_ACPI
@@ -475,6 +482,12 @@ void __init __attribute__((weak)) smp_setup_processor_id(void)
 {
 }
 
+static const char linux_banner[] =
+       "Linux version " UTS_RELEASE
+       " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+       " (" LINUX_COMPILER ")"
+       " " UTS_VERSION "\n";
+
 asmlinkage void __init start_kernel(void)
 {
        char * command_line;
@@ -619,8 +632,6 @@ static int __init initcall_debug_setup(char *str)
 }
 __setup("initcall_debug", initcall_debug_setup);
 
-struct task_struct *child_reaper = &init_task;
-
 extern initcall_t __initcall_start[], __initcall_end[];
 
 static void __init do_initcalls(void)
@@ -720,7 +731,7 @@ static int init(void * unused)
         * assumptions about where in the task array this
         * can be found.
         */
-       child_reaper = current;
+       init_pid_ns.child_reaper = current;
 
        cad_pid = task_pid(current);
 
@@ -733,12 +744,6 @@ static int init(void * unused)
 
        cpuset_init_smp();
 
-       /*
-        * Do this before initcalls, because some drivers want to access
-        * firmware files.
-        */
-       populate_rootfs();
-
        do_basic_setup();
 
        /*
index 8f28344..9d96d36 100644 (file)
@@ -33,7 +33,3 @@ struct uts_namespace init_uts_ns = {
        },
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
-
-const char linux_banner[] =
-       "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-       LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
index 4d20cfd..fa18141 100644 (file)
@@ -115,7 +115,6 @@ struct compat_shm_info {
 
 extern int sem_ctls[];
 #define sc_semopm      (sem_ctls[2])
-#define MAXBUF (64*1024)
 
 static inline int compat_ipc_parse_version(int *cmd)
 {
@@ -307,35 +306,30 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 {
-       struct msgbuf __user *p;
        struct compat_msgbuf __user *up = uptr;
        long type;
 
        if (first < 0)
                return -EINVAL;
-       if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+       if (second < 0)
                return -EINVAL;
 
-       p = compat_alloc_user_space(second + sizeof(struct msgbuf));
-       if (get_user(type, &up->mtype) ||
-           put_user(type, &p->mtype) ||
-           copy_in_user(p->mtext, up->mtext, second))
+       if (get_user(type, &up->mtype))
                return -EFAULT;
 
-       return sys_msgsnd(first, p, second, third);
+       return do_msgsnd(first, type, up->mtext, second, third);
 }
 
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                           int version, void __user *uptr)
 {
-       struct msgbuf __user *p;
        struct compat_msgbuf __user *up;
        long type;
        int err;
 
        if (first < 0)
                return -EINVAL;
-       if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+       if (second < 0)
                return -EINVAL;
 
        if (!version) {
@@ -349,14 +343,11 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                uptr = compat_ptr(ipck.msgp);
                msgtyp = ipck.msgtyp;
        }
-       p = compat_alloc_user_space(second + sizeof(struct msgbuf));
-       err = sys_msgrcv(first, p, second, msgtyp, third);
+       up = uptr;
+       err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
        if (err < 0)
                goto out;
-       up = uptr;
-       if (get_user(type, &p->mtype) ||
-           put_user(type, &up->mtype) ||
-           copy_in_user(up->mtext, p->mtext, err))
+       if (put_user(type, &up->mtype))
                err = -EFAULT;
 out:
        return err;
index 7c27400..02717f7 100644 (file)
@@ -90,7 +90,7 @@ static struct super_operations mqueue_super_ops;
 static void remove_notification(struct mqueue_inode_info *info);
 
 static spinlock_t mq_lock;
-static kmem_cache_t *mqueue_inode_cachep;
+static struct kmem_cache *mqueue_inode_cachep;
 static struct vfsmount *mqueue_mnt;
 
 static unsigned int queues_count;
@@ -211,7 +211,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type,
        return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
 }
 
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
 
@@ -224,7 +224,7 @@ static struct inode *mqueue_alloc_inode(struct super_block *sb)
 {
        struct mqueue_inode_info *ei;
 
-       ei = kmem_cache_alloc(mqueue_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(mqueue_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -322,7 +322,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
                                size_t count, loff_t * off)
 {
-       struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+       struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
        char buffer[FILENT_SIZE];
        size_t slen;
        loff_t o;
@@ -354,13 +354,13 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
                return -EFAULT;
 
        *off = o + count;
-       filp->f_dentry->d_inode->i_atime = filp->f_dentry->d_inode->i_ctime = CURRENT_TIME;
+       filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
        return count;
 }
 
 static int mqueue_flush_file(struct file *filp, fl_owner_t id)
 {
-       struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+       struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
 
        spin_lock(&info->lock);
        if (task_tgid(current) == info->notify_owner)
@@ -372,7 +372,7 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id)
 
 static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
 {
-       struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+       struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
        int retval = 0;
 
        poll_wait(filp, &info->wait_q, poll_tab);
@@ -836,7 +836,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
        if (unlikely(!filp))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (unlikely(filp->f_op != &mqueue_file_operations))
                goto out_fput;
        info = MQUEUE_I(inode);
@@ -919,7 +919,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
        if (unlikely(!filp))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (unlikely(filp->f_op != &mqueue_file_operations))
                goto out_fput;
        info = MQUEUE_I(inode);
@@ -1056,7 +1056,7 @@ retry:
        if (!filp)
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (unlikely(filp->f_op != &mqueue_file_operations))
                goto out_fput;
        info = MQUEUE_I(inode);
@@ -1126,7 +1126,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
        if (!filp)
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (unlikely(filp->f_op != &mqueue_file_operations))
                goto out_fput;
        info = MQUEUE_I(inode);
index 1266b1d..a388824 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -626,12 +626,11 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
        return 0;
 }
 
-asmlinkage long
-sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+long do_msgsnd(int msqid, long mtype, void __user *mtext,
+               size_t msgsz, int msgflg)
 {
        struct msg_queue *msq;
        struct msg_msg *msg;
-       long mtype;
        int err;
        struct ipc_namespace *ns;
 
@@ -639,12 +638,10 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
 
        if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
                return -EINVAL;
-       if (get_user(mtype, &msgp->mtype))
-               return -EFAULT;
        if (mtype < 1)
                return -EINVAL;
 
-       msg = load_msg(msgp->mtext, msgsz);
+       msg = load_msg(mtext, msgsz);
        if (IS_ERR(msg))
                return PTR_ERR(msg);
 
@@ -723,6 +720,16 @@ out_free:
        return err;
 }
 
+asmlinkage long
+sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+{
+       long mtype;
+
+       if (get_user(mtype, &msgp->mtype))
+               return -EFAULT;
+       return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
+}
+
 static inline int convert_mode(long *msgtyp, int msgflg)
 {
        /*
@@ -742,8 +749,8 @@ static inline int convert_mode(long *msgtyp, int msgflg)
        return SEARCH_EQUAL;
 }
 
-asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
-                          long msgtyp, int msgflg)
+long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
+               size_t msgsz, long msgtyp, int msgflg)
 {
        struct msg_queue *msq;
        struct msg_msg *msg;
@@ -889,15 +896,30 @@ out_unlock:
                return PTR_ERR(msg);
 
        msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-       if (put_user (msg->m_type, &msgp->mtype) ||
-           store_msg(msgp->mtext, msg, msgsz)) {
+       *pmtype = msg->m_type;
+       if (store_msg(mtext, msg, msgsz))
                msgsz = -EFAULT;
-       }
+
        free_msg(msg);
 
        return msgsz;
 }
 
+asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+                          long msgtyp, int msgflg)
+{
+       long err, mtype;
+
+       err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
+       if (err < 0)
+               goto out;
+
+       if (put_user(mtype, &msgp->mtype))
+               err = -EFAULT;
+out:
+       return err;
+}
+
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 {
index 21b3289..d3e12ef 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1070,14 +1070,13 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
        ipc_rcu_getref(sma);
        sem_unlock(sma);
 
-       new = (struct sem_undo *) kmalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
+       new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
        if (!new) {
                ipc_lock_by_ptr(&sma->sem_perm);
                ipc_rcu_putref(sma);
                sem_unlock(sma);
                return ERR_PTR(-ENOMEM);
        }
-       memset(new, 0, sizeof(struct sem_undo) + sizeof(short)*nsems);
        new->semadj = (short *) &new[1];
        new->semid = semid;
 
index d1198dd..6d16bb6 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -168,7 +168,7 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
 static void shm_open(struct vm_area_struct *shmd)
 {
        shm_inc(shm_file_ns(shmd->vm_file),
-                       shmd->vm_file->f_dentry->d_inode->i_ino);
+                       shmd->vm_file->f_path.dentry->d_inode->i_ino);
 }
 
 /*
@@ -187,7 +187,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
        if (!is_file_hugepages(shp->shm_file))
                shmem_lock(shp->shm_file, 0, shp->mlock_user);
        else
-               user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
+               user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
                                                shp->mlock_user);
        fput (shp->shm_file);
        security_shm_free(shp);
@@ -203,7 +203,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
 static void shm_close (struct vm_area_struct *shmd)
 {
        struct file * file = shmd->vm_file;
-       int id = file->f_dentry->d_inode->i_ino;
+       int id = file->f_path.dentry->d_inode->i_ino;
        struct shmid_kernel *shp;
        struct ipc_namespace *ns;
 
@@ -233,7 +233,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
                vma->vm_ops = &shm_vm_ops;
                if (!(vma->vm_flags & VM_WRITE))
                        vma->vm_flags &= ~VM_MAYWRITE;
-               shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino);
+               shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
        }
 
        return ret;
@@ -330,7 +330,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
        shp->shm_nattch = 0;
        shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
        shp->shm_file = file;
-       file->f_dentry->d_inode->i_ino = shp->id;
+       file->f_path.dentry->d_inode->i_ino = shp->id;
 
        shm_file_ns(file) = get_ipc_ns(ns);
 
@@ -495,7 +495,7 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
                if(!shp)
                        continue;
 
-               inode = shp->shm_file->f_dentry->d_inode;
+               inode = shp->shm_file->f_path.dentry->d_inode;
 
                if (is_file_hugepages(shp->shm_file)) {
                        struct address_space *mapping = inode->i_mapping;
@@ -843,7 +843,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
        }
                
        file = shp->shm_file;
-       size = i_size_read(file->f_dentry->d_inode);
+       size = i_size_read(file->f_path.dentry->d_inode);
        shp->shm_nattch++;
        shm_unlock(shp);
 
@@ -948,7 +948,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
                        (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
 
 
-                       size = vma->vm_file->f_dentry->d_inode->i_size;
+                       size = vma->vm_file->f_path.dentry->d_inode->i_size;
                        do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
                        /*
                         * We discovered the size of the shm segment, so
index cd8bb14..a9b7a22 100644 (file)
@@ -514,6 +514,11 @@ void ipc_rcu_getref(void *ptr)
        container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
 }
 
+static void ipc_do_vfree(struct work_struct *work)
+{
+       vfree(container_of(work, struct ipc_rcu_sched, work));
+}
+
 /**
  * ipc_schedule_free - free ipc + rcu space
  * @head: RCU callback structure for queued work
@@ -528,7 +533,7 @@ static void ipc_schedule_free(struct rcu_head *head)
        struct ipc_rcu_sched *sched =
                        container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
 
-       INIT_WORK(&sched->work, vfree, sched);
+       INIT_WORK(&sched->work, ipc_do_vfree);
        schedule_work(&sched->work);
 }
 
index 248e1c3..4af1580 100644 (file)
@@ -7,7 +7,7 @@ choice
        default HZ_250
        help
         Allows the configuration of the timer frequency. It is customary
-        to have the timer interrupt run at 1000 HZ but 100 HZ may be more
+        to have the timer interrupt run at 1000 Hz but 100 Hz may be more
         beneficial for servers and NUMA systems that do not need to have
         a fast response for user interaction and that may experience bus
         contention and cacheline bounces as a result of timer interrupts.
@@ -19,21 +19,30 @@ choice
        config HZ_100
                bool "100 HZ"
        help
-         100 HZ is a typical choice for servers, SMP and NUMA systems
+         100 Hz is a typical choice for servers, SMP and NUMA systems
          with lots of processors that may show reduced performance if
          too many timer interrupts are occurring.
 
        config HZ_250
                bool "250 HZ"
        help
-        250 HZ is a good compromise choice allowing server performance
+        250 Hz is a good compromise choice allowing server performance
         while also showing good interactive responsiveness even
-        on SMP and NUMA systems.
+        on SMP and NUMA systems. If you are going to be using NTSC video
+        or multimedia, selected 300Hz instead.
+
+       config HZ_300
+               bool "300 HZ"
+       help
+        300 Hz is a good compromise choice allowing server performance
+        while also showing good interactive responsiveness even
+        on SMP and NUMA systems and exactly dividing by both PAL and
+        NTSC frame rates for video and multimedia work.
 
        config HZ_1000
                bool "1000 HZ"
        help
-        1000 HZ is the preferred choice for desktop systems and other
+        1000 Hz is the preferred choice for desktop systems and other
         systems requiring fast interactive responses to events.
 
 endchoice
@@ -42,5 +51,6 @@ config HZ
        int
        default 100 if HZ_100
        default 250 if HZ_250
+       default 300 if HZ_300
        default 1000 if HZ_1000
 
index 0aad5ca..70d0d88 100644 (file)
@@ -89,7 +89,8 @@ struct acct_glbs {
        struct timer_list       timer;
 };
 
-static struct acct_glbs acct_globals __cacheline_aligned = {SPIN_LOCK_UNLOCKED};
+static struct acct_glbs acct_globals __cacheline_aligned =
+       {__SPIN_LOCK_UNLOCKED(acct_globals.lock)};
 
 /*
  * Called whenever the timer says to check the free space.
@@ -117,7 +118,7 @@ static int check_free_space(struct file *file)
        spin_unlock(&acct_globals.lock);
 
        /* May block */
-       if (vfs_statfs(file->f_dentry, &sbuf))
+       if (vfs_statfs(file->f_path.dentry, &sbuf))
                return res;
        suspend = sbuf.f_blocks * SUSPEND;
        resume = sbuf.f_blocks * RESUME;
@@ -193,7 +194,7 @@ static void acct_file_reopen(struct file *file)
                add_timer(&acct_globals.timer);
        }
        if (old_acct) {
-               mnt_unpin(old_acct->f_vfsmnt);
+               mnt_unpin(old_acct->f_path.mnt);
                spin_unlock(&acct_globals.lock);
                do_acct_process(old_acct);
                filp_close(old_acct, NULL);
@@ -211,7 +212,7 @@ static int acct_on(char *name)
        if (IS_ERR(file))
                return PTR_ERR(file);
 
-       if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
+       if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
                filp_close(file, NULL);
                return -EACCES;
        }
@@ -228,11 +229,11 @@ static int acct_on(char *name)
        }
 
        spin_lock(&acct_globals.lock);
-       mnt_pin(file->f_vfsmnt);
+       mnt_pin(file->f_path.mnt);
        acct_file_reopen(file);
        spin_unlock(&acct_globals.lock);
 
-       mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */
+       mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
 
        return 0;
 }
@@ -282,7 +283,7 @@ asmlinkage long sys_acct(const char __user *name)
 void acct_auto_close_mnt(struct vfsmount *m)
 {
        spin_lock(&acct_globals.lock);
-       if (acct_globals.file && acct_globals.file->f_vfsmnt == m)
+       if (acct_globals.file && acct_globals.file->f_path.mnt == m)
                acct_file_reopen(NULL);
        spin_unlock(&acct_globals.lock);
 }
@@ -298,7 +299,7 @@ void acct_auto_close(struct super_block *sb)
 {
        spin_lock(&acct_globals.lock);
        if (acct_globals.file &&
-           acct_globals.file->f_vfsmnt->mnt_sb == sb) {
+           acct_globals.file->f_path.mnt->mnt_sb == sb) {
                acct_file_reopen(NULL);
        }
        spin_unlock(&acct_globals.lock);
@@ -427,6 +428,7 @@ static void do_acct_process(struct file *file)
        u64 elapsed;
        u64 run_time;
        struct timespec uptime;
+       struct tty_struct *tty;
 
        /*
         * First check to see if there is enough free_space to continue
@@ -483,16 +485,9 @@ static void do_acct_process(struct file *file)
        ac.ac_ppid = current->parent->tgid;
 #endif
 
-       mutex_lock(&tty_mutex);
-       /* FIXME: Whoever is responsible for current->signal locking needs
-          to use the same locking all over the kernel and document it */
-       read_lock(&tasklist_lock);
-       ac.ac_tty = current->signal->tty ?
-               old_encode_dev(tty_devnum(current->signal->tty)) : 0;
-       read_unlock(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
-
        spin_lock_irq(&current->sighand->siglock);
+       tty = current->signal->tty;
+       ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0;
        ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
        ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime)));
        ac.ac_flag = pacct->ac_flag;
index 98106f6..d9b690a 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/netlink.h>
 #include <linux/selinux.h>
 #include <linux/inotify.h>
+#include <linux/freezer.h>
 
 #include "audit.h"
 
index 4f40d92..2e896f8 100644 (file)
@@ -636,10 +636,9 @@ static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
        struct audit_rule *rule;
        int i;
 
-       rule = kmalloc(sizeof(*rule), GFP_KERNEL);
+       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
        if (unlikely(!rule))
                return NULL;
-       memset(rule, 0, sizeof(*rule));
 
        rule->flags = krule->flags | krule->listnr;
        rule->action = krule->action;
index ab97e51..2988975 100644 (file)
@@ -731,7 +731,7 @@ static inline void audit_free_context(struct audit_context *context)
                printk(KERN_ERR "audit: freed %d contexts\n", count);
 }
 
-static void audit_log_task_context(struct audit_buffer *ab)
+void audit_log_task_context(struct audit_buffer *ab)
 {
        char *ctx = NULL;
        ssize_t len = 0;
@@ -760,6 +760,8 @@ error_path:
        return;
 }
 
+EXPORT_SYMBOL(audit_log_task_context);
+
 static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
 {
        char name[sizeof(tsk->comm)];
@@ -779,8 +781,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
                        if ((vma->vm_flags & VM_EXECUTABLE) &&
                            vma->vm_file) {
                                audit_log_d_path(ab, "exe=",
-                                                vma->vm_file->f_dentry,
-                                                vma->vm_file->f_vfsmnt);
+                                                vma->vm_file->f_path.dentry,
+                                                vma->vm_file->f_path.mnt);
                                break;
                        }
                        vma = vma->vm_next;
@@ -824,10 +826,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                                 context->return_code);
 
        mutex_lock(&tty_mutex);
+       read_lock(&tasklist_lock);
        if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
                tty = tsk->signal->tty->name;
        else
                tty = "(none)";
+       read_unlock(&tasklist_lock);
        audit_log_format(ab,
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
                  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
@@ -1488,6 +1492,8 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
        return ctx ? ctx->loginuid : -1;
 }
 
+EXPORT_SYMBOL(audit_get_loginuid);
+
 /**
  * __audit_mq_open - record audit data for a POSIX MQ open
  * @oflag: open flag
index f9e3197..8fa1fb2 100644 (file)
@@ -75,7 +75,7 @@ ikconfig_read_current(struct file *file, char __user *buf,
        return count;
 }
 
-static struct file_operations ikconfig_file_ops = {
+static const struct file_operations ikconfig_file_ops = {
        .owner = THIS_MODULE,
        .read = ikconfig_read_current,
 };
index 272254f..9124669 100644 (file)
@@ -270,11 +270,7 @@ int disable_nonboot_cpus(void)
                        goto out;
                }
        }
-       error = set_cpus_allowed(current, cpumask_of_cpu(first_cpu));
-       if (error) {
-               printk(KERN_ERR "Could not run on CPU%d\n", first_cpu);
-               goto out;
-       }
+
        /* We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
         */
index 6313c38..2c3b443 100644 (file)
@@ -413,8 +413,8 @@ static struct file_system_type cpuset_fs_type = {
  *
  *
  * When reading/writing to a file:
- *     - the cpuset to use in file->f_dentry->d_parent->d_fsdata
- *     - the 'cftype' of the file is file->f_dentry->d_fsdata
+ *     - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
+ *     - the 'cftype' of the file is file->f_path.dentry->d_fsdata
  */
 
 struct cftype {
@@ -729,9 +729,11 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
        }
 
        /* Remaining checks don't apply to root cpuset */
-       if ((par = cur->parent) == NULL)
+       if (cur == &top_cpuset)
                return 0;
 
+       par = cur->parent;
+
        /* We must be a subset of our parent cpuset */
        if (!is_cpuset_subset(trial, par))
                return -EACCES;
@@ -1060,10 +1062,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
        cpu_exclusive_changed =
                (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
        mutex_lock(&callback_mutex);
-       if (turning_on)
-               set_bit(bit, &cs->flags);
-       else
-               clear_bit(bit, &cs->flags);
+       cs->flags = trialcs.flags;
        mutex_unlock(&callback_mutex);
 
        if (cpu_exclusive_changed)
@@ -1281,18 +1280,19 @@ typedef enum {
        FILE_TASKLIST,
 } cpuset_filetype_t;
 
-static ssize_t cpuset_common_file_write(struct file *file, const char __user *userbuf,
+static ssize_t cpuset_common_file_write(struct file *file,
+                                       const char __user *userbuf,
                                        size_t nbytes, loff_t *unused_ppos)
 {
-       struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
-       struct cftype *cft = __d_cft(file->f_dentry);
+       struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+       struct cftype *cft = __d_cft(file->f_path.dentry);
        cpuset_filetype_t type = cft->private;
        char *buffer;
        char *pathbuf = NULL;
        int retval = 0;
 
        /* Crude upper limit on largest legitimate cpulist user might write. */
-       if (nbytes > 100 + 6 * NR_CPUS)
+       if (nbytes > 100 + 6 * max(NR_CPUS, MAX_NUMNODES))
                return -E2BIG;
 
        /* +1 for nul-terminator */
@@ -1367,7 +1367,7 @@ static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
                                                size_t nbytes, loff_t *ppos)
 {
        ssize_t retval = 0;
-       struct cftype *cft = __d_cft(file->f_dentry);
+       struct cftype *cft = __d_cft(file->f_path.dentry);
        if (!cft)
                return -ENODEV;
 
@@ -1417,8 +1417,8 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
 static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
                                size_t nbytes, loff_t *ppos)
 {
-       struct cftype *cft = __d_cft(file->f_dentry);
-       struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+       struct cftype *cft = __d_cft(file->f_path.dentry);
+       struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
        cpuset_filetype_t type = cft->private;
        char *page;
        ssize_t retval = 0;
@@ -1476,7 +1476,7 @@ static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbyt
                                                                loff_t *ppos)
 {
        ssize_t retval = 0;
-       struct cftype *cft = __d_cft(file->f_dentry);
+       struct cftype *cft = __d_cft(file->f_path.dentry);
        if (!cft)
                return -ENODEV;
 
@@ -1498,7 +1498,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
        if (err)
                return err;
 
-       cft = __d_cft(file->f_dentry);
+       cft = __d_cft(file->f_path.dentry);
        if (!cft)
                return -ENODEV;
        if (cft->open)
@@ -1511,7 +1511,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
 
 static int cpuset_file_release(struct inode *inode, struct file *file)
 {
-       struct cftype *cft = __d_cft(file->f_dentry);
+       struct cftype *cft = __d_cft(file->f_path.dentry);
        if (cft->release)
                return cft->release(inode, file);
        return 0;
@@ -1532,7 +1532,7 @@ static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry,
        return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
 }
 
-static struct file_operations cpuset_file_operations = {
+static const struct file_operations cpuset_file_operations = {
        .read = cpuset_file_read,
        .write = cpuset_file_write,
        .llseek = generic_file_llseek,
@@ -1700,7 +1700,7 @@ static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
  */
 static int cpuset_tasks_open(struct inode *unused, struct file *file)
 {
-       struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+       struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
        struct ctr_struct *ctr;
        pid_t *pidarray;
        int npids;
@@ -2045,7 +2045,6 @@ out:
        return err;
 }
 
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_MEMORY_HOTPLUG)
 /*
  * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
  * or memory nodes, we need to walk over the cpuset hierarchy,
@@ -2109,9 +2108,7 @@ static void common_cpu_mem_hotplug_unplug(void)
        mutex_unlock(&callback_mutex);
        mutex_unlock(&manage_mutex);
 }
-#endif
 
-#ifdef CONFIG_HOTPLUG_CPU
 /*
  * The top_cpuset tracks what CPUs and Memory Nodes are online,
  * period.  This is necessary in order to make cpusets transparent
@@ -2128,7 +2125,6 @@ static int cpuset_handle_cpuhp(struct notifier_block *nb,
        common_cpu_mem_hotplug_unplug();
        return 0;
 }
-#endif
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
@@ -2610,7 +2606,7 @@ static int cpuset_open(struct inode *inode, struct file *file)
        return single_open(file, proc_cpuset_show, pid);
 }
 
-struct file_operations proc_cpuset_operations = {
+const struct file_operations proc_cpuset_operations = {
        .open           = cpuset_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index 66a0ea4..766d591 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/delayacct.h>
 
 int delayacct_on __read_mostly = 1;    /* Delay accounting turned on/off */
-kmem_cache_t *delayacct_cache;
+struct kmem_cache *delayacct_cache;
 
 static int __init delayacct_setup_disable(char *str)
 {
@@ -41,7 +41,7 @@ void delayacct_init(void)
 
 void __delayacct_tsk_init(struct task_struct *tsk)
 {
-       tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL);
+       tsk->delays = kmem_cache_zalloc(delayacct_cache, GFP_KERNEL);
        if (tsk->delays)
                spin_lock_init(&tsk->delays->lock);
 }
index 2020644..937b13c 100644 (file)
@@ -140,7 +140,7 @@ static int proc_dma_open(struct inode *inode, struct file *file)
        return single_open(file, proc_dma_show, NULL);
 }
 
-static struct file_operations proc_dma_operations = {
+static const struct file_operations proc_dma_operations = {
        .open           = proc_dma_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index 06de6c4..122fadb 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/completion.h>
 #include <linux/personality.h>
 #include <linux/tty.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/key.h>
 #include <linux/security.h>
 #include <linux/cpu.h>
@@ -22,6 +22,7 @@
 #include <linux/file.h>
 #include <linux/binfmts.h>
 #include <linux/nsproxy.h>
+#include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
 #include <linux/mount.h>
@@ -48,7 +49,6 @@
 #include <asm/mmu_context.h>
 
 extern void sem_exit (void);
-extern struct task_struct *child_reaper;
 
 static void exit_mm(struct task_struct * tsk);
 
@@ -189,21 +189,18 @@ repeat:
 int session_of_pgrp(int pgrp)
 {
        struct task_struct *p;
-       int sid = -1;
+       int sid = 0;
 
        read_lock(&tasklist_lock);
-       do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
-               if (p->signal->session > 0) {
-                       sid = p->signal->session;
-                       goto out;
-               }
-       } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
-       p = find_task_by_pid(pgrp);
-       if (p)
-               sid = p->signal->session;
-out:
+
+       p = find_task_by_pid_type(PIDTYPE_PGID, pgrp);
+       if (p == NULL)
+               p = find_task_by_pid(pgrp);
+       if (p != NULL)
+               sid = process_session(p);
+
        read_unlock(&tasklist_lock);
-       
+
        return sid;
 }
 
@@ -225,8 +222,8 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task)
                                || p->exit_state
                                || is_init(p->real_parent))
                        continue;
-               if (process_group(p->real_parent) != pgrp
-                           && p->real_parent->signal->session == p->signal->session) {
+               if (process_group(p->real_parent) != pgrp &&
+                   process_session(p->real_parent) == process_session(p)) {
                        ret = 0;
                        break;
                }
@@ -260,7 +257,8 @@ static int has_stopped_jobs(int pgrp)
 }
 
 /**
- * reparent_to_init - Reparent the calling kernel thread to the init task.
+ * reparent_to_init - Reparent the calling kernel thread to the init task
+ * of the pid space that the thread belongs to.
  *
  * If a kernel thread is launched as a result of a system call, or if
  * it ever exits, it should generally reparent itself to init so that
@@ -278,8 +276,8 @@ static void reparent_to_init(void)
        ptrace_unlink(current);
        /* Reparent to init */
        remove_parent(current);
-       current->parent = child_reaper;
-       current->real_parent = child_reaper;
+       current->parent = child_reaper(current);
+       current->real_parent = child_reaper(current);
        add_parent(current);
 
        /* Set the exit signal to SIGCHLD so we signal init on exit */
@@ -302,9 +300,9 @@ void __set_special_pids(pid_t session, pid_t pgrp)
 {
        struct task_struct *curr = current->group_leader;
 
-       if (curr->signal->session != session) {
+       if (process_session(curr) != session) {
                detach_pid(curr, PIDTYPE_SID);
-               curr->signal->session = session;
+               set_signal_session(curr->signal, session);
                attach_pid(curr, PIDTYPE_SID, session);
        }
        if (process_group(curr) != pgrp) {
@@ -314,7 +312,7 @@ void __set_special_pids(pid_t session, pid_t pgrp)
        }
 }
 
-void set_special_pids(pid_t session, pid_t pgrp)
+static void set_special_pids(pid_t session, pid_t pgrp)
 {
        write_lock_irq(&tasklist_lock);
        __set_special_pids(session, pgrp);
@@ -384,9 +382,7 @@ void daemonize(const char *name, ...)
        exit_mm(current);
 
        set_special_pids(1, 1);
-       mutex_lock(&tty_mutex);
-       current->signal->tty = NULL;
-       mutex_unlock(&tty_mutex);
+       proc_clear_tty(current);
 
        /* Block and flush all signals */
        sigfillset(&blocked);
@@ -429,7 +425,7 @@ static void close_files(struct files_struct * files)
        for (;;) {
                unsigned long set;
                i = j * __NFDBITS;
-               if (i >= fdt->max_fdset || i >= fdt->max_fds)
+               if (i >= fdt->max_fds)
                        break;
                set = fdt->open_fds->fds_bits[j++];
                while (set) {
@@ -470,11 +466,9 @@ void fastcall put_files_struct(struct files_struct *files)
                 * you can free files immediately.
                 */
                fdt = files_fdtable(files);
-               if (fdt == &files->fdtab)
-                       fdt->free_files = files;
-               else
+               if (fdt != &files->fdtab)
                        kmem_cache_free(files_cachep, files);
-               free_fdtable(fdt);
+               call_rcu(&fdt->rcu, free_fdtable_rcu);
        }
 }
 
@@ -649,10 +643,11 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
         * outside, so the child pgrp is now orphaned.
         */
        if ((process_group(p) != process_group(father)) &&
-           (p->signal->session == father->signal->session)) {
+           (process_session(p) == process_session(father))) {
                int pgrp = process_group(p);
 
-               if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) {
+               if (will_become_orphaned_pgrp(pgrp, NULL) &&
+                   has_stopped_jobs(pgrp)) {
                        __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp);
                        __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp);
                }
@@ -663,7 +658,8 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
  * When we die, we re-parent all our children.
  * Try to give them to another thread in our thread
  * group, and if no such member exists, give it to
- * the global child reaper process (ie "init")
+ * the child reaper process (ie "init") in our pid
+ * space.
  */
 static void
 forget_original_parent(struct task_struct *father, struct list_head *to_release)
@@ -674,7 +670,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
        do {
                reaper = next_thread(reaper);
                if (reaper == father) {
-                       reaper = child_reaper;
+                       reaper = child_reaper(father);
                        break;
                }
        } while (reaper->exit_state);
@@ -786,7 +782,7 @@ static void exit_notify(struct task_struct *tsk)
        t = tsk->real_parent;
        
        if ((process_group(t) != process_group(tsk)) &&
-           (t->signal->session == tsk->signal->session) &&
+           (process_session(t) == process_session(tsk)) &&
            will_become_orphaned_pgrp(process_group(tsk), tsk) &&
            has_stopped_jobs(process_group(tsk))) {
                __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk));
@@ -850,9 +846,7 @@ static void exit_notify(struct task_struct *tsk)
 fastcall NORET_TYPE void do_exit(long code)
 {
        struct task_struct *tsk = current;
-       struct taskstats *tidstats;
        int group_dead;
-       unsigned int mycpu;
 
        profile_task_exit(tsk);
 
@@ -862,8 +856,13 @@ fastcall NORET_TYPE void do_exit(long code)
                panic("Aiee, killing interrupt handler!");
        if (unlikely(!tsk->pid))
                panic("Attempted to kill the idle task!");
-       if (unlikely(tsk == child_reaper))
-               panic("Attempted to kill init!");
+       if (unlikely(tsk == child_reaper(tsk))) {
+               if (tsk->nsproxy->pid_ns != &init_pid_ns)
+                       tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper;
+               else
+                       panic("Attempted to kill init!");
+       }
+
 
        if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
                current->ptrace_message = code;
@@ -890,8 +889,6 @@ fastcall NORET_TYPE void do_exit(long code)
                                current->comm, current->pid,
                                preempt_count());
 
-       taskstats_exit_alloc(&tidstats, &mycpu);
-
        acct_update_integrals(tsk);
        if (tsk->mm) {
                update_hiwater_rss(tsk->mm);
@@ -911,8 +908,8 @@ fastcall NORET_TYPE void do_exit(long code)
 #endif
        if (unlikely(tsk->audit_context))
                audit_free(tsk);
-       taskstats_exit_send(tsk, tidstats, group_dead, mycpu);
-       taskstats_exit_free(tidstats);
+
+       taskstats_exit(tsk, group_dead);
 
        exit_mm(tsk);
 
index 8cdd3e7..d16c566 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/completion.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/personality.h>
 #include <linux/mempolicy.h>
 #include <linux/sem.h>
@@ -36,6 +36,7 @@
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
 #include <linux/futex.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/rcupdate.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
@@ -82,26 +83,26 @@ int nr_processes(void)
 #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
 # define alloc_task_struct()   kmem_cache_alloc(task_struct_cachep, GFP_KERNEL)
 # define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk))
-static kmem_cache_t *task_struct_cachep;
+static struct kmem_cache *task_struct_cachep;
 #endif
 
 /* SLAB cache for signal_struct structures (tsk->signal) */
-static kmem_cache_t *signal_cachep;
+static struct kmem_cache *signal_cachep;
 
 /* SLAB cache for sighand_struct structures (tsk->sighand) */
-kmem_cache_t *sighand_cachep;
+struct kmem_cache *sighand_cachep;
 
 /* SLAB cache for files_struct structures (tsk->files) */
-kmem_cache_t *files_cachep;
+struct kmem_cache *files_cachep;
 
 /* SLAB cache for fs_struct structures (tsk->fs) */
-kmem_cache_t *fs_cachep;
+struct kmem_cache *fs_cachep;
 
 /* SLAB cache for vm_area_struct structures */
-kmem_cache_t *vm_area_cachep;
+struct kmem_cache *vm_area_cachep;
 
 /* SLAB cache for mm_struct structures (tsk->mm) */
-static kmem_cache_t *mm_cachep;
+static struct kmem_cache *mm_cachep;
 
 void free_task(struct task_struct *tsk)
 {
@@ -237,7 +238,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                                goto fail_nomem;
                        charge = len;
                }
-               tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+               tmp = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
                if (!tmp)
                        goto fail_nomem;
                *tmp = *mpnt;
@@ -252,7 +253,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                anon_vma_link(tmp);
                file = tmp->vm_file;
                if (file) {
-                       struct inode *inode = file->f_dentry->d_inode;
+                       struct inode *inode = file->f_path.dentry->d_inode;
                        get_file(file);
                        if (tmp->vm_flags & VM_DENYWRITE)
                                atomic_dec(&inode->i_writecount);
@@ -319,7 +320,7 @@ static inline void mm_free_pgd(struct mm_struct * mm)
 
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
 
-#define allocate_mm()  (kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
+#define allocate_mm()  (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
 #define free_mm(mm)    (kmem_cache_free(mm_cachep, (mm)))
 
 #include <linux/init_task.h>
@@ -448,7 +449,16 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
                tsk->vfork_done = NULL;
                complete(vfork_done);
        }
-       if (tsk->clear_child_tid && atomic_read(&mm->mm_users) > 1) {
+
+       /*
+        * If we're exiting normally, clear a user-space tid field if
+        * requested.  We leave this alone when dying by signal, to leave
+        * the value intact in a core dump, and to save the unnecessary
+        * trouble otherwise.  Userland only wants this done for a sys_exit.
+        */
+       if (tsk->clear_child_tid
+           && !(tsk->flags & PF_SIGNALED)
+           && atomic_read(&mm->mm_users) > 1) {
                u32 __user * tidptr = tsk->clear_child_tid;
                tsk->clear_child_tid = NULL;
 
@@ -479,6 +489,10 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
 
        memcpy(mm, oldmm, sizeof(*mm));
 
+       /* Initializing for Swap token stuff */
+       mm->token_priority = 0;
+       mm->last_interval = 0;
+
        if (!mm_init(mm))
                goto fail_nomem;
 
@@ -542,6 +556,10 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
                goto fail_nomem;
 
 good_mm:
+       /* Initializing for Swap token stuff */
+       mm->token_priority = 0;
+       mm->last_interval = 0;
+
        tsk->mm = mm;
        tsk->active_mm = mm;
        return 0;
@@ -596,7 +614,7 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
 
 static int count_open_files(struct fdtable *fdt)
 {
-       int size = fdt->max_fdset;
+       int size = fdt->max_fds;
        int i;
 
        /* Find the last open fd */
@@ -613,7 +631,7 @@ static struct files_struct *alloc_files(void)
        struct files_struct *newf;
        struct fdtable *fdt;
 
-       newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
+       newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
        if (!newf)
                goto out;
 
@@ -623,12 +641,10 @@ static struct files_struct *alloc_files(void)
        newf->next_fd = 0;
        fdt = &newf->fdtab;
        fdt->max_fds = NR_OPEN_DEFAULT;
-       fdt->max_fdset = EMBEDDED_FD_SET_SIZE;
        fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
        fdt->open_fds = (fd_set *)&newf->open_fds_init;
        fdt->fd = &newf->fd_array[0];
        INIT_RCU_HEAD(&fdt->rcu);
-       fdt->free_files = NULL;
        fdt->next = NULL;
        rcu_assign_pointer(newf->fdt, fdt);
 out:
@@ -644,7 +660,7 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
 {
        struct files_struct *newf;
        struct file **old_fds, **new_fds;
-       int open_files, size, i, expand;
+       int open_files, size, i;
        struct fdtable *old_fdt, *new_fdt;
 
        *errorp = -ENOMEM;
@@ -655,25 +671,14 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        spin_lock(&oldf->file_lock);
        old_fdt = files_fdtable(oldf);
        new_fdt = files_fdtable(newf);
-       size = old_fdt->max_fdset;
        open_files = count_open_files(old_fdt);
-       expand = 0;
 
        /*
-        * Check whether we need to allocate a larger fd array or fd set.
-        * Note: we're not a clone task, so the open count won't  change.
+        * Check whether we need to allocate a larger fd array and fd set.
+        * Note: we're not a clone task, so the open count won't change.
         */
-       if (open_files > new_fdt->max_fdset) {
-               new_fdt->max_fdset = 0;
-               expand = 1;
-       }
        if (open_files > new_fdt->max_fds) {
                new_fdt->max_fds = 0;
-               expand = 1;
-       }
-
-       /* if the old fdset gets grown now, we'll only copy up to "size" fds */
-       if (expand) {
                spin_unlock(&oldf->file_lock);
                spin_lock(&newf->file_lock);
                *errorp = expand_files(newf, open_files-1);
@@ -693,8 +698,10 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        old_fds = old_fdt->fd;
        new_fds = new_fdt->fd;
 
-       memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
-       memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
+       memcpy(new_fdt->open_fds->fds_bits,
+               old_fdt->open_fds->fds_bits, open_files/8);
+       memcpy(new_fdt->close_on_exec->fds_bits,
+               old_fdt->close_on_exec->fds_bits, open_files/8);
 
        for (i = open_files; i != 0; i--) {
                struct file *f = *old_fds++;
@@ -719,22 +726,19 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        /* This is long word aligned thus could use a optimized version */ 
        memset(new_fds, 0, size); 
 
-       if (new_fdt->max_fdset > open_files) {
-               int left = (new_fdt->max_fdset-open_files)/8;
+       if (new_fdt->max_fds > open_files) {
+               int left = (new_fdt->max_fds-open_files)/8;
                int start = open_files / (8 * sizeof(unsigned long));
 
                memset(&new_fdt->open_fds->fds_bits[start], 0, left);
                memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
        }
 
-out:
        return newf;
 
 out_release:
-       free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
-       free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
-       free_fd_array(new_fdt->fd, new_fdt->max_fds);
        kmem_cache_free(files_cachep, newf);
+out:
        return NULL;
 }
 
@@ -830,7 +834,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
        if (clone_flags & CLONE_THREAD) {
                atomic_inc(&current->signal->count);
                atomic_inc(&current->signal->live);
-               taskstats_tgid_alloc(current);
                return 0;
        }
        sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
@@ -1039,6 +1042,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        p->wchar = 0;           /* I/O counter: bytes written */
        p->syscr = 0;           /* I/O counter: read syscalls */
        p->syscw = 0;           /* I/O counter: write syscalls */
+       task_io_accounting_init(p);
        acct_clear_integrals(p);
 
        p->it_virt_expires = cputime_zero;
@@ -1243,9 +1247,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                if (thread_group_leader(p)) {
                        p->signal->tty = current->signal->tty;
                        p->signal->pgrp = process_group(current);
-                       p->signal->session = current->signal->session;
+                       set_signal_session(p->signal, process_session(current));
                        attach_pid(p, PIDTYPE_PGID, process_group(p));
-                       attach_pid(p, PIDTYPE_SID, p->signal->session);
+                       attach_pid(p, PIDTYPE_SID, process_session(p));
 
                        list_add_tail_rcu(&p->tasks, &init_task.tasks);
                        __get_cpu_var(process_counts)++;
@@ -1303,7 +1307,7 @@ fork_out:
        return ERR_PTR(retval);
 }
 
-struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
+noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
        return regs;
@@ -1413,7 +1417,7 @@ long do_fork(unsigned long clone_flags,
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
 
-static void sighand_ctor(void *data, kmem_cache_t *cachep, unsigned long flags)
+static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long flags)
 {
        struct sighand_struct *sighand = data;
 
@@ -1509,17 +1513,18 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
 }
 
 /*
- * Unshare the namespace structure if it is being shared
+ * Unshare the mnt_namespace structure if it is being shared
  */
-static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
+static int unshare_mnt_namespace(unsigned long unshare_flags,
+               struct mnt_namespace **new_nsp, struct fs_struct *new_fs)
 {
-       struct namespace *ns = current->nsproxy->namespace;
+       struct mnt_namespace *ns = current->nsproxy->mnt_ns;
 
        if ((unshare_flags & CLONE_NEWNS) && ns) {
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               *new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs);
+               *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs);
                if (!*new_nsp)
                        return -ENOMEM;
        }
@@ -1528,15 +1533,13 @@ static int unshare_namespace(unsigned long unshare_flags, struct namespace **new
 }
 
 /*
- * Unsharing of sighand for tasks created with CLONE_SIGHAND is not
- * supported yet
+ * Unsharing of sighand is not supported yet
  */
 static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
 {
        struct sighand_struct *sigh = current->sighand;
 
-       if ((unshare_flags & CLONE_SIGHAND) &&
-           (sigh && atomic_read(&sigh->count) > 1))
+       if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1)
                return -EINVAL;
        else
                return 0;
@@ -1609,8 +1612,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
 {
        int err = 0;
        struct fs_struct *fs, *new_fs = NULL;
-       struct namespace *ns, *new_ns = NULL;
-       struct sighand_struct *sigh, *new_sigh = NULL;
+       struct mnt_namespace *ns, *new_ns = NULL;
+       struct sighand_struct *new_sigh = NULL;
        struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
        struct files_struct *fd, *new_fd = NULL;
        struct sem_undo_list *new_ulist = NULL;
@@ -1631,7 +1634,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                goto bad_unshare_out;
        if ((err = unshare_fs(unshare_flags, &new_fs)))
                goto bad_unshare_cleanup_thread;
-       if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs)))
+       if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs)))
                goto bad_unshare_cleanup_fs;
        if ((err = unshare_sighand(unshare_flags, &new_sigh)))
                goto bad_unshare_cleanup_ns;
@@ -1655,7 +1658,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                }
        }
 
-       if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist ||
+       if (new_fs || new_ns || new_mm || new_fd || new_ulist ||
                                new_uts || new_ipc) {
 
                task_lock(current);
@@ -1672,17 +1675,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                }
 
                if (new_ns) {
-                       ns = current->nsproxy->namespace;
-                       current->nsproxy->namespace = new_ns;
+                       ns = current->nsproxy->mnt_ns;
+                       current->nsproxy->mnt_ns = new_ns;
                        new_ns = ns;
                }
 
-               if (new_sigh) {
-                       sigh = current->sighand;
-                       rcu_assign_pointer(current->sighand, new_sigh);
-                       new_sigh = sigh;
-               }
-
                if (new_mm) {
                        mm = current->mm;
                        active_mm = current->active_mm;
@@ -1740,7 +1737,7 @@ bad_unshare_cleanup_sigh:
 
 bad_unshare_cleanup_ns:
        if (new_ns)
-               put_namespace(new_ns);
+               put_mnt_ns(new_ns);
 
 bad_unshare_cleanup_fs:
        if (new_fs)
index 93ef30b..5a737de 100644 (file)
@@ -166,7 +166,7 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
 /*
  * Get parameters which are the keys for a futex.
  *
- * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode,
+ * For shared mappings, it's (page->index, vma->vm_file->f_path.dentry->d_inode,
  * offset_within_page).  For private mappings, it's (uaddr, current->mm).
  * We can usually work out the index without swapping in the page.
  *
@@ -223,7 +223,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
        /*
         * Linear file mappings are also simple.
         */
-       key->shared.inode = vma->vm_file->f_dentry->d_inode;
+       key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
        key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
        if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
                key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
@@ -282,9 +282,9 @@ static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
 {
        int ret;
 
-       inc_preempt_count();
+       pagefault_disable();
        ret = __copy_from_user_inatomic(dest, from, sizeof(u32));
-       dec_preempt_count();
+       pagefault_enable();
 
        return ret ? -EFAULT : 0;
 }
@@ -324,12 +324,11 @@ static int refill_pi_state_cache(void)
        if (likely(current->pi_state_cache))
                return 0;
 
-       pi_state = kmalloc(sizeof(*pi_state), GFP_KERNEL);
+       pi_state = kzalloc(sizeof(*pi_state), GFP_KERNEL);
 
        if (!pi_state)
                return -ENOMEM;
 
-       memset(pi_state, 0, sizeof(*pi_state));
        INIT_LIST_HEAD(&pi_state->list);
        /* pi_mutex gets initialized later */
        pi_state->owner = NULL;
@@ -553,7 +552,7 @@ static void wake_futex(struct futex_q *q)
         * at the end of wake_up_all() does not prevent this store from
         * moving.
         */
-       wmb();
+       smp_wmb();
        q->lock_ptr = NULL;
 }
 
@@ -585,9 +584,9 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
        if (!(uval & FUTEX_OWNER_DIED)) {
                newval = FUTEX_WAITERS | new_owner->pid;
 
-               inc_preempt_count();
+               pagefault_disable();
                curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-               dec_preempt_count();
+               pagefault_enable();
                if (curval == -EFAULT)
                        return -EFAULT;
                if (curval != uval)
@@ -618,9 +617,9 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
         * There is no waiter, so we unlock the futex. The owner died
         * bit has not to be preserved here. We are the owner:
         */
-       inc_preempt_count();
+       pagefault_disable();
        oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0);
-       dec_preempt_count();
+       pagefault_enable();
 
        if (oldval == -EFAULT)
                return oldval;
@@ -1158,9 +1157,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
         */
        newval = current->pid;
 
-       inc_preempt_count();
+       pagefault_disable();
        curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval);
-       dec_preempt_count();
+       pagefault_enable();
 
        if (unlikely(curval == -EFAULT))
                goto uaddr_faulted;
@@ -1183,9 +1182,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
        uval = curval;
        newval = uval | FUTEX_WAITERS;
 
-       inc_preempt_count();
+       pagefault_disable();
        curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-       dec_preempt_count();
+       pagefault_enable();
 
        if (unlikely(curval == -EFAULT))
                goto uaddr_faulted;
@@ -1215,10 +1214,10 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
                        newval = current->pid |
                                FUTEX_OWNER_DIED | FUTEX_WAITERS;
 
-                       inc_preempt_count();
+                       pagefault_disable();
                        curval = futex_atomic_cmpxchg_inatomic(uaddr,
                                                               uval, newval);
-                       dec_preempt_count();
+                       pagefault_enable();
 
                        if (unlikely(curval == -EFAULT))
                                goto uaddr_faulted;
@@ -1390,9 +1389,9 @@ retry_locked:
         * anyone else up:
         */
        if (!(uval & FUTEX_OWNER_DIED)) {
-               inc_preempt_count();
+               pagefault_disable();
                uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
-               dec_preempt_count();
+               pagefault_enable();
        }
 
        if (unlikely(uval == -EFAULT))
@@ -1493,7 +1492,7 @@ static unsigned int futex_poll(struct file *filp,
        return ret;
 }
 
-static struct file_operations futex_fops = {
+static const struct file_operations futex_fops = {
        .release        = futex_close,
        .poll           = futex_poll,
 };
@@ -1529,9 +1528,9 @@ static int futex_fd(u32 __user *uaddr, int signal)
                goto out;
        }
        filp->f_op = &futex_fops;
-       filp->f_vfsmnt = mntget(futex_mnt);
-       filp->f_dentry = dget(futex_mnt->mnt_root);
-       filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+       filp->f_path.mnt = mntget(futex_mnt);
+       filp->f_path.dentry = dget(futex_mnt->mnt_root);
+       filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
 
        if (signal) {
                err = __f_setown(filp, task_pid(current), PIDTYPE_PID, 1);
@@ -1858,10 +1857,16 @@ static struct file_system_type futex_fs_type = {
 
 static int __init init(void)
 {
-       unsigned int i;
+       int i = register_filesystem(&futex_fs_type);
+
+       if (i)
+               return i;
 
-       register_filesystem(&futex_fs_type);
        futex_mnt = kern_mount(&futex_fs_type);
+       if (IS_ERR(futex_mnt)) {
+               unregister_filesystem(&futex_fs_type);
+               return PTR_ERR(futex_mnt);
+       }
 
        for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
                INIT_LIST_HEAD(&futex_queues[i].chain);
index a681912..aff1f0f 100644 (file)
@@ -54,7 +54,7 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
                .chip = &no_irq_chip,
                .handle_irq = handle_bad_irq,
                .depth = 1,
-               .lock = SPIN_LOCK_UNLOCKED,
+               .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
 #ifdef CONFIG_SMP
                .affinity = CPU_MASK_ALL
 #endif
index 9a35266..61f5c71 100644 (file)
@@ -54,7 +54,8 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
        unsigned int irq = (int)(long)data, full_count = count, err;
        cpumask_t new_value, tmp;
 
-       if (!irq_desc[irq].chip->set_affinity || no_irq_affinity)
+       if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
+                               CHECK_IRQ_PER_CPU(irq_desc[irq].status))
                return -EIO;
 
        err = cpumask_parse_user(buffer, count, new_value);
index eeac3e3..6f294ff 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/proc_fs.h>
 #include <linux/sched.h>       /* for cond_resched */
 #include <linux/mm.h>
+#include <linux/ctype.h>
 
 #include <asm/sections.h>
 
 #endif
 
 /* These will be re-linked against their real values during the second link stage */
-extern unsigned long kallsyms_addresses[] __attribute__((weak));
-extern unsigned long kallsyms_num_syms __attribute__((weak,section("data")));
-extern u8 kallsyms_names[] __attribute__((weak));
+extern const unsigned long kallsyms_addresses[] __attribute__((weak));
+extern const unsigned long kallsyms_num_syms __attribute__((weak));
+extern const u8 kallsyms_names[] __attribute__((weak));
 
-extern u8 kallsyms_token_table[] __attribute__((weak));
-extern u16 kallsyms_token_index[] __attribute__((weak));
+extern const u8 kallsyms_token_table[] __attribute__((weak));
+extern const u16 kallsyms_token_index[] __attribute__((weak));
 
-extern unsigned long kallsyms_markers[] __attribute__((weak));
+extern const unsigned long kallsyms_markers[] __attribute__((weak));
 
 static inline int is_kernel_inittext(unsigned long addr)
 {
@@ -83,7 +84,7 @@ static int is_ksym_addr(unsigned long addr)
 static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
 {
        int len, skipped_first = 0;
-       u8 *tptr, *data;
+       const u8 *tptr, *data;
 
        /* get the compressed symbol length from the first symbol byte */
        data = &kallsyms_names[off];
@@ -131,7 +132,7 @@ static char kallsyms_get_symbol_type(unsigned int off)
  * kallsyms array */
 static unsigned int get_symbol_offset(unsigned long pos)
 {
-       u8 *name;
+       const u8 *name;
        int i;
 
        /* use the closest marker we have. We have markers every 256 positions,
@@ -301,13 +302,6 @@ struct kallsym_iter
        char name[KSYM_NAME_LEN+1];
 };
 
-/* Only label it "global" if it is exported. */
-static void upcase_if_global(struct kallsym_iter *iter)
-{
-       if (is_exported(iter->name, iter->owner))
-               iter->type += 'A' - 'a';
-}
-
 static int get_ksymbol_mod(struct kallsym_iter *iter)
 {
        iter->owner = module_get_kallsym(iter->pos - kallsyms_num_syms,
@@ -316,7 +310,10 @@ static int get_ksymbol_mod(struct kallsym_iter *iter)
        if (iter->owner == NULL)
                return 0;
 
-       upcase_if_global(iter);
+       /* Label it "global" if it is exported, "local" if not exported. */
+       iter->type = is_exported(iter->name, iter->owner)
+               ? toupper(iter->type) : tolower(iter->type);
+
        return 1;
 }
 
@@ -401,7 +398,7 @@ static int s_show(struct seq_file *m, void *p)
        return 0;
 }
 
-static struct seq_operations kallsyms_op = {
+static const struct seq_operations kallsyms_op = {
        .start = s_start,
        .next = s_next,
        .stop = s_stop,
@@ -436,7 +433,7 @@ static int kallsyms_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-static struct file_operations kallsyms_operations = {
+static const struct file_operations kallsyms_operations = {
        .open = kallsyms_open,
        .read = seq_read,
        .llseek = seq_lseek,
index fcdd5d2..2a59c8a 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/syscalls.h>
 #include <linux/ioport.h>
 #include <linux/hardirq.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -108,11 +110,10 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
 
        /* Allocate a controlling structure */
        result = -ENOMEM;
-       image = kmalloc(sizeof(*image), GFP_KERNEL);
+       image = kzalloc(sizeof(*image), GFP_KERNEL);
        if (!image)
                goto out;
 
-       memset(image, 0, sizeof(*image));
        image->head = 0;
        image->entry = &image->head;
        image->last_entry = &image->head;
@@ -851,6 +852,7 @@ static int kimage_load_crash_segment(struct kimage *image,
                        memset(ptr + uchunk, 0, mchunk - uchunk);
                }
                result = copy_from_user(ptr, buf, uchunk);
+               kexec_flush_icache_page(page);
                kunmap(page);
                if (result) {
                        result = (result < 0) ? result : -EIO;
@@ -1067,6 +1069,60 @@ void crash_kexec(struct pt_regs *regs)
        }
 }
 
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+                           size_t data_len)
+{
+       struct elf_note note;
+
+       note.n_namesz = strlen(name) + 1;
+       note.n_descsz = data_len;
+       note.n_type   = type;
+       memcpy(buf, &note, sizeof(note));
+       buf += (sizeof(note) + 3)/4;
+       memcpy(buf, name, note.n_namesz);
+       buf += (note.n_namesz + 3)/4;
+       memcpy(buf, data, note.n_descsz);
+       buf += (note.n_descsz + 3)/4;
+
+       return buf;
+}
+
+static void final_note(u32 *buf)
+{
+       struct elf_note note;
+
+       note.n_namesz = 0;
+       note.n_descsz = 0;
+       note.n_type   = 0;
+       memcpy(buf, &note, sizeof(note));
+}
+
+void crash_save_cpu(struct pt_regs *regs, int cpu)
+{
+       struct elf_prstatus prstatus;
+       u32 *buf;
+
+       if ((cpu < 0) || (cpu >= NR_CPUS))
+               return;
+
+       /* Using ELF notes here is opportunistic.
+        * I need a well defined structure format
+        * 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, so there is no need to invent something new.
+        */
+       buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+       if (!buf)
+               return;
+       memset(&prstatus, 0, sizeof(prstatus));
+       prstatus.pr_pid = current->pid;
+       elf_core_copy_regs(&prstatus.pr_reg, regs);
+       buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+                               sizeof(prstatus));
+       final_note(buf);
+}
+
 static int __init crash_notes_memory_init(void)
 {
        /* Allocate memory for saving cpu registers. */
index 2b76dee..3a7379a 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/kmod.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/workqueue.h>
@@ -114,6 +114,7 @@ EXPORT_SYMBOL(request_module);
 #endif /* CONFIG_KMOD */
 
 struct subprocess_info {
+       struct work_struct work;
        struct completion *complete;
        char *path;
        char **argv;
@@ -221,9 +222,10 @@ static int wait_for_helper(void *data)
 }
 
 /* This is run by khelper thread  */
-static void __call_usermodehelper(void *data)
+static void __call_usermodehelper(struct work_struct *work)
 {
-       struct subprocess_info *sub_info = data;
+       struct subprocess_info *sub_info =
+               container_of(work, struct subprocess_info, work);
        pid_t pid;
        int wait = sub_info->wait;
 
@@ -264,6 +266,8 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct subprocess_info sub_info = {
+               .work           = __WORK_INITIALIZER(sub_info.work,
+                                                    __call_usermodehelper),
                .complete       = &done,
                .path           = path,
                .argv           = argv,
@@ -272,7 +276,6 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
                .wait           = wait,
                .retval         = 0,
        };
-       DECLARE_WORK(work, __call_usermodehelper, &sub_info);
 
        if (!khelper_wq)
                return -EBUSY;
@@ -280,7 +283,7 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
        if (path[0] == '\0')
                return 0;
 
-       queue_work(khelper_wq, &work);
+       queue_work(khelper_wq, &sub_info.work);
        wait_for_completion(&done);
        return sub_info.retval;
 }
@@ -291,6 +294,8 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
 {
        DECLARE_COMPLETION(done);
        struct subprocess_info sub_info = {
+               .work           = __WORK_INITIALIZER(sub_info.work,
+                                                    __call_usermodehelper),
                .complete       = &done,
                .path           = path,
                .argv           = argv,
@@ -298,7 +303,6 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
                .retval         = 0,
        };
        struct file *f;
-       DECLARE_WORK(work, __call_usermodehelper, &sub_info);
 
        if (!khelper_wq)
                return -EBUSY;
@@ -318,7 +322,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
        }
        sub_info.stdin = f;
 
-       queue_work(khelper_wq, &work);
+       queue_work(khelper_wq, &sub_info.work);
        wait_for_completion(&done);
        return sub_info.retval;
 }
index 610c837..17ec4af 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/kallsyms.h>
+#include <linux/freezer.h>
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
@@ -83,9 +84,36 @@ struct kprobe_insn_page {
        kprobe_opcode_t *insns;         /* Page of instruction slots */
        char slot_used[INSNS_PER_PAGE];
        int nused;
+       int ngarbage;
 };
 
 static struct hlist_head kprobe_insn_pages;
+static int kprobe_garbage_slots;
+static int collect_garbage_slots(void);
+
+static int __kprobes check_safety(void)
+{
+       int ret = 0;
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_PM)
+       ret = freeze_processes();
+       if (ret == 0) {
+               struct task_struct *p, *q;
+               do_each_thread(p, q) {
+                       if (p != current && p->state == TASK_RUNNING &&
+                           p->pid != 0) {
+                               printk("Check failed: %s is running\n",p->comm);
+                               ret = -1;
+                               goto loop_end;
+                       }
+               } while_each_thread(p, q);
+       }
+loop_end:
+       thaw_processes();
+#else
+       synchronize_sched();
+#endif
+       return ret;
+}
 
 /**
  * get_insn_slot() - Find a slot on an executable page for an instruction.
@@ -96,6 +124,7 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
 
+      retry:
        hlist_for_each(pos, &kprobe_insn_pages) {
                kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
                if (kip->nused < INSNS_PER_PAGE) {
@@ -112,7 +141,11 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
                }
        }
 
-       /* All out of space.  Need to allocate a new page. Use slot 0.*/
+       /* If there are any garbage slots, collect it and try again. */
+       if (kprobe_garbage_slots && collect_garbage_slots() == 0) {
+               goto retry;
+       }
+       /* All out of space.  Need to allocate a new page. Use slot 0. */
        kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
        if (!kip) {
                return NULL;
@@ -133,10 +166,62 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
        memset(kip->slot_used, 0, INSNS_PER_PAGE);
        kip->slot_used[0] = 1;
        kip->nused = 1;
+       kip->ngarbage = 0;
        return kip->insns;
 }
 
-void __kprobes free_insn_slot(kprobe_opcode_t *slot)
+/* Return 1 if all garbages are collected, otherwise 0. */
+static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
+{
+       kip->slot_used[idx] = 0;
+       kip->nused--;
+       if (kip->nused == 0) {
+               /*
+                * Page is no longer in use.  Free it unless
+                * it's the last one.  We keep the last one
+                * so as not to have to set it up again the
+                * next time somebody inserts a probe.
+                */
+               hlist_del(&kip->hlist);
+               if (hlist_empty(&kprobe_insn_pages)) {
+                       INIT_HLIST_NODE(&kip->hlist);
+                       hlist_add_head(&kip->hlist,
+                                      &kprobe_insn_pages);
+               } else {
+                       module_free(NULL, kip->insns);
+                       kfree(kip);
+               }
+               return 1;
+       }
+       return 0;
+}
+
+static int __kprobes collect_garbage_slots(void)
+{
+       struct kprobe_insn_page *kip;
+       struct hlist_node *pos, *next;
+
+       /* Ensure no-one is preepmted on the garbages */
+       if (check_safety() != 0)
+               return -EAGAIN;
+
+       hlist_for_each_safe(pos, next, &kprobe_insn_pages) {
+               int i;
+               kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
+               if (kip->ngarbage == 0)
+                       continue;
+               kip->ngarbage = 0;      /* we will collect all garbages */
+               for (i = 0; i < INSNS_PER_PAGE; i++) {
+                       if (kip->slot_used[i] == -1 &&
+                           collect_one_slot(kip, i))
+                               break;
+               }
+       }
+       kprobe_garbage_slots = 0;
+       return 0;
+}
+
+void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
 {
        struct kprobe_insn_page *kip;
        struct hlist_node *pos;
@@ -146,28 +231,18 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot)
                if (kip->insns <= slot &&
                    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
                        int i = (slot - kip->insns) / MAX_INSN_SIZE;
-                       kip->slot_used[i] = 0;
-                       kip->nused--;
-                       if (kip->nused == 0) {
-                               /*
-                                * Page is no longer in use.  Free it unless
-                                * it's the last one.  We keep the last one
-                                * so as not to have to set it up again the
-                                * next time somebody inserts a probe.
-                                */
-                               hlist_del(&kip->hlist);
-                               if (hlist_empty(&kprobe_insn_pages)) {
-                                       INIT_HLIST_NODE(&kip->hlist);
-                                       hlist_add_head(&kip->hlist,
-                                               &kprobe_insn_pages);
-                               } else {
-                                       module_free(NULL, kip->insns);
-                                       kfree(kip);
-                               }
+                       if (dirty) {
+                               kip->slot_used[i] = -1;
+                               kip->ngarbage++;
+                       } else {
+                               collect_one_slot(kip, i);
                        }
-                       return;
+                       break;
                }
        }
+       if (dirty && (++kprobe_garbage_slots > INSNS_PER_PAGE)) {
+               collect_garbage_slots();
+       }
 }
 #endif
 
index 4f9c60e..1db8c72 100644 (file)
@@ -31,6 +31,8 @@ struct kthread_create_info
        /* Result passed back to kthread_create() from keventd. */
        struct task_struct *result;
        struct completion done;
+
+       struct work_struct work;
 };
 
 struct kthread_stop_info
@@ -111,9 +113,10 @@ static int kthread(void *_create)
 }
 
 /* We are keventd: create a thread. */
-static void keventd_create_kthread(void *_create)
+static void keventd_create_kthread(struct work_struct *work)
 {
-       struct kthread_create_info *create = _create;
+       struct kthread_create_info *create =
+               container_of(work, struct kthread_create_info, work);
        int pid;
 
        /* We want our own signal handler (we take no signals by default). */
@@ -154,20 +157,20 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
                                   ...)
 {
        struct kthread_create_info create;
-       DECLARE_WORK(work, keventd_create_kthread, &create);
 
        create.threadfn = threadfn;
        create.data = data;
        init_completion(&create.started);
        init_completion(&create.done);
+       INIT_WORK(&create.work, keventd_create_kthread);
 
        /*
         * The workqueue needs to start up first:
         */
        if (!helper_wq)
-               work.func(work.data);
+               create.work.func(&create.work);
        else {
-               queue_work(helper_wq, &work);
+               queue_work(helper_wq, &create.work);
                wait_for_completion(&create.done);
        }
        if (!IS_ERR(create.result)) {
index c9fefdb..b020324 100644 (file)
@@ -140,13 +140,6 @@ void lockdep_on(void)
 
 EXPORT_SYMBOL(lockdep_on);
 
-int lockdep_internal(void)
-{
-       return current->lockdep_recursion != 0;
-}
-
-EXPORT_SYMBOL(lockdep_internal);
-
 /*
  * Debugging switches:
  */
@@ -228,17 +221,15 @@ static int save_trace(struct stack_trace *trace)
        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;
 
        nr_stack_trace_entries += trace->nr_entries;
-       if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES))
+       if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) {
+               __raw_spin_unlock(&hash_lock);
                return 0;
+       }
 
        if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) {
                __raw_spin_unlock(&hash_lock);
@@ -357,7 +348,7 @@ get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4
 
 static void print_lock_name(struct lock_class *class)
 {
-       char str[128], c1, c2, c3, c4;
+       char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4;
        const char *name;
 
        get_usage_chars(class, &c1, &c2, &c3, &c4);
@@ -379,7 +370,7 @@ static void print_lock_name(struct lock_class *class)
 static void print_lockdep_cache(struct lockdep_map *lock)
 {
        const char *name;
-       char str[128];
+       char str[KSYM_NAME_LEN + 1];
 
        name = lock->name;
        if (!name)
@@ -449,7 +440,9 @@ static void print_lock_dependencies(struct lock_class *class, int depth)
        print_lock_class_header(class, depth);
 
        list_for_each_entry(entry, &class->locks_after, entry) {
-               DEBUG_LOCKS_WARN_ON(!entry->class);
+               if (DEBUG_LOCKS_WARN_ON(!entry->class))
+                       return;
+
                print_lock_dependencies(entry->class, depth + 1);
 
                printk("%*s ... acquired at:\n",depth,"");
@@ -474,7 +467,8 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
                return 0;
 
        entry->class = this;
-       save_trace(&entry->trace);
+       if (!save_trace(&entry->trace))
+               return 0;
 
        /*
         * Since we never remove from the dependency list, the list can
@@ -562,8 +556,12 @@ static noinline int print_circular_bug_tail(void)
        if (debug_locks_silent)
                return 0;
 
+       /* hash_lock unlocked by the header */
+       __raw_spin_lock(&hash_lock);
        this.class = check_source->class;
-       save_trace(&this.trace);
+       if (!save_trace(&this.trace))
+               return 0;
+       __raw_spin_unlock(&hash_lock);
        print_circular_bug_entry(&this, 0);
 
        printk("\nother info that might help us debug this:\n\n");
@@ -966,14 +964,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
                               &prev->class->locks_after, next->acquire_ip);
        if (!ret)
                return 0;
-       /*
-        * Return value of 2 signals 'dependency already added',
-        * in that case we dont have to add the backlink either.
-        */
-       if (ret == 2)
-               return 2;
+
        ret = add_lock_to_list(next->class, prev->class,
                               &next->class->locks_before, next->acquire_ip);
+       if (!ret)
+               return 0;
 
        /*
         * Debugging printouts:
@@ -1025,7 +1020,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
                 * added:
                 */
                if (hlock->read != 2) {
-                       check_prev_add(curr, hlock, next);
+                       if (!check_prev_add(curr, hlock, next))
+                               return 0;
                        /*
                         * Stop after the first non-trylock entry,
                         * as non-trylock entries have added their
@@ -1182,6 +1178,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
        struct lockdep_subclass_key *key;
        struct list_head *hash_head;
        struct lock_class *class;
+       unsigned long flags;
 
        class = look_up_lock_class(lock, subclass);
        if (likely(class))
@@ -1203,6 +1200,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
        key = lock->key->subkeys + subclass;
        hash_head = classhashentry(key);
 
+       raw_local_irq_save(flags);
        __raw_spin_lock(&hash_lock);
        /*
         * We have to do the hash-walk again, to avoid races
@@ -1217,6 +1215,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
         */
        if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
                __raw_spin_unlock(&hash_lock);
+               raw_local_irq_restore(flags);
                debug_locks_off();
                printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
                printk("turning off the locking correctness validator.\n");
@@ -1239,15 +1238,18 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
 
        if (verbose(class)) {
                __raw_spin_unlock(&hash_lock);
+               raw_local_irq_restore(flags);
                printk("\nnew class %p: %s", class->key, class->name);
                if (class->name_version > 1)
                        printk("#%d", class->name_version);
                printk("\n");
                dump_stack();
+               raw_local_irq_save(flags);
                __raw_spin_lock(&hash_lock);
        }
 out_unlock_set:
        __raw_spin_unlock(&hash_lock);
+       raw_local_irq_restore(flags);
 
        if (!subclass || force)
                lock->class_cache = class;
@@ -1728,6 +1730,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
                debug_atomic_dec(&nr_unused_locks);
                break;
        default:
+               __raw_spin_unlock(&hash_lock);
                debug_locks_off();
                WARN_ON(1);
                return 0;
@@ -2645,6 +2648,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
        }
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
 
 static void print_held_locks_bug(struct task_struct *curr)
 {
index eab043c..8ce09bc 100644 (file)
@@ -20,7 +20,7 @@
 #define MAX_LOCKDEP_KEYS_BITS  11
 #define MAX_LOCKDEP_KEYS       (1UL << MAX_LOCKDEP_KEYS_BITS)
 
-#define MAX_LOCKDEP_CHAINS_BITS        13
+#define MAX_LOCKDEP_CHAINS_BITS        14
 #define MAX_LOCKDEP_CHAINS     (1UL << MAX_LOCKDEP_CHAINS_BITS)
 
 /*
index f6e72ea..b554b40 100644 (file)
@@ -113,7 +113,7 @@ static int l_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct seq_operations lockdep_ops = {
+static const struct seq_operations lockdep_ops = {
        .start  = l_start,
        .next   = l_next,
        .stop   = l_stop,
@@ -135,7 +135,7 @@ static int lockdep_open(struct inode *inode, struct file *file)
        return res;
 }
 
-static struct file_operations proc_lockdep_operations = {
+static const struct file_operations proc_lockdep_operations = {
        .open           = lockdep_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -319,7 +319,7 @@ static int lockdep_stats_open(struct inode *inode, struct file *file)
        return single_open(file, lockdep_stats_show, NULL);
 }
 
-static struct file_operations proc_lockdep_stats_operations = {
+static const struct file_operations proc_lockdep_stats_operations = {
        .open           = lockdep_stats_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index e2d09d6..d9eae45 100644 (file)
@@ -2209,7 +2209,7 @@ static int m_show(struct seq_file *m, void *p)
    Where refcount is a number or -, and deps is a comma-separated list
    of depends or -.
 */
-struct seq_operations modules_op = {
+const struct seq_operations modules_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
index 1865164..841539d 100644 (file)
@@ -77,6 +77,9 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
 
 void debug_mutex_unlock(struct mutex *lock)
 {
+       if (unlikely(!debug_locks))
+               return;
+
        DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
        DEBUG_LOCKS_WARN_ON(lock->magic != lock);
        DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
index 8c71cf7..e7cbbb8 100644 (file)
@@ -206,6 +206,15 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass)
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_nested);
+
+int __sched
+mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
+{
+       might_sleep();
+       return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass);
+}
+
+EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
 #endif
 
 /*
index 674aceb..e2ce748 100644 (file)
@@ -17,8 +17,9 @@
 #include <linux/version.h>
 #include <linux/nsproxy.h>
 #include <linux/init_task.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
 #include <linux/utsname.h>
+#include <linux/pid_namespace.h>
 
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
@@ -45,8 +46,10 @@ static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
        struct nsproxy *ns;
 
        ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
-       if (ns)
+       if (ns) {
                atomic_set(&ns->count, 1);
+               ns->id = -1;
+       }
        return ns;
 }
 
@@ -60,12 +63,14 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
        struct nsproxy *ns = clone_namespaces(orig);
 
        if (ns) {
-               if (ns->namespace)
-                       get_namespace(ns->namespace);
+               if (ns->mnt_ns)
+                       get_mnt_ns(ns->mnt_ns);
                if (ns->uts_ns)
                        get_uts_ns(ns->uts_ns);
                if (ns->ipc_ns)
                        get_ipc_ns(ns->ipc_ns);
+               if (ns->pid_ns)
+                       get_pid_ns(ns->pid_ns);
        }
 
        return ns;
@@ -97,7 +102,7 @@ int copy_namespaces(int flags, struct task_struct *tsk)
 
        tsk->nsproxy = new_ns;
 
-       err = copy_namespace(flags, tsk);
+       err = copy_mnt_ns(flags, tsk);
        if (err)
                goto out_ns;
 
@@ -109,16 +114,23 @@ int copy_namespaces(int flags, struct task_struct *tsk)
        if (err)
                goto out_ipc;
 
+       err = copy_pid_ns(flags, tsk);
+       if (err)
+               goto out_pid;
+
 out:
        put_nsproxy(old_ns);
        return err;
 
+out_pid:
+       if (new_ns->ipc_ns)
+               put_ipc_ns(new_ns->ipc_ns);
 out_ipc:
        if (new_ns->uts_ns)
                put_uts_ns(new_ns->uts_ns);
 out_uts:
-       if (new_ns->namespace)
-               put_namespace(new_ns->namespace);
+       if (new_ns->mnt_ns)
+               put_mnt_ns(new_ns->mnt_ns);
 out_ns:
        tsk->nsproxy = old_ns;
        kfree(new_ns);
@@ -127,11 +139,13 @@ out_ns:
 
 void free_nsproxy(struct nsproxy *ns)
 {
-               if (ns->namespace)
-                       put_namespace(ns->namespace);
-               if (ns->uts_ns)
-                       put_uts_ns(ns->uts_ns);
-               if (ns->ipc_ns)
-                       put_ipc_ns(ns->ipc_ns);
-               kfree(ns);
+       if (ns->mnt_ns)
+               put_mnt_ns(ns->mnt_ns);
+       if (ns->uts_ns)
+               put_uts_ns(ns->uts_ns);
+       if (ns->ipc_ns)
+               put_ipc_ns(ns->ipc_ns);
+       if (ns->pid_ns)
+               put_pid_ns(ns->pid_ns);
+       kfree(ns);
 }
index b914392..2efe9d8 100644 (file)
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/hash.h>
-#include <linux/pspace.h>
+#include <linux/pid_namespace.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
 static struct hlist_head *pid_hash;
 static int pidhash_shift;
-static kmem_cache_t *pid_cachep;
+static struct kmem_cache *pid_cachep;
 
 int pid_max = PID_MAX_DEFAULT;
 
@@ -43,9 +43,10 @@ int pid_max_max = PID_MAX_LIMIT;
 #define BITS_PER_PAGE          (PAGE_SIZE*8)
 #define BITS_PER_PAGE_MASK     (BITS_PER_PAGE-1)
 
-static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off)
+static inline int mk_pid(struct pid_namespace *pid_ns,
+               struct pidmap *map, int off)
 {
-       return (map - pspace->pidmap)*BITS_PER_PAGE + off;
+       return (map - pid_ns->pidmap)*BITS_PER_PAGE + off;
 }
 
 #define find_next_offset(map, off)                                     \
@@ -57,11 +58,15 @@ static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off)
  * value does not cause lots of bitmaps to be allocated, but
  * the scheme scales to up to 4 million PIDs, runtime.
  */
-struct pspace init_pspace = {
+struct pid_namespace init_pid_ns = {
+       .kref = {
+               .refcount       = ATOMIC_INIT(2),
+       },
        .pidmap = {
                [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
        },
-       .last_pid = 0
+       .last_pid = 0,
+       .child_reaper = &init_task
 };
 
 /*
@@ -80,25 +85,25 @@ struct pspace init_pspace = {
 
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
 
-static fastcall void free_pidmap(struct pspace *pspace, int pid)
+static fastcall void free_pidmap(struct pid_namespace *pid_ns, int pid)
 {
-       struct pidmap *map = pspace->pidmap + pid / BITS_PER_PAGE;
+       struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE;
        int offset = pid & BITS_PER_PAGE_MASK;
 
        clear_bit(offset, map->page);
        atomic_inc(&map->nr_free);
 }
 
-static int alloc_pidmap(struct pspace *pspace)
+static int alloc_pidmap(struct pid_namespace *pid_ns)
 {
-       int i, offset, max_scan, pid, last = pspace->last_pid;
+       int i, offset, max_scan, pid, last = pid_ns->last_pid;
        struct pidmap *map;
 
        pid = last + 1;
        if (pid >= pid_max)
                pid = RESERVED_PIDS;
        offset = pid & BITS_PER_PAGE_MASK;
-       map = &pspace->pidmap[pid/BITS_PER_PAGE];
+       map = &pid_ns->pidmap[pid/BITS_PER_PAGE];
        max_scan = (pid_max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset;
        for (i = 0; i <= max_scan; ++i) {
                if (unlikely(!map->page)) {
@@ -120,11 +125,11 @@ static int alloc_pidmap(struct pspace *pspace)
                        do {
                                if (!test_and_set_bit(offset, map->page)) {
                                        atomic_dec(&map->nr_free);
-                                       pspace->last_pid = pid;
+                                       pid_ns->last_pid = pid;
                                        return pid;
                                }
                                offset = find_next_offset(map, offset);
-                               pid = mk_pid(pspace, map, offset);
+                               pid = mk_pid(pid_ns, map, offset);
                        /*
                         * find_next_offset() found a bit, the pid from it
                         * is in-bounds, and if we fell back to the last
@@ -135,34 +140,34 @@ static int alloc_pidmap(struct pspace *pspace)
                                        (i != max_scan || pid < last ||
                                            !((last+1) & BITS_PER_PAGE_MASK)));
                }
-               if (map < &pspace->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
+               if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
                        ++map;
                        offset = 0;
                } else {
-                       map = &pspace->pidmap[0];
+                       map = &pid_ns->pidmap[0];
                        offset = RESERVED_PIDS;
                        if (unlikely(last == offset))
                                break;
                }
-               pid = mk_pid(pspace, map, offset);
+               pid = mk_pid(pid_ns, map, offset);
        }
        return -1;
 }
 
-static int next_pidmap(struct pspace *pspace, int last)
+static int next_pidmap(struct pid_namespace *pid_ns, int last)
 {
        int offset;
        struct pidmap *map, *end;
 
        offset = (last + 1) & BITS_PER_PAGE_MASK;
-       map = &pspace->pidmap[(last + 1)/BITS_PER_PAGE];
-       end = &pspace->pidmap[PIDMAP_ENTRIES];
+       map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
+       end = &pid_ns->pidmap[PIDMAP_ENTRIES];
        for (; map < end; map++, offset = 0) {
                if (unlikely(!map->page))
                        continue;
                offset = find_next_bit((map)->page, BITS_PER_PAGE, offset);
                if (offset < BITS_PER_PAGE)
-                       return mk_pid(pspace, map, offset);
+                       return mk_pid(pid_ns, map, offset);
        }
        return -1;
 }
@@ -192,7 +197,7 @@ fastcall void free_pid(struct pid *pid)
        hlist_del_rcu(&pid->pid_chain);
        spin_unlock_irqrestore(&pidmap_lock, flags);
 
-       free_pidmap(&init_pspace, pid->nr);
+       free_pidmap(current->nsproxy->pid_ns, pid->nr);
        call_rcu(&pid->rcu, delayed_put_pid);
 }
 
@@ -206,7 +211,7 @@ struct pid *alloc_pid(void)
        if (!pid)
                goto out;
 
-       nr = alloc_pidmap(&init_pspace);
+       nr = alloc_pidmap(current->nsproxy->pid_ns);
        if (nr < 0)
                goto out_free;
 
@@ -348,13 +353,33 @@ struct pid *find_ge_pid(int nr)
                pid = find_pid(nr);
                if (pid)
                        break;
-               nr = next_pidmap(&init_pspace, nr);
+               nr = next_pidmap(current->nsproxy->pid_ns, nr);
        } while (nr > 0);
 
        return pid;
 }
 EXPORT_SYMBOL_GPL(find_get_pid);
 
+int copy_pid_ns(int flags, struct task_struct *tsk)
+{
+       struct pid_namespace *old_ns = tsk->nsproxy->pid_ns;
+       int err = 0;
+
+       if (!old_ns)
+               return 0;
+
+       get_pid_ns(old_ns);
+       return err;
+}
+
+void free_pid_ns(struct kref *kref)
+{
+       struct pid_namespace *ns;
+
+       ns = container_of(kref, struct pid_namespace, kref);
+       kfree(ns);
+}
+
 /*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
@@ -382,10 +407,10 @@ void __init pidhash_init(void)
 
 void __init pidmap_init(void)
 {
-       init_pspace.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       init_pid_ns.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
        /* Reserve PID 0. We never call free_pidmap(0) */
-       set_bit(0, init_pspace.pidmap[0].page);
-       atomic_dec(&init_pspace.pidmap[0].nr_free);
+       set_bit(0, init_pid_ns.pidmap[0].page);
+       atomic_dec(&init_pid_ns.pidmap[0].nr_free);
 
        pid_cachep = kmem_cache_create("pid", sizeof(struct pid),
                                        __alignof__(struct pid),
index 9cbb5d1..5fe87de 100644 (file)
@@ -70,7 +70,7 @@
 /*
  * Lets keep our timers in a slab cache :-)
  */
-static kmem_cache_t *posix_timers_cache;
+static struct kmem_cache *posix_timers_cache;
 static struct idr posix_timers_id;
 static DEFINE_SPINLOCK(idr_lock);
 
index 825068c..710ed08 100644 (file)
@@ -78,7 +78,7 @@ config PM_SYSFS_DEPRECATED
 
 config SOFTWARE_SUSPEND
        bool "Software Suspend"
-       depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP) && !X86_PAE) || ((FRV || PPC32) && !SMP))
+       depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
        ---help---
          Enable the possibility of suspending the machine.
          It doesn't need ACPI or APM.
index b1fb786..0b00f56 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
+#include <linux/freezer.h>
 
 #include "power.h"
 
 static int noresume = 0;
 char resume_file[256] = CONFIG_PM_STD_PARTITION;
 dev_t swsusp_resume_device;
+sector_t swsusp_resume_block;
+
+/**
+ *     platform_prepare - prepare the machine for hibernation using the
+ *     platform driver if so configured and return an error code if it fails
+ */
+
+static inline int platform_prepare(void)
+{
+       int error = 0;
+
+       if (pm_disk_mode == PM_DISK_PLATFORM) {
+               if (pm_ops && pm_ops->prepare)
+                       error = pm_ops->prepare(PM_SUSPEND_DISK);
+       }
+       return error;
+}
 
 /**
  *     power_down - Shut machine down for hibernate.
@@ -40,12 +58,10 @@ dev_t swsusp_resume_device;
 
 static void power_down(suspend_disk_method_t mode)
 {
-       int error = 0;
-
        switch(mode) {
        case PM_DISK_PLATFORM:
                kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-               error = pm_ops->enter(PM_SUSPEND_DISK);
+               pm_ops->enter(PM_SUSPEND_DISK);
                break;
        case PM_DISK_SHUTDOWN:
                kernel_power_off();
@@ -90,12 +106,18 @@ static int prepare_processes(void)
                goto thaw;
        }
 
+       error = platform_prepare();
+       if (error)
+               goto thaw;
+
        /* Free memory before shutting down devices. */
        if (!(error = swsusp_shrink_memory()))
                return 0;
-thaw:
+
+       platform_finish();
+ thaw:
        thaw_processes();
-enable_cpus:
+ enable_cpus:
        enable_nonboot_cpus();
        pm_restore_console();
        return error;
@@ -127,7 +149,7 @@ int pm_suspend_disk(void)
                return error;
 
        if (pm_disk_mode == PM_DISK_TESTPROC)
-               goto Thaw;
+               return 0;
 
        suspend_console();
        error = device_suspend(PMSG_FREEZE);
@@ -189,10 +211,10 @@ static int software_resume(void)
 {
        int error;
 
-       down(&pm_sem);
+       mutex_lock(&pm_mutex);
        if (!swsusp_resume_device) {
                if (!strlen(resume_file)) {
-                       up(&pm_sem);
+                       mutex_unlock(&pm_mutex);
                        return -ENOENT;
                }
                swsusp_resume_device = name_to_dev_t(resume_file);
@@ -207,7 +229,7 @@ static int software_resume(void)
                 * FIXME: If noresume is specified, we need to find the partition
                 * and reset it back to normal swap space.
                 */
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
                return 0;
        }
 
@@ -251,7 +273,7 @@ static int software_resume(void)
        unprepare_processes();
  Done:
        /* For success case, the suspend path will release the lock */
-       up(&pm_sem);
+       mutex_unlock(&pm_mutex);
        pr_debug("PM: Resume from disk failed.\n");
        return 0;
 }
@@ -312,7 +334,7 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
 
-       down(&pm_sem);
+       mutex_lock(&pm_mutex);
        for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) {
                if (!strncmp(buf, pm_disk_modes[i], len)) {
                        mode = i;
@@ -336,7 +358,7 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
 
        pr_debug("PM: suspend-to-disk mode set to '%s'\n",
                 pm_disk_modes[mode]);
-       up(&pm_sem);
+       mutex_unlock(&pm_mutex);
        return error ? error : n;
 }
 
@@ -361,14 +383,14 @@ static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
        if (maj != MAJOR(res) || min != MINOR(res))
                goto out;
 
-       down(&pm_sem);
+       mutex_lock(&pm_mutex);
        swsusp_resume_device = res;
-       up(&pm_sem);
+       mutex_unlock(&pm_mutex);
        printk("Attempting manual resume\n");
        noresume = 0;
        software_resume();
        ret = n;
-out:
+ out:
        return ret;
 }
 
@@ -423,6 +445,19 @@ static int __init resume_setup(char *str)
        return 1;
 }
 
+static int __init resume_offset_setup(char *str)
+{
+       unsigned long long offset;
+
+       if (noresume)
+               return 1;
+
+       if (sscanf(str, "%llu", &offset) == 1)
+               swsusp_resume_block = offset;
+
+       return 1;
+}
+
 static int __init noresume_setup(char *str)
 {
        noresume = 1;
@@ -430,4 +465,5 @@ static int __init noresume_setup(char *str)
 }
 
 __setup("noresume", noresume_setup);
+__setup("resume_offset=", resume_offset_setup);
 __setup("resume=", resume_setup);
index 873228c..500eb87 100644 (file)
@@ -8,6 +8,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/suspend.h>
 #include <linux/kobject.h>
 #include <linux/string.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/resume-trace.h>
+#include <linux/freezer.h>
 
 #include "power.h"
 
 /*This is just an arbitrary number */
 #define FREE_PAGE_NUMBER (100)
 
-DECLARE_MUTEX(pm_sem);
+DEFINE_MUTEX(pm_mutex);
 
 struct pm_ops *pm_ops;
 suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
@@ -36,9 +38,9 @@ suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
 
 void pm_set_ops(struct pm_ops * ops)
 {
-       down(&pm_sem);
+       mutex_lock(&pm_mutex);
        pm_ops = ops;
-       up(&pm_sem);
+       mutex_unlock(&pm_mutex);
 }
 
 
@@ -182,7 +184,7 @@ static int enter_state(suspend_state_t state)
 
        if (!valid_state(state))
                return -ENODEV;
-       if (down_trylock(&pm_sem))
+       if (!mutex_trylock(&pm_mutex))
                return -EBUSY;
 
        if (state == PM_SUSPEND_DISK) {
@@ -200,7 +202,7 @@ static int enter_state(suspend_state_t state)
        pr_debug("PM: Finishing wakeup.\n");
        suspend_finish(state);
  Unlock:
-       up(&pm_sem);
+       mutex_unlock(&pm_mutex);
        return error;
 }
 
@@ -229,7 +231,7 @@ int pm_suspend(suspend_state_t state)
        return -EINVAL;
 }
 
-
+EXPORT_SYMBOL(pm_suspend);
 
 decl_subsys(power,NULL,NULL);
 
index bfe999f..eb461b8 100644 (file)
@@ -22,7 +22,9 @@ static inline int pm_suspend_disk(void)
        return -EPERM;
 }
 #endif
-extern struct semaphore pm_sem;
+
+extern struct mutex pm_mutex;
+
 #define power_attr(_name) \
 static struct subsys_attribute _name##_attr = {        \
        .attr   = {                             \
@@ -42,6 +44,7 @@ extern const void __nosave_begin, __nosave_end;
 extern unsigned long image_size;
 extern int in_suspend;
 extern dev_t swsusp_resume_device;
+extern sector_t swsusp_resume_block;
 
 extern asmlinkage int swsusp_arch_suspend(void);
 extern asmlinkage int swsusp_arch_resume(void);
@@ -102,8 +105,18 @@ struct snapshot_handle {
 extern unsigned int snapshot_additional_pages(struct zone *zone);
 extern int snapshot_read_next(struct snapshot_handle *handle, size_t count);
 extern int snapshot_write_next(struct snapshot_handle *handle, size_t count);
+extern void snapshot_write_finalize(struct snapshot_handle *handle);
 extern int snapshot_image_loaded(struct snapshot_handle *handle);
-extern void snapshot_free_unused_memory(struct snapshot_handle *handle);
+
+/*
+ * This structure is used to pass the values needed for the identification
+ * of the resume swap area from a user space to the kernel via the
+ * SNAPSHOT_SET_SWAP_AREA ioctl
+ */
+struct resume_swap_area {
+       loff_t offset;
+       u_int32_t dev;
+} __attribute__((packed));
 
 #define SNAPSHOT_IOC_MAGIC     '3'
 #define SNAPSHOT_FREEZE                        _IO(SNAPSHOT_IOC_MAGIC, 1)
@@ -117,7 +130,14 @@ extern void snapshot_free_unused_memory(struct snapshot_handle *handle);
 #define SNAPSHOT_FREE_SWAP_PAGES       _IO(SNAPSHOT_IOC_MAGIC, 9)
 #define SNAPSHOT_SET_SWAP_FILE         _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int)
 #define SNAPSHOT_S2RAM                 _IO(SNAPSHOT_IOC_MAGIC, 11)
-#define SNAPSHOT_IOC_MAXNR     11
+#define SNAPSHOT_PMOPS                 _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int)
+#define SNAPSHOT_SET_SWAP_AREA         _IOW(SNAPSHOT_IOC_MAGIC, 13, \
+                                                       struct resume_swap_area)
+#define SNAPSHOT_IOC_MAXNR     13
+
+#define PMOPS_PREPARE  1
+#define PMOPS_ENTER    2
+#define PMOPS_FINISH   3
 
 /**
  *     The bitmap is used for tracing allocated swap pages
@@ -141,7 +161,7 @@ struct bitmap_page {
 
 extern void free_bitmap(struct bitmap_page *bitmap);
 extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits);
-extern unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap);
+extern sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap);
 extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap);
 
 extern int swsusp_check(void);
@@ -153,3 +173,7 @@ extern int swsusp_read(void);
 extern int swsusp_write(void);
 extern void swsusp_close(void);
 extern int suspend_enter(suspend_state_t state);
+
+struct timeval;
+extern void swsusp_show_speed(struct timeval *, struct timeval *,
+                               unsigned int, char *);
index f1f900a..678ec73 100644 (file)
  * callback we use.
  */
 
-static void do_poweroff(void *dummy)
+static void do_poweroff(struct work_struct *dummy)
 {
        kernel_power_off();
 }
 
-static DECLARE_WORK(poweroff_work, do_poweroff, NULL);
+static DECLARE_WORK(poweroff_work, do_poweroff);
 
 static void handle_poweroff(int key, struct tty_struct *tty)
 {
index 72e72d2..99eeb11 100644 (file)
 #include <linux/suspend.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/freezer.h>
 
 /* 
  * Timeout for stopping processes
  */
 #define TIMEOUT        (20 * HZ)
 
+#define FREEZER_KERNEL_THREADS 0
+#define FREEZER_USER_SPACE 1
 
 static inline int freezeable(struct task_struct * p)
 {
@@ -39,7 +42,6 @@ void refrigerator(void)
        long save;
        save = current->state;
        pr_debug("%s entered refrigerator\n", current->comm);
-       printk("=");
 
        frozen_process(current);
        spin_lock_irq(&current->sighand->siglock);
@@ -79,96 +81,136 @@ static void cancel_freezing(struct task_struct *p)
        }
 }
 
-/* 0 = success, else # of processes that we failed to stop */
-int freeze_processes(void)
+static inline int is_user_space(struct task_struct *p)
+{
+       return p->mm && !(p->flags & PF_BORROWED_MM);
+}
+
+static unsigned int try_to_freeze_tasks(int freeze_user_space)
 {
-       int todo, nr_user, user_frozen;
-       unsigned long start_time;
        struct task_struct *g, *p;
+       unsigned long end_time;
+       unsigned int todo;
 
-       printk( "Stopping tasks: " );
-       start_time = jiffies;
-       user_frozen = 0;
+       end_time = jiffies + TIMEOUT;
        do {
-               nr_user = todo = 0;
+               todo = 0;
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
                        if (!freezeable(p))
                                continue;
+
                        if (frozen(p))
                                continue;
-                       if (p->state == TASK_TRACED && frozen(p->parent)) {
+
+                       if (p->state == TASK_TRACED &&
+                           (frozen(p->parent) ||
+                            p->parent->state == TASK_STOPPED)) {
                                cancel_freezing(p);
                                continue;
                        }
-                       if (p->mm && !(p->flags & PF_BORROWED_MM)) {
-                               /* The task is a user-space one.
-                                * Freeze it unless there's a vfork completion
-                                * pending
+                       if (is_user_space(p)) {
+                               if (!freeze_user_space)
+                                       continue;
+
+                               /* Freeze the task unless there is a vfork
+                                * completion pending
                                 */
                                if (!p->vfork_done)
                                        freeze_process(p);
-                               nr_user++;
                        } else {
-                               /* Freeze only if the user space is frozen */
-                               if (user_frozen)
-                                       freeze_process(p);
-                               todo++;
+                               if (freeze_user_space)
+                                       continue;
+
+                               freeze_process(p);
                        }
+                       todo++;
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
-               todo += nr_user;
-               if (!user_frozen && !nr_user) {
-                       sys_sync();
-                       start_time = jiffies;
-               }
-               user_frozen = !nr_user;
                yield();                        /* Yield is okay here */
-               if (todo && time_after(jiffies, start_time + TIMEOUT))
+               if (todo && time_after(jiffies, end_time))
                        break;
-       } while(todo);
+       } while (todo);
 
-       /* This does not unfreeze processes that are already frozen
-        * (we have slightly ugly calling convention in that respect,
-        * and caller must call thaw_processes() if something fails),
-        * but it cleans up leftover PF_FREEZE requests.
-        */
        if (todo) {
-               printk( "\n" );
-               printk(KERN_ERR " stopping tasks timed out "
-                       "after %d seconds (%d tasks remaining):\n",
-                       TIMEOUT / HZ, todo);
+               /* This does not unfreeze processes that are already frozen
+                * (we have slightly ugly calling convention in that respect,
+                * and caller must call thaw_processes() if something fails),
+                * but it cleans up leftover PF_FREEZE requests.
+                */
+               printk("\n");
+               printk(KERN_ERR "Stopping %s timed out after %d seconds "
+                               "(%d tasks refusing to freeze):\n",
+                               freeze_user_space ? "user space processes" :
+                                       "kernel threads",
+                               TIMEOUT / HZ, todo);
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
+                       if (is_user_space(p) == !freeze_user_space)
+                               continue;
+
                        if (freezeable(p) && !frozen(p))
-                               printk(KERN_ERR "  %s\n", p->comm);
+                               printk(KERN_ERR " %s\n", p->comm);
+
                        cancel_freezing(p);
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
-               return todo;
        }
 
-       printk( "|\n" );
+       return todo;
+}
+
+/**
+ *     freeze_processes - tell processes to enter the refrigerator
+ *
+ *     Returns 0 on success, or the number of processes that didn't freeze,
+ *     although they were told to.
+ */
+int freeze_processes(void)
+{
+       unsigned int nr_unfrozen;
+
+       printk("Stopping tasks ... ");
+       nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE);
+       if (nr_unfrozen)
+               return nr_unfrozen;
+
+       sys_sync();
+       nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
+       if (nr_unfrozen)
+               return nr_unfrozen;
+
+       printk("done.\n");
        BUG_ON(in_atomic());
        return 0;
 }
 
-void thaw_processes(void)
+static void thaw_tasks(int thaw_user_space)
 {
        struct task_struct *g, *p;
 
-       printk( "Restarting tasks..." );
        read_lock(&tasklist_lock);
        do_each_thread(g, p) {
                if (!freezeable(p))
                        continue;
+
+               if (is_user_space(p) == !thaw_user_space)
+                       continue;
+
                if (!thaw_process(p))
-                       printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
+                       printk(KERN_WARNING " Strange, %s not stopped\n",
+                               p->comm );
        } while_each_thread(g, p);
-
        read_unlock(&tasklist_lock);
+}
+
+void thaw_processes(void)
+{
+       printk("Restarting tasks ... ");
+       thaw_tasks(FREEZER_KERNEL_THREADS);
+       thaw_tasks(FREEZER_USER_SPACE);
        schedule();
-       printk( " done\n" );
+       printk("done.\n");
 }
 
 EXPORT_SYMBOL(refrigerator);
index 99f9b7d..c024606 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * linux/kernel/power/snapshot.c
  *
- * This file provide system snapshot/restore functionality.
+ * This file provides system snapshot/restore functionality for swsusp.
  *
  * Copyright (C) 1998-2005 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
  *
- * This file is released under the GPLv2, and is based on swsusp.c.
+ * This file is released under the GPLv2.
  *
  */
 
-
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 
 #include "power.h"
 
-/* List of PBEs used for creating and restoring the suspend image */
+/* List of PBEs needed for restoring the pages that were allocated before
+ * the suspend and included in the suspend image, but have also been
+ * allocated by the "resume" kernel, so their contents cannot be written
+ * directly to their "original" page frames.
+ */
 struct pbe *restore_pblist;
 
-static unsigned int nr_copy_pages;
-static unsigned int nr_meta_pages;
+/* Pointer to an auxiliary buffer (1 page) */
 static void *buffer;
 
-#ifdef CONFIG_HIGHMEM
-unsigned int count_highmem_pages(void)
-{
-       struct zone *zone;
-       unsigned long zone_pfn;
-       unsigned int n = 0;
-
-       for_each_zone (zone)
-               if (is_highmem(zone)) {
-                       mark_free_pages(zone);
-                       for (zone_pfn = 0; zone_pfn < zone->spanned_pages; zone_pfn++) {
-                               struct page *page;
-                               unsigned long pfn = zone_pfn + zone->zone_start_pfn;
-                               if (!pfn_valid(pfn))
-                                       continue;
-                               page = pfn_to_page(pfn);
-                               if (PageReserved(page))
-                                       continue;
-                               if (PageNosaveFree(page))
-                                       continue;
-                               n++;
-                       }
-               }
-       return n;
-}
-
-struct highmem_page {
-       char *data;
-       struct page *page;
-       struct highmem_page *next;
-};
-
-static struct highmem_page *highmem_copy;
-
-static int save_highmem_zone(struct zone *zone)
-{
-       unsigned long zone_pfn;
-       mark_free_pages(zone);
-       for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
-               struct page *page;
-               struct highmem_page *save;
-               void *kaddr;
-               unsigned long pfn = zone_pfn + zone->zone_start_pfn;
-
-               if (!(pfn%10000))
-                       printk(".");
-               if (!pfn_valid(pfn))
-                       continue;
-               page = pfn_to_page(pfn);
-               /*
-                * This condition results from rvmalloc() sans vmalloc_32()
-                * and architectural memory reservations. This should be
-                * corrected eventually when the cases giving rise to this
-                * are better understood.
-                */
-               if (PageReserved(page))
-                       continue;
-               BUG_ON(PageNosave(page));
-               if (PageNosaveFree(page))
-                       continue;
-               save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC);
-               if (!save)
-                       return -ENOMEM;
-               save->next = highmem_copy;
-               save->page = page;
-               save->data = (void *) get_zeroed_page(GFP_ATOMIC);
-               if (!save->data) {
-                       kfree(save);
-                       return -ENOMEM;
-               }
-               kaddr = kmap_atomic(page, KM_USER0);
-               memcpy(save->data, kaddr, PAGE_SIZE);
-               kunmap_atomic(kaddr, KM_USER0);
-               highmem_copy = save;
-       }
-       return 0;
-}
-
-int save_highmem(void)
-{
-       struct zone *zone;
-       int res = 0;
-
-       pr_debug("swsusp: Saving Highmem");
-       drain_local_pages();
-       for_each_zone (zone) {
-               if (is_highmem(zone))
-                       res = save_highmem_zone(zone);
-               if (res)
-                       return res;
-       }
-       printk("\n");
-       return 0;
-}
-
-int restore_highmem(void)
-{
-       printk("swsusp: Restoring Highmem\n");
-       while (highmem_copy) {
-               struct highmem_page *save = highmem_copy;
-               void *kaddr;
-               highmem_copy = save->next;
-
-               kaddr = kmap_atomic(save->page, KM_USER0);
-               memcpy(kaddr, save->data, PAGE_SIZE);
-               kunmap_atomic(kaddr, KM_USER0);
-               free_page((long) save->data);
-               kfree(save);
-       }
-       return 0;
-}
-#else
-static inline unsigned int count_highmem_pages(void) {return 0;}
-static inline int save_highmem(void) {return 0;}
-static inline int restore_highmem(void) {return 0;}
-#endif
-
 /**
  *     @safe_needed - on resume, for storing the PBE list and the image,
  *     we can only use memory pages that do not conflict with the pages
- *     used before suspend.
+ *     used before suspend.  The unsafe pages have PageNosaveFree set
+ *     and we count them using unsafe_pages.
  *
- *     The unsafe pages are marked with the PG_nosave_free flag
- *     and we count them using unsafe_pages
+ *     Each allocated image page is marked as PageNosave and PageNosaveFree
+ *     so that swsusp_free() can release it.
  */
 
 #define PG_ANY         0
@@ -174,7 +61,7 @@ static inline int restore_highmem(void) {return 0;}
 
 static unsigned int allocated_unsafe_pages;
 
-static void *alloc_image_page(gfp_t gfp_mask, int safe_needed)
+static void *get_image_page(gfp_t gfp_mask, int safe_needed)
 {
        void *res;
 
@@ -195,20 +82,39 @@ static void *alloc_image_page(gfp_t gfp_mask, int safe_needed)
 
 unsigned long get_safe_page(gfp_t gfp_mask)
 {
-       return (unsigned long)alloc_image_page(gfp_mask, PG_SAFE);
+       return (unsigned long)get_image_page(gfp_mask, PG_SAFE);
+}
+
+static struct page *alloc_image_page(gfp_t gfp_mask)
+{
+       struct page *page;
+
+       page = alloc_page(gfp_mask);
+       if (page) {
+               SetPageNosave(page);
+               SetPageNosaveFree(page);
+       }
+       return page;
 }
 
 /**
  *     free_image_page - free page represented by @addr, allocated with
- *     alloc_image_page (page flags set by it must be cleared)
+ *     get_image_page (page flags set by it must be cleared)
  */
 
 static inline void free_image_page(void *addr, int clear_nosave_free)
 {
-       ClearPageNosave(virt_to_page(addr));
+       struct page *page;
+
+       BUG_ON(!virt_addr_valid(addr));
+
+       page = virt_to_page(addr);
+
+       ClearPageNosave(page);
        if (clear_nosave_free)
-               ClearPageNosaveFree(virt_to_page(addr));
-       free_page((unsigned long)addr);
+               ClearPageNosaveFree(page);
+
+       __free_page(page);
 }
 
 /* struct linked_page is used to build chains of pages */
@@ -269,7 +175,7 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
        if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) {
                struct linked_page *lp;
 
-               lp = alloc_image_page(ca->gfp_mask, ca->safe_needed);
+               lp = get_image_page(ca->gfp_mask, ca->safe_needed);
                if (!lp)
                        return NULL;
 
@@ -446,8 +352,8 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
 
        /* Compute the number of zones */
        nr = 0;
-       for_each_zone (zone)
-               if (populated_zone(zone) && !is_highmem(zone))
+       for_each_zone(zone)
+               if (populated_zone(zone))
                        nr++;
 
        /* Allocate the list of zones bitmap objects */
@@ -459,10 +365,10 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
        }
 
        /* Initialize the zone bitmap objects */
-       for_each_zone (zone) {
+       for_each_zone(zone) {
                unsigned long pfn;
 
-               if (!populated_zone(zone) || is_highmem(zone))
+               if (!populated_zone(zone))
                        continue;
 
                zone_bm->start_pfn = zone->zone_start_pfn;
@@ -481,7 +387,7 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
                while (bb) {
                        unsigned long *ptr;
 
-                       ptr = alloc_image_page(gfp_mask, safe_needed);
+                       ptr = get_image_page(gfp_mask, safe_needed);
                        bb->data = ptr;
                        if (!ptr)
                                goto Free;
@@ -505,7 +411,7 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
        memory_bm_position_reset(bm);
        return 0;
 
-Free:
+ Free:
        bm->p_list = ca.chain;
        memory_bm_free(bm, PG_UNSAFE_CLEAR);
        return -ENOMEM;
@@ -651,7 +557,7 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
        memory_bm_position_reset(bm);
        return BM_END_OF_MAP;
 
-Return_pfn:
+ Return_pfn:
        bm->cur.chunk = chunk;
        bm->cur.bit = bit;
        return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
@@ -669,9 +575,81 @@ unsigned int snapshot_additional_pages(struct zone *zone)
 
        res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
        res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE);
-       return res;
+       return 2 * res;
+}
+
+#ifdef CONFIG_HIGHMEM
+/**
+ *     count_free_highmem_pages - compute the total number of free highmem
+ *     pages, system-wide.
+ */
+
+static unsigned int count_free_highmem_pages(void)
+{
+       struct zone *zone;
+       unsigned int cnt = 0;
+
+       for_each_zone(zone)
+               if (populated_zone(zone) && is_highmem(zone))
+                       cnt += zone->free_pages;
+
+       return cnt;
+}
+
+/**
+ *     saveable_highmem_page - Determine whether a highmem page should be
+ *     included in the suspend image.
+ *
+ *     We should save the page if it isn't Nosave or NosaveFree, or Reserved,
+ *     and it isn't a part of a free chunk of pages.
+ */
+
+static struct page *saveable_highmem_page(unsigned long pfn)
+{
+       struct page *page;
+
+       if (!pfn_valid(pfn))
+               return NULL;
+
+       page = pfn_to_page(pfn);
+
+       BUG_ON(!PageHighMem(page));
+
+       if (PageNosave(page) || PageReserved(page) || PageNosaveFree(page))
+               return NULL;
+
+       return page;
 }
 
+/**
+ *     count_highmem_pages - compute the total number of saveable highmem
+ *     pages.
+ */
+
+unsigned int count_highmem_pages(void)
+{
+       struct zone *zone;
+       unsigned int n = 0;
+
+       for_each_zone(zone) {
+               unsigned long pfn, max_zone_pfn;
+
+               if (!is_highmem(zone))
+                       continue;
+
+               mark_free_pages(zone);
+               max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
+               for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
+                       if (saveable_highmem_page(pfn))
+                               n++;
+       }
+       return n;
+}
+#else
+static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; }
+static inline unsigned int count_highmem_pages(void) { return 0; }
+#endif /* CONFIG_HIGHMEM */
+
 /**
  *     pfn_is_nosave - check if given pfn is in the 'nosave' section
  */
@@ -684,12 +662,12 @@ static inline int pfn_is_nosave(unsigned long pfn)
 }
 
 /**
- *     saveable - Determine whether a page should be cloned or not.
- *     @pfn:   The page
+ *     saveable - Determine whether a non-highmem page should be included in
+ *     the suspend image.
  *
- *     We save a page if it isn't Nosave, and is not in the range of pages
- *     statically defined as 'unsaveable', and it
- *     isn't a part of a free chunk of pages.
+ *     We should save the page if it isn't Nosave, and is not in the range
+ *     of pages statically defined as 'unsaveable', and it isn't a part of
+ *     a free chunk of pages.
  */
 
 static struct page *saveable_page(unsigned long pfn)
@@ -701,76 +679,130 @@ static struct page *saveable_page(unsigned long pfn)
 
        page = pfn_to_page(pfn);
 
-       if (PageNosave(page))
+       BUG_ON(PageHighMem(page));
+
+       if (PageNosave(page) || PageNosaveFree(page))
                return NULL;
+
        if (PageReserved(page) && pfn_is_nosave(pfn))
                return NULL;
-       if (PageNosaveFree(page))
-               return NULL;
 
        return page;
 }
 
+/**
+ *     count_data_pages - compute the total number of saveable non-highmem
+ *     pages.
+ */
+
 unsigned int count_data_pages(void)
 {
        struct zone *zone;
        unsigned long pfn, max_zone_pfn;
        unsigned int n = 0;
 
-       for_each_zone (zone) {
+       for_each_zone(zone) {
                if (is_highmem(zone))
                        continue;
+
                mark_free_pages(zone);
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
-                       n += !!saveable_page(pfn);
+                       if(saveable_page(pfn))
+                               n++;
        }
        return n;
 }
 
-static inline void copy_data_page(long *dst, long *src)
+/* This is needed, because copy_page and memcpy are not usable for copying
+ * task structs.
+ */
+static inline void do_copy_page(long *dst, long *src)
 {
        int n;
 
-       /* copy_page and memcpy are not usable for copying task structs. */
        for (n = PAGE_SIZE / sizeof(long); n; n--)
                *dst++ = *src++;
 }
 
+#ifdef CONFIG_HIGHMEM
+static inline struct page *
+page_is_saveable(struct zone *zone, unsigned long pfn)
+{
+       return is_highmem(zone) ?
+                       saveable_highmem_page(pfn) : saveable_page(pfn);
+}
+
+static inline void
+copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
+{
+       struct page *s_page, *d_page;
+       void *src, *dst;
+
+       s_page = pfn_to_page(src_pfn);
+       d_page = pfn_to_page(dst_pfn);
+       if (PageHighMem(s_page)) {
+               src = kmap_atomic(s_page, KM_USER0);
+               dst = kmap_atomic(d_page, KM_USER1);
+               do_copy_page(dst, src);
+               kunmap_atomic(src, KM_USER0);
+               kunmap_atomic(dst, KM_USER1);
+       } else {
+               src = page_address(s_page);
+               if (PageHighMem(d_page)) {
+                       /* Page pointed to by src may contain some kernel
+                        * data modified by kmap_atomic()
+                        */
+                       do_copy_page(buffer, src);
+                       dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0);
+                       memcpy(dst, buffer, PAGE_SIZE);
+                       kunmap_atomic(dst, KM_USER0);
+               } else {
+                       dst = page_address(d_page);
+                       do_copy_page(dst, src);
+               }
+       }
+}
+#else
+#define page_is_saveable(zone, pfn)    saveable_page(pfn)
+
+static inline void
+copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
+{
+       do_copy_page(page_address(pfn_to_page(dst_pfn)),
+                       page_address(pfn_to_page(src_pfn)));
+}
+#endif /* CONFIG_HIGHMEM */
+
 static void
 copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
 {
        struct zone *zone;
        unsigned long pfn;
 
-       for_each_zone (zone) {
+       for_each_zone(zone) {
                unsigned long max_zone_pfn;
 
-               if (is_highmem(zone))
-                       continue;
-
                mark_free_pages(zone);
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
-                       if (saveable_page(pfn))
+                       if (page_is_saveable(zone, pfn))
                                memory_bm_set_bit(orig_bm, pfn);
        }
        memory_bm_position_reset(orig_bm);
        memory_bm_position_reset(copy_bm);
        do {
                pfn = memory_bm_next_pfn(orig_bm);
-               if (likely(pfn != BM_END_OF_MAP)) {
-                       struct page *page;
-                       void *src;
-
-                       page = pfn_to_page(pfn);
-                       src = page_address(page);
-                       page = pfn_to_page(memory_bm_next_pfn(copy_bm));
-                       copy_data_page(page_address(page), src);
-               }
+               if (likely(pfn != BM_END_OF_MAP))
+                       copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
        } while (pfn != BM_END_OF_MAP);
 }
 
+/* Total number of image pages */
+static unsigned int nr_copy_pages;
+/* Number of pages needed for saving the original pfns of the image pages */
+static unsigned int nr_meta_pages;
+
 /**
  *     swsusp_free - free pages allocated for the suspend.
  *
@@ -792,7 +824,7 @@ void swsusp_free(void)
                                if (PageNosave(page) && PageNosaveFree(page)) {
                                        ClearPageNosave(page);
                                        ClearPageNosaveFree(page);
-                                       free_page((long) page_address(page));
+                                       __free_page(page);
                                }
                        }
        }
@@ -802,34 +834,108 @@ void swsusp_free(void)
        buffer = NULL;
 }
 
+#ifdef CONFIG_HIGHMEM
+/**
+  *    count_pages_for_highmem - compute the number of non-highmem pages
+  *    that will be necessary for creating copies of highmem pages.
+  */
+
+static unsigned int count_pages_for_highmem(unsigned int nr_highmem)
+{
+       unsigned int free_highmem = count_free_highmem_pages();
+
+       if (free_highmem >= nr_highmem)
+               nr_highmem = 0;
+       else
+               nr_highmem -= free_highmem;
+
+       return nr_highmem;
+}
+#else
+static unsigned int
+count_pages_for_highmem(unsigned int nr_highmem) { return 0; }
+#endif /* CONFIG_HIGHMEM */
 
 /**
- *     enough_free_mem - Make sure we enough free memory to snapshot.
- *
- *     Returns TRUE or FALSE after checking the number of available
- *     free pages.
+ *     enough_free_mem - Make sure we have enough free memory for the
+ *     snapshot image.
  */
 
-static int enough_free_mem(unsigned int nr_pages)
+static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
 {
        struct zone *zone;
        unsigned int free = 0, meta = 0;
 
-       for_each_zone (zone)
-               if (!is_highmem(zone)) {
+       for_each_zone(zone) {
+               meta += snapshot_additional_pages(zone);
+               if (!is_highmem(zone))
                        free += zone->free_pages;
-                       meta += snapshot_additional_pages(zone);
-               }
+       }
 
-       pr_debug("swsusp: pages needed: %u + %u + %u, available pages: %u\n",
+       nr_pages += count_pages_for_highmem(nr_highmem);
+       pr_debug("swsusp: Normal pages needed: %u + %u + %u, available pages: %u\n",
                nr_pages, PAGES_FOR_IO, meta, free);
 
        return free > nr_pages + PAGES_FOR_IO + meta;
 }
 
+#ifdef CONFIG_HIGHMEM
+/**
+ *     get_highmem_buffer - if there are some highmem pages in the suspend
+ *     image, we may need the buffer to copy them and/or load their data.
+ */
+
+static inline int get_highmem_buffer(int safe_needed)
+{
+       buffer = get_image_page(GFP_ATOMIC | __GFP_COLD, safe_needed);
+       return buffer ? 0 : -ENOMEM;
+}
+
+/**
+ *     alloc_highmem_image_pages - allocate some highmem pages for the image.
+ *     Try to allocate as many pages as needed, but if the number of free
+ *     highmem pages is lesser than that, allocate them all.
+ */
+
+static inline unsigned int
+alloc_highmem_image_pages(struct memory_bitmap *bm, unsigned int nr_highmem)
+{
+       unsigned int to_alloc = count_free_highmem_pages();
+
+       if (to_alloc > nr_highmem)
+               to_alloc = nr_highmem;
+
+       nr_highmem -= to_alloc;
+       while (to_alloc-- > 0) {
+               struct page *page;
+
+               page = alloc_image_page(__GFP_HIGHMEM);
+               memory_bm_set_bit(bm, page_to_pfn(page));
+       }
+       return nr_highmem;
+}
+#else
+static inline int get_highmem_buffer(int safe_needed) { return 0; }
+
+static inline unsigned int
+alloc_highmem_image_pages(struct memory_bitmap *bm, unsigned int n) { return 0; }
+#endif /* CONFIG_HIGHMEM */
+
+/**
+ *     swsusp_alloc - allocate memory for the suspend image
+ *
+ *     We first try to allocate as many highmem pages as there are
+ *     saveable highmem pages in the system.  If that fails, we allocate
+ *     non-highmem pages for the copies of the remaining highmem ones.
+ *
+ *     In this approach it is likely that the copies of highmem pages will
+ *     also be located in the high memory, because of the way in which
+ *     copy_data_pages() works.
+ */
+
 static int
 swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm,
-               unsigned int nr_pages)
+               unsigned int nr_pages, unsigned int nr_highmem)
 {
        int error;
 
@@ -841,46 +947,61 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm,
        if (error)
                goto Free;
 
+       if (nr_highmem > 0) {
+               error = get_highmem_buffer(PG_ANY);
+               if (error)
+                       goto Free;
+
+               nr_pages += alloc_highmem_image_pages(copy_bm, nr_highmem);
+       }
        while (nr_pages-- > 0) {
-               struct page *page = alloc_page(GFP_ATOMIC | __GFP_COLD);
+               struct page *page = alloc_image_page(GFP_ATOMIC | __GFP_COLD);
+
                if (!page)
                        goto Free;
 
-               SetPageNosave(page);
-               SetPageNosaveFree(page);
                memory_bm_set_bit(copy_bm, page_to_pfn(page));
        }
        return 0;
 
-Free:
+ Free:
        swsusp_free();
        return -ENOMEM;
 }
 
-/* Memory bitmap used for marking saveable pages */
+/* Memory bitmap used for marking saveable pages (during suspend) or the
+ * suspend image pages (during resume)
+ */
 static struct memory_bitmap orig_bm;
-/* Memory bitmap used for marking allocated pages that will contain the copies
- * of saveable pages
+/* Memory bitmap used on suspend for marking allocated pages that will contain
+ * the copies of saveable pages.  During resume it is initially used for
+ * marking the suspend image pages, but then its set bits are duplicated in
+ * @orig_bm and it is released.  Next, on systems with high memory, it may be
+ * used for marking "safe" highmem pages, but it has to be reinitialized for
+ * this purpose.
  */
 static struct memory_bitmap copy_bm;
 
 asmlinkage int swsusp_save(void)
 {
-       unsigned int nr_pages;
+       unsigned int nr_pages, nr_highmem;
 
-       pr_debug("swsusp: critical section: \n");
+       printk("swsusp: critical section: \n");
 
        drain_local_pages();
        nr_pages = count_data_pages();
-       printk("swsusp: Need to copy %u pages\n", nr_pages);
+       nr_highmem = count_highmem_pages();
+       printk("swsusp: Need to copy %u pages\n", nr_pages + nr_highmem);
 
-       if (!enough_free_mem(nr_pages)) {
+       if (!enough_free_mem(nr_pages, nr_highmem)) {
                printk(KERN_ERR "swsusp: Not enough free memory\n");
                return -ENOMEM;
        }
 
-       if (swsusp_alloc(&orig_bm, &copy_bm, nr_pages))
+       if (swsusp_alloc(&orig_bm, &copy_bm, nr_pages, nr_highmem)) {
+               printk(KERN_ERR "swsusp: Memory allocation failed\n");
                return -ENOMEM;
+       }
 
        /* During allocating of suspend pagedir, new cold pages may appear.
         * Kill them.
@@ -894,10 +1015,12 @@ asmlinkage int swsusp_save(void)
         * touch swap space! Except we must write out our image of course.
         */
 
+       nr_pages += nr_highmem;
        nr_copy_pages = nr_pages;
-       nr_meta_pages = (nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
 
        printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages);
+
        return 0;
 }
 
@@ -960,7 +1083,7 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
 
        if (!buffer) {
                /* This makes the buffer be freed by swsusp_free() */
-               buffer = alloc_image_page(GFP_ATOMIC, PG_ANY);
+               buffer = get_image_page(GFP_ATOMIC, PG_ANY);
                if (!buffer)
                        return -ENOMEM;
        }
@@ -975,9 +1098,23 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
                        memset(buffer, 0, PAGE_SIZE);
                        pack_pfns(buffer, &orig_bm);
                } else {
-                       unsigned long pfn = memory_bm_next_pfn(&copy_bm);
+                       struct page *page;
 
-                       handle->buffer = page_address(pfn_to_page(pfn));
+                       page = pfn_to_page(memory_bm_next_pfn(&copy_bm));
+                       if (PageHighMem(page)) {
+                               /* Highmem pages are copied to the buffer,
+                                * because we can't return with a kmapped
+                                * highmem page (we may not be called again).
+                                */
+                               void *kaddr;
+
+                               kaddr = kmap_atomic(page, KM_USER0);
+                               memcpy(buffer, kaddr, PAGE_SIZE);
+                               kunmap_atomic(kaddr, KM_USER0);
+                               handle->buffer = buffer;
+                       } else {
+                               handle->buffer = page_address(page);
+                       }
                }
                handle->prev = handle->cur;
        }
@@ -1005,7 +1142,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
        unsigned long pfn, max_zone_pfn;
 
        /* Clear page flags */
-       for_each_zone (zone) {
+       for_each_zone(zone) {
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
                        if (pfn_valid(pfn))
@@ -1101,6 +1238,218 @@ unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
        }
 }
 
+/* List of "safe" pages that may be used to store data loaded from the suspend
+ * image
+ */
+static struct linked_page *safe_pages_list;
+
+#ifdef CONFIG_HIGHMEM
+/* struct highmem_pbe is used for creating the list of highmem pages that
+ * should be restored atomically during the resume from disk, because the page
+ * frames they have occupied before the suspend are in use.
+ */
+struct highmem_pbe {
+       struct page *copy_page; /* data is here now */
+       struct page *orig_page; /* data was here before the suspend */
+       struct highmem_pbe *next;
+};
+
+/* List of highmem PBEs needed for restoring the highmem pages that were
+ * allocated before the suspend and included in the suspend image, but have
+ * also been allocated by the "resume" kernel, so their contents cannot be
+ * written directly to their "original" page frames.
+ */
+static struct highmem_pbe *highmem_pblist;
+
+/**
+ *     count_highmem_image_pages - compute the number of highmem pages in the
+ *     suspend image.  The bits in the memory bitmap @bm that correspond to the
+ *     image pages are assumed to be set.
+ */
+
+static unsigned int count_highmem_image_pages(struct memory_bitmap *bm)
+{
+       unsigned long pfn;
+       unsigned int cnt = 0;
+
+       memory_bm_position_reset(bm);
+       pfn = memory_bm_next_pfn(bm);
+       while (pfn != BM_END_OF_MAP) {
+               if (PageHighMem(pfn_to_page(pfn)))
+                       cnt++;
+
+               pfn = memory_bm_next_pfn(bm);
+       }
+       return cnt;
+}
+
+/**
+ *     prepare_highmem_image - try to allocate as many highmem pages as
+ *     there are highmem image pages (@nr_highmem_p points to the variable
+ *     containing the number of highmem image pages).  The pages that are
+ *     "safe" (ie. will not be overwritten when the suspend image is
+ *     restored) have the corresponding bits set in @bm (it must be
+ *     unitialized).
+ *
+ *     NOTE: This function should not be called if there are no highmem
+ *     image pages.
+ */
+
+static unsigned int safe_highmem_pages;
+
+static struct memory_bitmap *safe_highmem_bm;
+
+static int
+prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p)
+{
+       unsigned int to_alloc;
+
+       if (memory_bm_create(bm, GFP_ATOMIC, PG_SAFE))
+               return -ENOMEM;
+
+       if (get_highmem_buffer(PG_SAFE))
+               return -ENOMEM;
+
+       to_alloc = count_free_highmem_pages();
+       if (to_alloc > *nr_highmem_p)
+               to_alloc = *nr_highmem_p;
+       else
+               *nr_highmem_p = to_alloc;
+
+       safe_highmem_pages = 0;
+       while (to_alloc-- > 0) {
+               struct page *page;
+
+               page = alloc_page(__GFP_HIGHMEM);
+               if (!PageNosaveFree(page)) {
+                       /* The page is "safe", set its bit the bitmap */
+                       memory_bm_set_bit(bm, page_to_pfn(page));
+                       safe_highmem_pages++;
+               }
+               /* Mark the page as allocated */
+               SetPageNosave(page);
+               SetPageNosaveFree(page);
+       }
+       memory_bm_position_reset(bm);
+       safe_highmem_bm = bm;
+       return 0;
+}
+
+/**
+ *     get_highmem_page_buffer - for given highmem image page find the buffer
+ *     that suspend_write_next() should set for its caller to write to.
+ *
+ *     If the page is to be saved to its "original" page frame or a copy of
+ *     the page is to be made in the highmem, @buffer is returned.  Otherwise,
+ *     the copy of the page is to be made in normal memory, so the address of
+ *     the copy is returned.
+ *
+ *     If @buffer is returned, the caller of suspend_write_next() will write
+ *     the page's contents to @buffer, so they will have to be copied to the
+ *     right location on the next call to suspend_write_next() and it is done
+ *     with the help of copy_last_highmem_page().  For this purpose, if
+ *     @buffer is returned, @last_highmem page is set to the page to which
+ *     the data will have to be copied from @buffer.
+ */
+
+static struct page *last_highmem_page;
+
+static void *
+get_highmem_page_buffer(struct page *page, struct chain_allocator *ca)
+{
+       struct highmem_pbe *pbe;
+       void *kaddr;
+
+       if (PageNosave(page) && PageNosaveFree(page)) {
+               /* We have allocated the "original" page frame and we can
+                * use it directly to store the loaded page.
+                */
+               last_highmem_page = page;
+               return buffer;
+       }
+       /* The "original" page frame has not been allocated and we have to
+        * use a "safe" page frame to store the loaded page.
+        */
+       pbe = chain_alloc(ca, sizeof(struct highmem_pbe));
+       if (!pbe) {
+               swsusp_free();
+               return NULL;
+       }
+       pbe->orig_page = page;
+       if (safe_highmem_pages > 0) {
+               struct page *tmp;
+
+               /* Copy of the page will be stored in high memory */
+               kaddr = buffer;
+               tmp = pfn_to_page(memory_bm_next_pfn(safe_highmem_bm));
+               safe_highmem_pages--;
+               last_highmem_page = tmp;
+               pbe->copy_page = tmp;
+       } else {
+               /* Copy of the page will be stored in normal memory */
+               kaddr = safe_pages_list;
+               safe_pages_list = safe_pages_list->next;
+               pbe->copy_page = virt_to_page(kaddr);
+       }
+       pbe->next = highmem_pblist;
+       highmem_pblist = pbe;
+       return kaddr;
+}
+
+/**
+ *     copy_last_highmem_page - copy the contents of a highmem image from
+ *     @buffer, where the caller of snapshot_write_next() has place them,
+ *     to the right location represented by @last_highmem_page .
+ */
+
+static void copy_last_highmem_page(void)
+{
+       if (last_highmem_page) {
+               void *dst;
+
+               dst = kmap_atomic(last_highmem_page, KM_USER0);
+               memcpy(dst, buffer, PAGE_SIZE);
+               kunmap_atomic(dst, KM_USER0);
+               last_highmem_page = NULL;
+       }
+}
+
+static inline int last_highmem_page_copied(void)
+{
+       return !last_highmem_page;
+}
+
+static inline void free_highmem_data(void)
+{
+       if (safe_highmem_bm)
+               memory_bm_free(safe_highmem_bm, PG_UNSAFE_CLEAR);
+
+       if (buffer)
+               free_image_page(buffer, PG_UNSAFE_CLEAR);
+}
+#else
+static inline int get_safe_write_buffer(void) { return 0; }
+
+static unsigned int
+count_highmem_image_pages(struct memory_bitmap *bm) { return 0; }
+
+static inline int
+prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p)
+{
+       return 0;
+}
+
+static inline void *
+get_highmem_page_buffer(struct page *page, struct chain_allocator *ca)
+{
+       return NULL;
+}
+
+static inline void copy_last_highmem_page(void) {}
+static inline int last_highmem_page_copied(void) { return 1; }
+static inline void free_highmem_data(void) {}
+#endif /* CONFIG_HIGHMEM */
+
 /**
  *     prepare_image - use the memory bitmap @bm to mark the pages that will
  *     be overwritten in the process of restoring the system memory state
@@ -1110,20 +1459,25 @@ unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
  *     The idea is to allocate a new memory bitmap first and then allocate
  *     as many pages as needed for the image data, but not to assign these
  *     pages to specific tasks initially.  Instead, we just mark them as
- *     allocated and create a list of "safe" pages that will be used later.
+ *     allocated and create a lists of "safe" pages that will be used
+ *     later.  On systems with high memory a list of "safe" highmem pages is
+ *     also created.
  */
 
 #define PBES_PER_LINKED_PAGE   (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe))
 
-static struct linked_page *safe_pages_list;
-
 static int
 prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
 {
-       unsigned int nr_pages;
+       unsigned int nr_pages, nr_highmem;
        struct linked_page *sp_list, *lp;
        int error;
 
+       /* If there is no highmem, the buffer will not be necessary */
+       free_image_page(buffer, PG_UNSAFE_CLEAR);
+       buffer = NULL;
+
+       nr_highmem = count_highmem_image_pages(bm);
        error = mark_unsafe_pages(bm);
        if (error)
                goto Free;
@@ -1134,6 +1488,11 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
 
        duplicate_memory_bitmap(new_bm, bm);
        memory_bm_free(bm, PG_UNSAFE_KEEP);
+       if (nr_highmem > 0) {
+               error = prepare_highmem_image(bm, &nr_highmem);
+               if (error)
+                       goto Free;
+       }
        /* Reserve some safe pages for potential later use.
         *
         * NOTE: This way we make sure there will be enough safe pages for the
@@ -1142,10 +1501,10 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
         */
        sp_list = NULL;
        /* nr_copy_pages cannot be lesser than allocated_unsafe_pages */
-       nr_pages = nr_copy_pages - allocated_unsafe_pages;
+       nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
        nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE);
        while (nr_pages > 0) {
-               lp = alloc_image_page(GFP_ATOMIC, PG_SAFE);
+               lp = get_image_page(GFP_ATOMIC, PG_SAFE);
                if (!lp) {
                        error = -ENOMEM;
                        goto Free;
@@ -1156,7 +1515,7 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
        }
        /* Preallocate memory for the image */
        safe_pages_list = NULL;
-       nr_pages = nr_copy_pages - allocated_unsafe_pages;
+       nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
        while (nr_pages > 0) {
                lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC);
                if (!lp) {
@@ -1181,7 +1540,7 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
        }
        return 0;
 
-Free:
+ Free:
        swsusp_free();
        return error;
 }
@@ -1196,6 +1555,9 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
        struct pbe *pbe;
        struct page *page = pfn_to_page(memory_bm_next_pfn(bm));
 
+       if (PageHighMem(page))
+               return get_highmem_page_buffer(page, ca);
+
        if (PageNosave(page) && PageNosaveFree(page))
                /* We have allocated the "original" page frame and we can
                 * use it directly to store the loaded page.
@@ -1210,12 +1572,12 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
                swsusp_free();
                return NULL;
        }
-       pbe->orig_address = (unsigned long)page_address(page);
-       pbe->address = (unsigned long)safe_pages_list;
+       pbe->orig_address = page_address(page);
+       pbe->address = safe_pages_list;
        safe_pages_list = safe_pages_list->next;
        pbe->next = restore_pblist;
        restore_pblist = pbe;
-       return (void *)pbe->address;
+       return pbe->address;
 }
 
 /**
@@ -1249,14 +1611,16 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count)
        if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages)
                return 0;
 
-       if (!buffer) {
-               /* This makes the buffer be freed by swsusp_free() */
-               buffer = alloc_image_page(GFP_ATOMIC, PG_ANY);
+       if (handle->offset == 0) {
+               if (!buffer)
+                       /* This makes the buffer be freed by swsusp_free() */
+                       buffer = get_image_page(GFP_ATOMIC, PG_ANY);
+
                if (!buffer)
                        return -ENOMEM;
-       }
-       if (!handle->offset)
+
                handle->buffer = buffer;
+       }
        handle->sync_read = 1;
        if (handle->prev < handle->cur) {
                if (handle->prev == 0) {
@@ -1284,8 +1648,10 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count)
                                        return -ENOMEM;
                        }
                } else {
+                       copy_last_highmem_page();
                        handle->buffer = get_buffer(&orig_bm, &ca);
-                       handle->sync_read = 0;
+                       if (handle->buffer != buffer)
+                               handle->sync_read = 0;
                }
                handle->prev = handle->cur;
        }
@@ -1301,15 +1667,73 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count)
        return count;
 }
 
+/**
+ *     snapshot_write_finalize - must be called after the last call to
+ *     snapshot_write_next() in case the last page in the image happens
+ *     to be a highmem page and its contents should be stored in the
+ *     highmem.  Additionally, it releases the memory that will not be
+ *     used any more.
+ */
+
+void snapshot_write_finalize(struct snapshot_handle *handle)
+{
+       copy_last_highmem_page();
+       /* Free only if we have loaded the image entirely */
+       if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) {
+               memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
+               free_highmem_data();
+       }
+}
+
 int snapshot_image_loaded(struct snapshot_handle *handle)
 {
-       return !(!nr_copy_pages ||
+       return !(!nr_copy_pages || !last_highmem_page_copied() ||
                        handle->cur <= nr_meta_pages + nr_copy_pages);
 }
 
-void snapshot_free_unused_memory(struct snapshot_handle *handle)
+#ifdef CONFIG_HIGHMEM
+/* Assumes that @buf is ready and points to a "safe" page */
+static inline void
+swap_two_pages_data(struct page *p1, struct page *p2, void *buf)
 {
-       /* Free only if we have loaded the image entirely */
-       if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages)
-               memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
+       void *kaddr1, *kaddr2;
+
+       kaddr1 = kmap_atomic(p1, KM_USER0);
+       kaddr2 = kmap_atomic(p2, KM_USER1);
+       memcpy(buf, kaddr1, PAGE_SIZE);
+       memcpy(kaddr1, kaddr2, PAGE_SIZE);
+       memcpy(kaddr2, buf, PAGE_SIZE);
+       kunmap_atomic(kaddr1, KM_USER0);
+       kunmap_atomic(kaddr2, KM_USER1);
+}
+
+/**
+ *     restore_highmem - for each highmem page that was allocated before
+ *     the suspend and included in the suspend image, and also has been
+ *     allocated by the "resume" kernel swap its current (ie. "before
+ *     resume") contents with the previous (ie. "before suspend") one.
+ *
+ *     If the resume eventually fails, we can call this function once
+ *     again and restore the "before resume" highmem state.
+ */
+
+int restore_highmem(void)
+{
+       struct highmem_pbe *pbe = highmem_pblist;
+       void *buf;
+
+       if (!pbe)
+               return 0;
+
+       buf = get_image_page(GFP_ATOMIC, PG_SAFE);
+       if (!buf)
+               return -ENOMEM;
+
+       while (pbe) {
+               swap_two_pages_data(pbe->copy_page, pbe->orig_page, buf);
+               pbe = pbe->next;
+       }
+       free_image_page(buf, PG_UNSAFE_CLEAR);
+       return 0;
 }
+#endif /* CONFIG_HIGHMEM */
index 1a3b0dd..f133d4a 100644 (file)
@@ -34,34 +34,123 @@ extern char resume_file[];
 #define SWSUSP_SIG     "S1SUSPEND"
 
 static struct swsusp_header {
-       char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
-       swp_entry_t image;
+       char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
+       sector_t image;
        char    orig_sig[10];
        char    sig[10];
 } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
 
 /*
- * Saving part...
+ * General things
  */
 
 static unsigned short root_swap = 0xffff;
+static struct block_device *resume_bdev;
+
+/**
+ *     submit - submit BIO request.
+ *     @rw:    READ or WRITE.
+ *     @off    physical offset of page.
+ *     @page:  page we're reading or writing.
+ *     @bio_chain: list of pending biod (for async reading)
+ *
+ *     Straight from the textbook - allocate and initialize the bio.
+ *     If we're reading, make sure the page is marked as dirty.
+ *     Then submit it and, if @bio_chain == NULL, wait.
+ */
+static int submit(int rw, pgoff_t page_off, struct page *page,
+                       struct bio **bio_chain)
+{
+       struct bio *bio;
+
+       bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
+       if (!bio)
+               return -ENOMEM;
+       bio->bi_sector = page_off * (PAGE_SIZE >> 9);
+       bio->bi_bdev = resume_bdev;
+       bio->bi_end_io = end_swap_bio_read;
+
+       if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
+               printk("swsusp: ERROR: adding page to bio at %ld\n", page_off);
+               bio_put(bio);
+               return -EFAULT;
+       }
+
+       lock_page(page);
+       bio_get(bio);
+
+       if (bio_chain == NULL) {
+               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+               wait_on_page_locked(page);
+               if (rw == READ)
+                       bio_set_pages_dirty(bio);
+               bio_put(bio);
+       } else {
+               if (rw == READ)
+                       get_page(page); /* These pages are freed later */
+               bio->bi_private = *bio_chain;
+               *bio_chain = bio;
+               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+       }
+       return 0;
+}
+
+static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+{
+       return submit(READ, page_off, virt_to_page(addr), bio_chain);
+}
+
+static int bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+{
+       return submit(WRITE, page_off, virt_to_page(addr), bio_chain);
+}
+
+static int wait_on_bio_chain(struct bio **bio_chain)
+{
+       struct bio *bio;
+       struct bio *next_bio;
+       int ret = 0;
+
+       if (bio_chain == NULL)
+               return 0;
+
+       bio = *bio_chain;
+       if (bio == NULL)
+               return 0;
+       while (bio) {
+               struct page *page;
+
+               next_bio = bio->bi_private;
+               page = bio->bi_io_vec[0].bv_page;
+               wait_on_page_locked(page);
+               if (!PageUptodate(page) || PageError(page))
+                       ret = -EIO;
+               put_page(page);
+               bio_put(bio);
+               bio = next_bio;
+       }
+       *bio_chain = NULL;
+       return ret;
+}
+
+/*
+ * Saving part
+ */
 
-static int mark_swapfiles(swp_entry_t start)
+static int mark_swapfiles(sector_t start)
 {
        int error;
 
-       rw_swap_page_sync(READ, swp_entry(root_swap, 0),
-                         virt_to_page((unsigned long)&swsusp_header), NULL);
+       bio_read_page(swsusp_resume_block, &swsusp_header, NULL);
        if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
            !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
                memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
                memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
                swsusp_header.image = start;
-               error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0),
-                               virt_to_page((unsigned long)&swsusp_header),
-                               NULL);
+               error = bio_write_page(swsusp_resume_block,
+                                       &swsusp_header, NULL);
        } else {
-               pr_debug("swsusp: Partition is not swap space.\n");
+               printk(KERN_ERR "swsusp: Swap header not found!\n");
                error = -ENODEV;
        }
        return error;
@@ -74,12 +163,21 @@ static int mark_swapfiles(swp_entry_t start)
 
 static int swsusp_swap_check(void) /* This is called before saving image */
 {
-       int res = swap_type_of(swsusp_resume_device);
+       int res;
+
+       res = swap_type_of(swsusp_resume_device, swsusp_resume_block);
+       if (res < 0)
+               return res;
+
+       root_swap = res;
+       resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE);
+       if (IS_ERR(resume_bdev))
+               return PTR_ERR(resume_bdev);
+
+       res = set_blocksize(resume_bdev, PAGE_SIZE);
+       if (res < 0)
+               blkdev_put(resume_bdev);
 
-       if (res >= 0) {
-               root_swap = res;
-               return 0;
-       }
        return res;
 }
 
@@ -90,36 +188,26 @@ static int swsusp_swap_check(void) /* This is called before saving image */
  *     @bio_chain:     Link the next write BIO here
  */
 
-static int write_page(void *buf, unsigned long offset, struct bio **bio_chain)
+static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
 {
-       swp_entry_t entry;
-       int error = -ENOSPC;
-
-       if (offset) {
-               struct page *page = virt_to_page(buf);
-
-               if (bio_chain) {
-                       /*
-                        * Whether or not we successfully allocated a copy page,
-                        * we take a ref on the page here.  It gets undone in
-                        * wait_on_bio_chain().
-                        */
-                       struct page *page_copy;
-                       page_copy = alloc_page(GFP_ATOMIC);
-                       if (page_copy == NULL) {
-                               WARN_ON_ONCE(1);
-                               bio_chain = NULL;       /* Go synchronous */
-                               get_page(page);
-                       } else {
-                               memcpy(page_address(page_copy),
-                                       page_address(page), PAGE_SIZE);
-                               page = page_copy;
-                       }
+       void *src;
+
+       if (!offset)
+               return -ENOSPC;
+
+       if (bio_chain) {
+               src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+               if (src) {
+                       memcpy(src, buf, PAGE_SIZE);
+               } else {
+                       WARN_ON_ONCE(1);
+                       bio_chain = NULL;       /* Go synchronous */
+                       src = buf;
                }
-               entry = swp_entry(root_swap, offset);
-               error = rw_swap_page_sync(WRITE, entry, page, bio_chain);
+       } else {
+               src = buf;
        }
-       return error;
+       return bio_write_page(offset, src, bio_chain);
 }
 
 /*
@@ -137,11 +225,11 @@ static int write_page(void *buf, unsigned long offset, struct bio **bio_chain)
  *     at a time.
  */
 
-#define MAP_PAGE_ENTRIES       (PAGE_SIZE / sizeof(long) - 1)
+#define MAP_PAGE_ENTRIES       (PAGE_SIZE / sizeof(sector_t) - 1)
 
 struct swap_map_page {
-       unsigned long           entries[MAP_PAGE_ENTRIES];
-       unsigned long           next_swap;
+       sector_t entries[MAP_PAGE_ENTRIES];
+       sector_t next_swap;
 };
 
 /**
@@ -151,7 +239,7 @@ struct swap_map_page {
 
 struct swap_map_handle {
        struct swap_map_page *cur;
-       unsigned long cur_swap;
+       sector_t cur_swap;
        struct bitmap_page *bitmap;
        unsigned int k;
 };
@@ -166,26 +254,6 @@ static void release_swap_writer(struct swap_map_handle *handle)
        handle->bitmap = NULL;
 }
 
-static void show_speed(struct timeval *start, struct timeval *stop,
-                       unsigned nr_pages, char *msg)
-{
-       s64 elapsed_centisecs64;
-       int centisecs;
-       int k;
-       int kps;
-
-       elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
-       do_div(elapsed_centisecs64, NSEC_PER_SEC / 100);
-       centisecs = elapsed_centisecs64;
-       if (centisecs == 0)
-               centisecs = 1;  /* avoid div-by-zero */
-       k = nr_pages * (PAGE_SIZE / 1024);
-       kps = (k * 100) / centisecs;
-       printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k,
-                       centisecs / 100, centisecs % 100,
-                       kps / 1000, (kps % 1000) / 10);
-}
-
 static int get_swap_writer(struct swap_map_handle *handle)
 {
        handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
@@ -196,7 +264,7 @@ static int get_swap_writer(struct swap_map_handle *handle)
                release_swap_writer(handle);
                return -ENOMEM;
        }
-       handle->cur_swap = alloc_swap_page(root_swap, handle->bitmap);
+       handle->cur_swap = alloc_swapdev_block(root_swap, handle->bitmap);
        if (!handle->cur_swap) {
                release_swap_writer(handle);
                return -ENOSPC;
@@ -205,43 +273,15 @@ static int get_swap_writer(struct swap_map_handle *handle)
        return 0;
 }
 
-static int wait_on_bio_chain(struct bio **bio_chain)
-{
-       struct bio *bio;
-       struct bio *next_bio;
-       int ret = 0;
-
-       if (bio_chain == NULL)
-               return 0;
-
-       bio = *bio_chain;
-       if (bio == NULL)
-               return 0;
-       while (bio) {
-               struct page *page;
-
-               next_bio = bio->bi_private;
-               page = bio->bi_io_vec[0].bv_page;
-               wait_on_page_locked(page);
-               if (!PageUptodate(page) || PageError(page))
-                       ret = -EIO;
-               put_page(page);
-               bio_put(bio);
-               bio = next_bio;
-       }
-       *bio_chain = NULL;
-       return ret;
-}
-
 static int swap_write_page(struct swap_map_handle *handle, void *buf,
                                struct bio **bio_chain)
 {
        int error = 0;
-       unsigned long offset;
+       sector_t offset;
 
        if (!handle->cur)
                return -EINVAL;
-       offset = alloc_swap_page(root_swap, handle->bitmap);
+       offset = alloc_swapdev_block(root_swap, handle->bitmap);
        error = write_page(buf, offset, bio_chain);
        if (error)
                return error;
@@ -250,7 +290,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
                error = wait_on_bio_chain(bio_chain);
                if (error)
                        goto out;
-               offset = alloc_swap_page(root_swap, handle->bitmap);
+               offset = alloc_swapdev_block(root_swap, handle->bitmap);
                if (!offset)
                        return -ENOSPC;
                handle->cur->next_swap = offset;
@@ -261,7 +301,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
                handle->cur_swap = offset;
                handle->k = 0;
        }
-out:
+ out:
        return error;
 }
 
@@ -315,7 +355,7 @@ static int save_image(struct swap_map_handle *handle,
                error = err2;
        if (!error)
                printk("\b\b\b\bdone\n");
-       show_speed(&start, &stop, nr_to_write, "Wrote");
+       swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
        return error;
 }
 
@@ -350,100 +390,50 @@ int swsusp_write(void)
        struct swsusp_info *header;
        int error;
 
-       if ((error = swsusp_swap_check())) {
+       error = swsusp_swap_check();
+       if (error) {
                printk(KERN_ERR "swsusp: Cannot find swap device, try "
                                "swapon -a.\n");
                return error;
        }
        memset(&snapshot, 0, sizeof(struct snapshot_handle));
        error = snapshot_read_next(&snapshot, PAGE_SIZE);
-       if (error < PAGE_SIZE)
-               return error < 0 ? error : -EFAULT;
+       if (error < PAGE_SIZE) {
+               if (error >= 0)
+                       error = -EFAULT;
+
+               goto out;
+       }
        header = (struct swsusp_info *)data_of(snapshot);
        if (!enough_swap(header->pages)) {
                printk(KERN_ERR "swsusp: Not enough free swap\n");
-               return -ENOSPC;
+               error = -ENOSPC;
+               goto out;
        }
        error = get_swap_writer(&handle);
        if (!error) {
-               unsigned long start = handle.cur_swap;
+               sector_t start = handle.cur_swap;
+
                error = swap_write_page(&handle, header, NULL);
                if (!error)
                        error = save_image(&handle, &snapshot,
                                        header->pages - 1);
+
                if (!error) {
                        flush_swap_writer(&handle);
                        printk("S");
-                       error = mark_swapfiles(swp_entry(root_swap, start));
+                       error = mark_swapfiles(start);
                        printk("|\n");
                }
        }
        if (error)
                free_all_swap_pages(root_swap, handle.bitmap);
        release_swap_writer(&handle);
+ out:
+       swsusp_close();
        return error;
 }
 
-static struct block_device *resume_bdev;
-
-/**
- *     submit - submit BIO request.
- *     @rw:    READ or WRITE.
- *     @off    physical offset of page.
- *     @page:  page we're reading or writing.
- *     @bio_chain: list of pending biod (for async reading)
- *
- *     Straight from the textbook - allocate and initialize the bio.
- *     If we're reading, make sure the page is marked as dirty.
- *     Then submit it and, if @bio_chain == NULL, wait.
- */
-static int submit(int rw, pgoff_t page_off, struct page *page,
-                       struct bio **bio_chain)
-{
-       struct bio *bio;
-
-       bio = bio_alloc(GFP_ATOMIC, 1);
-       if (!bio)
-               return -ENOMEM;
-       bio->bi_sector = page_off * (PAGE_SIZE >> 9);
-       bio->bi_bdev = resume_bdev;
-       bio->bi_end_io = end_swap_bio_read;
-
-       if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
-               printk("swsusp: ERROR: adding page to bio at %ld\n", page_off);
-               bio_put(bio);
-               return -EFAULT;
-       }
-
-       lock_page(page);
-       bio_get(bio);
-
-       if (bio_chain == NULL) {
-               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
-               wait_on_page_locked(page);
-               if (rw == READ)
-                       bio_set_pages_dirty(bio);
-               bio_put(bio);
-       } else {
-               if (rw == READ)
-                       get_page(page); /* These pages are freed later */
-               bio->bi_private = *bio_chain;
-               *bio_chain = bio;
-               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
-       }
-       return 0;
-}
-
-static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
-{
-       return submit(READ, page_off, virt_to_page(addr), bio_chain);
-}
-
-static int bio_write_page(pgoff_t page_off, void *addr)
-{
-       return submit(WRITE, page_off, virt_to_page(addr), NULL);
-}
-
 /**
  *     The following functions allow us to read data using a swap map
  *     in a file-alike way
@@ -456,17 +446,18 @@ static void release_swap_reader(struct swap_map_handle *handle)
        handle->cur = NULL;
 }
 
-static int get_swap_reader(struct swap_map_handle *handle,
-                                      swp_entry_t start)
+static int get_swap_reader(struct swap_map_handle *handle, sector_t start)
 {
        int error;
 
-       if (!swp_offset(start))
+       if (!start)
                return -EINVAL;
-       handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
+
+       handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
        if (!handle->cur)
                return -ENOMEM;
-       error = bio_read_page(swp_offset(start), handle->cur, NULL);
+
+       error = bio_read_page(start, handle->cur, NULL);
        if (error) {
                release_swap_reader(handle);
                return error;
@@ -478,7 +469,7 @@ static int get_swap_reader(struct swap_map_handle *handle,
 static int swap_read_page(struct swap_map_handle *handle, void *buf,
                                struct bio **bio_chain)
 {
-       unsigned long offset;
+       sector_t offset;
        int error;
 
        if (!handle->cur)
@@ -547,11 +538,11 @@ static int load_image(struct swap_map_handle *handle,
                error = err2;
        if (!error) {
                printk("\b\b\b\bdone\n");
-               snapshot_free_unused_memory(snapshot);
+               snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        error = -ENODATA;
        }
-       show_speed(&start, &stop, nr_to_read, "Read");
+       swsusp_show_speed(&start, &stop, nr_to_read, "Read");
        return error;
 }
 
@@ -600,12 +591,16 @@ int swsusp_check(void)
        if (!IS_ERR(resume_bdev)) {
                set_blocksize(resume_bdev, PAGE_SIZE);
                memset(&swsusp_header, 0, sizeof(swsusp_header));
-               if ((error = bio_read_page(0, &swsusp_header, NULL)))
+               error = bio_read_page(swsusp_resume_block,
+                                       &swsusp_header, NULL);
+               if (error)
                        return error;
+
                if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
                        memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
                        /* Reset swap signature now */
-                       error = bio_write_page(0, &swsusp_header);
+                       error = bio_write_page(swsusp_resume_block,
+                                               &swsusp_header, NULL);
                } else {
                        return -EINVAL;
                }
index 0b66659..31aa039 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
 #include <linux/highmem.h>
+#include <linux/time.h>
 
 #include "power.h"
 
@@ -64,10 +65,8 @@ int in_suspend __nosavedata = 0;
 
 #ifdef CONFIG_HIGHMEM
 unsigned int count_highmem_pages(void);
-int save_highmem(void);
 int restore_highmem(void);
 #else
-static inline int save_highmem(void) { return 0; }
 static inline int restore_highmem(void) { return 0; }
 static inline unsigned int count_highmem_pages(void) { return 0; }
 #endif
@@ -134,18 +133,18 @@ static int bitmap_set(struct bitmap_page *bitmap, unsigned long bit)
        return 0;
 }
 
-unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap)
+sector_t alloc_swapdev_block(int swap, struct bitmap_page *bitmap)
 {
        unsigned long offset;
 
        offset = swp_offset(get_swap_page_of_type(swap));
        if (offset) {
-               if (bitmap_set(bitmap, offset)) {
+               if (bitmap_set(bitmap, offset))
                        swap_free(swp_entry(swap, offset));
-                       offset = 0;
-               }
+               else
+                       return swapdev_block(swap, offset);
        }
-       return offset;
+       return 0;
 }
 
 void free_all_swap_pages(int swap, struct bitmap_page *bitmap)
@@ -165,6 +164,34 @@ void free_all_swap_pages(int swap, struct bitmap_page *bitmap)
        }
 }
 
+/**
+ *     swsusp_show_speed - print the time elapsed between two events represented by
+ *     @start and @stop
+ *
+ *     @nr_pages -     number of pages processed between @start and @stop
+ *     @msg -          introductory message to print
+ */
+
+void swsusp_show_speed(struct timeval *start, struct timeval *stop,
+                       unsigned nr_pages, char *msg)
+{
+       s64 elapsed_centisecs64;
+       int centisecs;
+       int k;
+       int kps;
+
+       elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
+       do_div(elapsed_centisecs64, NSEC_PER_SEC / 100);
+       centisecs = elapsed_centisecs64;
+       if (centisecs == 0)
+               centisecs = 1;  /* avoid div-by-zero */
+       k = nr_pages * (PAGE_SIZE / 1024);
+       kps = (k * 100) / centisecs;
+       printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k,
+                       centisecs / 100, centisecs % 100,
+                       kps / 1000, (kps % 1000) / 10);
+}
+
 /**
  *     swsusp_shrink_memory -  Try to free as much memory as needed
  *
@@ -184,23 +211,37 @@ static inline unsigned long __shrink_memory(long tmp)
 
 int swsusp_shrink_memory(void)
 {
-       long size, tmp;
+       long tmp;
        struct zone *zone;
        unsigned long pages = 0;
        unsigned int i = 0;
        char *p = "-\\|/";
+       struct timeval start, stop;
 
        printk("Shrinking memory...  ");
+       do_gettimeofday(&start);
        do {
-               size = 2 * count_highmem_pages();
-               size += size / 50 + count_data_pages() + PAGES_FOR_IO;
+               long size, highmem_size;
+
+               highmem_size = count_highmem_pages();
+               size = count_data_pages() + PAGES_FOR_IO;
                tmp = size;
+               size += highmem_size;
                for_each_zone (zone)
-                       if (!is_highmem(zone) && populated_zone(zone)) {
-                               tmp -= zone->free_pages;
-                               tmp += zone->lowmem_reserve[ZONE_NORMAL];
-                               tmp += snapshot_additional_pages(zone);
+                       if (populated_zone(zone)) {
+                               if (is_highmem(zone)) {
+                                       highmem_size -= zone->free_pages;
+                               } else {
+                                       tmp -= zone->free_pages;
+                                       tmp += zone->lowmem_reserve[ZONE_NORMAL];
+                                       tmp += snapshot_additional_pages(zone);
+                               }
                        }
+
+               if (highmem_size < 0)
+                       highmem_size = 0;
+
+               tmp += highmem_size;
                if (tmp > 0) {
                        tmp = __shrink_memory(tmp);
                        if (!tmp)
@@ -212,7 +253,9 @@ int swsusp_shrink_memory(void)
                }
                printk("\b%c", p[i++%4]);
        } while (tmp > 0);
+       do_gettimeofday(&stop);
        printk("\bdone (%lu pages freed)\n", pages);
+       swsusp_show_speed(&start, &stop, pages, "Freed");
 
        return 0;
 }
@@ -223,6 +266,7 @@ int swsusp_suspend(void)
 
        if ((error = arch_prepare_suspend()))
                return error;
+
        local_irq_disable();
        /* At this point, device_suspend() has been called, but *not*
         * device_power_down(). We *must* device_power_down() now.
@@ -235,23 +279,16 @@ int swsusp_suspend(void)
                goto Enable_irqs;
        }
 
-       if ((error = save_highmem())) {
-               printk(KERN_ERR "swsusp: Not enough free pages for highmem\n");
-               goto Restore_highmem;
-       }
-
        save_processor_state();
        if ((error = swsusp_arch_suspend()))
                printk(KERN_ERR "Error %d suspending\n", error);
        /* Restore control flow magically appears here */
        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:
+ Enable_irqs:
        local_irq_enable();
        return error;
 }
@@ -268,18 +305,23 @@ int swsusp_resume(void)
                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();
-       error = swsusp_arch_resume();
-       /* Code below is only ever reached in case of failure. Otherwise
-        * execution continues at place where swsusp_arch_suspend was called
-         */
-       BUG_ON(!error);
+       error = restore_highmem();
+       if (!error) {
+               error = swsusp_arch_resume();
+               /* The code below is only ever reached in case of a failure.
+                * Otherwise execution continues at place where
+                * swsusp_arch_suspend() was called
+                */
+               BUG_ON(!error);
+               /* This call to restore_highmem() undos the previous one */
+               restore_highmem();
+       }
        /* The only reason why swsusp_arch_resume() can fail is memory being
         * very tight, so we have to free it as soon as we can to avoid
         * subsequent failures
         */
        swsusp_free();
        restore_processor_state();
-       restore_highmem();
        touch_softlockup_watchdog();
        device_power_up();
        local_irq_enable();
index d991d3b..89443b8 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
+#include <linux/reboot.h>
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
@@ -21,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 
@@ -54,7 +56,8 @@ static int snapshot_open(struct inode *inode, struct file *filp)
        filp->private_data = data;
        memset(&data->handle, 0, sizeof(struct snapshot_handle));
        if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
-               data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device) : -1;
+               data->swap = swsusp_resume_device ?
+                               swap_type_of(swsusp_resume_device, 0) : -1;
                data->mode = O_RDONLY;
        } else {
                data->swap = -1;
@@ -76,10 +79,10 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_all_swap_pages(data->swap, data->bitmap);
        free_bitmap(data->bitmap);
        if (data->frozen) {
-               down(&pm_sem);
+               mutex_lock(&pm_mutex);
                thaw_processes();
                enable_nonboot_cpus();
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
        }
        atomic_inc(&device_available);
        return 0;
@@ -124,7 +127,8 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
 {
        int error = 0;
        struct snapshot_data *data;
-       loff_t offset, avail;
+       loff_t avail;
+       sector_t offset;
 
        if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
                return -ENOTTY;
@@ -140,7 +144,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
        case SNAPSHOT_FREEZE:
                if (data->frozen)
                        break;
-               down(&pm_sem);
+               mutex_lock(&pm_mutex);
                error = disable_nonboot_cpus();
                if (!error) {
                        error = freeze_processes();
@@ -150,7 +154,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                                error = -EBUSY;
                        }
                }
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
                if (!error)
                        data->frozen = 1;
                break;
@@ -158,10 +162,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
        case SNAPSHOT_UNFREEZE:
                if (!data->frozen)
                        break;
-               down(&pm_sem);
+               mutex_lock(&pm_mutex);
                thaw_processes();
                enable_nonboot_cpus();
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
                data->frozen = 0;
                break;
 
@@ -170,7 +174,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -EPERM;
                        break;
                }
-               down(&pm_sem);
+               mutex_lock(&pm_mutex);
                /* Free memory before shutting down devices. */
                error = swsusp_shrink_memory();
                if (!error) {
@@ -183,7 +187,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        }
                        resume_console();
                }
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
                if (!error)
                        error = put_user(in_suspend, (unsigned int __user *)arg);
                if (!error)
@@ -191,13 +195,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                break;
 
        case SNAPSHOT_ATOMIC_RESTORE:
+               snapshot_write_finalize(&data->handle);
                if (data->mode != O_WRONLY || !data->frozen ||
                    !snapshot_image_loaded(&data->handle)) {
                        error = -EPERM;
                        break;
                }
-               snapshot_free_unused_memory(&data->handle);
-               down(&pm_sem);
+               mutex_lock(&pm_mutex);
                pm_prepare_console();
                suspend_console();
                error = device_suspend(PMSG_PRETHAW);
@@ -207,7 +211,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                }
                resume_console();
                pm_restore_console();
-               up(&pm_sem);
+               mutex_unlock(&pm_mutex);
                break;
 
        case SNAPSHOT_FREE:
@@ -238,10 +242,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                                break;
                        }
                }
-               offset = alloc_swap_page(data->swap, data->bitmap);
+               offset = alloc_swapdev_block(data->swap, data->bitmap);
                if (offset) {
                        offset <<= PAGE_SHIFT;
-                       error = put_user(offset, (loff_t __user *)arg);
+                       error = put_user(offset, (sector_t __user *)arg);
                } else {
                        error = -ENOSPC;
                }
@@ -264,7 +268,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                         * so we need to recode them
                         */
                        if (old_decode_dev(arg)) {
-                               data->swap = swap_type_of(old_decode_dev(arg));
+                               data->swap = swap_type_of(old_decode_dev(arg), 0);
                                if (data->swap < 0)
                                        error = -ENODEV;
                        } else {
@@ -282,7 +286,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        break;
                }
 
-               if (down_trylock(&pm_sem)) {
+               if (!mutex_trylock(&pm_mutex)) {
                        error = -EBUSY;
                        break;
                }
@@ -309,8 +313,66 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                if (pm_ops->finish)
                        pm_ops->finish(PM_SUSPEND_MEM);
 
-OutS3:
-               up(&pm_sem);
+ OutS3:
+               mutex_unlock(&pm_mutex);
+               break;
+
+       case SNAPSHOT_PMOPS:
+               switch (arg) {
+
+               case PMOPS_PREPARE:
+                       if (pm_ops->prepare) {
+                               error = pm_ops->prepare(PM_SUSPEND_DISK);
+                       }
+                       break;
+
+               case PMOPS_ENTER:
+                       kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+                       error = pm_ops->enter(PM_SUSPEND_DISK);
+                       break;
+
+               case PMOPS_FINISH:
+                       if (pm_ops && pm_ops->finish) {
+                               pm_ops->finish(PM_SUSPEND_DISK);
+                       }
+                       break;
+
+               default:
+                       printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
+                       error = -EINVAL;
+
+               }
+               break;
+
+       case SNAPSHOT_SET_SWAP_AREA:
+               if (data->bitmap) {
+                       error = -EPERM;
+               } else {
+                       struct resume_swap_area swap_area;
+                       dev_t swdev;
+
+                       error = copy_from_user(&swap_area, (void __user *)arg,
+                                       sizeof(struct resume_swap_area));
+                       if (error) {
+                               error = -EFAULT;
+                               break;
+                       }
+
+                       /*
+                        * User space encodes device types as two-byte values,
+                        * so we need to recode them
+                        */
+                       swdev = old_decode_dev(swap_area.dev);
+                       if (swdev) {
+                               offset = swap_area.offset;
+                               data->swap = swap_type_of(swdev, offset);
+                               if (data->swap < 0)
+                                       error = -ENODEV;
+                       } else {
+                               data->swap = -1;
+                               error = -EINVAL;
+                       }
+               }
                break;
 
        default:
@@ -321,7 +383,7 @@ OutS3:
        return error;
 }
 
-static struct file_operations snapshot_fops = {
+static const struct file_operations snapshot_fops = {
        .open = snapshot_open,
        .release = snapshot_release,
        .read = snapshot_read,
index 6642655..185bb45 100644 (file)
@@ -53,8 +53,6 @@ int console_printk[4] = {
        DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
 };
 
-EXPORT_UNUSED_SYMBOL(console_printk);  /*  June 2006  */
-
 /*
  * Low lever drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
@@ -335,13 +333,25 @@ static void __call_console_drivers(unsigned long start, unsigned long end)
        }
 }
 
+static int __read_mostly ignore_loglevel;
+
+int __init ignore_loglevel_setup(char *str)
+{
+       ignore_loglevel = 1;
+       printk(KERN_INFO "debug: ignoring loglevel setting.\n");
+
+       return 1;
+}
+
+__setup("ignore_loglevel", ignore_loglevel_setup);
+
 /*
  * Write out chars from start to end - 1 inclusive
  */
 static void _call_console_drivers(unsigned long start,
                                unsigned long end, int msg_log_level)
 {
-       if (msg_log_level < console_loglevel &&
+       if ((msg_log_level < console_loglevel || ignore_loglevel) &&
                        console_drivers && start != end) {
                if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
                        /* wrapped write */
@@ -631,12 +641,7 @@ EXPORT_SYMBOL(vprintk);
 
 asmlinkage long sys_syslog(int type, char __user *buf, int len)
 {
-       return 0;
-}
-
-int do_syslog(int type, char __user *buf, int len)
-{
-       return 0;
+       return -ENOSYS;
 }
 
 static void call_console_drivers(unsigned long start, unsigned long end)
@@ -777,7 +782,6 @@ int is_console_locked(void)
 {
        return console_locked;
 }
-EXPORT_UNUSED_SYMBOL(is_console_locked);  /*  June 2006  */
 
 /**
  * release_console_sem - unlock the console system
index f940b46..fb5e03d 100644 (file)
@@ -40,7 +40,7 @@ int (*timer_hook)(struct pt_regs *) __read_mostly;
 
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
-static int prof_on __read_mostly;
+int prof_on __read_mostly;
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -51,9 +51,19 @@ static DEFINE_MUTEX(profile_flip_mutex);
 static int __init profile_setup(char * str)
 {
        static char __initdata schedstr[] = "schedule";
+       static char __initdata sleepstr[] = "sleep";
        int par;
 
-       if (!strncmp(str, schedstr, strlen(schedstr))) {
+       if (!strncmp(str, sleepstr, strlen(sleepstr))) {
+               prof_on = SLEEP_PROFILING;
+               if (str[strlen(sleepstr)] == ',')
+                       str += strlen(sleepstr) + 1;
+               if (get_option(&str, &par))
+                       prof_shift = par;
+               printk(KERN_INFO
+                       "kernel sleep profiling enabled (shift: %ld)\n",
+                       prof_shift);
+       } else if (!strncmp(str, sleepstr, strlen(sleepstr))) {
                prof_on = SCHED_PROFILING;
                if (str[strlen(schedstr)] == ',')
                        str += strlen(schedstr) + 1;
@@ -204,7 +214,8 @@ EXPORT_SYMBOL_GPL(profile_event_unregister);
  * positions to which hits are accounted during short intervals (e.g.
  * several seconds) is usually very small. Exclusion from buffer
  * flipping is provided by interrupt disablement (note that for
- * SCHED_PROFILING profile_hit() may be called from process context).
+ * SCHED_PROFILING or SLEEP_PROFILING profile_hit() may be called from
+ * process context).
  * The hash function is meant to be lightweight as opposed to strong,
  * and was vaguely inspired by ppc64 firmware-supported inverted
  * pagetable hash functions, but uses a full hashtable full of finite
@@ -257,7 +268,7 @@ static void profile_discard_flip_buffers(void)
        mutex_unlock(&profile_flip_mutex);
 }
 
-void profile_hit(int type, void *__pc)
+void profile_hits(int type, void *__pc, unsigned int nr_hits)
 {
        unsigned long primary, secondary, flags, pc = (unsigned long)__pc;
        int i, j, cpu;
@@ -274,21 +285,31 @@ void profile_hit(int type, void *__pc)
                put_cpu();
                return;
        }
+       /*
+        * We buffer the global profiler buffer into a per-CPU
+        * queue and thus reduce the number of global (and possibly
+        * NUMA-alien) accesses. The write-queue is self-coalescing:
+        */
        local_irq_save(flags);
        do {
                for (j = 0; j < PROFILE_GRPSZ; ++j) {
                        if (hits[i + j].pc == pc) {
-                               hits[i + j].hits++;
+                               hits[i + j].hits += nr_hits;
                                goto out;
                        } else if (!hits[i + j].hits) {
                                hits[i + j].pc = pc;
-                               hits[i + j].hits = 1;
+                               hits[i + j].hits = nr_hits;
                                goto out;
                        }
                }
                i = (i + secondary) & (NR_PROFILE_HIT - 1);
        } while (i != primary);
-       atomic_inc(&prof_buffer[pc]);
+
+       /*
+        * Add the current hit(s) and flush the write-queue out
+        * to the global buffer:
+        */
+       atomic_add(nr_hits, &prof_buffer[pc]);
        for (i = 0; i < NR_PROFILE_HIT; ++i) {
                atomic_add(hits[i].hits, &prof_buffer[hits[i].pc]);
                hits[i].pc = hits[i].hits = 0;
@@ -298,7 +319,6 @@ out:
        put_cpu();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int __devinit profile_cpu_callback(struct notifier_block *info,
                                        unsigned long action, void *__cpu)
 {
@@ -351,19 +371,19 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
        }
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 #else /* !CONFIG_SMP */
 #define profile_flip_buffers()         do { } while (0)
 #define profile_discard_flip_buffers() do { } while (0)
+#define profile_cpu_callback           NULL
 
-void profile_hit(int type, void *__pc)
+void profile_hits(int type, void *__pc, unsigned int nr_hits)
 {
        unsigned long pc;
 
        if (prof_on != type || !prof_buffer)
                return;
        pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
-       atomic_inc(&prof_buffer[min(pc, prof_len - 1)]);
+       atomic_add(nr_hits, &prof_buffer[min(pc, prof_len - 1)]);
 }
 #endif /* !CONFIG_SMP */
 
@@ -442,7 +462,8 @@ read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        read = 0;
 
        while (p < sizeof(unsigned int) && count > 0) {
-               put_user(*((char *)(&sample_step)+p),buf);
+               if (put_user(*((char *)(&sample_step)+p),buf))
+                       return -EFAULT;
                buf++; p++; count--; read++;
        }
        pnt = (char *)prof_buffer + p - sizeof(atomic_t);
@@ -480,7 +501,7 @@ static ssize_t write_profile(struct file *file, const char __user *buf,
        return count;
 }
 
-static struct file_operations proc_profile_operations = {
+static const struct file_operations proc_profile_operations = {
        .read           = read_profile,
        .write          = write_profile,
 };
index 26bb5ff..3554b76 100644 (file)
@@ -235,12 +235,14 @@ static void rcu_do_batch(struct rcu_data *rdp)
 
        list = rdp->donelist;
        while (list) {
-               next = rdp->donelist = list->next;
+               next = list->next;
+               prefetch(next);
                list->func(list);
                list = next;
                if (++count >= rdp->blimit)
                        break;
        }
+       rdp->donelist = list;
 
        local_irq_disable();
        rdp->qlen -= count;
index e2bda18..c52f981 100644 (file)
@@ -401,7 +401,7 @@ static void srcu_torture_cleanup(void)
        cleanup_srcu_struct(&srcu_ctl);
 }
 
-static int srcu_torture_read_lock(void)
+static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
 {
        return srcu_read_lock(&srcu_ctl);
 }
@@ -419,7 +419,7 @@ static void srcu_read_delay(struct rcu_random_state *rrsp)
                schedule_timeout_interruptible(longdelay);
 }
 
-static void srcu_torture_read_unlock(int idx)
+static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
 {
        srcu_read_unlock(&srcu_ctl, idx);
 }
index f04bbdb..818e514 100644 (file)
@@ -308,9 +308,10 @@ static struct rchan_callbacks default_channel_callbacks = {
  *     reason waking is deferred is that calling directly from write
  *     causes problems if you're writing from say the scheduler.
  */
-static void wakeup_readers(void *private)
+static void wakeup_readers(struct work_struct *work)
 {
-       struct rchan_buf *buf = private;
+       struct rchan_buf *buf =
+               container_of(work, struct rchan_buf, wake_readers.work);
        wake_up_interruptible(&buf->read_wait);
 }
 
@@ -328,7 +329,7 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
        if (init) {
                init_waitqueue_head(&buf->read_wait);
                kref_init(&buf->kref);
-               INIT_WORK(&buf->wake_readers, NULL, NULL);
+               INIT_DELAYED_WORK(&buf->wake_readers, NULL);
        } else {
                cancel_delayed_work(&buf->wake_readers);
                flush_scheduled_work();
@@ -549,7 +550,8 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                        buf->padding[old_subbuf];
                smp_mb();
                if (waitqueue_active(&buf->read_wait)) {
-                       PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
+                       PREPARE_DELAYED_WORK(&buf->wake_readers,
+                                            wakeup_readers);
                        schedule_delayed_work(&buf->wake_readers, 1);
                }
        }
@@ -957,7 +959,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
        if (!desc->count)
                return 0;
 
-       mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+       mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
        do {
                if (!relay_file_read_avail(buf, *ppos))
                        break;
@@ -977,7 +979,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
                        *ppos = relay_file_read_end_pos(buf, read_start, ret);
                }
        } while (desc->count && ret);
-       mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
 
        return desc->written;
 }
@@ -1011,7 +1013,7 @@ static ssize_t relay_file_sendfile(struct file *filp,
                                       actor, &desc);
 }
 
-struct file_operations relay_file_operations = {
+const struct file_operations relay_file_operations = {
        .open           = relay_file_open,
        .poll           = relay_file_poll,
        .mmap           = relay_file_mmap,
index 6de60c1..7b9a497 100644 (file)
@@ -88,7 +88,7 @@ static int r_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct seq_operations resource_op = {
+static const struct seq_operations resource_op = {
        .start  = r_start,
        .next   = r_next,
        .stop   = r_stop,
@@ -115,14 +115,14 @@ static int iomem_open(struct inode *inode, struct file *file)
        return res;
 }
 
-static struct file_operations proc_ioports_operations = {
+static const struct file_operations proc_ioports_operations = {
        .open           = ioports_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
 };
 
-static struct file_operations proc_iomem_operations = {
+static const struct file_operations proc_iomem_operations = {
        .open           = iomem_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index 6dcea9d..015fc63 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/timer.h>
+#include <linux/freezer.h>
 
 #include "rtmutex.h"
 
index 3399701..8a0afb9 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/security.h>
 #include <linux/notifier.h>
 #include <linux/profile.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/vmalloc.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -225,8 +225,10 @@ struct rq {
        unsigned long nr_uninterruptible;
 
        unsigned long expired_timestamp;
-       unsigned long long timestamp_last_tick;
+       /* Cached timestamp set by update_cpu_clock() */
+       unsigned long long most_recent_timestamp;
        struct task_struct *curr, *idle;
+       unsigned long next_balance;
        struct mm_struct *prev_mm;
        struct prio_array *active, *expired, arrays[2];
        int best_expired_prio;
@@ -426,7 +428,7 @@ static inline void task_rq_unlock(struct rq *rq, unsigned long *flags)
  * bump this up when changing the output format or the meaning of an existing
  * format, so that tools can adapt (or abort)
  */
-#define SCHEDSTAT_VERSION 12
+#define SCHEDSTAT_VERSION 14
 
 static int show_schedstat(struct seq_file *seq, void *v)
 {
@@ -464,7 +466,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
                        seq_printf(seq, "domain%d %s", dcnt++, mask_str);
                        for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
                                        itype++) {
-                               seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu",
+                               seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+                                               "%lu",
                                    sd->lb_cnt[itype],
                                    sd->lb_balanced[itype],
                                    sd->lb_failed[itype],
@@ -474,11 +477,13 @@ static int show_schedstat(struct seq_file *seq, void *v)
                                    sd->lb_nobusyq[itype],
                                    sd->lb_nobusyg[itype]);
                        }
-                       seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+                       seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+                           " %lu %lu %lu\n",
                            sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
                            sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
                            sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
-                           sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance);
+                           sd->ttwu_wake_remote, sd->ttwu_move_affine,
+                           sd->ttwu_move_balance);
                }
                preempt_enable();
 #endif
@@ -505,7 +510,7 @@ static int schedstat_open(struct inode *inode, struct file *file)
        return res;
 }
 
-struct file_operations proc_schedstat_operations = {
+const struct file_operations proc_schedstat_operations = {
        .open    = schedstat_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
@@ -547,7 +552,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
 #endif
 
 /*
- * rq_lock - lock a given runqueue and disable interrupts.
+ * this_rq_lock - lock this runqueue and disable interrupts.
  */
 static inline struct rq *this_rq_lock(void)
        __acquires(rq->lock)
@@ -938,18 +943,31 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
 {
        unsigned long long now;
 
+       if (rt_task(p))
+               goto out;
+
        now = sched_clock();
 #ifdef CONFIG_SMP
        if (!local) {
                /* Compensate for drifting sched_clock */
                struct rq *this_rq = this_rq();
-               now = (now - this_rq->timestamp_last_tick)
-                       + rq->timestamp_last_tick;
+               now = (now - this_rq->most_recent_timestamp)
+                       + rq->most_recent_timestamp;
        }
 #endif
 
-       if (!rt_task(p))
-               p->prio = recalc_task_prio(p, now);
+       /*
+        * Sleep time is in units of nanosecs, so shift by 20 to get a
+        * milliseconds-range estimation of the amount of time that the task
+        * spent sleeping:
+        */
+       if (unlikely(prof_on == SLEEP_PROFILING)) {
+               if (p->state == TASK_UNINTERRUPTIBLE)
+                       profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
+                                    (now - p->timestamp) >> 20);
+       }
+
+       p->prio = recalc_task_prio(p, now);
 
        /*
         * This checks to make sure it's not an uninterruptible task
@@ -974,7 +992,7 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
                }
        }
        p->timestamp = now;
-
+out:
        __activate_task(p, rq);
 }
 
@@ -1439,7 +1457,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
 
                if (this_sd->flags & SD_WAKE_AFFINE) {
                        unsigned long tl = this_load;
-                       unsigned long tl_per_task = cpu_avg_load_per_task(this_cpu);
+                       unsigned long tl_per_task;
+
+                       tl_per_task = cpu_avg_load_per_task(this_cpu);
 
                        /*
                         * If sync wakeup then subtract the (maximum possible)
@@ -1677,8 +1697,8 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
                 * Not the local CPU - must adjust timestamp. This should
                 * get optimised away in the !CONFIG_SMP case.
                 */
-               p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
-                                       + rq->timestamp_last_tick;
+               p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
+                                       + rq->most_recent_timestamp;
                __activate_task(p, rq);
                if (TASK_PREEMPTS_CURR(p, rq))
                        resched_task(rq->curr);
@@ -1941,6 +1961,7 @@ static void double_rq_lock(struct rq *rq1, struct rq *rq2)
        __acquires(rq1->lock)
        __acquires(rq2->lock)
 {
+       BUG_ON(!irqs_disabled());
        if (rq1 == rq2) {
                spin_lock(&rq1->lock);
                __acquire(rq2->lock);   /* Fake it out ;) */
@@ -1980,6 +2001,11 @@ static void double_lock_balance(struct rq *this_rq, struct rq *busiest)
        __acquires(busiest->lock)
        __acquires(this_rq->lock)
 {
+       if (unlikely(!irqs_disabled())) {
+               /* printk() doesn't work good under rq->lock */
+               spin_unlock(&this_rq->lock);
+               BUG_ON(1);
+       }
        if (unlikely(!spin_trylock(&busiest->lock))) {
                if (busiest < this_rq) {
                        spin_unlock(&this_rq->lock);
@@ -2050,8 +2076,8 @@ static void pull_task(struct rq *src_rq, struct prio_array *src_array,
        set_task_cpu(p, this_cpu);
        inc_nr_running(p, this_rq);
        enqueue_task(p, this_array);
-       p->timestamp = (p->timestamp - src_rq->timestamp_last_tick)
-                               + this_rq->timestamp_last_tick;
+       p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
+                               + this_rq->most_recent_timestamp;
        /*
         * Note that idle threads have a prio of MAX_PRIO, for this test
         * to be always true for them.
@@ -2087,10 +2113,15 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
         * 2) too many balance attempts have failed.
         */
 
-       if (sd->nr_balance_failed > sd->cache_nice_tries)
+       if (sd->nr_balance_failed > sd->cache_nice_tries) {
+#ifdef CONFIG_SCHEDSTATS
+               if (task_hot(p, rq->most_recent_timestamp, sd))
+                       schedstat_inc(sd, lb_hot_gained[idle]);
+#endif
                return 1;
+       }
 
-       if (task_hot(p, rq->timestamp_last_tick, sd))
+       if (task_hot(p, rq->most_recent_timestamp, sd))
                return 0;
        return 1;
 }
@@ -2188,11 +2219,6 @@ skip_queue:
                goto skip_bitmap;
        }
 
-#ifdef CONFIG_SCHEDSTATS
-       if (task_hot(tmp, busiest->timestamp_last_tick, sd))
-               schedstat_inc(sd, lb_hot_gained[idle]);
-#endif
-
        pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
        pulled++;
        rem_load_move -= tmp->load_weight;
@@ -2230,7 +2256,7 @@ out:
 static struct sched_group *
 find_busiest_group(struct sched_domain *sd, int this_cpu,
                   unsigned long *imbalance, enum idle_type idle, int *sd_idle,
-                  cpumask_t *cpus)
+                  cpumask_t *cpus, int *balance)
 {
        struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
        unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2259,10 +2285,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                unsigned long load, group_capacity;
                int local_group;
                int i;
+               unsigned int balance_cpu = -1, first_idle_cpu = 0;
                unsigned long sum_nr_running, sum_weighted_load;
 
                local_group = cpu_isset(this_cpu, group->cpumask);
 
+               if (local_group)
+                       balance_cpu = first_cpu(group->cpumask);
+
                /* Tally up the load of all CPUs in the group */
                sum_weighted_load = sum_nr_running = avg_load = 0;
 
@@ -2278,9 +2308,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                                *sd_idle = 0;
 
                        /* Bias balancing toward cpus of our domain */
-                       if (local_group)
+                       if (local_group) {
+                               if (idle_cpu(i) && !first_idle_cpu) {
+                                       first_idle_cpu = 1;
+                                       balance_cpu = i;
+                               }
+
                                load = target_load(i, load_idx);
-                       else
+                       else
                                load = source_load(i, load_idx);
 
                        avg_load += load;
@@ -2288,6 +2323,16 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                        sum_weighted_load += rq->raw_weighted_load;
                }
 
+               /*
+                * First idle cpu or the first cpu(busiest) in this sched group
+                * is eligible for doing load balancing at this and above
+                * domains.
+                */
+               if (local_group && balance_cpu != this_cpu && balance) {
+                       *balance = 0;
+                       goto ret;
+               }
+
                total_load += avg_load;
                total_pwr += group->cpu_power;
 
@@ -2447,18 +2492,21 @@ small_imbalance:
                pwr_now /= SCHED_LOAD_SCALE;
 
                /* Amount of load we'd subtract */
-               tmp = busiest_load_per_task*SCHED_LOAD_SCALE/busiest->cpu_power;
+               tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
+                       busiest->cpu_power;
                if (max_load > tmp)
                        pwr_move += busiest->cpu_power *
                                min(busiest_load_per_task, max_load - tmp);
 
                /* Amount of load we'd add */
-               if (max_load*busiest->cpu_power <
-                               busiest_load_per_task*SCHED_LOAD_SCALE)
-                       tmp = max_load*busiest->cpu_power/this->cpu_power;
+               if (max_load * busiest->cpu_power <
+                               busiest_load_per_task * SCHED_LOAD_SCALE)
+                       tmp = max_load * busiest->cpu_power / this->cpu_power;
                else
-                       tmp = busiest_load_per_task*SCHED_LOAD_SCALE/this->cpu_power;
-               pwr_move += this->cpu_power*min(this_load_per_task, this_load + tmp);
+                       tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
+                               this->cpu_power;
+               pwr_move += this->cpu_power *
+                       min(this_load_per_task, this_load + tmp);
                pwr_move /= SCHED_LOAD_SCALE;
 
                /* Move if we gain throughput */
@@ -2479,8 +2527,8 @@ out_balanced:
                *imbalance = min_load_per_task;
                return group_min;
        }
-ret:
 #endif
+ret:
        *imbalance = 0;
        return NULL;
 }
@@ -2529,17 +2577,17 @@ static inline unsigned long minus_1_or_zero(unsigned long n)
 /*
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
  * tasks if there is an imbalance.
- *
- * Called with this_rq unlocked.
  */
 static int load_balance(int this_cpu, struct rq *this_rq,
-                       struct sched_domain *sd, enum idle_type idle)
+                       struct sched_domain *sd, enum idle_type idle,
+                       int *balance)
 {
        int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
        struct sched_group *group;
        unsigned long imbalance;
        struct rq *busiest;
        cpumask_t cpus = CPU_MASK_ALL;
+       unsigned long flags;
 
        /*
         * When power savings policy is enabled for the parent domain, idle
@@ -2555,7 +2603,11 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 
 redo:
        group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
-                                                       &cpus);
+                                  &cpus, balance);
+
+       if (*balance == 0)
+               goto out_balanced;
+
        if (!group) {
                schedstat_inc(sd, lb_nobusyg[idle]);
                goto out_balanced;
@@ -2579,11 +2631,13 @@ redo:
                 * still unbalanced. nr_moved simply stays zero, so it is
                 * correctly treated as an imbalance.
                 */
+               local_irq_save(flags);
                double_rq_lock(this_rq, busiest);
                nr_moved = move_tasks(this_rq, this_cpu, busiest,
                                      minus_1_or_zero(busiest->nr_running),
                                      imbalance, sd, idle, &all_pinned);
                double_rq_unlock(this_rq, busiest);
+               local_irq_restore(flags);
 
                /* All tasks on this runqueue were pinned by CPU affinity */
                if (unlikely(all_pinned)) {
@@ -2600,13 +2654,13 @@ redo:
 
                if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
 
-                       spin_lock(&busiest->lock);
+                       spin_lock_irqsave(&busiest->lock, flags);
 
                        /* don't kick the migration_thread, if the curr
                         * task on busiest cpu can't be moved to this_cpu
                         */
                        if (!cpu_isset(this_cpu, busiest->curr->cpus_allowed)) {
-                               spin_unlock(&busiest->lock);
+                               spin_unlock_irqrestore(&busiest->lock, flags);
                                all_pinned = 1;
                                goto out_one_pinned;
                        }
@@ -2616,7 +2670,7 @@ redo:
                                busiest->push_cpu = this_cpu;
                                active_balance = 1;
                        }
-                       spin_unlock(&busiest->lock);
+                       spin_unlock_irqrestore(&busiest->lock, flags);
                        if (active_balance)
                                wake_up_process(busiest->migration_thread);
 
@@ -2695,7 +2749,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
        schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
 redo:
        group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
-                               &sd_idle, &cpus);
+                                  &sd_idle, &cpus, NULL);
        if (!group) {
                schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
                goto out_balanced;
@@ -2755,14 +2809,28 @@ out_balanced:
 static void idle_balance(int this_cpu, struct rq *this_rq)
 {
        struct sched_domain *sd;
+       int pulled_task = 0;
+       unsigned long next_balance = jiffies + 60 *  HZ;
 
        for_each_domain(this_cpu, sd) {
                if (sd->flags & SD_BALANCE_NEWIDLE) {
                        /* If we've pulled tasks over stop searching: */
-                       if (load_balance_newidle(this_cpu, this_rq, sd))
+                       pulled_task = load_balance_newidle(this_cpu,
+                                                       this_rq, sd);
+                       if (time_after(next_balance,
+                                 sd->last_balance + sd->balance_interval))
+                               next_balance = sd->last_balance
+                                               + sd->balance_interval;
+                       if (pulled_task)
                                break;
                }
        }
+       if (!pulled_task)
+               /*
+                * We are going idle. next_balance may be set based on
+                * a busy processor. So reset next_balance.
+                */
+               this_rq->next_balance = next_balance;
 }
 
 /*
@@ -2815,26 +2883,9 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
        spin_unlock(&target_rq->lock);
 }
 
-/*
- * rebalance_tick will get called every timer tick, on every CPU.
- *
- * It checks each scheduling domain to see if it is due to be balanced,
- * and initiates a balancing operation if so.
- *
- * Balancing parameters are set up in arch_init_sched_domains.
- */
-
-/* Don't have all balancing operations going off at once: */
-static inline unsigned long cpu_offset(int cpu)
+static void update_load(struct rq *this_rq)
 {
-       return jiffies + cpu * HZ / NR_CPUS;
-}
-
-static void
-rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
-{
-       unsigned long this_load, interval, j = cpu_offset(this_cpu);
-       struct sched_domain *sd;
+       unsigned long this_load;
        int i, scale;
 
        this_load = this_rq->raw_weighted_load;
@@ -2854,6 +2905,32 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
                        new_load += scale-1;
                this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
        }
+}
+
+/*
+ * run_rebalance_domains is triggered when needed from the scheduler tick.
+ *
+ * It checks each scheduling domain to see if it is due to be balanced,
+ * and initiates a balancing operation if so.
+ *
+ * Balancing parameters are set up in arch_init_sched_domains.
+ */
+static DEFINE_SPINLOCK(balancing);
+
+static void run_rebalance_domains(struct softirq_action *h)
+{
+       int this_cpu = smp_processor_id(), balance = 1;
+       struct rq *this_rq = cpu_rq(this_cpu);
+       unsigned long interval;
+       struct sched_domain *sd;
+       /*
+        * We are idle if there are no processes running. This
+        * is valid even if we are the idle process (SMT).
+        */
+       enum idle_type idle = !this_rq->nr_running ?
+                               SCHED_IDLE : NOT_IDLE;
+       /* Earliest time when we have to call run_rebalance_domains again */
+       unsigned long next_balance = jiffies + 60*HZ;
 
        for_each_domain(this_cpu, sd) {
                if (!(sd->flags & SD_LOAD_BALANCE))
@@ -2868,8 +2945,13 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
                if (unlikely(!interval))
                        interval = 1;
 
-               if (j - sd->last_balance >= interval) {
-                       if (load_balance(this_cpu, this_rq, sd, idle)) {
+               if (sd->flags & SD_SERIALIZE) {
+                       if (!spin_trylock(&balancing))
+                               goto out;
+               }
+
+               if (time_after_eq(jiffies, sd->last_balance + interval)) {
+                       if (load_balance(this_cpu, this_rq, sd, idle, &balance)) {
                                /*
                                 * We've pulled tasks over so either we're no
                                 * longer idle, or one of our SMT siblings is
@@ -2877,39 +2959,48 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
                                 */
                                idle = NOT_IDLE;
                        }
-                       sd->last_balance += interval;
+                       sd->last_balance = jiffies;
                }
+               if (sd->flags & SD_SERIALIZE)
+                       spin_unlock(&balancing);
+out:
+               if (time_after(next_balance, sd->last_balance + interval))
+                       next_balance = sd->last_balance + interval;
+
+               /*
+                * Stop the load balance at this level. There is another
+                * CPU in our sched group which is doing load balancing more
+                * actively.
+                */
+               if (!balance)
+                       break;
        }
+       this_rq->next_balance = next_balance;
 }
 #else
 /*
  * on UP we do not need to balance between CPUs:
  */
-static inline void rebalance_tick(int cpu, struct rq *rq, enum idle_type idle)
-{
-}
 static inline void idle_balance(int cpu, struct rq *rq)
 {
 }
 #endif
 
-static inline int wake_priority_sleeper(struct rq *rq)
+static inline void wake_priority_sleeper(struct rq *rq)
 {
-       int ret = 0;
-
 #ifdef CONFIG_SCHED_SMT
+       if (!rq->nr_running)
+               return;
+
        spin_lock(&rq->lock);
        /*
         * If an SMT sibling task has been put to sleep for priority
         * reasons reschedule the idle task to see if it can now run.
         */
-       if (rq->nr_running) {
+       if (rq->nr_running)
                resched_task(rq->idle);
-               ret = 1;
-       }
        spin_unlock(&rq->lock);
 #endif
-       return ret;
 }
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -2923,7 +3014,8 @@ EXPORT_PER_CPU_SYMBOL(kstat);
 static inline void
 update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
 {
-       p->sched_time += now - max(p->timestamp, rq->timestamp_last_tick);
+       p->sched_time += now - p->last_ran;
+       p->last_ran = rq->most_recent_timestamp = now;
 }
 
 /*
@@ -2936,8 +3028,7 @@ unsigned long long current_sched_time(const struct task_struct *p)
        unsigned long flags;
 
        local_irq_save(flags);
-       ns = max(p->timestamp, task_rq(p)->timestamp_last_tick);
-       ns = p->sched_time + sched_clock() - ns;
+       ns = p->sched_time + sched_clock() - p->last_ran;
        local_irq_restore(flags);
 
        return ns;
@@ -3037,35 +3128,12 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
                cpustat->steal = cputime64_add(cpustat->steal, tmp);
 }
 
-/*
- * This function gets called by the timer code, with HZ frequency.
- * We call it with interrupts disabled.
- *
- * It also gets called by the fork code, when changing the parent's
- * timeslices.
- */
-void scheduler_tick(void)
+static void task_running_tick(struct rq *rq, struct task_struct *p)
 {
-       unsigned long long now = sched_clock();
-       struct task_struct *p = current;
-       int cpu = smp_processor_id();
-       struct rq *rq = cpu_rq(cpu);
-
-       update_cpu_clock(p, rq, now);
-
-       rq->timestamp_last_tick = now;
-
-       if (p == rq->idle) {
-               if (wake_priority_sleeper(rq))
-                       goto out;
-               rebalance_tick(cpu, rq, SCHED_IDLE);
-               return;
-       }
-
-       /* Task might have expired already, but not scheduled off yet */
        if (p->array != rq->active) {
+               /* Task has expired but was not scheduled yet */
                set_tsk_need_resched(p);
-               goto out;
+               return;
        }
        spin_lock(&rq->lock);
        /*
@@ -3133,8 +3201,34 @@ void scheduler_tick(void)
        }
 out_unlock:
        spin_unlock(&rq->lock);
-out:
-       rebalance_tick(cpu, rq, NOT_IDLE);
+}
+
+/*
+ * This function gets called by the timer code, with HZ frequency.
+ * We call it with interrupts disabled.
+ *
+ * It also gets called by the fork code, when changing the parent's
+ * timeslices.
+ */
+void scheduler_tick(void)
+{
+       unsigned long long now = sched_clock();
+       struct task_struct *p = current;
+       int cpu = smp_processor_id();
+       struct rq *rq = cpu_rq(cpu);
+
+       update_cpu_clock(p, rq, now);
+
+       if (p == rq->idle)
+               /* Task on the idle queue */
+               wake_priority_sleeper(rq);
+       else
+               task_running_tick(rq, p);
+#ifdef CONFIG_SMP
+       update_load(rq);
+       if (time_after_eq(jiffies, rq->next_balance))
+               raise_softirq(SCHED_SOFTIRQ);
+#endif
 }
 
 #ifdef CONFIG_SCHED_SMT
@@ -3280,7 +3374,8 @@ void fastcall add_preempt_count(int val)
        /*
         * Spinlock count overflowing soon?
         */
-       DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= PREEMPT_MASK-10);
+       DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
+                               PREEMPT_MASK - 10);
 }
 EXPORT_SYMBOL(add_preempt_count);
 
@@ -3333,6 +3428,7 @@ asmlinkage void __sched schedule(void)
                printk(KERN_ERR "BUG: scheduling while atomic: "
                        "%s/0x%08x/%d\n",
                        current->comm, preempt_count(), current->pid);
+               debug_show_held_locks(current);
                dump_stack();
        }
        profile_hit(SCHED_PROFILING, __builtin_return_address(0));
@@ -4804,18 +4900,18 @@ static void show_task(struct task_struct *p)
                show_stack(p, NULL);
 }
 
-void show_state(void)
+void show_state_filter(unsigned long state_filter)
 {
        struct task_struct *g, *p;
 
 #if (BITS_PER_LONG == 32)
        printk("\n"
-              "                                               sibling\n");
-       printk("  task             PC      pid father child younger older\n");
+              "                         free                        sibling\n");
+       printk("  task             PC    stack   pid father child younger older\n");
 #else
        printk("\n"
-              "                                                       sibling\n");
-       printk("  task                 PC          pid father child younger older\n");
+              "                                 free                        sibling\n");
+       printk("  task                 PC        stack   pid father child younger older\n");
 #endif
        read_lock(&tasklist_lock);
        do_each_thread(g, p) {
@@ -4824,11 +4920,16 @@ void show_state(void)
                 * console might take alot of time:
                 */
                touch_nmi_watchdog();
-               show_task(p);
+               if (p->state & state_filter)
+                       show_task(p);
        } while_each_thread(g, p);
 
        read_unlock(&tasklist_lock);
-       debug_show_all_locks();
+       /*
+        * Only show locks if all tasks are dumped:
+        */
+       if (state_filter == -1)
+               debug_show_all_locks();
 }
 
 /**
@@ -4973,8 +5074,8 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
                 * afterwards, and pretending it was a local activate.
                 * This way is cleaner and logically correct.
                 */
-               p->timestamp = p->timestamp - rq_src->timestamp_last_tick
-                               + rq_dest->timestamp_last_tick;
+               p->timestamp = p->timestamp - rq_src->most_recent_timestamp
+                               + rq_dest->most_recent_timestamp;
                deactivate_task(p, rq_src);
                __activate_task(p, rq_dest);
                if (TASK_PREEMPTS_CURR(p, rq_dest))
@@ -5050,7 +5151,10 @@ wait_to_die:
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* Figure out where task on dead CPU should go, use force if neccessary. */
+/*
+ * Figure out where task on dead CPU should go, use force if neccessary.
+ * NOTE: interrupts should be disabled by the caller
+ */
 static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
 {
        unsigned long flags;
@@ -5170,6 +5274,7 @@ void idle_task_exit(void)
        mmdrop(mm);
 }
 
+/* called under rq->lock with disabled interrupts */
 static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
 {
        struct rq *rq = cpu_rq(dead_cpu);
@@ -5186,10 +5291,11 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
         * Drop lock around migration; if someone else moves it,
         * that's OK.  No task can be added to this CPU, so iteration is
         * fine.
+        * NOTE: interrupts should be left disabled  --dev@
         */
-       spin_unlock_irq(&rq->lock);
+       spin_unlock(&rq->lock);
        move_task_off_dead_cpu(dead_cpu, p);
-       spin_lock_irq(&rq->lock);
+       spin_lock(&rq->lock);
 
        put_task_struct(p);
 }
@@ -5342,16 +5448,19 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
                if (!(sd->flags & SD_LOAD_BALANCE)) {
                        printk("does not load-balance\n");
                        if (sd->parent)
-                               printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain has parent");
+                               printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain"
+                                               " has parent");
                        break;
                }
 
                printk("span %s\n", str);
 
                if (!cpu_isset(cpu, sd->span))
-                       printk(KERN_ERR "ERROR: domain->span does not contain CPU%d\n", cpu);
+                       printk(KERN_ERR "ERROR: domain->span does not contain "
+                                       "CPU%d\n", cpu);
                if (!cpu_isset(cpu, group->cpumask))
-                       printk(KERN_ERR "ERROR: domain->groups does not contain CPU%d\n", cpu);
+                       printk(KERN_ERR "ERROR: domain->groups does not contain"
+                                       " CPU%d\n", cpu);
 
                printk(KERN_DEBUG);
                for (i = 0; i < level + 2; i++)
@@ -5366,7 +5475,8 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
 
                        if (!group->cpu_power) {
                                printk("\n");
-                               printk(KERN_ERR "ERROR: domain->cpu_power not set\n");
+                               printk(KERN_ERR "ERROR: domain->cpu_power not "
+                                               "set\n");
                        }
 
                        if (!cpus_weight(group->cpumask)) {
@@ -5389,15 +5499,17 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
                printk("\n");
 
                if (!cpus_equal(sd->span, groupmask))
-                       printk(KERN_ERR "ERROR: groups don't span domain->span\n");
+                       printk(KERN_ERR "ERROR: groups don't span "
+                                       "domain->span\n");
 
                level++;
                sd = sd->parent;
+               if (!sd)
+                       continue;
 
-               if (sd) {
-                       if (!cpus_subset(groupmask, sd->span))
-                               printk(KERN_ERR "ERROR: parent span is not a superset of domain->span\n");
-               }
+               if (!cpus_subset(groupmask, sd->span))
+                       printk(KERN_ERR "ERROR: parent span is not a superset "
+                               "of domain->span\n");
 
        } while (sd);
 }
@@ -5511,28 +5623,27 @@ static int __init isolated_cpu_setup(char *str)
 __setup ("isolcpus=", isolated_cpu_setup);
 
 /*
- * init_sched_build_groups takes an array of groups, the cpumask we wish
- * to span, and a pointer to a function which identifies what group a CPU
- * belongs to. The return value of group_fn must be a valid index into the
- * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we
- * keep track of groups covered with a cpumask_t).
+ * init_sched_build_groups takes the cpumask we wish to span, and a pointer
+ * to a function which identifies what group(along with sched group) a CPU
+ * belongs to. The return value of group_fn must be a >= 0 and < NR_CPUS
+ * (due to the fact that we keep track of groups covered with a cpumask_t).
  *
  * init_sched_build_groups will build a circular linked list of the groups
  * covered by the given span, and will set each group's ->cpumask correctly,
  * and ->cpu_power to 0.
  */
 static void
-init_sched_build_groups(struct sched_group groups[], cpumask_t span,
-                       const cpumask_t *cpu_map,
-                       int (*group_fn)(int cpu, const cpumask_t *cpu_map))
+init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
+                       int (*group_fn)(int cpu, const cpumask_t *cpu_map,
+                                       struct sched_group **sg))
 {
        struct sched_group *first = NULL, *last = NULL;
        cpumask_t covered = CPU_MASK_NONE;
        int i;
 
        for_each_cpu_mask(i, span) {
-               int group = group_fn(i, cpu_map);
-               struct sched_group *sg = &groups[group];
+               struct sched_group *sg;
+               int group = group_fn(i, cpu_map, &sg);
                int j;
 
                if (cpu_isset(i, covered))
@@ -5542,7 +5653,7 @@ init_sched_build_groups(struct sched_group groups[], cpumask_t span,
                sg->cpu_power = 0;
 
                for_each_cpu_mask(j, span) {
-                       if (group_fn(j, cpu_map) != group)
+                       if (group_fn(j, cpu_map, NULL) != group)
                                continue;
 
                        cpu_set(j, covered);
@@ -5716,8 +5827,9 @@ __setup("max_cache_size=", setup_max_cache_size);
  */
 static void touch_cache(void *__cache, unsigned long __size)
 {
-       unsigned long size = __size/sizeof(long), chunk1 = size/3,
-                       chunk2 = 2*size/3;
+       unsigned long size = __size / sizeof(long);
+       unsigned long chunk1 = size / 3;
+       unsigned long chunk2 = 2 * size / 3;
        unsigned long *cache = __cache;
        int i;
 
@@ -5826,11 +5938,11 @@ measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
         */
        measure_one(cache, size, cpu1, cpu2);
        for (i = 0; i < ITERATIONS; i++)
-               cost1 += measure_one(cache, size - i*1024, cpu1, cpu2);
+               cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
 
        measure_one(cache, size, cpu2, cpu1);
        for (i = 0; i < ITERATIONS; i++)
-               cost1 += measure_one(cache, size - i*1024, cpu2, cpu1);
+               cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
 
        /*
         * (We measure the non-migrating [cached] cost on both
@@ -5840,17 +5952,17 @@ measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
 
        measure_one(cache, size, cpu1, cpu1);
        for (i = 0; i < ITERATIONS; i++)
-               cost2 += measure_one(cache, size - i*1024, cpu1, cpu1);
+               cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
 
        measure_one(cache, size, cpu2, cpu2);
        for (i = 0; i < ITERATIONS; i++)
-               cost2 += measure_one(cache, size - i*1024, cpu2, cpu2);
+               cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
 
        /*
         * Get the per-iteration migration cost:
         */
-       do_div(cost1, 2*ITERATIONS);
-       do_div(cost2, 2*ITERATIONS);
+       do_div(cost1, 2 * ITERATIONS);
+       do_div(cost2, 2 * ITERATIONS);
 
        return cost1 - cost2;
 }
@@ -5888,7 +6000,7 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2)
         */
        cache = vmalloc(max_size);
        if (!cache) {
-               printk("could not vmalloc %d bytes for cache!\n", 2*max_size);
+               printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
                return 1000000; /* return 1 msec on very small boxen */
        }
 
@@ -5913,7 +6025,8 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2)
                avg_fluct = (avg_fluct + fluct)/2;
 
                if (migration_debug)
-                       printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): (%8Ld %8Ld)\n",
+                       printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
+                               "(%8Ld %8Ld)\n",
                                cpu1, cpu2, size,
                                (long)cost / 1000000,
                                ((long)cost / 100000) % 10,
@@ -6008,20 +6121,18 @@ static void calibrate_migration_costs(const cpumask_t *cpu_map)
                        -1
 #endif
                );
-       if (system_state == SYSTEM_BOOTING) {
-               if (num_online_cpus() > 1) {
-                       printk("migration_cost=");
-                       for (distance = 0; distance <= max_distance; distance++) {
-                               if (distance)
-                                       printk(",");
-                               printk("%ld", (long)migration_cost[distance] / 1000);
-                       }
-                       printk("\n");
+       if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
+               printk("migration_cost=");
+               for (distance = 0; distance <= max_distance; distance++) {
+                       if (distance)
+                               printk(",");
+                       printk("%ld", (long)migration_cost[distance] / 1000);
                }
+               printk("\n");
        }
        j1 = jiffies;
        if (migration_debug)
-               printk("migration: %ld seconds\n", (j1-j0)/HZ);
+               printk("migration: %ld seconds\n", (j1-j0) / HZ);
 
        /*
         * Move back to the original CPU. NUMA-Q gets confused
@@ -6118,10 +6229,13 @@ int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
  */
 #ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static struct sched_group sched_group_cpus[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_cpus);
 
-static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map,
+                           struct sched_group **sg)
 {
+       if (sg)
+               *sg = &per_cpu(sched_group_cpus, cpu);
        return cpu;
 }
 #endif
@@ -6131,39 +6245,52 @@ static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map)
  */
 #ifdef CONFIG_SCHED_MC
 static DEFINE_PER_CPU(struct sched_domain, core_domains);
-static struct sched_group sched_group_core[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_core);
 #endif
 
 #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
-static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map,
+                            struct sched_group **sg)
 {
+       int group;
        cpumask_t mask = cpu_sibling_map[cpu];
        cpus_and(mask, mask, *cpu_map);
-       return first_cpu(mask);
+       group = first_cpu(mask);
+       if (sg)
+               *sg = &per_cpu(sched_group_core, group);
+       return group;
 }
 #elif defined(CONFIG_SCHED_MC)
-static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map,
+                            struct sched_group **sg)
 {
+       if (sg)
+               *sg = &per_cpu(sched_group_core, cpu);
        return cpu;
 }
 #endif
 
 static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static struct sched_group sched_group_phys[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_phys);
 
-static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map,
+                            struct sched_group **sg)
 {
+       int group;
 #ifdef CONFIG_SCHED_MC
        cpumask_t mask = cpu_coregroup_map(cpu);
        cpus_and(mask, mask, *cpu_map);
-       return first_cpu(mask);
+       group = first_cpu(mask);
 #elif defined(CONFIG_SCHED_SMT)
        cpumask_t mask = cpu_sibling_map[cpu];
        cpus_and(mask, mask, *cpu_map);
-       return first_cpu(mask);
+       group = first_cpu(mask);
 #else
-       return cpu;
+       group = cpu;
 #endif
+       if (sg)
+               *sg = &per_cpu(sched_group_phys, group);
+       return group;
 }
 
 #ifdef CONFIG_NUMA
@@ -6176,12 +6303,22 @@ static DEFINE_PER_CPU(struct sched_domain, node_domains);
 static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
 
 static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
-static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_allnodes);
 
-static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map,
+                                struct sched_group **sg)
 {
-       return cpu_to_node(cpu);
+       cpumask_t nodemask = node_to_cpumask(cpu_to_node(cpu));
+       int group;
+
+       cpus_and(nodemask, nodemask, *cpu_map);
+       group = first_cpu(nodemask);
+
+       if (sg)
+               *sg = &per_cpu(sched_group_allnodes, group);
+       return group;
 }
+
 static void init_numa_sched_groups_power(struct sched_group *group_head)
 {
        struct sched_group *sg = group_head;
@@ -6217,16 +6354,9 @@ static void free_sched_groups(const cpumask_t *cpu_map)
        int cpu, i;
 
        for_each_cpu_mask(cpu, *cpu_map) {
-               struct sched_group *sched_group_allnodes
-                       = sched_group_allnodes_bycpu[cpu];
                struct sched_group **sched_group_nodes
                        = sched_group_nodes_bycpu[cpu];
 
-               if (sched_group_allnodes) {
-                       kfree(sched_group_allnodes);
-                       sched_group_allnodes_bycpu[cpu] = NULL;
-               }
-
                if (!sched_group_nodes)
                        continue;
 
@@ -6320,7 +6450,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
        struct sched_domain *sd;
 #ifdef CONFIG_NUMA
        struct sched_group **sched_group_nodes = NULL;
-       struct sched_group *sched_group_allnodes = NULL;
+       int sd_allnodes = 0;
 
        /*
         * Allocate the per-node list of sched groups
@@ -6338,7 +6468,6 @@ static int build_sched_domains(const cpumask_t *cpu_map)
         * Set up domains for cpus specified by the cpu_map.
         */
        for_each_cpu_mask(i, *cpu_map) {
-               int group;
                struct sched_domain *sd = NULL, *p;
                cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
 
@@ -6347,26 +6476,12 @@ static int build_sched_domains(const cpumask_t *cpu_map)
 #ifdef CONFIG_NUMA
                if (cpus_weight(*cpu_map)
                                > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
-                       if (!sched_group_allnodes) {
-                               sched_group_allnodes
-                                       = kmalloc_node(sizeof(struct sched_group)
-                                                       * MAX_NUMNODES,
-                                                 GFP_KERNEL,
-                                                 cpu_to_node(i));
-                               if (!sched_group_allnodes) {
-                                       printk(KERN_WARNING
-                                       "Can not alloc allnodes sched group\n");
-                                       goto error;
-                               }
-                               sched_group_allnodes_bycpu[i]
-                                               = sched_group_allnodes;
-                       }
                        sd = &per_cpu(allnodes_domains, i);
                        *sd = SD_ALLNODES_INIT;
                        sd->span = *cpu_map;
-                       group = cpu_to_allnodes_group(i, cpu_map);
-                       sd->groups = &sched_group_allnodes[group];
+                       cpu_to_allnodes_group(i, cpu_map, &sd->groups);
                        p = sd;
+                       sd_allnodes = 1;
                } else
                        p = NULL;
 
@@ -6381,36 +6496,33 @@ static int build_sched_domains(const cpumask_t *cpu_map)
 
                p = sd;
                sd = &per_cpu(phys_domains, i);
-               group = cpu_to_phys_group(i, cpu_map);
                *sd = SD_CPU_INIT;
                sd->span = nodemask;
                sd->parent = p;
                if (p)
                        p->child = sd;
-               sd->groups = &sched_group_phys[group];
+               cpu_to_phys_group(i, cpu_map, &sd->groups);
 
 #ifdef CONFIG_SCHED_MC
                p = sd;
                sd = &per_cpu(core_domains, i);
-               group = cpu_to_core_group(i, cpu_map);
                *sd = SD_MC_INIT;
                sd->span = cpu_coregroup_map(i);
                cpus_and(sd->span, sd->span, *cpu_map);
                sd->parent = p;
                p->child = sd;
-               sd->groups = &sched_group_core[group];
+               cpu_to_core_group(i, cpu_map, &sd->groups);
 #endif
 
 #ifdef CONFIG_SCHED_SMT
                p = sd;
                sd = &per_cpu(cpu_domains, i);
-               group = cpu_to_cpu_group(i, cpu_map);
                *sd = SD_SIBLING_INIT;
                sd->span = cpu_sibling_map[i];
                cpus_and(sd->span, sd->span, *cpu_map);
                sd->parent = p;
                p->child = sd;
-               sd->groups = &sched_group_cpus[group];
+               cpu_to_cpu_group(i, cpu_map, &sd->groups);
 #endif
        }
 
@@ -6422,8 +6534,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
                if (i != first_cpu(this_sibling_map))
                        continue;
 
-               init_sched_build_groups(sched_group_cpus, this_sibling_map,
-                                       cpu_map, &cpu_to_cpu_group);
+               init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
        }
 #endif
 
@@ -6434,8 +6545,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
                cpus_and(this_core_map, this_core_map, *cpu_map);
                if (i != first_cpu(this_core_map))
                        continue;
-               init_sched_build_groups(sched_group_core, this_core_map,
-                                       cpu_map, &cpu_to_core_group);
+               init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
        }
 #endif
 
@@ -6448,15 +6558,13 @@ static int build_sched_domains(const cpumask_t *cpu_map)
                if (cpus_empty(nodemask))
                        continue;
 
-               init_sched_build_groups(sched_group_phys, nodemask,
-                                       cpu_map, &cpu_to_phys_group);
+               init_sched_build_groups(nodemask, cpu_map, &cpu_to_phys_group);
        }
 
 #ifdef CONFIG_NUMA
        /* Set up node groups */
-       if (sched_group_allnodes)
-               init_sched_build_groups(sched_group_allnodes, *cpu_map,
-                                       cpu_map, &cpu_to_allnodes_group);
+       if (sd_allnodes)
+               init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
 
        for (i = 0; i < MAX_NUMNODES; i++) {
                /* Set up node groups */
@@ -6548,10 +6656,10 @@ static int build_sched_domains(const cpumask_t *cpu_map)
        for (i = 0; i < MAX_NUMNODES; i++)
                init_numa_sched_groups_power(sched_group_nodes[i]);
 
-       if (sched_group_allnodes) {
-               int group = cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map);
-               struct sched_group *sg = &sched_group_allnodes[group];
+       if (sd_allnodes) {
+               struct sched_group *sg;
 
+               cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg);
                init_numa_sched_groups_power(sg);
        }
 #endif
@@ -6723,8 +6831,6 @@ SYSDEV_ATTR(sched_smt_power_savings, 0644, sched_smt_power_savings_show,
            sched_smt_power_savings_store);
 #endif
 
-
-#ifdef CONFIG_HOTPLUG_CPU
 /*
  * Force a reinitialization of the sched domains hierarchy.  The domains
  * and groups cannot be updated in place without racing with the balancing
@@ -6757,7 +6863,6 @@ static int update_sched_domains(struct notifier_block *nfb,
 
        return NOTIFY_OK;
 }
-#endif
 
 void __init sched_init_smp(void)
 {
@@ -6833,6 +6938,10 @@ void __init sched_init(void)
 
        set_load_weight(&init_task);
 
+#ifdef CONFIG_SMP
+       open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL);
+#endif
+
 #ifdef CONFIG_RT_MUTEXES
        plist_head_init(&init_task.pi_waiters, &init_task.pi_lock);
 #endif
@@ -6867,6 +6976,7 @@ void __might_sleep(char *file, int line)
                                " context at %s:%d\n", file, line);
                printk("in_atomic():%d, irqs_disabled():%d\n",
                        in_atomic(), irqs_disabled());
+               debug_show_held_locks(current);
                dump_stack();
        }
 #endif
index df18c16..1921ffd 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/capability.h>
+#include <linux/freezer.h>
+#include <linux/pid_namespace.h>
+#include <linux/nsproxy.h>
+
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -33,7 +37,7 @@
  * SLAB caches for signal bits.
  */
 
-static kmem_cache_t *sigqueue_cachep;
+static struct kmem_cache *sigqueue_cachep;
 
 /*
  * In POSIX a signal is sent either to a specific thread (Linux task)
@@ -582,7 +586,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
        error = -EPERM;
        if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
            && ((sig != SIGCONT) ||
-               (current->signal->session != t->signal->session))
+               (process_session(current) != process_session(t)))
            && (current->euid ^ t->suid) && (current->euid ^ t->uid)
            && (current->uid ^ t->suid) && (current->uid ^ t->uid)
            && !capable(CAP_KILL))
@@ -1133,8 +1137,7 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
        return error;
 }
 
-int
-kill_proc_info(int sig, struct siginfo *info, pid_t pid)
+static int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
 {
        int error;
        rcu_read_lock();
@@ -1877,8 +1880,12 @@ relock:
                if (sig_kernel_ignore(signr)) /* Default is nothing. */
                        continue;
 
-               /* Init gets no signals it doesn't want.  */
-               if (current == child_reaper)
+               /*
+                * Init of a pid space gets no signals it doesn't want from
+                * within that pid space. It can of course get signals from
+                * its parent pid space.
+                */
+               if (current == child_reaper(current))
                        continue;
 
                if (sig_kernel_stop(signr)) {
index bf25015..918e52d 100644 (file)
@@ -574,8 +574,6 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
-               BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
-               BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
                p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
                if (IS_ERR(p)) {
                        printk("ksoftirqd for %i failed\n", hotcpu);
index 98489d8..c7675c1 100644 (file)
@@ -880,7 +880,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
        return 0;
 }
 
-static void deferred_cad(void *dummy)
+static void deferred_cad(struct work_struct *dummy)
 {
        kernel_restart(NULL);
 }
@@ -892,7 +892,7 @@ static void deferred_cad(void *dummy)
  */
 void ctrl_alt_del(void)
 {
-       static DECLARE_WORK(cad_work, deferred_cad, NULL);
+       static DECLARE_WORK(cad_work, deferred_cad);
 
        if (C_A_D)
                schedule_work(&cad_work);
@@ -1102,14 +1102,14 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 asmlinkage long sys_setuid(uid_t uid)
 {
        int old_euid = current->euid;
-       int old_ruid, old_suid, new_ruid, new_suid;
+       int old_ruid, old_suid, new_suid;
        int retval;
 
        retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
        if (retval)
                return retval;
 
-       old_ruid = new_ruid = current->uid;
+       old_ruid = current->uid;
        old_suid = current->suid;
        new_suid = old_suid;
        
@@ -1381,7 +1381,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 
        if (p->real_parent == group_leader) {
                err = -EPERM;
-               if (p->signal->session != group_leader->signal->session)
+               if (process_session(p) != process_session(group_leader))
                        goto out;
                err = -EACCES;
                if (p->did_exec)
@@ -1397,16 +1397,13 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
                goto out;
 
        if (pgid != pid) {
-               struct task_struct *p;
+               struct task_struct *g =
+                       find_task_by_pid_type(PIDTYPE_PGID, pgid);
 
-               do_each_task_pid(pgid, PIDTYPE_PGID, p) {
-                       if (p->signal->session == group_leader->signal->session)
-                               goto ok_pgid;
-               } while_each_task_pid(pgid, PIDTYPE_PGID, p);
-               goto out;
+               if (!g || process_session(g) != process_session(group_leader))
+                       goto out;
        }
 
-ok_pgid:
        err = security_task_setpgid(p, pgid);
        if (err)
                goto out;
@@ -1459,7 +1456,7 @@ asmlinkage long sys_getpgrp(void)
 asmlinkage long sys_getsid(pid_t pid)
 {
        if (!pid)
-               return current->signal->session;
+               return process_session(current);
        else {
                int retval;
                struct task_struct *p;
@@ -1471,7 +1468,7 @@ asmlinkage long sys_getsid(pid_t pid)
                if (p) {
                        retval = security_task_getsid(p);
                        if (!retval)
-                               retval = p->signal->session;
+                               retval = process_session(p);
                }
                read_unlock(&tasklist_lock);
                return retval;
@@ -1484,7 +1481,6 @@ asmlinkage long sys_setsid(void)
        pid_t session;
        int err = -EPERM;
 
-       mutex_lock(&tty_mutex);
        write_lock_irq(&tasklist_lock);
 
        /* Fail if I am already a session leader */
@@ -1504,12 +1500,15 @@ asmlinkage long sys_setsid(void)
 
        group_leader->signal->leader = 1;
        __set_special_pids(session, session);
+
+       spin_lock(&group_leader->sighand->siglock);
        group_leader->signal->tty = NULL;
        group_leader->signal->tty_old_pgrp = 0;
+       spin_unlock(&group_leader->sighand->siglock);
+
        err = process_group(group_leader);
 out:
        write_unlock_irq(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
        return err;
 }
 
index 09e569f..130c5ec 100644 (file)
@@ -54,6 +54,7 @@ extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
 
 #ifdef CONFIG_X86
 #include <asm/nmi.h>
+#include <asm/stacktrace.h>
 #endif
 
 #if defined(CONFIG_SYSCTL)
@@ -91,7 +92,9 @@ extern char modprobe_path[];
 extern int sg_big_buff;
 #endif
 #ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+               void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
                void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
@@ -130,12 +133,22 @@ extern int max_lock_depth;
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 static int parse_table(int __user *, int, void __user *, size_t __user *,
-               void __user *, size_t, ctl_table *, void **);
+               void __user *, size_t, ctl_table *);
 #endif
 
 static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
 
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen);
+
+#ifdef CONFIG_SYSVIPC
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen);
+#endif
+
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -162,6 +175,40 @@ extern ctl_table inotify_table[];
 int sysctl_legacy_va_layout;
 #endif
 
+static void *get_uts(ctl_table *table, int write)
+{
+       char *which = table->data;
+#ifdef CONFIG_UTS_NS
+       struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
+       which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
+#endif
+       if (!write)
+               down_read(&uts_sem);
+       else
+               down_write(&uts_sem);
+       return which;
+}
+
+static void put_uts(ctl_table *table, int write, void *which)
+{
+       if (!write)
+               up_read(&uts_sem);
+       else
+               up_write(&uts_sem);
+}
+
+#ifdef CONFIG_SYSVIPC
+static void *get_ipc(ctl_table *table, int write)
+{
+       char *which = table->data;
+       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+       which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
+       return which;
+}
+#else
+#define get_ipc(T,W) ((T)->data)
+#endif
+
 /* /proc declarations: */
 
 #ifdef CONFIG_PROC_SYSCTL
@@ -170,7 +217,7 @@ static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
 static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
 static int proc_opensys(struct inode *, struct file *);
 
-struct file_operations proc_sys_file_operations = {
+const struct file_operations proc_sys_file_operations = {
        .open           = proc_opensys,
        .read           = proc_readsys,
        .write          = proc_writesys,
@@ -228,7 +275,6 @@ static ctl_table root_table[] = {
 };
 
 static ctl_table kern_table[] = {
-#ifndef CONFIG_UTS_NS
        {
                .ctl_name       = KERN_OSTYPE,
                .procname       = "ostype",
@@ -236,7 +282,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof(init_uts_ns.name.sysname),
                .mode           = 0444,
                .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
+               .strategy       = &sysctl_uts_string,
        },
        {
                .ctl_name       = KERN_OSRELEASE,
@@ -245,7 +291,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof(init_uts_ns.name.release),
                .mode           = 0444,
                .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
+               .strategy       = &sysctl_uts_string,
        },
        {
                .ctl_name       = KERN_VERSION,
@@ -254,7 +300,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof(init_uts_ns.name.version),
                .mode           = 0444,
                .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
+               .strategy       = &sysctl_uts_string,
        },
        {
                .ctl_name       = KERN_NODENAME,
@@ -263,7 +309,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof(init_uts_ns.name.nodename),
                .mode           = 0644,
                .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
+               .strategy       = &sysctl_uts_string,
        },
        {
                .ctl_name       = KERN_DOMAINNAME,
@@ -272,56 +318,8 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof(init_uts_ns.name.domainname),
                .mode           = 0644,
                .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
-       },
-#else  /* !CONFIG_UTS_NS */
-       {
-               .ctl_name       = KERN_OSTYPE,
-               .procname       = "ostype",
-               .data           = NULL,
-               /* could maybe use __NEW_UTS_LEN here? */
-               .maxlen         = FIELD_SIZEOF(struct new_utsname, sysname),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
+               .strategy       = &sysctl_uts_string,
        },
-       {
-               .ctl_name       = KERN_OSRELEASE,
-               .procname       = "osrelease",
-               .data           = NULL,
-               .maxlen         = FIELD_SIZEOF(struct new_utsname, release),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_VERSION,
-               .procname       = "version",
-               .data           = NULL,
-               .maxlen         = FIELD_SIZEOF(struct new_utsname, version),
-               .mode           = 0444,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_NODENAME,
-               .procname       = "hostname",
-               .data           = NULL,
-               .maxlen         = FIELD_SIZEOF(struct new_utsname, nodename),
-               .mode           = 0644,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_DOMAINNAME,
-               .procname       = "domainname",
-               .data           = NULL,
-               .maxlen         = FIELD_SIZEOF(struct new_utsname, domainname),
-               .mode           = 0644,
-               .proc_handler   = &proc_do_uts_string,
-               .strategy       = &sysctl_string,
-       },
-#endif /* !CONFIG_UTS_NS */
        {
                .ctl_name       = KERN_PANIC,
                .procname       = "panic",
@@ -480,58 +478,65 @@ static ctl_table kern_table[] = {
        {
                .ctl_name       = KERN_SHMMAX,
                .procname       = "shmmax",
-               .data           = NULL,
-               .maxlen         = sizeof (size_t),
+               .data           = &init_ipc_ns.shm_ctlmax,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SHMALL,
                .procname       = "shmall",
-               .data           = NULL,
-               .maxlen         = sizeof (size_t),
+               .data           = &init_ipc_ns.shm_ctlall,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SHMMNI,
                .procname       = "shmmni",
-               .data           = NULL,
-               .maxlen         = sizeof (int),
+               .data           = &init_ipc_ns.shm_ctlmni,
+               .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMAX,
                .procname       = "msgmax",
-               .data           = NULL,
-               .maxlen         = sizeof (int),
+               .data           = &init_ipc_ns.msg_ctlmax,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMNI,
                .procname       = "msgmni",
-               .data           = NULL,
-               .maxlen         = sizeof (int),
+               .data           = &init_ipc_ns.msg_ctlmni,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMNB,
                .procname       =  "msgmnb",
-               .data           = NULL,
-               .maxlen         = sizeof (int),
+               .data           = &init_ipc_ns.msg_ctlmnb,
+               .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SEM,
                .procname       = "sem",
-               .data           = NULL,
+               .data           = &init_ipc_ns.sem_ctls,
                .maxlen         = 4*sizeof (int),
                .mode           = 0644,
-               .proc_handler   = &proc_do_ipc_string,
+               .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -707,6 +712,14 @@ static ctl_table kern_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "kstack_depth_to_print",
+               .data           = &kstack_depth_to_print,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
 #endif
 #if defined(CONFIG_MMU)
        {
@@ -977,17 +990,6 @@ static ctl_table vm_table[] = {
                .extra1         = &zero,
        },
 #endif
-#ifdef CONFIG_SWAP
-       {
-               .ctl_name       = VM_SWAP_TOKEN_TIMEOUT,
-               .procname       = "swap_token_timeout",
-               .data           = &swap_token_default_timeout,
-               .maxlen         = sizeof(swap_token_default_timeout),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_jiffies,
-               .strategy       = &sysctl_jiffies,
-       },
-#endif
 #ifdef CONFIG_NUMA
        {
                .ctl_name       = VM_ZONE_RECLAIM_MODE,
@@ -1241,7 +1243,6 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
        do {
                struct ctl_table_header *head =
                        list_entry(tmp, struct ctl_table_header, ctl_entry);
-               void *context = NULL;
 
                if (!use_table(head))
                        continue;
@@ -1249,9 +1250,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
                spin_unlock(&sysctl_lock);
 
                error = parse_table(name, nlen, oldval, oldlenp, 
-                                       newval, newlen, head->ctl_table,
-                                       &context);
-               kfree(context);
+                                       newval, newlen, head->ctl_table);
 
                spin_lock(&sysctl_lock);
                unuse_table(head);
@@ -1307,7 +1306,7 @@ static inline int ctl_perm(ctl_table *table, int op)
 static int parse_table(int __user *name, int nlen,
                       void __user *oldval, size_t __user *oldlenp,
                       void __user *newval, size_t newlen,
-                      ctl_table *table, void **context)
+                      ctl_table *table)
 {
        int n;
 repeat:
@@ -1327,7 +1326,7 @@ repeat:
                                        error = table->strategy(
                                                table, name, nlen,
                                                oldval, oldlenp,
-                                               newval, newlen, context);
+                                               newval, newlen);
                                        if (error)
                                                return error;
                                }
@@ -1338,7 +1337,7 @@ repeat:
                        }
                        error = do_sysctl_strategy(table, name, nlen,
                                                   oldval, oldlenp,
-                                                  newval, newlen, context);
+                                                  newval, newlen);
                        return error;
                }
        }
@@ -1349,7 +1348,7 @@ repeat:
 int do_sysctl_strategy (ctl_table *table, 
                        int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen, void **context)
+                       void __user *newval, size_t newlen)
 {
        int op = 0, rc;
        size_t len;
@@ -1363,7 +1362,7 @@ int do_sysctl_strategy (ctl_table *table,
 
        if (table->strategy) {
                rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                                    newval, newlen, context);
+                                    newval, newlen);
                if (rc < 0)
                        return rc;
                if (rc > 0)
@@ -1616,7 +1615,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
                          size_t count, loff_t *ppos)
 {
        int op;
-       struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
        struct ctl_table *table;
        size_t res;
        ssize_t error = -ENOTDIR;
@@ -1755,66 +1754,17 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
  *     Special case of dostring for the UTS structure. This has locks
  *     to observe. Should this be in kernel/sys.c ????
  */
-#ifndef CONFIG_UTS_NS
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       int r;
 
-       if (!write) {
-               down_read(&uts_sem);
-               r=proc_dostring(table,0,filp,buffer,lenp, ppos);
-               up_read(&uts_sem);
-       } else {
-               down_write(&uts_sem);
-               r=proc_dostring(table,1,filp,buffer,lenp, ppos);
-               up_write(&uts_sem);
-       }
-       return r;
-}
-#else /* !CONFIG_UTS_NS */
 static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int r;
-       struct uts_namespace* uts_ns = current->nsproxy->uts_ns;
-       char* which;
-
-       switch (table->ctl_name) {
-       case KERN_OSTYPE:
-               which = uts_ns->name.sysname;
-               break;
-       case KERN_NODENAME:
-               which = uts_ns->name.nodename;
-               break;
-       case KERN_OSRELEASE:
-               which = uts_ns->name.release;
-               break;
-       case KERN_VERSION:
-               which = uts_ns->name.version;
-               break;
-       case KERN_DOMAINNAME:
-               which = uts_ns->name.domainname;
-               break;
-       default:
-               r = -EINVAL;
-               goto out;
-       }
-
-       if (!write) {
-               down_read(&uts_sem);
-               r=_proc_do_string(which,table->maxlen,0,filp,buffer,lenp, ppos);
-               up_read(&uts_sem);
-       } else {
-               down_write(&uts_sem);
-               r=_proc_do_string(which,table->maxlen,1,filp,buffer,lenp, ppos);
-               up_write(&uts_sem);
-       }
- out:
+       void *which;
+       which = get_uts(table, write);
+       r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos);
+       put_uts(table, write, which);
        return r;
 }
-#endif /* !CONFIG_UTS_NS */
 
 static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
                                 int *valp,
@@ -1886,7 +1836,7 @@ static int __do_proc_dointvec(void *tbl_data, ctl_table *table,
                        p = buf;
                        if (*p == '-' && left > 1) {
                                neg = 1;
-                               left--, p++;
+                               p++;
                        }
                        if (*p < '0' || *p > '9')
                                break;
@@ -1978,9 +1928,6 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
 
 #define OP_SET 0
 #define OP_AND 1
-#define OP_OR  2
-#define OP_MAX 3
-#define OP_MIN 4
 
 static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                                      int *valp,
@@ -1992,13 +1939,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                switch(op) {
                case OP_SET:    *valp = val; break;
                case OP_AND:    *valp &= val; break;
-               case OP_OR:     *valp |= val; break;
-               case OP_MAX:    if(*valp < val)
-                                       *valp = val;
-                               break;
-               case OP_MIN:    if(*valp > val)
-                               *valp = val;
-                               break;
                }
        } else {
                int val = *valp;
@@ -2137,7 +2077,7 @@ static int __do_proc_doulongvec_minmax(void *data, ctl_table *table, int write,
                        p = buf;
                        if (*p == '-' && left > 1) {
                                neg = 1;
-                               left--, p++;
+                               p++;
                        }
                        if (*p < '0' || *p > '9')
                                break;
@@ -2393,46 +2333,24 @@ int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
 }
 
 #ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
-               void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       void *data;
-       struct ipc_namespace *ns;
-
-       ns = current->nsproxy->ipc_ns;
-
-       switch (table->ctl_name) {
-       case KERN_SHMMAX:
-               data = &ns->shm_ctlmax;
-               goto proc_minmax;
-       case KERN_SHMALL:
-               data = &ns->shm_ctlall;
-               goto proc_minmax;
-       case KERN_SHMMNI:
-               data = &ns->shm_ctlmni;
-               break;
-       case KERN_MSGMAX:
-               data = &ns->msg_ctlmax;
-               break;
-       case KERN_MSGMNI:
-               data = &ns->msg_ctlmni;
-               break;
-       case KERN_MSGMNB:
-               data = &ns->msg_ctlmnb;
-               break;
-       case KERN_SEM:
-               data = &ns->sem_ctls;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return __do_proc_dointvec(data, table, write, filp, buffer,
+       void *which;
+       which = get_ipc(table, write);
+       return __do_proc_dointvec(which, table, write, filp, buffer,
                        lenp, ppos, NULL, NULL);
-proc_minmax:
-       return __do_proc_doulongvec_minmax(data, table, write, filp, buffer,
+}
+
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+       struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       void *which;
+       which = get_ipc(table, write);
+       return __do_proc_doulongvec_minmax(which, table, write, filp, buffer,
                        lenp, ppos, 1l, 1l);
 }
+
 #endif
 
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
@@ -2477,6 +2395,17 @@ static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
 {
        return -ENOSYS;
 }
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+               void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+               struct file *filp, void __user *buffer,
+               size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
 #endif
 
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
@@ -2541,7 +2470,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 /* The generic string strategy routine: */
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        if (!table->data || !table->maxlen) 
                return -ENOTDIR;
@@ -2587,7 +2516,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
  */
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
 
        if (newval && newlen) {
@@ -2623,7 +2552,7 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        if (oldval) {
                size_t olen;
@@ -2651,7 +2580,7 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        if (oldval) {
                size_t olen;
@@ -2676,6 +2605,64 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return 1;
 }
 
+
+/* The generic string strategy routine: */
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen)
+{
+       struct ctl_table uts_table;
+       int r, write;
+       write = newval && newlen;
+       memcpy(&uts_table, table, sizeof(uts_table));
+       uts_table.data = get_uts(table, write);
+       r = sysctl_string(&uts_table, name, nlen,
+               oldval, oldlenp, newval, newlen);
+       put_uts(table, write, uts_table.data);
+       return r;
+}
+
+#ifdef CONFIG_SYSVIPC
+/* The generic sysctl ipc data routine. */
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       size_t len;
+       void *data;
+
+       /* Get out of I don't have a variable */
+       if (!table->data || !table->maxlen)
+               return -ENOTDIR;
+
+       data = get_ipc(table, 1);
+       if (!data)
+               return -ENOTDIR;
+
+       if (oldval && oldlenp) {
+               if (get_user(len, oldlenp))
+                       return -EFAULT;
+               if (len) {
+                       if (len > table->maxlen)
+                               len = table->maxlen;
+                       if (copy_to_user(oldval, data, len))
+                               return -EFAULT;
+                       if (put_user(len, oldlenp))
+                               return -EFAULT;
+               }
+       }
+
+       if (newval && newlen) {
+               if (newlen > table->maxlen)
+                       newlen = table->maxlen;
+
+               if (copy_from_user(data, newval, newlen))
+                       return -EFAULT;
+       }
+       return 1;
+}
+#endif
+
 #else /* CONFIG_SYSCTL_SYSCALL */
 
 
@@ -2714,32 +2701,44 @@ out:
 
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen)
+{
+       return -ENOSYS;
+}
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       return -ENOSYS;
+}
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
index d3d2891..4c3476f 100644 (file)
@@ -34,7 +34,7 @@
 
 static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 };
 static int family_registered;
-kmem_cache_t *taskstats_cache;
+struct kmem_cache *taskstats_cache;
 
 static struct genl_family family = {
        .id             = GENL_ID_GENERATE,
@@ -69,7 +69,7 @@ enum actions {
 };
 
 static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
-                       void **replyp, size_t size)
+                               size_t size)
 {
        struct sk_buff *skb;
        void *reply;
@@ -94,7 +94,6 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
        }
 
        *skbp = skb;
-       *replyp = reply;
        return 0;
 }
 
@@ -119,10 +118,10 @@ static int send_reply(struct sk_buff *skb, pid_t pid)
 /*
  * Send taskstats data in @skb to listeners registered for @cpu's exit data
  */
-static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
+static void send_cpu_listeners(struct sk_buff *skb,
+                                       struct listener_list *listeners)
 {
        struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
-       struct listener_list *listeners;
        struct listener *s, *tmp;
        struct sk_buff *skb_next, *skb_cur = skb;
        void *reply = genlmsg_data(genlhdr);
@@ -135,7 +134,6 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
        }
 
        rc = 0;
-       listeners = &per_cpu(listener_array, cpu);
        down_read(&listeners->sem);
        list_for_each_entry(s, &listeners->list, list) {
                skb_next = NULL;
@@ -186,6 +184,7 @@ static int fill_pid(pid_t pid, struct task_struct *tsk,
        } else
                get_task_struct(tsk);
 
+       memset(stats, 0, sizeof(*stats));
        /*
         * Each accounting subsystem adds calls to its functions to
         * fill in relevant parts of struct taskstsats as follows
@@ -228,6 +227,8 @@ static int fill_tgid(pid_t tgid, struct task_struct *first,
 
        if (first->signal->stats)
                memcpy(stats, first->signal->stats, sizeof(*stats));
+       else
+               memset(stats, 0, sizeof(*stats));
 
        tsk = first;
        do {
@@ -344,14 +345,36 @@ static int parse(struct nlattr *na, cpumask_t *mask)
        return ret;
 }
 
+static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
+{
+       struct nlattr *na, *ret;
+       int aggr;
+
+       aggr = (type == TASKSTATS_TYPE_PID)
+                       ? TASKSTATS_TYPE_AGGR_PID
+                       : TASKSTATS_TYPE_AGGR_TGID;
+
+       na = nla_nest_start(skb, aggr);
+       if (!na)
+               goto err;
+       if (nla_put(skb, type, sizeof(pid), &pid) < 0)
+               goto err;
+       ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats));
+       if (!ret)
+               goto err;
+       nla_nest_end(skb, na);
+
+       return nla_data(ret);
+err:
+       return NULL;
+}
+
 static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 {
        int rc = 0;
        struct sk_buff *rep_skb;
-       struct taskstats stats;
-       void *reply;
+       struct taskstats *stats;
        size_t size;
-       struct nlattr *na;
        cpumask_t mask;
 
        rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask);
@@ -372,83 +395,71 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
        size = nla_total_size(sizeof(u32)) +
                nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
 
-       memset(&stats, 0, sizeof(stats));
-       rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
+       rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
        if (rc < 0)
                return rc;
 
+       rc = -EINVAL;
        if (info->attrs[TASKSTATS_CMD_ATTR_PID]) {
                u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]);
-               rc = fill_pid(pid, NULL, &stats);
-               if (rc < 0)
+               stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid);
+               if (!stats)
                        goto err;
 
-               na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID);
-               NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, pid);
-               NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
-                               stats);
+               rc = fill_pid(pid, NULL, stats);
+               if (rc < 0)
+                       goto err;
        } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) {
                u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]);
-               rc = fill_tgid(tgid, NULL, &stats);
-               if (rc < 0)
+               stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid);
+               if (!stats)
                        goto err;
 
-               na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID);
-               NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, tgid);
-               NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
-                               stats);
-       } else {
-               rc = -EINVAL;
+               rc = fill_tgid(tgid, NULL, stats);
+               if (rc < 0)
+                       goto err;
+       } else
                goto err;
-       }
-
-       nla_nest_end(rep_skb, na);
 
        return send_reply(rep_skb, info->snd_pid);
-
-nla_put_failure:
-       rc = genlmsg_cancel(rep_skb, reply);
 err:
        nlmsg_free(rep_skb);
        return rc;
 }
 
-void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
+static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
 {
-       struct listener_list *listeners;
-       struct taskstats *tmp;
-       /*
-        * This is the cpu on which the task is exiting currently and will
-        * be the one for which the exit event is sent, even if the cpu
-        * on which this function is running changes later.
-        */
-       *mycpu = raw_smp_processor_id();
+       struct signal_struct *sig = tsk->signal;
+       struct taskstats *stats;
 
-       *ptidstats = NULL;
-       tmp = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL);
-       if (!tmp)
-               return;
+       if (sig->stats || thread_group_empty(tsk))
+               goto ret;
 
-       listeners = &per_cpu(listener_array, *mycpu);
-       down_read(&listeners->sem);
-       if (!list_empty(&listeners->list)) {
-               *ptidstats = tmp;
-               tmp = NULL;
+       /* No problem if kmem_cache_zalloc() fails */
+       stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
+
+       spin_lock_irq(&tsk->sighand->siglock);
+       if (!sig->stats) {
+               sig->stats = stats;
+               stats = NULL;
        }
-       up_read(&listeners->sem);
-       kfree(tmp);
+       spin_unlock_irq(&tsk->sighand->siglock);
+
+       if (stats)
+               kmem_cache_free(taskstats_cache, stats);
+ret:
+       return sig->stats;
 }
 
 /* Send pid data out on exit */
-void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
-                       int group_dead, unsigned int mycpu)
+void taskstats_exit(struct task_struct *tsk, int group_dead)
 {
        int rc;
+       struct listener_list *listeners;
+       struct taskstats *stats;
        struct sk_buff *rep_skb;
-       void *reply;
        size_t size;
        int is_thread_group;
-       struct nlattr *na;
 
        if (!family_registered)
                return;
@@ -459,7 +470,7 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
        size = nla_total_size(sizeof(u32)) +
                nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
 
-       is_thread_group = (tsk->signal->stats != NULL);
+       is_thread_group = !!taskstats_tgid_alloc(tsk);
        if (is_thread_group) {
                /* PID + STATS + TGID + STATS */
                size = 2 * size;
@@ -467,49 +478,39 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
                fill_tgid_exit(tsk);
        }
 
-       if (!tidstats)
+       listeners = &__raw_get_cpu_var(listener_array);
+       if (list_empty(&listeners->list))
                return;
 
-       rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
-       if (rc < 0)
-               goto ret;
-
-       rc = fill_pid(tsk->pid, tsk, tidstats);
+       rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, size);
        if (rc < 0)
-               goto err_skb;
+               return;
 
-       na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID);
-       NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, (u32)tsk->pid);
-       NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
-                       *tidstats);
-       nla_nest_end(rep_skb, na);
+       stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid);
+       if (!stats)
+               goto err;
 
-       if (!is_thread_group)
-               goto send;
+       rc = fill_pid(tsk->pid, tsk, stats);
+       if (rc < 0)
+               goto err;
 
        /*
         * Doesn't matter if tsk is the leader or the last group member leaving
         */
-       if (!group_dead)
+       if (!is_thread_group || !group_dead)
                goto send;
 
-       na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID);
-       NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid);
-       /* No locking needed for tsk->signal->stats since group is dead */
-       NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
-                       *tsk->signal->stats);
-       nla_nest_end(rep_skb, na);
+       stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid);
+       if (!stats)
+               goto err;
+
+       memcpy(stats, tsk->signal->stats, sizeof(*stats));
 
 send:
-       send_cpu_listeners(rep_skb, mycpu);
+       send_cpu_listeners(rep_skb, listeners);
        return;
-
-nla_put_failure:
-       genlmsg_cancel(rep_skb, reply);
-err_skb:
+err:
        nlmsg_free(rep_skb);
-ret:
-       return;
 }
 
 static struct genl_ops taskstats_ops = {
index 74eca59..22504af 100644 (file)
@@ -156,7 +156,7 @@ int clocksource_register(struct clocksource *c)
        /* check if clocksource is already registered */
        if (is_registered_source(c)) {
                printk("register_clocksource: Cannot register %s. "
-                       "Already registered!", c->name);
+                      "Already registered!", c->name);
                ret = -EBUSY;
        } else {
                /* register it */
@@ -186,6 +186,7 @@ void clocksource_reselect(void)
 }
 EXPORT_SYMBOL(clocksource_reselect);
 
+#ifdef CONFIG_SYSFS
 /**
  * sysfs_show_current_clocksources - sysfs interface for current clocksource
  * @dev:       unused
@@ -275,10 +276,10 @@ sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
  * Sysfs setup bits:
  */
 static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
-                       sysfs_override_clocksource);
+                  sysfs_override_clocksource);
 
 static SYSDEV_ATTR(available_clocksource, 0600,
-                       sysfs_show_available_clocksources, NULL);
+                  sysfs_show_available_clocksources, NULL);
 
 static struct sysdev_class clocksource_sysclass = {
        set_kset_name("clocksource"),
@@ -307,6 +308,7 @@ static int __init init_clocksource_sysfs(void)
 }
 
 device_initcall(init_clocksource_sysfs);
+#endif /* CONFIG_SYSFS */
 
 /**
  * boot_override_clocksource - boot clock override
index c1c7fbc..0256ab4 100644 (file)
@@ -80,6 +80,138 @@ tvec_base_t boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
 static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 
+/**
+ * __round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies(unsigned long j, int cpu)
+{
+       int rem;
+       unsigned long original = j;
+
+       /*
+        * We don't want all cpus firing their timers at once hitting the
+        * same lock or cachelines, so we skew each extra cpu with an extra
+        * 3 jiffies. This 3 jiffies came originally from the mm/ code which
+        * already did this.
+        * The skew is done by adding 3*cpunr, then round, then subtract this
+        * extra offset again.
+        */
+       j += cpu * 3;
+
+       rem = j % HZ;
+
+       /*
+        * If the target jiffie is just after a whole second (which can happen
+        * due to delays of the timer irq, long irq off times etc etc) then
+        * we should round down to the whole second, not up. Use 1/4th second
+        * as cutoff for this rounding as an extreme upper bound for this.
+        */
+       if (rem < HZ/4) /* round down */
+               j = j - rem;
+       else /* round up */
+               j = j - rem + HZ;
+
+       /* now that we have rounded, subtract the extra skew again */
+       j -= cpu * 3;
+
+       if (j <= jiffies) /* rounding ate our timeout entirely; */
+               return original;
+       return j;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies);
+
+/**
+ * __round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies_relative rounds a time delta  in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies_relative(unsigned long j, int cpu)
+{
+       /*
+        * In theory the following code can skip a jiffy in case jiffies
+        * increments right between the addition and the later subtraction.
+        * However since the entire point of this function is to use approximate
+        * timeouts, it's entirely ok to not handle that.
+        */
+       return  __round_jiffies(j + jiffies, cpu) - jiffies;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies_relative);
+
+/**
+ * round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ *
+ * round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies(unsigned long j)
+{
+       return __round_jiffies(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies);
+
+/**
+ * round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ *
+ * round_jiffies_relative rounds a time delta  in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies_relative(unsigned long j)
+{
+       return __round_jiffies_relative(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies_relative);
+
+
 static inline void set_running_timer(tvec_base_t *base,
                                        struct timer_list *timer)
 {
@@ -714,7 +846,7 @@ static int change_clocksource(void)
                clock = new;
                clock->cycle_last = now;
                printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-                                       clock->name);
+                      clock->name);
                return 1;
        } else if (clock->update_callback) {
                return clock->update_callback();
@@ -722,7 +854,10 @@ static int change_clocksource(void)
        return 0;
 }
 #else
-#define change_clocksource() (0)
+static inline int change_clocksource(void)
+{
+       return 0;
+}
 #endif
 
 /**
@@ -820,7 +955,8 @@ device_initcall(timekeeping_init_device);
  * If the error is already larger, we look ahead even further
  * to compensate for late or lost adjustments.
  */
-static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *offset)
+static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
+                                                s64 *offset)
 {
        s64 tick_error, i;
        u32 look_ahead, adj;
@@ -844,7 +980,8 @@ static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *
         * Now calculate the error in (1 << look_ahead) ticks, but first
         * remove the single look ahead already included in the error.
         */
-       tick_error = current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
+       tick_error = current_tick_length() >>
+               (TICK_LENGTH_SHIFT - clock->shift + 1);
        tick_error -= clock->xtime_interval >> 1;
        error = ((error - tick_error) >> look_ahead) + tick_error;
 
@@ -896,7 +1033,8 @@ static void clocksource_adjust(struct clocksource *clock, s64 offset)
        clock->mult += adj;
        clock->xtime_interval += interval;
        clock->xtime_nsec -= offset;
-       clock->error -= (interval - offset) << (TICK_LENGTH_SHIFT - clock->shift);
+       clock->error -= (interval - offset) <<
+                       (TICK_LENGTH_SHIFT - clock->shift);
 }
 
 /**
index 96f7701..baacc36 100644 (file)
@@ -96,6 +96,15 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
        stats->write_char       = p->wchar;
        stats->read_syscalls    = p->syscr;
        stats->write_syscalls   = p->syscw;
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+       stats->read_bytes       = p->ioac.read_bytes;
+       stats->write_bytes      = p->ioac.write_bytes;
+       stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes;
+#else
+       stats->read_bytes       = 0;
+       stats->write_bytes      = 0;
+       stats->cancelled_write_bytes = 0;
+#endif
 }
 #undef KB
 #undef MB
index ed0a21d..09c2613 100644 (file)
 #include <linux/bootmem.h>
 #include <linux/sort.h>
 #include <linux/stop_machine.h>
+#include <linux/uaccess.h>
 #include <asm/sections.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
-extern char __start_unwind[], __end_unwind[];
+extern const char __start_unwind[], __end_unwind[];
 extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
 
 #define MAX_STACK_DEPTH 8
@@ -94,6 +95,7 @@ static const struct {
 
 typedef unsigned long uleb128_t;
 typedef   signed long sleb128_t;
+#define sleb128abs __builtin_labs
 
 static struct unwind_table {
        struct {
@@ -135,6 +137,17 @@ struct unwind_state {
 
 static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
 
+static unsigned unwind_debug;
+static int __init unwind_debug_setup(char *s)
+{
+       unwind_debug = simple_strtoul(s, NULL, 0);
+       return 1;
+}
+__setup("unwind_debug=", unwind_debug_setup);
+#define dprintk(lvl, fmt, args...) \
+       ((void)(lvl > unwind_debug \
+        || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
+
 static struct unwind_table *find_table(unsigned long pc)
 {
        struct unwind_table *table;
@@ -151,7 +164,9 @@ static struct unwind_table *find_table(unsigned long pc)
 
 static unsigned long read_pointer(const u8 **pLoc,
                                   const void *end,
-                                  signed ptrType);
+                                  signed ptrType,
+                                  unsigned long text_base,
+                                  unsigned long data_base);
 
 static void init_unwind_table(struct unwind_table *table,
                               const char *name,
@@ -176,10 +191,13 @@ static void init_unwind_table(struct unwind_table *table,
        /* See if the linker provided table looks valid. */
        if (header_size <= 4
            || header_start[0] != 1
-           || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
-           || header_start[2] == DW_EH_PE_omit
-           || read_pointer(&ptr, end, header_start[2]) <= 0
-           || header_start[3] == DW_EH_PE_omit)
+           || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
+              != table_start
+           || !read_pointer(&ptr, end, header_start[2], 0, 0)
+           || !read_pointer(&ptr, end, header_start[3], 0,
+                            (unsigned long)header_start)
+           || !read_pointer(&ptr, end, header_start[3], 0,
+                            (unsigned long)header_start))
                header_start = NULL;
        table->hdrsz = header_size;
        smp_wmb();
@@ -269,7 +287,7 @@ static void __init setup_unwind_table(struct unwind_table *table,
                ptr = (const u8 *)(fde + 2);
                if (!read_pointer(&ptr,
                                  (const u8 *)(fde + 1) + *fde,
-                                 ptrType))
+                                 ptrType, 0, 0))
                        return;
                ++n;
        }
@@ -279,6 +297,7 @@ static void __init setup_unwind_table(struct unwind_table *table,
 
        hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
                + 2 * n * sizeof(unsigned long);
+       dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
        header = alloc(hdrSize);
        if (!header)
                return;
@@ -303,7 +322,7 @@ static void __init setup_unwind_table(struct unwind_table *table,
                ptr = (const u8 *)(fde + 2);
                header->table[n].start = read_pointer(&ptr,
                                                      (const u8 *)(fde + 1) + *fde,
-                                                     fde_pointer_type(cie));
+                                                     fde_pointer_type(cie), 0, 0);
                header->table[n].fde = (unsigned long)fde;
                ++n;
        }
@@ -486,7 +505,9 @@ static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
 
 static unsigned long read_pointer(const u8 **pLoc,
                                   const void *end,
-                                  signed ptrType)
+                                  signed ptrType,
+                                  unsigned long text_base,
+                                  unsigned long data_base)
 {
        unsigned long value = 0;
        union {
@@ -498,13 +519,17 @@ static unsigned long read_pointer(const u8 **pLoc,
                const unsigned long *pul;
        } ptr;
 
-       if (ptrType < 0 || ptrType == DW_EH_PE_omit)
+       if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
+               dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
                return 0;
+       }
        ptr.p8 = *pLoc;
        switch(ptrType & DW_EH_PE_FORM) {
        case DW_EH_PE_data2:
-               if (end < (const void *)(ptr.p16u + 1))
+               if (end < (const void *)(ptr.p16u + 1)) {
+                       dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
                        return 0;
+               }
                if(ptrType & DW_EH_PE_signed)
                        value = get_unaligned(ptr.p16s++);
                else
@@ -512,8 +537,10 @@ static unsigned long read_pointer(const u8 **pLoc,
                break;
        case DW_EH_PE_data4:
 #ifdef CONFIG_64BIT
-               if (end < (const void *)(ptr.p32u + 1))
+               if (end < (const void *)(ptr.p32u + 1)) {
+                       dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
                        return 0;
+               }
                if(ptrType & DW_EH_PE_signed)
                        value = get_unaligned(ptr.p32s++);
                else
@@ -525,8 +552,10 @@ static unsigned long read_pointer(const u8 **pLoc,
                BUILD_BUG_ON(sizeof(u32) != sizeof(value));
 #endif
        case DW_EH_PE_native:
-               if (end < (const void *)(ptr.pul + 1))
+               if (end < (const void *)(ptr.pul + 1)) {
+                       dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
                        return 0;
+               }
                value = get_unaligned(ptr.pul++);
                break;
        case DW_EH_PE_leb128:
@@ -534,10 +563,14 @@ static unsigned long read_pointer(const u8 **pLoc,
                value = ptrType & DW_EH_PE_signed
                        ? get_sleb128(&ptr.p8, end)
                        : get_uleb128(&ptr.p8, end);
-               if ((const void *)ptr.p8 > end)
+               if ((const void *)ptr.p8 > end) {
+                       dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
                        return 0;
+               }
                break;
        default:
+               dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
+                       ptrType, ptr.p8, end);
                return 0;
        }
        switch(ptrType & DW_EH_PE_ADJUST) {
@@ -546,12 +579,33 @@ static unsigned long read_pointer(const u8 **pLoc,
        case DW_EH_PE_pcrel:
                value += (unsigned long)*pLoc;
                break;
+       case DW_EH_PE_textrel:
+               if (likely(text_base)) {
+                       value += text_base;
+                       break;
+               }
+               dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
+                       ptrType, *pLoc, end);
+               return 0;
+       case DW_EH_PE_datarel:
+               if (likely(data_base)) {
+                       value += data_base;
+                       break;
+               }
+               dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
+                       ptrType, *pLoc, end);
+               return 0;
        default:
+               dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
+                       ptrType, *pLoc, end);
                return 0;
        }
        if ((ptrType & DW_EH_PE_indirect)
-           && __get_user(value, (unsigned long *)value))
+           && probe_kernel_address((unsigned long *)value, value)) {
+               dprintk(1, "Cannot read indirect value %lx (%p,%p).",
+                       value, *pLoc, end);
                return 0;
+       }
        *pLoc = ptr.p8;
 
        return value;
@@ -594,7 +648,8 @@ static signed fde_pointer_type(const u32 *cie)
                        case 'P': {
                                        signed ptrType = *ptr++;
 
-                                       if (!read_pointer(&ptr, end, ptrType) || ptr > end)
+                                       if (!read_pointer(&ptr, end, ptrType, 0, 0)
+                                           || ptr > end)
                                                return -1;
                                }
                                break;
@@ -654,7 +709,8 @@ static int processCFI(const u8 *start,
                        case DW_CFA_nop:
                                break;
                        case DW_CFA_set_loc:
-                               if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
+                               state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
+                               if (state->loc == 0)
                                        result = 0;
                                break;
                        case DW_CFA_advance_loc1:
@@ -700,8 +756,10 @@ static int processCFI(const u8 *start,
                                        state->label = NULL;
                                        return 1;
                                }
-                               if (state->stackDepth >= MAX_STACK_DEPTH)
+                               if (state->stackDepth >= MAX_STACK_DEPTH) {
+                                       dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
                                        return 0;
+                               }
                                state->stack[state->stackDepth++] = ptr.p8;
                                break;
                        case DW_CFA_restore_state:
@@ -716,8 +774,10 @@ static int processCFI(const u8 *start,
                                        result = processCFI(start, end, 0, ptrType, state);
                                        state->loc = loc;
                                        state->label = label;
-                               } else
+                               } else {
+                                       dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
                                        return 0;
+                               }
                                break;
                        case DW_CFA_def_cfa:
                                state->cfa.reg = get_uleb128(&ptr.p8, end);
@@ -749,6 +809,7 @@ static int processCFI(const u8 *start,
                                break;
                        case DW_CFA_GNU_window_save:
                        default:
+                               dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
                                result = 0;
                                break;
                        }
@@ -764,12 +825,17 @@ static int processCFI(const u8 *start,
                        set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
                        break;
                }
-               if (ptr.p8 > end)
+               if (ptr.p8 > end) {
+                       dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
                        result = 0;
+               }
                if (result && targetLoc != 0 && targetLoc < state->loc)
                        return 1;
        }
 
+       if (result && ptr.p8 < end)
+               dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
+
        return result
           && ptr.p8 == end
           && (targetLoc == 0
@@ -786,7 +852,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 pc = UNW_PC(frame) - frame->call_frame, sp;
        unsigned long startLoc = 0, endLoc = 0, cfa;
        unsigned i;
        signed ptrType = -1;
@@ -813,9 +879,9 @@ int unwind(struct unwind_frame_info *frame)
                        ptr = hdr + 4;
                        end = hdr + table->hdrsz;
                        if (tableSize
-                           && read_pointer(&ptr, end, hdr[1])
+                           && read_pointer(&ptr, end, hdr[1], 0, 0)
                               == (unsigned long)table->address
-                           && (i = read_pointer(&ptr, end, hdr[2])) > 0
+                           && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
                            && i == (end - ptr) / (2 * tableSize)
                            && !((end - ptr) % (2 * tableSize))) {
                                do {
@@ -823,7 +889,8 @@ int unwind(struct unwind_frame_info *frame)
 
                                        startLoc = read_pointer(&cur,
                                                                cur + tableSize,
-                                                               hdr[3]);
+                                                               hdr[3], 0,
+                                                               (unsigned long)hdr);
                                        if (pc < startLoc)
                                                i /= 2;
                                        else {
@@ -834,13 +901,17 @@ int unwind(struct unwind_frame_info *frame)
                                if (i == 1
                                    && (startLoc = read_pointer(&ptr,
                                                                ptr + tableSize,
-                                                               hdr[3])) != 0
+                                                               hdr[3], 0,
+                                                               (unsigned long)hdr)) != 0
                                    && pc >= startLoc)
                                        fde = (void *)read_pointer(&ptr,
                                                                   ptr + tableSize,
-                                                                  hdr[3]);
+                                                                  hdr[3], 0,
+                                                                  (unsigned long)hdr);
                        }
                }
+               if(hdr && !fde)
+                       dprintk(3, "Binary lookup for %lx failed.", pc);
 
                if (fde != NULL) {
                        cie = cie_for_fde(fde, table);
@@ -851,17 +922,19 @@ int unwind(struct unwind_frame_info *frame)
                           && (ptrType = fde_pointer_type(cie)) >= 0
                           && read_pointer(&ptr,
                                           (const u8 *)(fde + 1) + *fde,
-                                          ptrType) == startLoc) {
+                                          ptrType, 0, 0) == startLoc) {
                                if (!(ptrType & DW_EH_PE_indirect))
                                        ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
                                endLoc = startLoc
                                         + read_pointer(&ptr,
                                                        (const u8 *)(fde + 1) + *fde,
-                                                       ptrType);
+                                                       ptrType, 0, 0);
                                if(pc >= endLoc)
                                        fde = NULL;
                        } else
                                fde = NULL;
+                       if(!fde)
+                               dprintk(1, "Binary lookup result for %lx discarded.", pc);
                }
                if (fde == NULL) {
                        for (fde = table->address, tableSize = table->size;
@@ -881,7 +954,7 @@ int unwind(struct unwind_frame_info *frame)
                                ptr = (const u8 *)(fde + 2);
                                startLoc = read_pointer(&ptr,
                                                        (const u8 *)(fde + 1) + *fde,
-                                                       ptrType);
+                                                       ptrType, 0, 0);
                                if (!startLoc)
                                        continue;
                                if (!(ptrType & DW_EH_PE_indirect))
@@ -889,10 +962,12 @@ int unwind(struct unwind_frame_info *frame)
                                endLoc = startLoc
                                         + read_pointer(&ptr,
                                                        (const u8 *)(fde + 1) + *fde,
-                                                       ptrType);
+                                                       ptrType, 0, 0);
                                if (pc >= startLoc && pc < endLoc)
                                        break;
                        }
+                       if(!fde)
+                               dprintk(3, "Linear lookup for %lx failed.", pc);
                }
        }
        if (cie != NULL) {
@@ -926,6 +1001,8 @@ int unwind(struct unwind_frame_info *frame)
                        if (ptr >= end || *ptr)
                                cie = NULL;
                }
+               if(!cie)
+                       dprintk(1, "CIE unusable (%p,%p).", ptr, end);
                ++ptr;
        }
        if (cie != NULL) {
@@ -935,7 +1012,12 @@ int unwind(struct unwind_frame_info *frame)
                state.dataAlign = get_sleb128(&ptr, end);
                if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
                        cie = NULL;
-               else {
+               else if (UNW_PC(frame) % state.codeAlign
+                        || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
+                       dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
+                               UNW_PC(frame), UNW_SP(frame));
+                       return -EPERM;
+               } else {
                        retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
                        /* skip augmentation */
                        if (((const char *)(cie + 2))[1] == 'z') {
@@ -949,6 +1031,8 @@ int unwind(struct unwind_frame_info *frame)
                           || reg_info[retAddrReg].width != sizeof(unsigned long))
                                cie = NULL;
                }
+               if(!cie)
+                       dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
        }
        if (cie != NULL) {
                state.cieStart = ptr;
@@ -962,11 +1046,15 @@ int unwind(struct unwind_frame_info *frame)
                        if ((ptr += augSize) > end)
                                fde = NULL;
                }
+               if(!fde)
+                       dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
        }
        if (cie == NULL || fde == NULL) {
 #ifdef CONFIG_FRAME_POINTER
                unsigned long top, bottom;
 
+               if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
+                       return -EPERM;
                top = STACK_TOP(frame->task);
                bottom = STACK_BOTTOM(frame->task);
 # if FRAME_RETADDR_OFFSET < 0
@@ -982,18 +1070,19 @@ int unwind(struct unwind_frame_info *frame)
                        & (sizeof(unsigned long) - 1))) {
                        unsigned long link;
 
-                       if (!__get_user(link,
+                       if (!probe_kernel_address(
                                        (unsigned long *)(UNW_FP(frame)
-                                                         + FRAME_LINK_OFFSET))
+                                                         + FRAME_LINK_OFFSET),
+                                                 link)
 # if FRAME_RETADDR_OFFSET < 0
                           && link > bottom && link < UNW_FP(frame)
 # else
                           && link > UNW_FP(frame) && link < bottom
 # endif
                           && !(link & (sizeof(link) - 1))
-                          && !__get_user(UNW_PC(frame),
+                          && !probe_kernel_address(
                                          (unsigned long *)(UNW_FP(frame)
-                                                           + FRAME_RETADDR_OFFSET))) {
+                                                           + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
                                UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
 # if FRAME_RETADDR_OFFSET < 0
                                        -
@@ -1016,8 +1105,11 @@ int unwind(struct unwind_frame_info *frame)
           || state.regs[retAddrReg].where == Nowhere
           || state.cfa.reg >= ARRAY_SIZE(reg_info)
           || reg_info[state.cfa.reg].width != sizeof(unsigned long)
-          || state.cfa.offs % sizeof(unsigned long))
+          || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
+          || state.cfa.offs % sizeof(unsigned long)) {
+               dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
                return -EIO;
+       }
        /* update frame */
 #ifndef CONFIG_AS_CFI_SIGNAL_FRAME
        if(frame->call_frame
@@ -1036,10 +1128,14 @@ int unwind(struct unwind_frame_info *frame)
 #else
 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
 #endif
+       pc = UNW_PC(frame);
+       sp = UNW_SP(frame);
        for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
                if (REG_INVALID(i)) {
                        if (state.regs[i].where == Nowhere)
                                continue;
+                       dprintk(1, "Cannot restore register %u (%d).",
+                               i, state.regs[i].where);
                        return -EIO;
                }
                switch(state.regs[i].where) {
@@ -1048,8 +1144,11 @@ int unwind(struct unwind_frame_info *frame)
                case Register:
                        if (state.regs[i].value >= ARRAY_SIZE(reg_info)
                           || REG_INVALID(state.regs[i].value)
-                          || reg_info[i].width > reg_info[state.regs[i].value].width)
+                          || reg_info[i].width > reg_info[state.regs[i].value].width) {
+                               dprintk(1, "Cannot restore register %u from register %lu.",
+                                       i, state.regs[i].value);
                                return -EIO;
+                       }
                        switch(reg_info[state.regs[i].value].width) {
 #define CASE(n) \
                        case sizeof(u##n): \
@@ -1059,6 +1158,9 @@ int unwind(struct unwind_frame_info *frame)
                        CASES;
 #undef CASE
                        default:
+                               dprintk(1, "Unsupported register size %u (%lu).",
+                                       reg_info[state.regs[i].value].width,
+                                       state.regs[i].value);
                                return -EIO;
                        }
                        break;
@@ -1083,12 +1185,17 @@ int unwind(struct unwind_frame_info *frame)
                        CASES;
 #undef CASE
                        default:
+                               dprintk(1, "Unsupported register size %u (%u).",
+                                       reg_info[i].width, i);
                                return -EIO;
                        }
                        break;
                case Value:
-                       if (reg_info[i].width != sizeof(unsigned long))
+                       if (reg_info[i].width != sizeof(unsigned long)) {
+                               dprintk(1, "Unsupported value size %u (%u).",
+                                       reg_info[i].width, i);
                                return -EIO;
+                       }
                        FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
                                                            * state.dataAlign;
                        break;
@@ -1100,15 +1207,20 @@ int unwind(struct unwind_frame_info *frame)
                                    % sizeof(unsigned long)
                                    || addr < startLoc
                                    || addr + sizeof(unsigned long) < addr
-                                   || addr + sizeof(unsigned long) > endLoc)
+                                   || addr + sizeof(unsigned long) > endLoc) {
+                                       dprintk(1, "Bad memory location %lx (%lx).",
+                                               addr, state.regs[i].value);
                                        return -EIO;
+                               }
                                switch(reg_info[i].width) {
 #define CASE(n)     case sizeof(u##n): \
-                                       __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
+                                       probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
                                        break
                                CASES;
 #undef CASE
                                default:
+                                       dprintk(1, "Unsupported memory size %u (%u).",
+                                               reg_info[i].width, i);
                                        return -EIO;
                                }
                        }
@@ -1116,6 +1228,17 @@ int unwind(struct unwind_frame_info *frame)
                }
        }
 
+       if (UNW_PC(frame) % state.codeAlign
+           || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
+               dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
+                       UNW_PC(frame), UNW_SP(frame));
+               return -EIO;
+       }
+       if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
+               dprintk(1, "No progress (%lx,%lx).", pc, sp);
+               return -EIO;
+       }
+
        return 0;
 #undef CASES
 #undef FRAME_REG
index 220e586..4869563 100644 (file)
@@ -26,7 +26,7 @@
 #define __uidhashfn(uid)       (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
 #define uidhashentry(uid)      (uidhash_table + __uidhashfn((uid)))
 
-static kmem_cache_t *uid_cachep;
+static struct kmem_cache *uid_cachep;
 static struct list_head uidhash_table[UIDHASH_SZ];
 
 /*
@@ -132,7 +132,7 @@ struct user_struct * alloc_uid(uid_t uid)
        if (!up) {
                struct user_struct *new;
 
-               new = kmem_cache_alloc(uid_cachep, SLAB_KERNEL);
+               new = kmem_cache_alloc(uid_cachep, GFP_KERNEL);
                if (!new)
                        return NULL;
                new->uid = uid;
index 17c2f03..db49886 100644 (file)
@@ -29,6 +29,9 @@
 #include <linux/kthread.h>
 #include <linux/hardirq.h>
 #include <linux/mempolicy.h>
+#include <linux/freezer.h>
+#include <linux/kallsyms.h>
+#include <linux/debug_locks.h>
 
 /*
  * The per-CPU workqueue (if single thread, we always use the first
@@ -55,6 +58,8 @@ struct cpu_workqueue_struct {
        struct task_struct *thread;
 
        int run_depth;          /* Detect run_workqueue() recursion depth */
+
+       int freezeable;         /* Freeze the thread during suspend */
 } ____cacheline_aligned;
 
 /*
@@ -80,6 +85,99 @@ static inline int is_single_threaded(struct workqueue_struct *wq)
        return list_empty(&wq->list);
 }
 
+/*
+ * Set the workqueue on which a work item is to be run
+ * - Must *only* be called if the pending flag is set
+ */
+static inline void set_wq_data(struct work_struct *work, void *wq)
+{
+       unsigned long new;
+
+       BUG_ON(!work_pending(work));
+
+       new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING);
+       new |= work->management & WORK_STRUCT_FLAG_MASK;
+       work->management = new;
+}
+
+static inline void *get_wq_data(struct work_struct *work)
+{
+       return (void *) (work->management & WORK_STRUCT_WQ_DATA_MASK);
+}
+
+static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cwq->lock, flags);
+       /*
+        * We need to re-validate the work info after we've gotten
+        * the cpu_workqueue lock. We can run the work now iff:
+        *
+        *  - the wq_data still matches the cpu_workqueue_struct
+        *  - AND the work is still marked pending
+        *  - AND the work is still on a list (which will be this
+        *    workqueue_struct list)
+        *
+        * All these conditions are important, because we
+        * need to protect against the work being run right
+        * now on another CPU (all but the last one might be
+        * true if it's currently running and has not been
+        * released yet, for example).
+        */
+       if (get_wq_data(work) == cwq
+           && work_pending(work)
+           && !list_empty(&work->entry)) {
+               work_func_t f = work->func;
+               list_del_init(&work->entry);
+               spin_unlock_irqrestore(&cwq->lock, flags);
+
+               if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management))
+                       work_release(work);
+               f(work);
+
+               spin_lock_irqsave(&cwq->lock, flags);
+               cwq->remove_sequence++;
+               wake_up(&cwq->work_done);
+               ret = 1;
+       }
+       spin_unlock_irqrestore(&cwq->lock, flags);
+       return ret;
+}
+
+/**
+ * run_scheduled_work - run scheduled work synchronously
+ * @work: work to run
+ *
+ * This checks if the work was pending, and runs it
+ * synchronously if so. It returns a boolean to indicate
+ * whether it had any scheduled work to run or not.
+ *
+ * NOTE! This _only_ works for normal work_structs. You
+ * CANNOT use this for delayed work, because the wq data
+ * for delayed work will not point properly to the per-
+ * CPU workqueue struct, but will change!
+ */
+int fastcall run_scheduled_work(struct work_struct *work)
+{
+       for (;;) {
+               struct cpu_workqueue_struct *cwq;
+
+               if (!work_pending(work))
+                       return 0;
+               if (list_empty(&work->entry))
+                       return 0;
+               /* NOTE! This depends intimately on __queue_work! */
+               cwq = get_wq_data(work);
+               if (!cwq)
+                       return 0;
+               if (__run_work(cwq, work))
+                       return 1;
+       }
+}
+EXPORT_SYMBOL(run_scheduled_work);
+
 /* Preempt must be disabled. */
 static void __queue_work(struct cpu_workqueue_struct *cwq,
                         struct work_struct *work)
@@ -87,7 +185,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
        unsigned long flags;
 
        spin_lock_irqsave(&cwq->lock, flags);
-       work->wq_data = cwq;
+       set_wq_data(work, cwq);
        list_add_tail(&work->entry, &cwq->worklist);
        cwq->insert_sequence++;
        wake_up(&cwq->more_work);
@@ -108,7 +206,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work)
 {
        int ret = 0, cpu = get_cpu();
 
-       if (!test_and_set_bit(0, &work->pending)) {
+       if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
                if (unlikely(is_single_threaded(wq)))
                        cpu = singlethread_cpu;
                BUG_ON(!list_empty(&work->entry));
@@ -122,38 +220,42 @@ EXPORT_SYMBOL_GPL(queue_work);
 
 static void delayed_work_timer_fn(unsigned long __data)
 {
-       struct work_struct *work = (struct work_struct *)__data;
-       struct workqueue_struct *wq = work->wq_data;
+       struct delayed_work *dwork = (struct delayed_work *)__data;
+       struct workqueue_struct *wq = get_wq_data(&dwork->work);
        int cpu = smp_processor_id();
 
        if (unlikely(is_single_threaded(wq)))
                cpu = singlethread_cpu;
 
-       __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
+       __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), &dwork->work);
 }
 
 /**
  * queue_delayed_work - queue work on a workqueue after delay
  * @wq: workqueue to use
- * @work: work to queue
+ * @work: delayable work to queue
  * @delay: number of jiffies to wait before queueing
  *
  * Returns 0 if @work was already on a queue, non-zero otherwise.
  */
 int fastcall queue_delayed_work(struct workqueue_struct *wq,
-                       struct work_struct *work, unsigned long delay)
+                       struct delayed_work *dwork, unsigned long delay)
 {
        int ret = 0;
-       struct timer_list *timer = &work->timer;
+       struct timer_list *timer = &dwork->timer;
+       struct work_struct *work = &dwork->work;
+
+       if (delay == 0)
+               return queue_work(wq, work);
 
-       if (!test_and_set_bit(0, &work->pending)) {
+       if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
                BUG_ON(timer_pending(timer));
                BUG_ON(!list_empty(&work->entry));
 
                /* This stores wq for the moment, for the timer_fn */
-               work->wq_data = wq;
+               set_wq_data(work, wq);
                timer->expires = jiffies + delay;
-               timer->data = (unsigned long)work;
+               timer->data = (unsigned long)dwork;
                timer->function = delayed_work_timer_fn;
                add_timer(timer);
                ret = 1;
@@ -172,19 +274,20 @@ EXPORT_SYMBOL_GPL(queue_delayed_work);
  * Returns 0 if @work was already on a queue, non-zero otherwise.
  */
 int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
-                       struct work_struct *work, unsigned long delay)
+                       struct delayed_work *dwork, unsigned long delay)
 {
        int ret = 0;
-       struct timer_list *timer = &work->timer;
+       struct timer_list *timer = &dwork->timer;
+       struct work_struct *work = &dwork->work;
 
-       if (!test_and_set_bit(0, &work->pending)) {
+       if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
                BUG_ON(timer_pending(timer));
                BUG_ON(!list_empty(&work->entry));
 
                /* This stores wq for the moment, for the timer_fn */
-               work->wq_data = wq;
+               set_wq_data(work, wq);
                timer->expires = jiffies + delay;
-               timer->data = (unsigned long)work;
+               timer->data = (unsigned long)dwork;
                timer->function = delayed_work_timer_fn;
                add_timer_on(timer, cpu);
                ret = 1;
@@ -212,15 +315,26 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
        while (!list_empty(&cwq->worklist)) {
                struct work_struct *work = list_entry(cwq->worklist.next,
                                                struct work_struct, entry);
-               void (*f) (void *) = work->func;
-               void *data = work->data;
+               work_func_t f = work->func;
 
                list_del_init(cwq->worklist.next);
                spin_unlock_irqrestore(&cwq->lock, flags);
 
-               BUG_ON(work->wq_data != cwq);
-               clear_bit(0, &work->pending);
-               f(data);
+               BUG_ON(get_wq_data(work) != cwq);
+               if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management))
+                       work_release(work);
+               f(work);
+
+               if (unlikely(in_atomic() || lockdep_depth(current) > 0)) {
+                       printk(KERN_ERR "BUG: workqueue leaked lock or atomic: "
+                                       "%s/0x%08x/%d\n",
+                                       current->comm, preempt_count(),
+                                       current->pid);
+                       printk(KERN_ERR "    last function: ");
+                       print_symbol("%s\n", (unsigned long)f);
+                       debug_show_held_locks(current);
+                       dump_stack();
+               }
 
                spin_lock_irqsave(&cwq->lock, flags);
                cwq->remove_sequence++;
@@ -237,7 +351,8 @@ static int worker_thread(void *__cwq)
        struct k_sigaction sa;
        sigset_t blocked;
 
-       current->flags |= PF_NOFREEZE;
+       if (!cwq->freezeable)
+               current->flags |= PF_NOFREEZE;
 
        set_user_nice(current, -5);
 
@@ -260,6 +375,9 @@ static int worker_thread(void *__cwq)
 
        set_current_state(TASK_INTERRUPTIBLE);
        while (!kthread_should_stop()) {
+               if (cwq->freezeable)
+                       try_to_freeze();
+
                add_wait_queue(&cwq->more_work, &wait);
                if (list_empty(&cwq->worklist))
                        schedule();
@@ -336,7 +454,7 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
 static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
-                                                  int cpu)
+                                                  int cpu, int freezeable)
 {
        struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
        struct task_struct *p;
@@ -346,6 +464,7 @@ static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
        cwq->thread = NULL;
        cwq->insert_sequence = 0;
        cwq->remove_sequence = 0;
+       cwq->freezeable = freezeable;
        INIT_LIST_HEAD(&cwq->worklist);
        init_waitqueue_head(&cwq->more_work);
        init_waitqueue_head(&cwq->work_done);
@@ -361,7 +480,7 @@ static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
 }
 
 struct workqueue_struct *__create_workqueue(const char *name,
-                                           int singlethread)
+                                           int singlethread, int freezeable)
 {
        int cpu, destroy = 0;
        struct workqueue_struct *wq;
@@ -381,7 +500,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
        mutex_lock(&workqueue_mutex);
        if (singlethread) {
                INIT_LIST_HEAD(&wq->list);
-               p = create_workqueue_thread(wq, singlethread_cpu);
+               p = create_workqueue_thread(wq, singlethread_cpu, freezeable);
                if (!p)
                        destroy = 1;
                else
@@ -389,7 +508,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
        } else {
                list_add(&wq->list, &workqueues);
                for_each_online_cpu(cpu) {
-                       p = create_workqueue_thread(wq, cpu);
+                       p = create_workqueue_thread(wq, cpu, freezeable);
                        if (p) {
                                kthread_bind(p, cpu);
                                wake_up_process(p);
@@ -468,38 +587,37 @@ EXPORT_SYMBOL(schedule_work);
 
 /**
  * schedule_delayed_work - put work task in global workqueue after delay
- * @work: job to be done
- * @delay: number of jiffies to wait
+ * @dwork: job to be done
+ * @delay: number of jiffies to wait or 0 for immediate execution
  *
  * After waiting for a given time this puts a job in the kernel-global
  * workqueue.
  */
-int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay)
+int fastcall schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
 {
-       return queue_delayed_work(keventd_wq, work, delay);
+       return queue_delayed_work(keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work);
 
 /**
  * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
  * @cpu: cpu to use
- * @work: job to be done
+ * @dwork: job to be done
  * @delay: number of jiffies to wait
  *
  * After waiting for a given time this puts a job in the kernel-global
  * workqueue on the specified CPU.
  */
 int schedule_delayed_work_on(int cpu,
-                       struct work_struct *work, unsigned long delay)
+                       struct delayed_work *dwork, unsigned long delay)
 {
-       return queue_delayed_work_on(cpu, keventd_wq, work, delay);
+       return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work_on);
 
 /**
  * schedule_on_each_cpu - call a function on each online CPU from keventd
  * @func: the function to call
- * @info: a pointer to pass to func()
  *
  * Returns zero on success.
  * Returns -ve errno on failure.
@@ -508,7 +626,7 @@ EXPORT_SYMBOL(schedule_delayed_work_on);
  *
  * schedule_on_each_cpu() is very slow.
  */
-int schedule_on_each_cpu(void (*func)(void *info), void *info)
+int schedule_on_each_cpu(work_func_t func)
 {
        int cpu;
        struct work_struct *works;
@@ -519,7 +637,7 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info)
 
        mutex_lock(&workqueue_mutex);
        for_each_online_cpu(cpu) {
-               INIT_WORK(per_cpu_ptr(works, cpu), func, info);
+               INIT_WORK(per_cpu_ptr(works, cpu), func);
                __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
                                per_cpu_ptr(works, cpu));
        }
@@ -539,12 +657,12 @@ EXPORT_SYMBOL(flush_scheduled_work);
  * cancel_rearming_delayed_workqueue - reliably kill off a delayed
  *                     work whose handler rearms the delayed work.
  * @wq:   the controlling workqueue structure
- * @work: the delayed work struct
+ * @dwork: the delayed work struct
  */
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
-                                      struct work_struct *work)
+                                      struct delayed_work *dwork)
 {
-       while (!cancel_delayed_work(work))
+       while (!cancel_delayed_work(dwork))
                flush_workqueue(wq);
 }
 EXPORT_SYMBOL(cancel_rearming_delayed_workqueue);
@@ -552,18 +670,17 @@ EXPORT_SYMBOL(cancel_rearming_delayed_workqueue);
 /**
  * cancel_rearming_delayed_work - reliably kill off a delayed keventd
  *                     work whose handler rearms the delayed work.
- * @work: the delayed work struct
+ * @dwork: the delayed work struct
  */
-void cancel_rearming_delayed_work(struct work_struct *work)
+void cancel_rearming_delayed_work(struct delayed_work *dwork)
 {
-       cancel_rearming_delayed_workqueue(keventd_wq, work);
+       cancel_rearming_delayed_workqueue(keventd_wq, dwork);
 }
 EXPORT_SYMBOL(cancel_rearming_delayed_work);
 
 /**
  * execute_in_process_context - reliably execute the routine with user context
  * @fn:                the function to execute
- * @data:      data to pass to the function
  * @ew:                guaranteed storage for the execute work structure (must
  *             be available when the work executes)
  *
@@ -573,15 +690,14 @@ EXPORT_SYMBOL(cancel_rearming_delayed_work);
  * Returns:    0 - function was executed
  *             1 - function was scheduled for execution
  */
-int execute_in_process_context(void (*fn)(void *data), void *data,
-                              struct execute_work *ew)
+int execute_in_process_context(work_func_t fn, struct execute_work *ew)
 {
        if (!in_interrupt()) {
-               fn(data);
+               fn(&ew->work);
                return 0;
        }
 
-       INIT_WORK(&ew->work, fn, data);
+       INIT_WORK(&ew->work, fn);
        schedule_work(&ew->work);
 
        return 1;
@@ -609,7 +725,6 @@ int current_is_keventd(void)
 
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 /* Take the work from this (downed) CPU. */
 static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
 {
@@ -642,7 +757,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                mutex_lock(&workqueue_mutex);
                /* Create a new workqueue thread for it. */
                list_for_each_entry(wq, &workqueues, list) {
-                       if (!create_workqueue_thread(wq, hotcpu)) {
+                       if (!create_workqueue_thread(wq, hotcpu, 0)) {
                                printk("workqueue for %i failed\n", hotcpu);
                                return NOTIFY_BAD;
                        }
@@ -692,7 +807,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 
        return NOTIFY_OK;
 }
-#endif
 
 void init_workqueues(void)
 {
index 734ce95..47b172d 100644 (file)
@@ -4,6 +4,9 @@
 
 menu "Library routines"
 
+config BITREVERSE
+       tristate
+
 config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
@@ -23,6 +26,7 @@ config CRC16
 config CRC32
        tristate "CRC32 functions"
        default y
+       select BITREVERSE
        help
          This option is provided for the case where no in-kernel-tree
          modules require CRC32 functions, but a module built outside the
index d367910..0701ddd 100644 (file)
@@ -1,6 +1,7 @@
 
 config PRINTK_TIME
        bool "Show timing information on printks"
+       depends on PRINTK
        help
          Selecting this option causes timing information to be
          included in printk output.  This allows you to measure
@@ -46,6 +47,30 @@ config UNUSED_SYMBOLS
          you really need it, and what the merge plan to the mainline kernel for
          your module is.
 
+config DEBUG_FS
+       bool "Debug Filesystem"
+       depends on SYSFS
+       help
+         debugfs is a virtual file system that kernel developers use to put
+         debugging files into.  Enable this option to be able to read and
+         write to these files.
+
+         If unsure, say N.
+
+config HEADERS_CHECK
+       bool "Run 'make headers_check' when building vmlinux"
+       depends on !UML
+       help
+         This option will extract the user-visible kernel headers whenever
+         building the kernel, and will run basic sanity checks on them to
+         ensure that exported files do not attempt to include files which
+         were not exported, etc.
+
+         If you're making modifications to header files which are
+         relevant for userspace, say 'Y', and check the headers
+         exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
+         your build tree), to make sure they're suitable.
+
 config DEBUG_KERNEL
        bool "Kernel debugging"
        help
@@ -284,7 +309,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 || SUPERH
+       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG
        default !EMBEDDED
        help
          Say Y here to make BUG() panics output the file name and line number
@@ -301,16 +326,6 @@ config DEBUG_INFO
 
          If unsure, say N.
 
-config DEBUG_FS
-       bool "Debug Filesystem"
-       depends on SYSFS
-       help
-         debugfs is a virtual file system that kernel developers use to put
-         debugging files into.  Enable this option to be able to read and
-         write to these files.
-
-         If unsure, say N.
-
 config DEBUG_VM
        bool "Debug VM"
        depends on DEBUG_KERNEL
@@ -371,20 +386,6 @@ config FORCED_INLINING
          become the default in the future, until then this option is there to
          test gcc for this.
 
-config HEADERS_CHECK
-       bool "Run 'make headers_check' when building vmlinux"
-       depends on !UML
-       help
-         This option will extract the user-visible kernel headers whenever
-         building the kernel, and will run basic sanity checks on them to
-         ensure that exported files do not attempt to include files which
-         were not exported, etc.
-
-         If you're making modifications to header files which are
-         relevant for userspace, say 'Y', and check the headers
-         exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
-         your build tree), to make sure they're suitable.
-
 config RCU_TORTURE_TEST
        tristate "torture tests for RCU"
        depends on DEBUG_KERNEL
@@ -401,6 +402,7 @@ config RCU_TORTURE_TEST
 
 config LKDTM
        tristate "Linux Kernel Dump Test Tool Module"
+       depends on DEBUG_KERNEL
        depends on KPROBES
        default n
        help
@@ -412,3 +414,36 @@ config LKDTM
 
        Documentation on how to use the module can be found in
        drivers/misc/lkdtm.c
+
+config FAULT_INJECTION
+       bool "Fault-injection framework"
+       depends on DEBUG_KERNEL
+       depends on STACKTRACE
+       select FRAME_POINTER
+       help
+         Provide fault-injection framework.
+         For more details, see Documentation/fault-injection/.
+
+config FAILSLAB
+       bool "Fault-injection capability for kmalloc"
+       depends on FAULT_INJECTION
+       help
+         Provide fault-injection capability for kmalloc.
+
+config FAIL_PAGE_ALLOC
+       bool "Fault-injection capabilitiy for alloc_pages()"
+       depends on FAULT_INJECTION
+       help
+         Provide fault-injection capability for alloc_pages().
+
+config FAIL_MAKE_REQUEST
+       bool "Fault-injection capabilitiy for disk IO"
+       depends on FAULT_INJECTION
+       help
+         Provide fault-injection capability for disk IO.
+
+config FAULT_INJECTION_DEBUG_FS
+       bool "Debugfs entries for fault-injection capabilities"
+       depends on FAULT_INJECTION && SYSFS && DEBUG_FS
+       help
+         Enable configuration of fault-injection capabilities via debugfs.
index cf98fab..2d6106a 100644 (file)
@@ -25,7 +25,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
-lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_PLIST) += plist.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
@@ -35,6 +35,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
 endif
 
+obj-$(CONFIG_BITREVERSE) += bitrev.o
 obj-$(CONFIG_CRC_CCITT)        += crc-ccitt.o
 obj-$(CONFIG_CRC16)    += crc16.o
 obj-$(CONFIG_CRC32)    += crc32.o
@@ -54,6 +55,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o
 obj-$(CONFIG_AUDIT_GENERIC) += audit.o
 
 obj-$(CONFIG_SWIOTLB) += swiotlb.o
+obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+
+lib-$(CONFIG_GENERIC_BUG) += bug.o
 
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
diff --git a/lib/bitrev.c b/lib/bitrev.c
new file mode 100644 (file)
index 0000000..989aff7
--- /dev/null
@@ -0,0 +1,58 @@
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/bitrev.h>
+
+MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
+MODULE_DESCRIPTION("Bit ordering reversal functions");
+MODULE_LICENSE("GPL");
+
+const u8 byte_rev_table[256] = {
+       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+EXPORT_SYMBOL_GPL(byte_rev_table);
+
+static __always_inline u16 bitrev16(u16 x)
+{
+       return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
+}
+
+/**
+ * bitrev32 - reverse the order of bits in a u32 value
+ * @x: value to be bit-reversed
+ */
+u32 bitrev32(u32 x)
+{
+       return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
+}
+EXPORT_SYMBOL(bitrev32);
diff --git a/lib/bug.c b/lib/bug.c
new file mode 100644 (file)
index 0000000..014b582
--- /dev/null
+++ b/lib/bug.c
@@ -0,0 +1,163 @@
+/*
+  Generic support for BUG()
+
+  This respects the following config options:
+
+  CONFIG_BUG - emit BUG traps.  Nothing happens without this.
+  CONFIG_GENERIC_BUG - enable this code.
+  CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
+
+  CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
+  (though they're generally always on).
+
+  CONFIG_GENERIC_BUG is set by each architecture using this code.
+
+  To use this, your architecture must:
+
+  1. Set up the config options:
+     - Enable CONFIG_GENERIC_BUG if CONFIG_BUG
+
+  2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
+     - Define HAVE_ARCH_BUG
+     - Implement BUG() to generate a faulting instruction
+     - NOTE: struct bug_entry does not have "file" or "line" entries
+       when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
+       the values accordingly.
+
+  3. Implement the trap
+     - In the illegal instruction trap handler (typically), verify
+       that the fault was in kernel mode, and call report_bug()
+     - report_bug() will return whether it was a false alarm, a warning,
+       or an actual bug.
+     - You must implement the is_valid_bugaddr(bugaddr) callback which
+       returns true if the eip is a real kernel address, and it points
+       to the expected BUG trap instruction.
+
+    Jeremy Fitzhardinge <jeremy@goop.org> 2006
+ */
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/bug.h>
+
+extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
+
+#ifdef CONFIG_MODULES
+static LIST_HEAD(module_bug_list);
+
+static const struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+       struct module *mod;
+
+       list_for_each_entry(mod, &module_bug_list, bug_list) {
+               const struct bug_entry *bug = mod->bug_table;
+               unsigned i;
+
+               for (i = 0; i < mod->num_bugs; ++i, ++bug)
+                       if (bugaddr == bug->bug_addr)
+                               return bug;
+       }
+       return NULL;
+}
+
+int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+                       struct module *mod)
+{
+       char *secstrings;
+       unsigned int i;
+
+       mod->bug_table = NULL;
+       mod->num_bugs = 0;
+
+       /* Find the __bug_table section, if present */
+       secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+       for (i = 1; i < hdr->e_shnum; i++) {
+               if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
+                       continue;
+               mod->bug_table = (void *) sechdrs[i].sh_addr;
+               mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
+               break;
+       }
+
+       /*
+        * Strictly speaking this should have a spinlock to protect against
+        * traversals, but since we only traverse on BUG()s, a spinlock
+        * could potentially lead to deadlock and thus be counter-productive.
+        */
+       list_add(&mod->bug_list, &module_bug_list);
+
+       return 0;
+}
+
+void module_bug_cleanup(struct module *mod)
+{
+       list_del(&mod->bug_list);
+}
+
+#else
+
+static inline const struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+       return NULL;
+}
+#endif
+
+const struct bug_entry *find_bug(unsigned long bugaddr)
+{
+       const struct bug_entry *bug;
+
+       for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
+               if (bugaddr == bug->bug_addr)
+                       return bug;
+
+       return module_find_bug(bugaddr);
+}
+
+enum bug_trap_type report_bug(unsigned long bugaddr)
+{
+       const struct bug_entry *bug;
+       const char *file;
+       unsigned line, warning;
+
+       if (!is_valid_bugaddr(bugaddr))
+               return BUG_TRAP_TYPE_NONE;
+
+       bug = find_bug(bugaddr);
+
+       printk(KERN_EMERG "------------[ cut here ]------------\n");
+
+       file = NULL;
+       line = 0;
+       warning = 0;
+
+       if (bug) {
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+               file = bug->file;
+               line = bug->line;
+#endif
+               warning = (bug->flags & BUGFLAG_WARNING) != 0;
+       }
+
+       if (warning) {
+               /* this is a WARN_ON rather than BUG/BUG_ON */
+               if (file)
+                       printk(KERN_ERR "Badness at %s:%u\n",
+                              file, line);
+               else
+                       printk(KERN_ERR "Badness at %p "
+                              "[verbose debug info unavailable]\n",
+                              (void *)bugaddr);
+
+               dump_stack();
+               return BUG_TRAP_TYPE_WARN;
+       }
+
+       if (file)
+               printk(KERN_CRIT "kernel BUG at %s:%u!\n",
+                      file, line);
+       else
+               printk(KERN_CRIT "Kernel BUG at %p "
+                      "[verbose debug info unavailable]\n",
+                      (void *)bugaddr);
+
+       return BUG_TRAP_TYPE_BUG;
+}
index 0331ed8..8a5b530 100644 (file)
 #include <linux/kernel.h>
 #include <linux/string.h>
 
+/*
+ *     If a hyphen was found in get_option, this will handle the
+ *     range of numbers, M-N.  This will expand the range and insert
+ *     the values[M, M+1, ..., N] into the ints array in get_options.
+ */
+
+static int get_range(char **str, int *pint)
+{
+       int x, inc_counter, upper_range;
+
+       (*str)++;
+       upper_range = simple_strtol((*str), NULL, 0);
+       inc_counter = upper_range - *pint;
+       for (x = *pint; x < upper_range; x++)
+               *pint++ = x;
+       return inc_counter;
+}
 
 /**
  *     get_option - Parse integer from an option string
@@ -29,6 +46,7 @@
  *     0 : no int in string
  *     1 : int found, no subsequent comma
  *     2 : int found including a subsequent comma
+ *     3 : hyphen found to denote a range
  */
 
 int get_option (char **str, int *pint)
@@ -44,6 +62,8 @@ int get_option (char **str, int *pint)
                (*str)++;
                return 2;
        }
+       if (**str == '-')
+               return 3;
 
        return 1;
 }
@@ -55,7 +75,8 @@ int get_option (char **str, int *pint)
  *     @ints: integer array
  *
  *     This function parses a string containing a comma-separated
- *     list of integers.  The parse halts when the array is
+ *     list of integers, a hyphen-separated range of _positive_ integers,
+ *     or a combination of both.  The parse halts when the array is
  *     full, or when no more numbers can be retrieved from the
  *     string.
  *
@@ -72,6 +93,18 @@ char *get_options(const char *str, int nints, int *ints)
                res = get_option ((char **)&str, ints + i);
                if (res == 0)
                        break;
+               if (res == 3) {
+                       int range_nums;
+                       range_nums = get_range((char **)&str, ints + i);
+                       if (range_nums < 0)
+                               break;
+                       /*
+                        * Decrement the result by one to leave out the
+                        * last number in the range.  The next iteration
+                        * will handle the upper number in the range
+                        */
+                       i += (range_nums - 1);
+               }
                i++;
                if (res == 1)
                        break;
index 285fd9b..bfc3331 100644 (file)
@@ -235,23 +235,8 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
 }
 #endif
 
-/**
- * bitreverse - reverse the order of bits in a u32 value
- * @x: value to be bit-reversed
- */
-u32 bitreverse(u32 x)
-{
-       x = (x >> 16) | (x << 16);
-       x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
-       x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
-       x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
-       x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
-       return x;
-}
-
 EXPORT_SYMBOL(crc32_le);
 EXPORT_SYMBOL(crc32_be);
-EXPORT_SYMBOL(bitreverse);
 
 /*
  * A brief CRC tutorial.
@@ -400,10 +385,7 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len)
 static void bytereverse(unsigned char *buf, size_t len)
 {
        while (len--) {
-               unsigned char x = *buf;
-               x = (x >> 4) | (x << 4);
-               x = (x >> 2 & 0x33) | (x << 2 & 0xcc);
-               x = (x >> 1 & 0x55) | (x << 1 & 0xaa);
+               unsigned char x = bitrev8(*buf);
                *buf++ = x;
        }
 }
@@ -460,11 +442,11 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len)
        /* Now swap it around for the other test */
 
        bytereverse(buf, len + 4);
-       init = bitreverse(init);
-       crc2 = bitreverse(crc1);
-       if (crc1 != bitreverse(crc2))
+       init = bitrev32(init);
+       crc2 = bitrev32(crc1);
+       if (crc1 != bitrev32(crc2))
                printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n",
-                      crc1, crc2, bitreverse(crc2));
+                      crc1, crc2, bitrev32(crc2));
        crc1 = crc32_le(init, buf, len);
        if (crc1 != crc2)
                printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1,
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
new file mode 100644 (file)
index 0000000..d143c0f
--- /dev/null
@@ -0,0 +1,336 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/unwind.h>
+#include <linux/stacktrace.h>
+#include <linux/kallsyms.h>
+#include <linux/fault-inject.h>
+
+/*
+ * setup_fault_attr() is a helper function for various __setup handlers, so it
+ * returns 0 on error, because that is what __setup handlers do.
+ */
+int __init setup_fault_attr(struct fault_attr *attr, char *str)
+{
+       unsigned long probability;
+       unsigned long interval;
+       int times;
+       int space;
+
+       /* "<interval>,<probability>,<space>,<times>" */
+       if (sscanf(str, "%lu,%lu,%d,%d",
+                       &interval, &probability, &space, &times) < 4) {
+               printk(KERN_WARNING
+                       "FAULT_INJECTION: failed to parse arguments\n");
+               return 0;
+       }
+
+       attr->probability = probability;
+       attr->interval = interval;
+       atomic_set(&attr->times, times);
+       atomic_set(&attr->space, space);
+
+       return 1;
+}
+
+static void fail_dump(struct fault_attr *attr)
+{
+       if (attr->verbose > 0)
+               printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n");
+       if (attr->verbose > 1)
+               dump_stack();
+}
+
+#define atomic_dec_not_zero(v)         atomic_add_unless((v), -1, 0)
+
+static bool fail_task(struct fault_attr *attr, struct task_struct *task)
+{
+       return !in_interrupt() && task->make_it_fail;
+}
+
+#define MAX_STACK_TRACE_DEPTH 32
+
+#ifdef CONFIG_STACK_UNWIND
+
+static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info,
+                                               void *arg)
+{
+       int depth;
+       struct fault_attr *attr = arg;
+       bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
+
+       for (depth = 0; depth < attr->stacktrace_depth
+                       && unwind(info) == 0 && UNW_PC(info); depth++) {
+               if (arch_unw_user_mode(info))
+                       break;
+               if (attr->reject_start <= UNW_PC(info) &&
+                              UNW_PC(info) < attr->reject_end)
+                       return false;
+               if (attr->require_start <= UNW_PC(info) &&
+                              UNW_PC(info) < attr->require_end)
+                       found = true;
+       }
+       return found;
+}
+
+static bool fail_stacktrace(struct fault_attr *attr)
+{
+       struct unwind_frame_info info;
+
+       return unwind_init_running(&info, fail_stacktrace_callback, attr);
+}
+
+#elif defined(CONFIG_STACKTRACE)
+
+static bool fail_stacktrace(struct fault_attr *attr)
+{
+       struct stack_trace trace;
+       int depth = attr->stacktrace_depth;
+       unsigned long entries[MAX_STACK_TRACE_DEPTH];
+       int n;
+       bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
+
+       if (depth == 0)
+               return found;
+
+       trace.nr_entries = 0;
+       trace.entries = entries;
+       trace.max_entries = depth;
+       trace.skip = 1;
+       trace.all_contexts = 0;
+
+       save_stack_trace(&trace, NULL);
+       for (n = 0; n < trace.nr_entries; n++) {
+               if (attr->reject_start <= entries[n] &&
+                              entries[n] < attr->reject_end)
+                       return false;
+               if (attr->require_start <= entries[n] &&
+                              entries[n] < attr->require_end)
+                       found = true;
+       }
+       return found;
+}
+
+#else
+
+static inline bool fail_stacktrace(struct fault_attr *attr)
+{
+       static bool firsttime = true;
+
+       if (firsttime) {
+               printk(KERN_WARNING
+               "This architecture does not implement save_stack_trace()\n");
+               firsttime = false;
+       }
+       return false;
+}
+
+#endif
+
+/*
+ * This code is stolen from failmalloc-1.0
+ * http://www.nongnu.org/failmalloc/
+ */
+
+bool should_fail(struct fault_attr *attr, ssize_t size)
+{
+       if (attr->task_filter && !fail_task(attr, current))
+               return false;
+
+       if (atomic_read(&attr->times) == 0)
+               return false;
+
+       if (atomic_read(&attr->space) > size) {
+               atomic_sub(size, &attr->space);
+               return false;
+       }
+
+       if (attr->interval > 1) {
+               attr->count++;
+               if (attr->count % attr->interval)
+                       return false;
+       }
+
+       if (attr->probability <= random32() % 100)
+               return false;
+
+       if (!fail_stacktrace(attr))
+               return false;
+
+       fail_dump(attr);
+
+       if (atomic_read(&attr->times) != -1)
+               atomic_dec_not_zero(&attr->times);
+
+       return true;
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static void debugfs_ul_set(void *data, u64 val)
+{
+       *(unsigned long *)data = val;
+}
+
+static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
+{
+       *(unsigned long *)data =
+               val < MAX_STACK_TRACE_DEPTH ?
+               val : MAX_STACK_TRACE_DEPTH;
+}
+
+static u64 debugfs_ul_get(void *data)
+{
+       return *(unsigned long *)data;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
+
+static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
+                               struct dentry *parent, unsigned long *value)
+{
+       return debugfs_create_file(name, mode, parent, value, &fops_ul);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
+                       debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
+
+static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+       const char *name, mode_t mode,
+       struct dentry *parent, unsigned long *value)
+{
+       return debugfs_create_file(name, mode, parent, value,
+                                  &fops_ul_MAX_STACK_TRACE_DEPTH);
+}
+
+static void debugfs_atomic_t_set(void *data, u64 val)
+{
+       atomic_set((atomic_t *)data, val);
+}
+
+static u64 debugfs_atomic_t_get(void *data)
+{
+       return atomic_read((atomic_t *)data);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
+                       debugfs_atomic_t_set, "%lld\n");
+
+static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
+                               struct dentry *parent, atomic_t *value)
+{
+       return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
+}
+
+void cleanup_fault_attr_dentries(struct fault_attr *attr)
+{
+       debugfs_remove(attr->dentries.probability_file);
+       attr->dentries.probability_file = NULL;
+
+       debugfs_remove(attr->dentries.interval_file);
+       attr->dentries.interval_file = NULL;
+
+       debugfs_remove(attr->dentries.times_file);
+       attr->dentries.times_file = NULL;
+
+       debugfs_remove(attr->dentries.space_file);
+       attr->dentries.space_file = NULL;
+
+       debugfs_remove(attr->dentries.verbose_file);
+       attr->dentries.verbose_file = NULL;
+
+       debugfs_remove(attr->dentries.task_filter_file);
+       attr->dentries.task_filter_file = NULL;
+
+       debugfs_remove(attr->dentries.stacktrace_depth_file);
+       attr->dentries.stacktrace_depth_file = NULL;
+
+       debugfs_remove(attr->dentries.require_start_file);
+       attr->dentries.require_start_file = NULL;
+
+       debugfs_remove(attr->dentries.require_end_file);
+       attr->dentries.require_end_file = NULL;
+
+       debugfs_remove(attr->dentries.reject_start_file);
+       attr->dentries.reject_start_file = NULL;
+
+       debugfs_remove(attr->dentries.reject_end_file);
+       attr->dentries.reject_end_file = NULL;
+
+       if (attr->dentries.dir)
+               WARN_ON(!simple_empty(attr->dentries.dir));
+
+       debugfs_remove(attr->dentries.dir);
+       attr->dentries.dir = NULL;
+}
+
+int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
+{
+       mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+       struct dentry *dir;
+
+       memset(&attr->dentries, 0, sizeof(attr->dentries));
+
+       dir = debugfs_create_dir(name, NULL);
+       if (!dir)
+               goto fail;
+       attr->dentries.dir = dir;
+
+       attr->dentries.probability_file =
+               debugfs_create_ul("probability", mode, dir, &attr->probability);
+
+       attr->dentries.interval_file =
+               debugfs_create_ul("interval", mode, dir, &attr->interval);
+
+       attr->dentries.times_file =
+               debugfs_create_atomic_t("times", mode, dir, &attr->times);
+
+       attr->dentries.space_file =
+               debugfs_create_atomic_t("space", mode, dir, &attr->space);
+
+       attr->dentries.verbose_file =
+               debugfs_create_ul("verbose", mode, dir, &attr->verbose);
+
+       attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
+                                               mode, dir, &attr->task_filter);
+
+       attr->dentries.stacktrace_depth_file =
+               debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+                       "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
+
+       attr->dentries.require_start_file =
+               debugfs_create_ul("require-start", mode, dir, &attr->require_start);
+
+       attr->dentries.require_end_file =
+               debugfs_create_ul("require-end", mode, dir, &attr->require_end);
+
+       attr->dentries.reject_start_file =
+               debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
+
+       attr->dentries.reject_end_file =
+               debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
+
+
+       if (!attr->dentries.probability_file || !attr->dentries.interval_file
+           || !attr->dentries.times_file || !attr->dentries.space_file
+           || !attr->dentries.verbose_file || !attr->dentries.task_filter_file
+           || !attr->dentries.stacktrace_depth_file
+           || !attr->dentries.require_start_file
+           || !attr->dentries.require_end_file
+           || !attr->dentries.reject_start_file
+           || !attr->dentries.reject_end_file
+           )
+               goto fail;
+
+       return 0;
+fail:
+       cleanup_fault_attr_dentries(attr);
+       return -ENOMEM;
+}
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
index 16d2143..7185353 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -33,7 +33,7 @@
 #include <linux/string.h>
 #include <linux/idr.h>
 
-static kmem_cache_t *idr_layer_cache;
+static struct kmem_cache *idr_layer_cache;
 
 static struct idr_layer *alloc_layer(struct idr *idp)
 {
@@ -445,7 +445,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
 }
 EXPORT_SYMBOL(idr_replace);
 
-static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache,
+static void idr_cache_ctor(void * idr_layer, struct kmem_cache *idr_layer_cache,
                unsigned long flags)
 {
        memset(idr_layer, 0, sizeof(struct idr_layer));
index 744a4b1..7ce6dc1 100644 (file)
@@ -111,10 +111,9 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
        len = get_kobj_path_length(kobj);
        if (len == 0)
                return NULL;
-       path = kmalloc(len, gfp_mask);
+       path = kzalloc(len, gfp_mask);
        if (!path)
                return NULL;
-       memset(path, 0x00, len);
        fill_kobj_path(kobj, path, len);
 
        return path;
index 7ba9d82..4350ba9 100644 (file)
@@ -21,13 +21,15 @@ void __list_add(struct list_head *new,
                              struct list_head *next)
 {
        if (unlikely(next->prev != prev)) {
-               printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n",
-                       prev, next->prev);
+               printk(KERN_ERR "list_add corruption. next->prev should be "
+                       "prev (%p), but was %p. (next=%p).\n",
+                       prev, next->prev, next);
                BUG();
        }
        if (unlikely(prev->next != next)) {
-               printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n",
-                       next, prev->next);
+               printk(KERN_ERR "list_add corruption. prev->next should be "
+                       "next (%p), but was %p. (prev=%p).\n",
+                       next, prev->next, prev);
                BUG();
        }
        next->prev = new;
index 7945787..280332c 100644 (file)
@@ -963,7 +963,9 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
                        printk("failed|");
                } else {
                        unexpected_testcase_failures++;
+
                        printk("FAILED|");
+                       dump_stack();
                }
        } else {
                testcase_successes++;
index aa9bfd0..d69ddbe 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
  * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
+ * Copyright (C) 2006 Nick Piggin
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -30,6 +31,7 @@
 #include <linux/gfp.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
+#include <linux/rcupdate.h>
 
 
 #ifdef __KERNEL__
@@ -45,7 +47,9 @@
        ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
 struct radix_tree_node {
+       unsigned int    height;         /* Height from the bottom */
        unsigned int    count;
+       struct rcu_head rcu_head;
        void            *slots[RADIX_TREE_MAP_SIZE];
        unsigned long   tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
 };
@@ -63,7 +67,7 @@ static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly;
 /*
  * Radix tree node cache.
  */
-static kmem_cache_t *radix_tree_node_cachep;
+static struct kmem_cache *radix_tree_node_cachep;
 
 /*
  * Per-cpu pool of preloaded nodes
@@ -100,13 +104,21 @@ radix_tree_node_alloc(struct radix_tree_root *root)
                        rtp->nr--;
                }
        }
+       BUG_ON(radix_tree_is_direct_ptr(ret));
        return ret;
 }
 
+static void radix_tree_node_rcu_free(struct rcu_head *head)
+{
+       struct radix_tree_node *node =
+                       container_of(head, struct radix_tree_node, rcu_head);
+       kmem_cache_free(radix_tree_node_cachep, node);
+}
+
 static inline void
 radix_tree_node_free(struct radix_tree_node *node)
 {
-       kmem_cache_free(radix_tree_node_cachep, node);
+       call_rcu(&node->rcu_head, radix_tree_node_rcu_free);
 }
 
 /*
@@ -222,11 +234,12 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
        }
 
        do {
+               unsigned int newheight;
                if (!(node = radix_tree_node_alloc(root)))
                        return -ENOMEM;
 
                /* Increase the height.  */
-               node->slots[0] = root->rnode;
+               node->slots[0] = radix_tree_direct_to_ptr(root->rnode);
 
                /* Propagate the aggregated tag info into the new root */
                for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
@@ -234,9 +247,11 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
                                tag_set(node, tag, 0);
                }
 
+               newheight = root->height+1;
+               node->height = newheight;
                node->count = 1;
-               root->rnode = node;
-               root->height++;
+               rcu_assign_pointer(root->rnode, node);
+               root->height = newheight;
        } while (height > root->height);
 out:
        return 0;
@@ -258,6 +273,8 @@ int radix_tree_insert(struct radix_tree_root *root,
        int offset;
        int error;
 
+       BUG_ON(radix_tree_is_direct_ptr(item));
+
        /* Make sure the tree is high enough.  */
        if (index > radix_tree_maxindex(root->height)) {
                error = radix_tree_extend(root, index);
@@ -275,11 +292,12 @@ int radix_tree_insert(struct radix_tree_root *root,
                        /* Have to add a child node.  */
                        if (!(slot = radix_tree_node_alloc(root)))
                                return -ENOMEM;
+                       slot->height = height;
                        if (node) {
-                               node->slots[offset] = slot;
+                               rcu_assign_pointer(node->slots[offset], slot);
                                node->count++;
                        } else
-                               root->rnode = slot;
+                               rcu_assign_pointer(root->rnode, slot);
                }
 
                /* Go a level down */
@@ -295,11 +313,11 @@ int radix_tree_insert(struct radix_tree_root *root,
 
        if (node) {
                node->count++;
-               node->slots[offset] = item;
+               rcu_assign_pointer(node->slots[offset], item);
                BUG_ON(tag_get(node, 0, offset));
                BUG_ON(tag_get(node, 1, offset));
        } else {
-               root->rnode = item;
+               rcu_assign_pointer(root->rnode, radix_tree_ptr_to_direct(item));
                BUG_ON(root_tag_get(root, 0));
                BUG_ON(root_tag_get(root, 1));
        }
@@ -308,49 +326,54 @@ int radix_tree_insert(struct radix_tree_root *root,
 }
 EXPORT_SYMBOL(radix_tree_insert);
 
-static inline void **__lookup_slot(struct radix_tree_root *root,
-                                  unsigned long index)
+/**
+ *     radix_tree_lookup_slot    -    lookup a slot in a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
+ *
+ *     Returns:  the slot corresponding to the position @index in the
+ *     radix tree @root. This is useful for update-if-exists operations.
+ *
+ *     This function cannot be called under rcu_read_lock, it must be
+ *     excluded from writers, as must the returned slot for subsequent
+ *     use by radix_tree_deref_slot() and radix_tree_replace slot.
+ *     Caller must hold tree write locked across slot lookup and
+ *     replace.
+ */
+void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
 {
        unsigned int height, shift;
-       struct radix_tree_node **slot;
-
-       height = root->height;
+       struct radix_tree_node *node, **slot;
 
-       if (index > radix_tree_maxindex(height))
+       node = root->rnode;
+       if (node == NULL)
                return NULL;
 
-       if (height == 0 && root->rnode)
+       if (radix_tree_is_direct_ptr(node)) {
+               if (index > 0)
+                       return NULL;
                return (void **)&root->rnode;
+       }
+
+       height = node->height;
+       if (index > radix_tree_maxindex(height))
+               return NULL;
 
        shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-       slot = &root->rnode;
 
-       while (height > 0) {
-               if (*slot == NULL)
+       do {
+               slot = (struct radix_tree_node **)
+                       (node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));
+               node = *slot;
+               if (node == NULL)
                        return NULL;
 
-               slot = (struct radix_tree_node **)
-                       ((*slot)->slots +
-                               ((index >> shift) & RADIX_TREE_MAP_MASK));
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
-       }
+       } while (height > 0);
 
        return (void **)slot;
 }
-
-/**
- *     radix_tree_lookup_slot    -    lookup a slot in a radix tree
- *     @root:          radix tree root
- *     @index:         index key
- *
- *     Lookup the slot corresponding to the position @index in the radix tree
- *     @root. This is useful for update-if-exists operations.
- */
-void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
-{
-       return __lookup_slot(root, index);
-}
 EXPORT_SYMBOL(radix_tree_lookup_slot);
 
 /**
@@ -359,13 +382,45 @@ EXPORT_SYMBOL(radix_tree_lookup_slot);
  *     @index:         index key
  *
  *     Lookup the item at the position @index in the radix tree @root.
+ *
+ *     This function can be called under rcu_read_lock, however the caller
+ *     must manage lifetimes of leaf nodes (eg. RCU may also be used to free
+ *     them safely). No RCU barriers are required to access or modify the
+ *     returned item, however.
  */
 void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
 {
-       void **slot;
+       unsigned int height, shift;
+       struct radix_tree_node *node, **slot;
+
+       node = rcu_dereference(root->rnode);
+       if (node == NULL)
+               return NULL;
+
+       if (radix_tree_is_direct_ptr(node)) {
+               if (index > 0)
+                       return NULL;
+               return radix_tree_direct_to_ptr(node);
+       }
+
+       height = node->height;
+       if (index > radix_tree_maxindex(height))
+               return NULL;
+
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
-       slot = __lookup_slot(root, index);
-       return slot != NULL ? *slot : NULL;
+       do {
+               slot = (struct radix_tree_node **)
+                       (node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));
+               node = rcu_dereference(*slot);
+               if (node == NULL)
+                       return NULL;
+
+               shift -= RADIX_TREE_MAP_SHIFT;
+               height--;
+       } while (height > 0);
+
+       return node;
 }
 EXPORT_SYMBOL(radix_tree_lookup);
 
@@ -495,27 +550,30 @@ int radix_tree_tag_get(struct radix_tree_root *root,
                        unsigned long index, unsigned int tag)
 {
        unsigned int height, shift;
-       struct radix_tree_node *slot;
+       struct radix_tree_node *node;
        int saw_unset_tag = 0;
 
-       height = root->height;
-       if (index > radix_tree_maxindex(height))
-               return 0;
-
        /* check the root's tag bit */
        if (!root_tag_get(root, tag))
                return 0;
 
-       if (height == 0)
-               return 1;
+       node = rcu_dereference(root->rnode);
+       if (node == NULL)
+               return 0;
+
+       if (radix_tree_is_direct_ptr(node))
+               return (index == 0);
+
+       height = node->height;
+       if (index > radix_tree_maxindex(height))
+               return 0;
 
        shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
-       slot = root->rnode;
 
        for ( ; ; ) {
                int offset;
 
-               if (slot == NULL)
+               if (node == NULL)
                        return 0;
 
                offset = (index >> shift) & RADIX_TREE_MAP_MASK;
@@ -524,15 +582,15 @@ int radix_tree_tag_get(struct radix_tree_root *root,
                 * This is just a debug check.  Later, we can bale as soon as
                 * we see an unset tag.
                 */
-               if (!tag_get(slot, tag, offset))
+               if (!tag_get(node, tag, offset))
                        saw_unset_tag = 1;
                if (height == 1) {
-                       int ret = tag_get(slot, tag, offset);
+                       int ret = tag_get(node, tag, offset);
 
                        BUG_ON(ret && saw_unset_tag);
                        return !!ret;
                }
-               slot = slot->slots[offset];
+               node = rcu_dereference(node->slots[offset]);
                shift -= RADIX_TREE_MAP_SHIFT;
                height--;
        }
@@ -541,47 +599,45 @@ EXPORT_SYMBOL(radix_tree_tag_get);
 #endif
 
 static unsigned int
-__lookup(struct radix_tree_root *root, void **results, unsigned long index,
+__lookup(struct radix_tree_node *slot, void **results, unsigned long index,
        unsigned int max_items, unsigned long *next_index)
 {
        unsigned int nr_found = 0;
        unsigned int shift, height;
-       struct radix_tree_node *slot;
        unsigned long i;
 
-       height = root->height;
-       if (height == 0) {
-               if (root->rnode && index == 0)
-                       results[nr_found++] = root->rnode;
+       height = slot->height;
+       if (height == 0)
                goto out;
-       }
-
        shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-       slot = root->rnode;
 
        for ( ; height > 1; height--) {
-
-               for (i = (index >> shift) & RADIX_TREE_MAP_MASK ;
-                               i < RADIX_TREE_MAP_SIZE; i++) {
+               i = (index >> shift) & RADIX_TREE_MAP_MASK;
+               for (;;) {
                        if (slot->slots[i] != NULL)
                                break;
                        index &= ~((1UL << shift) - 1);
                        index += 1UL << shift;
                        if (index == 0)
                                goto out;       /* 32-bit wraparound */
+                       i++;
+                       if (i == RADIX_TREE_MAP_SIZE)
+                               goto out;
                }
-               if (i == RADIX_TREE_MAP_SIZE)
-                       goto out;
 
                shift -= RADIX_TREE_MAP_SHIFT;
-               slot = slot->slots[i];
+               slot = rcu_dereference(slot->slots[i]);
+               if (slot == NULL)
+                       goto out;
        }
 
        /* Bottom level: grab some items */
        for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
+               struct radix_tree_node *node;
                index++;
-               if (slot->slots[i]) {
-                       results[nr_found++] = slot->slots[i];
+               node = slot->slots[i];
+               if (node) {
+                       results[nr_found++] = rcu_dereference(node);
                        if (nr_found == max_items)
                                goto out;
                }
@@ -603,28 +659,51 @@ out:
  *     *@results.
  *
  *     The implementation is naive.
+ *
+ *     Like radix_tree_lookup, radix_tree_gang_lookup may be called under
+ *     rcu_read_lock. In this case, rather than the returned results being
+ *     an atomic snapshot of the tree at a single point in time, the semantics
+ *     of an RCU protected gang lookup are as though multiple radix_tree_lookups
+ *     have been issued in individual locks, and results stored in 'results'.
  */
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items)
 {
-       const unsigned long max_index = radix_tree_maxindex(root->height);
+       unsigned long max_index;
+       struct radix_tree_node *node;
        unsigned long cur_index = first_index;
-       unsigned int ret = 0;
+       unsigned int ret;
+
+       node = rcu_dereference(root->rnode);
+       if (!node)
+               return 0;
 
+       if (radix_tree_is_direct_ptr(node)) {
+               if (first_index > 0)
+                       return 0;
+               node = radix_tree_direct_to_ptr(node);
+               results[0] = rcu_dereference(node);
+               return 1;
+       }
+
+       max_index = radix_tree_maxindex(node->height);
+
+       ret = 0;
        while (ret < max_items) {
                unsigned int nr_found;
                unsigned long next_index;       /* Index of next search */
 
                if (cur_index > max_index)
                        break;
-               nr_found = __lookup(root, results + ret, cur_index,
+               nr_found = __lookup(node, results + ret, cur_index,
                                        max_items - ret, &next_index);
                ret += nr_found;
                if (next_index == 0)
                        break;
                cur_index = next_index;
        }
+
        return ret;
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup);
@@ -634,55 +713,64 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
  * open-coding the search.
  */
 static unsigned int
-__lookup_tag(struct radix_tree_root *root, void **results, unsigned long index,
+__lookup_tag(struct radix_tree_node *slot, void **results, unsigned long index,
        unsigned int max_items, unsigned long *next_index, unsigned int tag)
 {
        unsigned int nr_found = 0;
-       unsigned int shift;
-       unsigned int height = root->height;
-       struct radix_tree_node *slot;
+       unsigned int shift, height;
 
-       if (height == 0) {
-               if (root->rnode && index == 0)
-                       results[nr_found++] = root->rnode;
+       height = slot->height;
+       if (height == 0)
                goto out;
-       }
-
-       shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
-       slot = root->rnode;
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
-       do {
-               unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK;
+       while (height > 0) {
+               unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK ;
 
-               for ( ; i < RADIX_TREE_MAP_SIZE; i++) {
-                       if (tag_get(slot, tag, i)) {
-                               BUG_ON(slot->slots[i] == NULL);
+               for (;;) {
+                       if (tag_get(slot, tag, i))
                                break;
-                       }
                        index &= ~((1UL << shift) - 1);
                        index += 1UL << shift;
                        if (index == 0)
                                goto out;       /* 32-bit wraparound */
+                       i++;
+                       if (i == RADIX_TREE_MAP_SIZE)
+                               goto out;
                }
-               if (i == RADIX_TREE_MAP_SIZE)
-                       goto out;
                height--;
                if (height == 0) {      /* Bottom level: grab some items */
                        unsigned long j = index & RADIX_TREE_MAP_MASK;
 
                        for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
+                               struct radix_tree_node *node;
                                index++;
-                               if (tag_get(slot, tag, j)) {
-                                       BUG_ON(slot->slots[j] == NULL);
-                                       results[nr_found++] = slot->slots[j];
+                               if (!tag_get(slot, tag, j))
+                                       continue;
+                               node = slot->slots[j];
+                               /*
+                                * Even though the tag was found set, we need to
+                                * recheck that we have a non-NULL node, because
+                                * if this lookup is lockless, it may have been
+                                * subsequently deleted.
+                                *
+                                * Similar care must be taken in any place that
+                                * lookup ->slots[x] without a lock (ie. can't
+                                * rely on its value remaining the same).
+                                */
+                               if (node) {
+                                       node = rcu_dereference(node);
+                                       results[nr_found++] = node;
                                        if (nr_found == max_items)
                                                goto out;
                                }
                        }
                }
                shift -= RADIX_TREE_MAP_SHIFT;
-               slot = slot->slots[i];
-       } while (height > 0);
+               slot = rcu_dereference(slot->slots[i]);
+               if (slot == NULL)
+                       break;
+       }
 out:
        *next_index = index;
        return nr_found;
@@ -706,27 +794,44 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
                unsigned long first_index, unsigned int max_items,
                unsigned int tag)
 {
-       const unsigned long max_index = radix_tree_maxindex(root->height);
+       struct radix_tree_node *node;
+       unsigned long max_index;
        unsigned long cur_index = first_index;
-       unsigned int ret = 0;
+       unsigned int ret;
 
        /* check the root's tag bit */
        if (!root_tag_get(root, tag))
                return 0;
 
+       node = rcu_dereference(root->rnode);
+       if (!node)
+               return 0;
+
+       if (radix_tree_is_direct_ptr(node)) {
+               if (first_index > 0)
+                       return 0;
+               node = radix_tree_direct_to_ptr(node);
+               results[0] = rcu_dereference(node);
+               return 1;
+       }
+
+       max_index = radix_tree_maxindex(node->height);
+
+       ret = 0;
        while (ret < max_items) {
                unsigned int nr_found;
                unsigned long next_index;       /* Index of next search */
 
                if (cur_index > max_index)
                        break;
-               nr_found = __lookup_tag(root, results + ret, cur_index,
+               nr_found = __lookup_tag(node, results + ret, cur_index,
                                        max_items - ret, &next_index, tag);
                ret += nr_found;
                if (next_index == 0)
                        break;
                cur_index = next_index;
        }
+
        return ret;
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup_tag);
@@ -742,8 +847,19 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
                        root->rnode->count == 1 &&
                        root->rnode->slots[0]) {
                struct radix_tree_node *to_free = root->rnode;
+               void *newptr;
 
-               root->rnode = to_free->slots[0];
+               /*
+                * We don't need rcu_assign_pointer(), since we are simply
+                * moving the node from one part of the tree to another. If
+                * it was safe to dereference the old pointer to it
+                * (to_free->slots[0]), it will be safe to dereference the new
+                * one (root->rnode).
+                */
+               newptr = to_free->slots[0];
+               if (root->height == 1)
+                       newptr = radix_tree_ptr_to_direct(newptr);
+               root->rnode = newptr;
                root->height--;
                /* must only free zeroed nodes into the slab */
                tag_clear(to_free, 0, 0);
@@ -767,6 +883,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 {
        struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
        struct radix_tree_node *slot = NULL;
+       struct radix_tree_node *to_free;
        unsigned int height, shift;
        int tag;
        int offset;
@@ -777,6 +894,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 
        slot = root->rnode;
        if (height == 0 && root->rnode) {
+               slot = radix_tree_direct_to_ptr(slot);
                root_tag_clear_all(root);
                root->rnode = NULL;
                goto out;
@@ -809,10 +927,17 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
                        radix_tree_tag_clear(root, index, tag);
        }
 
+       to_free = NULL;
        /* Now free the nodes we do not need anymore */
        while (pathp->node) {
                pathp->node->slots[pathp->offset] = NULL;
                pathp->node->count--;
+               /*
+                * Queue the node for deferred freeing after the
+                * last reference to it disappears (set NULL, above).
+                */
+               if (to_free)
+                       radix_tree_node_free(to_free);
 
                if (pathp->node->count) {
                        if (pathp->node == root->rnode)
@@ -821,13 +946,15 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
                }
 
                /* Node with zero slots in use so free it */
-               radix_tree_node_free(pathp->node);
-
+               to_free = pathp->node;
                pathp--;
+
        }
        root_tag_clear_all(root);
        root->height = 0;
        root->rnode = NULL;
+       if (to_free)
+               radix_tree_node_free(to_free);
 
 out:
        return slot;
@@ -846,7 +973,7 @@ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
 EXPORT_SYMBOL(radix_tree_tagged);
 
 static void
-radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
+radix_tree_node_ctor(void *node, struct kmem_cache *cachep, unsigned long flags)
 {
        memset(node, 0, sizeof(struct radix_tree_node));
 }
@@ -869,7 +996,6 @@ static __init void radix_tree_init_maxindex(void)
                height_to_maxindex[i] = __maxindex(i);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int radix_tree_callback(struct notifier_block *nfb,
                             unsigned long action,
                             void *hcpu)
@@ -889,7 +1015,6 @@ static int radix_tree_callback(struct notifier_block *nfb,
        }
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 void __init radix_tree_init(void)
 {
index b6c4f89..479fd46 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/nmi.h>
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
 #include <linux/delay.h>
@@ -117,6 +118,9 @@ static void __spin_lock_debug(spinlock_t *lock)
                                raw_smp_processor_id(), current->comm,
                                current->pid, lock);
                        dump_stack();
+#ifdef CONFIG_SMP
+                       trigger_all_cpu_backtrace();
+#endif
                }
        }
 }
index eaa9abe..b2486cf 100644 (file)
 void percpu_depopulate(void *__pdata, int cpu)
 {
        struct percpu_data *pdata = __percpu_disguise(__pdata);
-       if (pdata->ptrs[cpu]) {
-               kfree(pdata->ptrs[cpu]);
-               pdata->ptrs[cpu] = NULL;
-       }
+
+       kfree(pdata->ptrs[cpu]);
+       pdata->ptrs[cpu] = NULL;
 }
 EXPORT_SYMBOL_GPL(percpu_depopulate);
 
@@ -123,6 +122,8 @@ EXPORT_SYMBOL_GPL(__percpu_alloc_mask);
  */
 void percpu_free(void *__pdata)
 {
+       if (unlikely(!__pdata))
+               return;
        __percpu_depopulate_mask(__pdata, &cpu_possible_map);
        kfree(__percpu_disguise(__pdata));
 }
index d53112f..00a9697 100644 (file)
@@ -27,8 +27,6 @@ unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
 
-EXPORT_UNUSED_SYMBOL(max_pfn);  /*  June 2006  */
-
 static LIST_HEAD(bdata_list);
 #ifdef CONFIG_CRASH_DUMP
 /*
@@ -196,6 +194,10 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
        if (limit && bdata->node_boot_start >= limit)
                return NULL;
 
+       /* on nodes without memory - bootmem_map is NULL */
+       if (!bdata->node_bootmem_map)
+               return NULL;
+
        end_pfn = bdata->node_low_pfn;
        limit = PFN_DOWN(limit);
        if (limit && end_pfn > limit)
index 168c78a..0df4c89 100644 (file)
@@ -38,7 +38,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
        if (!file)
                return -EBADF;
 
-       if (S_ISFIFO(file->f_dentry->d_inode->i_mode)) {
+       if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
                ret = -ESPIPE;
                goto out;
        }
index 13df01c..8332c77 100644 (file)
@@ -1181,8 +1181,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                if (pos < size) {
                        retval = generic_file_direct_IO(READ, iocb,
                                                iov, pos, nr_segs);
-                       if (retval > 0 && !is_sync_kiocb(iocb))
-                               retval = -EIOCBQUEUED;
                        if (retval > 0)
                                *ppos = pos + retval;
                }
@@ -1445,7 +1443,6 @@ no_cached_page:
         * effect.
         */
        error = page_cache_read(file, pgoff);
-       grab_swap_token();
 
        /*
         * The page we want has now been added to the page cache.
@@ -2048,15 +2045,14 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
         * Sync the fs metadata but not the minor inode changes and
         * of course not the data as we did direct DMA for the IO.
         * i_mutex is held, which protects generic_osync_inode() from
-        * livelocking.
+        * livelocking.  AIO O_DIRECT ops attempt to sync metadata here.
         */
-       if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+       if ((written >= 0 || written == -EIOCBQUEUED) &&
+           ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
                int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
                if (err < 0)
                        written = err;
        }
-       if (written == count && !is_sync_kiocb(iocb))
-               written = -EIOCBQUEUED;
        return written;
 }
 EXPORT_SYMBOL(generic_file_direct_write);
@@ -2270,7 +2266,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        if (count == 0)
                goto out;
 
-       err = remove_suid(file->f_dentry);
+       err = remove_suid(file->f_path.dentry);
        if (err)
                goto out;
 
index b4fd0d7..8d66761 100644 (file)
@@ -379,7 +379,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
        if (count == 0)
                goto out_backing;
 
-       ret = remove_suid(filp->f_dentry);
+       ret = remove_suid(filp->f_path.dentry);
        if (ret)
                goto out_backing;
 
index 7a9d0f5..b77a002 100644 (file)
@@ -101,7 +101,6 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
 {
        int err = -ENOMEM;
        pte_t *pte;
-       pte_t pte_val;
        spinlock_t *ptl;
 
        pte = get_locked_pte(mm, addr, &ptl);
@@ -114,7 +113,6 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
        }
 
        set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
-       pte_val = *pte;
        /*
         * We don't need to run update_mmu_cache() here because the "file pte"
         * being installed by install_file_pte() is not a real pte - it's a
index a088f59..0ccc7f2 100644 (file)
@@ -109,7 +109,7 @@ static int alloc_fresh_huge_page(void)
        if (nid == MAX_NUMNODES)
                nid = first_node(node_online_map);
        if (page) {
-               page[1].lru.next = (void *)free_huge_page;      /* dtor */
+               set_compound_page_dtor(page, free_huge_page);
                spin_lock(&hugetlb_lock);
                nr_huge_pages++;
                nr_huge_pages_node[page_to_nid(page)]++;
@@ -344,7 +344,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                        entry = *src_pte;
                        ptepage = pte_page(entry);
                        get_page(ptepage);
-                       add_mm_counter(dst, file_rss, HPAGE_SIZE / PAGE_SIZE);
                        set_huge_pte_at(dst, addr, dst_pte, entry);
                }
                spin_unlock(&src->page_table_lock);
@@ -365,6 +364,11 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        pte_t pte;
        struct page *page;
        struct page *tmp;
+       /*
+        * A page gathering list, protected by per file i_mmap_lock. The
+        * lock is used to avoid list corruption from multiple unmapping
+        * of the same page since we are using page->lru.
+        */
        LIST_HEAD(page_list);
 
        WARN_ON(!is_vm_hugetlb_page(vma));
@@ -372,24 +376,21 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        BUG_ON(end & ~HPAGE_MASK);
 
        spin_lock(&mm->page_table_lock);
-
-       /* Update high watermark before we lower rss */
-       update_hiwater_rss(mm);
-
        for (address = start; address < end; address += HPAGE_SIZE) {
                ptep = huge_pte_offset(mm, address);
                if (!ptep)
                        continue;
 
+               if (huge_pmd_unshare(mm, &address, ptep))
+                       continue;
+
                pte = huge_ptep_get_and_clear(mm, address, ptep);
                if (pte_none(pte))
                        continue;
 
                page = pte_page(pte);
                list_add(&page->lru, &page_list);
-               add_mm_counter(mm, file_rss, (int) -(HPAGE_SIZE / PAGE_SIZE));
        }
-
        spin_unlock(&mm->page_table_lock);
        flush_tlb_range(vma, start, end);
        list_for_each_entry_safe(page, tmp, &page_list, lru) {
@@ -515,7 +516,6 @@ retry:
        if (!pte_none(*ptep))
                goto backout;
 
-       add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE);
        new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
                                && (vma->vm_flags & VM_SHARED)));
        set_huge_pte_at(mm, address, ptep, new_pte);
@@ -653,11 +653,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
        BUG_ON(address >= end);
        flush_cache_range(vma, address, end);
 
+       spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
        spin_lock(&mm->page_table_lock);
        for (; address < end; address += HPAGE_SIZE) {
                ptep = huge_pte_offset(mm, address);
                if (!ptep)
                        continue;
+               if (huge_pmd_unshare(mm, &address, ptep))
+                       continue;
                if (!pte_none(*ptep)) {
                        pte = huge_ptep_get_and_clear(mm, address, ptep);
                        pte = pte_mkhuge(pte_modify(pte, newprot));
@@ -666,6 +669,7 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
                }
        }
        spin_unlock(&mm->page_table_lock);
+       spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
 
        flush_tlb_range(vma, start, end);
 }
index 156861f..bf61002 100644 (file)
@@ -1110,23 +1110,29 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
 {
        pte_t *pte;
        spinlock_t *ptl;
+       int err = 0;
 
        pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
-               return -ENOMEM;
+               return -EAGAIN;
        arch_enter_lazy_mmu_mode();
        do {
                struct page *page = ZERO_PAGE(addr);
                pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
+
+               if (unlikely(!pte_none(*pte))) {
+                       err = -EEXIST;
+                       pte++;
+                       break;
+               }
                page_cache_get(page);
                page_add_file_rmap(page);
                inc_mm_counter(mm, file_rss);
-               BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, zero_pte);
        } while (pte++, addr += PAGE_SIZE, addr != end);
        arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
-       return 0;
+       return err;
 }
 
 static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
@@ -1134,16 +1140,18 @@ static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
 {
        pmd_t *pmd;
        unsigned long next;
+       int err;
 
        pmd = pmd_alloc(mm, pud, addr);
        if (!pmd)
-               return -ENOMEM;
+               return -EAGAIN;
        do {
                next = pmd_addr_end(addr, end);
-               if (zeromap_pte_range(mm, pmd, addr, next, prot))
-                       return -ENOMEM;
+               err = zeromap_pte_range(mm, pmd, addr, next, prot);
+               if (err)
+                       break;
        } while (pmd++, addr = next, addr != end);
-       return 0;
+       return err;
 }
 
 static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
@@ -1151,16 +1159,18 @@ static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
 {
        pud_t *pud;
        unsigned long next;
+       int err;
 
        pud = pud_alloc(mm, pgd, addr);
        if (!pud)
-               return -ENOMEM;
+               return -EAGAIN;
        do {
                next = pud_addr_end(addr, end);
-               if (zeromap_pmd_range(mm, pud, addr, next, prot))
-                       return -ENOMEM;
+               err = zeromap_pmd_range(mm, pud, addr, next, prot);
+               if (err)
+                       break;
        } while (pud++, addr = next, addr != end);
-       return 0;
+       return err;
 }
 
 int zeromap_page_range(struct vm_area_struct *vma,
@@ -1902,7 +1912,6 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
 
        return 0;
 }
-EXPORT_UNUSED_SYMBOL(vmtruncate_range);  /*  June 2006  */
 
 /**
  * swapin_readahead - swap in pages in hope we need them soon
@@ -1991,6 +2000,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        delayacct_set_flag(DELAYACCT_PF_SWAPIN);
        page = lookup_swap_cache(entry);
        if (!page) {
+               grab_swap_token(); /* Contend for token _before_ read-in */
                swapin_readahead(entry, address, vma);
                page = read_swap_cache_async(entry, vma, address);
                if (!page) {
@@ -2008,7 +2018,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                /* Had to read the page from swap area: Major fault */
                ret = VM_FAULT_MAJOR;
                count_vm_event(PGMAJFAULT);
-               grab_swap_token();
        }
 
        delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
index fd678a6..0c055a0 100644 (file)
@@ -72,7 +72,6 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
                        return ret;
        }
        memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
-       zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages);
        return 0;
 }
 
index 617fb31..da94639 100644 (file)
@@ -141,9 +141,11 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
        enum zone_type k;
 
        max = 1 + MAX_NR_ZONES * nodes_weight(*nodes);
+       max++;                  /* space for zlcache_ptr (see mmzone.h) */
        zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
        if (!zl)
                return NULL;
+       zl->zlcache_ptr = NULL;
        num = 0;
        /* First put in the highest zones from all nodes, then all the next 
           lower zones etc. Avoid empty zones because the memory allocator
@@ -219,7 +221,7 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
        orig_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
        do {
                struct page *page;
-               unsigned int nid;
+               int nid;
 
                if (!pte_present(*pte))
                        continue;
@@ -1324,7 +1326,7 @@ struct mempolicy *__mpol_copy(struct mempolicy *old)
        atomic_set(&new->refcnt, 1);
        if (new->policy == MPOL_BIND) {
                int sz = ksize(old->v.zonelist);
-               new->v.zonelist = kmemdup(old->v.zonelist, sz, SLAB_KERNEL);
+               new->v.zonelist = kmemdup(old->v.zonelist, sz, GFP_KERNEL);
                if (!new->v.zonelist) {
                        kmem_cache_free(policy_cache, new);
                        return ERR_PTR(-ENOMEM);
@@ -1705,8 +1707,8 @@ void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
  * Display pages allocated per node and memory policy via /proc.
  */
 
-static const char *policy_types[] = { "default", "prefer", "bind",
-                                     "interleave" };
+static const char * const policy_types[] =
+       { "default", "prefer", "bind", "interleave" };
 
 /*
  * Convert a mempolicy into a string.
@@ -1855,7 +1857,7 @@ int show_numa_map(struct seq_file *m, void *v)
 
        if (file) {
                seq_printf(m, " file=");
-               seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= ");
+               seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n\t= ");
        } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
                seq_printf(m, " heap");
        } else if (vma->vm_start <= mm->start_stack &&
index b4979d4..e9b161b 100644 (file)
@@ -294,7 +294,7 @@ out:
 static int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page)
 {
-       struct page **radix_pointer;
+       void **pslot;
 
        if (!mapping) {
                /* Anonymous page */
@@ -305,12 +305,11 @@ static int migrate_page_move_mapping(struct address_space *mapping,
 
        write_lock_irq(&mapping->tree_lock);
 
-       radix_pointer = (struct page **)radix_tree_lookup_slot(
-                                               &mapping->page_tree,
-                                               page_index(page));
+       pslot = radix_tree_lookup_slot(&mapping->page_tree,
+                                       page_index(page));
 
        if (page_count(page) != 2 + !!PagePrivate(page) ||
-                       *radix_pointer != page) {
+                       (struct page *)radix_tree_deref_slot(pslot) != page) {
                write_unlock_irq(&mapping->tree_lock);
                return -EAGAIN;
        }
@@ -318,7 +317,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
        /*
         * Now we know that no one else is looking at the page.
         */
-       get_page(newpage);
+       get_page(newpage);      /* add cache reference */
 #ifdef CONFIG_SWAP
        if (PageSwapCache(page)) {
                SetPageSwapCache(newpage);
@@ -326,8 +325,14 @@ static int migrate_page_move_mapping(struct address_space *mapping,
        }
 #endif
 
-       *radix_pointer = newpage;
+       radix_tree_replace_slot(pslot, newpage);
+
+       /*
+        * Drop cache reference from old page.
+        * We know this isn't the last reference.
+        */
        __put_page(page);
+
        write_unlock_irq(&mapping->tree_lock);
 
        return 0;
index b90c595..3446b7e 100644 (file)
@@ -65,7 +65,7 @@ success:
                        ret = make_pages_present(start, end);
        }
 
-       vma->vm_mm->locked_vm -= pages;
+       mm->locked_vm -= pages;
 out:
        if (ret == -ENOMEM)
                ret = -EAGAIN;
index 7b40abd..9717337 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -188,7 +188,7 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma,
                struct file *file, struct address_space *mapping)
 {
        if (vma->vm_flags & VM_DENYWRITE)
-               atomic_inc(&file->f_dentry->d_inode->i_writecount);
+               atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
        if (vma->vm_flags & VM_SHARED)
                mapping->i_mmap_writable--;
 
@@ -399,7 +399,7 @@ static inline void __vma_link_file(struct vm_area_struct *vma)
                struct address_space *mapping = file->f_mapping;
 
                if (vma->vm_flags & VM_DENYWRITE)
-                       atomic_dec(&file->f_dentry->d_inode->i_writecount);
+                       atomic_dec(&file->f_path.dentry->d_inode->i_writecount);
                if (vma->vm_flags & VM_SHARED)
                        mapping->i_mmap_writable++;
 
@@ -907,7 +907,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
         *  mounted, in which case we dont add PROT_EXEC.)
         */
        if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
-               if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+               if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
                        prot |= PROT_EXEC;
 
        if (!len)
@@ -960,7 +960,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
                        return -EAGAIN;
        }
 
-       inode = file ? file->f_dentry->d_inode : NULL;
+       inode = file ? file->f_path.dentry->d_inode : NULL;
 
        if (file) {
                switch (flags & MAP_TYPE) {
@@ -989,7 +989,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
                case MAP_PRIVATE:
                        if (!(file->f_mode & FMODE_READ))
                                return -EACCES;
-                       if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+                       if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
                                if (vm_flags & VM_EXEC)
                                        return -EPERM;
                                vm_flags &= ~VM_MAYEXEC;
@@ -1736,7 +1736,7 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
        if (mm->map_count >= sysctl_max_map_count)
                return -ENOMEM;
 
-       new = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+       new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
@@ -2057,7 +2057,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
                    vma_start < new_vma->vm_end)
                        *vmap = new_vma;
        } else {
-               new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+               new_vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
                if (new_vma) {
                        *new_vma = *vma;
                        pol = mpol_copy(vma_policy(vma));
index febea1c..eb58386 100644 (file)
@@ -14,8 +14,6 @@ struct pglist_data *first_online_pgdat(void)
        return NODE_DATA(first_online_node);
 }
 
-EXPORT_UNUSED_SYMBOL(first_online_pgdat);  /*  June 2006  */
-
 struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
 {
        int nid = next_online_node(pgdat->node_id);
@@ -24,8 +22,6 @@ struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
                return NULL;
        return NODE_DATA(nid);
 }
-EXPORT_UNUSED_SYMBOL(next_online_pgdat);  /*  June 2006  */
-
 
 /*
  * next_zone - helper magic for for_each_zone()
@@ -45,5 +41,4 @@ struct zone *next_zone(struct zone *zone)
        }
        return zone;
 }
-EXPORT_UNUSED_SYMBOL(next_zone);  /*  June 2006  */
 
index 8bdde95..23fb033 100644 (file)
@@ -497,15 +497,17 @@ static int validate_mmap_request(struct file *file,
            (flags & MAP_TYPE) != MAP_SHARED)
                return -EINVAL;
 
-       if (PAGE_ALIGN(len) == 0)
-               return addr;
-
-       if (len > TASK_SIZE)
+       if (!len)
                return -EINVAL;
 
+       /* Careful about overflows.. */
+       len = PAGE_ALIGN(len);
+       if (!len || len > TASK_SIZE)
+               return -ENOMEM;
+
        /* offset overflow? */
        if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
-               return -EINVAL;
+               return -EOVERFLOW;
 
        if (file) {
                /* validate file mapping requests */
@@ -521,7 +523,7 @@ static int validate_mmap_request(struct file *file,
                 */
                mapping = file->f_mapping;
                if (!mapping)
-                       mapping = file->f_dentry->d_inode->i_mapping;
+                       mapping = file->f_path.dentry->d_inode->i_mapping;
 
                capabilities = 0;
                if (mapping && mapping->backing_dev_info)
@@ -530,7 +532,7 @@ static int validate_mmap_request(struct file *file,
                if (!capabilities) {
                        /* no explicit capabilities set, so assume some
                         * defaults */
-                       switch (file->f_dentry->d_inode->i_mode & S_IFMT) {
+                       switch (file->f_path.dentry->d_inode->i_mode & S_IFMT) {
                        case S_IFREG:
                        case S_IFBLK:
                                capabilities = BDI_CAP_MAP_COPY;
@@ -561,11 +563,11 @@ static int validate_mmap_request(struct file *file,
                            !(file->f_mode & FMODE_WRITE))
                                return -EACCES;
 
-                       if (IS_APPEND(file->f_dentry->d_inode) &&
+                       if (IS_APPEND(file->f_path.dentry->d_inode) &&
                            (file->f_mode & FMODE_WRITE))
                                return -EACCES;
 
-                       if (locks_verify_locked(file->f_dentry->d_inode))
+                       if (locks_verify_locked(file->f_path.dentry->d_inode))
                                return -EAGAIN;
 
                        if (!(capabilities & BDI_CAP_MAP_DIRECT))
@@ -596,7 +598,7 @@ static int validate_mmap_request(struct file *file,
 
                /* handle executable mappings and implied executable
                 * mappings */
-               if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+               if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
                        if (prot & PROT_EXEC)
                                return -EPERM;
                }
@@ -806,10 +808,9 @@ unsigned long do_mmap_pgoff(struct file *file,
        vm_flags = determine_vm_flags(file, prot, flags, capabilities);
 
        /* we're going to need to record the mapping if it works */
-       vml = kmalloc(sizeof(struct vm_list_struct), GFP_KERNEL);
+       vml = kzalloc(sizeof(struct vm_list_struct), GFP_KERNEL);
        if (!vml)
                goto error_getting_vml;
-       memset(vml, 0, sizeof(*vml));
 
        down_write(&nommu_vma_sem);
 
@@ -832,7 +833,7 @@ unsigned long do_mmap_pgoff(struct file *file,
                                continue;
 
                        /* search for overlapping mappings on the same file */
-                       if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
+                       if (vma->vm_file->f_path.dentry->d_inode != file->f_path.dentry->d_inode)
                                continue;
 
                        if (vma->vm_pgoff >= pgoff + pglen)
@@ -885,11 +886,10 @@ unsigned long do_mmap_pgoff(struct file *file,
        }
 
        /* we're going to need a VMA struct as well */
-       vma = kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
+       vma = kzalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
        if (!vma)
                goto error_getting_vma;
 
-       memset(vma, 0, sizeof(*vma));
        INIT_LIST_HEAD(&vma->anon_vma_node);
        atomic_set(&vma->vm_usage, 1);
        if (file)
index 2e3ce3a..223d9cc 100644 (file)
@@ -264,7 +264,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
  * flag though it's unlikely that  we select a process with CAP_SYS_RAW_IO
  * set.
  */
-static void __oom_kill_task(struct task_struct *p, const char *message)
+static void __oom_kill_task(struct task_struct *p, int verbose)
 {
        if (is_init(p)) {
                WARN_ON(1);
@@ -278,10 +278,8 @@ static void __oom_kill_task(struct task_struct *p, const char *message)
                return;
        }
 
-       if (message) {
-               printk(KERN_ERR "%s: Killed process %d (%s).\n",
-                               message, p->pid, p->comm);
-       }
+       if (verbose)
+               printk(KERN_ERR "Killed process %d (%s)\n", p->pid, p->comm);
 
        /*
         * We give our sacrificial lamb high priority and access to
@@ -294,7 +292,7 @@ static void __oom_kill_task(struct task_struct *p, const char *message)
        force_sig(SIGKILL, p);
 }
 
-static int oom_kill_task(struct task_struct *p, const char *message)
+static int oom_kill_task(struct task_struct *p)
 {
        struct mm_struct *mm;
        struct task_struct *g, *q;
@@ -313,15 +311,25 @@ static int oom_kill_task(struct task_struct *p, const char *message)
        if (mm == NULL)
                return 1;
 
-       __oom_kill_task(p, message);
+       /*
+        * Don't kill the process if any threads are set to OOM_DISABLE
+        */
+       do_each_thread(g, q) {
+               if (q->mm == mm && p->oomkilladj == OOM_DISABLE)
+                       return 1;
+       } while_each_thread(g, q);
+
+       __oom_kill_task(p, 1);
+
        /*
         * kill all processes that share the ->mm (i.e. all threads),
-        * but are in a different thread group
+        * but are in a different thread group. Don't let them have access
+        * to memory reserves though, otherwise we might deplete all memory.
         */
-       do_each_thread(g, q)
+       do_each_thread(g, q) {
                if (q->mm == mm && q->tgid != p->tgid)
-                       __oom_kill_task(q, message);
-       while_each_thread(g, q);
+                       force_sig(SIGKILL, p);
+       while_each_thread(g, q);
 
        return 0;
 }
@@ -337,21 +345,22 @@ static int oom_kill_process(struct task_struct *p, unsigned long points,
         * its children or threads, just set TIF_MEMDIE so it can die quickly
         */
        if (p->flags & PF_EXITING) {
-               __oom_kill_task(p, NULL);
+               __oom_kill_task(p, 0);
                return 0;
        }
 
-       printk(KERN_ERR "Out of Memory: Kill process %d (%s) score %li"
-                       " and children.\n", p->pid, p->comm, points);
+       printk(KERN_ERR "%s: kill process %d (%s) score %li or a child\n",
+                                       message, p->pid, p->comm, points);
+
        /* Try to kill a child first */
        list_for_each(tsk, &p->children) {
                c = list_entry(tsk, struct task_struct, sibling);
                if (c->mm == p->mm)
                        continue;
-               if (!oom_kill_task(c, message))
+               if (!oom_kill_task(c))
                        return 0;
        }
-       return oom_kill_task(p, message);
+       return oom_kill_task(p);
 }
 
 static BLOCKING_NOTIFIER_HEAD(oom_notify_list);
index 8d9b19f..237107c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/writeback.h>
 #include <linux/init.h>
 #include <linux/backing-dev.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/blkdev.h>
 #include <linux/mpage.h>
 #include <linux/rmap.h>
@@ -761,23 +762,24 @@ int __set_page_dirty_nobuffers(struct page *page)
                struct address_space *mapping = page_mapping(page);
                struct address_space *mapping2;
 
-               if (mapping) {
-                       write_lock_irq(&mapping->tree_lock);
-                       mapping2 = page_mapping(page);
-                       if (mapping2) { /* Race with truncate? */
-                               BUG_ON(mapping2 != mapping);
-                               if (mapping_cap_account_dirty(mapping))
-                                       __inc_zone_page_state(page,
-                                                               NR_FILE_DIRTY);
-                               radix_tree_tag_set(&mapping->page_tree,
-                                       page_index(page), PAGECACHE_TAG_DIRTY);
-                       }
-                       write_unlock_irq(&mapping->tree_lock);
-                       if (mapping->host) {
-                               /* !PageAnon && !swapper_space */
-                               __mark_inode_dirty(mapping->host,
-                                                       I_DIRTY_PAGES);
+               if (!mapping)
+                       return 1;
+
+               write_lock_irq(&mapping->tree_lock);
+               mapping2 = page_mapping(page);
+               if (mapping2) { /* Race with truncate? */
+                       BUG_ON(mapping2 != mapping);
+                       if (mapping_cap_account_dirty(mapping)) {
+                               __inc_zone_page_state(page, NR_FILE_DIRTY);
+                               task_io_account_write(PAGE_CACHE_SIZE);
                        }
+                       radix_tree_tag_set(&mapping->page_tree,
+                               page_index(page), PAGECACHE_TAG_DIRTY);
+               }
+               write_unlock_irq(&mapping->tree_lock);
+               if (mapping->host) {
+                       /* !PageAnon && !swapper_space */
+                       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
                }
                return 1;
        }
@@ -851,27 +853,26 @@ int test_clear_page_dirty(struct page *page)
        struct address_space *mapping = page_mapping(page);
        unsigned long flags;
 
-       if (mapping) {
-               write_lock_irqsave(&mapping->tree_lock, flags);
-               if (TestClearPageDirty(page)) {
-                       radix_tree_tag_clear(&mapping->page_tree,
-                                               page_index(page),
-                                               PAGECACHE_TAG_DIRTY);
-                       write_unlock_irqrestore(&mapping->tree_lock, flags);
-                       /*
-                        * We can continue to use `mapping' here because the
-                        * page is locked, which pins the address_space
-                        */
-                       if (mapping_cap_account_dirty(mapping)) {
-                               page_mkclean(page);
-                               dec_zone_page_state(page, NR_FILE_DIRTY);
-                       }
-                       return 1;
-               }
+       if (!mapping)
+               return TestClearPageDirty(page);
+
+       write_lock_irqsave(&mapping->tree_lock, flags);
+       if (TestClearPageDirty(page)) {
+               radix_tree_tag_clear(&mapping->page_tree,
+                               page_index(page), PAGECACHE_TAG_DIRTY);
                write_unlock_irqrestore(&mapping->tree_lock, flags);
-               return 0;
+               /*
+                * We can continue to use `mapping' here because the
+                * page is locked, which pins the address_space
+                */
+               if (mapping_cap_account_dirty(mapping)) {
+                       page_mkclean(page);
+                       dec_zone_page_state(page, NR_FILE_DIRTY);
+               }
+               return 1;
        }
-       return TestClearPageDirty(page);
+       write_unlock_irqrestore(&mapping->tree_lock, flags);
+       return 0;
 }
 EXPORT_SYMBOL(test_clear_page_dirty);
 
@@ -893,17 +894,17 @@ int clear_page_dirty_for_io(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
 
-       if (mapping) {
-               if (TestClearPageDirty(page)) {
-                       if (mapping_cap_account_dirty(mapping)) {
-                               page_mkclean(page);
-                               dec_zone_page_state(page, NR_FILE_DIRTY);
-                       }
-                       return 1;
+       if (!mapping)
+               return TestClearPageDirty(page);
+
+       if (TestClearPageDirty(page)) {
+               if (mapping_cap_account_dirty(mapping)) {
+                       page_mkclean(page);
+                       dec_zone_page_state(page, NR_FILE_DIRTY);
                }
-               return 0;
+               return 1;
        }
-       return TestClearPageDirty(page);
+       return 0;
 }
 EXPORT_SYMBOL(clear_page_dirty_for_io);
 
index aa6fcc7..e6b17b2 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/sort.h>
 #include <linux/pfn.h>
 #include <linux/backing-dev.h>
+#include <linux/fault-inject.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -83,14 +84,7 @@ int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = {
 
 EXPORT_SYMBOL(totalram_pages);
 
-/*
- * Used by page_zone() to look up the address of the struct zone whose
- * id is encoded in the upper bits of page->flags
- */
-struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly;
-EXPORT_SYMBOL(zone_table);
-
-static char *zone_names[MAX_NR_ZONES] = {
+static char * const zone_names[MAX_NR_ZONES] = {
         "DMA",
 #ifdef CONFIG_ZONE_DMA32
         "DMA32",
@@ -237,7 +231,7 @@ static void prep_compound_page(struct page *page, unsigned long order)
        int i;
        int nr_pages = 1 << order;
 
-       page[1].lru.next = (void *)free_compound_page;  /* set dtor */
+       set_compound_page_dtor(page, free_compound_page);
        page[1].lru.prev = (void *)order;
        for (i = 0; i < nr_pages; i++) {
                struct page *p = page + i;
@@ -486,7 +480,7 @@ static void free_one_page(struct zone *zone, struct page *page, int order)
        spin_lock(&zone->lock);
        zone->all_unreclaimable = 0;
        zone->pages_scanned = 0;
-       __free_one_page(page, zone ,order);
+       __free_one_page(page, zoneorder);
        spin_unlock(&zone->lock);
 }
 
@@ -605,6 +599,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
                        1 << PG_checked | 1 << PG_mappedtodisk);
        set_page_private(page, 0);
        set_page_refcounted(page);
+
+       arch_alloc_page(page, order);
        kernel_map_pages(page, 1 << order, 1);
 
        if (gfp_flags & __GFP_ZERO)
@@ -690,9 +686,15 @@ void drain_node_pages(int nodeid)
 
                        pcp = &pset->pcp[i];
                        if (pcp->count) {
+                               int to_drain;
+
                                local_irq_save(flags);
-                               free_pages_bulk(zone, pcp->count, &pcp->list, 0);
-                               pcp->count = 0;
+                               if (pcp->count >= pcp->batch)
+                                       to_drain = pcp->batch;
+                               else
+                                       to_drain = pcp->count;
+                               free_pages_bulk(zone, to_drain, &pcp->list, 0);
+                               pcp->count -= to_drain;
                                local_irq_restore(flags);
                        }
                }
@@ -700,7 +702,6 @@ void drain_node_pages(int nodeid)
 }
 #endif
 
-#if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
 static void __drain_pages(unsigned int cpu)
 {
        unsigned long flags;
@@ -722,7 +723,6 @@ static void __drain_pages(unsigned int cpu)
                }
        }
 }
-#endif /* CONFIG_PM || CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_PM
 
@@ -893,6 +893,91 @@ failed:
 #define ALLOC_HIGH             0x20 /* __GFP_HIGH set */
 #define ALLOC_CPUSET           0x40 /* check for correct cpuset */
 
+#ifdef CONFIG_FAIL_PAGE_ALLOC
+
+static struct fail_page_alloc_attr {
+       struct fault_attr attr;
+
+       u32 ignore_gfp_highmem;
+       u32 ignore_gfp_wait;
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+       struct dentry *ignore_gfp_highmem_file;
+       struct dentry *ignore_gfp_wait_file;
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+} fail_page_alloc = {
+       .attr = FAULT_ATTR_INITIALIZER,
+       .ignore_gfp_wait = 1,
+       .ignore_gfp_highmem = 1,
+};
+
+static int __init setup_fail_page_alloc(char *str)
+{
+       return setup_fault_attr(&fail_page_alloc.attr, str);
+}
+__setup("fail_page_alloc=", setup_fail_page_alloc);
+
+static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+{
+       if (gfp_mask & __GFP_NOFAIL)
+               return 0;
+       if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM))
+               return 0;
+       if (fail_page_alloc.ignore_gfp_wait && (gfp_mask & __GFP_WAIT))
+               return 0;
+
+       return should_fail(&fail_page_alloc.attr, 1 << order);
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static int __init fail_page_alloc_debugfs(void)
+{
+       mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+       struct dentry *dir;
+       int err;
+
+       err = init_fault_attr_dentries(&fail_page_alloc.attr,
+                                      "fail_page_alloc");
+       if (err)
+               return err;
+       dir = fail_page_alloc.attr.dentries.dir;
+
+       fail_page_alloc.ignore_gfp_wait_file =
+               debugfs_create_bool("ignore-gfp-wait", mode, dir,
+                                     &fail_page_alloc.ignore_gfp_wait);
+
+       fail_page_alloc.ignore_gfp_highmem_file =
+               debugfs_create_bool("ignore-gfp-highmem", mode, dir,
+                                     &fail_page_alloc.ignore_gfp_highmem);
+
+       if (!fail_page_alloc.ignore_gfp_wait_file ||
+                       !fail_page_alloc.ignore_gfp_highmem_file) {
+               err = -ENOMEM;
+               debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
+               debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
+               cleanup_fault_attr_dentries(&fail_page_alloc.attr);
+       }
+
+       return err;
+}
+
+late_initcall(fail_page_alloc_debugfs);
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#else /* CONFIG_FAIL_PAGE_ALLOC */
+
+static inline int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+{
+       return 0;
+}
+
+#endif /* CONFIG_FAIL_PAGE_ALLOC */
+
 /*
  * Return 1 if free pages are above 'mark'. This takes into account the order
  * of the allocation.
@@ -925,31 +1010,160 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
        return 1;
 }
 
+#ifdef CONFIG_NUMA
 /*
- * get_page_from_freeliest goes through the zonelist trying to allocate
+ * zlc_setup - Setup for "zonelist cache".  Uses cached zone data to
+ * skip over zones that are not allowed by the cpuset, or that have
+ * been recently (in last second) found to be nearly full.  See further
+ * comments in mmzone.h.  Reduces cache footprint of zonelist scans
+ * that have to skip over alot of full or unallowed zones.
+ *
+ * If the zonelist cache is present in the passed in zonelist, then
+ * returns a pointer to the allowed node mask (either the current
+ * tasks mems_allowed, or node_online_map.)
+ *
+ * If the zonelist cache is not available for this zonelist, does
+ * nothing and returns NULL.
+ *
+ * If the fullzones BITMAP in the zonelist cache is stale (more than
+ * a second since last zap'd) then we zap it out (clear its bits.)
+ *
+ * We hold off even calling zlc_setup, until after we've checked the
+ * first zone in the zonelist, on the theory that most allocations will
+ * be satisfied from that first zone, so best to examine that zone as
+ * quickly as we can.
+ */
+static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
+{
+       struct zonelist_cache *zlc;     /* cached zonelist speedup info */
+       nodemask_t *allowednodes;       /* zonelist_cache approximation */
+
+       zlc = zonelist->zlcache_ptr;
+       if (!zlc)
+               return NULL;
+
+       if (jiffies - zlc->last_full_zap > 1 * HZ) {
+               bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
+               zlc->last_full_zap = jiffies;
+       }
+
+       allowednodes = !in_interrupt() && (alloc_flags & ALLOC_CPUSET) ?
+                                       &cpuset_current_mems_allowed :
+                                       &node_online_map;
+       return allowednodes;
+}
+
+/*
+ * Given 'z' scanning a zonelist, run a couple of quick checks to see
+ * if it is worth looking at further for free memory:
+ *  1) Check that the zone isn't thought to be full (doesn't have its
+ *     bit set in the zonelist_cache fullzones BITMAP).
+ *  2) Check that the zones node (obtained from the zonelist_cache
+ *     z_to_n[] mapping) is allowed in the passed in allowednodes mask.
+ * Return true (non-zero) if zone is worth looking at further, or
+ * else return false (zero) if it is not.
+ *
+ * This check -ignores- the distinction between various watermarks,
+ * such as GFP_HIGH, GFP_ATOMIC, PF_MEMALLOC, ...  If a zone is
+ * found to be full for any variation of these watermarks, it will
+ * be considered full for up to one second by all requests, unless
+ * we are so low on memory on all allowed nodes that we are forced
+ * into the second scan of the zonelist.
+ *
+ * In the second scan we ignore this zonelist cache and exactly
+ * apply the watermarks to all zones, even it is slower to do so.
+ * We are low on memory in the second scan, and should leave no stone
+ * unturned looking for a free page.
+ */
+static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
+                                               nodemask_t *allowednodes)
+{
+       struct zonelist_cache *zlc;     /* cached zonelist speedup info */
+       int i;                          /* index of *z in zonelist zones */
+       int n;                          /* node that zone *z is on */
+
+       zlc = zonelist->zlcache_ptr;
+       if (!zlc)
+               return 1;
+
+       i = z - zonelist->zones;
+       n = zlc->z_to_n[i];
+
+       /* This zone is worth trying if it is allowed but not full */
+       return node_isset(n, *allowednodes) && !test_bit(i, zlc->fullzones);
+}
+
+/*
+ * Given 'z' scanning a zonelist, set the corresponding bit in
+ * zlc->fullzones, so that subsequent attempts to allocate a page
+ * from that zone don't waste time re-examining it.
+ */
+static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
+{
+       struct zonelist_cache *zlc;     /* cached zonelist speedup info */
+       int i;                          /* index of *z in zonelist zones */
+
+       zlc = zonelist->zlcache_ptr;
+       if (!zlc)
+               return;
+
+       i = z - zonelist->zones;
+
+       set_bit(i, zlc->fullzones);
+}
+
+#else  /* CONFIG_NUMA */
+
+static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
+{
+       return NULL;
+}
+
+static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z,
+                               nodemask_t *allowednodes)
+{
+       return 1;
+}
+
+static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z)
+{
+}
+#endif /* CONFIG_NUMA */
+
+/*
+ * get_page_from_freelist goes through the zonelist trying to allocate
  * a page.
  */
 static struct page *
 get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
                struct zonelist *zonelist, int alloc_flags)
 {
-       struct zone **z = zonelist->zones;
+       struct zone **z;
        struct page *page = NULL;
-       int classzone_idx = zone_idx(*z);
+       int classzone_idx = zone_idx(zonelist->zones[0]);
        struct zone *zone;
+       nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */
+       int zlc_active = 0;             /* set if using zonelist_cache */
+       int did_zlc_setup = 0;          /* just call zlc_setup() one time */
 
+zonelist_scan:
        /*
-        * Go through the zonelist once, looking for a zone with enough free.
+        * Scan zonelist, looking for a zone with enough free.
         * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
         */
+       z = zonelist->zones;
+
        do {
+               if (NUMA_BUILD && zlc_active &&
+                       !zlc_zone_worth_trying(zonelist, z, allowednodes))
+                               continue;
                zone = *z;
                if (unlikely(NUMA_BUILD && (gfp_mask & __GFP_THISNODE) &&
                        zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
                                break;
                if ((alloc_flags & ALLOC_CPUSET) &&
-                               !cpuset_zone_allowed(zone, gfp_mask))
-                       continue;
+                       !cpuset_zone_allowed(zone, gfp_mask))
+                               goto try_next_zone;
 
                if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
                        unsigned long mark;
@@ -959,18 +1173,34 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
                                mark = zone->pages_low;
                        else
                                mark = zone->pages_high;
-                       if (!zone_watermark_ok(zone , order, mark,
-                                   classzone_idx, alloc_flags))
+                       if (!zone_watermark_ok(zone, order, mark,
+                                   classzone_idx, alloc_flags)) {
                                if (!zone_reclaim_mode ||
                                    !zone_reclaim(zone, gfp_mask, order))
-                                       continue;
+                                       goto this_zone_full;
+                       }
                }
 
                page = buffered_rmqueue(zonelist, zone, order, gfp_mask);
-               if (page) {
+               if (page)
                        break;
+this_zone_full:
+               if (NUMA_BUILD)
+                       zlc_mark_zone_full(zonelist, z);
+try_next_zone:
+               if (NUMA_BUILD && !did_zlc_setup) {
+                       /* we do zlc_setup after the first zone is tried */
+                       allowednodes = zlc_setup(zonelist, alloc_flags);
+                       zlc_active = 1;
+                       did_zlc_setup = 1;
                }
        } while (*(++z) != NULL);
+
+       if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {
+               /* Disable zlc cache for second zonelist scan */
+               zlc_active = 0;
+               goto zonelist_scan;
+       }
        return page;
 }
 
@@ -992,6 +1222,9 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order,
 
        might_sleep_if(wait);
 
+       if (should_fail_alloc_page(gfp_mask, order))
+               return NULL;
+
 restart:
        z = zonelist->zones;  /* the list of zones suitable for gfp_mask */
 
@@ -1005,9 +1238,19 @@ restart:
        if (page)
                goto got_pg;
 
-       do {
+       /*
+        * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and
+        * __GFP_NOWARN set) should not cause reclaim since the subsystem
+        * (f.e. slab) using GFP_THISNODE may choose to trigger reclaim
+        * using a larger set of nodes after it has established that the
+        * allowed per node queues are empty and that nodes are
+        * over allocated.
+        */
+       if (NUMA_BUILD && (gfp_mask & GFP_THISNODE) == GFP_THISNODE)
+               goto nopage;
+
+       for (z = zonelist->zones; *z; z++)
                wakeup_kswapd(*z, order);
-       } while (*(++z));
 
        /*
         * OK, we're below the kswapd watermark and have kicked background
@@ -1041,6 +1284,7 @@ restart:
 
        /* This allocation should allow future memory freeing. */
 
+rebalance:
        if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE)))
                        && !in_interrupt()) {
                if (!(gfp_mask & __GFP_NOMEMALLOC)) {
@@ -1062,7 +1306,6 @@ nofail_alloc:
        if (!wait)
                goto nopage;
 
-rebalance:
        cond_resched();
 
        /* We now go into synchronous reclaim */
@@ -1262,7 +1505,7 @@ unsigned int nr_free_pagecache_pages(void)
 static inline void show_node(struct zone *zone)
 {
        if (NUMA_BUILD)
-               printk("Node %ld ", zone_to_nid(zone));
+               printk("Node %d ", zone_to_nid(zone));
 }
 
 void si_meminfo(struct sysinfo *val)
@@ -1542,6 +1785,24 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
        }
 }
 
+/* Construct the zonelist performance cache - see further mmzone.h */
+static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+{
+       int i;
+
+       for (i = 0; i < MAX_NR_ZONES; i++) {
+               struct zonelist *zonelist;
+               struct zonelist_cache *zlc;
+               struct zone **z;
+
+               zonelist = pgdat->node_zonelists + i;
+               zonelist->zlcache_ptr = zlc = &zonelist->zlcache;
+               bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
+               for (z = zonelist->zones; *z; z++)
+                       zlc->z_to_n[z - zonelist->zones] = zone_to_nid(*z);
+       }
+}
+
 #else  /* CONFIG_NUMA */
 
 static void __meminit build_zonelists(pg_data_t *pgdat)
@@ -1579,14 +1840,26 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
        }
 }
 
+/* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
+static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+{
+       int i;
+
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               pgdat->node_zonelists[i].zlcache_ptr = NULL;
+}
+
 #endif /* CONFIG_NUMA */
 
 /* return values int ....just for stop_machine_run() */
 static int __meminit __build_all_zonelists(void *dummy)
 {
        int nid;
-       for_each_online_node(nid)
+
+       for_each_online_node(nid) {
                build_zonelists(NODE_DATA(nid));
+               build_zonelist_cache(NODE_DATA(nid));
+       }
        return 0;
 }
 
@@ -1715,20 +1988,6 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
        }
 }
 
-#define ZONETABLE_INDEX(x, zone_nr)    ((x << ZONES_SHIFT) | zone_nr)
-void zonetable_add(struct zone *zone, int nid, enum zone_type zid,
-               unsigned long pfn, unsigned long size)
-{
-       unsigned long snum = pfn_to_section_nr(pfn);
-       unsigned long end = pfn_to_section_nr(pfn + size);
-
-       if (FLAGS_HAS_NODE)
-               zone_table[ZONETABLE_INDEX(nid, zid)] = zone;
-       else
-               for (; snum <= end; snum++)
-                       zone_table[ZONETABLE_INDEX(snum, zid)] = zone;
-}
-
 #ifndef __HAVE_ARCH_MEMMAP_INIT
 #define memmap_init(size, nid, zone, start_pfn) \
        memmap_init_zone((size), (nid), (zone), (start_pfn))
@@ -1881,16 +2140,16 @@ static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
        int ret = NOTIFY_OK;
 
        switch (action) {
-               case CPU_UP_PREPARE:
-                       if (process_zones(cpu))
-                               ret = NOTIFY_BAD;
-                       break;
-               case CPU_UP_CANCELED:
-               case CPU_DEAD:
-                       free_zone_pagesets(cpu);
-                       break;
-               default:
-                       break;
+       case CPU_UP_PREPARE:
+               if (process_zones(cpu))
+                       ret = NOTIFY_BAD;
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               free_zone_pagesets(cpu);
+               break;
+       default:
+               break;
        }
        return ret;
 }
@@ -2421,7 +2680,6 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
                if (!size)
                        continue;
 
-               zonetable_add(zone, nid, j, zone_start_pfn, size);
                ret = init_currently_empty_zone(zone, zone_start_pfn, size);
                BUG_ON(ret);
                zone_start_pfn += size;
@@ -2736,7 +2994,6 @@ void __init free_area_init(unsigned long *zones_size)
                        __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int page_alloc_cpu_notify(struct notifier_block *self,
                                 unsigned long action, void *hcpu)
 {
@@ -2751,7 +3008,6 @@ static int page_alloc_cpu_notify(struct notifier_block *self,
        }
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 void __init page_alloc_init(void)
 {
@@ -3055,7 +3311,7 @@ void *__init alloc_large_system_hash(const char *tablename,
        /* allow the kernel cmdline to have a say */
        if (!numentries) {
                /* round applicable memory size up to nearest megabyte */
-               numentries = (flags & HASH_HIGHMEM) ? nr_all_pages : nr_kernel_pages;
+               numentries = nr_kernel_pages;
                numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
                numentries >>= 20 - PAGE_SHIFT;
                numentries <<= 20 - PAGE_SHIFT;
@@ -3077,7 +3333,7 @@ void *__init alloc_large_system_hash(const char *tablename,
        if (numentries > max)
                numentries = max;
 
-       log2qty = long_log2(numentries);
+       log2qty = ilog2(numentries);
 
        do {
                size = bucketsize << log2qty;
@@ -3099,7 +3355,7 @@ void *__init alloc_large_system_hash(const char *tablename,
        printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
               tablename,
               (1U << log2qty),
-              long_log2(size) - PAGE_SHIFT,
+              ilog2(size) - PAGE_SHIFT,
               size);
 
        if (_hash_shift)
index d4840ec..dbffec0 100644 (file)
@@ -147,48 +147,3 @@ int swap_readpage(struct file *file, struct page *page)
 out:
        return ret;
 }
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-/*
- * A scruffy utility function to read or write an arbitrary swap page
- * and wait on the I/O.  The caller must have a ref on the page.
- *
- * We use end_swap_bio_read() even for writes, because it happens to do what
- * we want.
- */
-int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page,
-                       struct bio **bio_chain)
-{
-       struct bio *bio;
-       int ret = 0;
-       int bio_rw;
-
-       lock_page(page);
-
-       bio = get_swap_bio(GFP_KERNEL, entry.val, page, end_swap_bio_read);
-       if (bio == NULL) {
-               unlock_page(page);
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       bio_rw = rw;
-       if (!bio_chain)
-               bio_rw |= (1 << BIO_RW_SYNC);
-       if (bio_chain)
-               bio_get(bio);
-       submit_bio(bio_rw, bio);
-       if (bio_chain == NULL) {
-               wait_on_page_locked(page);
-
-               if (!PageUptodate(page) || PageError(page))
-                       ret = -EIO;
-       }
-       if (bio_chain) {
-               bio->bi_private = *bio_chain;
-               *bio_chain = bio;
-       }
-out:
-       return ret;
-}
-#endif
index b02102f..8ce0900 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/writeback.h>   // Prototypes pdflush_operation()
 #include <linux/kthread.h>
 #include <linux/cpuset.h>
+#include <linux/freezer.h>
 
 
 /*
index 23cb61a..0f539e8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/pagevec.h>
 
 void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -148,15 +149,10 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
                if (!pagevec_add(&lru_pvec, page))
                        __pagevec_lru_add(&lru_pvec);
                if (ret) {
-                       while (!list_empty(pages)) {
-                               struct page *victim;
-
-                               victim = list_to_page(pages);
-                               list_del(&victim->lru);
-                               page_cache_release(victim);
-                       }
+                       put_pages_list(pages);
                        break;
                }
+               task_io_account_read(PAGE_CACHE_SIZE);
        }
        pagevec_lru_add(&lru_pvec);
        return ret;
@@ -456,7 +452,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
  *
  * Note that @filp is purely used for passing on to the ->readpage[s]()
  * handler: it may refer to a different file from @mapping (so we may not use
- * @filp->f_mapping or @filp->f_dentry->d_inode here).
+ * @filp->f_mapping or @filp->f_path.dentry->d_inode here).
  * Also, @ra may not be equal to &@filp->f_ra.
  *
  */
index 4959535..4bb28d2 100644 (file)
@@ -177,7 +177,7 @@ static inline void shmem_unacct_blocks(unsigned long flags, long pages)
 
 static struct super_operations shmem_ops;
 static const struct address_space_operations shmem_aops;
-static struct file_operations shmem_file_operations;
+static const struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
 static struct inode_operations shmem_special_inode_operations;
@@ -1225,7 +1225,7 @@ failed:
 
 struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
 {
-       struct inode *inode = vma->vm_file->f_dentry->d_inode;
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
        struct page *page = NULL;
        unsigned long idx;
        int error;
@@ -1248,7 +1248,7 @@ static int shmem_populate(struct vm_area_struct *vma,
        unsigned long addr, unsigned long len,
        pgprot_t prot, unsigned long pgoff, int nonblock)
 {
-       struct inode *inode = vma->vm_file->f_dentry->d_inode;
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
        struct mm_struct *mm = vma->vm_mm;
        enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
        unsigned long size;
@@ -1293,14 +1293,14 @@ static int shmem_populate(struct vm_area_struct *vma,
 #ifdef CONFIG_NUMA
 int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
 {
-       struct inode *i = vma->vm_file->f_dentry->d_inode;
+       struct inode *i = vma->vm_file->f_path.dentry->d_inode;
        return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
 }
 
 struct mempolicy *
 shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
 {
-       struct inode *i = vma->vm_file->f_dentry->d_inode;
+       struct inode *i = vma->vm_file->f_path.dentry->d_inode;
        unsigned long idx;
 
        idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
@@ -1310,7 +1310,7 @@ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
 
 int shmem_lock(struct file *file, int lock, struct user_struct *user)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct shmem_inode_info *info = SHMEM_I(inode);
        int retval = -ENOMEM;
 
@@ -1422,7 +1422,7 @@ shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsig
 static ssize_t
 shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       struct inode    *inode = file->f_dentry->d_inode;
+       struct inode    *inode = file->f_path.dentry->d_inode;
        loff_t          pos;
        unsigned long   written;
        ssize_t         err;
@@ -1442,7 +1442,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
        if (err || !count)
                goto out;
 
-       err = remove_suid(file->f_dentry);
+       err = remove_suid(file->f_path.dentry);
        if (err)
                goto out;
 
@@ -1524,7 +1524,7 @@ out:
 
 static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
        unsigned long index, offset;
 
@@ -1943,7 +1943,7 @@ static int shmem_xattr_security_set(struct inode *inode, const char *name,
        return security_inode_setsecurity(inode, name, value, size, flags);
 }
 
-struct xattr_handler shmem_xattr_security_handler = {
+static struct xattr_handler shmem_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = shmem_xattr_security_list,
        .get    = shmem_xattr_security_get,
@@ -2263,7 +2263,7 @@ static struct kmem_cache *shmem_inode_cachep;
 static struct inode *shmem_alloc_inode(struct super_block *sb)
 {
        struct shmem_inode_info *p;
-       p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, SLAB_KERNEL);
+       p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
        if (!p)
                return NULL;
        return &p->vfs_inode;
@@ -2319,7 +2319,7 @@ static const struct address_space_operations shmem_aops = {
        .migratepage    = migrate_page,
 };
 
-static struct file_operations shmem_file_operations = {
+static const struct file_operations shmem_file_operations = {
        .mmap           = shmem_mmap,
 #ifdef CONFIG_TMPFS
        .llseek         = generic_file_llseek,
@@ -2493,8 +2493,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
        d_instantiate(dentry, inode);
        inode->i_size = size;
        inode->i_nlink = 0;     /* It is unlinked */
-       file->f_vfsmnt = mntget(shm_mnt);
-       file->f_dentry = dentry;
+       file->f_path.mnt = mntget(shm_mnt);
+       file->f_path.dentry = dentry;
        file->f_mapping = inode->i_mapping;
        file->f_op = &shmem_file_operations;
        file->f_mode = FMODE_WRITE | FMODE_READ;
index 3c4a7e3..2c65553 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 #include       <linux/module.h>
 #include       <linux/rcupdate.h>
 #include       <linux/string.h>
+#include       <linux/uaccess.h>
 #include       <linux/nodemask.h>
 #include       <linux/mempolicy.h>
 #include       <linux/mutex.h>
+#include       <linux/fault-inject.h>
 #include       <linux/rtmutex.h>
 
-#include       <asm/uaccess.h>
 #include       <asm/cacheflush.h>
 #include       <asm/tlbflush.h>
 #include       <asm/page.h>
@@ -313,7 +314,7 @@ static int drain_freelist(struct kmem_cache *cache,
 static void free_block(struct kmem_cache *cachep, void **objpp, int len,
                        int node);
 static int enable_cpucache(struct kmem_cache *cachep);
-static void cache_reap(void *unused);
+static void cache_reap(struct work_struct *unused);
 
 /*
  * This function must be completely optimized away if a constant is passed to
@@ -730,7 +731,10 @@ static inline void init_lock_keys(void)
 }
 #endif
 
-/* Guard access to the cache-chain. */
+/*
+ * 1. Guard access to the cache-chain.
+ * 2. Protect sanity of cpu_online_map against cpu hotplug events
+ */
 static DEFINE_MUTEX(cache_chain_mutex);
 static struct list_head cache_chain;
 
@@ -753,7 +757,7 @@ int slab_is_available(void)
        return g_cpucache_up == FULL;
 }
 
-static DEFINE_PER_CPU(struct work_struct, reap_work);
+static DEFINE_PER_CPU(struct delayed_work, reap_work);
 
 static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 {
@@ -866,6 +870,22 @@ static void __slab_error(const char *function, struct kmem_cache *cachep,
        dump_stack();
 }
 
+/*
+ * By default on NUMA we use alien caches to stage the freeing of
+ * objects allocated from other nodes. This causes massive memory
+ * inefficiencies when using fake NUMA setup to split memory into a
+ * large number of small nodes, so it can be disabled on the command
+ * line
+  */
+
+static int use_alien_caches __read_mostly = 1;
+static int __init noaliencache_setup(char *s)
+{
+       use_alien_caches = 0;
+       return 1;
+}
+__setup("noaliencache", noaliencache_setup);
+
 #ifdef CONFIG_NUMA
 /*
  * Special reaping functions for NUMA systems called from cache_reap().
@@ -916,17 +936,18 @@ static void next_reap_node(void)
  */
 static void __devinit start_cpu_timer(int cpu)
 {
-       struct work_struct *reap_work = &per_cpu(reap_work, cpu);
+       struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
 
        /*
         * When this gets called from do_initcalls via cpucache_init(),
         * init_workqueues() has already run, so keventd will be setup
         * at that time.
         */
-       if (keventd_up() && reap_work->func == NULL) {
+       if (keventd_up() && reap_work->work.func == NULL) {
                init_reap_node(cpu);
-               INIT_WORK(reap_work, cache_reap, NULL);
-               schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
+               INIT_DELAYED_WORK(reap_work, cache_reap);
+               schedule_delayed_work_on(cpu, reap_work,
+                                       __round_jiffies_relative(HZ, cpu));
        }
 }
 
@@ -996,7 +1017,7 @@ static inline void *alternate_node_alloc(struct kmem_cache *cachep,
        return NULL;
 }
 
-static inline void *__cache_alloc_node(struct kmem_cache *cachep,
+static inline void *____cache_alloc_node(struct kmem_cache *cachep,
                 gfp_t flags, int nodeid)
 {
        return NULL;
@@ -1004,7 +1025,7 @@ static inline void *__cache_alloc_node(struct kmem_cache *cachep,
 
 #else  /* CONFIG_NUMA */
 
-static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
+static void *____cache_alloc_node(struct kmem_cache *, gfp_t, int);
 static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
 
 static struct array_cache **alloc_alien_cache(int node, int limit)
@@ -1114,7 +1135,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
         * Make sure we are not freeing a object from another node to the array
         * cache on this cpu.
         */
-       if (likely(slabp->nodeid == node))
+       if (likely(slabp->nodeid == node) || unlikely(!use_alien_caches))
                return 0;
 
        l3 = cachep->nodelists[node];
@@ -1192,7 +1213,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                list_for_each_entry(cachep, &cache_chain, next) {
                        struct array_cache *nc;
                        struct array_cache *shared;
-                       struct array_cache **alien;
+                       struct array_cache **alien = NULL;
 
                        nc = alloc_arraycache(node, cachep->limit,
                                                cachep->batchcount);
@@ -1204,9 +1225,11 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                        if (!shared)
                                goto bad;
 
-                       alien = alloc_alien_cache(node, cachep->limit);
-                       if (!alien)
-                               goto bad;
+                       if (use_alien_caches) {
+                                alien = alloc_alien_cache(node, cachep->limit);
+                                if (!alien)
+                                        goto bad;
+                        }
                        cachep->array[cpu] = nc;
                        l3 = cachep->nodelists[node];
                        BUG_ON(!l3);
@@ -1230,12 +1253,18 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                        kfree(shared);
                        free_alien_cache(alien);
                }
-               mutex_unlock(&cache_chain_mutex);
                break;
        case CPU_ONLINE:
+               mutex_unlock(&cache_chain_mutex);
                start_cpu_timer(cpu);
                break;
 #ifdef CONFIG_HOTPLUG_CPU
+       case CPU_DOWN_PREPARE:
+               mutex_lock(&cache_chain_mutex);
+               break;
+       case CPU_DOWN_FAILED:
+               mutex_unlock(&cache_chain_mutex);
+               break;
        case CPU_DEAD:
                /*
                 * Even if all the cpus of a node are down, we don't free the
@@ -1246,8 +1275,8 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                 * gets destroyed at kmem_cache_destroy().
                 */
                /* fall thru */
+#endif
        case CPU_UP_CANCELED:
-               mutex_lock(&cache_chain_mutex);
                list_for_each_entry(cachep, &cache_chain, next) {
                        struct array_cache *nc;
                        struct array_cache *shared;
@@ -1308,11 +1337,9 @@ free_array_cache:
                }
                mutex_unlock(&cache_chain_mutex);
                break;
-#endif
        }
        return NOTIFY_OK;
 bad:
-       mutex_unlock(&cache_chain_mutex);
        return NOTIFY_BAD;
 }
 
@@ -1580,12 +1607,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
        flags |= __GFP_COMP;
 #endif
 
-       /*
-        * 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;
+       flags |= cachep->gfpflags;
 
        page = alloc_pages_node(nodeid, flags, cachep->gfporder);
        if (!page)
@@ -2098,15 +2120,12 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        }
 
        /*
-        * Prevent CPUs from coming and going.
-        * lock_cpu_hotplug() nests outside cache_chain_mutex
+        * We use cache_chain_mutex to ensure a consistent view of
+        * cpu_online_map as well.  Please see cpuup_callback
         */
-       lock_cpu_hotplug();
-
        mutex_lock(&cache_chain_mutex);
 
        list_for_each_entry(pc, &cache_chain, next) {
-               mm_segment_t old_fs = get_fs();
                char tmp;
                int res;
 
@@ -2115,9 +2134,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                 * destroy its slab cache and no-one else reuses the vmalloc
                 * area of the module.  Print a warning.
                 */
-               set_fs(KERNEL_DS);
-               res = __get_user(tmp, pc->name);
-               set_fs(old_fs);
+               res = probe_kernel_address(pc->name, tmp);
                if (res) {
                        printk("SLAB: cache with size %d has lost its name\n",
                               pc->buffer_size);
@@ -2197,25 +2214,24 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
                ralign = BYTES_PER_WORD;
 
-       /* 2) arch mandated alignment: disables debug if necessary */
+       /* 2) arch mandated alignment */
        if (ralign < ARCH_SLAB_MINALIGN) {
                ralign = ARCH_SLAB_MINALIGN;
-               if (ralign > BYTES_PER_WORD)
-                       flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        }
-       /* 3) caller mandated alignment: disables debug if necessary */
+       /* 3) caller mandated alignment */
        if (ralign < align) {
                ralign = align;
-               if (ralign > BYTES_PER_WORD)
-                       flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        }
+       /* disable debug if necessary */
+       if (ralign > BYTES_PER_WORD)
+               flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        /*
         * 4) Store it.
         */
        align = ralign;
 
        /* Get cache's description obj. */
-       cachep = kmem_cache_zalloc(&cache_cache, SLAB_KERNEL);
+       cachep = kmem_cache_zalloc(&cache_cache, GFP_KERNEL);
        if (!cachep)
                goto oops;
 
@@ -2326,7 +2342,6 @@ oops:
                panic("kmem_cache_create(): failed to create slab `%s'\n",
                      name);
        mutex_unlock(&cache_chain_mutex);
-       unlock_cpu_hotplug();
        return cachep;
 }
 EXPORT_SYMBOL(kmem_cache_create);
@@ -2444,6 +2459,7 @@ out:
        return nr_freed;
 }
 
+/* Called with cache_chain_mutex held to protect against cpu hotplug */
 static int __cache_shrink(struct kmem_cache *cachep)
 {
        int ret = 0, i = 0;
@@ -2474,9 +2490,13 @@ static int __cache_shrink(struct kmem_cache *cachep)
  */
 int kmem_cache_shrink(struct kmem_cache *cachep)
 {
+       int ret;
        BUG_ON(!cachep || in_interrupt());
 
-       return __cache_shrink(cachep);
+       mutex_lock(&cache_chain_mutex);
+       ret = __cache_shrink(cachep);
+       mutex_unlock(&cache_chain_mutex);
+       return ret;
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
@@ -2500,23 +2520,16 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
 {
        BUG_ON(!cachep || in_interrupt());
 
-       /* Don't let CPUs to come and go */
-       lock_cpu_hotplug();
-
        /* Find the cache in the chain of caches. */
        mutex_lock(&cache_chain_mutex);
        /*
         * the chain is never empty, cache_cache is never destroyed
         */
        list_del(&cachep->next);
-       mutex_unlock(&cache_chain_mutex);
-
        if (__cache_shrink(cachep)) {
                slab_error(cachep, "Can't free all objects");
-               mutex_lock(&cache_chain_mutex);
                list_add(&cachep->next, &cache_chain);
                mutex_unlock(&cache_chain_mutex);
-               unlock_cpu_hotplug();
                return;
        }
 
@@ -2524,7 +2537,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
                synchronize_rcu();
 
        __kmem_cache_destroy(cachep);
-       unlock_cpu_hotplug();
+       mutex_unlock(&cache_chain_mutex);
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
@@ -2548,7 +2561,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
        if (OFF_SLAB(cachep)) {
                /* Slab management obj is off-slab. */
                slabp = kmem_cache_alloc_node(cachep->slabp_cache,
-                                             local_flags, nodeid);
+                                             local_flags & ~GFP_THISNODE, nodeid);
                if (!slabp)
                        return NULL;
        } else {
@@ -2618,7 +2631,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
 
 static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
 {
-       if (flags & SLAB_DMA)
+       if (flags & GFP_DMA)
                BUG_ON(!(cachep->gfpflags & GFP_DMA));
        else
                BUG_ON(cachep->gfpflags & GFP_DMA);
@@ -2689,10 +2702,10 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
  * Grow (by 1) the number of slabs within a cache.  This is called by
  * kmem_cache_alloc() when there are no active objs left in a cache.
  */
-static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
+static int cache_grow(struct kmem_cache *cachep,
+               gfp_t flags, int nodeid, void *objp)
 {
        struct slab *slabp;
-       void *objp;
        size_t offset;
        gfp_t local_flags;
        unsigned long ctor_flags;
@@ -2702,12 +2715,12 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         * Be lazy and only check for valid flags here,  keeping it out of the
         * critical path in kmem_cache_alloc().
         */
-       BUG_ON(flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW));
-       if (flags & SLAB_NO_GROW)
+       BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK | __GFP_NO_GROW));
+       if (flags & __GFP_NO_GROW)
                return 0;
 
        ctor_flags = SLAB_CTOR_CONSTRUCTOR;
-       local_flags = (flags & SLAB_LEVEL_MASK);
+       local_flags = (flags & GFP_LEVEL_MASK);
        if (!(local_flags & __GFP_WAIT))
                /*
                 * Not allowed to sleep.  Need to tell a constructor about
@@ -2744,12 +2757,14 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         * Get mem for the objs.  Attempt to allocate a physical page from
         * 'nodeid'.
         */
-       objp = kmem_getpages(cachep, flags, nodeid);
+       if (!objp)
+               objp = kmem_getpages(cachep, flags, nodeid);
        if (!objp)
                goto failed;
 
        /* Get slab management. */
-       slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
+       slabp = alloc_slabmgmt(cachep, objp, offset,
+                       local_flags & ~GFP_THISNODE, nodeid);
        if (!slabp)
                goto opps1;
 
@@ -2987,7 +3002,7 @@ alloc_done:
 
        if (unlikely(!ac->avail)) {
                int x;
-               x = cache_grow(cachep, flags, node);
+               x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
@@ -3063,18 +3078,101 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 
                cachep->ctor(objp, cachep, ctor_flags);
        }
+#if ARCH_SLAB_MINALIGN
+       if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
+               printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
+                      objp, ARCH_SLAB_MINALIGN);
+       }
+#endif
        return objp;
 }
 #else
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
+#ifdef CONFIG_FAILSLAB
+
+static struct failslab_attr {
+
+       struct fault_attr attr;
+
+       u32 ignore_gfp_wait;
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+       struct dentry *ignore_gfp_wait_file;
+#endif
+
+} failslab = {
+       .attr = FAULT_ATTR_INITIALIZER,
+       .ignore_gfp_wait = 1,
+};
+
+static int __init setup_failslab(char *str)
+{
+       return setup_fault_attr(&failslab.attr, str);
+}
+__setup("failslab=", setup_failslab);
+
+static int should_failslab(struct kmem_cache *cachep, gfp_t flags)
+{
+       if (cachep == &cache_cache)
+               return 0;
+       if (flags & __GFP_NOFAIL)
+               return 0;
+       if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT))
+               return 0;
+
+       return should_fail(&failslab.attr, obj_size(cachep));
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static int __init failslab_debugfs(void)
+{
+       mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+       struct dentry *dir;
+       int err;
+
+               err = init_fault_attr_dentries(&failslab.attr, "failslab");
+       if (err)
+               return err;
+       dir = failslab.attr.dentries.dir;
+
+       failslab.ignore_gfp_wait_file =
+               debugfs_create_bool("ignore-gfp-wait", mode, dir,
+                                     &failslab.ignore_gfp_wait);
+
+       if (!failslab.ignore_gfp_wait_file) {
+               err = -ENOMEM;
+               debugfs_remove(failslab.ignore_gfp_wait_file);
+               cleanup_fault_attr_dentries(&failslab.attr);
+       }
+
+       return err;
+}
+
+late_initcall(failslab_debugfs);
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#else /* CONFIG_FAILSLAB */
+
+static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags)
+{
+       return 0;
+}
+
+#endif /* CONFIG_FAILSLAB */
+
 static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *objp;
        struct array_cache *ac;
 
        check_irq_off();
+
+       if (should_failslab(cachep, flags))
+               return NULL;
+
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
                STATS_INC_ALLOCHIT(cachep);
@@ -3105,10 +3203,10 @@ static __always_inline void *__cache_alloc(struct kmem_cache *cachep,
                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
+        * ____cache_alloc_node() knows how to locate memory on other nodes
         */
        if (NUMA_BUILD && !objp)
-               objp = __cache_alloc_node(cachep, flags, numa_node_id());
+               objp = ____cache_alloc_node(cachep, flags, numa_node_id());
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp,
                                            caller);
@@ -3135,15 +3233,17 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
        else if (current->mempolicy)
                nid_alloc = slab_node(current->mempolicy);
        if (nid_alloc != nid_here)
-               return __cache_alloc_node(cachep, flags, nid_alloc);
+               return ____cache_alloc_node(cachep, flags, nid_alloc);
        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.
+ * certain node and fall back is permitted. First we scan all the
+ * available nodelists for available objects. If that fails then we
+ * perform an allocation without specifying a node. This allows the page
+ * allocator to do its reclaim / fallback magic. We then insert the
+ * slab into the proper nodelist and then allocate from it.
  */
 void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
 {
@@ -3151,15 +3251,51 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
                                        ->node_zonelists[gfp_zone(flags)];
        struct zone **z;
        void *obj = NULL;
+       int nid;
 
+retry:
+       /*
+        * Look through allowed nodes for objects available
+        * from existing per node queues.
+        */
        for (z = zonelist->zones; *z && !obj; z++) {
-               int nid = zone_to_nid(*z);
+               nid = zone_to_nid(*z);
 
-               if (zone_idx(*z) <= ZONE_NORMAL &&
-                               cpuset_zone_allowed(*z, flags) &&
-                               cache->nodelists[nid])
-                       obj = __cache_alloc_node(cache,
-                                       flags | __GFP_THISNODE, nid);
+               if (cpuset_zone_allowed(*z, flags | __GFP_HARDWALL) &&
+                       cache->nodelists[nid] &&
+                       cache->nodelists[nid]->free_objects)
+                               obj = ____cache_alloc_node(cache,
+                                       flags | GFP_THISNODE, nid);
+       }
+
+       if (!obj) {
+               /*
+                * This allocation will be performed within the constraints
+                * of the current cpuset / memory policy requirements.
+                * We may trigger various forms of reclaim on the allowed
+                * set and go into memory reserves if necessary.
+                */
+               obj = kmem_getpages(cache, flags, -1);
+               if (obj) {
+                       /*
+                        * Insert into the appropriate per node queues
+                        */
+                       nid = page_to_nid(virt_to_page(obj));
+                       if (cache_grow(cache, flags, nid, obj)) {
+                               obj = ____cache_alloc_node(cache,
+                                       flags | GFP_THISNODE, nid);
+                               if (!obj)
+                                       /*
+                                        * Another processor may allocate the
+                                        * objects in the slab since we are
+                                        * not holding any locks.
+                                        */
+                                       goto retry;
+                       } else {
+                               kmem_freepages(cache, obj);
+                               obj = NULL;
+                       }
+               }
        }
        return obj;
 }
@@ -3167,7 +3303,7 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
 /*
  * A interface to enable slab creation on nodeid
  */
-static void *__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
+static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
                                int nodeid)
 {
        struct list_head *entry;
@@ -3216,7 +3352,7 @@ retry:
 
 must_grow:
        spin_unlock(&l3->list_lock);
-       x = cache_grow(cachep, flags, nodeid);
+       x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
        if (x)
                goto retry;
 
@@ -3434,35 +3570,59 @@ out:
  * @flags: See kmalloc().
  * @nodeid: node number of the target node.
  *
- * Identical to kmem_cache_alloc, except that this function is slow
- * and can sleep. And it will allocate memory on the given node, which
- * can improve the performance for cpu bound structures.
- * New and improved: it will now make sure that the object gets
- * put on the correct node list so that there is no false sharing.
+ * Identical to kmem_cache_alloc but it will allocate memory on the given
+ * node, which can improve the performance for cpu bound structures.
+ *
+ * Fallback to other node is possible if __GFP_THISNODE is not set.
  */
-void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
+static __always_inline void *
+__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
+               int nodeid, void *caller)
 {
        unsigned long save_flags;
-       void *ptr;
+       void *ptr = NULL;
 
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
-       if (nodeid == -1 || nodeid == numa_node_id() ||
-                       !cachep->nodelists[nodeid])
-               ptr = ____cache_alloc(cachep, flags);
-       else
-               ptr = __cache_alloc_node(cachep, flags, nodeid);
-       local_irq_restore(save_flags);
+       if (unlikely(nodeid == -1))
+               nodeid = numa_node_id();
 
-       ptr = cache_alloc_debugcheck_after(cachep, flags, ptr,
-                                          __builtin_return_address(0));
+       if (likely(cachep->nodelists[nodeid])) {
+               if (nodeid == numa_node_id()) {
+                       /*
+                        * Use the locally cached objects if possible.
+                        * However ____cache_alloc does not allow fallback
+                        * to other nodes. It may fail while we still have
+                        * objects on other nodes available.
+                        */
+                       ptr = ____cache_alloc(cachep, flags);
+               }
+               if (!ptr) {
+                       /* ___cache_alloc_node can fall back to other nodes */
+                       ptr = ____cache_alloc_node(cachep, flags, nodeid);
+               }
+       } else {
+               /* Node not bootstrapped yet */
+               if (!(flags & __GFP_THISNODE))
+                       ptr = fallback_alloc(cachep, flags);
+       }
+
+       local_irq_restore(save_flags);
+       ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
 
        return ptr;
 }
+
+void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
+{
+       return __cache_alloc_node(cachep, flags, nodeid,
+                       __builtin_return_address(0));
+}
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
-void *__kmalloc_node(size_t size, gfp_t flags, int node)
+static __always_inline void *
+__do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller)
 {
        struct kmem_cache *cachep;
 
@@ -3471,8 +3631,29 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
                return NULL;
        return kmem_cache_alloc_node(cachep, flags, node);
 }
+
+#ifdef CONFIG_DEBUG_SLAB
+void *__kmalloc_node(size_t size, gfp_t flags, int node)
+{
+       return __do_kmalloc_node(size, flags, node,
+                       __builtin_return_address(0));
+}
 EXPORT_SYMBOL(__kmalloc_node);
-#endif
+
+void *__kmalloc_node_track_caller(size_t size, gfp_t flags,
+               int node, void *caller)
+{
+       return __do_kmalloc_node(size, flags, node, caller);
+}
+EXPORT_SYMBOL(__kmalloc_node_track_caller);
+#else
+void *__kmalloc_node(size_t size, gfp_t flags, int node)
+{
+       return __do_kmalloc_node(size, flags, node, NULL);
+}
+EXPORT_SYMBOL(__kmalloc_node);
+#endif /* CONFIG_DEBUG_SLAB */
+#endif /* CONFIG_NUMA */
 
 /**
  * __do_kmalloc - allocate memory
@@ -3583,13 +3764,15 @@ static int alloc_kmemlist(struct kmem_cache *cachep)
        int node;
        struct kmem_list3 *l3;
        struct array_cache *new_shared;
-       struct array_cache **new_alien;
+       struct array_cache **new_alien = NULL;
 
        for_each_online_node(node) {
 
-               new_alien = alloc_alien_cache(node, cachep->limit);
-               if (!new_alien)
-                       goto fail;
+                if (use_alien_caches) {
+                        new_alien = alloc_alien_cache(node, cachep->limit);
+                        if (!new_alien)
+                                goto fail;
+                }
 
                new_shared = alloc_arraycache(node,
                                cachep->shared*cachep->batchcount,
@@ -3815,7 +3998,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
  * If we cannot acquire the cache chain mutex then just give up - we'll try
  * again on the next iteration.
  */
-static void cache_reap(void *unused)
+static void cache_reap(struct work_struct *unused)
 {
        struct kmem_cache *searchp;
        struct kmem_list3 *l3;
@@ -3824,7 +4007,7 @@ static void cache_reap(void *unused)
        if (!mutex_trylock(&cache_chain_mutex)) {
                /* Give up. Setup the next iteration. */
                schedule_delayed_work(&__get_cpu_var(reap_work),
-                                     REAPTIMEOUT_CPUC);
+                                     round_jiffies_relative(REAPTIMEOUT_CPUC));
                return;
        }
 
@@ -3870,7 +4053,8 @@ next:
        next_reap_node();
        refresh_cpu_vm_stats(smp_processor_id());
        /* Set up the next iteration */
-       schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
+       schedule_delayed_work(&__get_cpu_var(reap_work),
+               round_jiffies_relative(REAPTIMEOUT_CPUC));
 }
 
 #ifdef CONFIG_PROC_FS
@@ -4038,7 +4222,7 @@ static int s_show(struct seq_file *m, void *p)
  * + further values on SMP and with statistics enabled
  */
 
-struct seq_operations slabinfo_op = {
+const struct seq_operations slabinfo_op = {
        .start = s_start,
        .next = s_next,
        .stop = s_stop,
@@ -4236,7 +4420,7 @@ static int leaks_show(struct seq_file *m, void *p)
        return 0;
 }
 
-struct seq_operations slabstats_op = {
+const struct seq_operations slabstats_op = {
        .start = leaks_start,
        .next = s_next,
        .stop = s_stop,
index b3c82ba..ac26eb0 100644 (file)
@@ -24,6 +24,25 @@ struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
 #endif
 EXPORT_SYMBOL(mem_section);
 
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+/*
+ * If we did not store the node number in the page then we have to
+ * do a lookup in the section_to_node_table in order to find which
+ * node the page belongs to.
+ */
+#if MAX_NUMNODES <= 256
+static u8 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
+#else
+static u16 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
+#endif
+
+int page_to_nid(struct page *page)
+{
+       return section_to_node_table[page_to_section(page)];
+}
+EXPORT_SYMBOL(page_to_nid);
+#endif
+
 #ifdef CONFIG_SPARSEMEM_EXTREME
 static struct mem_section *sparse_index_alloc(int nid)
 {
@@ -49,6 +68,10 @@ static int sparse_index_init(unsigned long section_nr, int nid)
        struct mem_section *section;
        int ret = 0;
 
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+       section_to_node_table[section_nr] = nid;
+#endif
+
        if (mem_section[root])
                return -EEXIST;
 
index 2e0e871..2ed7be3 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -57,9 +57,9 @@ static void put_compound_page(struct page *page)
 {
        page = (struct page *)page_private(page);
        if (put_page_testzero(page)) {
-               void (*dtor)(struct page *page);
+               compound_page_dtor *dtor;
 
-               dtor = (void (*)(struct page *))page[1].lru.next;
+               dtor = get_compound_page_dtor(page);
                (*dtor)(page);
        }
 }
@@ -216,7 +216,7 @@ void lru_add_drain(void)
 }
 
 #ifdef CONFIG_NUMA
-static void lru_add_drain_per_cpu(void *dummy)
+static void lru_add_drain_per_cpu(struct work_struct *dummy)
 {
        lru_add_drain();
 }
@@ -226,7 +226,7 @@ static void lru_add_drain_per_cpu(void *dummy)
  */
 int lru_add_drain_all(void)
 {
-       return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL);
+       return schedule_on_each_cpu(lru_add_drain_per_cpu);
 }
 
 #else
@@ -514,5 +514,7 @@ void __init swap_setup(void)
         * Right now other parts of the system means that we
         * _really_ don't want to cluster much more
         */
+#ifdef CONFIG_HOTPLUG_CPU
        hotcpu_notifier(cpu_swap_callback, 0);
+#endif
 }
index a15def6..b9fc0e5 100644 (file)
@@ -427,34 +427,48 @@ void free_swap_and_cache(swp_entry_t entry)
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
 /*
- * Find the swap type that corresponds to given device (if any)
+ * Find the swap type that corresponds to given device (if any).
  *
- * This is needed for software suspend and is done in such a way that inode
- * aliasing is allowed.
+ * @offset - number of the PAGE_SIZE-sized block of the device, starting
+ * from 0, in which the swap header is expected to be located.
+ *
+ * This is needed for the suspend to disk (aka swsusp).
  */
-int swap_type_of(dev_t device)
+int swap_type_of(dev_t device, sector_t offset)
 {
+       struct block_device *bdev = NULL;
        int i;
 
+       if (device)
+               bdev = bdget(device);
+
        spin_lock(&swap_lock);
        for (i = 0; i < nr_swapfiles; i++) {
-               struct inode *inode;
+               struct swap_info_struct *sis = swap_info + i;
 
-               if (!(swap_info[i].flags & SWP_WRITEOK))
+               if (!(sis->flags & SWP_WRITEOK))
                        continue;
 
-               if (!device) {
+               if (!bdev) {
                        spin_unlock(&swap_lock);
                        return i;
                }
-               inode = swap_info[i].swap_file->f_dentry->d_inode;
-               if (S_ISBLK(inode->i_mode) &&
-                   device == MKDEV(imajor(inode), iminor(inode))) {
-                       spin_unlock(&swap_lock);
-                       return i;
+               if (bdev == sis->bdev) {
+                       struct swap_extent *se;
+
+                       se = list_entry(sis->extent_list.next,
+                                       struct swap_extent, list);
+                       if (se->start_block == offset) {
+                               spin_unlock(&swap_lock);
+                               bdput(bdev);
+                               return i;
+                       }
                }
        }
        spin_unlock(&swap_lock);
+       if (bdev)
+               bdput(bdev);
+
        return -ENODEV;
 }
 
@@ -931,6 +945,23 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset)
        }
 }
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+/*
+ * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev
+ * corresponding to given index in swap_info (swap type).
+ */
+sector_t swapdev_block(int swap_type, pgoff_t offset)
+{
+       struct swap_info_struct *sis;
+
+       if (swap_type >= nr_swapfiles)
+               return 0;
+
+       sis = swap_info + swap_type;
+       return (sis->flags & SWP_WRITEOK) ? map_swap_page(sis, offset) : 0;
+}
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
 /*
  * Free all of a swapdev's extent information
  */
@@ -1274,10 +1305,13 @@ static void *swap_start(struct seq_file *swap, loff_t *pos)
 
        mutex_lock(&swapon_mutex);
 
+       if (!l)
+               return SEQ_START_TOKEN;
+
        for (i = 0; i < nr_swapfiles; i++, ptr++) {
                if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
                        continue;
-               if (!l--)
+               if (!--l)
                        return ptr;
        }
 
@@ -1286,10 +1320,17 @@ static void *swap_start(struct seq_file *swap, loff_t *pos)
 
 static void *swap_next(struct seq_file *swap, void *v, loff_t *pos)
 {
-       struct swap_info_struct *ptr = v;
+       struct swap_info_struct *ptr;
        struct swap_info_struct *endptr = swap_info + nr_swapfiles;
 
-       for (++ptr; ptr < endptr; ptr++) {
+       if (v == SEQ_START_TOKEN)
+               ptr = swap_info;
+       else {
+               ptr = v;
+               ptr++;
+       }
+
+       for (; ptr < endptr; ptr++) {
                if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
                        continue;
                ++*pos;
@@ -1310,14 +1351,16 @@ static int swap_show(struct seq_file *swap, void *v)
        struct file *file;
        int len;
 
-       if (v == swap_info)
-               seq_puts(swap, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+       if (ptr == SEQ_START_TOKEN) {
+               seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+               return 0;
+       }
 
        file = ptr->swap_file;
-       len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+       len = seq_path(swap, file->f_path.mnt, file->f_path.dentry, " \t\n\\");
        seq_printf(swap, "%*s%s\t%u\t%u\t%d\n",
                       len < 40 ? 40 - len : 1, " ",
-                      S_ISBLK(file->f_dentry->d_inode->i_mode) ?
+                      S_ISBLK(file->f_path.dentry->d_inode->i_mode) ?
                                "partition" : "file\t",
                       ptr->pages << (PAGE_SHIFT - 10),
                       ptr->inuse_pages << (PAGE_SHIFT - 10),
@@ -1325,7 +1368,7 @@ static int swap_show(struct seq_file *swap, void *v)
        return 0;
 }
 
-static struct seq_operations swaps_op = {
+static const struct seq_operations swaps_op = {
        .start =        swap_start,
        .next =         swap_next,
        .stop =         swap_stop,
@@ -1337,7 +1380,7 @@ static int swaps_open(struct inode *inode, struct file *file)
        return seq_open(file, &swaps_op);
 }
 
-static struct file_operations proc_swaps_operations = {
+static const struct file_operations proc_swaps_operations = {
        .open           = swaps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -1540,6 +1583,11 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                error = -EINVAL;
                if (!maxpages)
                        goto bad_swap;
+               if (swapfilesize && maxpages > swapfilesize) {
+                       printk(KERN_WARNING
+                              "Swap area shorter than signature indicates\n");
+                       goto bad_swap;
+               }
                if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode))
                        goto bad_swap;
                if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
@@ -1567,12 +1615,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                        goto bad_swap;
        }
 
-       if (swapfilesize && maxpages > swapfilesize) {
-               printk(KERN_WARNING
-                      "Swap area shorter than signature indicates\n");
-               error = -EINVAL;
-               goto bad_swap;
-       }
        if (nr_good_pages) {
                p->swap_map[0] = SWAP_MAP_BAD;
                p->max = maxpages;
index f4c560b..9ef9071 100644 (file)
  *
  * Simple token based thrashing protection, using the algorithm
  * described in:  http://www.cs.wm.edu/~sjiang/token.pdf
+ *
+ * Sep 2006, Ashwin Chaugule <ashwin.chaugule@celunite.com>
+ * Improved algorithm to pass token:
+ * Each task has a priority which is incremented if it contended
+ * for the token in an interval less than its previous attempt.
+ * If the token is acquired, that task's priority is boosted to prevent
+ * the token from bouncing around too often and to let the task make
+ * some progress in its execution.
  */
+
 #include <linux/jiffies.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
 
 static DEFINE_SPINLOCK(swap_token_lock);
-static unsigned long swap_token_timeout;
-static unsigned long swap_token_check;
-struct mm_struct * swap_token_mm = &init_mm;
-
-#define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
-#define SWAP_TOKEN_TIMEOUT     (300 * HZ)
-/*
- * Currently disabled; Needs further code to work at HZ * 300.
- */
-unsigned long swap_token_default_timeout = SWAP_TOKEN_TIMEOUT;
-
-/*
- * Take the token away if the process had no page faults
- * in the last interval, or if it has held the token for
- * too long.
- */
-#define SWAP_TOKEN_ENOUGH_RSS 1
-#define SWAP_TOKEN_TIMED_OUT 2
-static int should_release_swap_token(struct mm_struct *mm)
-{
-       int ret = 0;
-       if (!mm->recent_pagein)
-               ret = SWAP_TOKEN_ENOUGH_RSS;
-       else if (time_after(jiffies, swap_token_timeout))
-               ret = SWAP_TOKEN_TIMED_OUT;
-       mm->recent_pagein = 0;
-       return ret;
-}
+struct mm_struct *swap_token_mm;
+static unsigned int global_faults;
 
-/*
- * Try to grab the swapout protection token.  We only try to
- * grab it once every TOKEN_CHECK_INTERVAL, both to prevent
- * SMP lock contention and to check that the process that held
- * the token before is no longer thrashing.
- */
 void grab_swap_token(void)
 {
-       struct mm_struct *mm;
-       int reason;
+       int current_interval;
 
-       /* We have the token. Let others know we still need it. */
-       if (has_swap_token(current->mm)) {
-               current->mm->recent_pagein = 1;
-               if (unlikely(!swap_token_default_timeout))
-                       disable_swap_token();
-               return;
-       }
-
-       if (time_after(jiffies, swap_token_check)) {
+       global_faults++;
 
-               if (!swap_token_default_timeout) {
-                       swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
-                       return;
-               }
-
-               /* ... or if we recently held the token. */
-               if (time_before(jiffies, current->mm->swap_token_time))
-                       return;
+       current_interval = global_faults - current->mm->faultstamp;
 
-               if (!spin_trylock(&swap_token_lock))
-                       return;
+       if (!spin_trylock(&swap_token_lock))
+               return;
 
-               swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
+       /* First come first served */
+       if (swap_token_mm == NULL) {
+               current->mm->token_priority = current->mm->token_priority + 2;
+               swap_token_mm = current->mm;
+               goto out;
+       }
 
-               mm = swap_token_mm;
-               if ((reason = should_release_swap_token(mm))) {
-                       unsigned long eligible = jiffies;
-                       if (reason == SWAP_TOKEN_TIMED_OUT) {
-                               eligible += swap_token_default_timeout;
-                       }
-                       mm->swap_token_time = eligible;
-                       swap_token_timeout = jiffies + swap_token_default_timeout;
+       if (current->mm != swap_token_mm) {
+               if (current_interval < current->mm->last_interval)
+                       current->mm->token_priority++;
+               else {
+                       current->mm->token_priority--;
+                       if (unlikely(current->mm->token_priority < 0))
+                               current->mm->token_priority = 0;
+               }
+               /* Check if we deserve the token */
+               if (current->mm->token_priority >
+                               swap_token_mm->token_priority) {
+                       current->mm->token_priority += 2;
                        swap_token_mm = current->mm;
                }
-               spin_unlock(&swap_token_lock);
+       } else {
+               /* Token holder came in again! */
+               current->mm->token_priority += 2;
        }
-       return;
+
+out:
+       current->mm->faultstamp = global_faults;
+       current->mm->last_interval = current_interval;
+       spin_unlock(&swap_token_lock);
+return;
 }
 
 /* Called on process exit. */
 void __put_swap_token(struct mm_struct *mm)
 {
        spin_lock(&swap_token_lock);
-       if (likely(mm == swap_token_mm)) {
-               mm->swap_token_time = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
-               swap_token_mm = &init_mm;
-               swap_token_check = jiffies;
-       }
+       if (likely(mm == swap_token_mm))
+               swap_token_mm = NULL;
        spin_unlock(&swap_token_lock);
 }
index 5f2cbf0..c7f6e19 100644 (file)
@@ -79,8 +79,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
        d_instantiate(dentry, inode);
        inode->i_nlink = 0;     /* It is unlinked */
 
-       file->f_vfsmnt = mntget(shm_mnt);
-       file->f_dentry = dentry;
+       file->f_path.mnt = mntget(shm_mnt);
+       file->f_path.dentry = dentry;
        file->f_mapping = inode->i_mapping;
        file->f_op = &ramfs_file_operations;
        file->f_mode = FMODE_WRITE | FMODE_READ;
index e07b1e6..9bfb8e8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/buffer_head.h> /* grr. try_to_release_page,
                                   do_invalidatepage */
 
@@ -69,7 +70,8 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
        if (PagePrivate(page))
                do_invalidatepage(page, 0);
 
-       clear_page_dirty(page);
+       if (test_clear_page_dirty(page))
+               task_io_account_cancelled_write(PAGE_CACHE_SIZE);
        ClearPageUptodate(page);
        ClearPageMappedToDisk(page);
        remove_from_page_cache(page);
index 518540a..093f5fe 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/rwsem.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -1172,11 +1173,12 @@ loop_again:
                        if (!zone_watermark_ok(zone, order, zone->pages_high,
                                               0, 0)) {
                                end_zone = i;
-                               goto scan;
+                               break;
                        }
                }
-               goto out;
-scan:
+               if (i < 0)
+                       goto out;
+
                for (i = 0; i <= end_zone; i++) {
                        struct zone *zone = pgdat->node_zones + i;
 
@@ -1259,6 +1261,9 @@ out:
        }
        if (!all_zones_ok) {
                cond_resched();
+
+               try_to_freeze();
+
                goto loop_again;
        }
 
@@ -1508,7 +1513,6 @@ out:
 }
 #endif
 
-#ifdef CONFIG_HOTPLUG_CPU
 /* It's optimal to keep kswapds on the same CPUs as their memory, but
    not required for correctness.  So if the last cpu in a node goes
    away, we get changed to run anywhere: as the first one comes back,
@@ -1529,7 +1533,6 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
        }
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 /*
  * This kswapd start function will be called by init and node-hot-add.
index 8614e8f..dc005a0 100644 (file)
@@ -430,7 +430,7 @@ static int frag_show(struct seq_file *m, void *arg)
        return 0;
 }
 
-struct seq_operations fragmentation_op = {
+const struct seq_operations fragmentation_op = {
        .start  = frag_start,
        .next   = frag_next,
        .stop   = frag_stop,
@@ -452,7 +452,7 @@ struct seq_operations fragmentation_op = {
 #define TEXTS_FOR_ZONES(xx) xx "_dma", TEXT_FOR_DMA32(xx) xx "_normal", \
                                        TEXT_FOR_HIGHMEM(xx)
 
-static char *vmstat_text[] = {
+static const char * const vmstat_text[] = {
        /* Zoned VM counters */
        "nr_anon_pages",
        "nr_mapped",
@@ -597,7 +597,7 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
        return 0;
 }
 
-struct seq_operations zoneinfo_op = {
+const struct seq_operations zoneinfo_op = {
        .start  = frag_start, /* iterate over all zones. The same as in
                               * fragmentation. */
        .next   = frag_next,
@@ -660,7 +660,7 @@ static void vmstat_stop(struct seq_file *m, void *arg)
        m->private = NULL;
 }
 
-struct seq_operations vmstat_op = {
+const struct seq_operations vmstat_op = {
        .start  = vmstat_start,
        .next   = vmstat_next,
        .stop   = vmstat_stop,
@@ -679,13 +679,13 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
                void *hcpu)
 {
        switch (action) {
-               case CPU_UP_PREPARE:
-               case CPU_UP_CANCELED:
-               case CPU_DEAD:
-                       refresh_zone_stat_thresholds();
-                       break;
-               default:
-                       break;
+       case CPU_UP_PREPARE:
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               refresh_zone_stat_thresholds();
+               break;
+       default:
+               break;
        }
        return NOTIFY_OK;
 }
index 5946ec6..3fc0abe 100644 (file)
@@ -1454,7 +1454,7 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
 
 #define LEC_ARP_REFRESH_INTERVAL (3*HZ)
 
-static void lec_arp_check_expire(void *data);
+static void lec_arp_check_expire(struct work_struct *work);
 static void lec_arp_expire_arp(unsigned long data);
 
 /* 
@@ -1477,7 +1477,7 @@ static void lec_arp_init(struct lec_priv *priv)
         INIT_HLIST_HEAD(&priv->lec_no_forward);
         INIT_HLIST_HEAD(&priv->mcast_fwds);
        spin_lock_init(&priv->lec_arp_lock);
-       INIT_WORK(&priv->lec_arp_work, lec_arp_check_expire, priv);
+       INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
        schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
 }
 
@@ -1875,10 +1875,11 @@ static void lec_arp_expire_vcc(unsigned long data)
  *       to ESI_FORWARD_DIRECT. This causes the flush period to end
  *       regardless of the progress of the flush protocol.
  */
-static void lec_arp_check_expire(void *data)
+static void lec_arp_check_expire(struct work_struct *work)
 {
        unsigned long flags;
-       struct lec_priv *priv = data;
+       struct lec_priv *priv =
+               container_of(work, struct lec_priv, lec_arp_work.work);
        struct hlist_node *node, *next;
        struct lec_arp_table *entry;
        unsigned long now;
index 24cc95f..99136ba 100644 (file)
@@ -92,7 +92,7 @@ struct lec_priv {
        spinlock_t lec_arp_lock;
        struct atm_vcc *mcast_vcc;              /* Default Multicast Send VCC */
        struct atm_vcc *lecd;
-       struct work_struct lec_arp_work;        /* C10 */
+       struct delayed_work lec_arp_work;       /* C10 */
        unsigned int maximum_unknown_frame_count;
                                                /*
                                                 * Within the period of time defined by this variable, the client will send
index 91fe5f5..739866b 100644 (file)
@@ -393,7 +393,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
        if (count == 0) return 0;
        page = get_zeroed_page(GFP_KERNEL);
        if (!page) return -ENOMEM;
-       dev = PDE(file->f_dentry->d_inode)->data;
+       dev = PDE(file->f_path.dentry->d_inode)->data;
        if (!dev->ops->proc_read)
                length = -EINVAL;
        else {
index 5f0896a..97a49c7 100644 (file)
 #include <linux/interrupt.h>
 
 /*
- *     The null address is defined as a callsign of all spaces with an
- *     SSID of zero.
+ * The default broadcast address of an interface is QST-0; the default address
+ * is LINUX-1.  The null address is defined as a callsign of all spaces with
+ * an SSID of zero.
  */
-ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
 
+const ax25_address ax25_bcast =
+       {{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
+const ax25_address ax25_defaddr =
+       {{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, 1 << 1}};
+const ax25_address null_ax25_address =
+       {{' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
+
+EXPORT_SYMBOL_GPL(ax25_bcast);
+EXPORT_SYMBOL_GPL(ax25_defaddr);
 EXPORT_SYMBOL(null_ax25_address);
 
 /*
  *     ax25 -> ascii conversion
  */
-char *ax2asc(char *buf, ax25_address *a)
+char *ax2asc(char *buf, const ax25_address *a)
 {
        char c, *s;
        int n;
@@ -72,9 +81,9 @@ EXPORT_SYMBOL(ax2asc);
 /*
  *     ascii -> ax25 conversion
  */
-void asc2ax(ax25_address *addr, char *callsign)
+void asc2ax(ax25_address *addr, const char *callsign)
 {
-       char *s;
+       const char *s;
        int n;
 
        for (s = callsign, n = 0; n < 6; n++) {
@@ -107,7 +116,7 @@ EXPORT_SYMBOL(asc2ax);
 /*
  *     Compare two ax.25 addresses
  */
-int ax25cmp(ax25_address *a, ax25_address *b)
+int ax25cmp(const ax25_address *a, const ax25_address *b)
 {
        int ct = 0;
 
@@ -128,7 +137,7 @@ EXPORT_SYMBOL(ax25cmp);
 /*
  *     Compare two AX.25 digipeater paths.
  */
-int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
+int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2)
 {
        int i;
 
@@ -149,7 +158,9 @@ int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
  *     Given an AX.25 address pull of to, from, digi list, command/response and the start of data
  *
  */
-unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama)
+const unsigned char *ax25_addr_parse(const unsigned char *buf, int len,
+       ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags,
+       int *dama)
 {
        int d = 0;
 
@@ -204,7 +215,8 @@ unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, a
 /*
  *     Assemble an AX.25 header from the bits
  */
-int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, ax25_digi *d, int flag, int modulus)
+int ax25_addr_build(unsigned char *buf, const ax25_address *src,
+       const ax25_address *dest, const ax25_digi *d, int flag, int modulus)
 {
        int len = 0;
        int ct  = 0;
@@ -261,7 +273,7 @@ int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, a
        return len;
 }
 
-int ax25_addr_size(ax25_digi *dp)
+int ax25_addr_size(const ax25_digi *dp)
 {
        if (dp == NULL)
                return 2 * AX25_ADDR_LEN;
@@ -272,7 +284,7 @@ int ax25_addr_size(ax25_digi *dp)
 /*
  *     Reverse Digipeat List. May not pass both parameters as same struct
  */
-void ax25_digi_invert(ax25_digi *in, ax25_digi *out)
+void ax25_digi_invert(const ax25_digi *in, ax25_digi *out)
 {
        int ct;
 
index 3eeeb7a..d4c9356 100644 (file)
@@ -237,9 +237,9 @@ static void bt_release(struct device *dev)
        kfree(data);
 }
 
-static void add_conn(void *data)
+static void add_conn(struct work_struct *work)
 {
-       struct hci_conn *conn = data;
+       struct hci_conn *conn = container_of(work, struct hci_conn, work);
        int i;
 
        if (device_register(&conn->dev) < 0) {
@@ -272,14 +272,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
 
        dev_set_drvdata(&conn->dev, conn);
 
-       INIT_WORK(&conn->work, add_conn, (void *) conn);
+       INIT_WORK(&conn->work, add_conn);
 
        schedule_work(&conn->work);
 }
 
-static void del_conn(void *data)
+static void del_conn(struct work_struct *work)
 {
-       struct hci_conn *conn = data;
+       struct hci_conn *conn = container_of(work, struct hci_conn, work);
        device_del(&conn->dev);
 }
 
@@ -287,7 +287,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
 {
        BT_DBG("conn %p", conn);
 
-       INIT_WORK(&conn->work, del_conn, (void *) conn);
+       INIT_WORK(&conn->work, del_conn);
 
        schedule_work(&conn->work);
 }
index 1fb5d42..e0e0d09 100644 (file)
@@ -752,9 +752,9 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
        return -ENOIOCTLCMD;
 }
 
-static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
+static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
-       struct termios *new = (struct termios *) tty->termios;
+       struct ktermios *new = tty->termios;
        int old_baud_rate = tty_termios_baud_rate(old);
        int new_baud_rate = tty_termios_baud_rate(new);
 
index d9f0486..8ca448d 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/atomic.h>
 #include "br_private.h"
 
-static kmem_cache_t *br_fdb_cache __read_mostly;
+static struct kmem_cache *br_fdb_cache __read_mostly;
 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
                      const unsigned char *addr);
 
index f753c40..55bb263 100644 (file)
@@ -77,12 +77,16 @@ static int port_cost(struct net_device *dev)
  * Called from work queue to allow for calling functions that
  * might sleep (such as speed check), and to debounce.
  */
-static void port_carrier_check(void *arg)
+static void port_carrier_check(struct work_struct *work)
 {
-       struct net_device *dev = arg;
        struct net_bridge_port *p;
+       struct net_device *dev;
        struct net_bridge *br;
 
+       dev = container_of(work, struct net_bridge_port,
+                          carrier_check.work)->dev;
+       work_release(work);
+
        rtnl_lock();
        p = dev->br_port;
        if (!p)
@@ -276,7 +280,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
        p->port_no = index;
        br_init_port(p);
        p->state = BR_STATE_DISABLED;
-       INIT_WORK(&p->carrier_check, port_carrier_check, dev);
+       INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check);
        br_stp_port_timer_init(p);
 
        kobject_init(&p->kobj);
index ac47ba2..bd221ad 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_arp.h>
 #include <linux/in_route.h>
+#include <linux/inetdevice.h>
 
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -221,10 +222,14 @@ static void __br_dnat_complain(void)
  *
  * Otherwise, the packet is considered to be routed and we just
  * change the destination MAC address so that the packet will
- * later be passed up to the IP stack to be routed.
+ * later be passed up to the IP stack to be routed. For a redirected
+ * packet, ip_route_input() will give back the localhost as output device,
+ * which differs from the bridge device.
  *
  * Let us now consider the case that ip_route_input() fails:
  *
+ * This can be because the destination address is martian, in which case
+ * the packet will be dropped.
  * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input()
  * will fail, while __ip_route_output_key() will return success. The source
  * address for __ip_route_output_key() is set to zero, so __ip_route_output_key
@@ -237,7 +242,8 @@ static void __br_dnat_complain(void)
  *
  * --Lennert, 20020411
  * --Bart, 20020416 (updated)
- * --Bart, 20021007 (updated) */
+ * --Bart, 20021007 (updated)
+ * --Bart, 20062711 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
        if (skb->pkt_type == PACKET_OTHERHOST) {
@@ -264,15 +270,15 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        struct iphdr *iph = skb->nh.iph;
        struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+       int err;
 
        if (nf_bridge->mask & BRNF_PKT_TYPE) {
                skb->pkt_type = PACKET_OTHERHOST;
                nf_bridge->mask ^= BRNF_PKT_TYPE;
        }
        nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
-
        if (dnat_took_place(skb)) {
-               if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) {
+               if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
                        struct rtable *rt;
                        struct flowi fl = {
                                .nl_u = {
@@ -283,19 +289,33 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
                                },
                                .proto = 0,
                        };
+                       struct in_device *in_dev = in_dev_get(dev);
+
+                       /* If err equals -EHOSTUNREACH the error is due to a
+                        * martian destination or due to the fact that
+                        * forwarding is disabled. For most martian packets,
+                        * ip_route_output_key() will fail. It won't fail for 2 types of
+                        * martian destinations: loopback destinations and destination
+                        * 0.0.0.0. In both cases the packet will be dropped because the
+                        * destination is the loopback device and not the bridge. */
+                       if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
+                               goto free_skb;
 
                        if (!ip_route_output_key(&rt, &fl)) {
                                /* - Bridged-and-DNAT'ed traffic doesn't
-                                *   require ip_forwarding.
-                                * - Deal with redirected traffic. */
-                               if (((struct dst_entry *)rt)->dev == dev ||
-                                   rt->rt_type == RTN_LOCAL) {
+                                *   require ip_forwarding. */
+                               if (((struct dst_entry *)rt)->dev == dev) {
                                        skb->dst = (struct dst_entry *)rt;
                                        goto bridged_dnat;
                                }
+                               /* we are sure that forwarding is disabled, so printing
+                                * this message is no problem. Note that the packet could
+                                * still have a martian destination address, in which case
+                                * the packet could be dropped even if forwarding were enabled */
                                __br_dnat_complain();
                                dst_release((struct dst_entry *)rt);
                        }
+free_skb:
                        kfree_skb(skb);
                        return 0;
                } else {
index 74258d8..3a534e9 100644 (file)
@@ -82,7 +82,7 @@ struct net_bridge_port
        struct timer_list               hold_timer;
        struct timer_list               message_age_timer;
        struct kobject                  kobj;
-       struct work_struct              carrier_check;
+       struct delayed_work             carrier_check;
        struct rcu_head                 rcu;
 };
 
index 59d058a..e660cb5 100644 (file)
@@ -3340,7 +3340,6 @@ void unregister_netdev(struct net_device *dev)
 
 EXPORT_SYMBOL(unregister_netdev);
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int dev_cpu_callback(struct notifier_block *nfb,
                            unsigned long action,
                            void *ocpu)
@@ -3384,7 +3383,6 @@ static int dev_cpu_callback(struct notifier_block *nfb,
 
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_NET_DMA
 /**
index 1a5e49d..836ec66 100644 (file)
@@ -125,7 +125,7 @@ void * dst_alloc(struct dst_ops * ops)
                if (ops->gc())
                        return NULL;
        }
-       dst = kmem_cache_alloc(ops->kmem_cachep, SLAB_ATOMIC);
+       dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC);
        if (!dst)
                return NULL;
        memset(dst, 0, ops->entry_size);
index b16d31a..d137f97 100644 (file)
@@ -44,7 +44,7 @@ static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL };
 
 #define flow_table(cpu) (per_cpu(flow_tables, cpu))
 
-static kmem_cache_t *flow_cachep __read_mostly;
+static struct kmem_cache *flow_cachep __read_mostly;
 
 static int flow_lwm, flow_hwm;
 
@@ -211,7 +211,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
                if (flow_count(cpu) > flow_hwm)
                        flow_cache_shrink(cpu);
 
-               fle = kmem_cache_alloc(flow_cachep, SLAB_ATOMIC);
+               fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
                if (fle) {
                        fle->next = *head;
                        *head = fle;
@@ -340,7 +340,6 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
        tasklet_init(tasklet, flow_cache_flush_tasklet, 0);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int flow_cache_cpu(struct notifier_block *nfb,
                          unsigned long action,
                          void *hcpu)
@@ -349,7 +348,6 @@ static int flow_cache_cpu(struct notifier_block *nfb,
                __flow_cache_shrink((unsigned long)hcpu, 0);
        return NOTIFY_OK;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 static int __init flow_cache_init(void)
 {
index 4b36114..549a2ce 100644 (file)
@@ -34,8 +34,8 @@ enum lw_bits {
 static unsigned long linkwatch_flags;
 static unsigned long linkwatch_nextevent;
 
-static void linkwatch_event(void *dummy);
-static DECLARE_WORK(linkwatch_work, linkwatch_event, NULL);
+static void linkwatch_event(struct work_struct *dummy);
+static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
 
 static LIST_HEAD(lweventlist);
 static DEFINE_SPINLOCK(lweventlist_lock);
@@ -127,7 +127,7 @@ void linkwatch_run_queue(void)
 }       
 
 
-static void linkwatch_event(void *dummy)
+static void linkwatch_event(struct work_struct *dummy)
 {
        /* Limit the number of linkwatch events to one
         * per second so that a runaway driver does not
@@ -171,10 +171,9 @@ void linkwatch_fire_event(struct net_device *dev)
                        unsigned long delay = linkwatch_nextevent - jiffies;
 
                        /* If we wrap around we'll delay it by at most HZ. */
-                       if (!delay || delay > HZ)
-                               schedule_work(&linkwatch_work);
-                       else
-                               schedule_delayed_work(&linkwatch_work, delay);
+                       if (delay > HZ)
+                               delay = 0;
+                       schedule_delayed_work(&linkwatch_work, delay);
                }
        }
 }
index ba509a4..e7300b6 100644 (file)
@@ -251,7 +251,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
                        goto out_entries;
        }
 
-       n = kmem_cache_alloc(tbl->kmem_cachep, SLAB_ATOMIC);
+       n = kmem_cache_alloc(tbl->kmem_cachep, GFP_ATOMIC);
        if (!n)
                goto out_entries;
 
@@ -577,9 +577,10 @@ void neigh_destroy(struct neighbour *neigh)
        while ((hh = neigh->hh) != NULL) {
                neigh->hh = hh->hh_next;
                hh->hh_next = NULL;
-               write_lock_bh(&hh->hh_lock);
+
+               write_seqlock_bh(&hh->hh_lock);
                hh->hh_output = neigh_blackhole;
-               write_unlock_bh(&hh->hh_lock);
+               write_sequnlock_bh(&hh->hh_lock);
                if (atomic_dec_and_test(&hh->hh_refcnt))
                        kfree(hh);
        }
@@ -897,9 +898,9 @@ static void neigh_update_hhs(struct neighbour *neigh)
 
        if (update) {
                for (hh = neigh->hh; hh; hh = hh->hh_next) {
-                       write_lock_bh(&hh->hh_lock);
+                       write_seqlock_bh(&hh->hh_lock);
                        update(hh, neigh->dev, neigh->ha);
-                       write_unlock_bh(&hh->hh_lock);
+                       write_sequnlock_bh(&hh->hh_lock);
                }
        }
 }
@@ -1089,7 +1090,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
                        break;
 
        if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
-               rwlock_init(&hh->hh_lock);
+               seqlock_init(&hh->hh_lock);
                hh->hh_type = protocol;
                atomic_set(&hh->hh_refcnt, 0);
                hh->hh_next = NULL;
index 3c58846..a01abdd 100644 (file)
@@ -50,9 +50,10 @@ static atomic_t trapped;
 static void zap_completion_queue(void);
 static void arp_reply(struct sk_buff *skb);
 
-static void queue_process(void *p)
+static void queue_process(struct work_struct *work)
 {
-       struct netpoll_info *npinfo = p;
+       struct netpoll_info *npinfo =
+               container_of(work, struct netpoll_info, tx_work.work);
        struct sk_buff *skb;
 
        while ((skb = skb_dequeue(&npinfo->txq))) {
@@ -72,8 +73,6 @@ static void queue_process(void *p)
                        schedule_delayed_work(&npinfo->tx_work, HZ/10);
                        return;
                }
-
-               netif_tx_unlock_bh(dev);
        }
 }
 
@@ -243,27 +242,33 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
 
        /* don't get messages out of order, and no recursion */
        if (skb_queue_len(&npinfo->txq) == 0 &&
-           npinfo->poll_owner != smp_processor_id() &&
-           netif_tx_trylock(dev)) {
-               /* try until next clock tick */
-               for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) {
-                       if (!netif_queue_stopped(dev))
-                               status = dev->hard_start_xmit(skb, dev);
+                   npinfo->poll_owner != smp_processor_id()) {
+               unsigned long flags;
 
-                       if (status == NETDEV_TX_OK)
-                               break;
+               local_irq_save(flags);
+               if (netif_tx_trylock(dev)) {
+                       /* try until next clock tick */
+                       for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+                                       tries > 0; --tries) {
+                               if (!netif_queue_stopped(dev))
+                                       status = dev->hard_start_xmit(skb, dev);
 
-                       /* tickle device maybe there is some cleanup */
-                       netpoll_poll(np);
+                               if (status == NETDEV_TX_OK)
+                                       break;
 
-                       udelay(USEC_PER_POLL);
+                               /* tickle device maybe there is some cleanup */
+                               netpoll_poll(np);
+
+                               udelay(USEC_PER_POLL);
+                       }
+                       netif_tx_unlock(dev);
                }
-               netif_tx_unlock(dev);
+               local_irq_restore(flags);
        }
 
        if (status != NETDEV_TX_OK) {
                skb_queue_tail(&npinfo->txq, skb);
-               schedule_work(&npinfo->tx_work);
+               schedule_delayed_work(&npinfo->tx_work,0);
        }
 }
 
@@ -331,6 +336,7 @@ static void arp_reply(struct sk_buff *skb)
        unsigned char *arp_ptr;
        int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
        __be32 sip, tip;
+       unsigned char *sha;
        struct sk_buff *send_skb;
        struct netpoll *np = NULL;
 
@@ -357,9 +363,14 @@ static void arp_reply(struct sk_buff *skb)
            arp->ar_op != htons(ARPOP_REQUEST))
                return;
 
-       arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len;
+       arp_ptr = (unsigned char *)(arp+1);
+       /* save the location of the src hw addr */
+       sha = arp_ptr;
+       arp_ptr += skb->dev->addr_len;
        memcpy(&sip, arp_ptr, 4);
-       arp_ptr += 4 + skb->dev->addr_len;
+       arp_ptr += 4;
+       /* if we actually cared about dst hw addr, it would get copied here */
+       arp_ptr += skb->dev->addr_len;
        memcpy(&tip, arp_ptr, 4);
 
        /* Should we ignore arp? */
@@ -382,7 +393,7 @@ static void arp_reply(struct sk_buff *skb)
 
        if (np->dev->hard_header &&
            np->dev->hard_header(send_skb, skb->dev, ptype,
-                                np->remote_mac, np->local_mac,
+                                sha, np->local_mac,
                                 send_skb->len) < 0) {
                kfree_skb(send_skb);
                return;
@@ -406,7 +417,7 @@ static void arp_reply(struct sk_buff *skb)
        arp_ptr += np->dev->addr_len;
        memcpy(arp_ptr, &tip, 4);
        arp_ptr += 4;
-       memcpy(arp_ptr, np->remote_mac, np->dev->addr_len);
+       memcpy(arp_ptr, sha, np->dev->addr_len);
        arp_ptr += np->dev->addr_len;
        memcpy(arp_ptr, &sip, 4);
 
@@ -628,7 +639,7 @@ int netpoll_setup(struct netpoll *np)
                spin_lock_init(&npinfo->rx_lock);
                skb_queue_head_init(&npinfo->arp_tx);
                skb_queue_head_init(&npinfo->txq);
-               INIT_WORK(&npinfo->tx_work, queue_process, npinfo);
+               INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
 
                atomic_set(&npinfo->refcnt, 1);
        } else {
index 8e1c385..de7801d 100644 (file)
@@ -68,8 +68,8 @@
 
 #include "kmap_skb.h"
 
-static kmem_cache_t *skbuff_head_cache __read_mostly;
-static kmem_cache_t *skbuff_fclone_cache __read_mostly;
+static struct kmem_cache *skbuff_head_cache __read_mostly;
+static struct kmem_cache *skbuff_fclone_cache __read_mostly;
 
 /*
  *     Keep out-of-line to prevent kernel bloat.
@@ -132,6 +132,7 @@ EXPORT_SYMBOL(skb_truesize_bug);
  *     @gfp_mask: allocation mask
  *     @fclone: allocate from fclone cache instead of head cache
  *             and allocate a cloned (child) skb
+ *     @node: numa node to allocate memory on
  *
  *     Allocate a new &sk_buff. The returned buffer has no headroom and a
  *     tail room of size bytes. The object has a reference count of one.
@@ -141,9 +142,9 @@ EXPORT_SYMBOL(skb_truesize_bug);
  *     %GFP_ATOMIC.
  */
 struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
-                           int fclone)
+                           int fclone, int node)
 {
-       kmem_cache_t *cache;
+       struct kmem_cache *cache;
        struct skb_shared_info *shinfo;
        struct sk_buff *skb;
        u8 *data;
@@ -151,14 +152,14 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
        cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
 
        /* Get the HEAD */
-       skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
+       skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
        if (!skb)
                goto out;
 
        /* Get the DATA. Size must match skb_add_mtu(). */
        size = SKB_DATA_ALIGN(size);
-       data = kmalloc_track_caller(size + sizeof(struct skb_shared_info),
-                       gfp_mask);
+       data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),
+                       gfp_mask, node);
        if (!data)
                goto nodata;
 
@@ -210,7 +211,7 @@ nodata:
  *     Buffers may only be allocated from interrupts using a @gfp_mask of
  *     %GFP_ATOMIC.
  */
-struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
+struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
                                     unsigned int size,
                                     gfp_t gfp_mask)
 {
@@ -267,9 +268,10 @@ nodata:
 struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
                unsigned int length, gfp_t gfp_mask)
 {
+       int node = dev->class_dev.dev ? dev_to_node(dev->class_dev.dev) : -1;
        struct sk_buff *skb;
 
-       skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
+       skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
        if (likely(skb)) {
                skb_reserve(skb, NET_SKB_PAD);
                skb->dev = dev;
index 419c7d3..0ed5b4f 100644 (file)
@@ -810,24 +810,11 @@ lenout:
  */
 static void inline sock_lock_init(struct sock *sk)
 {
-       spin_lock_init(&sk->sk_lock.slock);
-       sk->sk_lock.owner = NULL;
-       init_waitqueue_head(&sk->sk_lock.wq);
-       /*
-        * Make sure we are not reinitializing a held lock:
-        */
-       debug_check_no_locks_freed((void *)&sk->sk_lock, sizeof(sk->sk_lock));
-
-       /*
-        * Mark both the sk_lock and the sk_lock.slock as a
-        * per-address-family lock class:
-        */
-       lockdep_set_class_and_name(&sk->sk_lock.slock,
-                                  af_family_slock_keys + sk->sk_family,
-                                  af_family_slock_key_strings[sk->sk_family]);
-       lockdep_init_map(&sk->sk_lock.dep_map,
-                        af_family_key_strings[sk->sk_family],
-                        af_family_keys + sk->sk_family, 0);
+       sock_lock_init_class_and_name(sk,
+                       af_family_slock_key_strings[sk->sk_family],
+                       af_family_slock_keys + sk->sk_family,
+                       af_family_key_strings[sk->sk_family],
+                       af_family_keys + sk->sk_family);
 }
 
 /**
@@ -841,7 +828,7 @@ struct sock *sk_alloc(int family, gfp_t priority,
                      struct proto *prot, int zero_it)
 {
        struct sock *sk = NULL;
-       kmem_cache_t *slab = prot->slab;
+       struct kmem_cache *slab = prot->slab;
 
        if (slab != NULL)
                sk = kmem_cache_alloc(slab, priority);
index cb1b872..f69ab7b 100644 (file)
@@ -2130,7 +2130,7 @@ int iw_handler_set_spy(struct net_device *        dev,
         * The rtnl_lock() make sure we don't race with the other iw_handlers.
         * This make sure wireless_spy_update() "see" that the spy list
         * is temporarily disabled. */
-       wmb();
+       smp_wmb();
 
        /* Are there are addresses to copy? */
        if(wrqu->data.length > 0) {
@@ -2159,7 +2159,7 @@ int iw_handler_set_spy(struct net_device *        dev,
        }
 
        /* Make sure above is updated before re-enabling */
-       wmb();
+       smp_wmb();
 
        /* Enable addresses */
        spydata->spy_number = wrqu->data.length;
index bdf1bb7..a086c63 100644 (file)
@@ -21,8 +21,8 @@
 
 #include <net/sock.h>
 
-static kmem_cache_t *dccp_ackvec_slab;
-static kmem_cache_t *dccp_ackvec_record_slab;
+static struct kmem_cache *dccp_ackvec_slab;
+static struct kmem_cache *dccp_ackvec_record_slab;
 
 static struct dccp_ackvec_record *dccp_ackvec_record_new(void)
 {
@@ -223,7 +223,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
                        gap = -new_head;
                }
                new_head += DCCP_MAX_ACKVEC_LEN;
-       } 
+       }
 
        av->dccpav_buf_head = new_head;
 
@@ -336,7 +336,7 @@ out_duplicate:
 void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
 {
        dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
-                                       (unsigned long long)ackno);
+                        (unsigned long long)ackno);
 
        while (len--) {
                const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
index ff05e59..d8cf92f 100644 (file)
@@ -55,9 +55,9 @@ static inline void ccids_read_unlock(void)
 #define ccids_read_unlock() do { } while(0)
 #endif
 
-static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
+static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
 {
-       kmem_cache_t *slab;
+       struct kmem_cache *slab;
        char slab_name_fmt[32], *slab_name;
        va_list args;
 
@@ -75,7 +75,7 @@ static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
        return slab;
 }
 
-static void ccid_kmem_cache_destroy(kmem_cache_t *slab)
+static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
 {
        if (slab != NULL) {
                const char *name = kmem_cache_name(slab);
index c7c2951..c65cb24 100644 (file)
@@ -27,9 +27,9 @@ struct ccid_operations {
        unsigned char   ccid_id;
        const char      *ccid_name;
        struct module   *ccid_owner;
-       kmem_cache_t    *ccid_hc_rx_slab;
+       struct kmem_cache       *ccid_hc_rx_slab;
        __u32           ccid_hc_rx_obj_size;
-       kmem_cache_t    *ccid_hc_tx_slab;
+       struct kmem_cache       *ccid_hc_tx_slab;
        __u32           ccid_hc_tx_obj_size;
        int             (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
        int             (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
@@ -43,8 +43,6 @@ struct ccid_operations {
                                                    unsigned char* value);
        int             (*ccid_hc_rx_insert_options)(struct sock *sk,
                                                     struct sk_buff *skb);
-       int             (*ccid_hc_tx_insert_options)(struct sock *sk,
-                                                    struct sk_buff *skb);
        void            (*ccid_hc_tx_packet_recv)(struct sock *sk,
                                                  struct sk_buff *skb);
        int             (*ccid_hc_tx_parse_options)(struct sock *sk,
@@ -146,14 +144,6 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
        return rc;
 }
 
-static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
-                                           struct sk_buff *skb)
-{
-       if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
-               return ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
-       return 0;
-}
-
 static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
                                            struct sk_buff *skb)
 {
index 2555be8..fd38b05 100644 (file)
@@ -351,7 +351,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
 
                while (seqp != hctx->ccid2hctx_seqh) {
                        ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
-                                      (unsigned long long)seqp->ccid2s_seq,
+                                      (unsigned long long)seqp->ccid2s_seq,
                                       seqp->ccid2s_acked, seqp->ccid2s_sent);
                        seqp = seqp->ccid2s_next;
                }
@@ -473,7 +473,7 @@ static inline void ccid2_new_ack(struct sock *sk,
                /* first measurement */
                if (hctx->ccid2hctx_srtt == -1) {
                        ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
-                                      r, jiffies,
+                                      r, jiffies,
                                       (unsigned long long)seqp->ccid2s_seq);
                        ccid2_change_srtt(hctx, r);
                        hctx->ccid2hctx_rttvar = r >> 1;
@@ -518,8 +518,8 @@ static inline void ccid2_new_ack(struct sock *sk,
                hctx->ccid2hctx_lastrtt = jiffies;
 
                ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
-                              hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
-                              hctx->ccid2hctx_rto, HZ, r);
+                              hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
+                              hctx->ccid2hctx_rto, HZ, r);
                hctx->ccid2hctx_sent = 0;
        }
 
@@ -667,9 +667,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                                /* new packet received or marked */
                                if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
                                    !seqp->ccid2s_acked) {
-                                       if (state ==
+                                       if (state ==
                                            DCCP_ACKVEC_STATE_ECN_MARKED) {
-                                               ccid2_congestion_event(hctx,
+                                               ccid2_congestion_event(hctx,
                                                                       seqp);
                                        } else
                                                ccid2_new_ack(sk, seqp,
index cf8c07b..fa6b753 100644 (file)
 #include "lib/tfrc.h"
 #include "ccid3.h"
 
-/*
- * Reason for maths here is to avoid 32 bit overflow when a is big.
- * With this we get close to the limit.
- */
-static u32 usecs_div(const u32 a, const u32 b)
-{
-       const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
-                       a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
-                       a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
-                       a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
-                       a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
-                       a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
-                       a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
-                       a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
-                                                                100000;
-       const u32 tmp = a * (USEC_PER_SEC / div);
-       return (b >= 2 * div) ? tmp / (b / div) : tmp;
-}
-
-
-
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 static int ccid3_debug;
 #define ccid3_pr_debug(format, a...)   DCCP_PR_DEBUG(ccid3_debug, format, ##a)
@@ -108,8 +87,9 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
 {
        timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
 
-       /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
-       hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
+       /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
+       hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s,
+                                          hctx->ccid3hctx_x >> 6);
 
        /* Update nominal send time with regard to the new t_ipi */
        timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
@@ -128,40 +108,44 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
  *          X = max(min(2 * X, 2 * X_recv), s / R);
  *          tld = now;
  *
+ * Note: X and X_recv are both stored in units of 64 * bytes/second, to support
+ *       fine-grained resolution of sending rates. This requires scaling by 2^6
+ *       throughout the code. Only X_calc is unscaled (in bytes/second).
+ *
  * If X has changed, we also update the scheduled send time t_now,
  * the inter-packet interval t_ipi, and the delta value.
- */ 
+ */
 static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
 
 {
        struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-       const __u32 old_x = hctx->ccid3hctx_x;
+       const  __u64 old_x = hctx->ccid3hctx_x;
 
        if (hctx->ccid3hctx_p > 0) {
-               hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
-                                                    hctx->ccid3hctx_rtt,
-                                                    hctx->ccid3hctx_p);
-               hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
-                                                  hctx->ccid3hctx_x_recv * 2),
-                                              hctx->ccid3hctx_s / TFRC_T_MBI);
-
-       } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
-                                                         hctx->ccid3hctx_rtt) {
-               hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
-                                           hctx->ccid3hctx_x      ) * 2,
-                                       usecs_div(hctx->ccid3hctx_s,
-                                                 hctx->ccid3hctx_rtt)   );
+
+               hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6,
+                                       hctx->ccid3hctx_x_recv * 2);
+               hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,
+                                       (((__u64)hctx->ccid3hctx_s) << 6) /
+                                                               TFRC_T_MBI);
+
+       } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) -
+                       (suseconds_t)hctx->ccid3hctx_rtt >= 0) {
+
+               hctx->ccid3hctx_x =
+                       max(2 * min(hctx->ccid3hctx_x, hctx->ccid3hctx_x_recv),
+                           scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+                                      hctx->ccid3hctx_rtt));
                hctx->ccid3hctx_t_ld = *now;
-       } else
-               ccid3_pr_debug("Not changing X\n");
+       }
 
        if (hctx->ccid3hctx_x != old_x)
                ccid3_update_send_time(hctx);
 }
 
 /*
- *     Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
- *     @len: DCCP packet payload size in bytes
+ *     Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
+ *     @len: DCCP packet payload size in bytes
  */
 static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
 {
@@ -178,6 +162,33 @@ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
         */
 }
 
+/*
+ *     Update Window Counter using the algorithm from [RFC 4342, 8.1].
+ *     The algorithm is not applicable if RTT < 4 microseconds.
+ */
+static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
+                                               struct timeval *now)
+{
+       suseconds_t delta;
+       u32 quarter_rtts;
+
+       if (unlikely(hctx->ccid3hctx_rtt < 4))  /* avoid divide-by-zero */
+               return;
+
+       delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
+       DCCP_BUG_ON(delta < 0);
+
+       quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+
+       if (quarter_rtts > 0) {
+               hctx->ccid3hctx_t_last_win_count = *now;
+               hctx->ccid3hctx_last_win_count  += min_t(u32, quarter_rtts, 5);
+               hctx->ccid3hctx_last_win_count  &= 0xF;         /* mod 16 */
+
+               ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
+       }
+}
+
 static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
 {
        struct sock *sk = (struct sock *)data;
@@ -191,20 +202,20 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
                goto restart_timer;
        }
 
-       ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
+       ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,
                       ccid3_tx_state_name(hctx->ccid3hctx_state));
-       
+
        switch (hctx->ccid3hctx_state) {
        case TFRC_SSTATE_NO_FBACK:
                /* RFC 3448, 4.4: Halve send rate directly */
-               hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
-                                              hctx->ccid3hctx_s / TFRC_T_MBI);
+               hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,
+                                       (((__u64)hctx->ccid3hctx_s) << 6) /
+                                                                   TFRC_T_MBI);
 
-               ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
-                              "bytes/s\n",
-                              dccp_role(sk), sk,
+               ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
+                              "bytes/s\n", dccp_role(sk), sk,
                               ccid3_tx_state_name(hctx->ccid3hctx_state),
-                              hctx->ccid3hctx_x);
+                              (unsigned)(hctx->ccid3hctx_x >> 6));
                /* The value of R is still undefined and so we can not recompute
                 * the timout value. Keep initial value as per [RFC 4342, 5]. */
                t_nfb = TFRC_INITIAL_TIMEOUT;
@@ -213,34 +224,46 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
        case TFRC_SSTATE_FBACK:
                /*
                 * Check if IDLE since last timeout and recv rate is less than
-                * 4 packets per RTT
+                * 4 packets (in units of 64*bytes/sec) per RTT
                 */
                if (!hctx->ccid3hctx_idle ||
-                   (hctx->ccid3hctx_x_recv >=
-                    4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
+                   (hctx->ccid3hctx_x_recv >= 4 *
+                    scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+                               hctx->ccid3hctx_rtt))) {
                        struct timeval now;
 
-                       ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
+                       ccid3_pr_debug("%s(%p, state=%s), not idle\n",
                                       dccp_role(sk), sk,
-                                      ccid3_tx_state_name(hctx->ccid3hctx_state));
-                       /* Halve sending rate */
+                                  ccid3_tx_state_name(hctx->ccid3hctx_state));
 
-                       /*  If (p == 0 || X_calc > 2 * X_recv)
+                       /*
+                        *  Modify the cached value of X_recv [RFC 3448, 4.4]
+                        *
+                        *  If (p == 0 || X_calc > 2 * X_recv)
                         *    X_recv = max(X_recv / 2, s / (2 * t_mbi));
                         *  Else
                         *    X_recv = X_calc / 4;
+                        *
+                        *  Note that X_recv is scaled by 2^6 while X_calc is not
                         */
                        BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);
 
                        if (hctx->ccid3hctx_p  == 0 ||
-                           hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
-                               hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
-                                                                   hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
-                       else
-                               hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
-
-                       /* Update sending rate */
-                       dccp_timestamp(sk, &now);
+                           (hctx->ccid3hctx_x_calc >
+                            (hctx->ccid3hctx_x_recv >> 5))) {
+
+                               hctx->ccid3hctx_x_recv =
+                                       max(hctx->ccid3hctx_x_recv / 2,
+                                           (((__u64)hctx->ccid3hctx_s) << 6) /
+                                                         (2 * TFRC_T_MBI));
+
+                               if (hctx->ccid3hctx_p == 0)
+                                       dccp_timestamp(sk, &now);
+                       } else {
+                               hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
+                               hctx->ccid3hctx_x_recv <<= 4;
+                       }
+                       /* Now recalculate X [RFC 3448, 4.3, step (4)] */
                        ccid3_hc_tx_update_x(sk, &now);
                }
                /*
@@ -251,7 +274,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
                t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
                break;
        case TFRC_SSTATE_NO_SENT:
-               DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
+               DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk);
                /* fall through */
        case TFRC_SSTATE_TERM:
                goto out;
@@ -277,9 +300,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-       struct dccp_tx_hist_entry *new_packet;
        struct timeval now;
-       long delay;
+       suseconds_t delay;
 
        BUG_ON(hctx == NULL);
 
@@ -291,34 +313,21 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
        if (unlikely(skb->len == 0))
                return -EBADMSG;
 
-       /* See if last packet allocated was not sent */
-       new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
-       if (new_packet == NULL || new_packet->dccphtx_sent) {
-               new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
-                                                   SLAB_ATOMIC);
-
-               if (unlikely(new_packet == NULL)) {
-                       DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
-                                 "send refused\n", dccp_role(sk), sk);
-                       return -ENOBUFS;
-               }
-
-               dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
-       }
-
        dccp_timestamp(sk, &now);
 
        switch (hctx->ccid3hctx_state) {
        case TFRC_SSTATE_NO_SENT:
                sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
-                              jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
+                              (jiffies +
+                               usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
                hctx->ccid3hctx_last_win_count   = 0;
                hctx->ccid3hctx_t_last_win_count = now;
                ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
 
-               /* Set initial sending rate to 1 packet per second */
+               /* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */
                ccid3_hc_tx_update_s(hctx, skb->len);
-               hctx->ccid3hctx_x     = hctx->ccid3hctx_s;
+               hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+               hctx->ccid3hctx_x <<= 6;
 
                /* First timeout, according to [RFC 3448, 4.2], is 1 second */
                hctx->ccid3hctx_t_ipi = USEC_PER_SEC;
@@ -332,77 +341,57 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
        case TFRC_SSTATE_FBACK:
                delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
                /*
-                *      Scheduling of packet transmissions [RFC 3448, 4.6]
+                *      Scheduling of packet transmissions [RFC 3448, 4.6]
                 *
                 * if (t_now > t_nom - delta)
                 *       // send the packet now
                 * else
                 *       // send the packet in (t_nom - t_now) milliseconds.
                 */
-               if (delay - (long)hctx->ccid3hctx_delta >= 0)
+               if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
                        return delay / 1000L;
+
+               ccid3_hc_tx_update_win_count(hctx, &now);
                break;
        case TFRC_SSTATE_TERM:
-               DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+               DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
                return -EINVAL;
        }
 
        /* prepare to send now (add options etc.) */
        dp->dccps_hc_tx_insert_options = 1;
-       new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
-                                   hctx->ccid3hctx_last_win_count;
+       DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
+
+       /* set the nominal send time for the next following packet */
        timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
 
        return 0;
 }
 
-static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
+                                   unsigned int len)
 {
-       const struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        struct timeval now;
-       unsigned long quarter_rtt;
        struct dccp_tx_hist_entry *packet;
 
        BUG_ON(hctx == NULL);
 
-       dccp_timestamp(sk, &now);
-
        ccid3_hc_tx_update_s(hctx, len);
 
-       packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+       packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
        if (unlikely(packet == NULL)) {
-               DCCP_WARN("packet doesn't exist in history!\n");
-               return;
-       }
-       if (unlikely(packet->dccphtx_sent)) {
-               DCCP_WARN("no unsent packet in history!\n");
+               DCCP_CRIT("packet history - out of memory!");
                return;
        }
-       packet->dccphtx_tstamp = now;
-       packet->dccphtx_seqno  = dp->dccps_gss;
-       /*
-        * Check if win_count have changed
-        * Algorithm in "8.1. Window Counter Value" in RFC 4342.
-        */
-       quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
-       if (likely(hctx->ccid3hctx_rtt > 8))
-               quarter_rtt /= hctx->ccid3hctx_rtt / 4;
-
-       if (quarter_rtt > 0) {
-               hctx->ccid3hctx_t_last_win_count = now;
-               hctx->ccid3hctx_last_win_count   = (hctx->ccid3hctx_last_win_count +
-                                                   min_t(unsigned long, quarter_rtt, 5)) % 16;
-               ccid3_pr_debug("%s, sk=%p, window changed from "
-                              "%u to %u!\n",
-                              dccp_role(sk), sk,
-                              packet->dccphtx_ccval,
-                              hctx->ccid3hctx_last_win_count);
-       }
+       dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);
 
-       hctx->ccid3hctx_idle = 0;
-       packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
-       packet->dccphtx_sent = 1;
+       dccp_timestamp(sk, &now);
+       packet->dccphtx_tstamp = now;
+       packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;
+       packet->dccphtx_rtt    = hctx->ccid3hctx_rtt;
+       packet->dccphtx_sent   = 1;
+       hctx->ccid3hctx_idle   = 0;
 }
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -414,7 +403,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
        struct timeval now;
        unsigned long t_nfb;
        u32 pinv;
-       long r_sample, t_elapsed;
+       suseconds_t r_sample, t_elapsed;
 
        BUG_ON(hctx == NULL);
 
@@ -430,44 +419,44 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
        case TFRC_SSTATE_FBACK:
                /* get packet from history to look up t_recvdata */
                packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
-                                                DCCP_SKB_CB(skb)->dccpd_ack_seq);
+                                             DCCP_SKB_CB(skb)->dccpd_ack_seq);
                if (unlikely(packet == NULL)) {
                        DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "
                                  "in history!\n",  dccp_role(sk), sk,
                            (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
-                                 dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+                               dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
                        return;
                }
 
-               /* Update receive rate */
+               /* Update receive rate in units of 64 * bytes/second */
                hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;
+               hctx->ccid3hctx_x_recv <<= 6;
 
                /* Update loss event rate */
                pinv = opt_recv->ccid3or_loss_event_rate;
-               if (pinv == ~0U || pinv == 0)
+               if (pinv == ~0U || pinv == 0)          /* see RFC 4342, 8.5   */
                        hctx->ccid3hctx_p = 0;
-               else
-                       hctx->ccid3hctx_p = 1000000 / pinv;
+               else                                   /* can not exceed 100% */
+                       hctx->ccid3hctx_p = 1000000 / pinv;
 
                dccp_timestamp(sk, &now);
 
                /*
                 * Calculate new round trip sample as per [RFC 3448, 4.3] by
-                *      R_sample  =  (now - t_recvdata) - t_elapsed
+                *      R_sample  =  (now - t_recvdata) - t_elapsed
                 */
                r_sample  = timeval_delta(&now, &packet->dccphtx_tstamp);
                t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
 
-               if (unlikely(r_sample <= 0)) {
-                       DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample);
-                       r_sample = 0;
-               } else if (unlikely(r_sample <= t_elapsed))
-                       DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n",
-                                 r_sample, t_elapsed);
+               DCCP_BUG_ON(r_sample < 0);
+               if (unlikely(r_sample <= t_elapsed))
+                       DCCP_WARN("WARNING: r_sample=%dus <= t_elapsed=%dus\n",
+                                 (int)r_sample, (int)t_elapsed);
                else
                        r_sample -= t_elapsed;
+               CCID3_RTT_SANITY_CHECK(r_sample);
 
-               /* Update RTT estimate by 
+               /* Update RTT estimate by
                 * If (No feedback recv)
                 *    R = R_sample;
                 * Else
@@ -476,34 +465,45 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                 * q is a constant, RFC 3448 recomments 0.9
                 */
                if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
-                       /* Use Larger Initial Windows [RFC 4342, sec. 5]
-                        * We deviate in that we use `s' instead of `MSS'. */
-                       u16 w_init = max(    4 * hctx->ccid3hctx_s,
-                                        max(2 * hctx->ccid3hctx_s, 4380));
+                       /*
+                        * Larger Initial Windows [RFC 4342, sec. 5]
+                        * We deviate in that we use `s' instead of `MSS'.
+                        */
+                       __u64 w_init = min(4 * hctx->ccid3hctx_s,
+                                          max(2 * hctx->ccid3hctx_s, 4380));
                        hctx->ccid3hctx_rtt  = r_sample;
-                       hctx->ccid3hctx_x    = usecs_div(w_init, r_sample);
+                       hctx->ccid3hctx_x    = scaled_div(w_init << 6, r_sample);
                        hctx->ccid3hctx_t_ld = now;
 
                        ccid3_update_send_time(hctx);
 
-                       ccid3_pr_debug("%s(%p), s=%u, w_init=%u, "
-                                      "R_sample=%ldus, X=%u\n", dccp_role(sk),
-                                      sk, hctx->ccid3hctx_s, w_init, r_sample,
-                                      hctx->ccid3hctx_x);
+                       ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, "
+                                      "R_sample=%dus, X=%u\n", dccp_role(sk),
+                                      sk, hctx->ccid3hctx_s, w_init,
+                                      (int)r_sample,
+                                      (unsigned)(hctx->ccid3hctx_x >> 6));
 
                        ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
                } else {
                        hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +
-                                                  (u32)r_sample        ) / 10;
-
+                                                  (u32)r_sample) / 10;
+
+                       /* Update sending rate (step 4 of [RFC 3448, 4.3]) */
+                       if (hctx->ccid3hctx_p > 0)
+                               hctx->ccid3hctx_x_calc =
+                                       tfrc_calc_x(hctx->ccid3hctx_s,
+                                                   hctx->ccid3hctx_rtt,
+                                                   hctx->ccid3hctx_p);
                        ccid3_hc_tx_update_x(sk, &now);
 
-                       ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, "
-                                      "p=%u, X_calc=%u, X=%u\n", dccp_role(sk),
-                                      sk, hctx->ccid3hctx_rtt, r_sample,
+                       ccid3_pr_debug("%s(%p), RTT=%uus (sample=%dus), s=%u, "
+                                      "p=%u, X_calc=%u, X_recv=%u, X=%u\n",
+                                      dccp_role(sk),
+                                      sk, hctx->ccid3hctx_rtt, (int)r_sample,
                                       hctx->ccid3hctx_s, hctx->ccid3hctx_p,
                                       hctx->ccid3hctx_x_calc,
-                                      hctx->ccid3hctx_x);
+                                      (unsigned)(hctx->ccid3hctx_x_recv >> 6),
+                                      (unsigned)(hctx->ccid3hctx_x >> 6));
                }
 
                /* unschedule no feedback timer */
@@ -513,57 +513,48 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                dccp_tx_hist_purge_older(ccid3_tx_hist,
                                         &hctx->ccid3hctx_hist, packet);
                /*
-                * As we have calculated new ipi, delta, t_nom it is possible that
-                * we now can send a packet, so wake up dccp_wait_for_ccid
+                * As we have calculated new ipi, delta, t_nom it is possible
+                * that we now can send a packet, so wake up dccp_wait_for_ccid
                 */
                sk->sk_write_space(sk);
 
                /*
                 * Update timeout interval for the nofeedback timer.
                 * We use a configuration option to increase the lower bound.
-                * This can help avoid triggering the nofeedback timer too often
-                * ('spinning') on LANs with small RTTs.
+                * This can help avoid triggering the nofeedback timer too
+                * often ('spinning') on LANs with small RTTs.
                 */
                hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
                                                   CONFIG_IP_DCCP_CCID3_RTO *
-                                                  (USEC_PER_SEC/1000)       );
+                                                  (USEC_PER_SEC/1000));
                /*
                 * Schedule no feedback timer to expire in
                 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
                 */
                t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
-                       
-               ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
+
+               ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "
                               "expire in %lu jiffies (%luus)\n",
-                              dccp_role(sk), sk,
-                              usecs_to_jiffies(t_nfb), t_nfb);
+                              dccp_role(sk),
+                              sk, usecs_to_jiffies(t_nfb), t_nfb);
 
-               sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
+               sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
                                   jiffies + usecs_to_jiffies(t_nfb));
 
                /* set idle flag */
-               hctx->ccid3hctx_idle = 1;   
+               hctx->ccid3hctx_idle = 1;
                break;
        case TFRC_SSTATE_NO_SENT:
-               if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT)
-                       DCCP_WARN("Illegal ACK received - no packet sent\n");
+               /*
+                * XXX when implementing bidirectional rx/tx check this again
+                */
+               DCCP_WARN("Illegal ACK received - no packet sent\n");
                /* fall through */
        case TFRC_SSTATE_TERM:          /* ignore feedback when closing */
                break;
        }
 }
 
-static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
-{
-       const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-
-       BUG_ON(hctx == NULL);
-
-       if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
-               DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
-       return 0;
-}
-
 static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
                                     unsigned char len, u16 idx,
                                     unsigned char *value)
@@ -588,13 +579,14 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
        switch (option) {
        case TFRC_OPT_LOSS_EVENT_RATE:
                if (unlikely(len != 4)) {
-                       DCCP_WARN("%s, sk=%p, invalid len %d "
+                       DCCP_WARN("%s(%p), invalid len %d "
                                  "for TFRC_OPT_LOSS_EVENT_RATE\n",
                                  dccp_role(sk), sk, len);
                        rc = -EINVAL;
                } else {
-                       opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
-                       ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
+                       opt_recv->ccid3or_loss_event_rate =
+                                               ntohl(*(__be32 *)value);
+                       ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
                                       dccp_role(sk), sk,
                                       opt_recv->ccid3or_loss_event_rate);
                }
@@ -602,20 +594,21 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
        case TFRC_OPT_LOSS_INTERVALS:
                opt_recv->ccid3or_loss_intervals_idx = idx;
                opt_recv->ccid3or_loss_intervals_len = len;
-               ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
+               ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
                               dccp_role(sk), sk,
                               opt_recv->ccid3or_loss_intervals_idx,
                               opt_recv->ccid3or_loss_intervals_len);
                break;
        case TFRC_OPT_RECEIVE_RATE:
                if (unlikely(len != 4)) {
-                       DCCP_WARN("%s, sk=%p, invalid len %d "
+                       DCCP_WARN("%s(%p), invalid len %d "
                                  "for TFRC_OPT_RECEIVE_RATE\n",
                                  dccp_role(sk), sk, len);
                        rc = -EINVAL;
                } else {
-                       opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
-                       ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
+                       opt_recv->ccid3or_receive_rate =
+                                               ntohl(*(__be32 *)value);
+                       ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
                                       dccp_role(sk), sk,
                                       opt_recv->ccid3or_receive_rate);
                }
@@ -630,10 +623,12 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
        struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
 
        hctx->ccid3hctx_s     = 0;
+       hctx->ccid3hctx_rtt   = 0;
        hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
        INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
 
-       hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
+       hctx->ccid3hctx_no_feedback_timer.function =
+                               ccid3_hc_tx_no_feedback_timer;
        hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
        init_timer(&hctx->ccid3hctx_no_feedback_timer);
 
@@ -698,8 +693,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        struct dccp_sock *dp = dccp_sk(sk);
        struct dccp_rx_hist_entry *packet;
        struct timeval now;
+       suseconds_t delta;
 
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+       ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
 
        dccp_timestamp(sk, &now);
 
@@ -707,21 +703,21 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        case TFRC_RSTATE_NO_DATA:
                hcrx->ccid3hcrx_x_recv = 0;
                break;
-       case TFRC_RSTATE_DATA: {
-               const u32 delta = timeval_delta(&now,
-                                       &hcrx->ccid3hcrx_tstamp_last_feedback);
-               hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
-                                                  delta);
-       }
+       case TFRC_RSTATE_DATA:
+               delta = timeval_delta(&now,
+                                     &hcrx->ccid3hcrx_tstamp_last_feedback);
+               DCCP_BUG_ON(delta < 0);
+               hcrx->ccid3hcrx_x_recv =
+                       scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
                break;
        case TFRC_RSTATE_TERM:
-               DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+               DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
                return;
        }
 
        packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
        if (unlikely(packet == NULL)) {
-               DCCP_WARN("%s, sk=%p, no data packet in history!\n",
+               DCCP_WARN("%s(%p), no data packet in history!\n",
                          dccp_role(sk), sk);
                return;
        }
@@ -730,13 +726,19 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
        hcrx->ccid3hcrx_bytes_recv           = 0;
 
-       /* Convert to multiples of 10us */
-       hcrx->ccid3hcrx_elapsed_time =
-                       timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
+       /* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
+       delta = timeval_delta(&now, &packet->dccphrx_tstamp);
+       DCCP_BUG_ON(delta < 0);
+       hcrx->ccid3hcrx_elapsed_time = delta / 10;
+
        if (hcrx->ccid3hcrx_p == 0)
-               hcrx->ccid3hcrx_pinv = ~0;
-       else
+               hcrx->ccid3hcrx_pinv = ~0U;     /* see RFC 4342, 8.5 */
+       else if (hcrx->ccid3hcrx_p > 1000000) {
+               DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);
+               hcrx->ccid3hcrx_pinv = 1;       /* use 100% in this case */
+       } else
                hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+
        dp->dccps_hc_rx_insert_options = 1;
        dccp_send_ack(sk);
 }
@@ -764,9 +766,9 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
                                             hcrx->ccid3hcrx_elapsed_time)) ||
            dccp_insert_option_timestamp(sk, skb) ||
            dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
-                              &pinv, sizeof(pinv)) ||
+                              &pinv, sizeof(pinv)) ||
            dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
-                              &x_recv, sizeof(x_recv)))
+                              &x_recv, sizeof(x_recv)))
                return -1;
 
        return 0;
@@ -780,12 +782,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
 {
        struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
-       u32 rtt, delta, x_recv, fval, p, tmp2;
+       u32 x_recv, p;
+       suseconds_t rtt, delta;
        struct timeval tstamp = { 0, };
        int interval = 0;
        int win_count = 0;
        int step = 0;
-       u64 tmp1;
+       u64 fval;
 
        list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
                                 dccphrx_node) {
@@ -810,13 +813,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
        }
 
        if (unlikely(step == 0)) {
-               DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
+               DCCP_WARN("%s(%p), packet history has no data packets!\n",
                          dccp_role(sk), sk);
                return ~0;
        }
 
        if (unlikely(interval == 0)) {
-               DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
+               DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
                          "Defaulting to 1\n", dccp_role(sk), sk);
                interval = 1;
        }
@@ -825,41 +828,51 @@ found:
                DCCP_CRIT("tail is null\n");
                return ~0;
        }
-       rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
-       ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
-                      dccp_role(sk), sk, rtt);
 
-       if (rtt == 0) {
-               DCCP_WARN("RTT==0, setting to 1\n");
-               rtt = 1;
+       delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+       DCCP_BUG_ON(delta < 0);
+
+       rtt = delta * 4 / interval;
+       ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
+                      dccp_role(sk), sk, (int)rtt);
+
+       /*
+        * Determine the length of the first loss interval via inverse lookup.
+        * Assume that X_recv can be computed by the throughput equation
+        *                  s
+        *      X_recv = --------
+        *               R * fval
+        * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+        */
+       if (rtt == 0) {                 /* would result in divide-by-zero */
+               DCCP_WARN("RTT==0, returning 1/p = 1\n");
+               return 1000000;
        }
 
        dccp_timestamp(sk, &tstamp);
        delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
-       x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
-
-       if (x_recv == 0)
-               x_recv = hcrx->ccid3hcrx_x_recv;
-
-       tmp1 = (u64)x_recv * (u64)rtt;
-       do_div(tmp1,10000000);
-       tmp2 = (u32)tmp1;
-
-       if (!tmp2) {
-               DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
-               return ~0;
+       DCCP_BUG_ON(delta <= 0);
+
+       x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
+       if (x_recv == 0) {              /* would also trigger divide-by-zero */
+               DCCP_WARN("X_recv==0\n");
+               if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
+                       DCCP_BUG("stored value of X_recv is zero");
+                       return 1000000;
+               }
        }
 
-       fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
-       /* do not alter order above or you will get overflow on 32 bit */
+       fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
+       fval = scaled_div32(fval, x_recv);
        p = tfrc_calc_x_reverse_lookup(fval);
-       ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
+
+       ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
                       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
 
        if (p == 0)
                return ~0;
        else
-               return 1000000 / p; 
+               return 1000000 / p;
 }
 
 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
@@ -889,7 +902,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
                /* new loss event detected */
                /* calculate last interval length */
                seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
-               entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC);
+               entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
 
                if (entry == NULL) {
                        DCCP_BUG("out of memory - can not allocate entry");
@@ -913,7 +926,8 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
                                     struct dccp_rx_hist_entry *packet)
 {
        struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-       struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+       struct dccp_rx_hist_entry *rx_hist =
+                               dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
        u64 seqno = packet->dccphrx_seqno;
        u64 tmp_seqno;
        int loss = 0;
@@ -941,7 +955,7 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
                dccp_inc_seqno(&tmp_seqno);
                while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
                   tmp_seqno, &ccval)) {
-                       hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+                       hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
                        hcrx->ccid3hcrx_ccval_nonloss = ccval;
                        dccp_inc_seqno(&tmp_seqno);
                }
@@ -967,7 +981,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        const struct dccp_options_received *opt_recv;
        struct dccp_rx_hist_entry *packet;
        struct timeval now;
-       u32 p_prev, rtt_prev, r_sample, t_elapsed;
+       u32 p_prev, rtt_prev;
+       suseconds_t r_sample, t_elapsed;
        int loss, payload_size;
 
        BUG_ON(hcrx == NULL);
@@ -987,11 +1002,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                r_sample = timeval_usecs(&now);
                t_elapsed = opt_recv->dccpor_elapsed_time * 10;
 
+               DCCP_BUG_ON(r_sample < 0);
                if (unlikely(r_sample <= t_elapsed))
-                       DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
+                       DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
                                  r_sample, t_elapsed);
                else
                        r_sample -= t_elapsed;
+               CCID3_RTT_SANITY_CHECK(r_sample);
 
                if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
                        hcrx->ccid3hcrx_rtt = r_sample;
@@ -1000,8 +1017,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                                              r_sample / 10;
 
                if (rtt_prev != hcrx->ccid3hcrx_rtt)
-                       ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
-                                      dccp_role(sk), hcrx->ccid3hcrx_rtt,
+                       ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
+                                      dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
                                       opt_recv->dccpor_elapsed_time);
                break;
        case DCCP_PKT_DATA:
@@ -1011,9 +1028,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        }
 
        packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
-                                       skb, SLAB_ATOMIC);
+                                       skb, GFP_ATOMIC);
        if (unlikely(packet == NULL)) {
-               DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
+               DCCP_WARN("%s(%p), Not enough mem to add rx packet "
                          "to history, consider it lost!\n", dccp_role(sk), sk);
                return;
        }
@@ -1028,9 +1045,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 
        switch (hcrx->ccid3hcrx_state) {
        case TFRC_RSTATE_NO_DATA:
-               ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
-                              "feedback\n",
-                              dccp_role(sk), sk,
+               ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial "
+                              "feedback\n", dccp_role(sk), sk,
                               dccp_state_name(sk->sk_state), skb);
                ccid3_hc_rx_send_feedback(sk);
                ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
@@ -1041,19 +1057,19 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                        break;
 
                dccp_timestamp(sk, &now);
-               if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
-                   hcrx->ccid3hcrx_rtt) {
+               if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) -
+                    (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) {
                        hcrx->ccid3hcrx_tstamp_last_ack = now;
                        ccid3_hc_rx_send_feedback(sk);
                }
                return;
        case TFRC_RSTATE_TERM:
-               DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+               DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
                return;
        }
 
        /* Dealing with packet loss */
-       ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+       ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
                       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
 
        p_prev = hcrx->ccid3hcrx_p;
@@ -1078,7 +1094,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
 {
        struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
 
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+       ccid3_pr_debug("entry\n");
 
        hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
        INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
@@ -1086,7 +1102,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
        dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
        hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
        hcrx->ccid3hcrx_s   = 0;
-       hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
+       hcrx->ccid3hcrx_rtt = 0;
        return 0;
 }
 
@@ -1115,9 +1131,9 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 
        BUG_ON(hcrx == NULL);
 
-       info->tcpi_ca_state     = hcrx->ccid3hcrx_state;
-       info->tcpi_options      |= TCPI_OPT_TIMESTAMPS;
-       info->tcpi_rcv_rtt      = hcrx->ccid3hcrx_rtt;
+       info->tcpi_ca_state = hcrx->ccid3hcrx_state;
+       info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;
+       info->tcpi_rcv_rtt  = hcrx->ccid3hcrx_rtt;
 }
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1198,7 +1214,6 @@ static struct ccid_operations ccid3 = {
        .ccid_hc_tx_send_packet    = ccid3_hc_tx_send_packet,
        .ccid_hc_tx_packet_sent    = ccid3_hc_tx_packet_sent,
        .ccid_hc_tx_packet_recv    = ccid3_hc_tx_packet_recv,
-       .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
        .ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,
        .ccid_hc_rx_obj_size       = sizeof(struct ccid3_hc_rx_sock),
        .ccid_hc_rx_init           = ccid3_hc_rx_init,
@@ -1210,7 +1225,7 @@ static struct ccid_operations ccid3 = {
        .ccid_hc_rx_getsockopt     = ccid3_hc_rx_getsockopt,
        .ccid_hc_tx_getsockopt     = ccid3_hc_tx_getsockopt,
 };
+
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 module_param(ccid3_debug, int, 0444);
 MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
@@ -1233,7 +1248,7 @@ static __init int ccid3_module_init(void)
                goto out_free_tx;
 
        rc = ccid_register(&ccid3);
-       if (rc != 0) 
+       if (rc != 0)
                goto out_free_loss_interval_history;
 out:
        return rc;
index 07596d7..15776a8 100644 (file)
 /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
 #define TFRC_T_MBI                64
 
+/* What we think is a reasonable upper limit on RTT values */
+#define CCID3_SANE_RTT_MAX        ((suseconds_t)(4 * USEC_PER_SEC))
+
+#define CCID3_RTT_SANITY_CHECK(rtt)                    do {               \
+               if (rtt > CCID3_SANE_RTT_MAX) {                            \
+                       DCCP_CRIT("RTT (%d) too large, substituting %d",   \
+                                 (int)rtt, (int)CCID3_SANE_RTT_MAX);      \
+                       rtt = CCID3_SANE_RTT_MAX;                          \
+               }                                       } while (0)
+
 enum ccid3_options {
        TFRC_OPT_LOSS_EVENT_RATE = 192,
        TFRC_OPT_LOSS_INTERVALS  = 193,
@@ -67,7 +77,7 @@ struct ccid3_options_received {
 
 /* TFRC sender states */
 enum ccid3_hc_tx_states {
-               TFRC_SSTATE_NO_SENT = 1,
+       TFRC_SSTATE_NO_SENT = 1,
        TFRC_SSTATE_NO_FBACK,
        TFRC_SSTATE_FBACK,
        TFRC_SSTATE_TERM,
@@ -75,23 +85,23 @@ enum ccid3_hc_tx_states {
 
 /** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
  *
- * @ccid3hctx_x - Current sending rate
- * @ccid3hctx_x_recv - Receive rate
- * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1)
+ * @ccid3hctx_x - Current sending rate in 64 * bytes per second
+ * @ccid3hctx_x_recv - Receive rate    in 64 * bytes per second
+ * @ccid3hctx_x_calc - Calculated rate in bytes per second
  * @ccid3hctx_rtt - Estimate of current round trip time in usecs
  * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
- * @ccid3hctx_s - Packet size
- * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1)
- * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6)
+ * @ccid3hctx_s - Packet size in bytes
+ * @ccid3hctx_t_rto - Nofeedback Timer setting in usecs
+ * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs
  * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states
  * @ccid3hctx_last_win_count - Last window counter sent
  * @ccid3hctx_t_last_win_count - Timestamp of earliest packet
- *                              with last_win_count value sent
+ *                              with last_win_count value sent
  * @ccid3hctx_no_feedback_timer - Handle to no feedback timer
  * @ccid3hctx_idle - Flag indicating that sender is idling
  * @ccid3hctx_t_ld - Time last doubled during slow start
  * @ccid3hctx_t_nom - Nominal send time of next packet
- * @ccid3hctx_delta - Send timer delta
+ * @ccid3hctx_delta - Send timer delta (RFC 3448, 4.6) in usecs
  * @ccid3hctx_hist - Packet history
  * @ccid3hctx_options_received - Parsed set of retrieved options
  */
@@ -105,7 +115,7 @@ struct ccid3_hc_tx_sock {
 #define ccid3hctx_t_rto                        ccid3hctx_tfrc.tfrctx_rto
 #define ccid3hctx_t_ipi                        ccid3hctx_tfrc.tfrctx_ipi
        u16                             ccid3hctx_s;
-       enum ccid3_hc_tx_states         ccid3hctx_state:8;
+       enum ccid3_hc_tx_states         ccid3hctx_state:8;
        u8                              ccid3hctx_last_win_count;
        u8                              ccid3hctx_idle;
        struct timeval                  ccid3hctx_t_last_win_count;
@@ -119,7 +129,7 @@ struct ccid3_hc_tx_sock {
 
 /* TFRC receiver states */
 enum ccid3_hc_rx_states {
-               TFRC_RSTATE_NO_DATA = 1,
+       TFRC_RSTATE_NO_DATA = 1,
        TFRC_RSTATE_DATA,
        TFRC_RSTATE_TERM    = 127,
 };
@@ -147,18 +157,18 @@ struct ccid3_hc_rx_sock {
 #define ccid3hcrx_x_recv               ccid3hcrx_tfrc.tfrcrx_x_recv
 #define ccid3hcrx_rtt                  ccid3hcrx_tfrc.tfrcrx_rtt
 #define ccid3hcrx_p                    ccid3hcrx_tfrc.tfrcrx_p
-       u64                             ccid3hcrx_seqno_nonloss:48,
+       u64                             ccid3hcrx_seqno_nonloss:48,
                                        ccid3hcrx_ccval_nonloss:4,
                                        ccid3hcrx_ccval_last_counter:4;
        enum ccid3_hc_rx_states         ccid3hcrx_state:8;
-       u32                             ccid3hcrx_bytes_recv;
-       struct timeval                  ccid3hcrx_tstamp_last_feedback;
-       struct timeval                  ccid3hcrx_tstamp_last_ack;
+       u32                             ccid3hcrx_bytes_recv;
+       struct timeval                  ccid3hcrx_tstamp_last_feedback;
+       struct timeval                  ccid3hcrx_tstamp_last_ack;
        struct list_head                ccid3hcrx_hist;
        struct list_head                ccid3hcrx_li_hist;
-       u16                             ccid3hcrx_s;
-       u32                             ccid3hcrx_pinv;
-       u32                             ccid3hcrx_elapsed_time;
+       u16                             ccid3hcrx_s;
+       u32                             ccid3hcrx_pinv;
+       u32                             ccid3hcrx_elapsed_time;
 };
 
 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
index 48b9b93..0a0baef 100644 (file)
@@ -125,7 +125,7 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
        int i;
 
        for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
-               entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
+               entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
                if (entry == NULL) {
                        dccp_li_hist_purge(hist, list);
                        DCCP_BUG("loss interval list entry is NULL");
index 0ae85f0..eb25701 100644 (file)
@@ -20,7 +20,7 @@
 #define DCCP_LI_HIST_IVAL_F_LENGTH  8
 
 struct dccp_li_hist {
-       kmem_cache_t *dccplih_slab;
+       struct kmem_cache *dccplih_slab;
 };
 
 extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
index b876c9c..2e8ef42 100644 (file)
 
 #include <linux/module.h>
 #include <linux/string.h>
-
 #include "packet_history.h"
 
+/*
+ *     Transmitter History Routines
+ */
+struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
+{
+       struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+       static const char dccp_tx_hist_mask[] = "tx_hist_%s";
+       char *slab_name;
+
+       if (hist == NULL)
+               goto out;
+
+       slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
+                           GFP_ATOMIC);
+       if (slab_name == NULL)
+               goto out_free_hist;
+
+       sprintf(slab_name, dccp_tx_hist_mask, name);
+       hist->dccptxh_slab = kmem_cache_create(slab_name,
+                                            sizeof(struct dccp_tx_hist_entry),
+                                              0, SLAB_HWCACHE_ALIGN,
+                                              NULL, NULL);
+       if (hist->dccptxh_slab == NULL)
+               goto out_free_slab_name;
+out:
+       return hist;
+out_free_slab_name:
+       kfree(slab_name);
+out_free_hist:
+       kfree(hist);
+       hist = NULL;
+       goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
+
+void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
+{
+       const char* name = kmem_cache_name(hist->dccptxh_slab);
+
+       kmem_cache_destroy(hist->dccptxh_slab);
+       kfree(name);
+       kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
+
+struct dccp_tx_hist_entry *
+       dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
+{
+       struct dccp_tx_hist_entry *packet = NULL, *entry;
+
+       list_for_each_entry(entry, list, dccphtx_node)
+               if (entry->dccphtx_seqno == seq) {
+                       packet = entry;
+                       break;
+               }
+
+       return packet;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
+
+void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
+{
+       struct dccp_tx_hist_entry *entry, *next;
+
+       list_for_each_entry_safe(entry, next, list, dccphtx_node) {
+               list_del_init(&entry->dccphtx_node);
+               dccp_tx_hist_entry_delete(hist, entry);
+       }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
+
+void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+                             struct list_head *list,
+                             struct dccp_tx_hist_entry *packet)
+{
+       struct dccp_tx_hist_entry *next;
+
+       list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
+               list_del_init(&packet->dccphtx_node);
+               dccp_tx_hist_entry_delete(hist, packet);
+       }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
+
+/*
+ *     Receiver History Routines
+ */
 struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
 {
        struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -83,18 +174,24 @@ void dccp_rx_hist_delete(struct dccp_rx_hist *hist)
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
 
-void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
+int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+                           u8 *ccval)
 {
-       struct dccp_rx_hist_entry *entry, *next;
+       struct dccp_rx_hist_entry *packet = NULL, *entry;
 
-       list_for_each_entry_safe(entry, next, list, dccphrx_node) {
-               list_del_init(&entry->dccphrx_node);
-               kmem_cache_free(hist->dccprxh_slab, entry);
-       }
-}
+       list_for_each_entry(entry, list, dccphrx_node)
+               if (entry->dccphrx_seqno == seq) {
+                       packet = entry;
+                       break;
+               }
 
-EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
+       if (packet)
+               *ccval = packet->dccphrx_ccval;
 
+       return packet != NULL;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
 struct dccp_rx_hist_entry *
                dccp_rx_hist_find_data_packet(const struct list_head *list)
 {
@@ -184,110 +281,18 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
 
-struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
-{
-       struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
-       static const char dccp_tx_hist_mask[] = "tx_hist_%s";
-       char *slab_name;
-
-       if (hist == NULL)
-               goto out;
-
-       slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
-                           GFP_ATOMIC);
-       if (slab_name == NULL)
-               goto out_free_hist;
-
-       sprintf(slab_name, dccp_tx_hist_mask, name);
-       hist->dccptxh_slab = kmem_cache_create(slab_name,
-                                            sizeof(struct dccp_tx_hist_entry),
-                                              0, SLAB_HWCACHE_ALIGN,
-                                              NULL, NULL);
-       if (hist->dccptxh_slab == NULL)
-               goto out_free_slab_name;
-out:
-       return hist;
-out_free_slab_name:
-       kfree(slab_name);
-out_free_hist:
-       kfree(hist);
-       hist = NULL;
-       goto out;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
-
-void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
-{
-       const char* name = kmem_cache_name(hist->dccptxh_slab);
-
-       kmem_cache_destroy(hist->dccptxh_slab);
-       kfree(name);
-       kfree(hist);
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
-
-struct dccp_tx_hist_entry *
-       dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
-{
-       struct dccp_tx_hist_entry *packet = NULL, *entry;
-
-       list_for_each_entry(entry, list, dccphtx_node)
-               if (entry->dccphtx_seqno == seq) {
-                       packet = entry;
-                       break;
-               }
-
-       return packet;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
-
-int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
-   u8 *ccval)
-{
-       struct dccp_rx_hist_entry *packet = NULL, *entry;
-
-       list_for_each_entry(entry, list, dccphrx_node)
-               if (entry->dccphrx_seqno == seq) {
-                       packet = entry;
-                       break;
-               }
-
-       if (packet)
-               *ccval = packet->dccphrx_ccval;
-
-       return packet != NULL;
-}
-
-EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
-
-void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
-                             struct list_head *list,
-                             struct dccp_tx_hist_entry *packet)
+void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
 {
-       struct dccp_tx_hist_entry *next;
+       struct dccp_rx_hist_entry *entry, *next;
 
-       list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
-               list_del_init(&packet->dccphtx_node);
-               dccp_tx_hist_entry_delete(hist, packet);
+       list_for_each_entry_safe(entry, next, list, dccphrx_node) {
+               list_del_init(&entry->dccphrx_node);
+               kmem_cache_free(hist->dccprxh_slab, entry);
        }
 }
 
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
-
-void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
-{
-       struct dccp_tx_hist_entry *entry, *next;
-
-       list_for_each_entry_safe(entry, next, list, dccphtx_node) {
-               list_del_init(&entry->dccphtx_node);
-               dccp_tx_hist_entry_delete(hist, entry);
-       }
-}
+EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
 
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
 
 MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
              "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
index 067cf1c..1f960c1 100644 (file)
 #define TFRC_WIN_COUNT_PER_RTT  4
 #define TFRC_WIN_COUNT_LIMIT   16
 
+/*
+ *     Transmitter History data structures and declarations
+ */
 struct dccp_tx_hist_entry {
        struct list_head dccphtx_node;
        u64              dccphtx_seqno:48,
-                        dccphtx_ccval:4,
                         dccphtx_sent:1;
        u32              dccphtx_rtt;
        struct timeval   dccphtx_tstamp;
 };
 
-struct dccp_rx_hist_entry {
-       struct list_head dccphrx_node;
-       u64              dccphrx_seqno:48,
-                        dccphrx_ccval:4,
-                        dccphrx_type:4;
-       u32              dccphrx_ndp; /* In fact it is from 8 to 24 bits */
-       struct timeval   dccphrx_tstamp;
-};
-
 struct dccp_tx_hist {
-       kmem_cache_t *dccptxh_slab;
+       struct kmem_cache *dccptxh_slab;
 };
 
 extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name);
-extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
-
-struct dccp_rx_hist {
-       kmem_cache_t *dccprxh_slab;
-};
-
-extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
-extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
-extern struct dccp_rx_hist_entry *
-               dccp_rx_hist_find_data_packet(const struct list_head *list);
+extern void                dccp_tx_hist_delete(struct dccp_tx_hist *hist);
 
 static inline struct dccp_tx_hist_entry *
-               dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
-                                      const gfp_t prio)
+                       dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
+                                              const gfp_t prio)
 {
        struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab,
                                                            prio);
@@ -96,18 +80,20 @@ static inline struct dccp_tx_hist_entry *
        return entry;
 }
 
-static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
-                                            struct dccp_tx_hist_entry *entry)
+static inline struct dccp_tx_hist_entry *
+                       dccp_tx_hist_head(struct list_head *list)
 {
-       if (entry != NULL)
-               kmem_cache_free(hist->dccptxh_slab, entry);
+       struct dccp_tx_hist_entry *head = NULL;
+
+       if (!list_empty(list))
+               head = list_entry(list->next, struct dccp_tx_hist_entry,
+                                 dccphtx_node);
+       return head;
 }
 
 extern struct dccp_tx_hist_entry *
                        dccp_tx_hist_find_entry(const struct list_head *list,
                                                const u64 seq);
-extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
-   u8 *ccval);
 
 static inline void dccp_tx_hist_add_entry(struct list_head *list,
                                          struct dccp_tx_hist_entry *entry)
@@ -115,30 +101,45 @@ static inline void dccp_tx_hist_add_entry(struct list_head *list,
        list_add(&entry->dccphtx_node, list);
 }
 
+static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
+                                            struct dccp_tx_hist_entry *entry)
+{
+       if (entry != NULL)
+               kmem_cache_free(hist->dccptxh_slab, entry);
+}
+
+extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
+                              struct list_head *list);
+
 extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
                                     struct list_head *list,
                                     struct dccp_tx_hist_entry *next);
 
-extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
-                              struct list_head *list);
+/*
+ *     Receiver History data structures and declarations
+ */
+struct dccp_rx_hist_entry {
+       struct list_head dccphrx_node;
+       u64              dccphrx_seqno:48,
+                        dccphrx_ccval:4,
+                        dccphrx_type:4;
+       u32              dccphrx_ndp; /* In fact it is from 8 to 24 bits */
+       struct timeval   dccphrx_tstamp;
+};
 
-static inline struct dccp_tx_hist_entry *
-               dccp_tx_hist_head(struct list_head *list)
-{
-       struct dccp_tx_hist_entry *head = NULL;
+struct dccp_rx_hist {
+       struct kmem_cache *dccprxh_slab;
+};
 
-       if (!list_empty(list))
-               head = list_entry(list->next, struct dccp_tx_hist_entry,
-                                 dccphtx_node);
-       return head;
-}
+extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
+extern void            dccp_rx_hist_delete(struct dccp_rx_hist *hist);
 
 static inline struct dccp_rx_hist_entry *
-                    dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
-                                           const struct sock *sk, 
-                                           const u32 ndp, 
-                                           const struct sk_buff *skb,
-                                           const gfp_t prio)
+                       dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+                                              const struct sock *sk,
+                                              const u32 ndp,
+                                              const struct sk_buff *skb,
+                                              const gfp_t prio)
 {
        struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
                                                            prio);
@@ -156,18 +157,8 @@ static inline struct dccp_rx_hist_entry *
        return entry;
 }
 
-static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
-                                            struct dccp_rx_hist_entry *entry)
-{
-       if (entry != NULL)
-               kmem_cache_free(hist->dccprxh_slab, entry);
-}
-
-extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
-                              struct list_head *list);
-
 static inline struct dccp_rx_hist_entry *
-               dccp_rx_hist_head(struct list_head *list)
+                       dccp_rx_hist_head(struct list_head *list)
 {
        struct dccp_rx_hist_entry *head = NULL;
 
@@ -177,6 +168,27 @@ static inline struct dccp_rx_hist_entry *
        return head;
 }
 
+extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+                                  u8 *ccval);
+extern struct dccp_rx_hist_entry *
+               dccp_rx_hist_find_data_packet(const struct list_head *list);
+
+extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+                                   struct list_head *rx_list,
+                                   struct list_head *li_list,
+                                   struct dccp_rx_hist_entry *packet,
+                                   u64 nonloss_seqno);
+
+static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
+                                            struct dccp_rx_hist_entry *entry)
+{
+       if (entry != NULL)
+               kmem_cache_free(hist->dccprxh_slab, entry);
+}
+
+extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
+                              struct list_head *list);
+
 static inline int
        dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
 {
@@ -184,12 +196,6 @@ static inline int
               entry->dccphrx_type == DCCP_PKT_DATAACK;
 }
 
-extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
-                                  struct list_head *rx_list,
-                                  struct list_head *li_list,
-                                  struct dccp_rx_hist_entry *packet,
-                                  u64 nonloss_seqno);
-
 extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
                                    struct list_head *li_list, u8 *win_loss);
 
index 45f30f5..faf5f7e 100644 (file)
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
  */
-
 #include <linux/types.h>
+#include <asm/div64.h>
+
+/* integer-arithmetic divisions of type (a * 1000000)/b */
+static inline u64 scaled_div(u64 a, u32 b)
+{
+       BUG_ON(b==0);
+       a *= 1000000;
+       do_div(a, b);
+       return a;
+}
+
+static inline u32 scaled_div32(u64 a, u32 b)
+{
+       u64 result = scaled_div(a, b);
+
+       if (result > UINT_MAX) {
+               DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U",
+                         (unsigned long long)a, b);
+               return UINT_MAX;
+       }
+       return result;
+}
 
 extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
 extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
index ddac2c5..90009fd 100644 (file)
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/div64.h>
 #include "../../dccp.h"
 #include "tfrc.h"
 
@@ -616,15 +615,12 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small)
  *  @R: RTT                  scaled by 1000000   (i.e., microseconds)
  *  @p: loss ratio estimate  scaled by 1000000
  *  Returns X_calc           in bytes per second (not scaled).
- *
- * Note: DO NOT alter this code unless you run test cases against it,
- *       as the code has been optimized to stop underflow/overflow.
  */
 u32 tfrc_calc_x(u16 s, u32 R, u32 p)
 {
-       int index;
+       u16 index;
        u32 f;
-       u64 tmp1, tmp2;
+       u64 result;
 
        /* check against invalid parameters and divide-by-zero   */
        BUG_ON(p >  1000000);           /* p must not exceed 100%   */
@@ -650,15 +646,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
                f = tfrc_calc_x_lookup[index][0];
        }
 
-       /* The following computes X = s/(R*f(p)) in bytes per second. Since f(p)
-        * and R are both scaled by 1000000, we need to multiply by 1000000^2.
-        * ==> DO NOT alter this unless you test against overflow on 32 bit   */
-       tmp1 = ((u64)s * 100000000);
-       tmp2 = ((u64)R * (u64)f);
-       do_div(tmp2, 10000);
-       do_div(tmp1, tmp2); 
-
-       return (u32)tmp1; 
+       /*
+        * Compute X = s/(R*f(p)) in bytes per second.
+        * Since f(p) and R are both scaled by 1000000, we need to multiply by
+        * 1000000^2. To avoid overflow, the result is computed in two stages.
+        * This works under almost all reasonable operational conditions, for a
+        * wide range of parameters. Yet, should some strange combination of
+        * parameters result in overflow, the use of scaled_div32 will catch
+        * this and return UINT_MAX - which is a logically adequate consequence.
+        */
+       result = scaled_div(s, R);
+       return scaled_div32(result, f);
 }
 
 EXPORT_SYMBOL_GPL(tfrc_calc_x);
index 6888698..a0900bf 100644 (file)
@@ -80,8 +80,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
 
 #define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
 
-#define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */
-
 /* sysctl variables for DCCP */
 extern int  sysctl_dccp_request_retries;
 extern int  sysctl_dccp_retries1;
@@ -434,6 +432,7 @@ static inline void timeval_sub_usecs(struct timeval *tv,
                tv->tv_sec--;
                tv->tv_usec += USEC_PER_SEC;
        }
+       DCCP_BUG_ON(tv->tv_sec < 0);
 }
 
 #ifdef CONFIG_SYSCTL
index 4dc487f..95b6927 100644 (file)
@@ -329,7 +329,7 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
        switch (type) {
        case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break;
        case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break;
-       default:             DCCP_WARN("invalid type %d\n", type); return;
+       default:             DCCP_WARN("invalid type %d\n", type); return;
 
        }
        opt->dccpop_feat = feature;
@@ -427,7 +427,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
        switch (type) {
        case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break;
        case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break;
-       default:              DCCP_WARN("invalid type %d\n", type);
+       default:              DCCP_WARN("invalid type %d\n", type);
                              return 1;
 
        }
@@ -610,7 +610,7 @@ const char *dccp_feat_typename(const u8 type)
        case DCCPO_CHANGE_R:  return("ChangeR");
        case DCCPO_CONFIRM_R: return("ConfirmR");
        /* the following case must not appear in feature negotation  */
-       default:              dccp_pr_debug("unknown type %d [BUG!]\n", type);
+       default:              dccp_pr_debug("unknown type %d [BUG!]\n", type);
        }
        return NULL;
 }
index 7371a2f..565bc80 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/input.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -82,7 +82,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
         *        Otherwise,
         *           Drop packet and return
         */
-       if (dh->dccph_type == DCCP_PKT_SYNC || 
+       if (dh->dccph_type == DCCP_PKT_SYNC ||
            dh->dccph_type == DCCP_PKT_SYNCACK) {
                if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
                              dp->dccps_awl, dp->dccps_awh) &&
@@ -185,8 +185,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                dccp_rcv_close(sk, skb);
                return 0;
        case DCCP_PKT_REQUEST:
-               /* Step 7 
-                *   or (S.is_server and P.type == Response)
+               /* Step 7
+                *   or (S.is_server and P.type == Response)
                 *   or (S.is_client and P.type == Request)
                 *   or (S.state >= OPEN and P.type == Request
                 *      and P.seqno >= S.OSR)
@@ -248,8 +248,18 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
                            DCCP_ACKVEC_STATE_RECEIVED))
                goto discard;
 
-       ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-       ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+       /*
+        * Deliver to the CCID module in charge.
+        * FIXME: Currently DCCP operates one-directional only, i.e. a listening
+        *        server is not at the same time a connecting client. There is
+        *        not much sense in delivering to both rx/tx sides at the moment
+        *        (only one is active at a time); when moving to bidirectional
+        *        service, this needs to be revised.
+        */
+       if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+               ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+       else
+               ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 
        return __dccp_rcv_established(sk, skb, dh, len);
 discard:
@@ -264,7 +274,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                                               const struct dccp_hdr *dh,
                                               const unsigned len)
 {
-       /* 
+       /*
         *  Step 4: Prepare sequence numbers in REQUEST
         *     If S.state == REQUEST,
         *        If (P.type == Response or P.type == Reset)
@@ -332,7 +342,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                 *            from the Response * /
                 *        S.state := PARTOPEN
                 *        Set PARTOPEN timer
-                *        Continue with S.state == PARTOPEN
+                *        Continue with S.state == PARTOPEN
                 *        / * Step 12 will send the Ack completing the
                 *            three-way handshake * /
                 */
@@ -363,7 +373,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
                         */
                        __kfree_skb(skb);
                        return 0;
-               } 
+               }
                dccp_send_ack(sk);
                return -1;
        }
@@ -371,7 +381,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
 out_invalid_packet:
        /* dccp_v4_do_rcv will send a reset */
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
-       return 1; 
+       return 1;
 }
 
 static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -478,14 +488,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
                        dccp_event_ack_recv(sk, skb);
 
-               if (dccp_msk(sk)->dccpms_send_ack_vector &&
+               if (dccp_msk(sk)->dccpms_send_ack_vector &&
                    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
-                                   DCCP_SKB_CB(skb)->dccpd_seq,
-                                   DCCP_ACKVEC_STATE_RECEIVED))
-                       goto discard;
+                                   DCCP_SKB_CB(skb)->dccpd_seq,
+                                   DCCP_ACKVEC_STATE_RECEIVED))
+                       goto discard;
 
-               ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
-               ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+               /* XXX see the comments in dccp_rcv_established about this */
+               if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+                       ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+               else
+                       ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
        }
 
        /*
@@ -567,7 +580,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                }
        }
 
-       if (!queued) { 
+       if (!queued) {
 discard:
                __kfree_skb(skb);
        }
index ff81679..90c74b4 100644 (file)
@@ -157,7 +157,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
        /* We don't check in the destentry if pmtu discovery is forbidden
         * on this route. We just assume that no packet_to_big packets
         * are send back when pmtu discovery is not active.
-        * There is a small race when the user changes this flag in the
+        * There is a small race when the user changes this flag in the
         * route, but I think that's acceptable.
         */
        if ((dst = __sk_dst_check(sk, 0)) == NULL)
@@ -467,7 +467,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
                            .uli_u = { .ports =
                                       { .sport = dccp_hdr(skb)->dccph_dport,
                                         .dport = dccp_hdr(skb)->dccph_sport }
-                                    }
+                                    }
                          };
 
        security_skb_classify_flow(skb, &fl);
@@ -595,7 +595,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        struct inet_request_sock *ireq;
        struct request_sock *req;
        struct dccp_request_sock *dreq;
-       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
        struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
        __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -609,7 +609,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (dccp_bad_service_code(sk, service)) {
                reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
                goto drop;
-       }
+       }
        /*
         * TW buckets are converted to open requests without
         * limitations, they conserve resources and peer is
@@ -644,7 +644,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        ireq->rmt_addr = skb->nh.iph->saddr;
        ireq->opt       = NULL;
 
-       /* 
+       /*
         * Step 3: Process LISTEN state
         *
         * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
@@ -846,15 +846,15 @@ static int dccp_v4_rcv(struct sk_buff *skb)
        }
 
        /* Step 2:
-        *      Look up flow ID in table and get corresponding socket */
+        *      Look up flow ID in table and get corresponding socket */
        sk = __inet_lookup(&dccp_hashinfo,
                           skb->nh.iph->saddr, dh->dccph_sport,
                           skb->nh.iph->daddr, dh->dccph_dport,
                           inet_iif(skb));
 
-       /* 
+       /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         */
        if (sk == NULL) {
                dccp_pr_debug("failed to look up flow ID in table and "
@@ -862,9 +862,9 @@ static int dccp_v4_rcv(struct sk_buff *skb)
                goto no_dccp_socket;
        }
 
-       /* 
+       /*
         * Step 2:
-        *      ... or S.state == TIMEWAIT,
+        *      ... or S.state == TIMEWAIT,
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
@@ -876,8 +876,8 @@ static int dccp_v4_rcv(struct sk_buff *skb)
 
        /*
         * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
-        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
-        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
         */
        min_cov = dccp_sk(sk)->dccps_pcrlen;
        if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov))  {
@@ -900,7 +900,7 @@ no_dccp_socket:
                goto discard_it;
        /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
index c7aaa25..6b91a9d 100644 (file)
@@ -77,7 +77,7 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
 }
 
 static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                                 __be16 sport, __be16 dport   )
+                                                 __be16 sport, __be16 dport   )
 {
        return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
 }
@@ -329,7 +329,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
        skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
                        GFP_ATOMIC);
        if (skb == NULL)
-               return;
+               return;
 
        skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
 
@@ -353,7 +353,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 
        dccp_csum_outgoing(skb);
        dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
-                                                     &rxskb->nh.ipv6h->daddr);
+                                                     &rxskb->nh.ipv6h->daddr);
 
        memset(&fl, 0, sizeof(fl));
        ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
@@ -424,7 +424,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        struct dccp_request_sock *dreq;
        struct inet6_request_sock *ireq6;
        struct ipv6_pinfo *np = inet6_sk(sk);
-       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
        struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
        __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -437,7 +437,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (dccp_bad_service_code(sk, service)) {
                reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
                goto drop;
-       }
+       }
        /*
         * There are no SYN attacks on IPv6, yet...
         */
@@ -787,7 +787,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                 * otherwise we just shortcircuit this and continue with
                 * the new socket..
                 */
-               if (nsk != sk) {
+               if (nsk != sk) {
                        if (dccp_child_process(sk, nsk, skb))
                                goto reset;
                        if (opt_skb != NULL)
@@ -843,14 +843,14 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
                DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
 
        /* Step 2:
-        *      Look up flow ID in table and get corresponding socket */
+        *      Look up flow ID in table and get corresponding socket */
        sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
                            dh->dccph_sport,
                            &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
                            inet6_iif(skb));
        /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         */
        if (sk == NULL) {
                dccp_pr_debug("failed to look up flow ID in table and "
@@ -860,7 +860,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
 
        /*
         * Step 2:
-        *      ... or S.state == TIMEWAIT,
+        *      ... or S.state == TIMEWAIT,
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
@@ -872,8 +872,8 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
 
        /*
         * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
-        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
-        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
         */
        min_cov = dccp_sk(sk)->dccps_pcrlen;
        if (dh->dccph_cscov  &&  (min_cov == 0 || dh->dccph_cscov < min_cov))  {
@@ -893,7 +893,7 @@ no_dccp_socket:
                goto discard_it;
        /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
index 7b52f2a..6656bb4 100644 (file)
@@ -32,8 +32,7 @@ struct inet_timewait_death_row dccp_death_row = {
        .tw_timer       = TIMER_INITIALIZER(inet_twdr_hangman, 0,
                                            (unsigned long)&dccp_death_row),
        .twkill_work    = __WORK_INITIALIZER(dccp_death_row.twkill_work,
-                                            inet_twdr_twkill_work,
-                                            &dccp_death_row),
+                                            inet_twdr_twkill_work),
 /* Short-time timewait calendar */
 
        .twcal_hand     = -1,
@@ -183,7 +182,7 @@ out_free:
 
 EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
 
-/* 
+/*
  * Process an incoming packet for RESPOND sockets represented
  * as an request_sock.
  */
index f398b43..c03ba61 100644 (file)
@@ -557,11 +557,6 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
                        return -1;
                dp->dccps_hc_rx_insert_options = 0;
        }
-       if (dp->dccps_hc_tx_insert_options) {
-               if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
-                       return -1;
-               dp->dccps_hc_tx_insert_options = 0;
-       }
 
        /* Feature negotiation */
        /* Data packets can't do feat negotiation */
index 400c30b..8245696 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/output.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -175,14 +175,12 @@ void dccp_write_space(struct sock *sk)
 /**
  * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
  * @sk: socket to wait for
- * @timeo: for how long
  */
-static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
-                             long *timeo)
+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        DEFINE_WAIT(wait);
-       long delay;
+       unsigned long delay;
        int rc;
 
        while (1) {
@@ -190,8 +188,6 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
 
                if (sk->sk_err)
                        goto do_error;
-               if (!*timeo)
-                       goto do_nonblock;
                if (signal_pending(current))
                        goto do_interrupted;
 
@@ -199,12 +195,9 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
                if (rc <= 0)
                        break;
                delay = msecs_to_jiffies(rc);
-               if (delay > *timeo || delay < 0)
-                       goto do_nonblock;
-
                sk->sk_write_pending++;
                release_sock(sk);
-               *timeo -= schedule_timeout(delay);
+               schedule_timeout(delay);
                lock_sock(sk);
                sk->sk_write_pending--;
        }
@@ -215,11 +208,8 @@ out:
 do_error:
        rc = -EPIPE;
        goto out;
-do_nonblock:
-       rc = -EAGAIN;
-       goto out;
 do_interrupted:
-       rc = sock_intr_errno(*timeo);
+       rc = -EINTR;
        goto out;
 }
 
@@ -240,8 +230,6 @@ void dccp_write_xmit(struct sock *sk, int block)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct sk_buff *skb;
-       long timeo = DCCP_XMIT_TIMEO;   /* If a packet is taking longer than
-                                          this we have other issues */
 
        while ((skb = skb_peek(&sk->sk_write_queue))) {
                int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
@@ -251,11 +239,9 @@ void dccp_write_xmit(struct sock *sk, int block)
                                sk_reset_timer(sk, &dp->dccps_xmit_timer,
                                                msecs_to_jiffies(err)+jiffies);
                                break;
-                       } else {
-                               err = dccp_wait_for_ccid(sk, skb, &timeo);
-                               timeo = DCCP_XMIT_TIMEO;
-                       }
-                       if (err)
+                       } else
+                               err = dccp_wait_for_ccid(sk, skb);
+                       if (err && err != -EINTR)
                                DCCP_BUG("err=%d after dccp_wait_for_ccid", err);
                }
 
@@ -281,8 +267,10 @@ void dccp_write_xmit(struct sock *sk, int block)
                        if (err)
                                DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",
                                         err);
-               } else
+               } else {
+                       dccp_pr_debug("packet discarded\n");
                        kfree(skb);
+               }
        }
 }
 
@@ -350,7 +338,6 @@ EXPORT_SYMBOL_GPL(dccp_make_response);
 
 static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
                                       const enum dccp_reset_codes code)
-                                  
 {
        struct dccp_hdr *dh;
        struct dccp_sock *dp = dccp_sk(sk);
@@ -431,14 +418,14 @@ static inline void dccp_connect_init(struct sock *sk)
        
        dccp_sync_mss(sk, dst_mtu(dst));
 
-       /*
+       /*
         * SWL and AWL are initially adjusted so that they are not less than
         * the initial Sequence Numbers received and sent, respectively:
         *      SWL := max(GSR + 1 - floor(W/4), ISR),
         *      AWL := max(GSS - W' + 1, ISS).
         * These adjustments MUST be applied only at the beginning of the
         * connection.
-        */
+        */
        dccp_update_gss(sk, dp->dccps_iss);
        dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
 
index 5ec47d9..63b3fa2 100644 (file)
@@ -196,7 +196,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
                                                      sk, GFP_KERNEL);
                dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
                                                      sk, GFP_KERNEL);
-               if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+               if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
                             dp->dccps_hc_tx_ccid == NULL)) {
                        ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
                        ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
@@ -390,7 +390,7 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
        struct dccp_sock *dp = dccp_sk(sk);
        struct dccp_service_list *sl = NULL;
 
-       if (service == DCCP_SERVICE_INVALID_VALUE || 
+       if (service == DCCP_SERVICE_INVALID_VALUE ||
            optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
                return -EINVAL;
 
@@ -830,7 +830,7 @@ EXPORT_SYMBOL_GPL(inet_dccp_listen);
 static const unsigned char dccp_new_state[] = {
        /* current state:   new state:      action:     */
        [0]               = DCCP_CLOSED,
-       [DCCP_OPEN]       = DCCP_CLOSING | DCCP_ACTION_FIN,
+       [DCCP_OPEN]       = DCCP_CLOSING | DCCP_ACTION_FIN,
        [DCCP_REQUESTING] = DCCP_CLOSED,
        [DCCP_PARTOPEN]   = DCCP_CLOSING | DCCP_ACTION_FIN,
        [DCCP_LISTEN]     = DCCP_CLOSED,
index e8f519e..e5348f3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  net/dccp/timer.c
- * 
+ *
  *  An implementation of the DCCP protocol
  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
@@ -102,13 +102,13 @@ static void dccp_retransmit_timer(struct sock *sk)
         * sk->sk_send_head has to have one skb with
         * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
         * packet types. The only packets eligible for retransmission are:
-        *      -- Requests in client-REQUEST  state (sec. 8.1.1)
-        *      -- Acks     in client-PARTOPEN state (sec. 8.1.5)
-        *      -- CloseReq in server-CLOSEREQ state (sec. 8.3)
-        *      -- Close    in   node-CLOSING  state (sec. 8.3)                */
+        *      -- Requests in client-REQUEST  state (sec. 8.1.1)
+        *      -- Acks     in client-PARTOPEN state (sec. 8.1.5)
+        *      -- CloseReq in server-CLOSEREQ state (sec. 8.3)
+        *      -- Close    in   node-CLOSING  state (sec. 8.3)                */
        BUG_TRAP(sk->sk_send_head != NULL);
 
-       /* 
+       /*
         * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
         * sent, no need to retransmit, this sock is dead.
         */
@@ -200,7 +200,7 @@ static void dccp_keepalive_timer(unsigned long data)
        /* Only process if socket is not in use. */
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
-               /* Try again later. */ 
+               /* Try again later. */
                inet_csk_reset_keepalive_timer(sk, HZ / 20);
                goto out;
        }
index 0b9d4c9..fc6f3c0 100644 (file)
@@ -167,8 +167,7 @@ static int dn_forwarding_proc(ctl_table *, int, struct file *,
                        void __user *, size_t *, loff_t *);
 static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen,
-                       void **context);
+                       void __user *newval, size_t newlen);
 
 static struct dn_dev_sysctl_table {
        struct ctl_table_header *sysctl_header;
@@ -347,8 +346,7 @@ static int dn_forwarding_proc(ctl_table *table, int write,
 
 static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen,
-                       void **context)
+                       void __user *newval, size_t newlen)
 {
 #ifdef CONFIG_DECNET_ROUTER
        struct net_device *dev = table->extra1;
index bdbc3f4..13b2421 100644 (file)
@@ -79,7 +79,7 @@ for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_n
 static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ];
 static DEFINE_RWLOCK(dn_fib_tables_lock);
 
-static kmem_cache_t *dn_hash_kmem __read_mostly;
+static struct kmem_cache *dn_hash_kmem __read_mostly;
 static int dn_fib_hash_zombies;
 
 static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
@@ -590,7 +590,7 @@ create:
 
 replace:
        err = -ENOBUFS;
-       new_f = kmem_cache_alloc(dn_hash_kmem, SLAB_KERNEL);
+       new_f = kmem_cache_alloc(dn_hash_kmem, GFP_KERNEL);
        if (new_f == NULL)
                goto out;
 
index e246f05..a4065eb 100644 (file)
@@ -134,8 +134,7 @@ static int parse_addr(__le16 *addr, char *str)
 
 static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen,
                                void __user *oldval, size_t __user *oldlenp,
-                               void __user *newval, size_t newlen,
-                               void **context)
+                               void __user *newval, size_t newlen)
 {
        size_t len;
        __le16 addr;
@@ -220,8 +219,7 @@ static int dn_node_address_handler(ctl_table *table, int write,
 
 static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen,
                                void __user *oldval, size_t __user *oldlenp,
-                               void __user *newval, size_t newlen,
-                               void **context)
+                               void __user *newval, size_t newlen)
 {
        size_t len;
        struct net_device *dev;
index cf51c87..e3f37fd 100644 (file)
@@ -58,9 +58,11 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
 }
 
 void
-ieee80211softmac_assoc_timeout(void *d)
+ieee80211softmac_assoc_timeout(struct work_struct *work)
 {
-       struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
+       struct ieee80211softmac_device *mac =
+               container_of(work, struct ieee80211softmac_device,
+                            associnfo.timeout.work);
        struct ieee80211softmac_network *n;
 
        mutex_lock(&mac->associnfo.mutex);
@@ -186,9 +188,11 @@ ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void
 
 /* This function is called to handle userspace requests (asynchronously) */
 void
-ieee80211softmac_assoc_work(void *d)
+ieee80211softmac_assoc_work(struct work_struct *work)
 {
-       struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
+       struct ieee80211softmac_device *mac =
+               container_of(work, struct ieee80211softmac_device,
+                            associnfo.work.work);
        struct ieee80211softmac_network *found = NULL;
        struct ieee80211_network *net = NULL, *best = NULL;
        int bssvalid;
@@ -412,7 +416,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
                                network->authenticated = 0;
                                /* we don't want to do this more than once ... */
                                network->auth_desynced_once = 1;
-                               schedule_work(&mac->associnfo.work);
+                               schedule_delayed_work(&mac->associnfo.work, 0);
                                break;
                        }
                default:
@@ -427,6 +431,17 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
        return 0;
 }
 
+void
+ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       mac->associnfo.associating = 1;
+       schedule_delayed_work(&mac->associnfo.work, 0);
+       spin_unlock_irqrestore(&mac->lock, flags);
+}
+
 int
 ieee80211softmac_handle_disassoc(struct net_device * dev,
                                 struct ieee80211_disassoc *disassoc)
@@ -445,8 +460,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
        dprintk(KERN_INFO PFX "got disassoc frame\n");
        ieee80211softmac_disassoc(mac);
 
-       /* try to reassociate */
-       schedule_work(&mac->associnfo.work);
+       ieee80211softmac_try_reassoc(mac);
 
        return 0;
 }
@@ -466,7 +480,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
                dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
                return 0;
        }
-       schedule_work(&mac->associnfo.work);
+       schedule_delayed_work(&mac->associnfo.work, 0);
 
        return 0;
 }
index 0612015..8ed3e59 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "ieee80211softmac_priv.h"
 
-static void ieee80211softmac_auth_queue(void *data);
+static void ieee80211softmac_auth_queue(struct work_struct *work);
 
 /* Queues an auth request to the desired AP */
 int
@@ -54,14 +54,14 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
        auth->mac = mac;
        auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
        auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
-       INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth);
+       INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
        
        /* Lock (for list) */
        spin_lock_irqsave(&mac->lock, flags);
 
        /* add to list */
        list_add_tail(&auth->list, &mac->auth_queue);
-       schedule_work(&auth->work);
+       schedule_delayed_work(&auth->work, 0);
        spin_unlock_irqrestore(&mac->lock, flags);
        
        return 0;
@@ -70,14 +70,15 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
 
 /* Sends an auth request to the desired AP and handles timeouts */
 static void
-ieee80211softmac_auth_queue(void *data)
+ieee80211softmac_auth_queue(struct work_struct *work)
 {
        struct ieee80211softmac_device *mac;
        struct ieee80211softmac_auth_queue_item *auth;
        struct ieee80211softmac_network *net;
        unsigned long flags;
 
-       auth = (struct ieee80211softmac_auth_queue_item *)data;
+       auth = container_of(work, struct ieee80211softmac_auth_queue_item,
+                           work.work);
        net = auth->net;
        mac = auth->mac;
 
@@ -118,9 +119,11 @@ ieee80211softmac_auth_queue(void *data)
 
 /* Sends a response to an auth challenge (for shared key auth). */
 static void
-ieee80211softmac_auth_challenge_response(void *_aq)
+ieee80211softmac_auth_challenge_response(struct work_struct *work)
 {
-       struct ieee80211softmac_auth_queue_item *aq = _aq;
+       struct ieee80211softmac_auth_queue_item *aq =
+               container_of(work, struct ieee80211softmac_auth_queue_item,
+                            work.work);
 
        /* Send our response */
        ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
@@ -234,8 +237,8 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
                         * we have obviously already sent the initial auth
                         * request. */
                        cancel_delayed_work(&aq->work);
-                       INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq);
-                       schedule_work(&aq->work);
+                       INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response);
+                       schedule_delayed_work(&aq->work, 0);
                        spin_unlock_irqrestore(&mac->lock, flags);
                        return 0;
                case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
@@ -334,6 +337,8 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
        /* can't transmit data right now... */
        netif_carrier_off(mac->dev);
        spin_unlock_irqrestore(&mac->lock, flags);
+
+       ieee80211softmac_try_reassoc(mac);
 }
 
 /* 
@@ -398,6 +403,6 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
        ieee80211softmac_deauth_from_net(mac, net);
 
        /* let's try to re-associate */
-       schedule_work(&mac->associnfo.work);
+       schedule_delayed_work(&mac->associnfo.work, 0);
        return 0;
 }
index f34fa2e..b901565 100644 (file)
@@ -73,10 +73,12 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
 
 
 static void
-ieee80211softmac_notify_callback(void *d)
+ieee80211softmac_notify_callback(struct work_struct *work)
 {
-       struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
-       kfree(d);
+       struct ieee80211softmac_event *pevent =
+               container_of(work, struct ieee80211softmac_event, work.work);
+       struct ieee80211softmac_event event = *pevent;
+       kfree(pevent);
        
        event.fun(event.mac->dev, event.event_type, event.context);
 }
@@ -99,7 +101,7 @@ ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
                return -ENOMEM;
        
        eventptr->event_type = event;
-       INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr);
+       INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback);
        eventptr->fun = fun;
        eventptr->context = context;
        eventptr->mac = mac;
@@ -170,7 +172,7 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
                                /* User may have subscribed to ANY event, so
                                 * we tell them which event triggered it. */
                                eventptr->event_type = event;
-                               schedule_work(&eventptr->work);
+                               schedule_delayed_work(&eventptr->work, 0);
                        }
                }
 }
index 33aff4f..256207b 100644 (file)
@@ -58,8 +58,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
        INIT_LIST_HEAD(&softmac->events);
 
        mutex_init(&softmac->associnfo.mutex);
-       INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
-       INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
+       INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work);
+       INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout);
        softmac->start_scan = ieee80211softmac_start_scan_implementation;
        softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
        softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
index 0642e09..4c2bba3 100644 (file)
@@ -78,7 +78,7 @@
 /* private definitions and prototypes */
 
 /*** prototypes from _scan.c */
-void ieee80211softmac_scan(void *sm);
+void ieee80211softmac_scan(struct work_struct *work);
 /* for internal use if scanning is needed */
 int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac);
 void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac);
@@ -149,7 +149,7 @@ int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *au
 int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth);
 
 /*** prototypes from _assoc.c */
-void ieee80211softmac_assoc_work(void *d);
+void ieee80211softmac_assoc_work(struct work_struct *work);
 int ieee80211softmac_handle_assoc_response(struct net_device * dev,
                                           struct ieee80211_assoc_response * resp,
                                           struct ieee80211_network * network);
@@ -157,7 +157,7 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev,
                                     struct ieee80211_disassoc * disassoc);
 int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
                                        struct ieee80211_reassoc_request * reassoc);
-void ieee80211softmac_assoc_timeout(void *d);
+void ieee80211softmac_assoc_timeout(struct work_struct *work);
 void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
 void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
 
@@ -207,7 +207,7 @@ struct ieee80211softmac_auth_queue_item {
        struct ieee80211softmac_device  *mac;   /* SoftMAC device */
        u8 retry;                               /* Retry limit */
        u8 state;                               /* Auth State */
-       struct work_struct              work;   /* Work queue */
+       struct delayed_work             work;   /* Work queue */
 };
 
 /* scanning information */
@@ -219,7 +219,8 @@ struct ieee80211softmac_scaninfo {
           stop:1;
        u8 skip_flags;
        struct completion finished;
-       struct work_struct softmac_scan;
+       struct delayed_work softmac_scan;
+       struct ieee80211softmac_device *mac;
 };
 
 /* private event struct */
@@ -227,7 +228,7 @@ struct ieee80211softmac_event {
        struct list_head list;
        int event_type;
        void *event_context;
-       struct work_struct work;
+       struct delayed_work work;
        notify_function_ptr fun;
        void *context;
        struct ieee80211softmac_device *mac;
@@ -238,4 +239,6 @@ void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, in
 int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
        int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
 
+void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac);
+
 #endif /* IEEE80211SOFTMAC_PRIV_H_ */
index 5507fea..0c85d6c 100644 (file)
@@ -90,12 +90,14 @@ ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
 
 
 /* internal scanning implementation follows */
-void ieee80211softmac_scan(void *d)
+void ieee80211softmac_scan(struct work_struct *work)
 {
        int invalid_channel;
        u8 current_channel_idx;
-       struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d;
-       struct ieee80211softmac_scaninfo *si = sm->scaninfo;
+       struct ieee80211softmac_scaninfo *si =
+               container_of(work, struct ieee80211softmac_scaninfo,
+                            softmac_scan.work);
+       struct ieee80211softmac_device *sm = si->mac;
        unsigned long flags;
 
        while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
@@ -146,7 +148,8 @@ static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee802
        struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
        if (unlikely(!info))
                return NULL;
-       INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac);
+       INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan);
+       info->mac = mac;
        init_completion(&info->finished);
        return info;
 }
@@ -187,7 +190,7 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev)
        sm->scaninfo->started = 1;
        sm->scaninfo->stop = 0;
        INIT_COMPLETION(sm->scaninfo->finished);
-       schedule_work(&sm->scaninfo->softmac_scan);
+       schedule_delayed_work(&sm->scaninfo->softmac_scan, 0);
        spin_unlock_irqrestore(&sm->lock, flags);
        return 0;
 }
index 23068a8..480d72c 100644 (file)
@@ -122,7 +122,7 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
 
        sm->associnfo.associating = 1;
        /* queue lower level code to do work (if necessary) */
-       schedule_work(&sm->associnfo.work);
+       schedule_delayed_work(&sm->associnfo.work, 0);
 out:
        mutex_unlock(&sm->associnfo.mutex);
 
@@ -356,7 +356,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
                /* force reassociation */
                mac->associnfo.bssvalid = 0;
                if (mac->associnfo.associated)
-                       schedule_work(&mac->associnfo.work);
+                       schedule_delayed_work(&mac->associnfo.work, 0);
        } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
                /* the bssid we have is no longer fixed */
                mac->associnfo.bssfixed = 0;
@@ -373,7 +373,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
                /* tell the other code that this bssid should be used no matter what */
                mac->associnfo.bssfixed = 1;
                /* queue associate if new bssid or (old one again and not associated) */
-               schedule_work(&mac->associnfo.work);
+               schedule_delayed_work(&mac->associnfo.work, 0);
         }
 
  out:
@@ -495,7 +495,8 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
                        printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
                        goto out;
                }
-               return ieee80211softmac_deauth_req(mac, net, reason);
+               err =  ieee80211softmac_deauth_req(mac, net, reason);
+               goto out;
        case IW_MLME_DISASSOC:
                ieee80211softmac_send_disassoc_req(mac, reason);
                mac->associnfo.associated = 0;
index 2fd8991..84bed40 100644 (file)
@@ -1303,8 +1303,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
 
 int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
                                  void __user *oldval, size_t __user *oldlenp,
-                                 void __user *newval, size_t newlen, 
-                                 void **context)
+                                 void __user *newval, size_t newlen)
 {
        int *valp = table->data;
        int new;
index 107bb6c..648f47c 100644 (file)
@@ -45,8 +45,8 @@
 
 #include "fib_lookup.h"
 
-static kmem_cache_t *fn_hash_kmem __read_mostly;
-static kmem_cache_t *fn_alias_kmem __read_mostly;
+static struct kmem_cache *fn_hash_kmem __read_mostly;
+static struct kmem_cache *fn_alias_kmem __read_mostly;
 
 struct fib_node {
        struct hlist_node       fn_hash;
@@ -485,13 +485,13 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg)
                goto out;
 
        err = -ENOBUFS;
-       new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+       new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
        if (new_fa == NULL)
                goto out;
 
        new_f = NULL;
        if (!f) {
-               new_f = kmem_cache_alloc(fn_hash_kmem, SLAB_KERNEL);
+               new_f = kmem_cache_alloc(fn_hash_kmem, GFP_KERNEL);
                if (new_f == NULL)
                        goto out_free_new_fa;
 
index d17990e..cfb249c 100644 (file)
@@ -172,7 +172,7 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn);
 static struct tnode *halve(struct trie *t, struct tnode *tn);
 static void tnode_free(struct tnode *tn);
 
-static kmem_cache_t *fn_alias_kmem __read_mostly;
+static struct kmem_cache *fn_alias_kmem __read_mostly;
 static struct trie *trie_local = NULL, *trie_main = NULL;
 
 
@@ -1187,7 +1187,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
                        u8 state;
 
                        err = -ENOBUFS;
-                       new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+                       new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
                        if (new_fa == NULL)
                                goto out;
 
@@ -1232,7 +1232,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
                goto out;
 
        err = -ENOBUFS;
-       new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+       new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
        if (new_fa == NULL)
                goto out;
 
index 244c4f4..8c79c8a 100644 (file)
  * Allocate and initialize a new local port bind bucket.
  * The bindhash mutex for snum's hash chain must be held here.
  */
-struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
+struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
                                                 struct inet_bind_hashbucket *head,
                                                 const unsigned short snum)
 {
-       struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, SLAB_ATOMIC);
+       struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
 
        if (tb != NULL) {
                tb->port      = snum;
@@ -45,7 +45,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
 /*
  * Caller must hold hashbucket lock for this tb with local BH disabled
  */
-void inet_bind_bucket_destroy(kmem_cache_t *cachep, struct inet_bind_bucket *tb)
+void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket *tb)
 {
        if (hlist_empty(&tb->owners)) {
                __hlist_del(&tb->node);
index cdd8053..9f414e3 100644 (file)
@@ -91,7 +91,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
 {
        struct inet_timewait_sock *tw =
                kmem_cache_alloc(sk->sk_prot_creator->twsk_prot->twsk_slab,
-                                SLAB_ATOMIC);
+                                GFP_ATOMIC);
        if (tw != NULL) {
                const struct inet_sock *inet = inet_sk(sk);
 
@@ -178,7 +178,6 @@ void inet_twdr_hangman(unsigned long data)
        need_timer = 0;
        if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
                twdr->thread_slots |= (1 << twdr->slot);
-               mb();
                schedule_work(&twdr->twkill_work);
                need_timer = 1;
        } else {
@@ -197,9 +196,10 @@ EXPORT_SYMBOL_GPL(inet_twdr_hangman);
 
 extern void twkill_slots_invalid(void);
 
-void inet_twdr_twkill_work(void *data)
+void inet_twdr_twkill_work(struct work_struct *work)
 {
-       struct inet_timewait_death_row *twdr = data;
+       struct inet_timewait_death_row *twdr =
+               container_of(work, struct inet_timewait_death_row, twkill_work);
        int i;
 
        if ((INET_TWDR_TWKILL_SLOTS - 1) > (sizeof(twdr->thread_slots) * 8))
index f072f38..711eb6d 100644 (file)
@@ -73,7 +73,7 @@
 /* Exported for inet_getid inline function.  */
 DEFINE_SPINLOCK(inet_peer_idlock);
 
-static kmem_cache_t *peer_cachep __read_mostly;
+static struct kmem_cache *peer_cachep __read_mostly;
 
 #define node_height(x) x->avl_height
 static struct inet_peer peer_fake_node = {
index a35209d..f071f84 100644 (file)
@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
 static inline int ip_finish_output2(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb->dst;
-       struct hh_cache *hh = dst->hh;
        struct net_device *dev = dst->dev;
        int hh_len = LL_RESERVED_SPACE(dev);
 
@@ -183,16 +182,9 @@ static inline int ip_finish_output2(struct sk_buff *skb)
                skb = skb2;
        }
 
-       if (hh) {
-               int hh_alen;
-
-               read_lock_bh(&hh->hh_lock);
-               hh_alen = HH_DATA_ALIGN(hh->hh_len);
-               memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
-               read_unlock_bh(&hh->hh_lock);
-               skb_push(skb, hh->hh_len);
-               return hh->hh_output(skb);
-       } else if (dst->neighbour)
+       if (dst->hh)
+               return neigh_hh_output(dst->hh, skb);
+       else if (dst->neighbour)
                return dst->neighbour->output(skb);
 
        if (net_ratelimit())
index efcf45e..ecb5422 100644 (file)
@@ -105,7 +105,7 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
    In this case data path is free of exclusive locks at all.
  */
 
-static kmem_cache_t *mrt_cachep __read_mostly;
+static struct kmem_cache *mrt_cachep __read_mostly;
 
 static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local);
 static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert);
index 8832eb5..8086787 100644 (file)
@@ -44,7 +44,7 @@
 static struct list_head *ip_vs_conn_tab;
 
 /*  SLAB cache for IPVS connections */
-static kmem_cache_t *ip_vs_conn_cachep __read_mostly;
+static struct kmem_cache *ip_vs_conn_cachep __read_mostly;
 
 /*  counter for current IPVS connections */
 static atomic_t ip_vs_conn_count = ATOMIC_INIT(0);
index f261616..9b93338 100644 (file)
@@ -221,10 +221,10 @@ static void update_defense_level(void)
  *     Timer for checking the defense
  */
 #define DEFENSE_TIMER_PERIOD   1*HZ
-static void defense_work_handler(void *data);
-static DECLARE_WORK(defense_work, defense_work_handler, NULL);
+static void defense_work_handler(struct work_struct *work);
+static DECLARE_DELAYED_WORK(defense_work, defense_work_handler);
 
-static void defense_work_handler(void *data)
+static void defense_work_handler(struct work_struct *work)
 {
        update_defense_level();
        if (atomic_read(&ip_vs_dropentry))
index 91a075e..7ea2d98 100644 (file)
@@ -657,7 +657,7 @@ static void sync_master_loop(void)
                if (stop_master_sync)
                        break;
 
-               ssleep(1);
+               msleep_interruptible(1000);
        }
 
        /* clean up the sync_buff queue */
@@ -714,7 +714,7 @@ static void sync_backup_loop(void)
                if (stop_backup_sync)
                        break;
 
-               ssleep(1);
+               msleep_interruptible(1000);
        }
 
        /* release the sending multicast socket */
@@ -826,7 +826,7 @@ static int fork_sync_thread(void *startup)
        if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
                IP_VS_ERR("could not create sync_thread due to %d... "
                          "retrying.\n", pid);
-               ssleep(1);
+               msleep_interruptible(1000);
                goto repeat;
        }
 
@@ -849,10 +849,12 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
 
        ip_vs_sync_state |= state;
        if (state == IP_VS_STATE_MASTER) {
-               strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn));
+               strlcpy(ip_vs_master_mcast_ifn, mcast_ifn,
+                       sizeof(ip_vs_master_mcast_ifn));
                ip_vs_master_syncid = syncid;
        } else {
-               strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn));
+               strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn,
+                       sizeof(ip_vs_backup_mcast_ifn));
                ip_vs_backup_syncid = syncid;
        }
 
@@ -860,7 +862,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
        if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
                IP_VS_ERR("could not create fork_sync_thread due to %d... "
                          "retrying.\n", pid);
-               ssleep(1);
+               msleep_interruptible(1000);
                goto repeat;
        }
 
@@ -880,7 +882,8 @@ int stop_sync_thread(int state)
 
        IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
        IP_VS_INFO("stopping sync thread %d ...\n",
-                  (state == IP_VS_STATE_MASTER) ? sync_master_pid : sync_backup_pid);
+                  (state == IP_VS_STATE_MASTER) ?
+                  sync_master_pid : sync_backup_pid);
 
        __set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&stop_sync_wait, &wait);
index 413c2d0..71b76ad 100644 (file)
@@ -375,6 +375,13 @@ static int mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->arp)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                 * big jump.
                                 */
@@ -404,6 +411,14 @@ static int mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           ARPT_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct arpt_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
+
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -426,8 +441,6 @@ static int mark_source_chains(struct xt_table_info *newinfo,
 static inline int standard_check(const struct arpt_entry_target *t,
                                 unsigned int max_offset)
 {
-       struct arpt_standard_target *targ = (void *)t;
-
        /* Check standard info. */
        if (t->u.target_size
            != ARPT_ALIGN(sizeof(struct arpt_standard_target))) {
@@ -437,18 +450,6 @@ static inline int standard_check(const struct arpt_entry_target *t,
                return 0;
        }
 
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct arpt_entry)) {
-               duprintf("arpt_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("arpt_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
        return 1;
 }
 
@@ -627,18 +628,20 @@ static int translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
+               duprintf("Looping hook\n");
+               return -ELOOP;
+       }
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
                                 check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
-               duprintf("Looping hook\n");
-               goto cleanup;
+       if (ret != 0) {
+               ARPT_ENTRY_ITERATE(entry0, newinfo->size,
+                               cleanup_entry, &i);
+               return ret;
        }
 
        /* And one copy for every other CPU */
@@ -647,9 +650,6 @@ static int translate_table(const char *name,
                        memcpy(newinfo->entries[i], entry0, newinfo->size);
        }
 
-       return 0;
-cleanup:
-       ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
        return ret;
 }
 
index f4b0e68..8556a4f 100644 (file)
@@ -65,8 +65,8 @@ static LIST_HEAD(helpers);
 unsigned int ip_conntrack_htable_size __read_mostly = 0;
 int ip_conntrack_max __read_mostly;
 struct list_head *ip_conntrack_hash __read_mostly;
-static kmem_cache_t *ip_conntrack_cachep __read_mostly;
-static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly;
+static struct kmem_cache *ip_conntrack_cachep __read_mostly;
+static struct kmem_cache *ip_conntrack_expect_cachep __read_mostly;
 struct ip_conntrack ip_conntrack_untracked;
 unsigned int ip_ct_log_invalid __read_mostly;
 static LIST_HEAD(unconfirmed);
index 8a45543..0ff2956 100644 (file)
@@ -401,6 +401,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ip)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                   big jump. */
                                do {
@@ -438,6 +445,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           IPT_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct ipt_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -469,27 +483,6 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
        return 0;
 }
 
-static inline int
-standard_check(const struct ipt_entry_target *t,
-              unsigned int max_offset)
-{
-       struct ipt_standard_target *targ = (void *)t;
-
-       /* Check standard info. */
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
-               duprintf("ipt_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("ipt_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       return 1;
-}
-
 static inline int
 check_match(struct ipt_entry_match *m,
            const char *name,
@@ -576,12 +569,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
        if (ret)
                goto err;
 
-       if (t->u.kernel.target == &ipt_standard_target) {
-               if (!standard_check(t, size)) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-       } else if (t->u.kernel.target->checkentry
+       if (t->u.kernel.target->checkentry
                   && !t->u.kernel.target->checkentry(name, e, target, t->data,
                                                      e->comefrom)) {
                duprintf("ip_tables: check failed for `%s'.\n",
@@ -718,17 +706,19 @@ translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0))
+               return -ELOOP;
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
                                check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0))
-               goto cleanup;
+       if (ret != 0) {
+               IPT_ENTRY_ITERATE(entry0, newinfo->size,
+                               cleanup_entry, &i);
+               return ret;
+       }
 
        /* And one copy for every other CPU */
        for_each_possible_cpu(i) {
@@ -736,9 +726,6 @@ translate_table(const char *name,
                        memcpy(newinfo->entries[i], entry0, newinfo->size);
        }
 
-       return 0;
-cleanup:
-       IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
        return ret;
 }
 
@@ -1529,25 +1516,8 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
        void **dstptr, compat_uint_t *size, const char *name,
        const struct ipt_ip *ip, unsigned int hookmask)
 {
-       struct ipt_entry_match *dm;
-       struct ipt_match *match;
-       int ret;
-
-       dm = (struct ipt_entry_match *)*dstptr;
-       match = m->u.kernel.match;
        xt_compat_match_from_user(m, dstptr, size);
-
-       ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
-                            name, hookmask, ip->proto,
-                            ip->invflags & IPT_INV_PROTO);
-       if (!ret && m->u.kernel.match->checkentry
-           && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
-                                             hookmask)) {
-               duprintf("ip_tables: check failed for `%s'.\n",
-                        m->u.kernel.match->name);
-               ret = -EINVAL;
-       }
-       return ret;
+       return 0;
 }
 
 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
@@ -1569,7 +1539,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
        ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
                        name, &de->ip, de->comefrom);
        if (ret)
-               goto err;
+               return ret;
        de->target_offset = e->target_offset - (origsize - *size);
        t = ipt_get_target(e);
        target = t->u.kernel.target;
@@ -1582,31 +1552,62 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
                if ((unsigned char *)de - base < newinfo->underflow[h])
                        newinfo->underflow[h] -= origsize - *size;
        }
+       return ret;
+}
+
+static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
+                               const struct ipt_ip *ip, unsigned int hookmask)
+{
+       struct ipt_match *match;
+       int ret;
+
+       match = m->u.kernel.match;
+       ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
+                            name, hookmask, ip->proto,
+                            ip->invflags & IPT_INV_PROTO);
+       if (!ret && m->u.kernel.match->checkentry
+           && !m->u.kernel.match->checkentry(name, ip, match, m->data,
+                                             hookmask)) {
+               duprintf("ip_tables: compat: check failed for `%s'.\n",
+                        m->u.kernel.match->name);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static inline int compat_check_target(struct ipt_entry *e, const char *name)
+{
+       struct ipt_entry_target *t;
+       struct ipt_target *target;
+       int ret;
 
-       t = ipt_get_target(de);
+       t = ipt_get_target(e);
        target = t->u.kernel.target;
        ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
                              name, e->comefrom, e->ip.proto,
                              e->ip.invflags & IPT_INV_PROTO);
-       if (ret)
-               goto err;
-
-       ret = -EINVAL;
-       if (t->u.kernel.target == &ipt_standard_target) {
-               if (!standard_check(t, *size))
-                       goto err;
-       } else if (t->u.kernel.target->checkentry
-                  && !t->u.kernel.target->checkentry(name, de, target,
-                                                     t->data, de->comefrom)) {
+       if (!ret && t->u.kernel.target->checkentry
+                  && !t->u.kernel.target->checkentry(name, e, target,
+                                                     t->data, e->comefrom)) {
                duprintf("ip_tables: compat: check failed for `%s'.\n",
                         t->u.kernel.target->name);
-               goto err;
+               ret = -EINVAL;
        }
-       ret = 0;
-err:
        return ret;
 }
 
+static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+{
+       int ret;
+
+       ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
+                                                               e->comefrom);
+       if (ret)
+               return ret;
+
+       return compat_check_target(e, name);
+}
+
 static int
 translate_compat_table(const char *name,
                unsigned int valid_hooks,
@@ -1695,6 +1696,11 @@ translate_compat_table(const char *name,
        if (!mark_source_chains(newinfo, valid_hooks, entry1))
                goto free_newinfo;
 
+       ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
+                                                                       name);
+       if (ret)
+               goto free_newinfo;
+
        /* And one copy for every other CPU */
        for_each_possible_cpu(i)
                if (newinfo->entries[i] && newinfo->entries[i] != entry1)
index 0983650..fef56ae 100644 (file)
@@ -683,7 +683,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 {
 #define PROC_WRITELEN  10
        char buffer[PROC_WRITELEN+1];
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        struct clusterip_config *c = pde->data;
        unsigned long nodenum;
 
index 126db44..4db0e73 100644 (file)
@@ -401,7 +401,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
 static ssize_t recent_proc_write(struct file *file, const char __user *input,
                                 size_t size, loff_t *loff)
 {
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        struct recent_table *t = pde->data;
        struct recent_entry *e;
        char buf[sizeof("+255.255.255.255")], *c = buf;
index 9f3924c..1aaff0a 100644 (file)
@@ -1780,7 +1780,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
 #endif
        if (in_dev->cnf.no_policy)
                rth->u.dst.flags |= DST_NOPOLICY;
-       if (in_dev->cnf.no_xfrm)
+       if (out_dev->cnf.no_xfrm)
                rth->u.dst.flags |= DST_NOXFRM;
        rth->fl.fl4_dst = daddr;
        rth->rt_dst     = daddr;
@@ -2872,8 +2872,7 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
                                                void __user *oldval,
                                                size_t __user *oldlenp,
                                                void __user *newval,
-                                               size_t newlen,
-                                               void **context)
+                                               size_t newlen)
 {
        int delay;
        if (newlen != sizeof(int))
index dfcf47f..fabf69a 100644 (file)
@@ -51,8 +51,7 @@ int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
 static int ipv4_sysctl_forward_strategy(ctl_table *table,
                         int __user *name, int nlen,
                         void __user *oldval, size_t __user *oldlenp,
-                        void __user *newval, size_t newlen, 
-                        void **context)
+                        void __user *newval, size_t newlen)
 {
        int *valp = table->data;
        int new;
@@ -111,8 +110,7 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file *
 static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
                                         int nlen, void __user *oldval,
                                         size_t __user *oldlenp,
-                                        void __user *newval, size_t newlen,
-                                        void **context)
+                                        void __user *newval, size_t newlen)
 {
        char val[TCP_CA_NAME_MAX];
        ctl_table tbl = {
@@ -122,8 +120,7 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
        int ret;
 
        tcp_get_default_congestion_control(val);
-       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
-                           context);
+       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
        if (ret == 0 && newval && newlen)
                ret = tcp_set_default_congestion_control(val);
        return ret;
@@ -169,8 +166,8 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
 static int strategy_allowed_congestion_control(ctl_table *table, int __user *name,
                                               int nlen, void __user *oldval,
                                               size_t __user *oldlenp,
-                                              void __user *newval, size_t newlen,
-                                              void **context)
+                                              void __user *newval,
+                                              size_t newlen)
 {
        ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
        int ret;
@@ -180,8 +177,7 @@ static int strategy_allowed_congestion_control(ctl_table *table, int __user *nam
                return -ENOMEM;
 
        tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
-       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
-                           context);
+       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
        if (ret == 0 && newval && newlen)
                ret = tcp_set_allowed_congestion_control(tbl.data);
        kfree(tbl.data);
index 9304034..c701f6a 100644 (file)
@@ -4235,7 +4235,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                 * Change state from SYN-SENT only after copied_seq
                 * is initialized. */
                tp->copied_seq = tp->rcv_nxt;
-               mb();
+               smp_mb();
                tcp_set_state(sk, TCP_ESTABLISHED);
 
                security_inet_conn_established(sk, skb);
@@ -4483,7 +4483,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                case TCP_SYN_RECV:
                        if (acceptable) {
                                tp->copied_seq = tp->rcv_nxt;
-                               mb();
+                               smp_mb();
                                tcp_set_state(sk, TCP_ESTABLISHED);
                                sk->sk_state_change(sk);
 
index 6dddf59..4a3889d 100644 (file)
@@ -45,8 +45,7 @@ struct inet_timewait_death_row tcp_death_row = {
        .tw_timer       = TIMER_INITIALIZER(inet_twdr_hangman, 0,
                                            (unsigned long)&tcp_death_row),
        .twkill_work    = __WORK_INITIALIZER(tcp_death_row.twkill_work,
-                                            inet_twdr_twkill_work,
-                                            &tcp_death_row),
+                                            inet_twdr_twkill_work),
 /* Short-time timewait calendar */
 
        .twcal_hand     = -1,
index d4107bb..fb9f69c 100644 (file)
@@ -274,6 +274,8 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
 
        if (likely(xdst->u.rt.idev))
                in_dev_put(xdst->u.rt.idev);
+       if (likely(xdst->u.rt.peer))
+               inet_putpeer(xdst->u.rt.peer);
        xfrm_dst_destroy(xdst);
 }
 
index a5e8d20..9b0a906 100644 (file)
@@ -3656,8 +3656,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
                                            int __user *name, int nlen,
                                            void __user *oldval,
                                            size_t __user *oldlenp,
-                                           void __user *newval, size_t newlen,
-                                           void **context)
+                                           void __user *newval, size_t newlen)
 {
        int *valp = table->data;
        int new;
index 87c8f54..e5cd83b 100644 (file)
@@ -720,10 +720,8 @@ snmp6_mib_free(void *ptr[2])
 {
        if (ptr == NULL)
                return;
-       if (ptr[0])
-               free_percpu(ptr[0]);
-       if (ptr[1])
-               free_percpu(ptr[1]);
+       free_percpu(ptr[0]);
+       free_percpu(ptr[1]);
        ptr[0] = ptr[1] = NULL;
 }
 
index bf52611..96d8310 100644 (file)
@@ -50,7 +50,7 @@
 
 struct rt6_statistics  rt6_stats;
 
-static kmem_cache_t * fib6_node_kmem __read_mostly;
+static struct kmem_cache * fib6_node_kmem __read_mostly;
 
 enum fib_walk_state_t
 {
@@ -150,7 +150,7 @@ static __inline__ struct fib6_node * node_alloc(void)
 {
        struct fib6_node *fn;
 
-       if ((fn = kmem_cache_alloc(fib6_node_kmem, SLAB_ATOMIC)) != NULL)
+       if ((fn = kmem_cache_alloc(fib6_node_kmem, GFP_ATOMIC)) != NULL)
                memset(fn, 0, sizeof(struct fib6_node));
 
        return fn;
index e05ecbb..7b7bd44 100644 (file)
@@ -72,20 +72,11 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
 
 static inline int ip6_output_finish(struct sk_buff *skb)
 {
-
        struct dst_entry *dst = skb->dst;
-       struct hh_cache *hh = dst->hh;
-
-       if (hh) {
-               int hh_alen;
-
-               read_lock_bh(&hh->hh_lock);
-               hh_alen = HH_DATA_ALIGN(hh->hh_len);
-               memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
-               read_unlock_bh(&hh->hh_lock);
-               skb_push(skb, hh->hh_len);
-               return hh->hh_output(skb);
-       } else if (dst->neighbour)
+
+       if (dst->hh)
+               return neigh_hh_output(dst->hh, skb);
+       else if (dst->neighbour)
                return dst->neighbour->output(skb);
 
        IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -624,13 +615,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                skb_shinfo(skb)->frag_list = NULL;
                /* BUILD HEADER */
 
+               *prevhdr = NEXTHDR_FRAGMENT;
                tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC);
                if (!tmp_hdr) {
                        IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
                        return -ENOMEM;
                }
 
-               *prevhdr = NEXTHDR_FRAGMENT;
                __skb_pull(skb, hlen);
                fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));
                skb->nh.raw = __skb_push(skb, hlen);
index 56ea928..6a9f616 100644 (file)
@@ -1667,8 +1667,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
 static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
                                        int nlen, void __user *oldval,
                                        size_t __user *oldlenp,
-                                       void __user *newval, size_t newlen,
-                                       void **context)
+                                       void __user *newval, size_t newlen)
 {
        struct net_device *dev = ctl->extra1;
        struct inet6_dev *idev;
@@ -1681,14 +1680,12 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
        switch (ctl->ctl_name) {
        case NET_NEIGH_REACHABLE_TIME:
                ret = sysctl_jiffies(ctl, name, nlen,
-                                    oldval, oldlenp, newval, newlen,
-                                    context);
+                                    oldval, oldlenp, newval, newlen);
                break;
        case NET_NEIGH_RETRANS_TIME_MS:
        case NET_NEIGH_REACHABLE_TIME_MS:
                 ret = sysctl_ms_jiffies(ctl, name, nlen,
-                                        oldval, oldlenp, newval, newlen,
-                                        context);
+                                        oldval, oldlenp, newval, newlen);
                 break;
        default:
                ret = 0;
index f63fb86..4eec4b3 100644 (file)
@@ -440,6 +440,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ipv6)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                   big jump. */
                                do {
@@ -477,6 +484,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           IP6T_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct ip6t_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -508,27 +522,6 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
        return 0;
 }
 
-static inline int
-standard_check(const struct ip6t_entry_target *t,
-              unsigned int max_offset)
-{
-       struct ip6t_standard_target *targ = (void *)t;
-
-       /* Check standard info. */
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
-               duprintf("ip6t_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       return 1;
-}
-
 static inline int
 check_match(struct ip6t_entry_match *m,
            const char *name,
@@ -616,12 +609,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
        if (ret)
                goto err;
 
-       if (t->u.kernel.target == &ip6t_standard_target) {
-               if (!standard_check(t, size)) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-       } else if (t->u.kernel.target->checkentry
+       if (t->u.kernel.target->checkentry
                   && !t->u.kernel.target->checkentry(name, e, target, t->data,
                                                      e->comefrom)) {
                duprintf("ip_tables: check failed for `%s'.\n",
@@ -758,17 +746,19 @@ translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0))
+               return -ELOOP;
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
                                check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0))
-               goto cleanup;
+       if (ret != 0) {
+               IP6T_ENTRY_ITERATE(entry0, newinfo->size,
+                                  cleanup_entry, &i);
+               return ret;
+       }
 
        /* And one copy for every other CPU */
        for_each_possible_cpu(i) {
@@ -777,9 +767,6 @@ translate_table(const char *name,
        }
 
        return 0;
-cleanup:
-       IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
-       return ret;
 }
 
 /* Gets counters. */
index c2e629d..4ae1b19 100644 (file)
@@ -854,7 +854,8 @@ back_from_confirm:
        }
 done:
        dst_release(dst);
-       release_sock(sk);
+       if (!inet->hdrincl)
+               release_sock(sk);
 out:   
        fl6_sock_release(flowlabel);
        return err<0?err:len;
index 01a5c52..12e426b 100644 (file)
@@ -50,7 +50,7 @@ static u32 xfrm6_tunnel_spi;
 #define XFRM6_TUNNEL_SPI_MIN   1
 #define XFRM6_TUNNEL_SPI_MAX   0xffffffff
 
-static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly;
+static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly;
 
 #define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256
 #define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256
@@ -180,7 +180,7 @@ try_next_2:;
        spi = 0;
        goto out;
 alloc_spi:
-       x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
+       x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC);
        if (!x6spi)
                goto out;
 
index d50a020..262bda8 100644 (file)
@@ -61,7 +61,7 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty);
 static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
 static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
 static void ircomm_tty_hangup(struct tty_struct *tty);
-static void ircomm_tty_do_softint(void *private_);
+static void ircomm_tty_do_softint(struct work_struct *work);
 static void ircomm_tty_shutdown(struct ircomm_tty_cb *self);
 static void ircomm_tty_stop(struct tty_struct *tty);
 
@@ -389,7 +389,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
                self->flow = FLOW_STOP;
 
                self->line = line;
-               INIT_WORK(&self->tqueue, ircomm_tty_do_softint, self);
+               INIT_WORK(&self->tqueue, ircomm_tty_do_softint);
                self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;
                self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED;
                self->close_delay = 5*HZ/10;
@@ -594,15 +594,16 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty)
 }
 
 /*
- * Function ircomm_tty_do_softint (private_)
+ * Function ircomm_tty_do_softint (work)
  *
  *    We use this routine to give the write wakeup to the user at at a
  *    safe time (as fast as possible after write have completed). This 
  *    can be compared to the Tx interrupt.
  */
-static void ircomm_tty_do_softint(void *private_)
+static void ircomm_tty_do_softint(struct work_struct *work)
 {
-       struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
+       struct ircomm_tty_cb *self =
+               container_of(work, struct ircomm_tty_cb, tqueue);
        struct tty_struct *tty;
        unsigned long flags;
        struct sk_buff *skb, *ctrl_skb;
index 197e3e7..75e39ea 100644 (file)
@@ -146,7 +146,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
  *    do something rational.
  */
 void ircomm_tty_set_termios(struct tty_struct *tty, 
-                           struct termios *old_termios)
+                           struct ktermios *old_termios)
 {
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
        unsigned int cflag = tty->termios->c_cflag;
index 252f110..03504f3 100644 (file)
@@ -1100,7 +1100,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
                        return -ENOMEM;
 
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve(tx_skb, TTP_MAX_HEADER);
+               skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
        } else {
                tx_skb = userdata;
                /*
@@ -1349,7 +1349,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
                        return -ENOMEM;
 
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve(tx_skb, TTP_MAX_HEADER);
+               skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
        } else {
                tx_skb = userdata;
                /*
index 0e1dbfb..5dd5094 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <net/xfrm.h>
+#include <linux/audit.h>
 
 #include <net/sock.h>
 
@@ -1420,6 +1421,9 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
        else
                err = xfrm_state_update(x);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);
+
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
@@ -1460,8 +1464,12 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
                err = -EPERM;
                goto out;
        }
-       
+
        err = xfrm_state_delete(x);
+
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
        if (err < 0)
                goto out;
 
@@ -1637,12 +1645,15 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
 {
        unsigned proto;
        struct km_event c;
+       struct xfrm_audit audit_info;
 
        proto = pfkey_satype2proto(hdr->sadb_msg_satype);
        if (proto == 0)
                return -EINVAL;
 
-       xfrm_state_flush(proto);
+       audit_info.loginuid = audit_get_loginuid(current->audit_context);
+       audit_info.secid = 0;
+       xfrm_state_flush(proto, &audit_info);
        c.data.proto = proto;
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
@@ -2205,6 +2216,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
                                 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_ADDSPD, err ? 0 : 1, xp, NULL);
+
        if (err)
                goto out;
 
@@ -2282,6 +2296,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
                                   &sel, tmp.security, 1);
        security_xfrm_policy_free(&tmp);
+
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
+
        if (xp == NULL)
                return -ENOENT;
 
@@ -2416,8 +2434,11 @@ static int key_notify_policy_flush(struct km_event *c)
 static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
        struct km_event c;
+       struct xfrm_audit audit_info;
 
-       xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN);
+       audit_info.loginuid = audit_get_loginuid(current->audit_context);
+       audit_info.secid = 0;
+       xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
        c.data.type = XFRM_POLICY_TYPE_MAIN;
        c.event = XFRM_MSG_FLUSHPOLICY;
        c.pid = hdr->sadb_msg_pid;
index eaa0f8a..9b02ec4 100644 (file)
@@ -108,7 +108,7 @@ static struct {
        size_t size;
 
        /* slab cache pointer */
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
 
        /* allocated slab cache + modules which uses this slab cache */
        int use;
@@ -147,7 +147,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name,
 {
        int ret = 0;
        char *cache_name;
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
 
        DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n",
               features, name, size);
@@ -226,7 +226,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_register_cache);
 /* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
 void nf_conntrack_unregister_cache(u_int32_t features)
 {
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
        char *name;
 
        /*
@@ -1093,7 +1093,7 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
                           get_order(sizeof(struct list_head) * size));
 }
 
-void nf_conntrack_flush()
+void nf_conntrack_flush(void)
 {
        nf_ct_iterate_cleanup(kill_all, NULL);
 }
index 588d379..9cbf926 100644 (file)
@@ -29,7 +29,7 @@
 LIST_HEAD(nf_conntrack_expect_list);
 EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
 
-kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
+struct kmem_cache *nf_conntrack_expect_cachep __read_mostly;
 static unsigned int nf_conntrack_expect_next_id;
 
 /* nf_conntrack_expect helper functions */
@@ -91,25 +91,28 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
 struct nf_conntrack_expect *
 find_expectation(const struct nf_conntrack_tuple *tuple)
 {
-       struct nf_conntrack_expect *i;
+       struct nf_conntrack_expect *exp;
+
+       exp = __nf_conntrack_expect_find(tuple);
+       if (!exp)
+               return NULL;
 
-       list_for_each_entry(i, &nf_conntrack_expect_list, list) {
        /* If master is not in hash table yet (ie. packet hasn't left
           this machine yet), how can other end know about expected?
           Hence these are not the droids you are looking for (if
           master ct never got confirmed, we'd hold a reference to it
           and weird things would happen to future packets). */
-               if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
-                   && nf_ct_is_confirmed(i->master)) {
-                       if (i->flags & NF_CT_EXPECT_PERMANENT) {
-                               atomic_inc(&i->use);
-                               return i;
-                       } else if (del_timer(&i->timeout)) {
-                               nf_ct_unlink_expect(i);
-                               return i;
-                       }
-               }
+       if (!nf_ct_is_confirmed(exp->master))
+               return NULL;
+
+       if (exp->flags & NF_CT_EXPECT_PERMANENT) {
+               atomic_inc(&exp->use);
+               return exp;
+       } else if (del_timer(&exp->timeout)) {
+               nf_ct_unlink_expect(exp);
+               return exp;
        }
+
        return NULL;
 }
 
index a98de0b..a5a6e19 100644 (file)
@@ -92,7 +92,7 @@ struct xt_hashlimit_htable {
 static DEFINE_SPINLOCK(hashlimit_lock);        /* protects htables list */
 static DEFINE_MUTEX(hlimit_mutex);     /* additional checkentry protection */
 static HLIST_HEAD(hashlimit_htables);
-static kmem_cache_t *hashlimit_cachep __read_mostly;
+static struct kmem_cache *hashlimit_cachep __read_mostly;
 
 static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
 {
index 3baafb1..276131f 100644 (file)
@@ -699,7 +699,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
 
 struct sock *netlink_getsockbyfilp(struct file *filp)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct sock *sock;
 
        if (!S_ISSOCK(inode->i_mode))
index b9b0374..548e4e6 100644 (file)
@@ -143,6 +143,13 @@ int genl_register_ops(struct genl_family *family, struct genl_ops *ops)
                goto errout;
        }
 
+       if (ops->dumpit)
+               ops->flags |= GENL_CMD_CAP_DUMP;
+       if (ops->doit)
+               ops->flags |= GENL_CMD_CAP_DO;
+       if (ops->policy)
+               ops->flags |= GENL_CMD_CAP_HASPOL;
+
        genl_lock();
        list_add_tail(&ops->ops_list, &family->ops_list);
        genl_unlock();
@@ -387,7 +394,7 @@ static void genl_rcv(struct sock *sk, int len)
 static struct genl_family genl_ctrl = {
        .id = GENL_ID_CTRL,
        .name = "nlctrl",
-       .version = 0x1,
+       .version = 0x2,
        .maxattr = CTRL_ATTR_MAX,
 };
 
@@ -425,15 +432,6 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
                        NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
                        NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
 
-                       if (ops->policy)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
-
-                       if (ops->doit)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
-
-                       if (ops->dumpit)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
-
                        nla_nest_end(skb, nest);
                }
 
index 08e68b6..da73e8a 100644 (file)
@@ -660,7 +660,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
        sll->sll_ifindex = dev->ifindex;
 
        h->tp_status = status;
-       mb();
+       smp_mb();
 
        {
                struct page *p_start, *p_end;
index dada34a..49effd9 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/freezer.h>
 #include <rxrpc/krxiod.h>
 #include <rxrpc/transport.h>
 #include <rxrpc/peer.h>
index cea4eb5..3ab0f77 100644 (file)
@@ -27,6 +27,7 @@
 #include <rxrpc/call.h>
 #include <linux/udp.h>
 #include <linux/ip.h>
+#include <linux/freezer.h>
 #include <net/sock.h>
 #include "internal.h"
 
index 3e74669..9a9b613 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
+#include <linux/freezer.h>
 #include <rxrpc/rxrpc.h>
 #include <rxrpc/krxtimod.h>
 #include <asm/errno.h>
index f59a2c4..c797d6a 100644 (file)
@@ -101,9 +101,10 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
        struct fw_head *head = (struct fw_head*)tp->root;
        struct fw_filter *f;
        int r;
-       u32 id = skb->mark & head->mask;
+       u32 id = skb->mark;
 
        if (head != NULL) {
+               id &= head->mask;
                for (f=head->ht[fw_hash(id)]; f; f=f->next) {
                        if (f->id == id) {
                                *res = f->res;
index ba82dfa..f79a4f3 100644 (file)
@@ -371,8 +371,6 @@ static void cbq_deactivate_class(struct cbq_class *this)
                                        return;
                                }
                        }
-
-                       cl = cl_prev->next_alive;
                        return;
                }
        } while ((cl_prev = cl) != q->active[prio]);
@@ -1258,6 +1256,8 @@ static unsigned int cbq_drop(struct Qdisc* sch)
                do {
                        if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) {
                                sch->q.qlen--;
+                               if (!cl->q->q.qlen)
+                                       cbq_deactivate_class(cl);
                                return len;
                        }
                } while ((cl = cl->next_alive) != cl_head);
@@ -1685,8 +1685,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 #endif
                }
                sch_tree_lock(sch);
-               *old = cl->q;
-               cl->q = new;
+               *old = xchg(&cl->q, new);
                qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
                qdisc_reset(*old);
                sch_tree_unlock(sch);
@@ -1704,6 +1703,14 @@ cbq_leaf(struct Qdisc *sch, unsigned long arg)
        return cl ? cl->q : NULL;
 }
 
+static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+       struct cbq_class *cl = (struct cbq_class *)arg;
+
+       if (cl->q->q.qlen == 0)
+               cbq_deactivate_class(cl);
+}
+
 static unsigned long cbq_get(struct Qdisc *sch, u32 classid)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1988,12 +1995,17 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
        struct cbq_class *cl = (struct cbq_class*)arg;
+       unsigned int qlen;
 
        if (cl->filters || cl->children || cl == &q->link)
                return -EBUSY;
 
        sch_tree_lock(sch);
 
+       qlen = cl->q->q.qlen;
+       qdisc_reset(cl->q);
+       qdisc_tree_decrease_qlen(cl->q, qlen);
+
        if (cl->next_alive)
                cbq_deactivate_class(cl);
 
@@ -2084,6 +2096,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 static struct Qdisc_class_ops cbq_class_ops = {
        .graft          =       cbq_graft,
        .leaf           =       cbq_leaf,
+       .qlen_notify    =       cbq_qlen_notify,
        .get            =       cbq_get,
        .put            =       cbq_put,
        .change         =       cbq_change_class,
index 215e68c..15f23c5 100644 (file)
@@ -147,6 +147,10 @@ struct htb_class {
        psched_tdiff_t mbuffer; /* max wait time */
        long tokens, ctokens;   /* current number of tokens */
        psched_time_t t_c;      /* checkpoint time */
+
+       int prio;               /* For parent to leaf return possible here */
+       int quantum;            /* we do backup. Finally full replacement  */
+                               /* of un.leaf originals should be done. */
 };
 
 /* TODO: maybe compute rate when size is too large .. or drop ? */
@@ -1271,6 +1275,38 @@ static void htb_destroy_filters(struct tcf_proto **fl)
        }
 }
 
+static inline int htb_parent_last_child(struct htb_class *cl)
+{
+       if (!cl->parent)
+               /* the root class */
+               return 0;
+
+       if (!(cl->parent->children.next == &cl->sibling &&
+               cl->parent->children.prev == &cl->sibling))
+               /* not the last child */
+               return 0;
+
+       return 1;
+}
+
+static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q)
+{
+       struct htb_class *parent = cl->parent;
+
+       BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
+
+       parent->level = 0;
+       memset(&parent->un.inner, 0, sizeof(parent->un.inner));
+       INIT_LIST_HEAD(&parent->un.leaf.drop_list);
+       parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
+       parent->un.leaf.quantum = parent->quantum;
+       parent->un.leaf.prio = parent->prio;
+       parent->tokens = parent->buffer;
+       parent->ctokens = parent->cbuffer;
+       PSCHED_GET_TIME(parent->t_c);
+       parent->cmode = HTB_CAN_SEND;
+}
+
 static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
 {
        struct htb_sched *q = qdisc_priv(sch);
@@ -1328,6 +1364,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)arg;
        unsigned int qlen;
+       struct Qdisc *new_q = NULL;
+       int last_child = 0;
 
        // TODO: why don't allow to delete subtree ? references ? does
        // tc subsys quarantee us that in htb_destroy it holds no class
@@ -1335,6 +1373,12 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
        if (!list_empty(&cl->children) || cl->filter_cnt)
                return -EBUSY;
 
+       if (!cl->level && htb_parent_last_child(cl)) {
+               new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                                               cl->parent->classid);
+               last_child = 1;
+       }
+
        sch_tree_lock(sch);
 
        /* delete from hash and active; remainder in destroy_class */
@@ -1349,6 +1393,9 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
        if (cl->prio_activity)
                htb_deactivate(q, cl);
 
+       if (last_child)
+               htb_parent_to_leaf(cl, new_q);
+
        if (--cl->refcnt == 0)
                htb_destroy_class(sch, cl);
 
@@ -1483,6 +1530,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        cl->un.leaf.quantum = hopt->quantum;
                if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
                        cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
+
+               /* backup for htb_parent_to_leaf */
+               cl->quantum = cl->un.leaf.quantum;
+               cl->prio = cl->un.leaf.prio;
        }
 
        cl->buffer = hopt->buffer;
index 39471d3..ad0057d 100644 (file)
@@ -61,7 +61,7 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal functions. */
-static void sctp_assoc_bh_rcv(struct sctp_association *asoc);
+static void sctp_assoc_bh_rcv(struct work_struct *work);
 
 
 /* 1st Level Abstractions. */
@@ -269,9 +269,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        /* Create an input queue.  */
        sctp_inq_init(&asoc->base.inqueue);
-       sctp_inq_set_th_handler(&asoc->base.inqueue,
-                                   (void (*)(void *))sctp_assoc_bh_rcv,
-                                   asoc);
+       sctp_inq_set_th_handler(&asoc->base.inqueue, sctp_assoc_bh_rcv);
 
        /* Create an output queue.  */
        sctp_outq_init(asoc, &asoc->outqueue);
@@ -946,8 +944,11 @@ out:
 }
 
 /* Do delayed input processing.  This is scheduled by sctp_rcv(). */
-static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
+static void sctp_assoc_bh_rcv(struct work_struct *work)
 {
+       struct sctp_association *asoc =
+               container_of(work, struct sctp_association,
+                            base.inqueue.immediate);
        struct sctp_endpoint *ep;
        struct sctp_chunk *chunk;
        struct sock *sk;
index 33a42e9..1297569 100644 (file)
@@ -61,7 +61,7 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers. */
-static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
+static void sctp_endpoint_bh_rcv(struct work_struct *work);
 
 /*
  * Initialize the base fields of the endpoint structure.
@@ -89,8 +89,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        sctp_inq_init(&ep->base.inqueue);
 
        /* Set its top-half handler */
-       sctp_inq_set_th_handler(&ep->base.inqueue,
-                               (void (*)(void *))sctp_endpoint_bh_rcv, ep);
+       sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv);
 
        /* Initialize the bind addr area */
        sctp_bind_addr_init(&ep->base.bind_addr, 0);
@@ -318,8 +317,11 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
 /* Do delayed input processing.  This is scheduled by sctp_rcv().
  * This may be called on BH or task time.
  */
-static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
+static void sctp_endpoint_bh_rcv(struct work_struct *work)
 {
+       struct sctp_endpoint *ep =
+               container_of(work, struct sctp_endpoint,
+                            base.inqueue.immediate);
        struct sctp_association *asoc;
        struct sock *sk;
        struct sctp_transport *transport;
index cf6deed..71b0746 100644 (file)
@@ -54,7 +54,7 @@ void sctp_inq_init(struct sctp_inq *queue)
        queue->in_progress = NULL;
 
        /* Create a task for delivering data.  */
-       INIT_WORK(&queue->immediate, NULL, NULL);
+       INIT_WORK(&queue->immediate, NULL);
 
        queue->malloced = 0;
 }
@@ -97,7 +97,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
         * on the BH related data structures.
         */
        list_add_tail(&chunk->list, &q->in_chunk_list);
-       q->immediate.func(q->immediate.data);
+       q->immediate.func(&q->immediate);
 }
 
 /* Extract a chunk from an SCTP inqueue.
@@ -205,9 +205,8 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
  * The intent is that this routine will pull stuff out of the
  * inqueue and process it.
  */
-void sctp_inq_set_th_handler(struct sctp_inq *q,
-                                void (*callback)(void *), void *arg)
+void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback)
 {
-       INIT_WORK(&q->immediate, callback, arg);
+       INIT_WORK(&q->immediate, callback);
 }
 
index 11f3b54..f2ba861 100644 (file)
@@ -79,8 +79,8 @@ static struct sctp_pf *sctp_pf_inet_specific;
 static struct sctp_af *sctp_af_v4_specific;
 static struct sctp_af *sctp_af_v6_specific;
 
-kmem_cache_t *sctp_chunk_cachep __read_mostly;
-kmem_cache_t *sctp_bucket_cachep __read_mostly;
+struct kmem_cache *sctp_chunk_cachep __read_mostly;
+struct kmem_cache *sctp_bucket_cachep __read_mostly;
 
 /* Return the address of the control sock. */
 struct sock *sctp_get_ctl_sock(void)
index 04954e5..30927d3 100644 (file)
@@ -65,7 +65,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
-extern kmem_cache_t *sctp_chunk_cachep;
+extern struct kmem_cache *sctp_chunk_cachep;
 
 SCTP_STATIC
 struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
@@ -979,7 +979,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
 {
        struct sctp_chunk *retval;
 
-       retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC);
+       retval = kmem_cache_alloc(sctp_chunk_cachep, GFP_ATOMIC);
 
        if (!retval)
                goto nodata;
index 02b2714..1e8132b 100644 (file)
@@ -107,7 +107,7 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
                              struct sctp_association *, sctp_socket_type_t);
 static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
 
-extern kmem_cache_t *sctp_bucket_cachep;
+extern struct kmem_cache *sctp_bucket_cachep;
 
 /* Get the sndbuf space available at the time on the association.  */
 static inline int sctp_wspace(struct sctp_association *asoc)
@@ -4989,7 +4989,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
 {
        struct sctp_bind_bucket *pp;
 
-       pp = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC);
+       pp = kmem_cache_alloc(sctp_bucket_cachep, GFP_ATOMIC);
        SCTP_DBG_OBJCNT_INC(bind_bucket);
        if (pp) {
                pp->port = snum;
index e8db547..4e39631 100644 (file)
@@ -230,13 +230,13 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
 
 #define SOCKFS_MAGIC 0x534F434B
 
-static kmem_cache_t *sock_inode_cachep __read_mostly;
+static struct kmem_cache *sock_inode_cachep __read_mostly;
 
 static struct inode *sock_alloc_inode(struct super_block *sb)
 {
        struct socket_alloc *ei;
 
-       ei = kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        init_waitqueue_head(&ei->socket.wait);
@@ -257,7 +257,7 @@ static void sock_destroy_inode(struct inode *inode)
                        container_of(inode, struct socket_alloc, vfs_inode));
 }
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
        struct socket_alloc *ei = (struct socket_alloc *)foo;
 
@@ -305,7 +305,14 @@ static struct file_system_type sock_fs_type = {
 
 static int sockfs_delete_dentry(struct dentry *dentry)
 {
-       return 1;
+       /*
+        * At creation time, we pretended this dentry was hashed
+        * (by clearing DCACHE_UNHASHED bit in d_flags)
+        * At delete time, we restore the truth : not hashed.
+        * (so that dput() can proceed correctly)
+        */
+       dentry->d_flags |= DCACHE_UNHASHED;
+       return 0;
 }
 static struct dentry_operations sockfs_dentry_operations = {
        .d_delete = sockfs_delete_dentry,
@@ -353,16 +360,22 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
 
        this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
        this.name = name;
-       this.hash = SOCK_INODE(sock)->i_ino;
+       this.hash = 0;
 
-       file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
-       if (unlikely(!file->f_dentry))
+       file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+       if (unlikely(!file->f_path.dentry))
                return -ENOMEM;
 
-       file->f_dentry->d_op = &sockfs_dentry_operations;
-       d_add(file->f_dentry, SOCK_INODE(sock));
-       file->f_vfsmnt = mntget(sock_mnt);
-       file->f_mapping = file->f_dentry->d_inode->i_mapping;
+       file->f_path.dentry->d_op = &sockfs_dentry_operations;
+       /*
+        * We dont want to push this dentry into global dentry hash table.
+        * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
+        * This permits a working /proc/$pid/fd/XXX on sockets
+        */
+       file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
+       file->f_path.mnt = mntget(sock_mnt);
+       file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
 
        sock->file = file;
        file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
@@ -400,7 +413,7 @@ static struct socket *sock_from_file(struct file *file, int *err)
        if (file->f_op == &socket_file_ops)
                return file->private_data;      /* set in sock_map_fd */
 
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        if (!S_ISSOCK(inode->i_mode)) {
                *err = -ENOTSOCK;
                return NULL;
index e5a84a4..e1a104a 100644 (file)
@@ -68,7 +68,7 @@ static struct rpc_credops gss_credops;
 #define GSS_CRED_SLACK         1024            /* XXX: unused */
 /* length of a krb5 verifier (48), plus data added before arguments when
  * using integrity (two 4-byte integers): */
-#define GSS_VERF_SLACK         56
+#define GSS_VERF_SLACK         100
 
 /* XXX this define must match the gssd define
 * as it is passed to gssd to signal the use of
@@ -94,46 +94,6 @@ struct gss_auth {
 static void gss_destroy_ctx(struct gss_cl_ctx *);
 static struct rpc_pipe_ops gss_upcall_ops;
 
-void
-print_hexl(u32 *p, u_int length, u_int offset)
-{
-       u_int i, j, jm;
-       u8 c, *cp;
-       
-       dprintk("RPC: print_hexl: length %d\n",length);
-       dprintk("\n");
-       cp = (u8 *) p;
-       
-       for (i = 0; i < length; i += 0x10) {
-               dprintk("  %04x: ", (u_int)(i + offset));
-               jm = length - i;
-               jm = jm > 16 ? 16 : jm;
-               
-               for (j = 0; j < jm; j++) {
-                       if ((j % 2) == 1)
-                               dprintk("%02x ", (u_int)cp[i+j]);
-                       else
-                               dprintk("%02x", (u_int)cp[i+j]);
-               }
-               for (; j < 16; j++) {
-                       if ((j % 2) == 1)
-                               dprintk("   ");
-                       else
-                               dprintk("  ");
-               }
-               dprintk(" ");
-               
-               for (j = 0; j < jm; j++) {
-                       c = cp[i+j];
-                       c = isprint(c) ? c : '.';
-                       dprintk("%c", c);
-               }
-               dprintk("\n");
-       }
-}
-
-EXPORT_SYMBOL(print_hexl);
-
 static inline struct gss_cl_ctx *
 gss_get_ctx(struct gss_cl_ctx *ctx)
 {
@@ -541,7 +501,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        if (!buf)
                goto out;
 
-       clnt = RPC_I(filp->f_dentry->d_inode)->private;
+       clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
        err = -EFAULT;
        if (copy_from_user(buf, src, mlen))
                goto err;
index e11a40b..d926cda 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/gss_krb5.h>
+#include <linux/sunrpc/xdr.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY        RPCDBG_AUTH
@@ -61,9 +62,6 @@ krb5_encrypt(
        u8 local_iv[16] = {0};
        struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
 
-       dprintk("RPC:      krb5_encrypt: input data:\n");
-       print_hexl((u32 *)in, length, 0);
-
        if (length % crypto_blkcipher_blocksize(tfm) != 0)
                goto out;
 
@@ -80,12 +78,9 @@ krb5_encrypt(
        sg_set_buf(sg, out, length);
 
        ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length);
-
-       dprintk("RPC:      krb5_encrypt: output data:\n");
-       print_hexl((u32 *)out, length, 0);
 out:
        dprintk("RPC:      krb5_encrypt returns %d\n",ret);
-       return(ret);
+       return ret;
 }
 
 EXPORT_SYMBOL(krb5_encrypt);
@@ -103,9 +98,6 @@ krb5_decrypt(
        u8 local_iv[16] = {0};
        struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
 
-       dprintk("RPC:      krb5_decrypt: input data:\n");
-       print_hexl((u32 *)in, length, 0);
-
        if (length % crypto_blkcipher_blocksize(tfm) != 0)
                goto out;
 
@@ -121,82 +113,13 @@ krb5_decrypt(
        sg_set_buf(sg, out, length);
 
        ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length);
-
-       dprintk("RPC:      krb5_decrypt: output_data:\n");
-       print_hexl((u32 *)out, length, 0);
 out:
        dprintk("RPC:      gss_k5decrypt returns %d\n",ret);
-       return(ret);
+       return ret;
 }
 
 EXPORT_SYMBOL(krb5_decrypt);
 
-static int
-process_xdr_buf(struct xdr_buf *buf, int offset, int len,
-               int (*actor)(struct scatterlist *, void *), void *data)
-{
-       int i, page_len, thislen, page_offset, ret = 0;
-       struct scatterlist      sg[1];
-
-       if (offset >= buf->head[0].iov_len) {
-               offset -= buf->head[0].iov_len;
-       } else {
-               thislen = buf->head[0].iov_len - offset;
-               if (thislen > len)
-                       thislen = len;
-               sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
-               ret = actor(sg, data);
-               if (ret)
-                       goto out;
-               offset = 0;
-               len -= thislen;
-       }
-       if (len == 0)
-               goto out;
-
-       if (offset >= buf->page_len) {
-               offset -= buf->page_len;
-       } else {
-               page_len = buf->page_len - offset;
-               if (page_len > len)
-                       page_len = len;
-               len -= page_len;
-               page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
-               i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
-               thislen = PAGE_CACHE_SIZE - page_offset;
-               do {
-                       if (thislen > page_len)
-                               thislen = page_len;
-                       sg->page = buf->pages[i];
-                       sg->offset = page_offset;
-                       sg->length = thislen;
-                       ret = actor(sg, data);
-                       if (ret)
-                               goto out;
-                       page_len -= thislen;
-                       i++;
-                       page_offset = 0;
-                       thislen = PAGE_CACHE_SIZE;
-               } while (page_len != 0);
-               offset = 0;
-       }
-       if (len == 0)
-               goto out;
-
-       if (offset < buf->tail[0].iov_len) {
-               thislen = buf->tail[0].iov_len - offset;
-               if (thislen > len)
-                       thislen = len;
-               sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
-               ret = actor(sg, data);
-               len -= thislen;
-       }
-       if (len != 0)
-               ret = -EINVAL;
-out:
-       return ret;
-}
-
 static int
 checksummer(struct scatterlist *sg, void *data)
 {
@@ -207,23 +130,13 @@ checksummer(struct scatterlist *sg, void *data)
 
 /* checksum the plaintext data and hdrlen bytes of the token header */
 s32
-make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
                   int body_offset, struct xdr_netobj *cksum)
 {
-       char                            *cksumname;
        struct hash_desc                desc; /* XXX add to ctx? */
        struct scatterlist              sg[1];
        int err;
 
-       switch (cksumtype) {
-               case CKSUMTYPE_RSA_MD5:
-                       cksumname = "md5";
-                       break;
-               default:
-                       dprintk("RPC:      krb5_make_checksum:"
-                               " unsupported checksum %d", cksumtype);
-                       return GSS_S_FAILURE;
-       }
        desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(desc.tfm))
                return GSS_S_FAILURE;
@@ -237,7 +150,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
        err = crypto_hash_update(&desc, sg, hdrlen);
        if (err)
                goto out;
-       err = process_xdr_buf(body, body_offset, body->len - body_offset,
+       err = xdr_process_buf(body, body_offset, body->len - body_offset,
                              checksummer, &desc);
        if (err)
                goto out;
@@ -335,7 +248,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
        desc.fragno = 0;
        desc.fraglen = 0;
 
-       ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
+       ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc);
        return ret;
 }
 
@@ -401,7 +314,7 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
        desc.desc.flags = 0;
        desc.fragno = 0;
        desc.fraglen = 0;
-       return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
+       return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc);
 }
 
 EXPORT_SYMBOL(gss_decrypt_xdr_buf);
index 754b8cd..05d4bee 100644 (file)
@@ -129,6 +129,7 @@ gss_import_sec_context_kerberos(const void *p,
 {
        const void *end = (const void *)((const char *)p + len);
        struct  krb5_ctx *ctx;
+       int tmp;
 
        if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
                goto out_err;
@@ -136,18 +137,23 @@ gss_import_sec_context_kerberos(const void *p,
        p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
        if (IS_ERR(p))
                goto out_err_free_ctx;
-       p = simple_get_bytes(p, end, &ctx->seed_init, sizeof(ctx->seed_init));
-       if (IS_ERR(p))
+       /* The downcall format was designed before we completely understood
+        * the uses of the context fields; so it includes some stuff we
+        * just give some minimal sanity-checking, and some we ignore
+        * completely (like the next twenty bytes): */
+       if (unlikely(p + 20 > end || p + 20 < p))
                goto out_err_free_ctx;
-       p = simple_get_bytes(p, end, ctx->seed, sizeof(ctx->seed));
+       p += 20;
+       p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
        if (IS_ERR(p))
                goto out_err_free_ctx;
-       p = simple_get_bytes(p, end, &ctx->signalg, sizeof(ctx->signalg));
-       if (IS_ERR(p))
+       if (tmp != SGN_ALG_DES_MAC_MD5)
                goto out_err_free_ctx;
-       p = simple_get_bytes(p, end, &ctx->sealalg, sizeof(ctx->sealalg));
+       p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
        if (IS_ERR(p))
                goto out_err_free_ctx;
+       if (tmp != SEAL_ALG_DES)
+               goto out_err_free_ctx;
        p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
        if (IS_ERR(p))
                goto out_err_free_ctx;
index 08601ee..d0bb506 100644 (file)
@@ -77,7 +77,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
                struct xdr_netobj *token)
 {
        struct krb5_ctx         *ctx = gss_ctx->internal_ctx_id;
-       s32                     checksum_type;
        char                    cksumdata[16];
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        unsigned char           *ptr, *krb5_hdr, *msg_start;
@@ -88,21 +87,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 
        now = get_seconds();
 
-       switch (ctx->signalg) {
-               case SGN_ALG_DES_MAC_MD5:
-                       checksum_type = CKSUMTYPE_RSA_MD5;
-                       break;
-               default:
-                       dprintk("RPC:      gss_krb5_seal: ctx->signalg %d not"
-                               " supported\n", ctx->signalg);
-                       goto out_err;
-       }
-       if (ctx->sealalg != SEAL_ALG_NONE && ctx->sealalg != SEAL_ALG_DES) {
-               dprintk("RPC:      gss_krb5_seal: ctx->sealalg %d not supported\n",
-                       ctx->sealalg);
-               goto out_err;
-       }
-
        token->len = g_token_size(&ctx->mech_used, 22);
 
        ptr = token->data;
@@ -115,37 +99,26 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
        krb5_hdr = ptr - 2;
        msg_start = krb5_hdr + 24;
 
-       *(__be16 *)(krb5_hdr + 2) = htons(ctx->signalg);
+       *(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
        memset(krb5_hdr + 4, 0xff, 4);
 
-       if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
-                       goto out_err;
-
-       switch (ctx->signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
-                                 md5cksum.data, md5cksum.len))
-                       goto out_err;
-               memcpy(krb5_hdr + 16,
-                      md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-                      KRB5_CKSUM_LENGTH);
-
-               dprintk("RPC:      make_seal_token: cksum data: \n");
-               print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
-               break;
-       default:
-               BUG();
-       }
+       if (make_checksum("md5", krb5_hdr, 8, text, 0, &md5cksum))
+               return GSS_S_FAILURE;
+
+       if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
+                         md5cksum.data, md5cksum.len))
+               return GSS_S_FAILURE;
+
+       memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+              KRB5_CKSUM_LENGTH);
 
        spin_lock(&krb5_seq_lock);
        seq_send = ctx->seq_send++;
        spin_unlock(&krb5_seq_lock);
 
-       if ((krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
-                              seq_send, krb5_hdr + 16, krb5_hdr + 8)))
-               goto out_err;
+       if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+                              ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))
+               return GSS_S_FAILURE;
 
-       return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
-out_err:
-       return GSS_S_FAILURE;
+       return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
 }
index 0828cf6..87f8977 100644 (file)
@@ -78,7 +78,6 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
        struct krb5_ctx         *ctx = gss_ctx->internal_ctx_id;
        int                     signalg;
        int                     sealalg;
-       s32                     checksum_type;
        char                    cksumdata[16];
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        s32                     now;
@@ -86,96 +85,54 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
        s32                     seqnum;
        unsigned char           *ptr = (unsigned char *)read_token->data;
        int                     bodysize;
-       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
 
        dprintk("RPC:      krb5_read_token\n");
 
        if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr,
                                        read_token->len))
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
        if ((*ptr++ != ((KG_TOK_MIC_MSG>>8)&0xff)) ||
            (*ptr++ != ( KG_TOK_MIC_MSG    &0xff))   )
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
        /* XXX sanity-check bodysize?? */
 
-       /* get the sign and seal algorithms */
-
        signalg = ptr[0] + (ptr[1] << 8);
-       sealalg = ptr[2] + (ptr[3] << 8);
+       if (signalg != SGN_ALG_DES_MAC_MD5)
+               return GSS_S_DEFECTIVE_TOKEN;
 
-       /* Sanity checks */
+       sealalg = ptr[2] + (ptr[3] << 8);
+       if (sealalg != SEAL_ALG_NONE)
+               return GSS_S_DEFECTIVE_TOKEN;
 
        if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
-               goto out;
-
-       if (sealalg != 0xffff)
-               goto out;
-
-       /* there are several mappings of seal algorithms to sign algorithms,
-          but few enough that we can try them all. */
-
-       if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
-           (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
-           (ctx->sealalg == SEAL_ALG_DES3KD &&
-            signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
-               goto out;
-
-       /* compute the checksum of the message */
-
-       /* initialize the the cksum */
-       switch (signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               checksum_type = CKSUMTYPE_RSA_MD5;
-               break;
-       default:
-               ret = GSS_S_DEFECTIVE_TOKEN;
-               goto out;
-       }
-
-       switch (signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               ret = make_checksum(checksum_type, ptr - 2, 8,
-                                        message_buffer, 0, &md5cksum);
-               if (ret)
-                       goto out;
-
-               ret = krb5_encrypt(ctx->seq, NULL, md5cksum.data,
-                                  md5cksum.data, 16);
-               if (ret)
-                       goto out;
-
-               if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
-                       ret = GSS_S_BAD_SIG;
-                       goto out;
-               }
-               break;
-       default:
-               ret = GSS_S_DEFECTIVE_TOKEN;
-               goto out;
-       }
+               return GSS_S_DEFECTIVE_TOKEN;
+
+       if (make_checksum("md5", ptr - 2, 8, message_buffer, 0, &md5cksum))
+               return GSS_S_FAILURE;
+
+       if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
+               return GSS_S_FAILURE;
+
+       if (memcmp(md5cksum.data + 8, ptr + 14, 8))
+               return GSS_S_BAD_SIG;
 
        /* it got through unscathed.  Make sure the context is unexpired */
 
        now = get_seconds();
 
-       ret = GSS_S_CONTEXT_EXPIRED;
        if (now > ctx->endtime)
-               goto out;
+               return GSS_S_CONTEXT_EXPIRED;
 
        /* do sequencing checks */
 
-       ret = GSS_S_BAD_SIG;
-       if ((ret = krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction,
-                                   &seqnum)))
-               goto out;
+       if (krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction, &seqnum))
+               return GSS_S_FAILURE;
 
        if ((ctx->initiate && direction != 0xff) ||
            (!ctx->initiate && direction != 0))
-               goto out;
+               return GSS_S_BAD_SIG;
 
-       ret = GSS_S_COMPLETE;
-out:
-       return ret;
+       return GSS_S_COMPLETE;
 }
index cc45c16..fe25b3d 100644 (file)
@@ -57,9 +57,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
                                        >>PAGE_CACHE_SHIFT;
                int offset = (buf->page_base + len - 1)
                                        & (PAGE_CACHE_SIZE - 1);
-               ptr = kmap_atomic(buf->pages[last], KM_SKB_SUNRPC_DATA);
+               ptr = kmap_atomic(buf->pages[last], KM_USER0);
                pad = *(ptr + offset);
-               kunmap_atomic(ptr, KM_SKB_SUNRPC_DATA);
+               kunmap_atomic(ptr, KM_USER0);
                goto out;
        } else
                len -= buf->page_len;
@@ -120,7 +120,6 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
                struct xdr_buf *buf, struct page **pages)
 {
        struct krb5_ctx         *kctx = ctx->internal_ctx_id;
-       s32                     checksum_type;
        char                    cksumdata[16];
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        int                     blocksize = 0, plainlen;
@@ -134,21 +133,6 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 
        now = get_seconds();
 
-       switch (kctx->signalg) {
-               case SGN_ALG_DES_MAC_MD5:
-                       checksum_type = CKSUMTYPE_RSA_MD5;
-                       break;
-               default:
-                       dprintk("RPC:      gss_krb5_seal: kctx->signalg %d not"
-                               " supported\n", kctx->signalg);
-                       goto out_err;
-       }
-       if (kctx->sealalg != SEAL_ALG_NONE && kctx->sealalg != SEAL_ALG_DES) {
-               dprintk("RPC:      gss_krb5_seal: kctx->sealalg %d not supported\n",
-                       kctx->sealalg);
-               goto out_err;
-       }
-
        blocksize = crypto_blkcipher_blocksize(kctx->enc);
        gss_krb5_add_padding(buf, offset, blocksize);
        BUG_ON((buf->len - offset) % blocksize);
@@ -175,37 +159,27 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
        /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
        krb5_hdr = ptr - 2;
        msg_start = krb5_hdr + 24;
-       /* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
 
-       *(__be16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+       *(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
        memset(krb5_hdr + 4, 0xff, 4);
-       *(__be16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+       *(__be16 *)(krb5_hdr + 4) = htons(SEAL_ALG_DES);
 
        make_confounder(msg_start, blocksize);
 
        /* XXXJBF: UGH!: */
        tmp_pages = buf->pages;
        buf->pages = pages;
-       if (make_checksum(checksum_type, krb5_hdr, 8, buf,
+       if (make_checksum("md5", krb5_hdr, 8, buf,
                                offset + headlen - blocksize, &md5cksum))
-               goto out_err;
+               return GSS_S_FAILURE;
        buf->pages = tmp_pages;
 
-       switch (kctx->signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
-                                 md5cksum.data, md5cksum.len))
-                       goto out_err;
-               memcpy(krb5_hdr + 16,
-                      md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-                      KRB5_CKSUM_LENGTH);
-
-               dprintk("RPC:      make_seal_token: cksum data: \n");
-               print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
-               break;
-       default:
-               BUG();
-       }
+       if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+                         md5cksum.data, md5cksum.len))
+               return GSS_S_FAILURE;
+       memcpy(krb5_hdr + 16,
+              md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+              KRB5_CKSUM_LENGTH);
 
        spin_lock(&krb5_seq_lock);
        seq_send = kctx->seq_send++;
@@ -215,15 +189,13 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
         * and encrypt at the same time: */
        if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
                               seq_send, krb5_hdr + 16, krb5_hdr + 8)))
-               goto out_err;
+               return GSS_S_FAILURE;
 
        if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
                                                                        pages))
-               goto out_err;
+               return GSS_S_FAILURE;
 
-       return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
-out_err:
-       return GSS_S_FAILURE;
+       return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
 }
 
 u32
@@ -232,7 +204,6 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
        struct krb5_ctx         *kctx = ctx->internal_ctx_id;
        int                     signalg;
        int                     sealalg;
-       s32                     checksum_type;
        char                    cksumdata[16];
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        s32                     now;
@@ -240,7 +211,6 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
        s32                     seqnum;
        unsigned char           *ptr;
        int                     bodysize;
-       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
        void                    *data_start, *orig_start;
        int                     data_len;
        int                     blocksize;
@@ -250,98 +220,58 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
        ptr = (u8 *)buf->head[0].iov_base + offset;
        if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
                                        buf->len - offset))
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
        if ((*ptr++ != ((KG_TOK_WRAP_MSG>>8)&0xff)) ||
            (*ptr++ !=  (KG_TOK_WRAP_MSG    &0xff))   )
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
        /* XXX sanity-check bodysize?? */
 
        /* get the sign and seal algorithms */
 
        signalg = ptr[0] + (ptr[1] << 8);
-       sealalg = ptr[2] + (ptr[3] << 8);
+       if (signalg != SGN_ALG_DES_MAC_MD5)
+               return GSS_S_DEFECTIVE_TOKEN;
 
-       /* Sanity checks */
+       sealalg = ptr[2] + (ptr[3] << 8);
+       if (sealalg != SEAL_ALG_DES)
+               return GSS_S_DEFECTIVE_TOKEN;
 
        if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
-               goto out;
-
-       if (sealalg == 0xffff)
-               goto out;
-
-       /* in the current spec, there is only one valid seal algorithm per
-          key type, so a simple comparison is ok */
-
-       if (sealalg != kctx->sealalg)
-               goto out;
-
-       /* there are several mappings of seal algorithms to sign algorithms,
-          but few enough that we can try them all. */
-
-       if ((kctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
-           (kctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
-           (kctx->sealalg == SEAL_ALG_DES3KD &&
-            signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
        if (gss_decrypt_xdr_buf(kctx->enc, buf,
                        ptr + 22 - (unsigned char *)buf->head[0].iov_base))
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
-       /* compute the checksum of the message */
+       if (make_checksum("md5", ptr - 2, 8, buf,
+                ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum))
+               return GSS_S_FAILURE;
 
-       /* initialize the the cksum */
-       switch (signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               checksum_type = CKSUMTYPE_RSA_MD5;
-               break;
-       default:
-               ret = GSS_S_DEFECTIVE_TOKEN;
-               goto out;
-       }
-
-       switch (signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               ret = make_checksum(checksum_type, ptr - 2, 8, buf,
-                        ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum);
-               if (ret)
-                       goto out;
-
-               ret = krb5_encrypt(kctx->seq, NULL, md5cksum.data,
-                                  md5cksum.data, md5cksum.len);
-               if (ret)
-                       goto out;
-
-               if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
-                       ret = GSS_S_BAD_SIG;
-                       goto out;
-               }
-               break;
-       default:
-               ret = GSS_S_DEFECTIVE_TOKEN;
-               goto out;
-       }
+       if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+                          md5cksum.data, md5cksum.len))
+               return GSS_S_FAILURE;
+
+       if (memcmp(md5cksum.data + 8, ptr + 14, 8))
+               return GSS_S_BAD_SIG;
 
        /* it got through unscathed.  Make sure the context is unexpired */
 
        now = get_seconds();
 
-       ret = GSS_S_CONTEXT_EXPIRED;
        if (now > kctx->endtime)
-               goto out;
+               return GSS_S_CONTEXT_EXPIRED;
 
        /* do sequencing checks */
 
-       ret = GSS_S_BAD_SIG;
-       if ((ret = krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
-                                   &seqnum)))
-               goto out;
+       if (krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
+                                   &seqnum))
+               return GSS_S_BAD_SIG;
 
        if ((kctx->initiate && direction != 0xff) ||
            (!kctx->initiate && direction != 0))
-               goto out;
+               return GSS_S_BAD_SIG;
 
        /* Copy the data back to the right position.  XXX: Would probably be
         * better to copy and encrypt at the same time. */
@@ -354,11 +284,8 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
        buf->head[0].iov_len -= (data_start - orig_start);
        buf->len -= (data_start - orig_start);
 
-       ret = GSS_S_DEFECTIVE_TOKEN;
        if (gss_krb5_remove_padding(buf, blocksize))
-               goto out;
+               return GSS_S_DEFECTIVE_TOKEN;
 
-       ret = GSS_S_COMPLETE;
-out:
-       return ret;
+       return GSS_S_COMPLETE;
 }
index d57f608..4146507 100644 (file)
@@ -82,133 +82,73 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
        return q;
 }
 
-static inline const void *
-get_key(const void *p, const void *end, struct crypto_blkcipher **res,
-       int *resalg)
-{
-       struct xdr_netobj       key = { 0 };
-       int                     setkey = 0;
-       char                    *alg_name;
-
-       p = simple_get_bytes(p, end, resalg, sizeof(*resalg));
-       if (IS_ERR(p))
-               goto out_err;
-       p = simple_get_netobj(p, end, &key);
-       if (IS_ERR(p))
-               goto out_err;
-
-       switch (*resalg) {
-               case NID_des_cbc:
-                       alg_name = "cbc(des)";
-                       setkey = 1;
-                       break;
-               case NID_cast5_cbc:
-                       /* XXXX here in name only, not used */
-                       alg_name = "cbc(cast5)";
-                       setkey = 0; /* XXX will need to set to 1 */
-                       break;
-               case NID_md5:
-                       if (key.len == 0) {
-                               dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n");
-                       }
-                       alg_name = "md5";
-                       setkey = 0;
-                       break;
-               default:
-                       dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg);
-                       goto out_err_free_key;
-       }
-       *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(*res)) {
-               printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name);
-               *res = NULL;
-               goto out_err_free_key;
-       }
-       if (setkey) {
-               if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
-                       printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name);
-                       goto out_err_free_tfm;
-               }
-       }
-
-       if(key.len > 0)
-               kfree(key.data);
-       return p;
-
-out_err_free_tfm:
-       crypto_free_blkcipher(*res);
-out_err_free_key:
-       if(key.len > 0)
-               kfree(key.data);
-       p = ERR_PTR(-EINVAL);
-out_err:
-       return p;
-}
-
 static int
 gss_import_sec_context_spkm3(const void *p, size_t len,
                                struct gss_ctx *ctx_id)
 {
        const void *end = (const void *)((const char *)p + len);
        struct  spkm3_ctx *ctx;
+       int     version;
 
        if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
                goto out_err;
 
+       p = simple_get_bytes(p, end, &version, sizeof(version));
+       if (IS_ERR(p))
+               goto out_err_free_ctx;
+       if (version != 1) {
+               dprintk("RPC: unknown spkm3 token format: obsolete nfs-utils?\n");
+               goto out_err_free_ctx;
+       }
+
        p = simple_get_netobj(p, end, &ctx->ctx_id);
        if (IS_ERR(p))
                goto out_err_free_ctx;
 
-       p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop));
+       p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
        if (IS_ERR(p))
                goto out_err_free_ctx_id;
 
        p = simple_get_netobj(p, end, &ctx->mech_used);
        if (IS_ERR(p))
-               goto out_err_free_mech;
+               goto out_err_free_ctx_id;
 
        p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
        if (IS_ERR(p))
                goto out_err_free_mech;
 
-       p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags));
+       p = simple_get_netobj(p, end, &ctx->conf_alg);
        if (IS_ERR(p))
                goto out_err_free_mech;
 
-       p = simple_get_netobj(p, end, &ctx->share_key);
-       if (IS_ERR(p))
-               goto out_err_free_s_key;
-
-       p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg);
+       p = simple_get_netobj(p, end, &ctx->derived_conf_key);
        if (IS_ERR(p))
-               goto out_err_free_s_key;
+               goto out_err_free_conf_alg;
 
-       p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg);
+       p = simple_get_netobj(p, end, &ctx->intg_alg);
        if (IS_ERR(p))
-               goto out_err_free_key1;
+               goto out_err_free_conf_key;
 
-       p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg));
+       p = simple_get_netobj(p, end, &ctx->derived_integ_key);
        if (IS_ERR(p))
-               goto out_err_free_key2;
-
-       p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg));
-       if (IS_ERR(p))
-               goto out_err_free_key2;
+               goto out_err_free_intg_alg;
 
        if (p != end)
-               goto out_err_free_key2;
+               goto out_err_free_intg_key;
 
        ctx_id->internal_ctx_id = ctx;
 
        dprintk("Successfully imported new spkm context.\n");
        return 0;
 
-out_err_free_key2:
-       crypto_free_blkcipher(ctx->derived_integ_key);
-out_err_free_key1:
-       crypto_free_blkcipher(ctx->derived_conf_key);
-out_err_free_s_key:
-       kfree(ctx->share_key.data);
+out_err_free_intg_key:
+       kfree(ctx->derived_integ_key.data);
+out_err_free_intg_alg:
+       kfree(ctx->intg_alg.data);
+out_err_free_conf_key:
+       kfree(ctx->derived_conf_key.data);
+out_err_free_conf_alg:
+       kfree(ctx->conf_alg.data);
 out_err_free_mech:
        kfree(ctx->mech_used.data);
 out_err_free_ctx_id:
@@ -220,13 +160,16 @@ out_err:
 }
 
 static void
-gss_delete_sec_context_spkm3(void *internal_ctx) {
+gss_delete_sec_context_spkm3(void *internal_ctx)
+{
        struct spkm3_ctx *sctx = internal_ctx;
 
-       crypto_free_blkcipher(sctx->derived_integ_key);
-       crypto_free_blkcipher(sctx->derived_conf_key);
-       kfree(sctx->share_key.data);
+       kfree(sctx->derived_integ_key.data);
+       kfree(sctx->intg_alg.data);
+       kfree(sctx->derived_conf_key.data);
+       kfree(sctx->conf_alg.data);
        kfree(sctx->mech_used.data);
+       kfree(sctx->ctx_id.data);
        kfree(sctx);
 }
 
@@ -238,7 +181,6 @@ gss_verify_mic_spkm3(struct gss_ctx         *ctx,
        u32 maj_stat = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
-       dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
        maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
        dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
@@ -253,10 +195,9 @@ gss_get_mic_spkm3(struct gss_ctx   *ctx,
        u32 err = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
-       dprintk("RPC: gss_get_mic_spkm3\n");
-
        err = spkm3_make_token(sctx, message_buffer,
-                             message_token, SPKM_MIC_TOK);
+                               message_token, SPKM_MIC_TOK);
+       dprintk("RPC: gss_get_mic_spkm3 returning %d\n", err);
        return err;
 }
 
index 18c7862..b179d58 100644 (file)
 #include <linux/sunrpc/gss_spkm3.h>
 #include <linux/random.h>
 #include <linux/crypto.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+#include <linux/sunrpc/xdr.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
+const struct xdr_netobj hmac_md5_oid = { 8, "\x2B\x06\x01\x05\x05\x08\x01\x01"};
+const struct xdr_netobj cast5_cbc_oid = {9, "\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A"};
+
 /*
  * spkm3_make_token()
  *
@@ -66,29 +72,23 @@ spkm3_make_token(struct spkm3_ctx *ctx,
        int                     ctxelen = 0, ctxzbit = 0;
        int                     md5elen = 0, md5zbit = 0;
 
-       dprintk("RPC: spkm3_make_token\n");
-
        now = jiffies;
 
        if (ctx->ctx_id.len != 16) {
                dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
-                       ctx->ctx_id.len);
+                               ctx->ctx_id.len);
                goto out_err;
        }
-               
-       switch (ctx->intg_alg) {
-               case NID_md5:
-                       checksum_type = CKSUMTYPE_RSA_MD5;
-                       break;
-               default:
-                       dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not"
-                               " supported\n", ctx->intg_alg);
-                       goto out_err;
-       }
-       /* XXX since we don't support WRAP, perhaps we don't care... */
-       if (ctx->conf_alg != NID_cast5_cbc) {
-               dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n",
-                       ctx->conf_alg);
+
+       if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
+               dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm."
+                               "only support hmac-md5 I-ALG.\n");
+               goto out_err;
+       } else
+               checksum_type = CKSUMTYPE_HMAC_MD5;
+
+       if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) {
+               dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n");
                goto out_err;
        }
 
@@ -96,10 +96,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
                /* Calculate checksum over the mic-header */
                asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
                spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
-                                        ctxelen, ctxzbit);
-
-               if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, 
-                                            text, 0, &md5cksum))
+                               ctxelen, ctxzbit);
+               if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key,
+                                       (char *)mic_hdr.data, mic_hdr.len,
+                                       text, 0, &md5cksum))
                        goto out_err;
 
                asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
@@ -121,7 +121,66 @@ spkm3_make_token(struct spkm3_ctx *ctx,
 
        return  GSS_S_COMPLETE;
 out_err:
+       if (md5cksum.data)
+               kfree(md5cksum.data);
+
        token->data = NULL;
        token->len = 0;
        return GSS_S_FAILURE;
 }
+
+static int
+spkm3_checksummer(struct scatterlist *sg, void *data)
+{
+       struct hash_desc *desc = data;
+
+       return crypto_hash_update(desc, sg, sg->length);
+}
+
+/* checksum the plaintext data and hdrlen bytes of the token header */
+s32
+make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+                   unsigned int hdrlen, struct xdr_buf *body,
+                   unsigned int body_offset, struct xdr_netobj *cksum)
+{
+       char                            *cksumname;
+       struct hash_desc                desc; /* XXX add to ctx? */
+       struct scatterlist              sg[1];
+       int err;
+
+       switch (cksumtype) {
+               case CKSUMTYPE_HMAC_MD5:
+                       cksumname = "md5";
+                       break;
+               default:
+                       dprintk("RPC:      spkm3_make_checksum:"
+                                       " unsupported checksum %d", cksumtype);
+                       return GSS_S_FAILURE;
+       }
+
+       if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE;
+
+       desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(desc.tfm))
+               return GSS_S_FAILURE;
+       cksum->len = crypto_hash_digestsize(desc.tfm);
+       desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+       err = crypto_hash_setkey(desc.tfm, key->data, key->len);
+       if (err)
+               goto out;
+
+       sg_set_buf(sg, header, hdrlen);
+       crypto_hash_update(&desc, sg, 1);
+
+       xdr_process_buf(body, body_offset, body->len - body_offset,
+                       spkm3_checksummer, &desc);
+       crypto_hash_final(&desc, cksum->data);
+
+out:
+       crypto_free_hash(desc.tfm);
+
+       return err ? GSS_S_FAILURE : 0;
+}
+
+EXPORT_SYMBOL(make_spkm3_checksum);
index 854a983..35188b6 100644 (file)
@@ -172,10 +172,10 @@ spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ct
        *(u8 *)hptr++ = zbit;
        memcpy(hptr, ctxdata, elen);
        hptr += elen;
-       *hdrlen = hptr - top; 
+       *hdrlen = hptr - top;
 }
-               
-/* 
+
+/*
  * spkm3_mic_innercontext_token()
  *
  * *tokp points to the beginning of the SPKM_MIC token  described 
index 8537f58..e54581c 100644 (file)
@@ -54,70 +54,70 @@ spkm3_read_token(struct spkm3_ctx *ctx,
                struct xdr_buf *message_buffer, /* signbuf */
                int toktype)
 {
+       s32                     checksum_type;
        s32                     code;
        struct xdr_netobj       wire_cksum = {.len =0, .data = NULL};
        char                    cksumdata[16];
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        unsigned char           *ptr = (unsigned char *)read_token->data;
-       unsigned char           *cksum;
+       unsigned char           *cksum;
        int                     bodysize, md5elen;
        int                     mic_hdrlen;
        u32                     ret = GSS_S_DEFECTIVE_TOKEN;
 
-       dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len);
-
        if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
                                        &bodysize, &ptr, read_token->len))
                goto out;
 
        /* decode the token */
 
-       if (toktype == SPKM_MIC_TOK) {
-
-               if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) 
-                       goto out;
-
-               if (*cksum++ != 0x03) {
-                       dprintk("RPC: spkm3_read_token BAD checksum type\n");
-                       goto out;
-               }
-               md5elen = *cksum++; 
-               cksum++;        /* move past the zbit */
-       
-               if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
-                       goto out;
-
-               /* HARD CODED FOR MD5 */
-
-               /* compute the checksum of the message.
-               *  ptr + 2 = start of header piece of checksum
-               *  mic_hdrlen + 2 = length of header piece of checksum
-               */
-               ret = GSS_S_DEFECTIVE_TOKEN;
-               code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, 
-                                       mic_hdrlen + 2, 
-                                       message_buffer, 0, &md5cksum);
-
-               if (code)
-                       goto out;
-
-               dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", 
-                       wire_cksum.len);
-               dprintk("          md5cksum.data\n");
-               print_hexl((u32 *) md5cksum.data, 16, 0);
-               dprintk("          cksum.data:\n");
-               print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0);
-
-               ret = GSS_S_BAD_SIG;
-               code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
-               if (code)
-                       goto out;
-
-       } else { 
-               dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype);
+       if (toktype != SPKM_MIC_TOK) {
+               dprintk("RPC: BAD SPKM3 token type: %d\n", toktype);
+               goto out;
+       }
+
+       if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum)))
+               goto out;
+
+       if (*cksum++ != 0x03) {
+               dprintk("RPC: spkm3_read_token BAD checksum type\n");
+               goto out;
+       }
+       md5elen = *cksum++;
+       cksum++;        /* move past the zbit */
+
+       if (!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
+               goto out;
+
+       /* HARD CODED FOR MD5 */
+
+       /* compute the checksum of the message.
+        * ptr + 2 = start of header piece of checksum
+        * mic_hdrlen + 2 = length of header piece of checksum
+        */
+       ret = GSS_S_DEFECTIVE_TOKEN;
+       if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
+               dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm\n");
+               goto out;
+       }
+
+       checksum_type = CKSUMTYPE_HMAC_MD5;
+
+       code = make_spkm3_checksum(checksum_type,
+               &ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2,
+               message_buffer, 0, &md5cksum);
+
+       if (code)
+               goto out;
+
+       ret = GSS_S_BAD_SIG;
+       code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
+       if (code) {
+               dprintk("RPC: bad MIC checksum\n");
                goto out;
        }
 
+
        /* XXX: need to add expiration and sequencing */
        ret = GSS_S_COMPLETE;
 out:
index 00cb388..80aff04 100644 (file)
@@ -284,8 +284,8 @@ static struct file_operations cache_file_operations;
 static struct file_operations content_file_operations;
 static struct file_operations cache_flush_operations;
 
-static void do_cache_clean(void *data);
-static DECLARE_WORK(cache_cleaner, do_cache_clean, NULL);
+static void do_cache_clean(struct work_struct *work);
+static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean);
 
 void cache_register(struct cache_detail *cd)
 {
@@ -337,7 +337,7 @@ void cache_register(struct cache_detail *cd)
        spin_unlock(&cache_list_lock);
 
        /* start the cleaning process */
-       schedule_work(&cache_cleaner);
+       schedule_delayed_work(&cache_cleaner, 0);
 }
 
 int cache_unregister(struct cache_detail *cd)
@@ -461,7 +461,7 @@ static int cache_clean(void)
 /*
  * We want to regularly clean the cache, so we need to schedule some work ...
  */
-static void do_cache_clean(void *data)
+static void do_cache_clean(struct work_struct *work)
 {
        int delay = 5;
        if (cache_clean() == -1)
@@ -670,7 +670,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
 {
        struct cache_reader *rp = filp->private_data;
        struct cache_request *rq;
-       struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+       struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
        int err;
 
        if (count == 0)
@@ -747,7 +747,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
            loff_t *ppos)
 {
        int err;
-       struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+       struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
 
        if (count == 0)
                return 0;
@@ -778,7 +778,7 @@ cache_poll(struct file *filp, poll_table *wait)
        unsigned int mask;
        struct cache_reader *rp = filp->private_data;
        struct cache_queue *cq;
-       struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+       struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
 
        poll_wait(filp, &queue_wait, wait);
 
@@ -1254,7 +1254,7 @@ static struct file_operations content_file_operations = {
 static ssize_t read_flush(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
-       struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+       struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
        char tbuf[20];
        unsigned long p = *ppos;
        int len;
@@ -1275,7 +1275,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
 static ssize_t write_flush(struct file * file, const char __user * buf,
                             size_t count, loff_t *ppos)
 {
-       struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+       struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
        char tbuf[20];
        char *ep;
        long flushtime;
index dfeea4f..aba528b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/utsname.h>
 #include <linux/workqueue.h>
 
@@ -141,6 +142,10 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        clnt->cl_vers     = version->number;
        clnt->cl_stats    = program->stats;
        clnt->cl_metrics  = rpc_alloc_iostats(clnt);
+       err = -ENOMEM;
+       if (clnt->cl_metrics == NULL)
+               goto out_no_stats;
+       clnt->cl_program  = program;
 
        if (!xprt_bound(clnt->cl_xprt))
                clnt->cl_autobind = 1;
@@ -173,6 +178,8 @@ out_no_auth:
                rpc_put_mount();
        }
 out_no_path:
+       rpc_free_iostats(clnt->cl_metrics);
+out_no_stats:
        if (clnt->cl_server != clnt->cl_inline_name)
                kfree(clnt->cl_server);
        kfree(clnt);
@@ -252,12 +259,19 @@ struct rpc_clnt *
 rpc_clone_client(struct rpc_clnt *clnt)
 {
        struct rpc_clnt *new;
+       int err = -ENOMEM;
 
        new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
        if (!new)
                goto out_no_clnt;
        atomic_set(&new->cl_count, 1);
        atomic_set(&new->cl_users, 0);
+       new->cl_metrics = rpc_alloc_iostats(clnt);
+       if (new->cl_metrics == NULL)
+               goto out_no_stats;
+       err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
+       if (err != 0)
+               goto out_no_path;
        new->cl_parent = clnt;
        atomic_inc(&clnt->cl_count);
        new->cl_xprt = xprt_get(clnt->cl_xprt);
@@ -265,16 +279,17 @@ rpc_clone_client(struct rpc_clnt *clnt)
        new->cl_autobind = 0;
        new->cl_oneshot = 0;
        new->cl_dead = 0;
-       if (!IS_ERR(new->cl_dentry))
-               dget(new->cl_dentry);
        rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
        if (new->cl_auth)
                atomic_inc(&new->cl_auth->au_count);
-       new->cl_metrics = rpc_alloc_iostats(clnt);
        return new;
+out_no_path:
+       rpc_free_iostats(new->cl_metrics);
+out_no_stats:
+       kfree(new);
 out_no_clnt:
-       printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
-       return ERR_PTR(-ENOMEM);
+       dprintk("RPC: %s returned error %d\n", __FUNCTION__, err);
+       return ERR_PTR(err);
 }
 
 /*
@@ -327,16 +342,14 @@ rpc_destroy_client(struct rpc_clnt *clnt)
                rpcauth_destroy(clnt->cl_auth);
                clnt->cl_auth = NULL;
        }
-       if (clnt->cl_parent != clnt) {
-               if (!IS_ERR(clnt->cl_dentry))
-                       dput(clnt->cl_dentry);
-               rpc_destroy_client(clnt->cl_parent);
-               goto out_free;
-       }
        if (!IS_ERR(clnt->cl_dentry)) {
                rpc_rmdir(clnt->cl_dentry);
                rpc_put_mount();
        }
+       if (clnt->cl_parent != clnt) {
+               rpc_destroy_client(clnt->cl_parent);
+               goto out_free;
+       }
        if (clnt->cl_server != clnt->cl_inline_name)
                kfree(clnt->cl_server);
 out_free:
@@ -466,10 +479,9 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 
        BUG_ON(flags & RPC_TASK_ASYNC);
 
-       status = -ENOMEM;
        task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
        if (task == NULL)
-               goto out;
+               return -ENOMEM;
 
        /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
        rpc_task_sigmask(task, &oldset);
@@ -478,15 +490,17 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 
        /* Set up the call info struct and execute the task */
        status = task->tk_status;
-       if (status == 0) {
-               atomic_inc(&task->tk_count);
-               status = rpc_execute(task);
-               if (status == 0)
-                       status = task->tk_status;
+       if (status != 0) {
+               rpc_release_task(task);
+               goto out;
        }
-       rpc_restore_sigmask(&oldset);
-       rpc_release_task(task);
+       atomic_inc(&task->tk_count);
+       status = rpc_execute(task);
+       if (status == 0)
+               status = task->tk_status;
+       rpc_put_task(task);
 out:
+       rpc_restore_sigmask(&oldset);
        return status;
 }
 
@@ -528,8 +542,7 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
        rpc_restore_sigmask(&oldset);           
        return status;
 out_release:
-       if (tk_ops->rpc_release != NULL)
-               tk_ops->rpc_release(data);
+       rpc_release_calldata(tk_ops, data);
        return status;
 }
 
@@ -581,7 +594,11 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr);
 char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format)
 {
        struct rpc_xprt *xprt = clnt->cl_xprt;
-       return xprt->ops->print_addr(xprt, format);
+
+       if (xprt->address_strings[format] != NULL)
+               return xprt->address_strings[format];
+       else
+               return "unprintable";
 }
 EXPORT_SYMBOL_GPL(rpc_peeraddr2str);
 
@@ -811,8 +828,10 @@ call_encode(struct rpc_task *task)
        if (encode == NULL)
                return;
 
+       lock_kernel();
        task->tk_status = rpcauth_wrap_req(task, encode, req, p,
                        task->tk_msg.rpc_argp);
+       unlock_kernel();
        if (task->tk_status == -ENOMEM) {
                /* XXX: Is this sane? */
                rpc_delay(task, 3*HZ);
@@ -1143,9 +1162,12 @@ call_decode(struct rpc_task *task)
 
        task->tk_action = rpc_exit_task;
 
-       if (decode)
+       if (decode) {
+               lock_kernel();
                task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
                                                      task->tk_msg.rpc_resp);
+               unlock_kernel();
+       }
        dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
                                        task->tk_status);
        return;
index e52afab..3946ec3 100644 (file)
@@ -101,14 +101,14 @@ void rpc_getport(struct rpc_task *task)
        /* Autobind on cloned rpc clients is discouraged */
        BUG_ON(clnt->cl_parent != clnt);
 
+       status = -EACCES;               /* tell caller to check again */
+       if (xprt_test_and_set_binding(xprt))
+               goto bailout_nowake;
+
        /* Put self on queue before sending rpcbind request, in case
         * pmap_getport_done completes before we return from rpc_run_task */
        rpc_sleep_on(&xprt->binding, task, NULL, NULL);
 
-       status = -EACCES;               /* tell caller to check again */
-       if (xprt_test_and_set_binding(xprt))
-               goto bailout_nofree;
-
        /* Someone else may have bound if we slept */
        status = 0;
        if (xprt_bound(xprt))
@@ -134,7 +134,7 @@ void rpc_getport(struct rpc_task *task)
        child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map);
        if (IS_ERR(child))
                goto bailout;
-       rpc_release_task(child);
+       rpc_put_task(child);
 
        task->tk_xprt->stat.bind_count++;
        return;
@@ -143,8 +143,9 @@ bailout:
        pmap_map_free(map);
        xprt_put(xprt);
 bailout_nofree:
-       task->tk_status = status;
        pmap_wake_portmap_waiters(xprt, status);
+bailout_nowake:
+       task->tk_status = status;
 }
 
 #ifdef CONFIG_ROOT_NFS
index 9a0b41a..89273d3 100644 (file)
@@ -33,7 +33,7 @@ static int rpc_mount_count;
 static struct file_system_type rpc_pipe_fs_type;
 
 
-static kmem_cache_t *rpc_inode_cachep __read_mostly;
+static struct kmem_cache *rpc_inode_cachep __read_mostly;
 
 #define RPC_UPCALL_TIMEOUT (30*HZ)
 
@@ -54,10 +54,11 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head,
 }
 
 static void
-rpc_timeout_upcall_queue(void *data)
+rpc_timeout_upcall_queue(struct work_struct *work)
 {
        LIST_HEAD(free_list);
-       struct rpc_inode *rpci = (struct rpc_inode *)data;
+       struct rpc_inode *rpci =
+               container_of(work, struct rpc_inode, queue_timeout.work);
        struct inode *inode = &rpci->vfs_inode;
        void (*destroy_msg)(struct rpc_pipe_msg *);
 
@@ -142,7 +143,7 @@ static struct inode *
 rpc_alloc_inode(struct super_block *sb)
 {
        struct rpc_inode *rpci;
-       rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, SLAB_KERNEL);
+       rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
        if (!rpci)
                return NULL;
        return &rpci->vfs_inode;
@@ -213,7 +214,7 @@ out:
 static ssize_t
 rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct rpc_inode *rpci = RPC_I(inode);
        struct rpc_pipe_msg *msg;
        int res = 0;
@@ -256,7 +257,7 @@ out_unlock:
 static ssize_t
 rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct rpc_inode *rpci = RPC_I(inode);
        int res;
 
@@ -274,7 +275,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
        struct rpc_inode *rpci;
        unsigned int mask = 0;
 
-       rpci = RPC_I(filp->f_dentry->d_inode);
+       rpci = RPC_I(filp->f_path.dentry->d_inode);
        poll_wait(filp, &rpci->waitq, wait);
 
        mask = POLLOUT | POLLWRNORM;
@@ -289,7 +290,7 @@ static int
 rpc_pipe_ioctl(struct inode *ino, struct file *filp,
                unsigned int cmd, unsigned long arg)
 {
-       struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+       struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
        int len;
 
        switch (cmd) {
@@ -823,7 +824,7 @@ static struct file_system_type rpc_pipe_fs_type = {
 };
 
 static void
-init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct rpc_inode *rpci = (struct rpc_inode *) foo;
 
@@ -837,7 +838,8 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                INIT_LIST_HEAD(&rpci->pipe);
                rpci->pipelen = 0;
                init_waitqueue_head(&rpci->waitq);
-               INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci);
+               INIT_DELAYED_WORK(&rpci->queue_timeout,
+                                   rpc_timeout_upcall_queue);
                rpci->ops = NULL;
        }
 }
index a1ab4ee..79bc4cd 100644 (file)
@@ -34,14 +34,14 @@ static int                  rpc_task_id;
 #define RPC_BUFFER_MAXSIZE     (2048)
 #define RPC_BUFFER_POOLSIZE    (8)
 #define RPC_TASK_POOLSIZE      (8)
-static kmem_cache_t    *rpc_task_slabp __read_mostly;
-static kmem_cache_t    *rpc_buffer_slabp __read_mostly;
+static struct kmem_cache       *rpc_task_slabp __read_mostly;
+static struct kmem_cache       *rpc_buffer_slabp __read_mostly;
 static mempool_t       *rpc_task_mempool __read_mostly;
 static mempool_t       *rpc_buffer_mempool __read_mostly;
 
 static void                    __rpc_default_timer(struct rpc_task *task);
 static void                    rpciod_killall(void);
-static void                    rpc_async_schedule(void *);
+static void                    rpc_async_schedule(struct work_struct *);
 
 /*
  * RPC tasks sit here while waiting for conditions to improve.
@@ -266,12 +266,28 @@ static int rpc_wait_bit_interruptible(void *word)
        return 0;
 }
 
+static void rpc_set_active(struct rpc_task *task)
+{
+       if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0)
+               return;
+       spin_lock(&rpc_sched_lock);
+#ifdef RPC_DEBUG
+       task->tk_magic = RPC_TASK_MAGIC_ID;
+       task->tk_pid = rpc_task_id++;
+#endif
+       /* Add to global list of all tasks */
+       list_add_tail(&task->tk_task, &all_tasks);
+       spin_unlock(&rpc_sched_lock);
+}
+
 /*
  * Mark an RPC call as having completed by clearing the 'active' bit
  */
-static inline void rpc_mark_complete_task(struct rpc_task *task)
+static void rpc_mark_complete_task(struct rpc_task *task)
 {
-       rpc_clear_active(task);
+       smp_mb__before_clear_bit();
+       clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate);
+       smp_mb__after_clear_bit();
        wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE);
 }
 
@@ -295,17 +311,19 @@ EXPORT_SYMBOL(__rpc_wait_for_completion_task);
  */
 static void rpc_make_runnable(struct rpc_task *task)
 {
-       int do_ret;
-
        BUG_ON(task->tk_timeout_fn);
-       do_ret = rpc_test_and_set_running(task);
        rpc_clear_queued(task);
-       if (do_ret)
+       if (rpc_test_and_set_running(task))
                return;
+       /* We might have raced */
+       if (RPC_IS_QUEUED(task)) {
+               rpc_clear_running(task);
+               return;
+       }
        if (RPC_IS_ASYNC(task)) {
                int status;
 
-               INIT_WORK(&task->u.tk_work, rpc_async_schedule, (void *)task);
+               INIT_WORK(&task->u.tk_work, rpc_async_schedule);
                status = queue_work(task->tk_workqueue, &task->u.tk_work);
                if (status < 0) {
                        printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
@@ -333,9 +351,6 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
                return;
        }
 
-       /* Mark the task as being activated if so needed */
-       rpc_set_active(task);
-
        __rpc_add_wait_queue(q, task);
 
        BUG_ON(task->tk_callback != NULL);
@@ -346,6 +361,9 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
 void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
                                rpc_action action, rpc_action timer)
 {
+       /* Mark the task as being activated if so needed */
+       rpc_set_active(task);
+
        /*
         * Protect the queue operations.
         */
@@ -409,16 +427,19 @@ __rpc_default_timer(struct rpc_task *task)
  */
 void rpc_wake_up_task(struct rpc_task *task)
 {
+       rcu_read_lock_bh();
        if (rpc_start_wakeup(task)) {
                if (RPC_IS_QUEUED(task)) {
                        struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
 
-                       spin_lock_bh(&queue->lock);
+                       /* Note: we're already in a bh-safe context */
+                       spin_lock(&queue->lock);
                        __rpc_do_wake_up_task(task);
-                       spin_unlock_bh(&queue->lock);
+                       spin_unlock(&queue->lock);
                }
                rpc_finish_wakeup(task);
        }
+       rcu_read_unlock_bh();
 }
 
 /*
@@ -481,14 +502,16 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
        struct rpc_task *task = NULL;
 
        dprintk("RPC:      wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue));
-       spin_lock_bh(&queue->lock);
+       rcu_read_lock_bh();
+       spin_lock(&queue->lock);
        if (RPC_IS_PRIORITY(queue))
                task = __rpc_wake_up_next_priority(queue);
        else {
                task_for_first(task, &queue->tasks[0])
                        __rpc_wake_up_task(task);
        }
-       spin_unlock_bh(&queue->lock);
+       spin_unlock(&queue->lock);
+       rcu_read_unlock_bh();
 
        return task;
 }
@@ -504,7 +527,8 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
        struct rpc_task *task, *next;
        struct list_head *head;
 
-       spin_lock_bh(&queue->lock);
+       rcu_read_lock_bh();
+       spin_lock(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
                list_for_each_entry_safe(task, next, head, u.tk_wait.list)
@@ -513,7 +537,8 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
                        break;
                head--;
        }
-       spin_unlock_bh(&queue->lock);
+       spin_unlock(&queue->lock);
+       rcu_read_unlock_bh();
 }
 
 /**
@@ -528,7 +553,8 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
        struct rpc_task *task, *next;
        struct list_head *head;
 
-       spin_lock_bh(&queue->lock);
+       rcu_read_lock_bh();
+       spin_lock(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
                list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
@@ -539,7 +565,8 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
                        break;
                head--;
        }
-       spin_unlock_bh(&queue->lock);
+       spin_unlock(&queue->lock);
+       rcu_read_unlock_bh();
 }
 
 static void __rpc_atrun(struct rpc_task *task)
@@ -561,7 +588,9 @@ void rpc_delay(struct rpc_task *task, unsigned long delay)
  */
 static void rpc_prepare_task(struct rpc_task *task)
 {
+       lock_kernel();
        task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
+       unlock_kernel();
 }
 
 /*
@@ -571,7 +600,9 @@ void rpc_exit_task(struct rpc_task *task)
 {
        task->tk_action = NULL;
        if (task->tk_ops->rpc_call_done != NULL) {
+               lock_kernel();
                task->tk_ops->rpc_call_done(task, task->tk_calldata);
+               unlock_kernel();
                if (task->tk_action != NULL) {
                        WARN_ON(RPC_ASSASSINATED(task));
                        /* Always release the RPC slot and buffer memory */
@@ -581,6 +612,15 @@ void rpc_exit_task(struct rpc_task *task)
 }
 EXPORT_SYMBOL(rpc_exit_task);
 
+void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
+{
+       if (ops->rpc_release != NULL) {
+               lock_kernel();
+               ops->rpc_release(calldata);
+               unlock_kernel();
+       }
+}
+
 /*
  * This is the RPC `scheduler' (or rather, the finite state machine).
  */
@@ -615,9 +655,7 @@ static int __rpc_execute(struct rpc_task *task)
                         */
                        save_callback=task->tk_callback;
                        task->tk_callback=NULL;
-                       lock_kernel();
                        save_callback(task);
-                       unlock_kernel();
                }
 
                /*
@@ -628,9 +666,7 @@ static int __rpc_execute(struct rpc_task *task)
                if (!RPC_IS_QUEUED(task)) {
                        if (task->tk_action == NULL)
                                break;
-                       lock_kernel();
                        task->tk_action(task);
-                       unlock_kernel();
                }
 
                /*
@@ -671,8 +707,6 @@ static int __rpc_execute(struct rpc_task *task)
        }
 
        dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status);
-       /* Wake up anyone who is waiting for task completion */
-       rpc_mark_complete_task(task);
        /* Release all resources associated with the task */
        rpc_release_task(task);
        return status;
@@ -695,9 +729,9 @@ rpc_execute(struct rpc_task *task)
        return __rpc_execute(task);
 }
 
-static void rpc_async_schedule(void *arg)
+static void rpc_async_schedule(struct work_struct *work)
 {
-       __rpc_execute((struct rpc_task *)arg);
+       __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
 }
 
 /**
@@ -786,15 +820,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
                        task->tk_flags |= RPC_TASK_NOINTR;
        }
 
-#ifdef RPC_DEBUG
-       task->tk_magic = RPC_TASK_MAGIC_ID;
-       task->tk_pid = rpc_task_id++;
-#endif
-       /* Add to global list of all tasks */
-       spin_lock(&rpc_sched_lock);
-       list_add_tail(&task->tk_task, &all_tasks);
-       spin_unlock(&rpc_sched_lock);
-
        BUG_ON(task->tk_ops == NULL);
 
        /* starting timestamp */
@@ -810,8 +835,9 @@ rpc_alloc_task(void)
        return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
 }
 
-static void rpc_free_task(struct rpc_task *task)
+static void rpc_free_task(struct rcu_head *rcu)
 {
+       struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
        dprintk("RPC: %4d freeing task\n", task->tk_pid);
        mempool_free(task, rpc_task_mempool);
 }
@@ -847,16 +873,34 @@ cleanup:
        goto out;
 }
 
-void rpc_release_task(struct rpc_task *task)
+
+void rpc_put_task(struct rpc_task *task)
 {
        const struct rpc_call_ops *tk_ops = task->tk_ops;
        void *calldata = task->tk_calldata;
 
+       if (!atomic_dec_and_test(&task->tk_count))
+               return;
+       /* Release resources */
+       if (task->tk_rqstp)
+               xprt_release(task);
+       if (task->tk_msg.rpc_cred)
+               rpcauth_unbindcred(task);
+       if (task->tk_client) {
+               rpc_release_client(task->tk_client);
+               task->tk_client = NULL;
+       }
+       if (task->tk_flags & RPC_TASK_DYNAMIC)
+               call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
+       rpc_release_calldata(tk_ops, calldata);
+}
+EXPORT_SYMBOL(rpc_put_task);
+
+void rpc_release_task(struct rpc_task *task)
+{
 #ifdef RPC_DEBUG
        BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
 #endif
-       if (!atomic_dec_and_test(&task->tk_count))
-               return;
        dprintk("RPC: %4d release task\n", task->tk_pid);
 
        /* Remove from global task list */
@@ -869,23 +913,13 @@ void rpc_release_task(struct rpc_task *task)
        /* Synchronously delete any running timer */
        rpc_delete_timer(task);
 
-       /* Release resources */
-       if (task->tk_rqstp)
-               xprt_release(task);
-       if (task->tk_msg.rpc_cred)
-               rpcauth_unbindcred(task);
-       if (task->tk_client) {
-               rpc_release_client(task->tk_client);
-               task->tk_client = NULL;
-       }
-
 #ifdef RPC_DEBUG
        task->tk_magic = 0;
 #endif
-       if (task->tk_flags & RPC_TASK_DYNAMIC)
-               rpc_free_task(task);
-       if (tk_ops->rpc_release)
-               tk_ops->rpc_release(calldata);
+       /* Wake up anyone who is waiting for task completion */
+       rpc_mark_complete_task(task);
+
+       rpc_put_task(task);
 }
 
 /**
@@ -902,8 +936,7 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
        struct rpc_task *task;
        task = rpc_new_task(clnt, flags, ops, data);
        if (task == NULL) {
-               if (ops->rpc_release != NULL)
-                       ops->rpc_release(data);
+               rpc_release_calldata(ops, data);
                return ERR_PTR(-ENOMEM);
        }
        atomic_inc(&task->tk_count);
index 2635c54..634885b 100644 (file)
@@ -16,7 +16,7 @@
 
 
 /**
- * skb_read_bits - copy some data bits from skb to internal buffer
+ * xdr_skb_read_bits - copy some data bits from skb to internal buffer
  * @desc: sk_buff copy helper
  * @to: copy destination
  * @len: number of bytes to copy
  * Possibly called several times to iterate over an sk_buff and copy
  * data out of it.
  */
-static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
 {
        if (len > desc->count)
                len = desc->count;
-       if (skb_copy_bits(desc->skb, desc->offset, to, len))
+       if (unlikely(skb_copy_bits(desc->skb, desc->offset, to, len)))
                return 0;
        desc->count -= len;
        desc->offset += len;
@@ -36,14 +36,14 @@ static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
 }
 
 /**
- * skb_read_and_csum_bits - copy and checksum from skb to buffer
+ * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer
  * @desc: sk_buff copy helper
  * @to: copy destination
  * @len: number of bytes to copy
  *
  * Same as skb_read_bits, but calculate a checksum at the same time.
  */
-static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+static size_t xdr_skb_read_and_csum_bits(struct xdr_skb_reader *desc, void *to, size_t len)
 {
        unsigned int pos;
        __wsum csum2;
@@ -66,7 +66,7 @@ static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
  * @copy_actor: virtual method for copying data
  *
  */
-ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, skb_reader_t *desc, skb_read_actor_t copy_actor)
+ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct xdr_skb_reader *desc, xdr_skb_read_actor copy_actor)
 {
        struct page     **ppage = xdr->pages;
        unsigned int    len, pglen = xdr->page_len;
@@ -148,7 +148,7 @@ out:
  */
 int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
 {
-       skb_reader_t    desc;
+       struct xdr_skb_reader   desc;
 
        desc.skb = skb;
        desc.offset = sizeof(struct udphdr);
@@ -158,7 +158,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
                goto no_checksum;
 
        desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
-       if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+       if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_and_csum_bits) < 0)
                return -1;
        if (desc.offset != skb->len) {
                __wsum csum2;
@@ -173,7 +173,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
                netdev_rx_csum_fault(skb->dev);
        return 0;
 no_checksum:
-       if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+       if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
                return -1;
        if (desc.count)
                return -1;
index 192dff5..d85fdde 100644 (file)
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(rpciod_down);
 EXPORT_SYMBOL(rpciod_up);
 EXPORT_SYMBOL(rpc_new_task);
 EXPORT_SYMBOL(rpc_wake_up_status);
-EXPORT_SYMBOL(rpc_release_task);
 
 /* RPC client functions */
 EXPORT_SYMBOL(rpc_clone_client);
@@ -139,6 +138,8 @@ EXPORT_SYMBOL(nlm_debug);
 extern int register_rpc_pipefs(void);
 extern void unregister_rpc_pipefs(void);
 extern struct cache_detail ip_map_cache;
+extern int init_socket_xprt(void);
+extern void cleanup_socket_xprt(void);
 
 static int __init
 init_sunrpc(void)
@@ -156,6 +157,7 @@ init_sunrpc(void)
        rpc_proc_init();
 #endif
        cache_register(&ip_map_cache);
+       init_socket_xprt();
 out:
        return err;
 }
@@ -163,6 +165,7 @@ out:
 static void __exit
 cleanup_sunrpc(void)
 {
+       cleanup_socket_xprt();
        unregister_rpc_pipefs();
        rpc_destroy_mempool();
        if (cache_unregister(&ip_map_cache))
index ee9bb15..c7bb5f7 100644 (file)
@@ -119,7 +119,8 @@ EXPORT_SYMBOL(svc_auth_unregister);
 #define        DN_HASHMASK     (DN_HASHMAX-1)
 
 static struct hlist_head       auth_domain_table[DN_HASHMAX];
-static spinlock_t      auth_domain_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t      auth_domain_lock =
+       __SPIN_LOCK_UNLOCKED(auth_domain_lock);
 
 void auth_domain_put(struct auth_domain *dom)
 {
index 64ca1f6..99f54fb 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/file.h>
+#include <linux/freezer.h>
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
@@ -84,6 +85,35 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req);
  */
 static int svc_conn_age_period = 6*60;
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static struct lock_class_key svc_key[2];
+static struct lock_class_key svc_slock_key[2];
+
+static inline void svc_reclassify_socket(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       BUG_ON(sk->sk_lock.owner != NULL);
+       switch (sk->sk_family) {
+       case AF_INET:
+               sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD",
+                   &svc_slock_key[0], "sk_lock-AF_INET-NFSD", &svc_key[0]);
+               break;
+
+       case AF_INET6:
+               sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFSD",
+                   &svc_slock_key[1], "sk_lock-AF_INET6-NFSD", &svc_key[1]);
+               break;
+
+       default:
+               BUG();
+       }
+}
+#else
+static inline void svc_reclassify_socket(struct socket *sock)
+{
+}
+#endif
+
 /*
  * Queue up an idle server thread.  Must have pool->sp_lock held.
  * Note: this is really a stack rather than a queue, so that we only
@@ -1556,6 +1586,8 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
        if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
                return error;
 
+       svc_reclassify_socket(sock);
+
        if (type == SOCK_STREAM)
                sock->sk->sk_reuse = 1; /* allow address reuse */
        error = kernel_bind(sock, (struct sockaddr *) sin,
index d89b048..82b2752 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/stats.h>
-#include <linux/sunrpc/xprt.h>
 
 /*
  * Declare the debug flags here
@@ -119,11 +118,6 @@ done:
 }
 
 
-static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
-static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
-static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
-static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
-
 static ctl_table debug_table[] = {
        {
                .ctl_name       = CTL_RPCDEBUG,
@@ -157,50 +151,6 @@ static ctl_table debug_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dodebug
        }, 
-       {
-               .ctl_name       = CTL_SLOTTABLE_UDP,
-               .procname       = "udp_slot_table_entries",
-               .data           = &xprt_udp_slot_table_entries,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &min_slot_table_size,
-               .extra2         = &max_slot_table_size
-       },
-       {
-               .ctl_name       = CTL_SLOTTABLE_TCP,
-               .procname       = "tcp_slot_table_entries",
-               .data           = &xprt_tcp_slot_table_entries,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &min_slot_table_size,
-               .extra2         = &max_slot_table_size
-       },
-       {
-               .ctl_name       = CTL_MIN_RESVPORT,
-               .procname       = "min_resvport",
-               .data           = &xprt_min_resvport,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &xprt_min_resvport_limit,
-               .extra2         = &xprt_max_resvport_limit
-       },
-       {
-               .ctl_name       = CTL_MAX_RESVPORT,
-               .procname       = "max_resvport",
-               .data           = &xprt_max_resvport,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &xprt_min_resvport_limit,
-               .extra2         = &xprt_max_resvport_limit
-       },
        { .ctl_name = 0 }
 };
 
index 9022eb8..a0af250 100644 (file)
@@ -640,41 +640,30 @@ xdr_buf_from_iov(struct kvec *iov, struct xdr_buf *buf)
        buf->buflen = buf->len = iov->iov_len;
 }
 
-/* Sets subiov to the intersection of iov with the buffer of length len
- * starting base bytes after iov.  Indicates empty intersection by setting
- * length of subiov to zero.  Decrements len by length of subiov, sets base
- * to zero (or decrements it by length of iov if subiov is empty). */
-static void
-iov_subsegment(struct kvec *iov, struct kvec *subiov, int *base, int *len)
-{
-       if (*base > iov->iov_len) {
-               subiov->iov_base = NULL;
-               subiov->iov_len = 0;
-               *base -= iov->iov_len;
-       } else {
-               subiov->iov_base = iov->iov_base + *base;
-               subiov->iov_len = min(*len, (int)iov->iov_len - *base);
-               *base = 0;
-       }
-       *len -= subiov->iov_len; 
-}
-
 /* Sets subbuf to the portion of buf of length len beginning base bytes
  * from the start of buf. Returns -1 if base of length are out of bounds. */
 int
 xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
-                       int base, int len)
+                       unsigned int base, unsigned int len)
 {
-       int i;
-
        subbuf->buflen = subbuf->len = len;
-       iov_subsegment(buf->head, subbuf->head, &base, &len);
+       if (base < buf->head[0].iov_len) {
+               subbuf->head[0].iov_base = buf->head[0].iov_base + base;
+               subbuf->head[0].iov_len = min_t(unsigned int, len,
+                                               buf->head[0].iov_len - base);
+               len -= subbuf->head[0].iov_len;
+               base = 0;
+       } else {
+               subbuf->head[0].iov_base = NULL;
+               subbuf->head[0].iov_len = 0;
+               base -= buf->head[0].iov_len;
+       }
 
        if (base < buf->page_len) {
-               i = (base + buf->page_base) >> PAGE_CACHE_SHIFT;
-               subbuf->pages = &buf->pages[i];
-               subbuf->page_base = (base + buf->page_base) & ~PAGE_CACHE_MASK;
-               subbuf->page_len = min((int)buf->page_len - base, len);
+               subbuf->page_len = min(buf->page_len - base, len);
+               base += buf->page_base;
+               subbuf->page_base = base & ~PAGE_CACHE_MASK;
+               subbuf->pages = &buf->pages[base >> PAGE_CACHE_SHIFT];
                len -= subbuf->page_len;
                base = 0;
        } else {
@@ -682,66 +671,85 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
                subbuf->page_len = 0;
        }
 
-       iov_subsegment(buf->tail, subbuf->tail, &base, &len);
+       if (base < buf->tail[0].iov_len) {
+               subbuf->tail[0].iov_base = buf->tail[0].iov_base + base;
+               subbuf->tail[0].iov_len = min_t(unsigned int, len,
+                                               buf->tail[0].iov_len - base);
+               len -= subbuf->tail[0].iov_len;
+               base = 0;
+       } else {
+               subbuf->tail[0].iov_base = NULL;
+               subbuf->tail[0].iov_len = 0;
+               base -= buf->tail[0].iov_len;
+       }
+
        if (base || len)
                return -1;
        return 0;
 }
 
-/* obj is assumed to point to allocated memory of size at least len: */
-int
-read_bytes_from_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len)
+static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len)
 {
-       struct xdr_buf subbuf;
-       int this_len;
-       int status;
+       unsigned int this_len;
 
-       status = xdr_buf_subsegment(buf, &subbuf, base, len);
-       if (status)
-               goto out;
-       this_len = min(len, (int)subbuf.head[0].iov_len);
-       memcpy(obj, subbuf.head[0].iov_base, this_len);
+       this_len = min_t(unsigned int, len, subbuf->head[0].iov_len);
+       memcpy(obj, subbuf->head[0].iov_base, this_len);
        len -= this_len;
        obj += this_len;
-       this_len = min(len, (int)subbuf.page_len);
+       this_len = min_t(unsigned int, len, subbuf->page_len);
        if (this_len)
-               _copy_from_pages(obj, subbuf.pages, subbuf.page_base, this_len);
+               _copy_from_pages(obj, subbuf->pages, subbuf->page_base, this_len);
        len -= this_len;
        obj += this_len;
-       this_len = min(len, (int)subbuf.tail[0].iov_len);
-       memcpy(obj, subbuf.tail[0].iov_base, this_len);
-out:
-       return status;
+       this_len = min_t(unsigned int, len, subbuf->tail[0].iov_len);
+       memcpy(obj, subbuf->tail[0].iov_base, this_len);
 }
 
 /* obj is assumed to point to allocated memory of size at least len: */
-int
-write_bytes_to_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len)
+int read_bytes_from_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, unsigned int len)
 {
        struct xdr_buf subbuf;
-       int this_len;
        int status;
 
        status = xdr_buf_subsegment(buf, &subbuf, base, len);
-       if (status)
-               goto out;
-       this_len = min(len, (int)subbuf.head[0].iov_len);
-       memcpy(subbuf.head[0].iov_base, obj, this_len);
+       if (status != 0)
+               return status;
+       __read_bytes_from_xdr_buf(&subbuf, obj, len);
+       return 0;
+}
+
+static void __write_bytes_to_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len)
+{
+       unsigned int this_len;
+
+       this_len = min_t(unsigned int, len, subbuf->head[0].iov_len);
+       memcpy(subbuf->head[0].iov_base, obj, this_len);
        len -= this_len;
        obj += this_len;
-       this_len = min(len, (int)subbuf.page_len);
+       this_len = min_t(unsigned int, len, subbuf->page_len);
        if (this_len)
-               _copy_to_pages(subbuf.pages, subbuf.page_base, obj, this_len);
+               _copy_to_pages(subbuf->pages, subbuf->page_base, obj, this_len);
        len -= this_len;
        obj += this_len;
-       this_len = min(len, (int)subbuf.tail[0].iov_len);
-       memcpy(subbuf.tail[0].iov_base, obj, this_len);
-out:
-       return status;
+       this_len = min_t(unsigned int, len, subbuf->tail[0].iov_len);
+       memcpy(subbuf->tail[0].iov_base, obj, this_len);
+}
+
+/* obj is assumed to point to allocated memory of size at least len: */
+int write_bytes_to_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, unsigned int len)
+{
+       struct xdr_buf subbuf;
+       int status;
+
+       status = xdr_buf_subsegment(buf, &subbuf, base, len);
+       if (status != 0)
+               return status;
+       __write_bytes_to_xdr_buf(&subbuf, obj, len);
+       return 0;
 }
 
 int
-xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
+xdr_decode_word(struct xdr_buf *buf, unsigned int base, u32 *obj)
 {
        __be32  raw;
        int     status;
@@ -754,7 +762,7 @@ xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
 }
 
 int
-xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
+xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj)
 {
        __be32  raw = htonl(obj);
 
@@ -765,44 +773,37 @@ xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
  * entirely in the head or the tail, set object to point to it; otherwise
  * try to find space for it at the end of the tail, copy it there, and
  * set obj to point to it. */
-int
-xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, int offset)
+int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset)
 {
-       u32     tail_offset = buf->head[0].iov_len + buf->page_len;
-       u32     obj_end_offset;
+       struct xdr_buf subbuf;
 
        if (xdr_decode_word(buf, offset, &obj->len))
-               goto out;
-       obj_end_offset = offset + 4 + obj->len;
-
-       if (obj_end_offset <= buf->head[0].iov_len) {
-               /* The obj is contained entirely in the head: */
-               obj->data = buf->head[0].iov_base + offset + 4;
-       } else if (offset + 4 >= tail_offset) {
-               if (obj_end_offset - tail_offset
-                               > buf->tail[0].iov_len)
-                       goto out;
-               /* The obj is contained entirely in the tail: */
-               obj->data = buf->tail[0].iov_base
-                       + offset - tail_offset + 4;
-       } else {
-               /* use end of tail as storage for obj:
-                * (We don't copy to the beginning because then we'd have
-                * to worry about doing a potentially overlapping copy.
-                * This assumes the object is at most half the length of the
-                * tail.) */
-               if (obj->len > buf->tail[0].iov_len)
-                       goto out;
-               obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len - 
-                               obj->len;
-               if (read_bytes_from_xdr_buf(buf, offset + 4,
-                                       obj->data, obj->len))
-                       goto out;
+               return -EFAULT;
+       if (xdr_buf_subsegment(buf, &subbuf, offset + 4, obj->len))
+               return -EFAULT;
 
-       }
+       /* Is the obj contained entirely in the head? */
+       obj->data = subbuf.head[0].iov_base;
+       if (subbuf.head[0].iov_len == obj->len)
+               return 0;
+       /* ..or is the obj contained entirely in the tail? */
+       obj->data = subbuf.tail[0].iov_base;
+       if (subbuf.tail[0].iov_len == obj->len)
+               return 0;
+
+       /* use end of tail as storage for obj:
+        * (We don't copy to the beginning because then we'd have
+        * to worry about doing a potentially overlapping copy.
+        * This assumes the object is at most half the length of the
+        * tail.) */
+       if (obj->len > buf->buflen - buf->len)
+               return -ENOMEM;
+       if (buf->tail[0].iov_len != 0)
+               obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len;
+       else
+               obj->data = buf->head[0].iov_base + buf->head[0].iov_len;
+       __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len);
        return 0;
-out:
-       return -1;
 }
 
 /* Returns 0 on success, or else a negative error code. */
@@ -1020,3 +1021,71 @@ xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
 
        return xdr_xcode_array2(buf, base, desc, 1);
 }
+
+int
+xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len,
+                int (*actor)(struct scatterlist *, void *), void *data)
+{
+       int i, ret = 0;
+       unsigned page_len, thislen, page_offset;
+       struct scatterlist      sg[1];
+
+       if (offset >= buf->head[0].iov_len) {
+               offset -= buf->head[0].iov_len;
+       } else {
+               thislen = buf->head[0].iov_len - offset;
+               if (thislen > len)
+                       thislen = len;
+               sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
+               ret = actor(sg, data);
+               if (ret)
+                       goto out;
+               offset = 0;
+               len -= thislen;
+       }
+       if (len == 0)
+               goto out;
+
+       if (offset >= buf->page_len) {
+               offset -= buf->page_len;
+       } else {
+               page_len = buf->page_len - offset;
+               if (page_len > len)
+                       page_len = len;
+               len -= page_len;
+               page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
+               i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
+               thislen = PAGE_CACHE_SIZE - page_offset;
+               do {
+                       if (thislen > page_len)
+                               thislen = page_len;
+                       sg->page = buf->pages[i];
+                       sg->offset = page_offset;
+                       sg->length = thislen;
+                       ret = actor(sg, data);
+                       if (ret)
+                               goto out;
+                       page_len -= thislen;
+                       i++;
+                       page_offset = 0;
+                       thislen = PAGE_CACHE_SIZE;
+               } while (page_len != 0);
+               offset = 0;
+       }
+       if (len == 0)
+               goto out;
+       if (offset < buf->tail[0].iov_len) {
+               thislen = buf->tail[0].iov_len - offset;
+               if (thislen > len)
+                       thislen = len;
+               sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
+               ret = actor(sg, data);
+               len -= thislen;
+       }
+       if (len != 0)
+               ret = -EINVAL;
+out:
+       return ret;
+}
+EXPORT_SYMBOL(xdr_process_buf);
+
index 8085747..7a3999f 100644 (file)
@@ -459,7 +459,6 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
                if (to->to_maxval && req->rq_timeout >= to->to_maxval)
                        req->rq_timeout = to->to_maxval;
                req->rq_retries++;
-               pprintk("RPC: %lu retrans\n", jiffies);
        } else {
                req->rq_timeout = to->to_initval;
                req->rq_retries = 0;
@@ -468,7 +467,6 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
                spin_lock_bh(&xprt->transport_lock);
                rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
                spin_unlock_bh(&xprt->transport_lock);
-               pprintk("RPC: %lu timeout\n", jiffies);
                status = -ETIMEDOUT;
        }
 
@@ -479,9 +477,10 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
        return status;
 }
 
-static void xprt_autoclose(void *args)
+static void xprt_autoclose(struct work_struct *work)
 {
-       struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+       struct rpc_xprt *xprt =
+               container_of(work, struct rpc_xprt, task_cleanup);
 
        xprt_disconnect(xprt);
        xprt->ops->close(xprt);
@@ -891,39 +890,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
  */
 struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
 {
-       int result;
        struct rpc_xprt *xprt;
        struct rpc_rqst *req;
 
-       if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) {
-               dprintk("RPC:      xprt_create_transport: no memory\n");
-               return ERR_PTR(-ENOMEM);
-       }
-       if (size <= sizeof(xprt->addr)) {
-               memcpy(&xprt->addr, ap, size);
-               xprt->addrlen = size;
-       } else {
-               kfree(xprt);
-               dprintk("RPC:      xprt_create_transport: address too large\n");
-               return ERR_PTR(-EBADF);
-       }
-
        switch (proto) {
        case IPPROTO_UDP:
-               result = xs_setup_udp(xprt, to);
+               xprt = xs_setup_udp(ap, size, to);
                break;
        case IPPROTO_TCP:
-               result = xs_setup_tcp(xprt, to);
+               xprt = xs_setup_tcp(ap, size, to);
                break;
        default:
                printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
                                proto);
                return ERR_PTR(-EIO);
        }
-       if (result) {
-               kfree(xprt);
-               dprintk("RPC:      xprt_create_transport: failed, %d\n", result);
-               return ERR_PTR(result);
+       if (IS_ERR(xprt)) {
+               dprintk("RPC:      xprt_create_transport: failed, %ld\n",
+                               -PTR_ERR(xprt));
+               return xprt;
        }
 
        kref_init(&xprt->kref);
@@ -932,7 +917,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
 
        INIT_LIST_HEAD(&xprt->free);
        INIT_LIST_HEAD(&xprt->recv);
-       INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
+       INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
        init_timer(&xprt->timer);
        xprt->timer.function = xprt_init_autodisconnect;
        xprt->timer.data = (unsigned long) xprt;
@@ -969,8 +954,11 @@ static void xprt_destroy(struct kref *kref)
        dprintk("RPC:      destroying transport %p\n", xprt);
        xprt->shutdown = 1;
        del_timer_sync(&xprt->timer);
+
+       /*
+        * Tear down transport state and free the rpc_xprt
+        */
        xprt->ops->destroy(xprt);
-       kfree(xprt);
 }
 
 /**
index 757fc91..49cabff 100644 (file)
@@ -45,6 +45,92 @@ unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
 unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
 unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
 
+/*
+ * We can register our own files under /proc/sys/sunrpc by
+ * calling register_sysctl_table() again.  The files in that
+ * directory become the union of all files registered there.
+ *
+ * We simply need to make sure that we don't collide with
+ * someone else's file names!
+ */
+
+#ifdef RPC_DEBUG
+
+static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
+static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
+static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
+
+static struct ctl_table_header *sunrpc_table_header;
+
+/*
+ * FIXME: changing the UDP slot table size should also resize the UDP
+ *        socket buffers for existing UDP transports
+ */
+static ctl_table xs_tunables_table[] = {
+       {
+               .ctl_name       = CTL_SLOTTABLE_UDP,
+               .procname       = "udp_slot_table_entries",
+               .data           = &xprt_udp_slot_table_entries,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &min_slot_table_size,
+               .extra2         = &max_slot_table_size
+       },
+       {
+               .ctl_name       = CTL_SLOTTABLE_TCP,
+               .procname       = "tcp_slot_table_entries",
+               .data           = &xprt_tcp_slot_table_entries,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &min_slot_table_size,
+               .extra2         = &max_slot_table_size
+       },
+       {
+               .ctl_name       = CTL_MIN_RESVPORT,
+               .procname       = "min_resvport",
+               .data           = &xprt_min_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
+       {
+               .ctl_name       = CTL_MAX_RESVPORT,
+               .procname       = "max_resvport",
+               .data           = &xprt_max_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
+       {
+               .ctl_name = 0,
+       },
+};
+
+static ctl_table sunrpc_table[] = {
+       {
+               .ctl_name       = CTL_SUNRPC,
+               .procname       = "sunrpc",
+               .mode           = 0555,
+               .child          = xs_tunables_table
+       },
+       {
+               .ctl_name = 0,
+       },
+};
+
+#endif
+
 /*
  * How many times to try sending a request on a socket before waiting
  * for the socket buffer to clear.
@@ -125,6 +211,55 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
 }
 #endif
 
+struct sock_xprt {
+       struct rpc_xprt         xprt;
+
+       /*
+        * Network layer
+        */
+       struct socket *         sock;
+       struct sock *           inet;
+
+       /*
+        * State of TCP reply receive
+        */
+       __be32                  tcp_fraghdr,
+                               tcp_xid;
+
+       u32                     tcp_offset,
+                               tcp_reclen;
+
+       unsigned long           tcp_copied,
+                               tcp_flags;
+
+       /*
+        * Connection of transports
+        */
+       struct delayed_work     connect_worker;
+       unsigned short          port;
+
+       /*
+        * UDP socket buffer size parameters
+        */
+       size_t                  rcvsize,
+                               sndsize;
+
+       /*
+        * Saved socket callback addresses
+        */
+       void                    (*old_data_ready)(struct sock *, int);
+       void                    (*old_state_change)(struct sock *);
+       void                    (*old_write_space)(struct sock *);
+};
+
+/*
+ * TCP receive state flags
+ */
+#define TCP_RCV_LAST_FRAG      (1UL << 0)
+#define TCP_RCV_COPY_FRAGHDR   (1UL << 1)
+#define TCP_RCV_COPY_XID       (1UL << 2)
+#define TCP_RCV_COPY_DATA      (1UL << 3)
+
 static void xs_format_peer_addresses(struct rpc_xprt *xprt)
 {
        struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
@@ -168,37 +303,52 @@ static void xs_free_peer_addresses(struct rpc_xprt *xprt)
 
 #define XS_SENDMSG_FLAGS       (MSG_DONTWAIT | MSG_NOSIGNAL)
 
-static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, struct kvec *vec, unsigned int base, int more)
 {
-       struct kvec iov = {
-               .iov_base       = xdr->head[0].iov_base + base,
-               .iov_len        = len - base,
-       };
        struct msghdr msg = {
                .msg_name       = addr,
                .msg_namelen    = addrlen,
-               .msg_flags      = XS_SENDMSG_FLAGS,
+               .msg_flags      = XS_SENDMSG_FLAGS | (more ? MSG_MORE : 0),
+       };
+       struct kvec iov = {
+               .iov_base       = vec->iov_base + base,
+               .iov_len        = vec->iov_len - base,
        };
 
-       if (xdr->len > len)
-               msg.msg_flags |= MSG_MORE;
-
-       if (likely(iov.iov_len))
+       if (iov.iov_len != 0)
                return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
        return kernel_sendmsg(sock, &msg, NULL, 0, 0);
 }
 
-static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more)
 {
-       struct kvec iov = {
-               .iov_base       = xdr->tail[0].iov_base + base,
-               .iov_len        = len - base,
-       };
-       struct msghdr msg = {
-               .msg_flags      = XS_SENDMSG_FLAGS,
-       };
+       struct page **ppage;
+       unsigned int remainder;
+       int err, sent = 0;
+
+       remainder = xdr->page_len - base;
+       base += xdr->page_base;
+       ppage = xdr->pages + (base >> PAGE_SHIFT);
+       base &= ~PAGE_MASK;
+       for(;;) {
+               unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder);
+               int flags = XS_SENDMSG_FLAGS;
 
-       return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+               remainder -= len;
+               if (remainder != 0 || more)
+                       flags |= MSG_MORE;
+               err = sock->ops->sendpage(sock, *ppage, base, len, flags);
+               if (remainder == 0 || err != len)
+                       break;
+               sent += err;
+               ppage++;
+               base = 0;
+       }
+       if (sent == 0)
+               return err;
+       if (err > 0)
+               sent += err;
+       return sent;
 }
 
 /**
@@ -210,76 +360,51 @@ static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int b
  * @base: starting position in the buffer
  *
  */
-static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
 {
-       struct page **ppage = xdr->pages;
-       unsigned int len, pglen = xdr->page_len;
-       int err, ret = 0;
+       unsigned int remainder = xdr->len - base;
+       int err, sent = 0;
 
        if (unlikely(!sock))
                return -ENOTCONN;
 
        clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+       if (base != 0) {
+               addr = NULL;
+               addrlen = 0;
+       }
 
-       len = xdr->head[0].iov_len;
-       if (base < len || (addr != NULL && base == 0)) {
-               err = xs_send_head(sock, addr, addrlen, xdr, base, len);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-               if (err != (len - base))
+       if (base < xdr->head[0].iov_len || addr != NULL) {
+               unsigned int len = xdr->head[0].iov_len - base;
+               remainder -= len;
+               err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0);
+               if (remainder == 0 || err != len)
                        goto out;
+               sent += err;
                base = 0;
        } else
-               base -= len;
+               base -= xdr->head[0].iov_len;
 
-       if (unlikely(pglen == 0))
-               goto copy_tail;
-       if (unlikely(base >= pglen)) {
-               base -= pglen;
-               goto copy_tail;
-       }
-       if (base || xdr->page_base) {
-               pglen -= base;
-               base += xdr->page_base;
-               ppage += base >> PAGE_CACHE_SHIFT;
-               base &= ~PAGE_CACHE_MASK;
-       }
-
-       do {
-               int flags = XS_SENDMSG_FLAGS;
-
-               len = PAGE_CACHE_SIZE;
-               if (base)
-                       len -= base;
-               if (pglen < len)
-                       len = pglen;
-
-               if (pglen != len || xdr->tail[0].iov_len != 0)
-                       flags |= MSG_MORE;
-
-               err = kernel_sendpage(sock, *ppage, base, len, flags);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-               if (err != len)
+       if (base < xdr->page_len) {
+               unsigned int len = xdr->page_len - base;
+               remainder -= len;
+               err = xs_send_pagedata(sock, xdr, base, remainder != 0);
+               if (remainder == 0 || err != len)
                        goto out;
+               sent += err;
                base = 0;
-               ppage++;
-       } while ((pglen -= len) != 0);
-copy_tail:
-       len = xdr->tail[0].iov_len;
-       if (base < len) {
-               err = xs_send_tail(sock, xdr, base, len);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-       }
+       } else
+               base -= xdr->page_len;
+
+       if (base >= xdr->tail[0].iov_len)
+               return sent;
+       err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0);
 out:
-       return ret;
+       if (sent == 0)
+               return err;
+       if (err > 0)
+               sent += err;
+       return sent;
 }
 
 /**
@@ -291,19 +416,20 @@ static void xs_nospace(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
 
        dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
                        task->tk_pid, req->rq_slen - req->rq_bytes_sent,
                        req->rq_slen);
 
-       if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+       if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
                /* Protect against races with write_space */
                spin_lock_bh(&xprt->transport_lock);
 
                /* Don't race with disconnect */
                if (!xprt_connected(xprt))
                        task->tk_status = -ENOTCONN;
-               else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+               else if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
                        xprt_wait_for_buffer_space(task);
 
                spin_unlock_bh(&xprt->transport_lock);
@@ -327,6 +453,7 @@ static int xs_udp_send_request(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        struct xdr_buf *xdr = &req->rq_snd_buf;
        int status;
 
@@ -335,8 +462,10 @@ static int xs_udp_send_request(struct rpc_task *task)
                                req->rq_svec->iov_len);
 
        req->rq_xtime = jiffies;
-       status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
-                               xprt->addrlen, xdr, req->rq_bytes_sent);
+       status = xs_sendpages(transport->sock,
+                             (struct sockaddr *) &xprt->addr,
+                             xprt->addrlen, xdr,
+                             req->rq_bytes_sent);
 
        dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
                        xdr->len - req->rq_bytes_sent, status);
@@ -392,6 +521,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        struct xdr_buf *xdr = &req->rq_snd_buf;
        int status, retry = 0;
 
@@ -406,8 +536,8 @@ static int xs_tcp_send_request(struct rpc_task *task)
         * called sendmsg(). */
        while (1) {
                req->rq_xtime = jiffies;
-               status = xs_sendpages(xprt->sock, NULL, 0, xdr,
-                                               req->rq_bytes_sent);
+               status = xs_sendpages(transport->sock,
+                                       NULL, 0, xdr, req->rq_bytes_sent);
 
                dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
                                xdr->len - req->rq_bytes_sent, status);
@@ -485,8 +615,9 @@ out_release:
  */
 static void xs_close(struct rpc_xprt *xprt)
 {
-       struct socket *sock = xprt->sock;
-       struct sock *sk = xprt->inet;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct socket *sock = transport->sock;
+       struct sock *sk = transport->inet;
 
        if (!sk)
                goto clear_close_wait;
@@ -494,13 +625,13 @@ static void xs_close(struct rpc_xprt *xprt)
        dprintk("RPC:      xs_close xprt %p\n", xprt);
 
        write_lock_bh(&sk->sk_callback_lock);
-       xprt->inet = NULL;
-       xprt->sock = NULL;
+       transport->inet = NULL;
+       transport->sock = NULL;
 
        sk->sk_user_data = NULL;
-       sk->sk_data_ready = xprt->old_data_ready;
-       sk->sk_state_change = xprt->old_state_change;
-       sk->sk_write_space = xprt->old_write_space;
+       sk->sk_data_ready = transport->old_data_ready;
+       sk->sk_state_change = transport->old_state_change;
+       sk->sk_write_space = transport->old_write_space;
        write_unlock_bh(&sk->sk_callback_lock);
 
        sk->sk_no_check = 0;
@@ -519,15 +650,18 @@ clear_close_wait:
  */
 static void xs_destroy(struct rpc_xprt *xprt)
 {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+
        dprintk("RPC:      xs_destroy xprt %p\n", xprt);
 
-       cancel_delayed_work(&xprt->connect_worker);
+       cancel_delayed_work(&transport->connect_worker);
        flush_scheduled_work();
 
        xprt_disconnect(xprt);
        xs_close(xprt);
        xs_free_peer_addresses(xprt);
        kfree(xprt->slot);
+       kfree(xprt);
 }
 
 static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -603,91 +737,75 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        read_unlock(&sk->sk_callback_lock);
 }
 
-static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
-{
-       if (len > desc->count)
-               len = desc->count;
-       if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
-               dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
-                               len, desc->count);
-               return 0;
-       }
-       desc->offset += len;
-       desc->count -= len;
-       dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
-                       len, desc->count);
-       return len;
-}
-
-static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
 {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        size_t len, used;
        char *p;
 
-       p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
-       len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
-       used = xs_tcp_copy_data(desc, p, len);
-       xprt->tcp_offset += used;
+       p = ((char *) &transport->tcp_fraghdr) + transport->tcp_offset;
+       len = sizeof(transport->tcp_fraghdr) - transport->tcp_offset;
+       used = xdr_skb_read_bits(desc, p, len);
+       transport->tcp_offset += used;
        if (used != len)
                return;
 
-       xprt->tcp_reclen = ntohl(xprt->tcp_recm);
-       if (xprt->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
-               xprt->tcp_flags |= XPRT_LAST_FRAG;
+       transport->tcp_reclen = ntohl(transport->tcp_fraghdr);
+       if (transport->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
+               transport->tcp_flags |= TCP_RCV_LAST_FRAG;
        else
-               xprt->tcp_flags &= ~XPRT_LAST_FRAG;
-       xprt->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
+               transport->tcp_flags &= ~TCP_RCV_LAST_FRAG;
+       transport->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
 
-       xprt->tcp_flags &= ~XPRT_COPY_RECM;
-       xprt->tcp_offset = 0;
+       transport->tcp_flags &= ~TCP_RCV_COPY_FRAGHDR;
+       transport->tcp_offset = 0;
 
        /* Sanity check of the record length */
-       if (unlikely(xprt->tcp_reclen < 4)) {
+       if (unlikely(transport->tcp_reclen < 4)) {
                dprintk("RPC:      invalid TCP record fragment length\n");
                xprt_disconnect(xprt);
                return;
        }
        dprintk("RPC:      reading TCP record fragment of length %d\n",
-                       xprt->tcp_reclen);
+                       transport->tcp_reclen);
 }
 
-static void xs_tcp_check_recm(struct rpc_xprt *xprt)
+static void xs_tcp_check_fraghdr(struct sock_xprt *transport)
 {
-       dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
-                       xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
-       if (xprt->tcp_offset == xprt->tcp_reclen) {
-               xprt->tcp_flags |= XPRT_COPY_RECM;
-               xprt->tcp_offset = 0;
-               if (xprt->tcp_flags & XPRT_LAST_FRAG) {
-                       xprt->tcp_flags &= ~XPRT_COPY_DATA;
-                       xprt->tcp_flags |= XPRT_COPY_XID;
-                       xprt->tcp_copied = 0;
+       if (transport->tcp_offset == transport->tcp_reclen) {
+               transport->tcp_flags |= TCP_RCV_COPY_FRAGHDR;
+               transport->tcp_offset = 0;
+               if (transport->tcp_flags & TCP_RCV_LAST_FRAG) {
+                       transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
+                       transport->tcp_flags |= TCP_RCV_COPY_XID;
+                       transport->tcp_copied = 0;
                }
        }
 }
 
-static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_reader *desc)
 {
        size_t len, used;
        char *p;
 
-       len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+       len = sizeof(transport->tcp_xid) - transport->tcp_offset;
        dprintk("RPC:      reading XID (%Zu bytes)\n", len);
-       p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
-       used = xs_tcp_copy_data(desc, p, len);
-       xprt->tcp_offset += used;
+       p = ((char *) &transport->tcp_xid) + transport->tcp_offset;
+       used = xdr_skb_read_bits(desc, p, len);
+       transport->tcp_offset += used;
        if (used != len)
                return;
-       xprt->tcp_flags &= ~XPRT_COPY_XID;
-       xprt->tcp_flags |= XPRT_COPY_DATA;
-       xprt->tcp_copied = 4;
+       transport->tcp_flags &= ~TCP_RCV_COPY_XID;
+       transport->tcp_flags |= TCP_RCV_COPY_DATA;
+       transport->tcp_copied = 4;
        dprintk("RPC:      reading reply for XID %08x\n",
-                                               ntohl(xprt->tcp_xid));
-       xs_tcp_check_recm(xprt);
+                       ntohl(transport->tcp_xid));
+       xs_tcp_check_fraghdr(transport);
 }
 
-static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
 {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        struct rpc_rqst *req;
        struct xdr_buf *rcvbuf;
        size_t len;
@@ -695,116 +813,118 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc
 
        /* Find and lock the request corresponding to this xid */
        spin_lock(&xprt->transport_lock);
-       req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+       req = xprt_lookup_rqst(xprt, transport->tcp_xid);
        if (!req) {
-               xprt->tcp_flags &= ~XPRT_COPY_DATA;
+               transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
                dprintk("RPC:      XID %08x request not found!\n",
-                               ntohl(xprt->tcp_xid));
+                               ntohl(transport->tcp_xid));
                spin_unlock(&xprt->transport_lock);
                return;
        }
 
        rcvbuf = &req->rq_private_buf;
        len = desc->count;
-       if (len > xprt->tcp_reclen - xprt->tcp_offset) {
-               skb_reader_t my_desc;
+       if (len > transport->tcp_reclen - transport->tcp_offset) {
+               struct xdr_skb_reader my_desc;
 
-               len = xprt->tcp_reclen - xprt->tcp_offset;
+               len = transport->tcp_reclen - transport->tcp_offset;
                memcpy(&my_desc, desc, sizeof(my_desc));
                my_desc.count = len;
-               r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-                                         &my_desc, xs_tcp_copy_data);
+               r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
+                                         &my_desc, xdr_skb_read_bits);
                desc->count -= r;
                desc->offset += r;
        } else
-               r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-                                         desc, xs_tcp_copy_data);
+               r = xdr_partial_copy_from_skb(rcvbuf, transport->tcp_copied,
+                                         desc, xdr_skb_read_bits);
 
        if (r > 0) {
-               xprt->tcp_copied += r;
-               xprt->tcp_offset += r;
+               transport->tcp_copied += r;
+               transport->tcp_offset += r;
        }
        if (r != len) {
                /* Error when copying to the receive buffer,
                 * usually because we weren't able to allocate
                 * additional buffer pages. All we can do now
-                * is turn off XPRT_COPY_DATA, so the request
+                * is turn off TCP_RCV_COPY_DATA, so the request
                 * will not receive any additional updates,
                 * and time out.
                 * Any remaining data from this record will
                 * be discarded.
                 */
-               xprt->tcp_flags &= ~XPRT_COPY_DATA;
+               transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
                dprintk("RPC:      XID %08x truncated request\n",
-                               ntohl(xprt->tcp_xid));
+                               ntohl(transport->tcp_xid));
                dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-                               xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+                               xprt, transport->tcp_copied, transport->tcp_offset,
+                                       transport->tcp_reclen);
                goto out;
        }
 
        dprintk("RPC:      XID %08x read %Zd bytes\n",
-                       ntohl(xprt->tcp_xid), r);
+                       ntohl(transport->tcp_xid), r);
        dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-                       xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
-
-       if (xprt->tcp_copied == req->rq_private_buf.buflen)
-               xprt->tcp_flags &= ~XPRT_COPY_DATA;
-       else if (xprt->tcp_offset == xprt->tcp_reclen) {
-               if (xprt->tcp_flags & XPRT_LAST_FRAG)
-                       xprt->tcp_flags &= ~XPRT_COPY_DATA;
+                       xprt, transport->tcp_copied, transport->tcp_offset,
+                               transport->tcp_reclen);
+
+       if (transport->tcp_copied == req->rq_private_buf.buflen)
+               transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
+       else if (transport->tcp_offset == transport->tcp_reclen) {
+               if (transport->tcp_flags & TCP_RCV_LAST_FRAG)
+                       transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
        }
 
 out:
-       if (!(xprt->tcp_flags & XPRT_COPY_DATA))
-               xprt_complete_rqst(req->rq_task, xprt->tcp_copied);
+       if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
+               xprt_complete_rqst(req->rq_task, transport->tcp_copied);
        spin_unlock(&xprt->transport_lock);
-       xs_tcp_check_recm(xprt);
+       xs_tcp_check_fraghdr(transport);
 }
 
-static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
 {
        size_t len;
 
-       len = xprt->tcp_reclen - xprt->tcp_offset;
+       len = transport->tcp_reclen - transport->tcp_offset;
        if (len > desc->count)
                len = desc->count;
        desc->count -= len;
        desc->offset += len;
-       xprt->tcp_offset += len;
+       transport->tcp_offset += len;
        dprintk("RPC:      discarded %Zu bytes\n", len);
-       xs_tcp_check_recm(xprt);
+       xs_tcp_check_fraghdr(transport);
 }
 
 static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
 {
        struct rpc_xprt *xprt = rd_desc->arg.data;
-       skb_reader_t desc = {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct xdr_skb_reader desc = {
                .skb    = skb,
                .offset = offset,
                .count  = len,
-               .csum   = 0
        };
 
        dprintk("RPC:      xs_tcp_data_recv started\n");
        do {
                /* Read in a new fragment marker if necessary */
                /* Can we ever really expect to get completely empty fragments? */
-               if (xprt->tcp_flags & XPRT_COPY_RECM) {
+               if (transport->tcp_flags & TCP_RCV_COPY_FRAGHDR) {
                        xs_tcp_read_fraghdr(xprt, &desc);
                        continue;
                }
                /* Read in the xid if necessary */
-               if (xprt->tcp_flags & XPRT_COPY_XID) {
-                       xs_tcp_read_xid(xprt, &desc);
+               if (transport->tcp_flags & TCP_RCV_COPY_XID) {
+                       xs_tcp_read_xid(transport, &desc);
                        continue;
                }
                /* Read in the request data */
-               if (xprt->tcp_flags & XPRT_COPY_DATA) {
+               if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
                        xs_tcp_read_request(xprt, &desc);
                        continue;
                }
                /* Skip over any trailing bytes on short reads */
-               xs_tcp_read_discard(xprt, &desc);
+               xs_tcp_read_discard(transport, &desc);
        } while (desc.count);
        dprintk("RPC:      xs_tcp_data_recv done\n");
        return len - desc.count;
@@ -858,11 +978,16 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_ESTABLISHED:
                spin_lock_bh(&xprt->transport_lock);
                if (!xprt_test_and_set_connected(xprt)) {
+                       struct sock_xprt *transport = container_of(xprt,
+                                       struct sock_xprt, xprt);
+
                        /* Reset TCP record info */
-                       xprt->tcp_offset = 0;
-                       xprt->tcp_reclen = 0;
-                       xprt->tcp_copied = 0;
-                       xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+                       transport->tcp_offset = 0;
+                       transport->tcp_reclen = 0;
+                       transport->tcp_copied = 0;
+                       transport->tcp_flags =
+                               TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID;
+
                        xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
                        xprt_wake_pending_tasks(xprt, 0);
                }
@@ -951,15 +1076,16 @@ static void xs_tcp_write_space(struct sock *sk)
 
 static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
 {
-       struct sock *sk = xprt->inet;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct sock *sk = transport->inet;
 
-       if (xprt->rcvsize) {
+       if (transport->rcvsize) {
                sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
-               sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
+               sk->sk_rcvbuf = transport->rcvsize * xprt->max_reqs * 2;
        }
-       if (xprt->sndsize) {
+       if (transport->sndsize) {
                sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-               sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
+               sk->sk_sndbuf = transport->sndsize * xprt->max_reqs * 2;
                sk->sk_write_space(sk);
        }
 }
@@ -974,12 +1100,14 @@ static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
  */
 static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
 {
-       xprt->sndsize = 0;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+
+       transport->sndsize = 0;
        if (sndsize)
-               xprt->sndsize = sndsize + 1024;
-       xprt->rcvsize = 0;
+               transport->sndsize = sndsize + 1024;
+       transport->rcvsize = 0;
        if (rcvsize)
-               xprt->rcvsize = rcvsize + 1024;
+               transport->rcvsize = rcvsize + 1024;
 
        xs_udp_do_set_buffer_size(xprt);
 }
@@ -1002,19 +1130,6 @@ static unsigned short xs_get_random_port(void)
        return rand + xprt_min_resvport;
 }
 
-/**
- * xs_print_peer_address - format an IPv4 address for printing
- * @xprt: generic transport
- * @format: flags field indicating which parts of the address to render
- */
-static char *xs_print_peer_address(struct rpc_xprt *xprt, enum rpc_display_format_t format)
-{
-       if (xprt->address_strings[format] != NULL)
-               return xprt->address_strings[format];
-       else
-               return "unprintable";
-}
-
 /**
  * xs_set_port - reset the port number in the remote endpoint address
  * @xprt: generic transport
@@ -1030,20 +1145,20 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
        sap->sin_port = htons(port);
 }
 
-static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock)
 {
        struct sockaddr_in myaddr = {
                .sin_family = AF_INET,
        };
        int err;
-       unsigned short port = xprt->port;
+       unsigned short port = transport->port;
 
        do {
                myaddr.sin_port = htons(port);
                err = kernel_bind(sock, (struct sockaddr *) &myaddr,
                                                sizeof(myaddr));
                if (err == 0) {
-                       xprt->port = port;
+                       transport->port = port;
                        dprintk("RPC:      xs_bindresvport bound to port %u\n",
                                        port);
                        return 0;
@@ -1052,22 +1167,53 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
                        port = xprt_max_resvport;
                else
                        port--;
-       } while (err == -EADDRINUSE && port != xprt->port);
+       } while (err == -EADDRINUSE && port != transport->port);
 
        dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
        return err;
 }
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static struct lock_class_key xs_key[2];
+static struct lock_class_key xs_slock_key[2];
+
+static inline void xs_reclassify_socket(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       BUG_ON(sk->sk_lock.owner != NULL);
+       switch (sk->sk_family) {
+       case AF_INET:
+               sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS",
+                       &xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]);
+               break;
+
+       case AF_INET6:
+               sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS",
+                       &xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]);
+               break;
+
+       default:
+               BUG();
+       }
+}
+#else
+static inline void xs_reclassify_socket(struct socket *sock)
+{
+}
+#endif
+
 /**
  * xs_udp_connect_worker - set up a UDP socket
- * @args: RPC transport to connect
+ * @work: RPC transport to connect
  *
  * Invoked by a work queue tasklet.
  */
-static void xs_udp_connect_worker(void *args)
+static void xs_udp_connect_worker(struct work_struct *work)
 {
-       struct rpc_xprt *xprt = (struct rpc_xprt *) args;
-       struct socket *sock = xprt->sock;
+       struct sock_xprt *transport =
+               container_of(work, struct sock_xprt, connect_worker.work);
+       struct rpc_xprt *xprt = &transport->xprt;
+       struct socket *sock = transport->sock;
        int err, status = -EIO;
 
        if (xprt->shutdown || !xprt_bound(xprt))
@@ -1080,24 +1226,25 @@ static void xs_udp_connect_worker(void *args)
                dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
                goto out;
        }
+       xs_reclassify_socket(sock);
 
-       if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+       if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
                sock_release(sock);
                goto out;
        }
 
        dprintk("RPC:      worker connecting xprt %p to address: %s\n",
-                       xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL));
+                       xprt, xprt->address_strings[RPC_DISPLAY_ALL]);
 
-       if (!xprt->inet) {
+       if (!transport->inet) {
                struct sock *sk = sock->sk;
 
                write_lock_bh(&sk->sk_callback_lock);
 
                sk->sk_user_data = xprt;
-               xprt->old_data_ready = sk->sk_data_ready;
-               xprt->old_state_change = sk->sk_state_change;
-               xprt->old_write_space = sk->sk_write_space;
+               transport->old_data_ready = sk->sk_data_ready;
+               transport->old_state_change = sk->sk_state_change;
+               transport->old_write_space = sk->sk_write_space;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
                sk->sk_no_check = UDP_CSUM_NORCV;
@@ -1106,8 +1253,8 @@ static void xs_udp_connect_worker(void *args)
                xprt_set_connected(xprt);
 
                /* Reset to new socket */
-               xprt->sock = sock;
-               xprt->inet = sk;
+               transport->sock = sock;
+               transport->inet = sk;
 
                write_unlock_bh(&sk->sk_callback_lock);
        }
@@ -1125,7 +1272,7 @@ out:
 static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
 {
        int result;
-       struct socket *sock = xprt->sock;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        struct sockaddr any;
 
        dprintk("RPC:      disconnecting xprt %p to reuse port\n", xprt);
@@ -1136,7 +1283,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
         */
        memset(&any, 0, sizeof(any));
        any.sa_family = AF_UNSPEC;
-       result = kernel_connect(sock, &any, sizeof(any), 0);
+       result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (result)
                dprintk("RPC:      AF_UNSPEC connect return code %d\n",
                                result);
@@ -1144,27 +1291,30 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
 
 /**
  * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
- * @args: RPC transport to connect
+ * @work: RPC transport to connect
  *
  * Invoked by a work queue tasklet.
  */
-static void xs_tcp_connect_worker(void *args)
+static void xs_tcp_connect_worker(struct work_struct *work)
 {
-       struct rpc_xprt *xprt = (struct rpc_xprt *)args;
-       struct socket *sock = xprt->sock;
+       struct sock_xprt *transport =
+               container_of(work, struct sock_xprt, connect_worker.work);
+       struct rpc_xprt *xprt = &transport->xprt;
+       struct socket *sock = transport->sock;
        int err, status = -EIO;
 
        if (xprt->shutdown || !xprt_bound(xprt))
                goto out;
 
-       if (!xprt->sock) {
+       if (!sock) {
                /* start from scratch */
                if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
                        dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
                        goto out;
                }
+               xs_reclassify_socket(sock);
 
-               if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+               if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
                        sock_release(sock);
                        goto out;
                }
@@ -1173,17 +1323,17 @@ static void xs_tcp_connect_worker(void *args)
                xs_tcp_reuse_connection(xprt);
 
        dprintk("RPC:      worker connecting xprt %p to address: %s\n",
-                       xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL));
+                       xprt, xprt->address_strings[RPC_DISPLAY_ALL]);
 
-       if (!xprt->inet) {
+       if (!transport->inet) {
                struct sock *sk = sock->sk;
 
                write_lock_bh(&sk->sk_callback_lock);
 
                sk->sk_user_data = xprt;
-               xprt->old_data_ready = sk->sk_data_ready;
-               xprt->old_state_change = sk->sk_state_change;
-               xprt->old_write_space = sk->sk_write_space;
+               transport->old_data_ready = sk->sk_data_ready;
+               transport->old_state_change = sk->sk_state_change;
+               transport->old_write_space = sk->sk_write_space;
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
@@ -1198,8 +1348,8 @@ static void xs_tcp_connect_worker(void *args)
                xprt_clear_connected(xprt);
 
                /* Reset to new socket */
-               xprt->sock = sock;
-               xprt->inet = sk;
+               transport->sock = sock;
+               transport->inet = sk;
 
                write_unlock_bh(&sk->sk_callback_lock);
        }
@@ -1248,21 +1398,22 @@ out_clear:
 static void xs_connect(struct rpc_task *task)
 {
        struct rpc_xprt *xprt = task->tk_xprt;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
 
        if (xprt_test_and_set_connecting(xprt))
                return;
 
-       if (xprt->sock != NULL) {
+       if (transport->sock != NULL) {
                dprintk("RPC:      xs_connect delayed xprt %p for %lu seconds\n",
                                xprt, xprt->reestablish_timeout / HZ);
-               schedule_delayed_work(&xprt->connect_worker,
+               schedule_delayed_work(&transport->connect_worker,
                                        xprt->reestablish_timeout);
                xprt->reestablish_timeout <<= 1;
                if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
                        xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
        } else {
                dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
-               schedule_work(&xprt->connect_worker);
+               schedule_delayed_work(&transport->connect_worker, 0);
 
                /* flush_scheduled_work can sleep... */
                if (!RPC_IS_ASYNC(task))
@@ -1278,8 +1429,10 @@ static void xs_connect(struct rpc_task *task)
  */
 static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
 {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+
        seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n",
-                       xprt->port,
+                       transport->port,
                        xprt->stat.bind_count,
                        xprt->stat.sends,
                        xprt->stat.recvs,
@@ -1296,13 +1449,14 @@ static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
  */
 static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
 {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        long idle_time = 0;
 
        if (xprt_connected(xprt))
                idle_time = (long)(jiffies - xprt->last_used) / HZ;
 
        seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n",
-                       xprt->port,
+                       transport->port,
                        xprt->stat.bind_count,
                        xprt->stat.connect_count,
                        xprt->stat.connect_time,
@@ -1316,7 +1470,6 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
 
 static struct rpc_xprt_ops xs_udp_ops = {
        .set_buffer_size        = xs_udp_set_buffer_size,
-       .print_addr             = xs_print_peer_address,
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong,
        .rpcbind                = rpc_getport,
@@ -1334,7 +1487,6 @@ static struct rpc_xprt_ops xs_udp_ops = {
 };
 
 static struct rpc_xprt_ops xs_tcp_ops = {
-       .print_addr             = xs_print_peer_address,
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
        .rpcbind                = rpc_getport,
@@ -1349,33 +1501,64 @@ static struct rpc_xprt_ops xs_tcp_ops = {
        .print_stats            = xs_tcp_print_stats,
 };
 
+static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
+{
+       struct rpc_xprt *xprt;
+       struct sock_xprt *new;
+
+       if (addrlen > sizeof(xprt->addr)) {
+               dprintk("RPC:      xs_setup_xprt: address too large\n");
+               return ERR_PTR(-EBADF);
+       }
+
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (new == NULL) {
+               dprintk("RPC:      xs_setup_xprt: couldn't allocate rpc_xprt\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       xprt = &new->xprt;
+
+       xprt->max_reqs = slot_table_size;
+       xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);
+       if (xprt->slot == NULL) {
+               kfree(xprt);
+               dprintk("RPC:      xs_setup_xprt: couldn't allocate slot table\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       memcpy(&xprt->addr, addr, addrlen);
+       xprt->addrlen = addrlen;
+       new->port = xs_get_random_port();
+
+       return xprt;
+}
+
 /**
  * xs_setup_udp - Set up transport to use a UDP socket
- * @xprt: transport to set up
+ * @addr: address of remote server
+ * @addrlen: length of address in bytes
  * @to:   timeout parameters
  *
  */
-int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
 {
-       size_t slot_table_size;
-       struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
+       struct rpc_xprt *xprt;
+       struct sock_xprt *transport;
 
-       xprt->max_reqs = xprt_udp_slot_table_entries;
-       slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
-       xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
-       if (xprt->slot == NULL)
-               return -ENOMEM;
+       xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
+       if (IS_ERR(xprt))
+               return xprt;
+       transport = container_of(xprt, struct sock_xprt, xprt);
 
-       if (ntohs(addr->sin_port) != 0)
+       if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
                xprt_set_bound(xprt);
-       xprt->port = xs_get_random_port();
 
        xprt->prot = IPPROTO_UDP;
        xprt->tsh_size = 0;
        /* XXX: header size can vary due to auth type, IPv6, etc. */
        xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
 
-       INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+       INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker);
        xprt->bind_timeout = XS_BIND_TO;
        xprt->connect_timeout = XS_UDP_CONN_TO;
        xprt->reestablish_timeout = XS_UDP_REEST_TO;
@@ -1390,37 +1573,36 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 
        xs_format_peer_addresses(xprt);
        dprintk("RPC:      set up transport to address %s\n",
-                       xs_print_peer_address(xprt, RPC_DISPLAY_ALL));
+                       xprt->address_strings[RPC_DISPLAY_ALL]);
 
-       return 0;
+       return xprt;
 }
 
 /**
  * xs_setup_tcp - Set up transport to use a TCP socket
- * @xprt: transport to set up
+ * @addr: address of remote server
+ * @addrlen: length of address in bytes
  * @to: timeout parameters
  *
  */
-int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
 {
-       size_t slot_table_size;
-       struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
+       struct rpc_xprt *xprt;
+       struct sock_xprt *transport;
 
-       xprt->max_reqs = xprt_tcp_slot_table_entries;
-       slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
-       xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
-       if (xprt->slot == NULL)
-               return -ENOMEM;
+       xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
+       if (IS_ERR(xprt))
+               return xprt;
+       transport = container_of(xprt, struct sock_xprt, xprt);
 
-       if (ntohs(addr->sin_port) != 0)
+       if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
                xprt_set_bound(xprt);
-       xprt->port = xs_get_random_port();
 
        xprt->prot = IPPROTO_TCP;
        xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
        xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
 
-       INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+       INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker);
        xprt->bind_timeout = XS_BIND_TO;
        xprt->connect_timeout = XS_TCP_CONN_TO;
        xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
@@ -1435,7 +1617,40 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 
        xs_format_peer_addresses(xprt);
        dprintk("RPC:      set up transport to address %s\n",
-                       xs_print_peer_address(xprt, RPC_DISPLAY_ALL));
+                       xprt->address_strings[RPC_DISPLAY_ALL]);
+
+       return xprt;
+}
+
+/**
+ * init_socket_xprt - set up xprtsock's sysctls
+ *
+ */
+int init_socket_xprt(void)
+{
+#ifdef RPC_DEBUG
+       if (!sunrpc_table_header) {
+               sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
+#ifdef CONFIG_PROC_FS
+               if (sunrpc_table[0].de)
+                       sunrpc_table[0].de->owner = THIS_MODULE;
+#endif
+       }
+#endif
 
        return 0;
 }
+
+/**
+ * cleanup_socket_xprt - remove xprtsock's sysctls
+ *
+ */
+void cleanup_socket_xprt(void)
+{
+#ifdef RPC_DEBUG
+       if (sunrpc_table_header) {
+               unregister_sysctl_table(sunrpc_table_header);
+               sunrpc_table_header = NULL;
+       }
+#endif
+}
index ae6ddf0..eb80778 100644 (file)
@@ -42,7 +42,7 @@ struct queue_item {
        unsigned long data;
 };
 
-static kmem_cache_t *tipc_queue_item_cache;
+static struct kmem_cache *tipc_queue_item_cache;
 static struct list_head signal_queue_head;
 static DEFINE_SPINLOCK(qitem_lock);
 static int handler_enabled = 0;
index 746c2f4..f14ad66 100644 (file)
@@ -96,7 +96,7 @@ atomic_t unix_tot_inflight = ATOMIC_INIT(0);
 static struct sock *unix_get_socket(struct file *filp)
 {
        struct sock *u_sock = NULL;
-       struct inode *inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_path.dentry->d_inode;
 
        /*
         *      Socket ?
index 316211d..769cdd6 100644 (file)
 
 #define KMEM_SAFETYZONE 8
 
-/***********FOR DEBUGGING PURPOSES*********************************************
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
-       int i = 0;
-       void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
-       char * c1 = v;
-       c1 += sizeof(unsigned int);
-       *((unsigned int *)v) = size;
-
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
-               c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
-               c1 += 8;
-       }
-       c1 += size;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
-               c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
-               c1 += 8;
-       }
-       v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
-       printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
-       return v;
-}
-static void dbg_kfree(void * v, int line) {
-       unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
-       unsigned int size = *sp;
-       char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
-       int i = 0;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
-                   || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
-                       printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
-                       printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-                                       c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-               }
-               c1 += 8;
-       }
-       c1 += size;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
-                   || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
-                  ) {
-                       printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
-                       printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-                                       c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-               }
-               c1 += 8;
-       }
-       printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
-       v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
-       kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-*****************************************************************************/
-
 /*
  *     Function Prototypes
  */
index 5a0dbeb..6b381fc 100644 (file)
@@ -119,6 +119,23 @@ static struct xfrm_algo_desc aalg_list[] = {
                .sadb_alg_maxbits = 160
        }
 },
+{
+       .name = "xcbc(aes)",
+
+       .uinfo = {
+               .auth = {
+                       .icv_truncbits = 96,
+                       .icv_fullbits = 128,
+               }
+       },
+
+       .desc = {
+               .sadb_alg_id = SADB_X_AALG_AES_XCBC_MAC,
+               .sadb_alg_ivlen = 0,
+               .sadb_alg_minbits = 128,
+               .sadb_alg_maxbits = 128
+       }
+},
 };
 
 static struct xfrm_algo_desc ealg_list[] = {
index e8198a2..414f890 100644 (file)
@@ -12,7 +12,7 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-static kmem_cache_t *secpath_cachep __read_mostly;
+static struct kmem_cache *secpath_cachep __read_mostly;
 
 void __secpath_destroy(struct sec_path *sp)
 {
@@ -27,7 +27,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
 {
        struct sec_path *sp;
 
-       sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC);
+       sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC);
        if (!sp)
                return NULL;
 
index 64d3938..bebd40e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/cache.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
+#include <linux/audit.h>
 
 #include "xfrm_hash.h"
 
@@ -39,7 +40,7 @@ EXPORT_SYMBOL(xfrm_policy_count);
 static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
 static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
 
-static kmem_cache_t *xfrm_dst_cache __read_mostly;
+static struct kmem_cache *xfrm_dst_cache __read_mostly;
 
 static struct work_struct xfrm_policy_gc_work;
 static HLIST_HEAD(xfrm_policy_gc_list);
@@ -392,7 +393,7 @@ static void xfrm_policy_gc_kill(struct xfrm_policy *policy)
        xfrm_pol_put(policy);
 }
 
-static void xfrm_policy_gc_task(void *data)
+static void xfrm_policy_gc_task(struct work_struct *work)
 {
        struct xfrm_policy *policy;
        struct hlist_node *entry, *tmp;
@@ -580,7 +581,7 @@ static inline int xfrm_byidx_should_resize(int total)
 
 static DEFINE_MUTEX(hash_resize_mutex);
 
-static void xfrm_hash_resize(void *__unused)
+static void xfrm_hash_resize(struct work_struct *__unused)
 {
        int dir, total;
 
@@ -597,7 +598,7 @@ static void xfrm_hash_resize(void *__unused)
        mutex_unlock(&hash_resize_mutex);
 }
 
-static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
+static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize);
 
 /* Generate new index... KAME seems to generate them ordered by cost
  * of an absolute inpredictability of ordering of rules. This will not pass. */
@@ -804,7 +805,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
 }
 EXPORT_SYMBOL(xfrm_policy_byid);
 
-void xfrm_policy_flush(u8 type)
+void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
 {
        int dir;
 
@@ -824,6 +825,9 @@ void xfrm_policy_flush(u8 type)
                        hlist_del(&pol->byidx);
                        write_unlock_bh(&xfrm_policy_lock);
 
+                       xfrm_audit_log(audit_info->loginuid, audit_info->secid,
+                                      AUDIT_MAC_IPSEC_DELSPD, 1, pol, NULL);
+
                        xfrm_policy_kill(pol);
                        killed++;
 
@@ -842,6 +846,11 @@ void xfrm_policy_flush(u8 type)
                                hlist_del(&pol->byidx);
                                write_unlock_bh(&xfrm_policy_lock);
 
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSPD, 1,
+                                              pol, NULL);
+
                                xfrm_policy_kill(pol);
                                killed++;
 
@@ -860,33 +869,12 @@ EXPORT_SYMBOL(xfrm_policy_flush);
 int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
                     void *data)
 {
-       struct xfrm_policy *pol;
+       struct xfrm_policy *pol, *last = NULL;
        struct hlist_node *entry;
-       int dir, count, error;
+       int dir, last_dir = 0, count, error;
 
        read_lock_bh(&xfrm_policy_lock);
        count = 0;
-       for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
-               struct hlist_head *table = xfrm_policy_bydst[dir].table;
-               int i;
-
-               hlist_for_each_entry(pol, entry,
-                                    &xfrm_policy_inexact[dir], bydst) {
-                       if (pol->type == type)
-                               count++;
-               }
-               for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
-                       hlist_for_each_entry(pol, entry, table + i, bydst) {
-                               if (pol->type == type)
-                                       count++;
-                       }
-               }
-       }
-
-       if (count == 0) {
-               error = -ENOENT;
-               goto out;
-       }
 
        for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
                struct hlist_head *table = xfrm_policy_bydst[dir].table;
@@ -896,21 +884,37 @@ int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*)
                                     &xfrm_policy_inexact[dir], bydst) {
                        if (pol->type != type)
                                continue;
-                       error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                       if (error)
-                               goto out;
+                       if (last) {
+                               error = func(last, last_dir % XFRM_POLICY_MAX,
+                                            count, data);
+                               if (error)
+                                       goto out;
+                       }
+                       last = pol;
+                       last_dir = dir;
+                       count++;
                }
                for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
                        hlist_for_each_entry(pol, entry, table + i, bydst) {
                                if (pol->type != type)
                                        continue;
-                               error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                               if (error)
-                                       goto out;
+                               if (last) {
+                                       error = func(last, last_dir % XFRM_POLICY_MAX,
+                                                    count, data);
+                                       if (error)
+                                               goto out;
+                               }
+                               last = pol;
+                               last_dir = dir;
+                               count++;
                        }
                }
        }
-       error = 0;
+       if (count == 0) {
+               error = -ENOENT;
+               goto out;
+       }
+       error = func(last, last_dir % XFRM_POLICY_MAX, 0, data);
 out:
        read_unlock_bh(&xfrm_policy_lock);
        return error;
@@ -1982,6 +1986,117 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
+#ifdef CONFIG_AUDITSYSCALL
+/* Audit addition and deletion of SAs and ipsec policy */
+
+void xfrm_audit_log(uid_t auid, u32 sid, int type, int result,
+                   struct xfrm_policy *xp, struct xfrm_state *x)
+{
+
+       char *secctx;
+       u32 secctx_len;
+       struct xfrm_sec_ctx *sctx = NULL;
+       struct audit_buffer *audit_buf;
+       int family;
+       extern int audit_enabled;
+
+       if (audit_enabled == 0)
+               return;
+
+       audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
+       if (audit_buf == NULL)
+       return;
+
+       switch(type) {
+       case AUDIT_MAC_IPSEC_ADDSA:
+               audit_log_format(audit_buf, "SAD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSA:
+               audit_log_format(audit_buf, "SAD delete: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_ADDSPD:
+               audit_log_format(audit_buf, "SPD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSPD:
+               audit_log_format(audit_buf, "SPD delete: auid=%u", auid);
+               break;
+       default:
+               return;
+       }
+
+       if (sid != 0 &&
+               security_secid_to_secctx(sid, &secctx, &secctx_len) == 0)
+               audit_log_format(audit_buf, " subj=%s", secctx);
+       else
+               audit_log_task_context(audit_buf);
+
+       if (xp) {
+               family = xp->selector.family;
+               if (xp->security)
+                       sctx = xp->security;
+       } else {
+               family = x->props.family;
+               if (x->security)
+                       sctx = x->security;
+       }
+
+       if (sctx)
+               audit_log_format(audit_buf,
+                               " sec_alg=%u sec_doi=%u sec_obj=%s",
+                               sctx->ctx_alg, sctx->ctx_doi, sctx->ctx_str);
+
+       switch(family) {
+       case AF_INET:
+               {
+                       struct in_addr saddr, daddr;
+                       if (xp) {
+                               saddr.s_addr = xp->selector.saddr.a4;
+                               daddr.s_addr = xp->selector.daddr.a4;
+                       } else {
+                               saddr.s_addr = x->props.saddr.a4;
+                               daddr.s_addr = x->id.daddr.a4;
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
+                                        NIPQUAD(saddr), NIPQUAD(daddr));
+               }
+                       break;
+       case AF_INET6:
+               {
+                       struct in6_addr saddr6, daddr6;
+                       if (xp) {
+                               memcpy(&saddr6, xp->selector.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, xp->selector.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       } else {
+                               memcpy(&saddr6, x->props.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, x->id.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=" NIP6_FMT "dst=" NIP6_FMT,
+                                        NIP6(saddr6), NIP6(daddr6));
+               }
+               break;
+       }
+
+       if (x)
+               audit_log_format(audit_buf, " spi=%lu(0x%lx) protocol=%s",
+                               (unsigned long)ntohl(x->id.spi),
+                               (unsigned long)ntohl(x->id.spi),
+                               x->id.proto == IPPROTO_AH ? "AH" :
+                               (x->id.proto == IPPROTO_ESP ?
+                               "ESP" : "IPCOMP"));
+
+       audit_log_format(audit_buf, " res=%u", result);
+       audit_log_end(audit_buf);
+}
+
+EXPORT_SYMBOL(xfrm_audit_log);
+#endif /* CONFIG_AUDITSYSCALL */
+
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
        int err = 0;
@@ -2116,7 +2231,7 @@ static void __init xfrm_policy_init(void)
                        panic("XFRM: failed to allocate bydst hash\n");
        }
 
-       INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL);
+       INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task);
        register_netdevice_notifier(&xfrm_dev_notifier);
 }
 
index 864962b..fdb08d9 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <asm/uaccess.h>
+#include <linux/audit.h>
 
 #include "xfrm_hash.h"
 
@@ -115,7 +116,7 @@ static unsigned long xfrm_hash_new_size(void)
 
 static DEFINE_MUTEX(hash_resize_mutex);
 
-static void xfrm_hash_resize(void *__unused)
+static void xfrm_hash_resize(struct work_struct *__unused)
 {
        struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
        unsigned long nsize, osize;
@@ -168,7 +169,7 @@ out_unlock:
        mutex_unlock(&hash_resize_mutex);
 }
 
-static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
+static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize);
 
 DECLARE_WAIT_QUEUE_HEAD(km_waitq);
 EXPORT_SYMBOL(km_waitq);
@@ -207,7 +208,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
        kfree(x);
 }
 
-static void xfrm_state_gc_task(void *data)
+static void xfrm_state_gc_task(struct work_struct *data)
 {
        struct xfrm_state *x;
        struct hlist_node *entry, *tmp;
@@ -238,6 +239,7 @@ static void xfrm_timer_handler(unsigned long data)
        unsigned long now = (unsigned long)xtime.tv_sec;
        long next = LONG_MAX;
        int warn = 0;
+       int err = 0;
 
        spin_lock(&x->lock);
        if (x->km.state == XFRM_STATE_DEAD)
@@ -295,9 +297,14 @@ expired:
                next = 2;
                goto resched;
        }
-       if (!__xfrm_state_delete(x) && x->id.spi)
+
+       err = __xfrm_state_delete(x);
+       if (!err && x->id.spi)
                km_state_expired(x, 1, 0);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
 out:
        spin_unlock(&x->lock);
 }
@@ -384,9 +391,10 @@ int xfrm_state_delete(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
-void xfrm_state_flush(u8 proto)
+void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
 {
        int i;
+       int err = 0;
 
        spin_lock_bh(&xfrm_state_lock);
        for (i = 0; i <= xfrm_state_hmask; i++) {
@@ -399,7 +407,11 @@ restart:
                                xfrm_state_hold(x);
                                spin_unlock_bh(&xfrm_state_lock);
 
-                               xfrm_state_delete(x);
+                               err = xfrm_state_delete(x);
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSA,
+                                              err ? 0 : 1, NULL, x);
                                xfrm_state_put(x);
 
                                spin_lock_bh(&xfrm_state_lock);
@@ -1099,7 +1111,7 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
                    void *data)
 {
        int i;
-       struct xfrm_state *x;
+       struct xfrm_state *x, *last = NULL;
        struct hlist_node *entry;
        int count = 0;
        int err = 0;
@@ -1107,24 +1119,22 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
        spin_lock_bh(&xfrm_state_lock);
        for (i = 0; i <= xfrm_state_hmask; i++) {
                hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
-                       if (xfrm_id_proto_match(x->id.proto, proto))
-                               count++;
+                       if (!xfrm_id_proto_match(x->id.proto, proto))
+                               continue;
+                       if (last) {
+                               err = func(last, count, data);
+                               if (err)
+                                       goto out;
+                       }
+                       last = x;
+                       count++;
                }
        }
        if (count == 0) {
                err = -ENOENT;
                goto out;
        }
-
-       for (i = 0; i <= xfrm_state_hmask; i++) {
-               hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
-                       if (!xfrm_id_proto_match(x->id.proto, proto))
-                               continue;
-                       err = func(x, --count, data);
-                       if (err)
-                               goto out;
-               }
-       }
+       err = func(last, 0, data);
 out:
        spin_unlock_bh(&xfrm_state_lock);
        return err;
@@ -1568,6 +1578,6 @@ void __init xfrm_state_init(void)
                panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
        xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
 
-       INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
+       INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task);
 }
 
index 311205f..e5372b1 100644 (file)
@@ -31,6 +31,7 @@
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
 #endif
+#include <linux/audit.h>
 
 static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
 {
@@ -454,6 +455,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        else
                err = xfrm_state_update(x);
 
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);
+
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
@@ -523,6 +527,10 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        }
 
        err = xfrm_state_delete(x);
+
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
        if (err < 0)
                goto out;
 
@@ -1030,6 +1038,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
         * a type XFRM_MSG_UPDPOLICY - JHS */
        excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
        err = xfrm_policy_insert(p->dir, xp, excl);
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
+
        if (err) {
                security_xfrm_policy_free(xp);
                kfree(xp);
@@ -1257,6 +1268,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
                security_xfrm_policy_free(&tmp);
        }
+       if (delete)
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
+
        if (xp == NULL)
                return -ENOENT;
 
@@ -1291,8 +1306,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma
 {
        struct km_event c;
        struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
+       struct xfrm_audit audit_info;
 
-       xfrm_state_flush(p->proto);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_state_flush(p->proto, &audit_info);
        c.data.proto = p->proto;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1442,12 +1460,15 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
        struct km_event c;
        u8 type = XFRM_POLICY_TYPE_MAIN;
        int err;
+       struct xfrm_audit audit_info;
 
        err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
        if (err)
                return err;
 
-       xfrm_policy_flush(type);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_policy_flush(type, &audit_info);
        c.data.type = type;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1502,6 +1523,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void *
        err = 0;
        if (up->hard) {
                xfrm_policy_delete(xp, p->dir);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                               AUDIT_MAC_IPSEC_DELSPD, 1, xp, NULL);
+
        } else {
                // reset the timers here?
                printk("Dont know what to do with soft policy expire\n");
@@ -1533,8 +1557,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **
                goto out;
        km_state_expired(x, ue->hard, current->pid);
 
-       if (ue->hard)
+       if (ue->hard) {
                __xfrm_state_delete(x);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSA, 1, NULL, x);
+       }
 out:
        spin_unlock_bh(&x->lock);
        xfrm_state_put(x);
index 4f5ff19..f01f8c0 100644 (file)
@@ -56,6 +56,9 @@ endef
 # gcc support functions
 # See documentation in Documentation/kbuild/makefiles.txt
 
+# output directory for tests below
+TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+
 # as-option
 # Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
 
@@ -66,9 +69,11 @@ as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
 # 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)
+as-instr = $(shell if echo -e "$(1)" | \
+                     $(CC) $(AFLAGS) -c -xassembler - \
+                           -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
+                  then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
+                  else echo "$(3)"; fi)
 
 # cc-option
 # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
@@ -97,10 +102,10 @@ cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
 
 # ld-option
 # Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(shell if $(CC) $(1) \
-                            -nostdlib -o ldtest$$$$.out -xc /dev/null \
-             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi; \
-            rm -f ldtest$$$$.out)
+ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
+                            -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
+             then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
+             else echo "$(2)"; fi)
 
 ###
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
index 22d281c..8b809b2 100644 (file)
@@ -43,7 +43,7 @@ struct sym_entry {
 
 static struct sym_entry *table;
 static unsigned int table_size, table_cnt;
-static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
+static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
 static int all_symbols = 0;
 static char symbol_prefix_char = '\0';
 
@@ -91,7 +91,9 @@ static int read_symbol(FILE *in, struct sym_entry *s)
                sym++;
 
        /* Ignore most absolute/undefined (?) symbols. */
-       if (strcmp(sym, "_stext") == 0)
+       if (strcmp(sym, "_text") == 0)
+               _text = s->addr;
+       else if (strcmp(sym, "_stext") == 0)
                _stext = s->addr;
        else if (strcmp(sym, "_etext") == 0)
                _etext = s->addr;
@@ -263,11 +265,27 @@ static void write_src(void)
        printf("#define ALGN .align 4\n");
        printf("#endif\n");
 
-       printf(".data\n");
+       printf("\t.section .rodata, \"a\"\n");
 
+       /* Provide proper symbols relocatability by their '_text'
+        * relativeness.  The symbol names cannot be used to construct
+        * normal symbol references as the list of symbols contains
+        * symbols that are declared static and are private to their
+        * .o files.  This prevents .tmp_kallsyms.o or any other
+        * object from referencing them.
+        */
        output_label("kallsyms_addresses");
        for (i = 0; i < table_cnt; i++) {
-               printf("\tPTR\t%#llx\n", table[i].addr);
+               if (toupper(table[i].sym[0]) != 'A') {
+                       if (_text <= table[i].addr)
+                               printf("\tPTR\t_text + %#llx\n",
+                                       table[i].addr - _text);
+                       else
+                               printf("\tPTR\t_text - %#llx\n",
+                                       _text - table[i].addr);
+               } else {
+                       printf("\tPTR\t%#llx\n", table[i].addr);
+               }
        }
        printf("\n");
 
index 338bdea..f5628c5 100644 (file)
@@ -798,7 +798,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                        QAction *action;
 
                        headerPopup = new QPopupMenu(this);
-                       action = new QAction("Show Name", 0, this);
+                       action = new QAction(NULL, "Show Name", 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowName(bool)));
@@ -806,7 +806,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                                  action, SLOT(setOn(bool)));
                          action->setOn(showName);
                          action->addTo(headerPopup);
-                       action = new QAction("Show Range", 0, this);
+                       action = new QAction(NULL, "Show Range", 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowRange(bool)));
@@ -814,7 +814,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                                  action, SLOT(setOn(bool)));
                          action->setOn(showRange);
                          action->addTo(headerPopup);
-                       action = new QAction("Show Data", 0, this);
+                       action = new QAction(NULL, "Show Data", 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowData(bool)));
@@ -1161,7 +1161,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
 QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
 {
        QPopupMenu* popup = Parent::createPopupMenu(pos);
-       QAction* action = new QAction("Show Debug Info", 0, popup);
+       QAction* action = new QAction(NULL,"Show Debug Info", 0, popup);
          action->setToggleAction(TRUE);
          connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
          connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
index 187f5de..df3b272 100755 (executable)
@@ -1430,7 +1430,7 @@ sub create_parameterlist($$$) {
            # corresponding data structures "correctly". Catch it later in
            # output_* subs.
            push_parameter($arg, "", $file);
-       } elsif ($arg =~ m/\(/) {
+       } elsif ($arg =~ m/\(.*\*/) {
            # pointer-to-function
            $arg =~ tr/#/,/;
            $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
index 2e11416..ac0a582 100644 (file)
@@ -911,6 +911,7 @@ static int init_section_ref_ok(const char *name)
                ".toc1",  /* used by ppc64 */
                ".stab",
                ".rodata",
+               ".parainstructions",
                ".text.lock",
                "__bug_table", /* used by powerpc for BUG() */
                ".pci_fixup_header",
@@ -931,6 +932,7 @@ static int init_section_ref_ok(const char *name)
                ".altinstructions",
                ".eh_frame",
                ".debug",
+               ".parainstructions",
                NULL
        };
        /* part of section name */
index 84999f6..72876df 100755 (executable)
@@ -48,6 +48,8 @@ fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
 xfs_db -V 2>&1 | grep version | awk \
 'NR==1{print "xfsprogs              ", $3}'
 
+pccardctl -V 2>&1| grep pcmciautils | awk '{print "pcmciautils           ", $2}'
+
 cardmgr -V 2>&1| grep version | awk \
 'NR==1{print "pcmcia-cs             ", $3}'
 
@@ -87,10 +89,16 @@ loadkeys -h 2>&1 | awk \
 loadkeys -V 2>&1 | awk \
 '(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools         ", $3}'
 
+oprofiled --version 2>&1 | awk \
+'(NR==1 && ($2 == "oprofile")) {print "oprofile              ", $3}'
+
 expr --v 2>&1 | awk 'NR==1{print "Sh-utils              ", $NF}'
 
 udevinfo -V 2>&1 | grep version | awk '{print "udev                  ", $3}'
 
+iwconfig --version 2>&1 | awk \
+'(NR==1 && ($3 == "version")) {print "wireless-tools        ",$4}'
+
 if [ -e /proc/modules ]; then
     X=`cat /proc/modules | sed -e "s/ .*$//"`
     echo "Modules Loaded         "$X
index 80de8c3..ac9326c 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/err.h>
 #include "internal.h"
 
-static kmem_cache_t    *key_jar;
+static struct kmem_cache       *key_jar;
 struct rb_root         key_serial_tree; /* tree of keys indexed by serial */
 DEFINE_SPINLOCK(key_serial_lock);
 
@@ -30,8 +30,8 @@ DEFINE_SPINLOCK(key_user_lock);
 static LIST_HEAD(key_types_list);
 static DECLARE_RWSEM(key_types_sem);
 
-static void key_cleanup(void *data);
-static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL);
+static void key_cleanup(struct work_struct *work);
+static DECLARE_WORK(key_cleanup_task, key_cleanup);
 
 /* we serialise key instantiation and link */
 DECLARE_RWSEM(key_construction_sem);
@@ -285,16 +285,14 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        }
 
        /* allocate and initialise the key and its description */
-       key = kmem_cache_alloc(key_jar, SLAB_KERNEL);
+       key = kmem_cache_alloc(key_jar, GFP_KERNEL);
        if (!key)
                goto no_memory_2;
 
        if (desc) {
-               key->description = kmalloc(desclen, GFP_KERNEL);
+               key->description = kmemdup(desc, desclen, GFP_KERNEL);
                if (!key->description)
                        goto no_memory_3;
-
-               memcpy(key->description, desc, desclen);
        }
 
        atomic_set(&key->usage, 1);
@@ -552,7 +550,7 @@ EXPORT_SYMBOL(key_negate_and_link);
  * do cleaning up in process context so that we don't have to disable
  * interrupts all over the place
  */
-static void key_cleanup(void *data)
+static void key_cleanup(struct work_struct *work)
 {
        struct rb_node *_n;
        struct key *key;
index e8d02ac..ad45ce7 100644 (file)
@@ -706,12 +706,10 @@ int __key_link(struct key *keyring, struct key *key)
                                BUG_ON(size > PAGE_SIZE);
 
                                ret = -ENOMEM;
-                               nklist = kmalloc(size, GFP_KERNEL);
+                               nklist = kmemdup(klist, size, GFP_KERNEL);
                                if (!nklist)
                                        goto error2;
 
-                               memcpy(nklist, klist, size);
-
                                /* replace matched key */
                                atomic_inc(&key->usage);
                                nklist->keys[loop] = key;
index 32150cf..b6f8680 100644 (file)
@@ -27,7 +27,7 @@ static DEFINE_MUTEX(key_session_mutex);
 struct key_user root_key_user = {
        .usage          = ATOMIC_INIT(3),
        .consq          = LIST_HEAD_INIT(root_key_user.consq),
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
        .nkeys          = ATOMIC_INIT(2),
        .nikeys         = ATOMIC_INIT(2),
        .uid            = 0,
index e73ac1a..e7c0b5e 100644 (file)
@@ -124,7 +124,7 @@ DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
 
 static struct avc_cache avc_cache;
 static struct avc_callback_node *avc_callbacks;
-static kmem_cache_t *avc_node_cachep;
+static struct kmem_cache *avc_node_cachep;
 
 static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
 {
@@ -332,7 +332,7 @@ static struct avc_node *avc_alloc_node(void)
 {
        struct avc_node *node;
 
-       node = kmem_cache_alloc(avc_node_cachep, SLAB_ATOMIC);
+       node = kmem_cache_alloc(avc_node_cachep, GFP_ATOMIC);
        if (!node)
                goto out;
 
index 78f98fe..65fb5e8 100644 (file)
@@ -124,7 +124,7 @@ static struct security_operations *secondary_ops = NULL;
 static LIST_HEAD(superblock_security_head);
 static DEFINE_SPINLOCK(sb_security_lock);
 
-static kmem_cache_t *sel_inode_cache;
+static struct kmem_cache *sel_inode_cache;
 
 /* Return security context for a given sid or just the context 
    length if the buffer is null or length is 0 */
@@ -181,7 +181,7 @@ static int inode_alloc_security(struct inode *inode)
        struct task_security_struct *tsec = current->security;
        struct inode_security_struct *isec;
 
-       isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL);
+       isec = kmem_cache_alloc(sel_inode_cache, GFP_KERNEL);
        if (!isec)
                return -ENOMEM;
 
@@ -1120,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk,
 {
        struct task_security_struct *tsec = tsk->security;
        struct file_security_struct *fsec = file->f_security;
-       struct vfsmount *mnt = file->f_vfsmnt;
-       struct dentry *dentry = file->f_dentry;
+       struct vfsmount *mnt = file->f_path.mnt;
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct avc_audit_data ad;
        int rc;
@@ -1581,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
 static int selinux_bprm_set_security(struct linux_binprm *bprm)
 {
        struct task_security_struct *tsec;
-       struct inode *inode = bprm->file->f_dentry->d_inode;
+       struct inode *inode = bprm->file->f_path.dentry->d_inode;
        struct inode_security_struct *isec;
        struct bprm_security_struct *bsec;
        u32 newsid;
@@ -1621,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
        }
 
        AVC_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.mnt = bprm->file->f_vfsmnt;
-       ad.u.fs.dentry = bprm->file->f_dentry;
+       ad.u.fs.mnt = bprm->file->f_path.mnt;
+       ad.u.fs.dentry = bprm->file->f_path.dentry;
 
-       if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
+       if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
                newsid = tsec->sid;
 
         if (tsec->sid == newsid) {
@@ -1695,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files)
        struct tty_struct *tty;
        struct fdtable *fdt;
        long j = -1;
+       int drop_tty = 0;
 
        mutex_lock(&tty_mutex);
-       tty = current->signal->tty;
+       tty = get_current_tty();
        if (tty) {
                file_list_lock();
                file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
@@ -1707,15 +1708,17 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                           than using file_has_perm, as this particular open
                           file may belong to another process and we are only
                           interested in the inode-based check here. */
-                       struct inode *inode = file->f_dentry->d_inode;
+                       struct inode *inode = file->f_path.dentry->d_inode;
                        if (inode_has_perm(current, inode,
                                           FILE__READ | FILE__WRITE, NULL)) {
-                               /* Reset controlling tty. */
-                               current->signal->tty = NULL;
-                               current->signal->tty_old_pgrp = 0;
+                               drop_tty = 1;
                        }
                }
                file_list_unlock();
+
+               /* Reset controlling tty. */
+               if (drop_tty)
+                       proc_set_tty(current, NULL);
        }
        mutex_unlock(&tty_mutex);
 
@@ -1731,7 +1734,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                j++;
                i = j * __NFDBITS;
                fdt = files_fdtable(files);
-               if (i >= fdt->max_fds || i >= fdt->max_fdset)
+               if (i >= fdt->max_fds)
                        break;
                set = fdt->open_fds->fds_bits[j];
                if (!set)
@@ -2417,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
 static int selinux_file_permission(struct file *file, int mask)
 {
        int rc;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        if (!mask) {
                /* No permission to check.  Existence test. */
@@ -2594,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
 
        switch (cmd) {
                case F_SETFL:
-                       if (!file->f_dentry || !file->f_dentry->d_inode) {
+                       if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
                                err = -EINVAL;
                                break;
                        }
@@ -2620,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
                case F_SETLK64:
                case F_SETLKW64:
 #endif
-                       if (!file->f_dentry || !file->f_dentry->d_inode) {
+                       if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
                                err = -EINVAL;
                                break;
                        }
index cd24441..c8bf6e1 100644 (file)
@@ -448,7 +448,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 
 static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
-       ino_t ino =  file->f_dentry->d_inode->i_ino;
+       ino_t ino =  file->f_path.dentry->d_inode->i_ino;
        char *data;
        ssize_t rv;
 
@@ -805,7 +805,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
                goto out;
        }
 
-       inode = filep->f_dentry->d_inode;
+       inode = filep->f_path.dentry->d_inode;
        cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
        if (cur_enforcing < 0) {
                ret = cur_enforcing;
@@ -864,7 +864,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
        if (new_value)
                new_value = 1;
 
-       inode = filep->f_dentry->d_inode;
+       inode = filep->f_path.dentry->d_inode;
        bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
        length = count;
 
@@ -965,7 +965,7 @@ static void sel_remove_bools(struct dentry *de)
        file_list_lock();
        list_for_each(p, &sb->s_files) {
                struct file * filp = list_entry(p, struct file, f_u.fu_list);
-               struct dentry * dentry = filp->f_dentry;
+               struct dentry * dentry = filp->f_path.dentry;
 
                if (dentry->d_parent != de) {
                        continue;
index d049c7a..ebb993c 100644 (file)
@@ -28,7 +28,7 @@
  (keyp->source_type << 9)) & \
  AVTAB_HASH_MASK)
 
-static kmem_cache_t *avtab_node_cachep;
+static struct kmem_cache *avtab_node_cachep;
 
 static struct avtab_node*
 avtab_insert_node(struct avtab *h, int hvalue,
@@ -36,7 +36,7 @@ avtab_insert_node(struct avtab *h, int hvalue,
                  struct avtab_key *key, struct avtab_datum *datum)
 {
        struct avtab_node * newnode;
-       newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
+       newnode = kmem_cache_alloc(avtab_node_cachep, GFP_KERNEL);
        if (newnode == NULL)
                return NULL;
        memset(newnode, 0, sizeof(struct avtab_node));
index 3a61f31..ee64f5d 100644 (file)
@@ -59,10 +59,10 @@ struct gpio_methods {
 };
 
 struct gpio_notification {
+       struct delayed_work work;
        notify_func_t notify;
        void *data;
        void *gpio_private;
-       struct work_struct work;
        struct mutex mutex;
 };
 
index 40eb47e..2b03bc7 100644 (file)
@@ -195,9 +195,10 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
        ftr_gpio_set_lineout(rt, (s>>2)&1);
 }
 
-static void ftr_handle_notify(void *data)
+static void ftr_handle_notify(struct work_struct *work)
 {
-       struct gpio_notification *notif = data;
+       struct gpio_notification *notif =
+               container_of(work, struct gpio_notification, work.work);
 
        mutex_lock(&notif->mutex);
        if (notif->notify)
@@ -253,12 +254,9 @@ static void ftr_gpio_init(struct gpio_runtime *rt)
 
        ftr_gpio_all_amps_off(rt);
        rt->implementation_private = 0;
-       INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify,
-                 &rt->headphone_notify);
-       INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify,
-                 &rt->line_in_notify);
-       INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify,
-                 &rt->line_out_notify);
+       INIT_DELAYED_WORK(&rt->headphone_notify.work, ftr_handle_notify);
+       INIT_DELAYED_WORK(&rt->line_in_notify.work, ftr_handle_notify);
+       INIT_DELAYED_WORK(&rt->line_out_notify.work, ftr_handle_notify);
        mutex_init(&rt->headphone_notify.mutex);
        mutex_init(&rt->line_in_notify.mutex);
        mutex_init(&rt->line_out_notify.mutex);
@@ -287,7 +285,7 @@ static irqreturn_t ftr_handle_notify_irq(int xx, void *data)
 {
        struct gpio_notification *notif = data;
 
-       schedule_work(&notif->work);
+       schedule_delayed_work(&notif->work, 0);
 
        return IRQ_HANDLED;
 }
index 2836c32..5ca2220 100644 (file)
@@ -69,9 +69,10 @@ static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt)
        pmf_gpio_set_lineout(rt, (s>>2)&1);
 }
 
-static void pmf_handle_notify(void *data)
+static void pmf_handle_notify(struct work_struct *work)
 {
-       struct gpio_notification *notif = data;
+       struct gpio_notification *notif =
+               container_of(work, struct gpio_notification, work.work);
 
        mutex_lock(&notif->mutex);
        if (notif->notify)
@@ -83,12 +84,9 @@ static void pmf_gpio_init(struct gpio_runtime *rt)
 {
        pmf_gpio_all_amps_off(rt);
        rt->implementation_private = 0;
-       INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify,
-                 &rt->headphone_notify);
-       INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify,
-                 &rt->line_in_notify);
-       INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify,
-                 &rt->line_out_notify);
+       INIT_DELAYED_WORK(&rt->headphone_notify.work, pmf_handle_notify);
+       INIT_DELAYED_WORK(&rt->line_in_notify.work, pmf_handle_notify);
+       INIT_DELAYED_WORK(&rt->line_out_notify.work, pmf_handle_notify);
        mutex_init(&rt->headphone_notify.mutex);
        mutex_init(&rt->line_in_notify.mutex);
        mutex_init(&rt->line_out_notify.mutex);
@@ -129,7 +127,7 @@ static void pmf_handle_notify_irq(void *data)
 {
        struct gpio_notification *notif = data;
 
-       schedule_work(&notif->work);
+       schedule_delayed_work(&notif->work, 0);
 }
 
 static int pmf_set_notify(struct gpio_runtime *rt,
index c79a9af..c7e1b26 100644 (file)
@@ -125,7 +125,7 @@ struct audio_stream {
 #else
        dma_regs_t *dma_regs;   /* points to our DMA registers */
 #endif
-       int active:1;           /* we are using this stream for transfer now */
+       unsigned int active:1;  /* we are using this stream for transfer now */
        int period;             /* current transfer period */
        int periods;            /* current count of periods registerd in the DMA engine */
        int tx_spin;            /* are we recoding - flag used to do DMA trans. for sync */
index 0b4aab3..54591e2 100644 (file)
@@ -488,7 +488,7 @@ static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
 
 static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct snd_info_private_data *data;
        struct snd_info_entry *entry;
 
index 66e24b5..b52e893 100644 (file)
@@ -1604,7 +1604,7 @@ static struct file *snd_pcm_file_fd(int fd)
        file = fget(fd);
        if (!file)
                return NULL;
-       inode = file->f_dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        if (!S_ISCHR(inode->i_mode) ||
            imajor(inode) != snd_major) {
                fput(file);
@@ -3027,7 +3027,7 @@ static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
        struct page * page;
        
        if (substream == NULL)
-               return NOPAGE_OOM;
+               return NOPAGE_SIGBUS;
        runtime = substream->runtime;
        page = virt_to_page(runtime->status);
        get_page(page);
@@ -3070,7 +3070,7 @@ static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
        struct page * page;
        
        if (substream == NULL)
-               return NOPAGE_OOM;
+               return NOPAGE_SIGBUS;
        runtime = substream->runtime;
        page = virt_to_page(runtime->control);
        get_page(page);
@@ -3131,18 +3131,18 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
        size_t dma_bytes;
        
        if (substream == NULL)
-               return NOPAGE_OOM;
+               return NOPAGE_SIGBUS;
        runtime = substream->runtime;
        offset = area->vm_pgoff << PAGE_SHIFT;
        offset += address - area->vm_start;
-       snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
+       snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS);
        dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
        if (offset > dma_bytes - PAGE_SIZE)
                return NOPAGE_SIGBUS;
        if (substream->ops->page) {
                page = substream->ops->page(substream, offset);
                if (! page)
-                       return NOPAGE_OOM;
+                       return NOPAGE_OOM; /* XXX: is this really due to OOM? */
        } else {
                vaddr = runtime->dma_area + offset;
                page = virt_to_page(vaddr);
index 12ffffc..d2f2c50 100644 (file)
@@ -35,7 +35,7 @@ MODULE_LICENSE("GPL");
 
 #define AK4114_ADDR                    0x00 /* fixed address */
 
-static void ak4114_stats(void *);
+static void ak4114_stats(struct work_struct *work);
 
 static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val)
 {
@@ -158,7 +158,7 @@ void snd_ak4114_reinit(struct ak4114 *chip)
        reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
        /* bring up statistics / event queing */
        chip->init = 0;
-       INIT_WORK(&chip->work, ak4114_stats, chip);
+       INIT_DELAYED_WORK(&chip->work, ak4114_stats);
        queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
 }
 
@@ -561,9 +561,9 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
        return res;
 }
 
-static void ak4114_stats(void *data)
+static void ak4114_stats(struct work_struct *work)
 {
-       struct ak4114 *chip = (struct ak4114 *)data;
+       struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
        if (chip->init)
                return;
index cc2b9ab..a0588c2 100644 (file)
@@ -5,20 +5,6 @@
 #
 # Prompt user for primary drivers.
 
-config OSS_OBSOLETE_DRIVER
-       bool "Obsolete OSS drivers"
-       depends on SOUND_PRIME
-       help
-         This option enables support for obsolete OSS drivers that
-         are scheduled for removal in the near future since there
-         are ALSA drivers for the same hardware.
-
-         Please contact Adrian Bunk <bunk@stusta.de> if you had to
-         say Y here because your soundcard is not properly supported
-         by ALSA.
-
-         If unsure, say N.
-
 config SOUND_BT878
        tristate "BT878 audio dma"
        depends on SOUND_PRIME && PCI
@@ -35,40 +21,6 @@ config SOUND_BT878
          To compile this driver as a module, choose M here: the module will
          be called btaudio.
 
-config SOUND_EMU10K1
-       tristate "Creative SBLive! (EMU10K1)"
-       depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
-       ---help---
-         Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
-         such as the Creative SBLive!, SB PCI512 or Emu-APS.
-
-         For more information on this driver and the degree of support for
-         the different card models please check:
-
-               <http://sourceforge.net/projects/emu10k1/>
-
-         It is now possible to load dsp microcode patches into the EMU10K1
-         chip.  These patches are used to implement real time sound
-         processing effects which include for example: signal routing,
-         bass/treble control, AC3 passthrough, ...
-         Userspace tools to create new patches and load/unload them can be
-         found in the emu-tools package at the above URL.
-
-config MIDI_EMU10K1
-       bool "Creative SBLive! MIDI (EXPERIMENTAL)"
-       depends on SOUND_EMU10K1 && EXPERIMENTAL && ISA_DMA_API
-       help
-         Say Y if you want to be able to use the OSS /dev/sequencer
-         interface.  This code is still experimental.
-
-config SOUND_FUSION
-       tristate "Crystal SoundFusion (CS4280/461x)"
-       depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
-       help
-         This module drives the Crystal SoundFusion devices (CS4280/46xx
-         series) when wired as native sound drivers with AC97 codecs.  If
-         this driver does not work try the CS4232 driver.
-
 config SOUND_BCM_CS4297A
        tristate "Crystal Sound CS4297a (for Swarm)"
        depends on SOUND_PRIME && SIBYTE_SWARM
@@ -448,47 +400,6 @@ config SOUND_DMAP
 
          Say Y unless you have 16MB or more RAM or a PCI sound card.
 
-config SOUND_AD1816
-       tristate "AD1816(A) based cards (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && SOUND_OSS && OSS_OBSOLETE_DRIVER
-       help
-         Say M here if you have a sound card based on the Analog Devices
-         AD1816(A) chip.
-
-         If you compile the driver into the kernel, you have to add
-         "ad1816=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_AD1889
-       tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && SOUND_OSS && PCI && OSS_OBSOLETE_DRIVER
-       help
-         Say M here if you have a sound card based on the Analog Devices
-         AD1889 chip.
-
-config SOUND_ADLIB
-       tristate "Adlib Cards"
-       depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
-       help
-         Includes ASB 64 4D. Information on programming AdLib cards is
-         available at <http://www.itsnet.com/home/ldragon/Specs/adlib.html>.
-
-config SOUND_ACI_MIXER
-       tristate "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)"
-       depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
-       ---help---
-         ACI (Audio Command Interface) is a protocol used to communicate with
-         the microcontroller on some sound cards produced by miro and
-         Cardinal Technologies.  The main function of the ACI is to control
-         the mixer and to get a product identification.
-
-         This VoxWare ACI driver currently supports the ACI functions on the
-         miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI
-         also controls the radio tuner. This is supported in the video4linux
-         miropcm20 driver (say M or Y here and go back to "Multimedia
-         devices" -> "Radio Adapters").
-
-         This driver is also available as a module and will be called aci.
-
 config SOUND_CS4232
        tristate "Crystal CS4232 based (PnP) cards"
        depends on SOUND_OSS
@@ -594,18 +505,6 @@ config SOUND_MPU401
          If you compile the driver into the kernel, you have to add
          "mpu401=<io>,<irq>" to the kernel command line.
 
-config SOUND_NM256
-       tristate "NM256AV/NM256ZX audio support"
-       depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
-       help
-         Say M here to include audio support for the NeoMagic 256AV/256ZX
-         chipsets. These are the audio chipsets found in the Sony
-         Z505S/SX/DX, some Sony F-series, and the Dell Latitude CPi and CPt
-         laptops. It includes support for an AC97-compatible mixer and an
-         apparently proprietary sound engine.
-
-         See <file:Documentation/sound/oss/NM256> for further information.
-
 config SOUND_PAS
        tristate "ProAudioSpectrum 16 support"
        depends on SOUND_OSS
@@ -714,20 +613,6 @@ config SOUND_YM3812
 
          If unsure, say Y.
 
-config SOUND_OPL3SA2
-       tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
-       depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
-       help
-         Say Y or M if you have a card based on one of these Yamaha sound
-         chipsets or the "SAx", which is actually a SA3. Read
-         <file:Documentation/sound/oss/OPL3-SA2> for more information on
-         configuring these cards.
-
-         If you compile the driver into the kernel and do not also
-         configure in the optional ISA PnP support, you will have to add
-         "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
-         command line.
-
 config SOUND_UART6850
        tristate "6850 UART support"
        depends on SOUND_OSS
index 6ad3841..ad7210a 100644 (file)
@@ -1020,6 +1020,7 @@ static int __devinit btaudio_probe(struct pci_dev *pci_dev,
  fail2:
         free_irq(bta->irq,bta);        
  fail1:
+       iounmap(bta->mmio);
        kfree(bta);
  fail0:
        release_mem_region(pci_resource_start(pci_dev,0),
@@ -1051,6 +1052,7 @@ static void __devexit btaudio_remove(struct pci_dev *pci_dev)
         free_irq(bta->irq,bta);
        release_mem_region(pci_resource_start(pci_dev,0),
                           pci_resource_len(pci_dev,0));
+       iounmap(bta->mmio);
 
        /* remove from linked list */
        if (bta == btaudios) {
index 87bd310..80b836e 100644 (file)
@@ -1051,7 +1051,7 @@ static int sq_release(struct inode *inode, struct file *file)
 
        if (file->f_mode & FMODE_WRITE) {
                if (write_sq.busy)
-                       rc = sq_fsync(file, file->f_dentry);
+                       rc = sq_fsync(file, file->f_path.dentry);
 
                sq_reset_output() ; /* make sure dma is stopped and all is quiet */
                write_sq_release_buffers();
@@ -1217,7 +1217,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
                if ((file->f_mode & FMODE_READ) && dmasound.mach.record)
                        sq_reset_input() ;
                if (file->f_mode & FMODE_WRITE) {
-                       result = sq_fsync(file, file->f_dentry);
+                       result = sq_fsync(file, file->f_path.dentry);
                        sq_reset_output() ;
                }
                /* if we are the shared resource owner then release them */
index 86dd239..49f902f 100644 (file)
@@ -111,9 +111,15 @@ static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t
 
                if ((bytestocopy >= wiinst->buffer.fragment_size)
                    || (bytestocopy >= count)) {
+                       int rc;
+
                        bytestocopy = min_t(u32, bytestocopy, count);
 
-                       emu10k1_wavein_xferdata(wiinst, (u8 __user *)buffer, &bytestocopy);
+                       rc = emu10k1_wavein_xferdata(wiinst,
+                                                    (u8 __user *)buffer,
+                                                    &bytestocopy);
+                       if (rc)
+                               return rc;
 
                        count -= bytestocopy;
                        buffer += bytestocopy;
index 8bbf44b..060d1be 100644 (file)
@@ -304,11 +304,12 @@ void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
        }
 }
 
-static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
+static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
 {
-       if (cov == 1)
-               __copy_to_user(dst, src + str, len);
-       else {
+       if (cov == 1) {
+               if (__copy_to_user(dst, src + str, len))
+                       return -EFAULT;
+       } else {
                u8 byte;
                u32 i;
 
@@ -316,22 +317,26 @@ static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
 
                for (i = 0; i < len; i++) {
                        byte = src[2 * i] ^ 0x80;
-                       __copy_to_user(dst + i, &byte, 1);
+                       if (__copy_to_user(dst + i, &byte, 1))
+                               return -EFAULT;
                }
        }
+
+       return 0;
 }
 
-void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
+int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
 {
        struct wavein_buffer *buffer = &wiinst->buffer;
        u32 sizetocopy, sizetocopy_now, start;
        unsigned long flags;
+       int ret;
 
        sizetocopy = min_t(u32, buffer->size, *size);
        *size = sizetocopy;
 
        if (!sizetocopy)
-               return;
+               return 0;
 
        spin_lock_irqsave(&wiinst->lock, flags);
        start = buffer->pos;
@@ -345,11 +350,17 @@ void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
        if (sizetocopy > sizetocopy_now) {
                sizetocopy -= sizetocopy_now;
 
-               copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov);
-               copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov);
+               ret = copy_block(data, buffer->addr, start, sizetocopy_now,
+                                buffer->cov);
+               if (ret == 0)
+                       ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
+                                        sizetocopy, buffer->cov);
        } else {
-               copy_block(data, buffer->addr, start, sizetocopy, buffer->cov);
+               ret = copy_block(data, buffer->addr, start, sizetocopy,
+                                buffer->cov);
        }
+
+       return ret;
 }
 
 void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
index 15cfb9b..e82029b 100644 (file)
@@ -83,7 +83,7 @@ void emu10k1_wavein_close(struct emu10k1_wavedevice *);
 void emu10k1_wavein_start(struct emu10k1_wavedevice *);
 void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
 void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
-void emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
+int emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
 int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
 void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
 
index 4e3baca..6d21d43 100644 (file)
@@ -162,12 +162,15 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
 
                DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
                if (count < needed) {
-                       copy_from_user(pt->buf + pt->prepend_size, buffer, count);
+                       if (copy_from_user(pt->buf + pt->prepend_size,
+                                          buffer, count))
+                               return -EFAULT;
                        pt->prepend_size += count;
                        DPD(3, "prepend size now %d\n", pt->prepend_size);
                        return count;
                }
-               copy_from_user(pt->buf + pt->prepend_size, buffer, needed);
+               if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
+                       return -EFAULT;
                r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
                if (r)
                        return r;
@@ -178,7 +181,8 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
        blocks_copied = 0;
        while (blocks > 0) {
                u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
-               copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE);
+               if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
+                       return -EFAULT;
                r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
                if (r) {
                        if (bytes_copied)
@@ -193,7 +197,8 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
        i = count - bytes_copied;
        if (i) {
                pt->prepend_size = i;
-               copy_from_user(pt->buf, buffer + bytes_copied, i);
+               if (copy_from_user(pt->buf, buffer + bytes_copied, i))
+                       return -EFAULT;
                bytes_copied += i;
                DPD(3, "filling prepend buffer with %d bytes", i);
        }
index d514679..24110d6 100644 (file)
@@ -1007,7 +1007,7 @@ static int dsp_write(const char __user *buf, size_t len)
 
 static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 {
-       int minor = iminor(file->f_dentry->d_inode);
+       int minor = iminor(file->f_path.dentry->d_inode);
        if (minor == dev.dsp_minor)
                return dsp_read(buf, count);
        else
@@ -1016,7 +1016,7 @@ static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_
 
 static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
 {
-       int minor = iminor(file->f_dentry->d_inode);
+       int minor = iminor(file->f_path.dentry->d_inode);
        if (minor == dev.dsp_minor)
                return dsp_write(buf, count);
        else
index 8fb8e7f..a89108c 100644 (file)
@@ -141,7 +141,7 @@ static int get_mixer_levels(void __user * arg)
 
 static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        int ret = -EINVAL;
 
        /*
@@ -174,7 +174,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
 
 static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
        int ret = -EINVAL;
        
        lock_kernel();
@@ -393,7 +393,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
 
 static unsigned int sound_poll(struct file *file, poll_table * wait)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        int dev = iminor(inode);
 
        DEB(printk("sound_poll(dev=%d)\n", dev));
@@ -418,7 +418,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
        int dev_class;
        unsigned long size;
        struct dma_buffparms *dmap = NULL;
-       int dev = iminor(file->f_dentry->d_inode);
+       int dev = iminor(file->f_path.dentry->d_inode);
 
        dev_class = dev & 0x0f;
        dev >>= 4;
index 17837d4..c96cc8c 100644 (file)
@@ -2120,8 +2120,8 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
                return NOPAGE_SIGBUS; /* Disallow mremap */
        }
         if (!card) {
-               DPRINTK ("EXIT, returning NOPAGE_OOM\n");
-               return NOPAGE_OOM;      /* Nothing allocated */
+               DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
+               return NOPAGE_SIGBUS;   /* Nothing allocated */
        }
 
        pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
index 6577b23..7abcb10 100644 (file)
@@ -1927,9 +1927,10 @@ static int snd_ac97_dev_disconnect(struct snd_device *device)
 static struct snd_ac97_build_ops null_build_ops;
 
 #ifdef CONFIG_SND_AC97_POWER_SAVE
-static void do_update_power(void *data)
+static void do_update_power(struct work_struct *work)
 {
-       update_power_regs(data);
+       update_power_regs(
+               container_of(work, struct snd_ac97, power_work.work));
 }
 #endif
 
@@ -1989,7 +1990,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
        mutex_init(&ac97->page_mutex);
 #ifdef CONFIG_SND_AC97_POWER_SAVE
        ac97->power_workq = create_workqueue("ac97");
-       INIT_WORK(&ac97->power_work, do_update_power, ac97);
+       INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
 #endif
 
 #ifdef CONFIG_PCI
index 9c3d7ac..71482c1 100644 (file)
@@ -272,10 +272,11 @@ EXPORT_SYMBOL(snd_hda_queue_unsol_event);
 /*
  * process queueud unsolicited events
  */
-static void process_unsol_events(void *data)
+static void process_unsol_events(struct work_struct *work)
 {
-       struct hda_bus *bus = data;
-       struct hda_bus_unsolicited *unsol = bus->unsol;
+       struct hda_bus_unsolicited *unsol =
+               container_of(work, struct hda_bus_unsolicited, work);
+       struct hda_bus *bus = unsol->bus;
        struct hda_codec *codec;
        unsigned int rp, caddr, res;
 
@@ -314,7 +315,8 @@ static int init_unsol_queue(struct hda_bus *bus)
                kfree(unsol);
                return -ENOMEM;
        }
-       INIT_WORK(&unsol->work, process_unsol_events, bus);
+       INIT_WORK(&unsol->work, process_unsol_events);
+       unsol->bus = bus;
        bus->unsol = unsol;
        return 0;
 }
index f9416c3..9ca1baf 100644 (file)
@@ -206,6 +206,7 @@ struct hda_bus_unsolicited {
        /* workqueue */
        struct workqueue_struct *workq;
        struct work_struct work;
+       struct hda_bus *bus;
 };
 
 /*
index 2fbe1d1..8f074c7 100644 (file)
@@ -942,10 +942,11 @@ static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int
 }
 
 static struct work_struct device_change;
+static struct snd_pmac *device_change_chip;
 
-static void device_change_handler(void *self)
+static void device_change_handler(struct work_struct *work)
 {
-       struct snd_pmac *chip = self;
+       struct snd_pmac *chip = device_change_chip;
        struct pmac_tumbler *mix;
        int headphone, lineout;
 
@@ -1417,7 +1418,8 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
        chip->resume = tumbler_resume;
 #endif
 
-       INIT_WORK(&device_change, device_change_handler, (void *)chip);
+       INIT_WORK(&device_change, device_change_handler);
+       device_change_chip = chip;
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
        if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0)
index 3a181d4..3304344 100644 (file)
@@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
                printk(KERN_INFO "Unable to load '%s'.\n", fn);
                return 0;
        }
-       l = filp->f_dentry->d_inode->i_size;
+       l = filp->f_path.dentry->d_inode->i_size;
        if (l <= 0 || l > 131072)
        {
                printk(KERN_INFO "Invalid firmware '%s'\n", fn);
index 4b52d18..b76b3dd 100644 (file)
@@ -48,7 +48,7 @@ static struct page * snd_us428ctls_vm_nopage(struct vm_area_struct *area, unsign
        
        offset = area->vm_pgoff << PAGE_SHIFT;
        offset += address - area->vm_start;
-       snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
+       snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS);
        vaddr = (char*)((struct usX2Ydev *)area->vm_private_data)->us428ctls_sharedmem + offset;
        page = virt_to_page(vaddr);
        get_page(page);